# HG changeset patch # User Gabor Varga # Date 1294520396 -3600 # Node ID ae0b056593a78cd4c06c43c14ae81abb2e3f4bb2 # Parent 4980b05606bdffb4ca3c522a9449dd5b1f5310d4 Heuristic algorithms for symmetric TSP (#386) diff -r 4980b05606bd -r ae0b056593a7 lemon/Makefile.am --- a/lemon/Makefile.am Tue Nov 16 07:46:01 2010 +0100 +++ b/lemon/Makefile.am Sat Jan 08 21:59:56 2011 +0100 @@ -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 -r 4980b05606bd -r ae0b056593a7 lemon/christofides_tsp.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/christofides_tsp.h Sat Jan 08 21:59:56 2011 +0100 @@ -0,0 +1,129 @@ +#ifndef LEMON_CHRISTOFIDES_TSP_H +#define LEMON_CHRISTOFIDES_TSP_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace lemon { + + namespace christofides_helper { + template + L vectorConvert(const std::vector &_path) { + return L(_path.begin(), _path.end()); + } + + template <> + std::vector vectorConvert(const std::vector &_path) { + return _path; + } + } + + template + class ChristofidesTsp { + private: + GRAPH_TYPEDEFS(SmartGraph); + + public: + typedef typename CM::Value Cost; + typedef SmartGraph::EdgeMap 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 tree(_gr); + kruskal(_gr, _cost, tree); + + FilterEdges treefiltered(_gr, tree); + InDegMap > deg(treefiltered); + + SmartGraph::NodeMap oddfilter(_gr, false); + FilterNodes oddNodes(_gr, oddfilter); + + for (NodeIt n(_gr); n!=INVALID; ++n) { + if (deg[n]%2 == 1) { + oddNodes.enable(n); + } + } + + NegMap negmap(_cost); + MaxWeightedPerfectMatching, + NegMap > perfmatch(oddNodes, negmap); + perfmatch.run(); + + for (FilterNodes::EdgeIt e(oddNodes); e!=INVALID; ++e) { + if (perfmatch.matching(e)) { + treefiltered.enable(_gr.addEdge(_gr.u(e), _gr.v(e))); + } + } + + FilterEdges::NodeMap seen(treefiltered, false); + for (EulerIt > 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 + void tourNodes(L &container) { + container(christofides_helper::vectorConvert(_path)); + } + + template