1 #ifndef LEMON_CHRISTOFIDES_TSP_H
2 #define LEMON_CHRISTOFIDES_TSP_H
4 #include <lemon/full_graph.h>
5 #include <lemon/smart_graph.h>
6 #include <lemon/path.h>
7 #include <lemon/kruskal.h>
8 #include <lemon/matching.h>
9 #include <lemon/adaptors.h>
10 #include <lemon/maps.h>
11 #include <lemon/euler.h>
15 namespace christofides_helper {
17 L vectorConvert(const std::vector<FullGraph::Node> &_path) {
18 return L(_path.begin(), _path.end());
22 std::vector<FullGraph::Node> vectorConvert(const std::vector<FullGraph::Node> &_path) {
27 template <typename CM>
28 class ChristofidesTsp {
30 GRAPH_TYPEDEFS(SmartGraph);
33 typedef typename CM::Value Cost;
34 typedef SmartGraph::EdgeMap<Cost> CostMap;
36 ChristofidesTsp(const FullGraph &gr, const CM &cost) : _cost(_gr), fullg(gr), fullcost(cost), nr(_gr) {
37 graphCopy(gr, _gr).nodeCrossRef(nr).edgeMap(cost, _cost).run();
43 SmartGraph::EdgeMap<bool> tree(_gr);
44 kruskal(_gr, _cost, tree);
46 FilterEdges<SmartGraph> treefiltered(_gr, tree);
47 InDegMap<FilterEdges<SmartGraph> > deg(treefiltered);
49 SmartGraph::NodeMap<bool> oddfilter(_gr, false);
50 FilterNodes<SmartGraph> oddNodes(_gr, oddfilter);
52 for (NodeIt n(_gr); n!=INVALID; ++n) {
58 NegMap<CostMap> negmap(_cost);
59 MaxWeightedPerfectMatching<FilterNodes<SmartGraph>,
60 NegMap<CostMap> > perfmatch(oddNodes, negmap);
63 for (FilterNodes<SmartGraph>::EdgeIt e(oddNodes); e!=INVALID; ++e) {
64 if (perfmatch.matching(e)) {
65 treefiltered.enable(_gr.addEdge(_gr.u(e), _gr.v(e)));
69 FilterEdges<SmartGraph>::NodeMap<bool> seen(treefiltered, false);
70 for (EulerIt<FilterEdges<SmartGraph> > e(treefiltered); e!=INVALID; ++e) {
71 if (seen[treefiltered.target(e)]==false) {
72 _path.push_back(nr[treefiltered.target(e)]);
73 seen[treefiltered.target(e)] = true;
77 _sum = fullcost[ fullg.edge(_path.back(), _path.front()) ];
78 for (unsigned int i=0; i<_path.size()-1; ++i)
79 _sum += fullcost[ fullg.edge(_path[i], _path[i+1]) ];
85 void tourNodes(L &container) {
86 container(christofides_helper::vectorConvert<L>(_path));
89 template <template <typename> class L>
90 L<FullGraph::Node> tourNodes() {
91 return christofides_helper::vectorConvert<L<FullGraph::Node> >(_path);
94 const std::vector<Node>& tourNodes() {
98 Path<FullGraph> tour() {
103 for (unsigned int i=0; i<_path.size()-1; ++i) {
104 p.addBack(fullg.arc(_path[i], _path[i+1]));
106 p.addBack(fullg.arc(_path.back(), _path.front()));
120 const FullGraph &fullg;
122 std::vector<FullGraph::Node> _path;
123 SmartGraph::NodeMap<FullGraph::Node> nr;
127 }; // namespace lemon