Implementacja tabu search dla TSP
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

pea2plus.cpp 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. #include <fstream>
  2. #include <iostream>
  3. #include <string>
  4. #include <vector>
  5. #include <cmath>
  6. #include "Stopwatch.h"
  7. #include "ArrayGraph.h"
  8. #include "ListGraph.h"
  9. using namespace std;
  10. // USTAWIENIA
  11. // Liczba powtorzen automatycznych pomiarow do usrednienia
  12. const int measureIterations = 10;
  13. // liczba automatycznych pomiarow
  14. const int measureNumber = 4;
  15. // Czas zatrzymania algorytmu tabu search w kazdym z automatycznych pomiarow
  16. const int measureTabuStop[4] = {1, 5, 10, 15};
  17. // Maksymalna odleglosc miast przy automatycznym generowaniu
  18. const int measureSalesmanDistance = 400;
  19. // Kadencja tabu search
  20. const int tabuLength = 30;
  21. // Kryterium dywersyfikacji, liczba iteracji bez poprawy
  22. const int tabuIterationsToRestart = 10000;
  23. // Wykorzystanie reprezentacji grafu w postaci list sasiedztwa...
  24. // ...zamiast (domyslnie) macierzy sasiedztwa
  25. // (wolniejsze obliczenia, mniejsze uzycie pamieci)
  26. const bool useListGraph = false;
  27. // Liczba watkow tabu search
  28. const unsigned tabuThreadsNumber = 2;
  29. // Domyslny czas zatrzymania algorytmu tabu search [s]
  30. int tabuStopTime = 60;
  31. // Domyslny stan dywersyfikacji
  32. bool tabuDiversification = true;
  33. int main()
  34. {
  35. Stopwatch clock; // czasomierz
  36. Graph *graph = NULL; // <- tu bedziemy zapisywac adresy przez caly program
  37. cout << "PEA Projekt 2 v2.0ALPHA Plus" << endl;
  38. cout << "Jan Potocki 2017-2019" << endl;
  39. cout << "(beerware)" << endl;
  40. if(useListGraph)
  41. cout << "Uzycie listowej reprezentacji grafu" << endl;
  42. else
  43. cout << "Uzycie macierzowej reprezentacji grafu" << endl;
  44. cout << endl;
  45. int salesmanSelection;
  46. do
  47. {
  48. cout << "1 - wygeneruj losowe dane" << endl;
  49. cout << "2 - wyswietl dane" << endl;
  50. cout << "3 - dywersyfikacja TS" << endl;
  51. cout << "4 - czas zatrzymania TS" << endl;
  52. cout << "5 - tabu search" << endl;
  53. cout << "6 - algorytm zachlanny" << endl;
  54. cout << "7 - podzial i ograniczenia" << endl;
  55. cout << "8 - przeglad zupelny" << endl;
  56. cout << "9 - automatyczne pomiary (tabu search)" << endl;
  57. cout << "10 - wczytaj dane z pliku ATSP" << endl;
  58. cout << "11 - wczytaj dane z pliku TSP" << endl;
  59. cout << "Aby zakonczyc - 0" << endl;
  60. cout << "Wybierz: ";
  61. cin >> salesmanSelection;
  62. cout << endl;
  63. switch(salesmanSelection)
  64. {
  65. case 1:
  66. {
  67. int vertex;
  68. cout << "Liczba miast: ";
  69. cin >> vertex;
  70. cout << endl;
  71. if(graph != NULL)
  72. delete graph;
  73. if(useListGraph)
  74. graph = new ListGraph(vertex);
  75. else
  76. graph = new ArrayGraph(vertex);
  77. Graph::randomGenerateFullGraph(*graph, measureSalesmanDistance);
  78. }
  79. break;
  80. case 2:
  81. {
  82. if(graph != NULL)
  83. graph->displayGraph();
  84. else
  85. cout << "Brak wygenerowanych danych" << endl;
  86. cout << endl;
  87. }
  88. break;
  89. case 3:
  90. {
  91. tabuDiversification = !tabuDiversification;
  92. if(tabuDiversification == true)
  93. cout << "Dywersyfikacja TS zostala wlaczona" << endl;
  94. else
  95. cout << "Dywersyfikacja TS zostala wylaczona" << endl;
  96. cout << endl;
  97. }
  98. break;
  99. case 4:
  100. {
  101. cout << "Poprzedni czas pracy TS: " << tabuStopTime << endl;
  102. cout << "Podaj nowy czas: ";
  103. cin >> tabuStopTime;
  104. cout << endl;
  105. }
  106. break;
  107. case 5:
  108. {
  109. if(graph != NULL)
  110. {
  111. if(tabuStopTime != 0)
  112. {
  113. cout << "Kadencja: " << tabuLength << endl;
  114. cout << "Czas zatrzymania algorytmu [s]: " << tabuStopTime << endl;
  115. if(tabuDiversification == true)
  116. cout << "Dywersyfikacja wlaczona, kryterium: " << tabuIterationsToRestart << " iteracji" << endl;
  117. else
  118. cout << "Dywersyfikacja wylaczona" << endl;
  119. cout << endl;
  120. clock.start();
  121. vector<unsigned> route = Graph::travellingSalesmanTabuSearch(*graph, tabuLength, tabuDiversification, tabuIterationsToRestart, tabuStopTime, tabuThreadsNumber);
  122. clock.stop();
  123. // Wyswietlenie trasy
  124. unsigned distFromStart = 0;
  125. unsigned length = 0;
  126. cout << route.at(0) << '\t' << length << '\t' << distFromStart << endl;
  127. for(int i = 1; i < route.size(); i++)
  128. {
  129. length = graph->getWeight(route.at(i - 1), route.at(i));
  130. distFromStart += length;
  131. cout << route.at(i) << '\t' << length << '\t' << distFromStart << endl;
  132. }
  133. cout << "Dlugosc trasy: " << distFromStart << endl;
  134. cout << endl;
  135. cout << "Czas wykonania algorytmu [s]: " << clock.read() << endl;
  136. }
  137. else
  138. {
  139. // Easter egg ;-)
  140. cout << "+++ MELON MELON MELON +++ Blad: Brak Sera! +++ !!!!! +++" << endl;
  141. }
  142. }
  143. else
  144. cout << "+++ MELON MELON MELON +++ Brak zaladowanych danych +++" << endl;
  145. cout << endl;
  146. }
  147. break;
  148. case 6:
  149. {
  150. if(graph != NULL)
  151. {
  152. clock.start();
  153. vector<unsigned> route = Graph::travellingSalesmanGreedy(*graph, 0);
  154. clock.stop();
  155. // Wyswietlenie trasy
  156. unsigned distFromStart = 0;
  157. unsigned length = 0;
  158. cout << route.at(0) << '\t' << length << '\t' << distFromStart << endl;
  159. for(int i = 1; i < route.size(); i++)
  160. {
  161. length = graph->getWeight(route.at(i - 1), route.at(i));
  162. distFromStart += length;
  163. cout << route.at(i) << '\t' << length << '\t' << distFromStart << endl;
  164. }
  165. cout << "Dlugosc trasy: " << distFromStart << endl;
  166. cout << endl;
  167. cout << "Czas wykonania algorytmu [s]: " << clock.read() << endl;
  168. }
  169. else
  170. cout << "+++ MELON MELON MELON +++ Brak zaladowanych danych +++" << endl;
  171. cout << endl;
  172. }
  173. break;
  174. case 7:
  175. {
  176. if(graph != NULL)
  177. {
  178. clock.start();
  179. vector<unsigned> route = Graph::travellingSalesmanBranchAndBound(*graph);
  180. clock.stop();
  181. // Wyswietlenie trasy
  182. unsigned distFromStart = 0;
  183. unsigned length = 0;
  184. cout << route.at(0) << '\t' << length << '\t' << distFromStart << endl;
  185. for(int i = 1; i < route.size(); i++)
  186. {
  187. length = graph->getWeight(route.at(i - 1), route.at(i));
  188. distFromStart += length;
  189. cout << route.at(i) << '\t' << length << '\t' << distFromStart << endl;
  190. }
  191. cout << "Dlugosc trasy: " << distFromStart << endl;
  192. cout << endl;
  193. cout << "Czas wykonania algorytmu [s]: " << clock.read() << endl;
  194. }
  195. else
  196. cout << "+++ MELON MELON MELON +++ Brak zaladowanych danych +++" << endl;
  197. cout << endl;
  198. }
  199. break;
  200. case 8:
  201. {
  202. if(graph != NULL)
  203. {
  204. clock.start();
  205. vector<unsigned> route = Graph::travellingSalesmanBruteForce(*graph);
  206. clock.stop();
  207. // Wyswietlenie trasy
  208. unsigned distFromStart = 0;
  209. unsigned length = 0;
  210. cout << route.at(0) << '\t' << length << '\t' << distFromStart << endl;
  211. for(int i = 1; i < route.size(); i++)
  212. {
  213. length = graph->getWeight(route.at(i - 1), route.at(i));
  214. distFromStart += length;
  215. cout << route.at(i) << '\t' << length << '\t' << distFromStart << endl;
  216. }
  217. cout << "Dlugosc trasy: " << distFromStart << endl;
  218. cout << endl;
  219. cout << "Czas wykonania algorytmu [s]: " << clock.read() << endl;
  220. }
  221. else
  222. cout << "+++ MELON MELON MELON +++ Brak zaladowanych danych +++" << endl;
  223. cout << endl;
  224. }
  225. break;
  226. case 9:
  227. {
  228. // PEA 2
  229. // Jan Potocki 2017
  230. if(graph != NULL)
  231. {
  232. double measureResults[measureNumber], measureResultsDiv[measureNumber];
  233. for(int i = 0; i < measureNumber; i++)
  234. {
  235. measureResults[i] = 0;
  236. measureResultsDiv[i] = 0;
  237. }
  238. cout << "Pomiary dla problemu komiwojazera, tabu search" << tabuLength << endl;
  239. cout << "Kadencja: " << tabuLength << endl;
  240. cout << "Kryterium dywersyfikacji: " << tabuIterationsToRestart << " iteracji" << endl;
  241. // Petla pomiarowa
  242. for(int krok = 0; krok < measureIterations; krok++)
  243. {
  244. for(int i = 0; i < measureNumber; i++)
  245. {
  246. vector<unsigned> route;
  247. unsigned routeLength;
  248. // Bez dywersyfikacji
  249. cout << "Pomiar " << measureTabuStop[i] << " [s] (" << krok + 1 << " z " << measureIterations << " bez dywersyfikacji)..." << endl;
  250. route = Graph::travellingSalesmanTabuSearch(*graph, tabuLength, false, tabuIterationsToRestart, measureTabuStop[i], tabuThreadsNumber);
  251. routeLength = 0;
  252. for(int j = 1; j < route.size(); j++)
  253. routeLength += graph->getWeight(route.at(j - 1), route.at(j));
  254. measureResults[i] += routeLength;
  255. // Z dywersyfikacja
  256. cout << "Pomiar " << measureTabuStop[i] << " [s] (" << krok + 1 << " z " << measureIterations << " z dywersyfikacja)..." << endl;
  257. route = Graph::travellingSalesmanTabuSearch(*graph, tabuLength, true, tabuIterationsToRestart, measureTabuStop[i], tabuThreadsNumber);
  258. routeLength = 0;
  259. for(int j = 1; j < route.size(); j++)
  260. routeLength += graph->getWeight(route.at(j - 1), route.at(j));
  261. measureResultsDiv[i] += routeLength;
  262. }
  263. }
  264. cout << "Opracowywanie wynikow..." << endl;
  265. for(int i = 0; i < measureNumber; i++)
  266. {
  267. measureResults[i] = nearbyint(measureResults[i] / measureIterations);
  268. measureResultsDiv[i] = nearbyint(measureResultsDiv[i] / measureIterations);
  269. }
  270. cout << "Zapis wynikow..." << endl;
  271. ofstream salesmanToFile;
  272. salesmanToFile.open("wyniki-komiwojazer-ts.txt");
  273. salesmanToFile << "czas - bez dywersyfikacji - z dywersyfikacja" << endl;
  274. for(int i = 0; i < measureNumber; i++)
  275. {
  276. salesmanToFile << measureTabuStop[i] << " [s]: " << (int)measureResults[i] << ' ' << (int)measureResultsDiv[i] << endl;
  277. }
  278. salesmanToFile.close();
  279. cout << "Gotowe!" << endl;
  280. cout << endl;
  281. }
  282. else
  283. {
  284. cout << "+++ MELON MELON MELON +++ Brak zaladowanych danych +++" << endl;
  285. cout << endl;
  286. }
  287. }
  288. break;
  289. case 10:
  290. {
  291. // Jan Potocki 2017
  292. string filename, fileInput;
  293. ifstream salesmanDataFile;
  294. cout << "Podaj nazwe pliku: ";
  295. cin >> filename;
  296. salesmanDataFile.open(filename.c_str());
  297. if(salesmanDataFile.is_open())
  298. {
  299. do
  300. salesmanDataFile >> fileInput;
  301. while(fileInput != "DIMENSION:");
  302. salesmanDataFile >> fileInput;
  303. int vertex = stoi(fileInput);
  304. do
  305. salesmanDataFile >> fileInput;
  306. while(fileInput != "EDGE_WEIGHT_FORMAT:");
  307. salesmanDataFile >> fileInput;
  308. if(fileInput == "FULL_MATRIX")
  309. {
  310. if(graph != NULL)
  311. delete graph;
  312. if(useListGraph)
  313. graph = new ListGraph(vertex);
  314. else
  315. graph = new ArrayGraph(vertex);
  316. do
  317. salesmanDataFile >> fileInput;
  318. while(fileInput != "EDGE_WEIGHT_SECTION");
  319. for(int i = 0; i < vertex; i++)
  320. {
  321. for(int j = 0; j < vertex; j++)
  322. {
  323. salesmanDataFile >> fileInput;
  324. int weight = stoi(fileInput);
  325. if(i != j)
  326. graph->addEdge(i, j, weight);
  327. }
  328. }
  329. cout << "Wczytano - liczba wierzcholkow: " << vertex << endl;
  330. cout << endl;
  331. }
  332. else
  333. {
  334. cout << "+++ MELON MELON MELON +++ Nieobslugiwany format " << fileInput << " +++" << endl;
  335. cout << endl;
  336. }
  337. salesmanDataFile.close();
  338. }
  339. else
  340. {
  341. cout << "+++ MELON MELON MELON +++ Brak pliku " << filename << " +++" << endl;
  342. cout << endl;
  343. }
  344. }
  345. break;
  346. case 11:
  347. {
  348. // Jan Potocki 2017
  349. string filename, fileInput;
  350. vector<float> xCoord, yCoord;
  351. ifstream salesmanDataFile;
  352. cout << "Podaj nazwe pliku: ";
  353. cin >> filename;
  354. salesmanDataFile.open(filename.c_str());
  355. if(salesmanDataFile.is_open())
  356. {
  357. do
  358. salesmanDataFile >> fileInput;
  359. while(fileInput != "DIMENSION:");
  360. salesmanDataFile >> fileInput;
  361. int vertex = stoi(fileInput);
  362. do
  363. salesmanDataFile >> fileInput;
  364. while(fileInput != "EDGE_WEIGHT_TYPE:");
  365. salesmanDataFile >> fileInput;
  366. if(fileInput == "EUC_2D")
  367. {
  368. if(graph != NULL)
  369. delete graph;
  370. if(useListGraph)
  371. graph = new ListGraph(vertex);
  372. else
  373. graph = new ArrayGraph(vertex);
  374. do
  375. salesmanDataFile >> fileInput;
  376. while(fileInput != "NODE_COORD_SECTION");
  377. for(int i = 0; i < vertex; i++)
  378. {
  379. salesmanDataFile >> fileInput;
  380. salesmanDataFile >> fileInput;
  381. xCoord.push_back(stof(fileInput));
  382. salesmanDataFile >> fileInput;
  383. yCoord.push_back(stof(fileInput));
  384. }
  385. // To daloby sie zrobic optymalniej (macierz symetryczna), ale nie chce mi sie ...
  386. // ..wole zoptymalizować czas programowania ;-)
  387. for(int i = 0; i < vertex; i++)
  388. {
  389. for(int j = 0; j < vertex; j++)
  390. {
  391. if(i != j)
  392. {
  393. float xDiff = xCoord.at(i) - xCoord.at(j);
  394. float yDiff = yCoord.at(i) - yCoord.at(j);
  395. int weight = nearbyint(sqrt(xDiff * xDiff + yDiff * yDiff));
  396. graph->addEdge(i, j, weight);
  397. }
  398. }
  399. }
  400. cout << "Wczytano - liczba wierzcholkow: " << vertex << endl;
  401. cout << endl;
  402. }
  403. else
  404. {
  405. cout << "+++ MELON MELON MELON +++ Nieobslugiwany format " << fileInput << " +++" << endl;
  406. cout << endl;
  407. }
  408. salesmanDataFile.close();
  409. }
  410. else
  411. {
  412. cout << "+++ MELON MELON MELON +++ Brak pliku " << filename << " +++" << endl;
  413. cout << endl;
  414. }
  415. }
  416. break;
  417. case 0:
  418. {
  419. }
  420. break;
  421. default:
  422. {
  423. cout << "Nieprawidlowy wybor" << endl;
  424. cout << endl;
  425. }
  426. }
  427. } while(salesmanSelection != 0);
  428. if(graph != NULL)
  429. delete graph;
  430. cout << "Konczenie..." << endl;
  431. // Easter egg :-P
  432. cout << '"' << "Myslak Stibbons niepokoil sie HEX-em." << endl;
  433. cout << "Nie wiedzial, jak dziala, chociaz wszyscy uwazali, ze wie." << endl;
  434. cout << "Oczywiscie, calkiem niezle orientowal sie w niektorych elementach;" << endl;
  435. cout << "byl tez pewien, ze HEX mysli o problemach, przeksztalcajac je" << endl;
  436. cout << "w liczby i mielac ..." << '"' << endl;
  437. cout << "(Terry Pratchett, " << '"' << "Wiedzmikolaj" << '"' << ", tlumaczenie Piotr Cholewa)" << endl;
  438. cout << endl;
  439. return 0;
  440. }