Implementacja tabu search dla TSP
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

pea2plus.cpp 22KB

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