From 1f86a9097bb05c227dfc11a6739a4970d7b42360 Mon Sep 17 00:00:00 2001 From: mzuenni Date: Fri, 28 Jul 2017 01:03:43 +0200 Subject: implemented new bitonic tsp algorithm this algorithm technically can be used to to solve bitonic tsp with linear space (by calculating dist[i][j] on the fly) it should be easier to use, a little bit quicker and is able reconstruct the used tour(maybe there is an easier way to reconstruct it?) --- graph/bitonicTSP.cpp | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) (limited to 'graph/bitonicTSP.cpp') diff --git a/graph/bitonicTSP.cpp b/graph/bitonicTSP.cpp index bf01f9e..478362d 100644 --- a/graph/bitonicTSP.cpp +++ b/graph/bitonicTSP.cpp @@ -1,16 +1,35 @@ -// Laufzeit: O(|V|^2) -vector< vector > dp; // Initialisiere mit -1 -vector< vector > dist; // Initialisiere mit Entfernungen zwischen Punkten. -vector lr, rl; // Links-nach-rechts und rechts-nach-links Pfade. -int n; // #Knoten +// Laufzeit: O(n^2) +vector> dist; // Initialisiere mit Entfernungen zwischen Punkten. -// get(0, 0) gibt die Länge der kürzesten bitonischen Route. -double get(int p1, int p2) { - int v = max(p1, p2) + 1; - if (v == n - 1) return dist[p1][v] + dist[v][p2]; - if (dp[p1][p2] > -0.5) return dp[p1][p2]; - double tryLR = dist[p1][v] + get(v, p2), tryRl = dist[v][p2] + get(p1, v); - if (tryLR < tryRL) lr.push_back(v); // Baut die Pfade auf. Fügt v zu rl hinzu, falls beide gleich teuer. - else rl.push_back(v); // Änder das, falls nötig. - return min(tryLR, tryRL); +void bitonicTSP() { + vector dp(dist.size(), HUGE_VAL); + vector pre(dist.size()); // nur für Tour + dp[0] = 0, dp[1] = 2 * dist[0][1], pre[1] = 0; + for (unsigned int i = 2; i < dist.size(); i++) { + double link = 0; + for (int j = i - 2; j >= 0; j--) { + link += dist[j + 1][j + 2]; + double opt = link + dist[j][i] + dp[j + 1] - dist[j][j + 1]; + if (opt < dp[i]) { + dp[i] = opt; + pre[i] = j; + }}} + // return dp[dist.size() - 1]; // Länger der Tour + + int n = dist.size() - 1; + vector lt, ut; + lt.push_back(n), lt.push_back(n - 1); + int j; + do { + j = pre[n]; + (lt.back() == n ? lt : ut).push_back(j); + for (int i = n - 1; i > j + 1; i--) { + (lt.back() == i ? lt : ut).push_back(i - 1); + } + n = j + 1; + } while(j != 0); + lt.push_back(0); + reverse(lt.begin(), lt.end()); + lt.insert(lt.end(), ut.begin(), ut.end()); + //return lt;// Enthält Knoten 0 zweimal. An erster und letzter Position. } -- cgit v1.2.3 From ff4b56d3bbd9b512a2963288712116d9a2aeeb18 Mon Sep 17 00:00:00 2001 From: mzuenni Date: Fri, 28 Jul 2017 18:32:18 +0200 Subject: fixed last inserted edge --- graph/bitonicTSP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'graph/bitonicTSP.cpp') diff --git a/graph/bitonicTSP.cpp b/graph/bitonicTSP.cpp index 478362d..babddbd 100644 --- a/graph/bitonicTSP.cpp +++ b/graph/bitonicTSP.cpp @@ -28,7 +28,7 @@ void bitonicTSP() { } n = j + 1; } while(j != 0); - lt.push_back(0); + (lt.back() == 1 ? lt : ut).push_back(0); reverse(lt.begin(), lt.end()); lt.insert(lt.end(), ut.begin(), ut.end()); //return lt;// Enthält Knoten 0 zweimal. An erster und letzter Position. -- cgit v1.2.3 From c7c2ee8604b84227be8f1b727930cf544efe2fcc Mon Sep 17 00:00:00 2001 From: mzuenni Date: Sat, 29 Jul 2017 11:44:53 +0200 Subject: reimplemented old dp solution and added path reconstruction --- graph/bitonicTSP.cpp | 54 +++++++++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 30 deletions(-) (limited to 'graph/bitonicTSP.cpp') diff --git a/graph/bitonicTSP.cpp b/graph/bitonicTSP.cpp index babddbd..f607f2c 100644 --- a/graph/bitonicTSP.cpp +++ b/graph/bitonicTSP.cpp @@ -1,35 +1,29 @@ // Laufzeit: O(n^2) vector> dist; // Initialisiere mit Entfernungen zwischen Punkten. +vector> dp; +vector> choice; -void bitonicTSP() { - vector dp(dist.size(), HUGE_VAL); - vector pre(dist.size()); // nur für Tour - dp[0] = 0, dp[1] = 2 * dist[0][1], pre[1] = 0; - for (unsigned int i = 2; i < dist.size(); i++) { - double link = 0; - for (int j = i - 2; j >= 0; j--) { - link += dist[j + 1][j + 2]; - double opt = link + dist[j][i] + dp[j + 1] - dist[j][j + 1]; - if (opt < dp[i]) { - dp[i] = opt; - pre[i] = j; - }}} - // return dp[dist.size() - 1]; // Länger der Tour +double get(int p1, int p2) { + int v = max(p1, p2) + 1; + if (v == dist.size()) return dist[p1][v - 1] + dist[p2][v - 1]; + if (dp[p1][p2] >= 0.0) return dp[p1][p2]; + double tryLR = dist[p1][v] + get(v, p2), tryRL = dist[p2][v] + get(p1, v); + choice[p1][p2] = tryLR < tryRL; + return dp[p1][p2] = min(tryLR, tryRL); +} - int n = dist.size() - 1; - vector lt, ut; - lt.push_back(n), lt.push_back(n - 1); - int j; - do { - j = pre[n]; - (lt.back() == n ? lt : ut).push_back(j); - for (int i = n - 1; i > j + 1; i--) { - (lt.back() == i ? lt : ut).push_back(i - 1); - } - n = j + 1; - } while(j != 0); - (lt.back() == 1 ? lt : ut).push_back(0); - reverse(lt.begin(), lt.end()); - lt.insert(lt.end(), ut.begin(), ut.end()); - //return lt;// Enthält Knoten 0 zweimal. An erster und letzter Position. +void bitonicTour() { + dp = vector>(dist.size(), vector(dist.size(), -1)); + choice = vector>(dist.size(), vector(dist.size())); + get(0, 0); + // return dp[0][0]; // Länger der Tour + vector lr = {0}, rl = {0}; + for (int p1 = 0, p2 = 0, v; (v = max(p1, p2) + 1) < dist.size();) { + if (choice[p1][p2]) { + lr.push_back(v); p1 = v; + } else { + rl.push_back(v); p2 = v; + }} + lr.insert(lr.end(), rl.rbegin(), rl.rend()); + // return lr; // Enthält Knoten 0 zweimal. An erster und letzter Position. } -- cgit v1.2.3