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