浏览代码

Initial commit

Jan Potocki 5 年前
当前提交
bbc24df31f
共有 16 个文件被更改,包括 1623 次插入0 次删除
  1. 32
    0
      .gitignore
  2. 70
    0
      ArrayGraph.cpp
  3. 24
    0
      ArrayGraph.h
  4. 681
    0
      Graph.cpp
  5. 40
    0
      Graph.h
  6. 167
    0
      ListGraph.cpp
  7. 29
    0
      ListGraph.h
  8. 24
    0
      Makefile
  9. 23
    0
      Stopwatch.cpp
  10. 22
    0
      Stopwatch.h
  11. 二进制
      berlin52.tsp.gz
  12. 二进制
      ftv33.atsp.gz
  13. 二进制
      ftv47.atsp.gz
  14. 二进制
      ftv64.atsp.gz
  15. 511
    0
      pea2plus.cpp
  16. 二进制
      swiss42.tsp.gz

+ 32
- 0
.gitignore 查看文件

1
+# Prerequisites
2
+*.d
3
+
4
+# Compiled Object files
5
+*.slo
6
+*.lo
7
+*.o
8
+*.obj
9
+
10
+# Precompiled Headers
11
+*.gch
12
+*.pch
13
+
14
+# Compiled Dynamic libraries
15
+*.so
16
+*.dylib
17
+*.dll
18
+
19
+# Fortran module files
20
+*.mod
21
+*.smod
22
+
23
+# Compiled Static libraries
24
+*.lai
25
+*.la
26
+*.a
27
+*.lib
28
+
29
+# Executables
30
+*.exe
31
+*.out
32
+*.app

+ 70
- 0
ArrayGraph.cpp 查看文件

1
+#include "ArrayGraph.h"
2
+#include <iostream>
3
+
4
+ArrayGraph::ArrayGraph(unsigned vertexNumber)
5
+{
6
+    //ctor
7
+    this->vertexNumber = vertexNumber;
8
+    graphMatrix = new unsigned*[vertexNumber];
9
+    graphArray = new unsigned[vertexNumber*vertexNumber];
10
+    // W ten sposob cala tablica bedzie w pamieci w jednej czesci
11
+    // (mniej chybien w odwolaniach procesora do cache)
12
+
13
+    for(int i = 0; i < vertexNumber; i++)
14
+    {
15
+        graphMatrix[i] = graphArray + i * vertexNumber;
16
+
17
+        for(int j = 0; j < vertexNumber; j++)
18
+            graphMatrix[i][j] = 0;
19
+    }
20
+}
21
+
22
+ArrayGraph::~ArrayGraph()
23
+{
24
+    //dtor
25
+    delete graphArray;
26
+    delete graphMatrix;
27
+}
28
+
29
+bool ArrayGraph::addEdge(unsigned v, unsigned w, unsigned weight)
30
+{
31
+    if(weight >= 1000)
32
+        // Waga krawedzi musi byc mniejsza od 1000
33
+        weight = 900;
34
+
35
+    if(graphMatrix[v][w] > 0)
36
+        return false;
37
+    else
38
+    {
39
+        graphMatrix[v][w] = weight;
40
+        return true;
41
+    }
42
+}
43
+
44
+bool ArrayGraph::removeEdge(unsigned v, unsigned w)
45
+{
46
+    if(graphMatrix[v][w] == 0)
47
+        return false;
48
+    else
49
+    {
50
+        graphMatrix[v][w] = 0;
51
+        return true;
52
+    }
53
+}
54
+
55
+unsigned ArrayGraph::getWeight(unsigned v, unsigned w)
56
+{
57
+    return graphMatrix[v][w];
58
+}
59
+
60
+void ArrayGraph::displayGraph()
61
+{
62
+    for(int i = 0; i < vertexNumber; i++)
63
+    {
64
+        for(int j = 0; j < vertexNumber; j++)
65
+        {
66
+            std::cout << graphMatrix[i][j] << '\t';
67
+        }
68
+        std::cout << std::endl;
69
+    }
70
+}

+ 24
- 0
ArrayGraph.h 查看文件

1
+#ifndef ARRAYGRAPH_H
2
+#define ARRAYGRAPH_H
3
+
4
+#include "Graph.h"
5
+
6
+class ArrayGraph : public Graph
7
+{
8
+    public:
9
+        ArrayGraph(unsigned vertexNumber);
10
+        virtual ~ArrayGraph();
11
+        bool addEdge(unsigned v, unsigned w, unsigned weight);
12
+        bool removeEdge(unsigned v, unsigned w);
13
+        unsigned getWeight(unsigned v, unsigned w);
14
+        void displayGraph();
15
+
16
+    protected:
17
+
18
+    private:
19
+        unsigned **graphMatrix;
20
+        unsigned *graphArray;
21
+
22
+};
23
+
24
+#endif // ARRAYGRAPH_H

+ 681
- 0
Graph.cpp 查看文件

1
+#include "Graph.h"
2
+#include "Stopwatch.h"
3
+#include <algorithm>
4
+#include <chrono>
5
+#include <queue>
6
+#include <random>
7
+#include <thread>
8
+
9
+#include <iostream>
10
+
11
+Graph::Graph()
12
+{
13
+    //ctor
14
+}
15
+
16
+Graph::~Graph()
17
+{
18
+    //dtor
19
+}
20
+
21
+unsigned Graph::getVertexNumber()
22
+{
23
+    return vertexNumber;
24
+}
25
+
26
+void Graph::randomGenerateFullGraph(Graph &graph, unsigned maxWeight)
27
+{
28
+    std::random_device randomSrc;
29
+    std::default_random_engine randomGen(randomSrc());
30
+    std::uniform_int_distribution<> weightDist(1, maxWeight);
31
+
32
+    for(int i = 0; i < graph.vertexNumber; i++)
33
+    {
34
+        for(int j = 0; j < graph.vertexNumber; j++)
35
+        {
36
+            if(i != j)
37
+            {
38
+                // Bez warunku na krawedzie juz wygenerowane...
39
+                // ...z tym radzi sobie juz metoda addEdge
40
+                int randomWeight = weightDist(randomGen);
41
+                graph.addEdge(i, j, randomWeight);
42
+            }
43
+        }
44
+    }
45
+}
46
+
47
+std::vector<unsigned> Graph::travellingSalesmanBruteForce(Graph &graph)
48
+{
49
+    // ALGORYTM przegladu zupelnego
50
+    // Implementacja: Jan Potocki 2017
51
+    // (refactoring 2019)
52
+    std::vector<unsigned> vertexArray;
53
+
54
+    // Generowanie "spisu" wierzcholkow
55
+    // (od razu w odpowiedniej kolejnosci dla next_permutation)
56
+    for(int i = 1; i < graph.vertexNumber; i++)
57
+        vertexArray.push_back(i);
58
+
59
+    std::vector<unsigned> minCombination;
60
+    int minRoute = -1;
61
+
62
+    // Petla przegladajaca kolejne permutacje
63
+    do
64
+    {
65
+        std::vector<unsigned> combination;
66
+
67
+        // Dodanie wierzcholka startowego i pierwszego na trasie
68
+        combination.push_back(0);
69
+        combination.push_back(vertexArray.front());
70
+
71
+        // W petli reszta wiercholkow
72
+        for(int i = 1; i < vertexArray.size(); i++)
73
+            combination.push_back(vertexArray.at(i));
74
+
75
+        // Powrot do wierzcholka startowego
76
+        combination.push_back(0);
77
+        // PEA 2
78
+        // Jan Potocki 2017
79
+
80
+        int route = 0;
81
+        for(int i = 1; i < combination.size(); i++)
82
+            route += graph.getWeight(combination.at(i - 1), combination.at(i));
83
+
84
+        if(minRoute == -1 || route < minRoute)
85
+        {
86
+            minRoute = route;
87
+            minCombination = combination;
88
+        }
89
+    }
90
+    while(next_permutation(vertexArray.begin(), vertexArray.end()));
91
+
92
+    return minCombination;
93
+}
94
+
95
+std::vector<unsigned> Graph::travellingSalesmanBranchAndBound(Graph &graph)
96
+{
97
+    // ALGORYTM pracujacy w oparciu o kolejke priorytetowa i niejawnie utworzone drzewo
98
+    // Zrodlo: www.ii.uni.wroc.pl/~prz/2011lato/ah/opracowania/met_podz_ogr.opr.pdf
99
+    // Autor: Mateusz Lyczek 2011
100
+    // Implementacja: Jan Potocki 2017
101
+    std::priority_queue<std::vector<unsigned>, std::vector< std::vector<unsigned> >, RouteComparison> routeQueue;
102
+    std::vector<unsigned> optimalRoute;     // Tu bedziemy zapisywac optymalne (w danej chwili) rozwiazanie
103
+    int optimalRouteLength = -1;            // -1 - bedziemy odtad uznawac, ze to jest nieskonczonosc ;-)
104
+
105
+    // UMOWA
106
+    // Pierwszy element wektora to dlugosc trasy (trzeba ustawic "z palca"!)
107
+    // Kolejne to wierzcholki na trasie
108
+    std::vector<unsigned> currentRoute;     // Niejawne tworzenie drzewa, tu bedzie korzen
109
+    currentRoute.push_back(0);              // Poczatkowe oszacowanie nie ma znaczenia
110
+    currentRoute.push_back(0);              // Wierzcholek startowy (korzen drzewa rozwiazan)
111
+    routeQueue.push(currentRoute);          // Dodanie do kolejki korzenia
112
+
113
+    while(!routeQueue.empty())
114
+    {
115
+        // Przypisanie korzenia do dalszej roboty
116
+        currentRoute = routeQueue.top();
117
+        routeQueue.pop();
118
+
119
+        // Sprawdzenie, czy rozwiazanie jest warte rozwijania, czy odrzucic
120
+        if(optimalRouteLength == -1 || currentRoute.at(0) < optimalRouteLength)
121
+        {
122
+            for(int i = 0; i < graph.vertexNumber; i++)
123
+            {
124
+                // Petla wykonywana dla kazdego potomka rozpatrywanego wlasnie rozwiazania w drzewie
125
+                // Ustalenie, czy dany wierzcholek mozna jeszcze wykorzystac, czy juz zostal uzyty
126
+                bool vertexUsed = false;
127
+                for(int j = 1; j < currentRoute.size(); j++)
128
+                {
129
+                    if(currentRoute.at(j) == i)
130
+                    {
131
+                        vertexUsed = true;
132
+                        break;
133
+                    }
134
+                }
135
+                if(vertexUsed)
136
+                    continue;
137
+
138
+                // Niejawne utworzenie nowego wezla reprezuntujacego rozpatrywane rozwiazanie...
139
+                std::vector<unsigned> nextRoute = currentRoute;
140
+                //unsigned nextLength = graph.getWeight(nextRoute.back(), i);
141
+                nextRoute.push_back(i);
142
+
143
+                // Dalej bedziemy postepowac roznie...
144
+                if(nextRoute.size() > graph.vertexNumber)
145
+                {
146
+                    // Doszlismy wlasnie do liscia
147
+                    // Dodajemy droge powrotna, nie musimy nic szacowac
148
+                    // (wszystko juz wiemy)
149
+                    nextRoute.push_back(0);
150
+
151
+                    nextRoute.at(0) = 0;
152
+
153
+                    for(int j = 1; j < nextRoute.size() - 1; j++)
154
+                    {
155
+                        // Liczymy dystans od poczatku do konca
156
+                        nextRoute.at(0) += graph.getWeight(nextRoute.at(j), nextRoute.at(j+ 1));
157
+                    }
158
+                    if(optimalRouteLength == -1 || nextRoute.at(0) < optimalRouteLength)
159
+                    {
160
+                        optimalRouteLength = nextRoute.at(0);
161
+                        nextRoute.erase(nextRoute.begin());
162
+                        optimalRoute = nextRoute;
163
+                    }
164
+                }
165
+                else
166
+                {
167
+                    // Liczenie tego, co juz wiemy, od nowa...
168
+                    // (dystans od poczatku)
169
+                    nextRoute.at(0) = 0;
170
+                    for(int j = 1; j < nextRoute.size() - 1; j++)
171
+                    {
172
+                        nextRoute.at(0) += graph.getWeight(nextRoute.at(j), nextRoute.at(j + 1));
173
+                    }
174
+
175
+                    // Reszte szacujemy...
176
+                    // Pomijamy od razu wierzcholek startowy
177
+                    for(int j = 1; j < graph.vertexNumber; j++)
178
+                    {
179
+                        // Odrzucenie wierzcholkow juz umieszczonych na trasie
180
+                        bool vertexUsed = false;
181
+                        for(int k = 1; k < currentRoute.size(); k++)
182
+                        {
183
+                            if(j == currentRoute.at(k))
184
+                            {
185
+                                vertexUsed = true;
186
+                                break;
187
+                            }
188
+                        }
189
+                        if(vertexUsed)
190
+                            continue;
191
+
192
+                        int minEdge = -1;
193
+                        for(int k = 0; k < graph.vertexNumber; k++)
194
+                        {
195
+                            // Odrzucenie krawedzi do wierzcholka 0 przy ostatnim wierzcholku w czesciowym rozwiazaniu
196
+                            // Wyjatkiem jest ostatnia mozliwa krawedz
197
+                            if(j == i && k == 0)
198
+                                continue;
199
+
200
+                            // Odrzucenie krawedzi do wierzcholka umieszczonego juz na rozwazanej trasie
201
+                            bool vertexUsed = false;
202
+                            for(int l = 2; l < nextRoute.size(); l++)
203
+                            {
204
+                                if(k == nextRoute.at(l))
205
+                                {
206
+                                    vertexUsed = true;
207
+                                    break;
208
+                                }
209
+                            }
210
+                            if(vertexUsed)
211
+                                continue;
212
+
213
+                            // Odrzucenie samego siebie
214
+                            if(k == j)
215
+                                continue;
216
+
217
+                            // Znalezienie najkrotszej mozliwej jeszcze do uzycia krawedzi
218
+                            unsigned consideredLength = graph.getWeight(j, k);
219
+
220
+                            if(minEdge == -1)
221
+                                minEdge = consideredLength;
222
+                            else if(minEdge > consideredLength)
223
+                                minEdge = consideredLength;
224
+                        }
225
+                        nextRoute.at(0) += minEdge;
226
+                    }
227
+
228
+                    // ...i teraz zastanawiamy sie co dalej
229
+                    if(optimalRouteLength == -1 || nextRoute.at(0) < optimalRouteLength)
230
+                    {
231
+                        routeQueue.push(nextRoute);
232
+                    }
233
+                }
234
+            }
235
+        }
236
+        else
237
+        {
238
+            // Jezeli jedno rozwiazanie odrzucilismy, to wszystkie inne tez mozemy
239
+            // (kolejka priorytetowa, inne nie moga byc lepsze)
240
+            break;
241
+        }
242
+    }
243
+
244
+    return optimalRoute;
245
+}
246
+
247
+std::vector<unsigned> Graph::travellingSalesmanGreedy(Graph &graph, unsigned startVertex)
248
+{
249
+    // ALGORYTM zachlanny z wierzcholkiem startowym przekazanym w parametrze
250
+    // Implementacja: Jan Potocki 2017
251
+    std::vector<unsigned> route;
252
+
253
+    // std::random_device randomSrc;
254
+    // std::default_random_engine randomGen(randomSrc());
255
+    // std::uniform_int_distribution<> vertexDist(0, graph.vertexNumber - 1);
256
+
257
+    // Losowanie wierzcholka startowego
258
+    //route.push_back(vertexDist(randomGen));
259
+    route.push_back(startVertex);
260
+
261
+    for(int i = 0; i < graph.vertexNumber - 1; i++)
262
+    {
263
+        int minEdge = -1;
264
+        unsigned nextVertex;
265
+        for(int j = 0; j < graph.vertexNumber; j++)
266
+        {
267
+            // Odrzucenie samego siebie lub wierzcholka startowego
268
+            // (zeby bylo szybciej)
269
+            if(route.back() == j || route.front() == j)
270
+                continue;
271
+
272
+            // Odrzucenie krawedzi do wierzcholka umieszczonego juz na trasie
273
+            bool vertexUsed = false;
274
+            for(int k = 0; k < route.size(); k++)
275
+            {
276
+                if(j == route.at(k))
277
+                {
278
+                    vertexUsed = true;
279
+                    break;
280
+                }
281
+            }
282
+            if(vertexUsed)
283
+                continue;
284
+
285
+            // Znalezienie najkrotszej mozliwej jeszcze do uzycia krawedzi
286
+            unsigned consideredLength = graph.getWeight(route.back(), j);
287
+
288
+            if(minEdge == -1)
289
+            {
290
+                minEdge = consideredLength;
291
+                nextVertex = j;
292
+            }
293
+            else if(minEdge > consideredLength)
294
+            {
295
+                minEdge = consideredLength;
296
+                nextVertex = j;
297
+            }
298
+        }
299
+        route.push_back(nextVertex);
300
+    }
301
+
302
+    route.push_back(startVertex);
303
+    return route;
304
+}
305
+
306
+std::vector<unsigned> Graph::travellingSalesmanHybrid(Graph &graph)
307
+{
308
+    // ALGORYTM hybrydowy losowo-zachlanny
309
+    // Losowa czesc wierzcholkow jest losowana, reszta zachlannie
310
+    // Implementacja: Jan Potocki 2019
311
+    std::vector<unsigned> route;
312
+
313
+    std::random_device randomSrc;
314
+    std::default_random_engine randomGen(randomSrc());
315
+    std::uniform_int_distribution<> vertexNumberDist(1, graph.vertexNumber);
316
+    std::uniform_int_distribution<> vertexDist(0, graph.vertexNumber - 1);
317
+
318
+    // Liczba losowanych wierzcholkow
319
+    unsigned randomVertexNumber = vertexNumberDist(randomGen);
320
+
321
+    // Czesc losowa
322
+    for(int i = 0; i < randomVertexNumber; i++)
323
+    {
324
+        unsigned randomVertex;
325
+        bool vertexUsed;
326
+
327
+        do
328
+        {
329
+            randomVertex = vertexDist(randomGen);
330
+            vertexUsed = false;
331
+
332
+            for(int j = 0; j < route.size(); j++)
333
+            {
334
+                if(route.at(j) == randomVertex)
335
+                {
336
+                    vertexUsed = true;
337
+                    break;
338
+                }
339
+            }
340
+        } while(vertexUsed == true);
341
+
342
+        route.push_back(randomVertex);
343
+    }
344
+
345
+    // Czesc zachlanna
346
+    for(int i = 0; i < graph.vertexNumber - randomVertexNumber; i++)
347
+    {
348
+        int minEdge = -1;
349
+        unsigned nextVertex;
350
+        for(int j = 0; j < graph.vertexNumber; j++)
351
+        {
352
+            // Odrzucenie samego siebie lub wierzcholka startowego
353
+            // (zeby bylo szybciej)
354
+            if(route.back() == j || route.front() == j)
355
+                continue;
356
+
357
+            // Odrzucenie krawedzi do wierzcholka umieszczonego juz na trasie
358
+            bool vertexUsed = false;
359
+            for(int k = 0; k < route.size(); k++)
360
+            {
361
+                if(j == route.at(k))
362
+                {
363
+                    vertexUsed = true;
364
+                    break;
365
+                }
366
+            }
367
+            if(vertexUsed)
368
+                continue;
369
+
370
+            // Znalezienie najkrotszej mozliwej jeszcze do uzycia krawedzi
371
+            unsigned consideredLength = graph.getWeight(route.back(), j);
372
+
373
+            if(minEdge == -1)
374
+            {
375
+                minEdge = consideredLength;
376
+                nextVertex = j;
377
+            }
378
+            else if(minEdge > consideredLength)
379
+            {
380
+                minEdge = consideredLength;
381
+                nextVertex = j;
382
+            }
383
+        }
384
+        route.push_back(nextVertex);
385
+    }
386
+
387
+    route.push_back(route.front());
388
+    return route;
389
+}
390
+
391
+std::vector<unsigned> Graph::travellingSalesmanRandom(Graph &graph)
392
+{
393
+    // ALGORYTM losowy
394
+    // Implementacja: Jan Potocki 2019
395
+    std::vector<unsigned> route;
396
+
397
+    std::random_device randomSrc;
398
+    std::default_random_engine randomGen(randomSrc());
399
+    std::uniform_int_distribution<> vertexDist(0, graph.vertexNumber - 1);
400
+
401
+    for(int i = 0; i < graph.vertexNumber; i++)
402
+    {
403
+        unsigned randomVertex;
404
+        bool vertexUsed;
405
+
406
+        do
407
+        {
408
+            randomVertex = vertexDist(randomGen);
409
+            vertexUsed = false;
410
+
411
+            for(int j = 0; j < route.size(); j++)
412
+            {
413
+                if(route.at(j) == randomVertex)
414
+                {
415
+                    vertexUsed = true;
416
+                    break;
417
+                }
418
+            }
419
+        } while(vertexUsed == true);
420
+
421
+        route.push_back(randomVertex);
422
+    }
423
+
424
+    route.push_back(route.front());
425
+    return route;
426
+}
427
+
428
+std::vector<unsigned> Graph::travellingSalesmanTabuSearch(Graph &graph, unsigned tabuSteps, bool diversification, int iterationsToRestart, unsigned minStopTime, unsigned threadsNumber)
429
+{
430
+    // ALGORYTM wielawotkowy oparty na metaheurystyce tabu search
431
+    // Pomocniczy kod uruchamiajacy watki wlasciwego algorytmu w najbardziej optymalny sposob
432
+    // Implementacja: Jan Potocki 2019
433
+    std::vector<unsigned> startVertexVector;
434
+    std::vector<std::thread> threadsVector;
435
+    std::vector<std::vector<unsigned>> resultsVector(threadsNumber);
436
+    std::vector<int> resultsLength(threadsNumber);
437
+    std::vector<unsigned> optimalResult;
438
+    int optimalResultIndex;
439
+    int optimalResultLength;
440
+
441
+    std::random_device randomSrc;
442
+    std::default_random_engine randomGen(randomSrc());
443
+    std::uniform_int_distribution<> vertexDist(0, graph.vertexNumber - 1);
444
+
445
+    for(int i = 0; i < threadsNumber; i++)
446
+    {
447
+        std::vector<unsigned> startRoute;
448
+        unsigned startVertex;
449
+        bool startVertexUsed;
450
+
451
+        if(i < graph.vertexNumber)
452
+        {
453
+            do
454
+            {
455
+                startVertex = vertexDist(randomGen);
456
+                startVertexUsed = false;
457
+
458
+                for(int j = 0; j < startVertexVector.size(); j++)
459
+                {
460
+                    if(startVertexVector.at(j) == startVertex)
461
+                    {
462
+                        startVertexUsed = true;
463
+                        break;
464
+                    }
465
+                }
466
+            } while(startVertexUsed == true);
467
+
468
+            startVertexVector.push_back(startVertex);
469
+            startRoute = Graph::travellingSalesmanGreedy(graph, startVertex);
470
+        }
471
+        else
472
+        {
473
+            startRoute = Graph::travellingSalesmanRandom(graph);
474
+        }
475
+
476
+        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))));
477
+    }
478
+
479
+    for(int i = 0; i < threadsNumber; i++)
480
+        threadsVector.at(i).join();
481
+
482
+    optimalResultIndex = 0;
483
+    optimalResultLength = resultsLength.at(0);
484
+
485
+    for(int i = 0; i < threadsNumber; i++)
486
+    {
487
+        if(resultsLength.at(i) < optimalResultLength)
488
+        {
489
+            optimalResultIndex = i;
490
+            optimalResultLength = resultsLength.at(i);
491
+        }
492
+    }
493
+
494
+    optimalResult = resultsVector.at(optimalResultIndex);
495
+
496
+    return optimalResult;
497
+}
498
+
499
+void Graph::travellingSalesmanTabuSearchEngine(Graph &graph, unsigned tabuSteps, bool diversification, int iterationsToRestart, unsigned minStopTime, std::vector<unsigned> startRoute, std::vector<unsigned> &result, int &resultLength)
500
+{
501
+    // ALGORYTM oparty na metaheurystyce tabu search z dywersyfikacja i sasiedztwem typu swap
502
+    // Rdzen przeznaczony do uruchamiania jako jeden watek
503
+    // Projekt i implementacja: Jan Potocki 2017
504
+    // (refactoring 2019)
505
+    Stopwatch onboardClock;
506
+
507
+    std::vector<unsigned> optimalRoute;     // Tu bedziemy zapisywac optymalne (w danej chwili) rozwiazanie
508
+    int optimalRouteLength = -1;            // -1 - bedziemy odtad uznawac, ze to jest nieskonczonosc ;-)
509
+    std::vector<unsigned> currentRoute;     // Rozpatrywane rozwiazanie
510
+
511
+    // Wyznaczenie poczatkowego rozwiazania algorytmem zachlannym
512
+    //currentRoute = Graph::travellingSalesmanGreedy(graph);
513
+    currentRoute = startRoute;
514
+
515
+    // Inicjalizacja glownej petli...
516
+    std::vector< std::vector<unsigned> > tabuArray;
517
+    unsigned currentTabuSteps = tabuSteps;
518
+    int stopCounter = 0;
519
+    bool timeNotExceeded = true;
520
+    onboardClock.start();
521
+
522
+    // Rdzen algorytmu
523
+    while(timeNotExceeded == true)
524
+    {
525
+        bool cheeseSupplied = true;
526
+        bool intensification = false;
527
+
528
+        while(cheeseSupplied == true)
529
+        {
530
+            std::vector<unsigned> nextRoute;
531
+            int nextRouteLength = -1;
532
+
533
+            std::vector<unsigned> nextTabu(3, 0);
534
+            nextTabu.at(0) = currentTabuSteps;
535
+
536
+            // Generowanie sasiedztwa typu swap przez zamiane wierzcholkow
537
+            // (wierzcholka startowego i zarazem ostatniego nie ruszamy,
538
+            // pomijamy tez od razu aktualny wierzcholek)
539
+            for(int i = 1; i < graph.vertexNumber - 1; i++)
540
+            {
541
+                for(int j = i + 1; j < graph.vertexNumber; j++)
542
+                {
543
+                    std::vector<unsigned> neighbourRoute = currentRoute;
544
+
545
+                    // Zamiana
546
+                    unsigned buffer = neighbourRoute.at(j);
547
+                    neighbourRoute.at(j) = neighbourRoute.at(i);
548
+                    neighbourRoute.at(i) = buffer;
549
+
550
+                    unsigned neighbourRouteLength = 0;
551
+                    for(int i = 1; i < neighbourRoute.size(); i++)
552
+                        neighbourRouteLength += graph.getWeight(neighbourRoute.at(i - 1), neighbourRoute.at(i));
553
+
554
+                    // Sprawdzenie, czy dany ruch nie jest na liscie tabu
555
+                    // (dwa wierzcholki)
556
+                    bool tabu = false;
557
+                    for(int k = 0; k < tabuArray.size(); k++)
558
+                    {
559
+                        if(tabuArray.at(k).at(1) == i && tabuArray.at(k).at(2) == j)
560
+                        {
561
+                            tabu = true;
562
+                            break;
563
+                        }
564
+
565
+                        if(tabuArray.at(k).at(1) == j && tabuArray.at(k).at(2) == i)
566
+                        {
567
+                            tabu = true;
568
+                            break;
569
+                        }
570
+                    }
571
+
572
+                    // Kryterium aspiracji...
573
+                    if(tabu == true && neighbourRouteLength >= optimalRouteLength)
574
+                        // ...jezeli niespelnione - pomijamy ruch
575
+                        continue;
576
+
577
+                    if(nextRouteLength == -1)
578
+                    {
579
+                        nextRouteLength = neighbourRouteLength;
580
+                        nextRoute = neighbourRoute;
581
+                        nextTabu.at(1) = i;
582
+                        nextTabu.at(2) = j;
583
+                    }
584
+                    else if(nextRouteLength > neighbourRouteLength)
585
+                    {
586
+                        nextRouteLength = neighbourRouteLength;
587
+                        nextRoute = neighbourRoute;
588
+                        nextTabu.at(1) = i;
589
+                        nextTabu.at(2) = j;
590
+                    }
591
+                }
592
+            }
593
+
594
+            currentRoute = nextRoute;
595
+
596
+            if(optimalRouteLength == -1)
597
+            {
598
+                optimalRouteLength = nextRouteLength;
599
+                optimalRoute = nextRoute;
600
+
601
+                // Reset licznika
602
+                stopCounter = 0;
603
+            }
604
+            else if(optimalRouteLength > nextRouteLength)
605
+            {
606
+                optimalRouteLength = nextRouteLength;
607
+                optimalRoute = nextRoute;
608
+
609
+                // Zaplanowanie intensyfikacji
610
+                intensification = true;
611
+
612
+                // Reset licznika
613
+                stopCounter = 0;
614
+            }
615
+
616
+            // Weryfikacja listy tabu...
617
+            // ...aktualizacja kadencji na liscie tabu
618
+            for(int i = 0; i < tabuArray.size(); i++)
619
+            {
620
+                tabuArray.at(i).at(0)--;
621
+            }
622
+
623
+            //...usuniecie zerowych kadencji
624
+            for(int i = 0; i < tabuArray.size(); i++)
625
+            {
626
+                if(tabuArray.at(i).at(0) == 0)
627
+                    tabuArray.erase(tabuArray.begin() + i);
628
+            }
629
+
630
+            // ...dopisanie ostatniego ruchu do listy tabu
631
+            tabuArray.push_back(nextTabu);
632
+
633
+            // Zliczenie iteracji
634
+            stopCounter++;
635
+
636
+            // Zmierzenie czasu
637
+            onboardClock.stop();
638
+            if(onboardClock.read() > minStopTime)
639
+                timeNotExceeded = false;
640
+
641
+            // Sprawdzenie warunku zatrzymania
642
+            if(diversification == true)
643
+            {
644
+                // Przy aktywowanej dywersyfikacji - po zadanej liczbie iteracji bez poprawy
645
+                if(stopCounter >= iterationsToRestart || timeNotExceeded == false)
646
+                    cheeseSupplied = false;
647
+            }
648
+            else
649
+            {
650
+                // Przy nieaktywowanej dywersyfikacji - po uplynieciu okreslonego czasu
651
+                if(timeNotExceeded == false)
652
+                    cheeseSupplied = false;
653
+            }
654
+        }
655
+
656
+        // Dywersyfikacja
657
+        if(diversification == true)
658
+        {
659
+            if(intensification == true)
660
+            {
661
+                // Intensyfikacja przeszukiwania przy ostatnim minimum
662
+                currentRoute = optimalRoute;
663
+                currentTabuSteps = tabuSteps / 4;
664
+                intensification = false;
665
+            }
666
+            else
667
+            {
668
+                // Algorytm hybrydowy losowo-zachlanny
669
+                currentRoute = Graph::travellingSalesmanHybrid(graph);
670
+                currentTabuSteps = tabuSteps;
671
+                intensification = false;
672
+            }
673
+        }
674
+
675
+        // Reset licznika iteracji przed restartem
676
+        stopCounter = 0;
677
+    }
678
+
679
+    result = optimalRoute;
680
+    resultLength = optimalRouteLength;
681
+}

+ 40
- 0
Graph.h 查看文件

1
+#ifndef GRAPH_H
2
+#define GRAPH_H
3
+#include <vector>
4
+
5
+
6
+class Graph
7
+{
8
+    public:
9
+        Graph();
10
+        virtual ~Graph();
11
+        virtual bool addEdge(unsigned v, unsigned w, unsigned weight) = 0;
12
+        virtual bool removeEdge(unsigned v, unsigned w) = 0;
13
+        virtual unsigned getWeight(unsigned v, unsigned w) = 0;
14
+        unsigned getVertexNumber();
15
+        virtual void displayGraph() = 0;
16
+        static void randomGenerateFullGraph(Graph &graph, unsigned maxWeight);
17
+        static std::vector<unsigned> travellingSalesmanBruteForce(Graph &graph);
18
+        static std::vector<unsigned> travellingSalesmanBranchAndBound(Graph &graph);
19
+        static std::vector<unsigned> travellingSalesmanGreedy(Graph &graph, unsigned startVertex);
20
+        static std::vector<unsigned> travellingSalesmanHybrid(Graph &graph);
21
+        static std::vector<unsigned> travellingSalesmanRandom(Graph &graph);
22
+        static std::vector<unsigned> travellingSalesmanTabuSearch(Graph &graph, unsigned tabuSteps, bool diversification, int iterationsToRestart, unsigned minStopTime, unsigned threadsNumber);
23
+
24
+    protected:
25
+        unsigned vertexNumber;
26
+
27
+    private:
28
+        static void travellingSalesmanTabuSearchEngine(Graph &graph, unsigned tabuSteps, bool diversification, int iterationsToRestart, unsigned minStopTime, std::vector<unsigned> startRoute, std::vector<unsigned> &result, int &resultLength);
29
+
30
+        class RouteComparison
31
+        {
32
+            public:
33
+                bool operator() (const std::vector<unsigned>& lhs, const std::vector<unsigned>& rhs) const
34
+                {
35
+                    return (lhs.at(0) > rhs.at(0));
36
+                }
37
+        };
38
+};
39
+
40
+#endif // GRAPH_H

+ 167
- 0
ListGraph.cpp 查看文件

1
+#include "ListGraph.h"
2
+#include <iostream>
3
+
4
+ListGraph::ListGraph(unsigned vertexNumber)
5
+{
6
+    //ctor
7
+    this->vertexNumber = vertexNumber;
8
+    graphList = new element*[vertexNumber];
9
+
10
+    for(int i = 0; i < vertexNumber; i++)
11
+        graphList[i] = NULL;
12
+}
13
+
14
+ListGraph::~ListGraph()
15
+{
16
+    //dtor
17
+    for(int i = 0; i < vertexNumber; i++)
18
+    {
19
+        if(graphList[i] != NULL)
20
+        {
21
+            element *position = graphList[i];
22
+            do
23
+            {
24
+                element *next = position->next;
25
+                delete position;
26
+                position = next;
27
+            }
28
+            while(position != NULL);
29
+        }
30
+    }
31
+
32
+    delete[] graphList;
33
+}
34
+
35
+bool ListGraph::addEdge(unsigned v, unsigned w, unsigned weight)
36
+{
37
+    if(weight >= 1000)
38
+        // Waga krawedzi musi byc mniejsza od 1000
39
+        weight = 900;
40
+
41
+    if(graphList[v] == NULL)
42
+    {
43
+        graphList[v] = new element;
44
+        graphList[v]->vertex = w;
45
+        graphList[v]->weight = weight;
46
+        graphList[v]->next = NULL;
47
+
48
+        return true;
49
+    }
50
+    else
51
+    {
52
+        bool isAlready = false;
53
+        element *next = graphList[v];
54
+        element *position = NULL;
55
+        do
56
+        {
57
+            position = next;
58
+            next = next->next;
59
+            if(position->vertex == w)
60
+            {
61
+                isAlready = true;
62
+                break;
63
+            }
64
+        }
65
+        while(next != NULL);
66
+
67
+        if(!isAlready)
68
+        {
69
+            element *newEdge = new element;
70
+            newEdge->vertex = w;
71
+            newEdge->weight = weight;
72
+            newEdge->next = NULL;
73
+            position->next = newEdge;
74
+
75
+            return true;
76
+        }
77
+        else
78
+            return false;
79
+    }
80
+}
81
+
82
+bool ListGraph::removeEdge(unsigned v, unsigned w)
83
+{
84
+    if(graphList[v] == NULL)
85
+        return false;
86
+    else
87
+    {
88
+        bool isAlready = false;
89
+        element *next = graphList[v];
90
+        element *position = NULL;
91
+        element *prev = NULL;
92
+        do
93
+        {
94
+            prev = position;
95
+            position = next;
96
+            next = next->next;
97
+            if(position->vertex == w)
98
+            {
99
+                isAlready = true;
100
+                break;
101
+            }
102
+        }
103
+        while(next != NULL);
104
+
105
+        if(!isAlready)
106
+            return false;
107
+        else
108
+        {
109
+            delete position;
110
+            if(prev != NULL)
111
+                prev->next = next;
112
+            else
113
+                graphList[v] = next;
114
+
115
+            return true;
116
+        }
117
+    }
118
+}
119
+
120
+unsigned ListGraph::getWeight(unsigned v, unsigned w)
121
+{
122
+    if(graphList[v] == NULL)
123
+        return 0;
124
+    else
125
+    {
126
+        bool isAlready = false;
127
+        element *next = graphList[v];
128
+        element *position = NULL;
129
+        do
130
+        {
131
+            position = next;
132
+            next = next->next;
133
+            if(position->vertex == w)
134
+            {
135
+                isAlready = true;
136
+                break;
137
+            }
138
+        }
139
+        while(next != NULL);
140
+
141
+        if(!isAlready)
142
+            return 0;
143
+        else
144
+            return position->weight;
145
+    }
146
+}
147
+
148
+void ListGraph::displayGraph()
149
+{
150
+    for(int i = 0; i < vertexNumber; i++)
151
+    {
152
+        std::cout << i << " -> ";
153
+        if(graphList[i] != NULL)
154
+        {
155
+            element *next = graphList[i];
156
+            element *position = NULL;
157
+            do
158
+            {
159
+                position = next;
160
+                next = next->next;
161
+                std::cout << position->vertex << '@' << position->weight << ' ';
162
+            }
163
+            while(next != NULL);
164
+        }
165
+        std::cout << std::endl;
166
+    }
167
+}

+ 29
- 0
ListGraph.h 查看文件

1
+#ifndef LISTGRAPH_H
2
+#define LISTGRAPH_H
3
+
4
+#include "Graph.h"
5
+
6
+class ListGraph : public Graph
7
+{
8
+    public:
9
+        ListGraph(unsigned vertexNumber);
10
+        virtual ~ListGraph();
11
+        bool addEdge(unsigned v, unsigned w, unsigned weight);
12
+        bool removeEdge(unsigned v, unsigned w);
13
+        unsigned getWeight(unsigned v, unsigned w);
14
+        void displayGraph();
15
+
16
+    protected:
17
+
18
+    private:
19
+        struct element
20
+        {
21
+            unsigned vertex;
22
+            int weight;
23
+            element *next;
24
+        };
25
+        element **graphList;
26
+
27
+};
28
+
29
+#endif // LISTGRAPH_H

+ 24
- 0
Makefile 查看文件

1
+CXXFLAGS =	-O3 -Wall -std=c++11
2
+
3
+ifeq ($(OS),Windows_NT)
4
+	detected_OS := Windows
5
+else
6
+	detected_OS := $(shell uname)
7
+endif
8
+ifeq ($(detected_OS),Darwin)
9
+    CXXFLAGS += -stdlib=libc++
10
+endif
11
+
12
+OBJS =		pea2plus.o ArrayGraph.o Graph.o ListGraph.o Stopwatch.o
13
+
14
+LIBS =		-pthread
15
+
16
+TARGET =	pea2plus
17
+
18
+$(TARGET):	$(OBJS)
19
+	$(CXX) -o $(TARGET) $(OBJS) $(LIBS)
20
+
21
+all:	$(TARGET)
22
+
23
+clean:
24
+	rm -f $(OBJS) $(TARGET)

+ 23
- 0
Stopwatch.cpp 查看文件

1
+#include "Stopwatch.h"
2
+
3
+Stopwatch::Stopwatch()
4
+{
5
+    //ctor
6
+    // Jan Potocki 2017-2019
7
+}
8
+
9
+void Stopwatch::start()
10
+{
11
+    tstart = std::chrono::steady_clock::now();
12
+}
13
+
14
+void Stopwatch::stop()
15
+{
16
+    tstop = std::chrono::steady_clock::now();
17
+    measurement = tstop - tstart;
18
+}
19
+
20
+double Stopwatch::read()
21
+{
22
+    return measurement.count();
23
+}

+ 22
- 0
Stopwatch.h 查看文件

1
+#ifndef STOPWATCH_H
2
+#define STOPWATCH_H
3
+
4
+#include <chrono>
5
+
6
+// Klasa do pomiaru czasu (wieloplatformowa)
7
+// Jan Potocki 2017-2019
8
+class Stopwatch
9
+{
10
+    public:
11
+        Stopwatch();
12
+        void start();
13
+        void stop();
14
+        double read();
15
+    protected:
16
+    private:
17
+        std::chrono::duration<double> measurement;
18
+        std::chrono::time_point<std::chrono::steady_clock> tstart;
19
+        std::chrono::time_point<std::chrono::steady_clock> tstop;
20
+};
21
+
22
+#endif // STOPWATCH_H

二进制
berlin52.tsp.gz 查看文件


二进制
ftv33.atsp.gz 查看文件


二进制
ftv47.atsp.gz 查看文件


二进制
ftv64.atsp.gz 查看文件


+ 511
- 0
pea2plus.cpp 查看文件

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

二进制
swiss42.tsp.gz 查看文件


正在加载...
取消
保存