Implementacja tabu search dla TSP
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

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. }