|
@@ -426,15 +426,13 @@ std::vector<unsigned> Graph::travellingSalesmanTabuSearch(Graph &graph, unsigned
|
426
|
426
|
{
|
427
|
427
|
// ALGORYTM wielawotkowy oparty na metaheurystyce tabu search
|
428
|
428
|
// Pomocniczy kod uruchamiajacy watki wlasciwego algorytmu w najbardziej optymalny sposob
|
429
|
|
- // Implementacja: Jan Potocki 2019
|
|
429
|
+ // Implementacja: Jan Potocki 2019-2020
|
430
|
430
|
std::vector<unsigned> startVertexVector;
|
431
|
431
|
std::vector<std::thread> threadsVector;
|
432
|
|
- std::vector<std::vector<unsigned>> resultsVector(threadsNumber);
|
433
|
432
|
|
434
|
|
- std::vector<int> resultsLength(threadsNumber);
|
435
|
|
- std::vector<unsigned> optimalResult;
|
436
|
|
- int optimalResultIndex;
|
437
|
|
- int optimalResultLength;
|
|
433
|
+ std::mutex globalOptimumMutex;
|
|
434
|
+ std::vector<unsigned> globalOptimum;
|
|
435
|
+ unsigned globalOptimumLength = -1;
|
438
|
436
|
|
439
|
437
|
std::random_device randomSrc;
|
440
|
438
|
std::default_random_engine randomGen(randomSrc());
|
|
@@ -479,45 +477,28 @@ std::vector<unsigned> Graph::travellingSalesmanTabuSearch(Graph &graph, unsigned
|
479
|
477
|
}
|
480
|
478
|
|
481
|
479
|
// Uruchomienie watku
|
482
|
|
- threadsVector.push_back(std::thread(Graph::travellingSalesmanTabuSearchEngine, std::ref(graph), tabuSteps, diversification, iterationsToRestart, minStopTime, startRoute, std::ref(resultsVector.at(i)), std::ref(resultsLength.at(i))));
|
|
480
|
+ threadsVector.push_back(std::thread(Graph::travellingSalesmanTabuSearchEngine, std::ref(graph), tabuSteps, diversification, iterationsToRestart, minStopTime, startRoute, std::ref(globalOptimum), std::ref(globalOptimumLength), std::ref(globalOptimumMutex)));
|
483
|
481
|
}
|
484
|
482
|
|
485
|
483
|
// Petla potwierdzajaca zakonczenie watkow
|
486
|
484
|
for(int i = 0; i < threadsNumber; i++)
|
487
|
485
|
threadsVector.at(i).join();
|
488
|
486
|
|
489
|
|
- // Przegladanie wszystkich rozwiazan i wybor optymalnego
|
490
|
|
- optimalResultIndex = 0;
|
491
|
|
- optimalResultLength = resultsLength.at(0);
|
492
|
|
-
|
493
|
|
- for(int i = 0; i < threadsNumber; i++)
|
494
|
|
- {
|
495
|
|
- if(resultsLength.at(i) < optimalResultLength)
|
496
|
|
- {
|
497
|
|
- optimalResultIndex = i;
|
498
|
|
- optimalResultLength = resultsLength.at(i);
|
499
|
|
- }
|
500
|
|
- }
|
501
|
|
-
|
502
|
|
- optimalResult = resultsVector.at(optimalResultIndex);
|
503
|
|
-
|
504
|
|
- return optimalResult;
|
|
487
|
+ return globalOptimum;
|
505
|
488
|
}
|
506
|
489
|
|
507
|
|
-void Graph::travellingSalesmanTabuSearchEngine(Graph &graph, unsigned tabuSteps, bool diversification, int iterationsToRestart, unsigned minStopTime, std::vector<unsigned> startRoute, std::vector<unsigned> &result, int &resultLength)
|
|
490
|
+void Graph::travellingSalesmanTabuSearchEngine(Graph &graph, unsigned tabuSteps, bool diversification, int iterationsToRestart, unsigned minStopTime, std::vector<unsigned> startRoute, std::vector<unsigned> &globalOptimum, unsigned &globalOptimumLength, std::mutex &globalOptimumMutex)
|
508
|
491
|
{
|
509
|
492
|
// ALGORYTM oparty na metaheurystyce tabu search z dywersyfikacja i sasiedztwem typu swap
|
510
|
493
|
// Rdzen przeznaczony do uruchamiania jako jeden watek
|
511
|
494
|
// Projekt i implementacja: Jan Potocki 2017
|
512
|
|
- // (refactoring 2019)
|
|
495
|
+ // (refactoring 2019-2020)
|
513
|
496
|
Stopwatch onboardClock;
|
514
|
497
|
|
515
|
498
|
std::vector<unsigned> optimalRoute; // Tu bedziemy zapisywac optymalne (w danej chwili) rozwiazanie
|
516
|
499
|
int optimalRouteLength = -1; // -1 - bedziemy odtad uznawac, ze to jest nieskonczonosc ;-)
|
517
|
500
|
std::vector<unsigned> currentRoute; // Rozpatrywane rozwiazanie
|
518
|
501
|
|
519
|
|
- // Wyznaczenie poczatkowego rozwiazania algorytmem zachlannym
|
520
|
|
- //currentRoute = Graph::travellingSalesmanGreedy(graph);
|
521
|
502
|
currentRoute = startRoute;
|
522
|
503
|
|
523
|
504
|
// Inicjalizacja glownej petli...
|
|
@@ -623,13 +604,26 @@ void Graph::travellingSalesmanTabuSearchEngine(Graph &graph, unsigned tabuSteps,
|
623
|
604
|
stopCounter = 0;
|
624
|
605
|
}
|
625
|
606
|
|
|
607
|
+ // Synchronizacja globalnie najlepszej trasy
|
|
608
|
+ globalOptimumMutex.lock();
|
|
609
|
+ if(globalOptimumLength == -1 || globalOptimumLength > nextRouteLength)
|
|
610
|
+ {
|
|
611
|
+ globalOptimumLength = nextRouteLength;
|
|
612
|
+ globalOptimum = nextRoute;
|
|
613
|
+
|
|
614
|
+ onboardClock.stop();
|
|
615
|
+ std::cout << "Nowa najlepsza trasa: " << globalOptimumLength;
|
|
616
|
+ std::cout << " (w czasie " << onboardClock.read() << " s)" << std::endl;
|
|
617
|
+ }
|
|
618
|
+ globalOptimumMutex.unlock();
|
|
619
|
+
|
626
|
620
|
// Weryfikacja listy tabu...
|
627
|
621
|
int tabuPos = 0;
|
628
|
622
|
while(tabuPos < tabuArray.size())
|
629
|
|
- {
|
|
623
|
+ {
|
630
|
624
|
// ...aktualizacja kadencji na liscie tabu
|
631
|
625
|
tabuArray.at(tabuPos).at(0)--;
|
632
|
|
-
|
|
626
|
+
|
633
|
627
|
//...usuniecie zerowych kadencji
|
634
|
628
|
if(tabuArray.at(tabuPos).at(0) == 0)
|
635
|
629
|
tabuArray.erase(tabuArray.begin() + tabuPos);
|
|
@@ -690,6 +684,5 @@ void Graph::travellingSalesmanTabuSearchEngine(Graph &graph, unsigned tabuSteps,
|
690
|
684
|
stopCounter = 0;
|
691
|
685
|
}
|
692
|
686
|
|
693
|
|
- result = optimalRoute;
|
694
|
|
- resultLength = optimalRouteLength;
|
|
687
|
+ std::cout << std::endl;
|
695
|
688
|
}
|