f4c3@1031
|
1 |
#ifndef LEMON_INSERTION_TSP_H
|
f4c3@1031
|
2 |
#define LEMON_INSERTION_TSP_H
|
f4c3@1031
|
3 |
|
f4c3@1031
|
4 |
#include <lemon/full_graph.h>
|
f4c3@1031
|
5 |
#include <lemon/path.h>
|
f4c3@1031
|
6 |
#include <lemon/maps.h>
|
f4c3@1031
|
7 |
#include <lemon/random.h>
|
f4c3@1031
|
8 |
#include <vector>
|
f4c3@1031
|
9 |
|
f4c3@1031
|
10 |
namespace lemon {
|
f4c3@1031
|
11 |
|
f4c3@1031
|
12 |
namespace insertion_tsp_helper {
|
f4c3@1031
|
13 |
|
f4c3@1031
|
14 |
template <class L>
|
f4c3@1031
|
15 |
L vectorConvert(const std::vector<FullGraph::Node> &_path) {
|
f4c3@1031
|
16 |
return L(_path.begin(), _path.end());
|
f4c3@1031
|
17 |
};
|
f4c3@1031
|
18 |
|
f4c3@1031
|
19 |
template <>
|
f4c3@1031
|
20 |
std::vector<FullGraph::Node> vectorConvert(
|
f4c3@1031
|
21 |
const std::vector<FullGraph::Node> &_path) {
|
f4c3@1031
|
22 |
return _path;
|
f4c3@1031
|
23 |
};
|
f4c3@1031
|
24 |
|
f4c3@1031
|
25 |
};
|
f4c3@1031
|
26 |
|
f4c3@1031
|
27 |
template <typename CM>
|
f4c3@1031
|
28 |
class InsertionTsp {
|
f4c3@1031
|
29 |
private:
|
f4c3@1031
|
30 |
GRAPH_TYPEDEFS(FullGraph);
|
f4c3@1031
|
31 |
|
f4c3@1031
|
32 |
public:
|
f4c3@1031
|
33 |
typedef CM CostMap;
|
f4c3@1031
|
34 |
typedef typename CM::Value Cost;
|
f4c3@1031
|
35 |
|
f4c3@1031
|
36 |
InsertionTsp(const FullGraph &gr, const CostMap &cost) :
|
f4c3@1031
|
37 |
_gr(gr), _cost(cost) {}
|
f4c3@1031
|
38 |
|
f4c3@1031
|
39 |
enum InsertionMethod {
|
f4c3@1031
|
40 |
INSERT_NEAREST,
|
f4c3@1031
|
41 |
INSERT_FARTHEST,
|
f4c3@1031
|
42 |
INSERT_CHEAPEST,
|
f4c3@1031
|
43 |
INSERT_RANDOM
|
f4c3@1031
|
44 |
};
|
f4c3@1031
|
45 |
|
f4c3@1031
|
46 |
Cost run(InsertionMethod method = INSERT_FARTHEST) {
|
f4c3@1031
|
47 |
switch (method) {
|
f4c3@1031
|
48 |
case INSERT_NEAREST:
|
f4c3@1031
|
49 |
start<InitTour<true>, NearestSelection, DefaultInsert>();
|
f4c3@1031
|
50 |
break;
|
f4c3@1031
|
51 |
case INSERT_FARTHEST:
|
f4c3@1031
|
52 |
start<InitTour<false>, FarthestSelection, DefaultInsert>();
|
f4c3@1031
|
53 |
break;
|
f4c3@1031
|
54 |
case INSERT_CHEAPEST:
|
f4c3@1031
|
55 |
start<InitTour<true>, CheapestSelection, CheapestInsert>();
|
f4c3@1031
|
56 |
break;
|
f4c3@1031
|
57 |
case INSERT_RANDOM:
|
f4c3@1031
|
58 |
start<InitTour<true>, RandomSelection, DefaultInsert>();
|
f4c3@1031
|
59 |
break;
|
f4c3@1031
|
60 |
}
|
f4c3@1031
|
61 |
return sum;
|
f4c3@1031
|
62 |
}
|
f4c3@1031
|
63 |
|
f4c3@1031
|
64 |
template <typename L>
|
f4c3@1031
|
65 |
void tourNodes(L &container) {
|
f4c3@1031
|
66 |
container(insertion_tsp_helper::vectorConvert<L>(nodesPath));
|
f4c3@1031
|
67 |
}
|
f4c3@1031
|
68 |
|
f4c3@1031
|
69 |
template <template <typename> class L>
|
f4c3@1031
|
70 |
L<Node> tourNodes() {
|
f4c3@1031
|
71 |
return insertion_tsp_helper::vectorConvert<L<Node> >(nodesPath);
|
f4c3@1031
|
72 |
}
|
f4c3@1031
|
73 |
|
f4c3@1031
|
74 |
const std::vector<Node>& tourNodes() {
|
f4c3@1031
|
75 |
return nodesPath;
|
f4c3@1031
|
76 |
}
|
f4c3@1031
|
77 |
|
f4c3@1031
|
78 |
Path<FullGraph> tour() {
|
f4c3@1031
|
79 |
Path<FullGraph> p;
|
f4c3@1031
|
80 |
if (nodesPath.size()<2)
|
f4c3@1031
|
81 |
return p;
|
f4c3@1031
|
82 |
|
f4c3@1031
|
83 |
for (unsigned int i=0; i<nodesPath.size()-1; ++i)
|
f4c3@1031
|
84 |
p.addBack(_gr.arc(nodesPath[i], nodesPath[i+1]));
|
f4c3@1031
|
85 |
|
f4c3@1031
|
86 |
p.addBack(_gr.arc(nodesPath.back(), nodesPath.front()));
|
f4c3@1031
|
87 |
return p;
|
f4c3@1031
|
88 |
}
|
f4c3@1031
|
89 |
|
f4c3@1031
|
90 |
Cost tourCost() {
|
f4c3@1031
|
91 |
return sum;
|
f4c3@1031
|
92 |
}
|
f4c3@1031
|
93 |
|
f4c3@1031
|
94 |
|
f4c3@1031
|
95 |
private:
|
f4c3@1031
|
96 |
|
f4c3@1031
|
97 |
template <bool MIN>
|
f4c3@1031
|
98 |
class InitTour {
|
f4c3@1031
|
99 |
public:
|
f4c3@1031
|
100 |
InitTour(const FullGraph &gr, const CostMap &cost,
|
f4c3@1031
|
101 |
std::vector<Node> &used, std::vector<Node> ¬used,
|
f4c3@1031
|
102 |
Cost &fullcost) :
|
f4c3@1031
|
103 |
_gr(gr), _cost(cost), _used(used), _notused(notused),
|
f4c3@1031
|
104 |
_fullcost(fullcost) {}
|
f4c3@1031
|
105 |
|
f4c3@1031
|
106 |
std::vector<Node> init() const {
|
f4c3@1031
|
107 |
Edge min = (MIN) ? mapMin(_gr, _cost) : mapMax(_gr, _cost);
|
f4c3@1031
|
108 |
std::vector<Node> path;
|
f4c3@1031
|
109 |
path.push_back(_gr.u(min));
|
f4c3@1031
|
110 |
path.push_back(_gr.v(min));
|
f4c3@1031
|
111 |
|
f4c3@1031
|
112 |
_used.clear();
|
f4c3@1031
|
113 |
_notused.clear();
|
f4c3@1031
|
114 |
for (NodeIt n(_gr); n!=INVALID; ++n) {
|
f4c3@1031
|
115 |
if (n != _gr.u(min) && n != _gr.v(min)) {
|
f4c3@1031
|
116 |
_notused.push_back(n);
|
f4c3@1031
|
117 |
}
|
f4c3@1031
|
118 |
}
|
f4c3@1031
|
119 |
_used.push_back(_gr.u(min));
|
f4c3@1031
|
120 |
_used.push_back(_gr.v(min));
|
f4c3@1031
|
121 |
|
f4c3@1031
|
122 |
_fullcost = _cost[min]*2;
|
f4c3@1031
|
123 |
return path;
|
f4c3@1031
|
124 |
}
|
f4c3@1031
|
125 |
|
f4c3@1031
|
126 |
private:
|
f4c3@1031
|
127 |
const FullGraph &_gr;
|
f4c3@1031
|
128 |
const CostMap &_cost;
|
f4c3@1031
|
129 |
std::vector<Node> &_used;
|
f4c3@1031
|
130 |
std::vector<Node> &_notused;
|
f4c3@1031
|
131 |
Cost &_fullcost;
|
f4c3@1031
|
132 |
};
|
f4c3@1031
|
133 |
|
f4c3@1031
|
134 |
class NearestSelection {
|
f4c3@1031
|
135 |
public:
|
f4c3@1031
|
136 |
NearestSelection(const FullGraph &gr, const CostMap &cost,
|
f4c3@1031
|
137 |
std::vector<Node> &used, std::vector<Node> ¬used) :
|
f4c3@1031
|
138 |
_gr(gr), _cost(cost), _used(used), _notused(notused) {}
|
f4c3@1031
|
139 |
|
f4c3@1031
|
140 |
Node select() const {
|
f4c3@1031
|
141 |
|
f4c3@1031
|
142 |
Cost insert_val =
|
f4c3@1031
|
143 |
std::numeric_limits<Cost>::max();
|
f4c3@1031
|
144 |
int insert_node = -1;
|
f4c3@1031
|
145 |
|
f4c3@1031
|
146 |
for (unsigned int i=0; i<_notused.size(); ++i) {
|
f4c3@1031
|
147 |
Cost min_val = _cost[_gr.edge(_notused[i], _used[0])];
|
f4c3@1031
|
148 |
int min_node = 0;
|
f4c3@1031
|
149 |
|
f4c3@1031
|
150 |
for (unsigned int j=1; j<_used.size(); ++j) {
|
f4c3@1031
|
151 |
if (min_val > _cost[_gr.edge(_notused[i], _used[j])]) {
|
f4c3@1031
|
152 |
min_val = _cost[_gr.edge(_notused[i], _used[j])];
|
f4c3@1031
|
153 |
min_node = j;
|
f4c3@1031
|
154 |
}
|
f4c3@1031
|
155 |
}
|
f4c3@1031
|
156 |
|
f4c3@1031
|
157 |
if (insert_val > min_val) {
|
f4c3@1031
|
158 |
insert_val = min_val;
|
f4c3@1031
|
159 |
insert_node = i;
|
f4c3@1031
|
160 |
}
|
f4c3@1031
|
161 |
}
|
f4c3@1031
|
162 |
|
f4c3@1031
|
163 |
Node n = _notused[insert_node];
|
f4c3@1031
|
164 |
_notused.erase(_notused.begin()+insert_node);
|
f4c3@1031
|
165 |
|
f4c3@1031
|
166 |
return n;
|
f4c3@1031
|
167 |
}
|
f4c3@1031
|
168 |
|
f4c3@1031
|
169 |
private:
|
f4c3@1031
|
170 |
const FullGraph &_gr;
|
f4c3@1031
|
171 |
const CostMap &_cost;
|
f4c3@1031
|
172 |
std::vector<Node> &_used;
|
f4c3@1031
|
173 |
std::vector<Node> &_notused;
|
f4c3@1031
|
174 |
};
|
f4c3@1031
|
175 |
|
f4c3@1031
|
176 |
class FarthestSelection {
|
f4c3@1031
|
177 |
public:
|
f4c3@1031
|
178 |
FarthestSelection(const FullGraph &gr, const CostMap &cost,
|
f4c3@1031
|
179 |
std::vector<Node> &used, std::vector<Node> ¬used) :
|
f4c3@1031
|
180 |
_gr(gr), _cost(cost), _used(used), _notused(notused) {}
|
f4c3@1031
|
181 |
|
f4c3@1031
|
182 |
Node select() const {
|
f4c3@1031
|
183 |
|
f4c3@1031
|
184 |
Cost insert_val =
|
f4c3@1031
|
185 |
std::numeric_limits<Cost>::min();
|
f4c3@1031
|
186 |
int insert_node = -1;
|
f4c3@1031
|
187 |
|
f4c3@1031
|
188 |
for (unsigned int i=0; i<_notused.size(); ++i) {
|
f4c3@1031
|
189 |
Cost min_val = _cost[_gr.edge(_notused[i], _used[0])];
|
f4c3@1031
|
190 |
int min_node = 0;
|
f4c3@1031
|
191 |
|
f4c3@1031
|
192 |
for (unsigned int j=1; j<_used.size(); ++j) {
|
f4c3@1031
|
193 |
if (min_val > _cost[_gr.edge(_notused[i], _used[j])]) {
|
f4c3@1031
|
194 |
min_val = _cost[_gr.edge(_notused[i], _used[j])];
|
f4c3@1031
|
195 |
min_node = j;
|
f4c3@1031
|
196 |
}
|
f4c3@1031
|
197 |
}
|
f4c3@1031
|
198 |
|
f4c3@1031
|
199 |
if (insert_val < min_val || insert_node == -1) {
|
f4c3@1031
|
200 |
insert_val = min_val;
|
f4c3@1031
|
201 |
insert_node = i;
|
f4c3@1031
|
202 |
}
|
f4c3@1031
|
203 |
}
|
f4c3@1031
|
204 |
|
f4c3@1031
|
205 |
Node n = _notused[insert_node];
|
f4c3@1031
|
206 |
_notused.erase(_notused.begin()+insert_node);
|
f4c3@1031
|
207 |
|
f4c3@1031
|
208 |
return n;
|
f4c3@1031
|
209 |
}
|
f4c3@1031
|
210 |
|
f4c3@1031
|
211 |
private:
|
f4c3@1031
|
212 |
const FullGraph &_gr;
|
f4c3@1031
|
213 |
const CostMap &_cost;
|
f4c3@1031
|
214 |
std::vector<Node> &_used;
|
f4c3@1031
|
215 |
std::vector<Node> &_notused;
|
f4c3@1031
|
216 |
};
|
f4c3@1031
|
217 |
|
f4c3@1031
|
218 |
|
f4c3@1031
|
219 |
class CheapestSelection {
|
f4c3@1031
|
220 |
private:
|
f4c3@1031
|
221 |
Cost costDiff(Node u, Node v, Node w) const {
|
f4c3@1031
|
222 |
return
|
f4c3@1031
|
223 |
_cost[_gr.edge(u, w)] +
|
f4c3@1031
|
224 |
_cost[_gr.edge(v, w)] -
|
f4c3@1031
|
225 |
_cost[_gr.edge(u, v)];
|
f4c3@1031
|
226 |
}
|
f4c3@1031
|
227 |
|
f4c3@1031
|
228 |
public:
|
f4c3@1031
|
229 |
CheapestSelection(const FullGraph &gr, const CostMap &cost,
|
f4c3@1031
|
230 |
std::vector<Node> &used, std::vector<Node> ¬used) :
|
f4c3@1031
|
231 |
_gr(gr), _cost(cost), _used(used), _notused(notused) {}
|
f4c3@1031
|
232 |
|
f4c3@1031
|
233 |
Cost select() const {
|
f4c3@1031
|
234 |
int insert_notused = -1;
|
f4c3@1031
|
235 |
int best_insert_index = -1;
|
f4c3@1031
|
236 |
Cost insert_val =
|
f4c3@1031
|
237 |
std::numeric_limits<Cost>::max();
|
f4c3@1031
|
238 |
|
f4c3@1031
|
239 |
for (unsigned int i=0; i<_notused.size(); ++i) {
|
f4c3@1031
|
240 |
int min = i;
|
f4c3@1031
|
241 |
int best_insert_tmp = 0;
|
f4c3@1031
|
242 |
Cost min_val =
|
f4c3@1031
|
243 |
costDiff(_used.front(), _used.back(), _notused[i]);
|
f4c3@1031
|
244 |
|
f4c3@1031
|
245 |
for (unsigned int j=1; j<_used.size(); ++j) {
|
f4c3@1031
|
246 |
Cost tmp =
|
f4c3@1031
|
247 |
costDiff(_used[j-1], _used[j], _notused[i]);
|
f4c3@1031
|
248 |
|
f4c3@1031
|
249 |
if (min_val > tmp) {
|
f4c3@1031
|
250 |
min = i;
|
f4c3@1031
|
251 |
min_val = tmp;
|
f4c3@1031
|
252 |
best_insert_tmp = j;
|
f4c3@1031
|
253 |
}
|
f4c3@1031
|
254 |
}
|
f4c3@1031
|
255 |
|
f4c3@1031
|
256 |
if (insert_val > min_val) {
|
f4c3@1031
|
257 |
insert_notused = min;
|
f4c3@1031
|
258 |
insert_val = min_val;
|
f4c3@1031
|
259 |
best_insert_index = best_insert_tmp;
|
f4c3@1031
|
260 |
}
|
f4c3@1031
|
261 |
}
|
f4c3@1031
|
262 |
|
f4c3@1031
|
263 |
_used.insert(_used.begin()+best_insert_index, _notused[insert_notused]);
|
f4c3@1031
|
264 |
_notused.erase(_notused.begin()+insert_notused);
|
f4c3@1031
|
265 |
|
f4c3@1031
|
266 |
return insert_val;
|
f4c3@1031
|
267 |
}
|
f4c3@1031
|
268 |
|
f4c3@1031
|
269 |
private:
|
f4c3@1031
|
270 |
const FullGraph &_gr;
|
f4c3@1031
|
271 |
const CostMap &_cost;
|
f4c3@1031
|
272 |
std::vector<Node> &_used;
|
f4c3@1031
|
273 |
std::vector<Node> &_notused;
|
f4c3@1031
|
274 |
};
|
f4c3@1031
|
275 |
|
f4c3@1031
|
276 |
class RandomSelection {
|
f4c3@1031
|
277 |
public:
|
f4c3@1031
|
278 |
RandomSelection(const FullGraph &, const CostMap &,
|
f4c3@1031
|
279 |
std::vector<Node> &, std::vector<Node> ¬used) :
|
f4c3@1031
|
280 |
_notused(notused) {
|
f4c3@1031
|
281 |
rnd.seedFromTime();
|
f4c3@1031
|
282 |
}
|
f4c3@1031
|
283 |
|
f4c3@1031
|
284 |
Node select() const {
|
f4c3@1031
|
285 |
const int index = rnd[_notused.size()];
|
f4c3@1031
|
286 |
Node n = _notused[index];
|
f4c3@1031
|
287 |
_notused.erase(_notused.begin()+index);
|
f4c3@1031
|
288 |
return n;
|
f4c3@1031
|
289 |
}
|
f4c3@1031
|
290 |
private:
|
f4c3@1031
|
291 |
std::vector<Node> &_notused;
|
f4c3@1031
|
292 |
};
|
f4c3@1031
|
293 |
|
f4c3@1031
|
294 |
|
f4c3@1031
|
295 |
class DefaultInsert {
|
f4c3@1031
|
296 |
private:
|
f4c3@1031
|
297 |
Cost costDiff(Node u, Node v, Node w) const {
|
f4c3@1031
|
298 |
return
|
f4c3@1031
|
299 |
_cost[_gr.edge(u, w)] +
|
f4c3@1031
|
300 |
_cost[_gr.edge(v, w)] -
|
f4c3@1031
|
301 |
_cost[_gr.edge(u, v)];
|
f4c3@1031
|
302 |
}
|
f4c3@1031
|
303 |
|
f4c3@1031
|
304 |
public:
|
f4c3@1031
|
305 |
DefaultInsert(const FullGraph &gr, const CostMap &cost,
|
f4c3@1031
|
306 |
std::vector<Node> &path, Cost &fullcost) :
|
f4c3@1031
|
307 |
_gr(gr), _cost(cost), _path(path), _fullcost(fullcost) {}
|
f4c3@1031
|
308 |
|
f4c3@1031
|
309 |
void insert(Node n) const {
|
f4c3@1031
|
310 |
int min = 0;
|
f4c3@1031
|
311 |
Cost min_val =
|
f4c3@1031
|
312 |
costDiff(_path.front(), _path.back(), n);
|
f4c3@1031
|
313 |
|
f4c3@1031
|
314 |
for (unsigned int i=1; i<_path.size(); ++i) {
|
f4c3@1031
|
315 |
Cost tmp = costDiff(_path[i-1], _path[i], n);
|
f4c3@1031
|
316 |
if (tmp < min_val) {
|
f4c3@1031
|
317 |
min = i;
|
f4c3@1031
|
318 |
min_val = tmp;
|
f4c3@1031
|
319 |
}
|
f4c3@1031
|
320 |
}
|
f4c3@1031
|
321 |
|
f4c3@1031
|
322 |
_path.insert(_path.begin()+min, n);
|
f4c3@1031
|
323 |
_fullcost += min_val;
|
f4c3@1031
|
324 |
}
|
f4c3@1031
|
325 |
|
f4c3@1031
|
326 |
private:
|
f4c3@1031
|
327 |
const FullGraph &_gr;
|
f4c3@1031
|
328 |
const CostMap &_cost;
|
f4c3@1031
|
329 |
std::vector<Node> &_path;
|
f4c3@1031
|
330 |
Cost &_fullcost;
|
f4c3@1031
|
331 |
};
|
f4c3@1031
|
332 |
|
f4c3@1031
|
333 |
class CheapestInsert {
|
f4c3@1031
|
334 |
TEMPLATE_GRAPH_TYPEDEFS(FullGraph);
|
f4c3@1031
|
335 |
public:
|
f4c3@1031
|
336 |
CheapestInsert(const FullGraph &, const CostMap &,
|
f4c3@1031
|
337 |
std::vector<Node> &, Cost &fullcost) :
|
f4c3@1031
|
338 |
_fullcost(fullcost) {}
|
f4c3@1031
|
339 |
|
f4c3@1031
|
340 |
void insert(Cost diff) const {
|
f4c3@1031
|
341 |
_fullcost += diff;
|
f4c3@1031
|
342 |
}
|
f4c3@1031
|
343 |
|
f4c3@1031
|
344 |
private:
|
f4c3@1031
|
345 |
Cost &_fullcost;
|
f4c3@1031
|
346 |
};
|
f4c3@1031
|
347 |
|
f4c3@1031
|
348 |
|
f4c3@1031
|
349 |
template <class InitFunctor, class SelectionFunctor, class InsertFunctor>
|
f4c3@1031
|
350 |
void start() {
|
f4c3@1031
|
351 |
InitFunctor init(_gr, _cost, nodesPath, notused, sum);
|
f4c3@1031
|
352 |
SelectionFunctor selectNode(_gr, _cost, nodesPath, notused);
|
f4c3@1031
|
353 |
InsertFunctor insertNode(_gr, _cost, nodesPath, sum);
|
f4c3@1031
|
354 |
|
f4c3@1031
|
355 |
nodesPath = init.init();
|
f4c3@1031
|
356 |
|
f4c3@1031
|
357 |
for (int i=0; i<_gr.nodeNum()-2; ++i) {
|
f4c3@1031
|
358 |
insertNode.insert(selectNode.select());
|
f4c3@1031
|
359 |
}
|
f4c3@1031
|
360 |
|
f4c3@1031
|
361 |
sum = _cost[ _gr.edge(nodesPath.front(), nodesPath.back()) ];
|
f4c3@1031
|
362 |
for (unsigned int i=0; i<nodesPath.size()-1; ++i)
|
f4c3@1031
|
363 |
sum += _cost[ _gr.edge(nodesPath[i], nodesPath[i+1]) ];
|
f4c3@1031
|
364 |
}
|
f4c3@1031
|
365 |
|
f4c3@1031
|
366 |
const FullGraph &_gr;
|
f4c3@1031
|
367 |
const CostMap &_cost;
|
f4c3@1031
|
368 |
std::vector<Node> notused;
|
f4c3@1031
|
369 |
std::vector<Node> nodesPath;
|
f4c3@1031
|
370 |
Cost sum;
|
f4c3@1031
|
371 |
};
|
f4c3@1031
|
372 |
|
f4c3@1031
|
373 |
}; // namespace lemon
|
f4c3@1031
|
374 |
|
f4c3@1031
|
375 |
#endif
|