[Lemon-commits] Gabor Varga: Heuristic algorithms for symmetric ...
Lemon HG
hg at lemon.cs.elte.hu
Fri Mar 1 18:03:15 CET 2013
details: http://lemon.cs.elte.hu/hg/lemon/rev/ae0b056593a7
changeset: 1199:ae0b056593a7
user: Gabor Varga <f4c3 [at] inf.elte.hu>
date: Sat Jan 08 21:59:56 2011 +0100
description:
Heuristic algorithms for symmetric TSP (#386)
diffstat:
lemon/Makefile.am | 5 +
lemon/christofides_tsp.h | 129 ++++++++++++++
lemon/greedy_tsp.h | 176 ++++++++++++++++++++
lemon/insertion_tsp.h | 375 +++++++++++++++++++++++++++++++++++++++++++
lemon/nearest_neighbor_tsp.h | 145 ++++++++++++++++
lemon/opt2_tsp.h | 203 +++++++++++++++++++++++
6 files changed, 1033 insertions(+), 0 deletions(-)
diffs (truncated from 1088 to 300 lines):
diff --git a/lemon/Makefile.am b/lemon/Makefile.am
--- a/lemon/Makefile.am
+++ b/lemon/Makefile.am
@@ -64,6 +64,7 @@
lemon/bucket_heap.h \
lemon/capacity_scaling.h \
lemon/cbc.h \
+ lemon/christofides_tsp.h \
lemon/circulation.h \
lemon/clp.h \
lemon/color.h \
@@ -89,11 +90,13 @@
lemon/glpk.h \
lemon/gomory_hu.h \
lemon/graph_to_eps.h \
+ lemon/greedy_tsp.h \
lemon/grid_graph.h \
lemon/grosso_locatelli_pullan_mc.h \
lemon/hartmann_orlin_mmc.h \
lemon/howard_mmc.h \
lemon/hypercube_graph.h \
+ lemon/insertion_tsp.h \
lemon/karp_mmc.h \
lemon/kruskal.h \
lemon/hao_orlin.h \
@@ -110,7 +113,9 @@
lemon/max_cardinality_search.h \
lemon/nagamochi_ibaraki.h \
lemon/nauty_reader.h \
+ lemon/nearest_neighbor_tsp.h \
lemon/network_simplex.h \
+ lemon/opt2_tsp.h \
lemon/pairing_heap.h \
lemon/path.h \
lemon/planarity.h \
diff --git a/lemon/christofides_tsp.h b/lemon/christofides_tsp.h
new file mode 100644
--- /dev/null
+++ b/lemon/christofides_tsp.h
@@ -0,0 +1,129 @@
+#ifndef LEMON_CHRISTOFIDES_TSP_H
+#define LEMON_CHRISTOFIDES_TSP_H
+
+#include <lemon/full_graph.h>
+#include <lemon/smart_graph.h>
+#include <lemon/path.h>
+#include <lemon/kruskal.h>
+#include <lemon/matching.h>
+#include <lemon/adaptors.h>
+#include <lemon/maps.h>
+#include <lemon/euler.h>
+
+namespace lemon {
+
+ namespace christofides_helper {
+ template <class L>
+ L vectorConvert(const std::vector<FullGraph::Node> &_path) {
+ return L(_path.begin(), _path.end());
+ }
+
+ template <>
+ std::vector<FullGraph::Node> vectorConvert(const std::vector<FullGraph::Node> &_path) {
+ return _path;
+ }
+ }
+
+ template <typename CM>
+ class ChristofidesTsp {
+ private:
+ GRAPH_TYPEDEFS(SmartGraph);
+
+ public:
+ typedef typename CM::Value Cost;
+ typedef SmartGraph::EdgeMap<Cost> CostMap;
+
+ ChristofidesTsp(const FullGraph &gr, const CM &cost) : _cost(_gr), fullg(gr), fullcost(cost), nr(_gr) {
+ graphCopy(gr, _gr).nodeCrossRef(nr).edgeMap(cost, _cost).run();
+ }
+
+ Cost run() {
+ _path.clear();
+
+ SmartGraph::EdgeMap<bool> tree(_gr);
+ kruskal(_gr, _cost, tree);
+
+ FilterEdges<SmartGraph> treefiltered(_gr, tree);
+ InDegMap<FilterEdges<SmartGraph> > deg(treefiltered);
+
+ SmartGraph::NodeMap<bool> oddfilter(_gr, false);
+ FilterNodes<SmartGraph> oddNodes(_gr, oddfilter);
+
+ for (NodeIt n(_gr); n!=INVALID; ++n) {
+ if (deg[n]%2 == 1) {
+ oddNodes.enable(n);
+ }
+ }
+
+ NegMap<CostMap> negmap(_cost);
+ MaxWeightedPerfectMatching<FilterNodes<SmartGraph>,
+ NegMap<CostMap> > perfmatch(oddNodes, negmap);
+ perfmatch.run();
+
+ for (FilterNodes<SmartGraph>::EdgeIt e(oddNodes); e!=INVALID; ++e) {
+ if (perfmatch.matching(e)) {
+ treefiltered.enable(_gr.addEdge(_gr.u(e), _gr.v(e)));
+ }
+ }
+
+ FilterEdges<SmartGraph>::NodeMap<bool> seen(treefiltered, false);
+ for (EulerIt<FilterEdges<SmartGraph> > e(treefiltered); e!=INVALID; ++e) {
+ if (seen[treefiltered.target(e)]==false) {
+ _path.push_back(nr[treefiltered.target(e)]);
+ seen[treefiltered.target(e)] = true;
+ }
+ }
+
+ _sum = fullcost[ fullg.edge(_path.back(), _path.front()) ];
+ for (unsigned int i=0; i<_path.size()-1; ++i)
+ _sum += fullcost[ fullg.edge(_path[i], _path[i+1]) ];
+
+ return _sum;
+ }
+
+ template <typename L>
+ void tourNodes(L &container) {
+ container(christofides_helper::vectorConvert<L>(_path));
+ }
+
+ template <template <typename> class L>
+ L<FullGraph::Node> tourNodes() {
+ return christofides_helper::vectorConvert<L<FullGraph::Node> >(_path);
+ }
+
+ const std::vector<Node>& tourNodes() {
+ return _path;
+ }
+
+ Path<FullGraph> tour() {
+ Path<FullGraph> p;
+ if (_path.size()<2)
+ return p;
+
+ for (unsigned int i=0; i<_path.size()-1; ++i) {
+ p.addBack(fullg.arc(_path[i], _path[i+1]));
+ }
+ p.addBack(fullg.arc(_path.back(), _path.front()));
+
+ return p;
+ }
+
+ Cost tourCost() {
+ return _sum;
+ }
+
+
+ private:
+ SmartGraph _gr;
+ CostMap _cost;
+ Cost _sum;
+ const FullGraph &fullg;
+ const CM &fullcost;
+ std::vector<FullGraph::Node> _path;
+ SmartGraph::NodeMap<FullGraph::Node> nr;
+ };
+
+
+}; // namespace lemon
+
+#endif
diff --git a/lemon/greedy_tsp.h b/lemon/greedy_tsp.h
new file mode 100644
--- /dev/null
+++ b/lemon/greedy_tsp.h
@@ -0,0 +1,176 @@
+#ifndef LEMON_GREEDY_TSP_H
+#define LEMON_GREEDY_TSP_H
+
+#include <lemon/path.h>
+#include <lemon/full_graph.h>
+#include <lemon/unionfind.h>
+#include <algorithm>
+
+namespace lemon {
+
+ namespace greedy_tsp_helper {
+
+ template <typename CostMap>
+ class KeyComp {
+ typedef typename CostMap::Key Key;
+ const CostMap &cost;
+
+ public:
+ KeyComp(const CostMap &_cost) : cost(_cost) {}
+
+ bool operator() (const Key &a, const Key &b) const {
+ return cost[a] < cost[b];
+ }
+ };
+
+
+ template <class L>
+ L vectorConvert(const std::vector<FullGraph::Node> &_path) {
+ return L(_path.begin(), _path.end());
+ }
+
+ template <>
+ std::vector<FullGraph::Node> vectorConvert(const std::vector<FullGraph::Node> &_path) {
+ return _path;
+ }
+
+ }
+
+
+ template <typename CM>
+ class GreedyTsp {
+ private:
+ GRAPH_TYPEDEFS(FullGraph);
+
+ public:
+ typedef CM CostMap;
+ typedef typename CM::Value Cost;
+
+ GreedyTsp(const FullGraph &gr, const CostMap &cost) : _gr(gr), _cost(cost) {}
+
+ Cost run() {
+ typedef UnionFind<FullGraph::NodeMap<int> > Union;
+ _nodes.clear();
+
+ std::vector<int> path;
+ path.resize(_gr.nodeNum()*2, -1);
+
+ std::vector<typename CostMap::Key> sorted_edges;
+ sorted_edges.reserve(_gr.edgeNum());
+ for (EdgeIt n(_gr); n != INVALID; ++n)
+ sorted_edges.push_back(n);
+
+ std::sort(sorted_edges.begin(), sorted_edges.end(), greedy_tsp_helper::KeyComp<CostMap>(_cost));
+
+ FullGraph::NodeMap<int> nodemap(_gr);
+ Union unionfind(nodemap);
+
+ for (NodeIt n(_gr); n != INVALID; ++n)
+ unionfind.insert(n);
+
+ FullGraph::NodeMap<int> degree(_gr, 0);
+
+ int nodesNum = 0, i = 0;
+
+ while ( nodesNum != _gr.nodeNum()-1 ) {
+ const Edge &e = sorted_edges[i];
+
+ const Node u = _gr.u(e),
+ v = _gr.v(e);
+
+ if (degree[u]<=1 && degree[v]<=1) {
+ if (unionfind.join(u, v)) {
+ ++degree[u];
+ ++degree[v];
+ ++nodesNum;
+
+ const int uid = _gr.id(u),
+ vid = _gr.id(v);
+
+
+ path[uid*2 + (path[uid*2]==-1 ? 0 : 1)] = vid;
+ path[vid*2 + (path[vid*2]==-1 ? 0 : 1)] = uid;
+ }
+ }
+
+ ++i;
+ }
+
+
+ for (int i=0, n=-1; i<_gr.nodeNum()*2; ++i) {
+ if (path[i] == -1) {
+ if (n==-1) {
+ n = i;
+ } else {
+ path[n] = i/2;
+ path[i] = n/2;
+ break;
+ }
+ }
+ }
+
+
+ for (int i=0, j=0, last=-1; i!=_gr.nodeNum(); ++i) {
+ _nodes.push_back(_gr.nodeFromId(j));
+
+ if (path[2*j] != last) {
+ last = j;
+ j = path[2*j];
+ } else {
+ last = j;
+ j = path[2*j+1];
+ }
+ }
+
+ _sum = _cost[_gr.edge(_nodes.back(), _nodes.front())];
+ for (unsigned int i=0; i<_nodes.size()-1; ++i)
More information about the Lemon-commits
mailing list