f4c3@1031
|
1 |
#ifndef LEMON_OPT2_TSP_H
|
f4c3@1031
|
2 |
#define LEMON_OPT2_TSP_H
|
f4c3@1031
|
3 |
|
f4c3@1031
|
4 |
#include <vector>
|
f4c3@1031
|
5 |
#include <lemon/full_graph.h>
|
f4c3@1031
|
6 |
#include <lemon/path.h>
|
f4c3@1031
|
7 |
|
f4c3@1031
|
8 |
namespace lemon {
|
f4c3@1031
|
9 |
|
f4c3@1031
|
10 |
namespace opt2_helper {
|
f4c3@1031
|
11 |
template <class L>
|
f4c3@1031
|
12 |
L vectorConvert(const std::vector<FullGraph::Node> &_path) {
|
f4c3@1031
|
13 |
return L(_path.begin(), _path.end());
|
f4c3@1031
|
14 |
}
|
f4c3@1031
|
15 |
|
f4c3@1031
|
16 |
template <>
|
f4c3@1031
|
17 |
std::vector<FullGraph::Node> vectorConvert(const std::vector<FullGraph::Node> &_path) {
|
f4c3@1031
|
18 |
return _path;
|
f4c3@1031
|
19 |
}
|
f4c3@1031
|
20 |
}
|
f4c3@1031
|
21 |
|
f4c3@1031
|
22 |
template <typename CM>
|
f4c3@1031
|
23 |
class Opt2Tsp {
|
f4c3@1031
|
24 |
private:
|
f4c3@1031
|
25 |
GRAPH_TYPEDEFS(FullGraph);
|
f4c3@1031
|
26 |
|
f4c3@1031
|
27 |
public:
|
f4c3@1031
|
28 |
typedef CM CostMap;
|
f4c3@1031
|
29 |
typedef typename CM::Value Cost;
|
f4c3@1031
|
30 |
|
f4c3@1031
|
31 |
|
f4c3@1031
|
32 |
Opt2Tsp(const FullGraph &gr, const CostMap &cost) : _gr(gr), _cost(cost),
|
f4c3@1031
|
33 |
tmppath(_gr.nodeNum()*2) {
|
f4c3@1031
|
34 |
|
f4c3@1031
|
35 |
for (int i=1; i<_gr.nodeNum()-1; ++i) {
|
f4c3@1031
|
36 |
tmppath[2*i] = i-1;
|
f4c3@1031
|
37 |
tmppath[2*i+1] = i+1;
|
f4c3@1031
|
38 |
}
|
f4c3@1031
|
39 |
tmppath[0] = _gr.nodeNum()-1;
|
f4c3@1031
|
40 |
tmppath[1] = 1;
|
f4c3@1031
|
41 |
tmppath[2*(_gr.nodeNum()-1)] = _gr.nodeNum()-2;
|
f4c3@1031
|
42 |
tmppath[2*(_gr.nodeNum()-1)+1] = 0;
|
f4c3@1031
|
43 |
}
|
f4c3@1031
|
44 |
|
f4c3@1031
|
45 |
Opt2Tsp(const FullGraph &gr, const CostMap &cost, const std::vector<Node> &path) :
|
f4c3@1031
|
46 |
_gr(gr), _cost(cost), tmppath(_gr.nodeNum()*2) {
|
f4c3@1031
|
47 |
|
f4c3@1031
|
48 |
for (unsigned int i=1; i<path.size()-1; ++i) {
|
f4c3@1031
|
49 |
tmppath[2*_gr.id(path[i])] = _gr.id(path[i-1]);
|
f4c3@1031
|
50 |
tmppath[2*_gr.id(path[i])+1] = _gr.id(path[i+1]);
|
f4c3@1031
|
51 |
}
|
f4c3@1031
|
52 |
|
f4c3@1031
|
53 |
tmppath[2*_gr.id(path[0])] = _gr.id(path.back());
|
f4c3@1031
|
54 |
tmppath[2*_gr.id(path[0])+1] = _gr.id(path[1]);
|
f4c3@1031
|
55 |
tmppath[2*_gr.id(path.back())] = _gr.id(path[path.size()-2]);
|
f4c3@1031
|
56 |
tmppath[2*_gr.id(path.back())+1] = _gr.id(path.front());
|
f4c3@1031
|
57 |
}
|
f4c3@1031
|
58 |
|
f4c3@1031
|
59 |
private:
|
f4c3@1031
|
60 |
Cost c(int u, int v) {
|
f4c3@1031
|
61 |
return _cost[_gr.edge(_gr.nodeFromId(u), _gr.nodeFromId(v))];
|
f4c3@1031
|
62 |
}
|
f4c3@1031
|
63 |
|
f4c3@1031
|
64 |
class It {
|
f4c3@1031
|
65 |
public:
|
f4c3@1031
|
66 |
It(const std::vector<int> &path, int i=0) : tmppath(path), act(i), last(tmppath[2*act]) {}
|
f4c3@1031
|
67 |
It(const std::vector<int> &path, int i, int l) : tmppath(path), act(i), last(l) {}
|
f4c3@1031
|
68 |
|
f4c3@1031
|
69 |
int next_index() const {
|
f4c3@1031
|
70 |
return (tmppath[2*act]==last)? 2*act+1 : 2*act;
|
f4c3@1031
|
71 |
}
|
f4c3@1031
|
72 |
|
f4c3@1031
|
73 |
int prev_index() const {
|
f4c3@1031
|
74 |
return (tmppath[2*act]==last)? 2*act : 2*act+1;
|
f4c3@1031
|
75 |
}
|
f4c3@1031
|
76 |
|
f4c3@1031
|
77 |
int next() const {
|
f4c3@1031
|
78 |
return tmppath[next_index()];
|
f4c3@1031
|
79 |
}
|
f4c3@1031
|
80 |
|
f4c3@1031
|
81 |
int prev() const {
|
f4c3@1031
|
82 |
return tmppath[prev_index()];
|
f4c3@1031
|
83 |
}
|
f4c3@1031
|
84 |
|
f4c3@1031
|
85 |
It& operator++() {
|
f4c3@1031
|
86 |
int tmp = act;
|
f4c3@1031
|
87 |
act = next();
|
f4c3@1031
|
88 |
last = tmp;
|
f4c3@1031
|
89 |
return *this;
|
f4c3@1031
|
90 |
}
|
f4c3@1031
|
91 |
|
f4c3@1031
|
92 |
operator int() const {
|
f4c3@1031
|
93 |
return act;
|
f4c3@1031
|
94 |
}
|
f4c3@1031
|
95 |
|
f4c3@1031
|
96 |
private:
|
f4c3@1031
|
97 |
const std::vector<int> &tmppath;
|
f4c3@1031
|
98 |
int act;
|
f4c3@1031
|
99 |
int last;
|
f4c3@1031
|
100 |
};
|
f4c3@1031
|
101 |
|
f4c3@1031
|
102 |
bool check(std::vector<int> &path, It i, It j) {
|
f4c3@1031
|
103 |
if (c(i, i.next()) + c(j, j.next()) >
|
f4c3@1031
|
104 |
c(i, j) + c(j.next(), i.next())) {
|
f4c3@1031
|
105 |
|
f4c3@1031
|
106 |
path[ It(path, i.next(), i).prev_index() ] = j.next();
|
f4c3@1031
|
107 |
path[ It(path, j.next(), j).prev_index() ] = i.next();
|
f4c3@1031
|
108 |
|
f4c3@1031
|
109 |
path[i.next_index()] = j;
|
f4c3@1031
|
110 |
path[j.next_index()] = i;
|
f4c3@1031
|
111 |
|
f4c3@1031
|
112 |
return true;
|
f4c3@1031
|
113 |
}
|
f4c3@1031
|
114 |
return false;
|
f4c3@1031
|
115 |
}
|
f4c3@1031
|
116 |
|
f4c3@1031
|
117 |
public:
|
f4c3@1031
|
118 |
|
f4c3@1031
|
119 |
Cost run() {
|
f4c3@1031
|
120 |
_path.clear();
|
f4c3@1031
|
121 |
|
f4c3@1031
|
122 |
if (_gr.nodeNum()>3) {
|
f4c3@1031
|
123 |
|
f4c3@1031
|
124 |
opt2_tsp_label:
|
f4c3@1031
|
125 |
It i(tmppath);
|
f4c3@1031
|
126 |
It j(tmppath, i, i.prev());
|
f4c3@1031
|
127 |
++j; ++j;
|
f4c3@1031
|
128 |
for (; j.next()!=0; ++j) {
|
f4c3@1031
|
129 |
if (check(tmppath, i, j))
|
f4c3@1031
|
130 |
goto opt2_tsp_label;
|
f4c3@1031
|
131 |
}
|
f4c3@1031
|
132 |
|
f4c3@1031
|
133 |
for (++i; i.next()!=0; ++i) {
|
f4c3@1031
|
134 |
It j(tmppath, i, i.prev());
|
f4c3@1031
|
135 |
if (++j==0)
|
f4c3@1031
|
136 |
break;
|
f4c3@1031
|
137 |
if (++j==0)
|
f4c3@1031
|
138 |
break;
|
f4c3@1031
|
139 |
|
f4c3@1031
|
140 |
for (; j!=0; ++j) {
|
f4c3@1031
|
141 |
if (check(tmppath, i, j))
|
f4c3@1031
|
142 |
goto opt2_tsp_label;
|
f4c3@1031
|
143 |
}
|
f4c3@1031
|
144 |
}
|
f4c3@1031
|
145 |
}
|
f4c3@1031
|
146 |
|
f4c3@1031
|
147 |
It k(tmppath);
|
f4c3@1031
|
148 |
_path.push_back(_gr.nodeFromId(k));
|
f4c3@1031
|
149 |
for (++k; k!=0; ++k)
|
f4c3@1031
|
150 |
_path.push_back(_gr.nodeFromId(k));
|
f4c3@1031
|
151 |
|
f4c3@1031
|
152 |
|
f4c3@1031
|
153 |
|
f4c3@1031
|
154 |
_sum = _cost[ _gr.edge(_path.back(), _path.front()) ];
|
f4c3@1031
|
155 |
for (unsigned int i=0; i<_path.size()-1; ++i)
|
f4c3@1031
|
156 |
_sum += _cost[ _gr.edge(_path[i], _path[i+1]) ];
|
f4c3@1031
|
157 |
return _sum;
|
f4c3@1031
|
158 |
}
|
f4c3@1031
|
159 |
|
f4c3@1031
|
160 |
|
f4c3@1031
|
161 |
template <typename L>
|
f4c3@1031
|
162 |
void tourNodes(L &container) {
|
f4c3@1031
|
163 |
container(opt2_helper::vectorConvert<L>(_path));
|
f4c3@1031
|
164 |
}
|
f4c3@1031
|
165 |
|
f4c3@1031
|
166 |
template <template <typename> class L>
|
f4c3@1031
|
167 |
L<Node> tourNodes() {
|
f4c3@1031
|
168 |
return opt2_helper::vectorConvert<L<Node> >(_path);
|
f4c3@1031
|
169 |
}
|
f4c3@1031
|
170 |
|
f4c3@1031
|
171 |
const std::vector<Node>& tourNodes() {
|
f4c3@1031
|
172 |
return _path;
|
f4c3@1031
|
173 |
}
|
f4c3@1031
|
174 |
|
f4c3@1031
|
175 |
Path<FullGraph> tour() {
|
f4c3@1031
|
176 |
Path<FullGraph> p;
|
f4c3@1031
|
177 |
if (_path.size()<2)
|
f4c3@1031
|
178 |
return p;
|
f4c3@1031
|
179 |
|
f4c3@1031
|
180 |
for (unsigned int i=0; i<_path.size()-1; ++i) {
|
f4c3@1031
|
181 |
p.addBack(_gr.arc(_path[i], _path[i+1]));
|
f4c3@1031
|
182 |
}
|
f4c3@1031
|
183 |
p.addBack(_gr.arc(_path.back(), _path.front()));
|
f4c3@1031
|
184 |
return p;
|
f4c3@1031
|
185 |
}
|
f4c3@1031
|
186 |
|
f4c3@1031
|
187 |
Cost tourCost() {
|
f4c3@1031
|
188 |
return _sum;
|
f4c3@1031
|
189 |
}
|
f4c3@1031
|
190 |
|
f4c3@1031
|
191 |
|
f4c3@1031
|
192 |
private:
|
f4c3@1031
|
193 |
const FullGraph &_gr;
|
f4c3@1031
|
194 |
const CostMap &_cost;
|
f4c3@1031
|
195 |
Cost _sum;
|
f4c3@1031
|
196 |
std::vector<int> tmppath;
|
f4c3@1031
|
197 |
std::vector<Node> _path;
|
f4c3@1031
|
198 |
};
|
f4c3@1031
|
199 |
|
f4c3@1031
|
200 |
|
f4c3@1031
|
201 |
}; // namespace lemon
|
f4c3@1031
|
202 |
|
f4c3@1031
|
203 |
#endif
|