f4c3@1031
|
1 |
#ifndef LEMON_CHRISTOFIDES_TSP_H
|
f4c3@1031
|
2 |
#define LEMON_CHRISTOFIDES_TSP_H
|
f4c3@1031
|
3 |
|
f4c3@1031
|
4 |
#include <lemon/full_graph.h>
|
f4c3@1031
|
5 |
#include <lemon/smart_graph.h>
|
f4c3@1031
|
6 |
#include <lemon/path.h>
|
f4c3@1031
|
7 |
#include <lemon/kruskal.h>
|
f4c3@1031
|
8 |
#include <lemon/matching.h>
|
f4c3@1031
|
9 |
#include <lemon/adaptors.h>
|
f4c3@1031
|
10 |
#include <lemon/maps.h>
|
f4c3@1031
|
11 |
#include <lemon/euler.h>
|
f4c3@1031
|
12 |
|
f4c3@1031
|
13 |
namespace lemon {
|
f4c3@1031
|
14 |
|
f4c3@1031
|
15 |
namespace christofides_helper {
|
f4c3@1031
|
16 |
template <class L>
|
f4c3@1031
|
17 |
L vectorConvert(const std::vector<FullGraph::Node> &_path) {
|
f4c3@1031
|
18 |
return L(_path.begin(), _path.end());
|
f4c3@1031
|
19 |
}
|
f4c3@1031
|
20 |
|
f4c3@1031
|
21 |
template <>
|
f4c3@1031
|
22 |
std::vector<FullGraph::Node> vectorConvert(const std::vector<FullGraph::Node> &_path) {
|
f4c3@1031
|
23 |
return _path;
|
f4c3@1031
|
24 |
}
|
f4c3@1031
|
25 |
}
|
f4c3@1031
|
26 |
|
f4c3@1031
|
27 |
template <typename CM>
|
f4c3@1031
|
28 |
class ChristofidesTsp {
|
f4c3@1031
|
29 |
private:
|
f4c3@1031
|
30 |
GRAPH_TYPEDEFS(SmartGraph);
|
f4c3@1031
|
31 |
|
f4c3@1031
|
32 |
public:
|
f4c3@1031
|
33 |
typedef typename CM::Value Cost;
|
f4c3@1031
|
34 |
typedef SmartGraph::EdgeMap<Cost> CostMap;
|
f4c3@1031
|
35 |
|
f4c3@1031
|
36 |
ChristofidesTsp(const FullGraph &gr, const CM &cost) : _cost(_gr), fullg(gr), fullcost(cost), nr(_gr) {
|
f4c3@1031
|
37 |
graphCopy(gr, _gr).nodeCrossRef(nr).edgeMap(cost, _cost).run();
|
f4c3@1031
|
38 |
}
|
f4c3@1031
|
39 |
|
f4c3@1031
|
40 |
Cost run() {
|
f4c3@1031
|
41 |
_path.clear();
|
f4c3@1031
|
42 |
|
f4c3@1031
|
43 |
SmartGraph::EdgeMap<bool> tree(_gr);
|
f4c3@1031
|
44 |
kruskal(_gr, _cost, tree);
|
f4c3@1031
|
45 |
|
f4c3@1031
|
46 |
FilterEdges<SmartGraph> treefiltered(_gr, tree);
|
f4c3@1031
|
47 |
InDegMap<FilterEdges<SmartGraph> > deg(treefiltered);
|
f4c3@1031
|
48 |
|
f4c3@1031
|
49 |
SmartGraph::NodeMap<bool> oddfilter(_gr, false);
|
f4c3@1031
|
50 |
FilterNodes<SmartGraph> oddNodes(_gr, oddfilter);
|
f4c3@1031
|
51 |
|
f4c3@1031
|
52 |
for (NodeIt n(_gr); n!=INVALID; ++n) {
|
f4c3@1031
|
53 |
if (deg[n]%2 == 1) {
|
f4c3@1031
|
54 |
oddNodes.enable(n);
|
f4c3@1031
|
55 |
}
|
f4c3@1031
|
56 |
}
|
f4c3@1031
|
57 |
|
f4c3@1031
|
58 |
NegMap<CostMap> negmap(_cost);
|
f4c3@1031
|
59 |
MaxWeightedPerfectMatching<FilterNodes<SmartGraph>,
|
f4c3@1031
|
60 |
NegMap<CostMap> > perfmatch(oddNodes, negmap);
|
f4c3@1031
|
61 |
perfmatch.run();
|
f4c3@1031
|
62 |
|
f4c3@1031
|
63 |
for (FilterNodes<SmartGraph>::EdgeIt e(oddNodes); e!=INVALID; ++e) {
|
f4c3@1031
|
64 |
if (perfmatch.matching(e)) {
|
f4c3@1031
|
65 |
treefiltered.enable(_gr.addEdge(_gr.u(e), _gr.v(e)));
|
f4c3@1031
|
66 |
}
|
f4c3@1031
|
67 |
}
|
f4c3@1031
|
68 |
|
f4c3@1031
|
69 |
FilterEdges<SmartGraph>::NodeMap<bool> seen(treefiltered, false);
|
f4c3@1031
|
70 |
for (EulerIt<FilterEdges<SmartGraph> > e(treefiltered); e!=INVALID; ++e) {
|
f4c3@1031
|
71 |
if (seen[treefiltered.target(e)]==false) {
|
f4c3@1031
|
72 |
_path.push_back(nr[treefiltered.target(e)]);
|
f4c3@1031
|
73 |
seen[treefiltered.target(e)] = true;
|
f4c3@1031
|
74 |
}
|
f4c3@1031
|
75 |
}
|
f4c3@1031
|
76 |
|
f4c3@1031
|
77 |
_sum = fullcost[ fullg.edge(_path.back(), _path.front()) ];
|
f4c3@1031
|
78 |
for (unsigned int i=0; i<_path.size()-1; ++i)
|
f4c3@1031
|
79 |
_sum += fullcost[ fullg.edge(_path[i], _path[i+1]) ];
|
f4c3@1031
|
80 |
|
f4c3@1031
|
81 |
return _sum;
|
f4c3@1031
|
82 |
}
|
f4c3@1031
|
83 |
|
f4c3@1031
|
84 |
template <typename L>
|
f4c3@1031
|
85 |
void tourNodes(L &container) {
|
f4c3@1031
|
86 |
container(christofides_helper::vectorConvert<L>(_path));
|
f4c3@1031
|
87 |
}
|
f4c3@1031
|
88 |
|
f4c3@1031
|
89 |
template <template <typename> class L>
|
f4c3@1031
|
90 |
L<FullGraph::Node> tourNodes() {
|
f4c3@1031
|
91 |
return christofides_helper::vectorConvert<L<FullGraph::Node> >(_path);
|
f4c3@1031
|
92 |
}
|
f4c3@1031
|
93 |
|
f4c3@1031
|
94 |
const std::vector<Node>& tourNodes() {
|
f4c3@1031
|
95 |
return _path;
|
f4c3@1031
|
96 |
}
|
f4c3@1031
|
97 |
|
f4c3@1031
|
98 |
Path<FullGraph> tour() {
|
f4c3@1031
|
99 |
Path<FullGraph> p;
|
f4c3@1031
|
100 |
if (_path.size()<2)
|
f4c3@1031
|
101 |
return p;
|
f4c3@1031
|
102 |
|
f4c3@1031
|
103 |
for (unsigned int i=0; i<_path.size()-1; ++i) {
|
f4c3@1031
|
104 |
p.addBack(fullg.arc(_path[i], _path[i+1]));
|
f4c3@1031
|
105 |
}
|
f4c3@1031
|
106 |
p.addBack(fullg.arc(_path.back(), _path.front()));
|
f4c3@1031
|
107 |
|
f4c3@1031
|
108 |
return p;
|
f4c3@1031
|
109 |
}
|
f4c3@1031
|
110 |
|
f4c3@1031
|
111 |
Cost tourCost() {
|
f4c3@1031
|
112 |
return _sum;
|
f4c3@1031
|
113 |
}
|
f4c3@1031
|
114 |
|
f4c3@1031
|
115 |
|
f4c3@1031
|
116 |
private:
|
f4c3@1031
|
117 |
SmartGraph _gr;
|
f4c3@1031
|
118 |
CostMap _cost;
|
f4c3@1031
|
119 |
Cost _sum;
|
f4c3@1031
|
120 |
const FullGraph &fullg;
|
f4c3@1031
|
121 |
const CM &fullcost;
|
f4c3@1031
|
122 |
std::vector<FullGraph::Node> _path;
|
f4c3@1031
|
123 |
SmartGraph::NodeMap<FullGraph::Node> nr;
|
f4c3@1031
|
124 |
};
|
f4c3@1031
|
125 |
|
f4c3@1031
|
126 |
|
f4c3@1031
|
127 |
}; // namespace lemon
|
f4c3@1031
|
128 |
|
f4c3@1031
|
129 |
#endif
|