From bbc24df31f2694ec0c8e6e257dce6f9e4dd720b8 Mon Sep 17 00:00:00 2001 From: Jan Potocki Date: Sun, 17 Nov 2019 21:02:29 +0100 Subject: [PATCH] Initial commit --- .gitignore | 32 +++ ArrayGraph.cpp | 70 +++++ ArrayGraph.h | 24 ++ Graph.cpp | 681 ++++++++++++++++++++++++++++++++++++++++++++++++ Graph.h | 40 +++ ListGraph.cpp | 167 ++++++++++++ ListGraph.h | 29 +++ Makefile | 24 ++ Stopwatch.cpp | 23 ++ Stopwatch.h | 22 ++ berlin52.tsp.gz | Bin 0 -> 472 bytes ftv33.atsp.gz | Bin 0 -> 2487 bytes ftv47.atsp.gz | Bin 0 -> 4694 bytes ftv64.atsp.gz | Bin 0 -> 8252 bytes pea2plus.cpp | 511 ++++++++++++++++++++++++++++++++++++ swiss42.tsp.gz | Bin 0 -> 2904 bytes 16 files changed, 1623 insertions(+) create mode 100644 .gitignore create mode 100755 ArrayGraph.cpp create mode 100755 ArrayGraph.h create mode 100755 Graph.cpp create mode 100755 Graph.h create mode 100755 ListGraph.cpp create mode 100755 ListGraph.h create mode 100644 Makefile create mode 100755 Stopwatch.cpp create mode 100755 Stopwatch.h create mode 100755 berlin52.tsp.gz create mode 100755 ftv33.atsp.gz create mode 100644 ftv47.atsp.gz create mode 100644 ftv64.atsp.gz create mode 100755 pea2plus.cpp create mode 100644 swiss42.tsp.gz diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..259148f --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app diff --git a/ArrayGraph.cpp b/ArrayGraph.cpp new file mode 100755 index 0000000..3ab1d54 --- /dev/null +++ b/ArrayGraph.cpp @@ -0,0 +1,70 @@ +#include "ArrayGraph.h" +#include + +ArrayGraph::ArrayGraph(unsigned vertexNumber) +{ + //ctor + this->vertexNumber = vertexNumber; + graphMatrix = new unsigned*[vertexNumber]; + graphArray = new unsigned[vertexNumber*vertexNumber]; + // W ten sposob cala tablica bedzie w pamieci w jednej czesci + // (mniej chybien w odwolaniach procesora do cache) + + for(int i = 0; i < vertexNumber; i++) + { + graphMatrix[i] = graphArray + i * vertexNumber; + + for(int j = 0; j < vertexNumber; j++) + graphMatrix[i][j] = 0; + } +} + +ArrayGraph::~ArrayGraph() +{ + //dtor + delete graphArray; + delete graphMatrix; +} + +bool ArrayGraph::addEdge(unsigned v, unsigned w, unsigned weight) +{ + if(weight >= 1000) + // Waga krawedzi musi byc mniejsza od 1000 + weight = 900; + + if(graphMatrix[v][w] > 0) + return false; + else + { + graphMatrix[v][w] = weight; + return true; + } +} + +bool ArrayGraph::removeEdge(unsigned v, unsigned w) +{ + if(graphMatrix[v][w] == 0) + return false; + else + { + graphMatrix[v][w] = 0; + return true; + } +} + +unsigned ArrayGraph::getWeight(unsigned v, unsigned w) +{ + return graphMatrix[v][w]; +} + +void ArrayGraph::displayGraph() +{ + for(int i = 0; i < vertexNumber; i++) + { + for(int j = 0; j < vertexNumber; j++) + { + std::cout << graphMatrix[i][j] << '\t'; + } + std::cout << std::endl; + } +} diff --git a/ArrayGraph.h b/ArrayGraph.h new file mode 100755 index 0000000..c0a86cb --- /dev/null +++ b/ArrayGraph.h @@ -0,0 +1,24 @@ +#ifndef ARRAYGRAPH_H +#define ARRAYGRAPH_H + +#include "Graph.h" + +class ArrayGraph : public Graph +{ + public: + ArrayGraph(unsigned vertexNumber); + virtual ~ArrayGraph(); + bool addEdge(unsigned v, unsigned w, unsigned weight); + bool removeEdge(unsigned v, unsigned w); + unsigned getWeight(unsigned v, unsigned w); + void displayGraph(); + + protected: + + private: + unsigned **graphMatrix; + unsigned *graphArray; + +}; + +#endif // ARRAYGRAPH_H diff --git a/Graph.cpp b/Graph.cpp new file mode 100755 index 0000000..745098a --- /dev/null +++ b/Graph.cpp @@ -0,0 +1,681 @@ +#include "Graph.h" +#include "Stopwatch.h" +#include +#include +#include +#include +#include + +#include + +Graph::Graph() +{ + //ctor +} + +Graph::~Graph() +{ + //dtor +} + +unsigned Graph::getVertexNumber() +{ + return vertexNumber; +} + +void Graph::randomGenerateFullGraph(Graph &graph, unsigned maxWeight) +{ + std::random_device randomSrc; + std::default_random_engine randomGen(randomSrc()); + std::uniform_int_distribution<> weightDist(1, maxWeight); + + for(int i = 0; i < graph.vertexNumber; i++) + { + for(int j = 0; j < graph.vertexNumber; j++) + { + if(i != j) + { + // Bez warunku na krawedzie juz wygenerowane... + // ...z tym radzi sobie juz metoda addEdge + int randomWeight = weightDist(randomGen); + graph.addEdge(i, j, randomWeight); + } + } + } +} + +std::vector Graph::travellingSalesmanBruteForce(Graph &graph) +{ + // ALGORYTM przegladu zupelnego + // Implementacja: Jan Potocki 2017 + // (refactoring 2019) + std::vector vertexArray; + + // Generowanie "spisu" wierzcholkow + // (od razu w odpowiedniej kolejnosci dla next_permutation) + for(int i = 1; i < graph.vertexNumber; i++) + vertexArray.push_back(i); + + std::vector minCombination; + int minRoute = -1; + + // Petla przegladajaca kolejne permutacje + do + { + std::vector combination; + + // Dodanie wierzcholka startowego i pierwszego na trasie + combination.push_back(0); + combination.push_back(vertexArray.front()); + + // W petli reszta wiercholkow + for(int i = 1; i < vertexArray.size(); i++) + combination.push_back(vertexArray.at(i)); + + // Powrot do wierzcholka startowego + combination.push_back(0); + // PEA 2 + // Jan Potocki 2017 + + int route = 0; + for(int i = 1; i < combination.size(); i++) + route += graph.getWeight(combination.at(i - 1), combination.at(i)); + + if(minRoute == -1 || route < minRoute) + { + minRoute = route; + minCombination = combination; + } + } + while(next_permutation(vertexArray.begin(), vertexArray.end())); + + return minCombination; +} + +std::vector Graph::travellingSalesmanBranchAndBound(Graph &graph) +{ + // ALGORYTM pracujacy w oparciu o kolejke priorytetowa i niejawnie utworzone drzewo + // Zrodlo: www.ii.uni.wroc.pl/~prz/2011lato/ah/opracowania/met_podz_ogr.opr.pdf + // Autor: Mateusz Lyczek 2011 + // Implementacja: Jan Potocki 2017 + std::priority_queue, std::vector< std::vector >, RouteComparison> routeQueue; + std::vector optimalRoute; // Tu bedziemy zapisywac optymalne (w danej chwili) rozwiazanie + int optimalRouteLength = -1; // -1 - bedziemy odtad uznawac, ze to jest nieskonczonosc ;-) + + // UMOWA + // Pierwszy element wektora to dlugosc trasy (trzeba ustawic "z palca"!) + // Kolejne to wierzcholki na trasie + std::vector currentRoute; // Niejawne tworzenie drzewa, tu bedzie korzen + currentRoute.push_back(0); // Poczatkowe oszacowanie nie ma znaczenia + currentRoute.push_back(0); // Wierzcholek startowy (korzen drzewa rozwiazan) + routeQueue.push(currentRoute); // Dodanie do kolejki korzenia + + while(!routeQueue.empty()) + { + // Przypisanie korzenia do dalszej roboty + currentRoute = routeQueue.top(); + routeQueue.pop(); + + // Sprawdzenie, czy rozwiazanie jest warte rozwijania, czy odrzucic + if(optimalRouteLength == -1 || currentRoute.at(0) < optimalRouteLength) + { + for(int i = 0; i < graph.vertexNumber; i++) + { + // Petla wykonywana dla kazdego potomka rozpatrywanego wlasnie rozwiazania w drzewie + // Ustalenie, czy dany wierzcholek mozna jeszcze wykorzystac, czy juz zostal uzyty + bool vertexUsed = false; + for(int j = 1; j < currentRoute.size(); j++) + { + if(currentRoute.at(j) == i) + { + vertexUsed = true; + break; + } + } + if(vertexUsed) + continue; + + // Niejawne utworzenie nowego wezla reprezuntujacego rozpatrywane rozwiazanie... + std::vector nextRoute = currentRoute; + //unsigned nextLength = graph.getWeight(nextRoute.back(), i); + nextRoute.push_back(i); + + // Dalej bedziemy postepowac roznie... + if(nextRoute.size() > graph.vertexNumber) + { + // Doszlismy wlasnie do liscia + // Dodajemy droge powrotna, nie musimy nic szacowac + // (wszystko juz wiemy) + nextRoute.push_back(0); + + nextRoute.at(0) = 0; + + for(int j = 1; j < nextRoute.size() - 1; j++) + { + // Liczymy dystans od poczatku do konca + nextRoute.at(0) += graph.getWeight(nextRoute.at(j), nextRoute.at(j+ 1)); + } + if(optimalRouteLength == -1 || nextRoute.at(0) < optimalRouteLength) + { + optimalRouteLength = nextRoute.at(0); + nextRoute.erase(nextRoute.begin()); + optimalRoute = nextRoute; + } + } + else + { + // Liczenie tego, co juz wiemy, od nowa... + // (dystans od poczatku) + nextRoute.at(0) = 0; + for(int j = 1; j < nextRoute.size() - 1; j++) + { + nextRoute.at(0) += graph.getWeight(nextRoute.at(j), nextRoute.at(j + 1)); + } + + // Reszte szacujemy... + // Pomijamy od razu wierzcholek startowy + for(int j = 1; j < graph.vertexNumber; j++) + { + // Odrzucenie wierzcholkow juz umieszczonych na trasie + bool vertexUsed = false; + for(int k = 1; k < currentRoute.size(); k++) + { + if(j == currentRoute.at(k)) + { + vertexUsed = true; + break; + } + } + if(vertexUsed) + continue; + + int minEdge = -1; + for(int k = 0; k < graph.vertexNumber; k++) + { + // Odrzucenie krawedzi do wierzcholka 0 przy ostatnim wierzcholku w czesciowym rozwiazaniu + // Wyjatkiem jest ostatnia mozliwa krawedz + if(j == i && k == 0) + continue; + + // Odrzucenie krawedzi do wierzcholka umieszczonego juz na rozwazanej trasie + bool vertexUsed = false; + for(int l = 2; l < nextRoute.size(); l++) + { + if(k == nextRoute.at(l)) + { + vertexUsed = true; + break; + } + } + if(vertexUsed) + continue; + + // Odrzucenie samego siebie + if(k == j) + continue; + + // Znalezienie najkrotszej mozliwej jeszcze do uzycia krawedzi + unsigned consideredLength = graph.getWeight(j, k); + + if(minEdge == -1) + minEdge = consideredLength; + else if(minEdge > consideredLength) + minEdge = consideredLength; + } + nextRoute.at(0) += minEdge; + } + + // ...i teraz zastanawiamy sie co dalej + if(optimalRouteLength == -1 || nextRoute.at(0) < optimalRouteLength) + { + routeQueue.push(nextRoute); + } + } + } + } + else + { + // Jezeli jedno rozwiazanie odrzucilismy, to wszystkie inne tez mozemy + // (kolejka priorytetowa, inne nie moga byc lepsze) + break; + } + } + + return optimalRoute; +} + +std::vector Graph::travellingSalesmanGreedy(Graph &graph, unsigned startVertex) +{ + // ALGORYTM zachlanny z wierzcholkiem startowym przekazanym w parametrze + // Implementacja: Jan Potocki 2017 + std::vector route; + + // std::random_device randomSrc; + // std::default_random_engine randomGen(randomSrc()); + // std::uniform_int_distribution<> vertexDist(0, graph.vertexNumber - 1); + + // Losowanie wierzcholka startowego + //route.push_back(vertexDist(randomGen)); + route.push_back(startVertex); + + for(int i = 0; i < graph.vertexNumber - 1; i++) + { + int minEdge = -1; + unsigned nextVertex; + for(int j = 0; j < graph.vertexNumber; j++) + { + // Odrzucenie samego siebie lub wierzcholka startowego + // (zeby bylo szybciej) + if(route.back() == j || route.front() == j) + continue; + + // Odrzucenie krawedzi do wierzcholka umieszczonego juz na trasie + bool vertexUsed = false; + for(int k = 0; k < route.size(); k++) + { + if(j == route.at(k)) + { + vertexUsed = true; + break; + } + } + if(vertexUsed) + continue; + + // Znalezienie najkrotszej mozliwej jeszcze do uzycia krawedzi + unsigned consideredLength = graph.getWeight(route.back(), j); + + if(minEdge == -1) + { + minEdge = consideredLength; + nextVertex = j; + } + else if(minEdge > consideredLength) + { + minEdge = consideredLength; + nextVertex = j; + } + } + route.push_back(nextVertex); + } + + route.push_back(startVertex); + return route; +} + +std::vector Graph::travellingSalesmanHybrid(Graph &graph) +{ + // ALGORYTM hybrydowy losowo-zachlanny + // Losowa czesc wierzcholkow jest losowana, reszta zachlannie + // Implementacja: Jan Potocki 2019 + std::vector route; + + std::random_device randomSrc; + std::default_random_engine randomGen(randomSrc()); + std::uniform_int_distribution<> vertexNumberDist(1, graph.vertexNumber); + std::uniform_int_distribution<> vertexDist(0, graph.vertexNumber - 1); + + // Liczba losowanych wierzcholkow + unsigned randomVertexNumber = vertexNumberDist(randomGen); + + // Czesc losowa + for(int i = 0; i < randomVertexNumber; i++) + { + unsigned randomVertex; + bool vertexUsed; + + do + { + randomVertex = vertexDist(randomGen); + vertexUsed = false; + + for(int j = 0; j < route.size(); j++) + { + if(route.at(j) == randomVertex) + { + vertexUsed = true; + break; + } + } + } while(vertexUsed == true); + + route.push_back(randomVertex); + } + + // Czesc zachlanna + for(int i = 0; i < graph.vertexNumber - randomVertexNumber; i++) + { + int minEdge = -1; + unsigned nextVertex; + for(int j = 0; j < graph.vertexNumber; j++) + { + // Odrzucenie samego siebie lub wierzcholka startowego + // (zeby bylo szybciej) + if(route.back() == j || route.front() == j) + continue; + + // Odrzucenie krawedzi do wierzcholka umieszczonego juz na trasie + bool vertexUsed = false; + for(int k = 0; k < route.size(); k++) + { + if(j == route.at(k)) + { + vertexUsed = true; + break; + } + } + if(vertexUsed) + continue; + + // Znalezienie najkrotszej mozliwej jeszcze do uzycia krawedzi + unsigned consideredLength = graph.getWeight(route.back(), j); + + if(minEdge == -1) + { + minEdge = consideredLength; + nextVertex = j; + } + else if(minEdge > consideredLength) + { + minEdge = consideredLength; + nextVertex = j; + } + } + route.push_back(nextVertex); + } + + route.push_back(route.front()); + return route; +} + +std::vector Graph::travellingSalesmanRandom(Graph &graph) +{ + // ALGORYTM losowy + // Implementacja: Jan Potocki 2019 + std::vector route; + + std::random_device randomSrc; + std::default_random_engine randomGen(randomSrc()); + std::uniform_int_distribution<> vertexDist(0, graph.vertexNumber - 1); + + for(int i = 0; i < graph.vertexNumber; i++) + { + unsigned randomVertex; + bool vertexUsed; + + do + { + randomVertex = vertexDist(randomGen); + vertexUsed = false; + + for(int j = 0; j < route.size(); j++) + { + if(route.at(j) == randomVertex) + { + vertexUsed = true; + break; + } + } + } while(vertexUsed == true); + + route.push_back(randomVertex); + } + + route.push_back(route.front()); + return route; +} + +std::vector Graph::travellingSalesmanTabuSearch(Graph &graph, unsigned tabuSteps, bool diversification, int iterationsToRestart, unsigned minStopTime, unsigned threadsNumber) +{ + // ALGORYTM wielawotkowy oparty na metaheurystyce tabu search + // Pomocniczy kod uruchamiajacy watki wlasciwego algorytmu w najbardziej optymalny sposob + // Implementacja: Jan Potocki 2019 + std::vector startVertexVector; + std::vector threadsVector; + std::vector> resultsVector(threadsNumber); + std::vector resultsLength(threadsNumber); + std::vector optimalResult; + int optimalResultIndex; + int optimalResultLength; + + std::random_device randomSrc; + std::default_random_engine randomGen(randomSrc()); + std::uniform_int_distribution<> vertexDist(0, graph.vertexNumber - 1); + + for(int i = 0; i < threadsNumber; i++) + { + std::vector startRoute; + unsigned startVertex; + bool startVertexUsed; + + if(i < graph.vertexNumber) + { + do + { + startVertex = vertexDist(randomGen); + startVertexUsed = false; + + for(int j = 0; j < startVertexVector.size(); j++) + { + if(startVertexVector.at(j) == startVertex) + { + startVertexUsed = true; + break; + } + } + } while(startVertexUsed == true); + + startVertexVector.push_back(startVertex); + startRoute = Graph::travellingSalesmanGreedy(graph, startVertex); + } + else + { + startRoute = Graph::travellingSalesmanRandom(graph); + } + + 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)))); + } + + for(int i = 0; i < threadsNumber; i++) + threadsVector.at(i).join(); + + optimalResultIndex = 0; + optimalResultLength = resultsLength.at(0); + + for(int i = 0; i < threadsNumber; i++) + { + if(resultsLength.at(i) < optimalResultLength) + { + optimalResultIndex = i; + optimalResultLength = resultsLength.at(i); + } + } + + optimalResult = resultsVector.at(optimalResultIndex); + + return optimalResult; +} + +void Graph::travellingSalesmanTabuSearchEngine(Graph &graph, unsigned tabuSteps, bool diversification, int iterationsToRestart, unsigned minStopTime, std::vector startRoute, std::vector &result, int &resultLength) +{ + // ALGORYTM oparty na metaheurystyce tabu search z dywersyfikacja i sasiedztwem typu swap + // Rdzen przeznaczony do uruchamiania jako jeden watek + // Projekt i implementacja: Jan Potocki 2017 + // (refactoring 2019) + Stopwatch onboardClock; + + std::vector optimalRoute; // Tu bedziemy zapisywac optymalne (w danej chwili) rozwiazanie + int optimalRouteLength = -1; // -1 - bedziemy odtad uznawac, ze to jest nieskonczonosc ;-) + std::vector currentRoute; // Rozpatrywane rozwiazanie + + // Wyznaczenie poczatkowego rozwiazania algorytmem zachlannym + //currentRoute = Graph::travellingSalesmanGreedy(graph); + currentRoute = startRoute; + + // Inicjalizacja glownej petli... + std::vector< std::vector > tabuArray; + unsigned currentTabuSteps = tabuSteps; + int stopCounter = 0; + bool timeNotExceeded = true; + onboardClock.start(); + + // Rdzen algorytmu + while(timeNotExceeded == true) + { + bool cheeseSupplied = true; + bool intensification = false; + + while(cheeseSupplied == true) + { + std::vector nextRoute; + int nextRouteLength = -1; + + std::vector nextTabu(3, 0); + nextTabu.at(0) = currentTabuSteps; + + // Generowanie sasiedztwa typu swap przez zamiane wierzcholkow + // (wierzcholka startowego i zarazem ostatniego nie ruszamy, + // pomijamy tez od razu aktualny wierzcholek) + for(int i = 1; i < graph.vertexNumber - 1; i++) + { + for(int j = i + 1; j < graph.vertexNumber; j++) + { + std::vector neighbourRoute = currentRoute; + + // Zamiana + unsigned buffer = neighbourRoute.at(j); + neighbourRoute.at(j) = neighbourRoute.at(i); + neighbourRoute.at(i) = buffer; + + unsigned neighbourRouteLength = 0; + for(int i = 1; i < neighbourRoute.size(); i++) + neighbourRouteLength += graph.getWeight(neighbourRoute.at(i - 1), neighbourRoute.at(i)); + + // Sprawdzenie, czy dany ruch nie jest na liscie tabu + // (dwa wierzcholki) + bool tabu = false; + for(int k = 0; k < tabuArray.size(); k++) + { + if(tabuArray.at(k).at(1) == i && tabuArray.at(k).at(2) == j) + { + tabu = true; + break; + } + + if(tabuArray.at(k).at(1) == j && tabuArray.at(k).at(2) == i) + { + tabu = true; + break; + } + } + + // Kryterium aspiracji... + if(tabu == true && neighbourRouteLength >= optimalRouteLength) + // ...jezeli niespelnione - pomijamy ruch + continue; + + if(nextRouteLength == -1) + { + nextRouteLength = neighbourRouteLength; + nextRoute = neighbourRoute; + nextTabu.at(1) = i; + nextTabu.at(2) = j; + } + else if(nextRouteLength > neighbourRouteLength) + { + nextRouteLength = neighbourRouteLength; + nextRoute = neighbourRoute; + nextTabu.at(1) = i; + nextTabu.at(2) = j; + } + } + } + + currentRoute = nextRoute; + + if(optimalRouteLength == -1) + { + optimalRouteLength = nextRouteLength; + optimalRoute = nextRoute; + + // Reset licznika + stopCounter = 0; + } + else if(optimalRouteLength > nextRouteLength) + { + optimalRouteLength = nextRouteLength; + optimalRoute = nextRoute; + + // Zaplanowanie intensyfikacji + intensification = true; + + // Reset licznika + stopCounter = 0; + } + + // Weryfikacja listy tabu... + // ...aktualizacja kadencji na liscie tabu + for(int i = 0; i < tabuArray.size(); i++) + { + tabuArray.at(i).at(0)--; + } + + //...usuniecie zerowych kadencji + for(int i = 0; i < tabuArray.size(); i++) + { + if(tabuArray.at(i).at(0) == 0) + tabuArray.erase(tabuArray.begin() + i); + } + + // ...dopisanie ostatniego ruchu do listy tabu + tabuArray.push_back(nextTabu); + + // Zliczenie iteracji + stopCounter++; + + // Zmierzenie czasu + onboardClock.stop(); + if(onboardClock.read() > minStopTime) + timeNotExceeded = false; + + // Sprawdzenie warunku zatrzymania + if(diversification == true) + { + // Przy aktywowanej dywersyfikacji - po zadanej liczbie iteracji bez poprawy + if(stopCounter >= iterationsToRestart || timeNotExceeded == false) + cheeseSupplied = false; + } + else + { + // Przy nieaktywowanej dywersyfikacji - po uplynieciu okreslonego czasu + if(timeNotExceeded == false) + cheeseSupplied = false; + } + } + + // Dywersyfikacja + if(diversification == true) + { + if(intensification == true) + { + // Intensyfikacja przeszukiwania przy ostatnim minimum + currentRoute = optimalRoute; + currentTabuSteps = tabuSteps / 4; + intensification = false; + } + else + { + // Algorytm hybrydowy losowo-zachlanny + currentRoute = Graph::travellingSalesmanHybrid(graph); + currentTabuSteps = tabuSteps; + intensification = false; + } + } + + // Reset licznika iteracji przed restartem + stopCounter = 0; + } + + result = optimalRoute; + resultLength = optimalRouteLength; +} diff --git a/Graph.h b/Graph.h new file mode 100755 index 0000000..a4fd6aa --- /dev/null +++ b/Graph.h @@ -0,0 +1,40 @@ +#ifndef GRAPH_H +#define GRAPH_H +#include + + +class Graph +{ + public: + Graph(); + virtual ~Graph(); + virtual bool addEdge(unsigned v, unsigned w, unsigned weight) = 0; + virtual bool removeEdge(unsigned v, unsigned w) = 0; + virtual unsigned getWeight(unsigned v, unsigned w) = 0; + unsigned getVertexNumber(); + virtual void displayGraph() = 0; + static void randomGenerateFullGraph(Graph &graph, unsigned maxWeight); + static std::vector travellingSalesmanBruteForce(Graph &graph); + static std::vector travellingSalesmanBranchAndBound(Graph &graph); + static std::vector travellingSalesmanGreedy(Graph &graph, unsigned startVertex); + static std::vector travellingSalesmanHybrid(Graph &graph); + static std::vector travellingSalesmanRandom(Graph &graph); + static std::vector travellingSalesmanTabuSearch(Graph &graph, unsigned tabuSteps, bool diversification, int iterationsToRestart, unsigned minStopTime, unsigned threadsNumber); + + protected: + unsigned vertexNumber; + + private: + static void travellingSalesmanTabuSearchEngine(Graph &graph, unsigned tabuSteps, bool diversification, int iterationsToRestart, unsigned minStopTime, std::vector startRoute, std::vector &result, int &resultLength); + + class RouteComparison + { + public: + bool operator() (const std::vector& lhs, const std::vector& rhs) const + { + return (lhs.at(0) > rhs.at(0)); + } + }; +}; + +#endif // GRAPH_H diff --git a/ListGraph.cpp b/ListGraph.cpp new file mode 100755 index 0000000..bb5b1a5 --- /dev/null +++ b/ListGraph.cpp @@ -0,0 +1,167 @@ +#include "ListGraph.h" +#include + +ListGraph::ListGraph(unsigned vertexNumber) +{ + //ctor + this->vertexNumber = vertexNumber; + graphList = new element*[vertexNumber]; + + for(int i = 0; i < vertexNumber; i++) + graphList[i] = NULL; +} + +ListGraph::~ListGraph() +{ + //dtor + for(int i = 0; i < vertexNumber; i++) + { + if(graphList[i] != NULL) + { + element *position = graphList[i]; + do + { + element *next = position->next; + delete position; + position = next; + } + while(position != NULL); + } + } + + delete[] graphList; +} + +bool ListGraph::addEdge(unsigned v, unsigned w, unsigned weight) +{ + if(weight >= 1000) + // Waga krawedzi musi byc mniejsza od 1000 + weight = 900; + + if(graphList[v] == NULL) + { + graphList[v] = new element; + graphList[v]->vertex = w; + graphList[v]->weight = weight; + graphList[v]->next = NULL; + + return true; + } + else + { + bool isAlready = false; + element *next = graphList[v]; + element *position = NULL; + do + { + position = next; + next = next->next; + if(position->vertex == w) + { + isAlready = true; + break; + } + } + while(next != NULL); + + if(!isAlready) + { + element *newEdge = new element; + newEdge->vertex = w; + newEdge->weight = weight; + newEdge->next = NULL; + position->next = newEdge; + + return true; + } + else + return false; + } +} + +bool ListGraph::removeEdge(unsigned v, unsigned w) +{ + if(graphList[v] == NULL) + return false; + else + { + bool isAlready = false; + element *next = graphList[v]; + element *position = NULL; + element *prev = NULL; + do + { + prev = position; + position = next; + next = next->next; + if(position->vertex == w) + { + isAlready = true; + break; + } + } + while(next != NULL); + + if(!isAlready) + return false; + else + { + delete position; + if(prev != NULL) + prev->next = next; + else + graphList[v] = next; + + return true; + } + } +} + +unsigned ListGraph::getWeight(unsigned v, unsigned w) +{ + if(graphList[v] == NULL) + return 0; + else + { + bool isAlready = false; + element *next = graphList[v]; + element *position = NULL; + do + { + position = next; + next = next->next; + if(position->vertex == w) + { + isAlready = true; + break; + } + } + while(next != NULL); + + if(!isAlready) + return 0; + else + return position->weight; + } +} + +void ListGraph::displayGraph() +{ + for(int i = 0; i < vertexNumber; i++) + { + std::cout << i << " -> "; + if(graphList[i] != NULL) + { + element *next = graphList[i]; + element *position = NULL; + do + { + position = next; + next = next->next; + std::cout << position->vertex << '@' << position->weight << ' '; + } + while(next != NULL); + } + std::cout << std::endl; + } +} diff --git a/ListGraph.h b/ListGraph.h new file mode 100755 index 0000000..928c2e3 --- /dev/null +++ b/ListGraph.h @@ -0,0 +1,29 @@ +#ifndef LISTGRAPH_H +#define LISTGRAPH_H + +#include "Graph.h" + +class ListGraph : public Graph +{ + public: + ListGraph(unsigned vertexNumber); + virtual ~ListGraph(); + bool addEdge(unsigned v, unsigned w, unsigned weight); + bool removeEdge(unsigned v, unsigned w); + unsigned getWeight(unsigned v, unsigned w); + void displayGraph(); + + protected: + + private: + struct element + { + unsigned vertex; + int weight; + element *next; + }; + element **graphList; + +}; + +#endif // LISTGRAPH_H diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..537ac92 --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ +CXXFLAGS = -O3 -Wall -std=c++11 + +ifeq ($(OS),Windows_NT) + detected_OS := Windows +else + detected_OS := $(shell uname) +endif +ifeq ($(detected_OS),Darwin) + CXXFLAGS += -stdlib=libc++ +endif + +OBJS = pea2plus.o ArrayGraph.o Graph.o ListGraph.o Stopwatch.o + +LIBS = -pthread + +TARGET = pea2plus + +$(TARGET): $(OBJS) + $(CXX) -o $(TARGET) $(OBJS) $(LIBS) + +all: $(TARGET) + +clean: + rm -f $(OBJS) $(TARGET) diff --git a/Stopwatch.cpp b/Stopwatch.cpp new file mode 100755 index 0000000..9fe15dc --- /dev/null +++ b/Stopwatch.cpp @@ -0,0 +1,23 @@ +#include "Stopwatch.h" + +Stopwatch::Stopwatch() +{ + //ctor + // Jan Potocki 2017-2019 +} + +void Stopwatch::start() +{ + tstart = std::chrono::steady_clock::now(); +} + +void Stopwatch::stop() +{ + tstop = std::chrono::steady_clock::now(); + measurement = tstop - tstart; +} + +double Stopwatch::read() +{ + return measurement.count(); +} diff --git a/Stopwatch.h b/Stopwatch.h new file mode 100755 index 0000000..05b1272 --- /dev/null +++ b/Stopwatch.h @@ -0,0 +1,22 @@ +#ifndef STOPWATCH_H +#define STOPWATCH_H + +#include + +// Klasa do pomiaru czasu (wieloplatformowa) +// Jan Potocki 2017-2019 +class Stopwatch +{ + public: + Stopwatch(); + void start(); + void stop(); + double read(); + protected: + private: + std::chrono::duration measurement; + std::chrono::time_point tstart; + std::chrono::time_point tstop; +}; + +#endif // STOPWATCH_H diff --git a/berlin52.tsp.gz b/berlin52.tsp.gz new file mode 100755 index 0000000000000000000000000000000000000000..23c8f2f3153f088f4b4b1bbf2dfb3514a6a12841 GIT binary patch literal 472 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 YKg_z@G(UTI_59gC0nn$_E*)+F0Kg$t%>V!Z literal 0 HcmV?d00001 diff --git a/ftv64.atsp.gz b/ftv64.atsp.gz new file mode 100644 index 0000000000000000000000000000000000000000..ff7c12713731a90f9cf9c3ae68b5be788a026c42 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/pea2plus.cpp b/pea2plus.cpp new file mode 100755 index 0000000..b561a88 --- /dev/null +++ b/pea2plus.cpp @@ -0,0 +1,511 @@ +#include +#include +#include +#include +#include +#include "Stopwatch.h" +#include "ArrayGraph.h" +#include "ListGraph.h" + +using namespace std; + +// USTAWIENIA +// Liczba powtorzen automatycznych pomiarow do usrednienia +const int measureIterations = 10; +// liczba automatycznych pomiarow +const int measureNumber = 4; +// Czas zatrzymania algorytmu tabu search w kazdym z automatycznych pomiarow +const int measureTabuStop[4] = {1, 5, 10, 15}; +// Maksymalna odleglosc miast przy automatycznym generowaniu +const int measureSalesmanDistance = 400; + +// Kadencja tabu search +const int tabuLength = 30; +// Kryterium dywersyfikacji, liczba iteracji bez poprawy +const int tabuIterationsToRestart = 10000; + +// Wykorzystanie reprezentacji grafu w postaci list sasiedztwa... +// ...zamiast (domyslnie) macierzy sasiedztwa +// (wolniejsze obliczenia, mniejsze uzycie pamieci) +const bool useListGraph = false; + +// Liczba watkow tabu search +const unsigned tabuThreadsNumber = 2; + +// Domyslny czas zatrzymania algorytmu tabu search [s] +int tabuStopTime = 60; + +// Domyslny stan dywersyfikacji +bool tabuDiversification = true; + +int main() +{ + Stopwatch clock; // czasomierz + Graph *graph = NULL; // <- tu bedziemy zapisywac adresy przez caly program + + cout << "PEA Projekt 2 v2.0ALPHA Plus" << endl; + cout << "Jan Potocki 2017-2019" << endl; + cout << "(beerware)" << endl; + if(useListGraph) + cout << "Uzycie listowej reprezentacji grafu" << endl; + else + cout << "Uzycie macierzowej reprezentacji grafu" << endl; + cout << endl; + + int salesmanSelection; + do + { + cout << "1 - wygeneruj losowe dane" << endl; + cout << "2 - wyswietl dane" << endl; + cout << "3 - dywersyfikacja TS" << endl; + cout << "4 - czas zatrzymania TS" << endl; + cout << "5 - tabu search" << endl; + cout << "6 - algorytm zachlanny" << endl; + cout << "7 - podzial i ograniczenia" << endl; + cout << "8 - przeglad zupelny" << endl; + cout << "9 - automatyczne pomiary (tabu search)" << endl; + cout << "10 - wczytaj dane z pliku ATSP" << endl; + cout << "11 - wczytaj dane z pliku TSP" << endl; + cout << "Aby zakonczyc - 0" << endl; + cout << "Wybierz: "; + cin >> salesmanSelection; + cout << endl; + + switch(salesmanSelection) + { + case 1: + { + int vertex; + cout << "Liczba miast: "; + cin >> vertex; + cout << endl; + + if(graph != NULL) + delete graph; + + if(useListGraph) + graph = new ListGraph(vertex); + else + graph = new ArrayGraph(vertex); + + Graph::randomGenerateFullGraph(*graph, measureSalesmanDistance); + } + break; + case 2: + { + if(graph != NULL) + graph->displayGraph(); + else + cout << "Brak wygenerowanych danych" << endl; + cout << endl; + } + break; + case 3: + { + tabuDiversification = !tabuDiversification; + + if(tabuDiversification == true) + cout << "Dywersyfikacja TS zostala wlaczona" << endl; + else + cout << "Dywersyfikacja TS zostala wylaczona" << endl; + cout << endl; + } + break; + case 4: + { + cout << "Poprzedni czas pracy TS: " << tabuStopTime << endl; + cout << "Podaj nowy czas: "; + cin >> tabuStopTime; + cout << endl; + } + break; + case 5: + { + if(graph != NULL) + { + if(tabuStopTime != 0) + { + cout << "Kadencja: " << tabuLength << endl; + cout << "Czas zatrzymania algorytmu [s]: " << tabuStopTime << endl; + + if(tabuDiversification == true) + cout << "Dywersyfikacja wlaczona, kryterium: " << tabuIterationsToRestart << " iteracji" << endl; + else + cout << "Dywersyfikacja wylaczona" << endl; + + cout << endl; + + clock.start(); + vector route = Graph::travellingSalesmanTabuSearch(*graph, tabuLength, tabuDiversification, tabuIterationsToRestart, tabuStopTime, tabuThreadsNumber); + clock.stop(); + + // Wyswietlenie trasy + unsigned distFromStart = 0; + unsigned length = 0; + cout << route.at(0) << '\t' << length << '\t' << distFromStart << endl; + for(int i = 1; i < route.size(); i++) + { + length = graph->getWeight(route.at(i - 1), route.at(i)); + distFromStart += length; + + cout << route.at(i) << '\t' << length << '\t' << distFromStart << endl; + } + + cout << "Dlugosc trasy: " << distFromStart << endl; + cout << endl; + cout << "Czas wykonania algorytmu [s]: " << clock.read() << endl; + } + else + { + // Easter egg ;-) + cout << "+++ MELON MELON MELON +++ Blad: Brak Sera! +++ !!!!! +++" << endl; + } + } + else + cout << "+++ MELON MELON MELON +++ Brak zaladowanych danych +++" << endl; + cout << endl; + } + break; + case 6: + { + if(graph != NULL) + { + clock.start(); + vector route = Graph::travellingSalesmanGreedy(*graph, 0); + clock.stop(); + + // Wyswietlenie trasy + unsigned distFromStart = 0; + unsigned length = 0; + cout << route.at(0) << '\t' << length << '\t' << distFromStart << endl; + for(int i = 1; i < route.size(); i++) + { + length = graph->getWeight(route.at(i - 1), route.at(i)); + distFromStart += length; + + cout << route.at(i) << '\t' << length << '\t' << distFromStart << endl; + } + + cout << "Dlugosc trasy: " << distFromStart << endl; + cout << endl; + cout << "Czas wykonania algorytmu [s]: " << clock.read() << endl; + } + else + cout << "+++ MELON MELON MELON +++ Brak zaladowanych danych +++" << endl; + cout << endl; + } + break; + case 7: + { + if(graph != NULL) + { + clock.start(); + vector route = Graph::travellingSalesmanBranchAndBound(*graph); + clock.stop(); + + // Wyswietlenie trasy + unsigned distFromStart = 0; + unsigned length = 0; + cout << route.at(0) << '\t' << length << '\t' << distFromStart << endl; + for(int i = 1; i < route.size(); i++) + { + length = graph->getWeight(route.at(i - 1), route.at(i)); + distFromStart += length; + + cout << route.at(i) << '\t' << length << '\t' << distFromStart << endl; + } + + cout << "Dlugosc trasy: " << distFromStart << endl; + cout << endl; + cout << "Czas wykonania algorytmu [s]: " << clock.read() << endl; + } + else + cout << "+++ MELON MELON MELON +++ Brak zaladowanych danych +++" << endl; + cout << endl; + } + break; + case 8: + { + if(graph != NULL) + { + clock.start(); + vector route = Graph::travellingSalesmanBruteForce(*graph); + clock.stop(); + + // Wyswietlenie trasy + unsigned distFromStart = 0; + unsigned length = 0; + cout << route.at(0) << '\t' << length << '\t' << distFromStart << endl; + for(int i = 1; i < route.size(); i++) + { + length = graph->getWeight(route.at(i - 1), route.at(i)); + distFromStart += length; + + cout << route.at(i) << '\t' << length << '\t' << distFromStart << endl; + } + + cout << "Dlugosc trasy: " << distFromStart << endl; + cout << endl; + cout << "Czas wykonania algorytmu [s]: " << clock.read() << endl; + } + else + cout << "+++ MELON MELON MELON +++ Brak zaladowanych danych +++" << endl; + cout << endl; + } + break; + case 9: + { + // PEA 2 + // Jan Potocki 2017 + if(graph != NULL) + { + double measureResults[measureNumber], measureResultsDiv[measureNumber]; + for(int i = 0; i < measureNumber; i++) + { + measureResults[i] = 0; + measureResultsDiv[i] = 0; + } + + cout << "Pomiary dla problemu komiwojazera, tabu search" << tabuLength << endl; + cout << "Kadencja: " << tabuLength << endl; + cout << "Kryterium dywersyfikacji: " << tabuIterationsToRestart << " iteracji" << endl; + + // Petla pomiarowa + for(int krok = 0; krok < measureIterations; krok++) + { + for(int i = 0; i < measureNumber; i++) + { + vector route; + unsigned routeLength; + + // Bez dywersyfikacji + cout << "Pomiar " << measureTabuStop[i] << " [s] (" << krok + 1 << " z " << measureIterations << " bez dywersyfikacji)..." << endl; + + route = Graph::travellingSalesmanTabuSearch(*graph, tabuLength, false, tabuIterationsToRestart, measureTabuStop[i], tabuThreadsNumber); + + routeLength = 0; + for(int j = 1; j < route.size(); j++) + routeLength += graph->getWeight(route.at(j - 1), route.at(j)); + measureResults[i] += routeLength; + + // Z dywersyfikacja + cout << "Pomiar " << measureTabuStop[i] << " [s] (" << krok + 1 << " z " << measureIterations << " z dywersyfikacja)..." << endl; + + route = Graph::travellingSalesmanTabuSearch(*graph, tabuLength, true, tabuIterationsToRestart, measureTabuStop[i], tabuThreadsNumber); + + routeLength = 0; + for(int j = 1; j < route.size(); j++) + routeLength += graph->getWeight(route.at(j - 1), route.at(j)); + measureResultsDiv[i] += routeLength; + } + } + + cout << "Opracowywanie wynikow..." << endl; + + for(int i = 0; i < measureNumber; i++) + { + measureResults[i] = nearbyint(measureResults[i] / measureIterations); + measureResultsDiv[i] = nearbyint(measureResultsDiv[i] / measureIterations); + } + + cout << "Zapis wynikow..." << endl; + + ofstream salesmanToFile; + salesmanToFile.open("wyniki-komiwojazer-ts.txt"); + salesmanToFile << "czas - bez dywersyfikacji - z dywersyfikacja" << endl; + for(int i = 0; i < measureNumber; i++) + { + salesmanToFile << measureTabuStop[i] << " [s]: " << (int)measureResults[i] << ' ' << (int)measureResultsDiv[i] << endl; + } + salesmanToFile.close(); + + cout << "Gotowe!" << endl; + cout << endl; + } + else + { + cout << "+++ MELON MELON MELON +++ Brak zaladowanych danych +++" << endl; + cout << endl; + } + } + break; + case 10: + { + // Jan Potocki 2017 + string filename, fileInput; + ifstream salesmanDataFile; + + cout << "Podaj nazwe pliku: "; + cin >> filename; + + salesmanDataFile.open(filename.c_str()); + if(salesmanDataFile.is_open()) + { + do + salesmanDataFile >> fileInput; + while(fileInput != "DIMENSION:"); + + salesmanDataFile >> fileInput; + int vertex = stoi(fileInput); + + do + salesmanDataFile >> fileInput; + while(fileInput != "EDGE_WEIGHT_FORMAT:"); + + salesmanDataFile >> fileInput; + if(fileInput == "FULL_MATRIX") + { + if(graph != NULL) + delete graph; + + if(useListGraph) + graph = new ListGraph(vertex); + else + graph = new ArrayGraph(vertex); + + do + salesmanDataFile >> fileInput; + while(fileInput != "EDGE_WEIGHT_SECTION"); + + for(int i = 0; i < vertex; i++) + { + for(int j = 0; j < vertex; j++) + { + salesmanDataFile >> fileInput; + int weight = stoi(fileInput); + + if(i != j) + graph->addEdge(i, j, weight); + } + } + + cout << "Wczytano - liczba wierzcholkow: " << vertex << endl; + cout << endl; + } + else + { + cout << "+++ MELON MELON MELON +++ Nieobslugiwany format " << fileInput << " +++" << endl; + cout << endl; + } + + salesmanDataFile.close(); + } + else + { + cout << "+++ MELON MELON MELON +++ Brak pliku " << filename << " +++" << endl; + cout << endl; + } + } + break; + case 11: + { + // Jan Potocki 2017 + string filename, fileInput; + vector xCoord, yCoord; + ifstream salesmanDataFile; + + cout << "Podaj nazwe pliku: "; + cin >> filename; + + salesmanDataFile.open(filename.c_str()); + if(salesmanDataFile.is_open()) + { + do + salesmanDataFile >> fileInput; + while(fileInput != "DIMENSION:"); + + salesmanDataFile >> fileInput; + int vertex = stoi(fileInput); + + do + salesmanDataFile >> fileInput; + while(fileInput != "EDGE_WEIGHT_TYPE:"); + + salesmanDataFile >> fileInput; + if(fileInput == "EUC_2D") + { + if(graph != NULL) + delete graph; + + if(useListGraph) + graph = new ListGraph(vertex); + else + graph = new ArrayGraph(vertex); + + do + salesmanDataFile >> fileInput; + while(fileInput != "NODE_COORD_SECTION"); + + for(int i = 0; i < vertex; i++) + { + salesmanDataFile >> fileInput; + + salesmanDataFile >> fileInput; + xCoord.push_back(stof(fileInput)); + + salesmanDataFile >> fileInput; + yCoord.push_back(stof(fileInput)); + } + + // To daloby sie zrobic optymalniej (macierz symetryczna), ale nie chce mi sie ... + // ..wole zoptymalizować czas programowania ;-) + for(int i = 0; i < vertex; i++) + { + for(int j = 0; j < vertex; j++) + { + if(i != j) + { + float xDiff = xCoord.at(i) - xCoord.at(j); + float yDiff = yCoord.at(i) - yCoord.at(j); + int weight = nearbyint(sqrt(xDiff * xDiff + yDiff * yDiff)); + + graph->addEdge(i, j, weight); + } + } + } + + cout << "Wczytano - liczba wierzcholkow: " << vertex << endl; + cout << endl; + } + else + { + cout << "+++ MELON MELON MELON +++ Nieobslugiwany format " << fileInput << " +++" << endl; + cout << endl; + } + + salesmanDataFile.close(); + } + else + { + cout << "+++ MELON MELON MELON +++ Brak pliku " << filename << " +++" << endl; + cout << endl; + } + } + break; + case 0: + { + } + break; + default: + { + cout << "Nieprawidlowy wybor" << endl; + cout << endl; + } + } + } while(salesmanSelection != 0); + + if(graph != NULL) + delete graph; + + cout << "Konczenie..." << endl; + // Easter egg :-P + cout << '"' << "Myslak Stibbons niepokoil sie HEX-em." << endl; + cout << "Nie wiedzial, jak dziala, chociaz wszyscy uwazali, ze wie." << endl; + cout << "Oczywiscie, calkiem niezle orientowal sie w niektorych elementach;" << endl; + cout << "byl tez pewien, ze HEX mysli o problemach, przeksztalcajac je" << endl; + cout << "w liczby i mielac ..." << '"' << endl; + cout << "(Terry Pratchett, " << '"' << "Wiedzmikolaj" << '"' << ", tlumaczenie Piotr Cholewa)" << endl; + cout << endl; + + return 0; +} diff --git a/swiss42.tsp.gz b/swiss42.tsp.gz new file mode 100644 index 0000000000000000000000000000000000000000..daa1e2774a7157487833737dcd108e6d334cc8ee GIT binary patch literal 2904 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 C#eF#d literal 0 HcmV?d00001