Ticket #386: 386tsp7ed08f6da055.patch
File 386tsp7ed08f6da055.patch, 29.8 KB (added by , 14 years ago) 


lemon/Makefile.am
# HG changeset patch # User Gabor Varga <f4c3@inf.elte.hu> # Date 1281513228 7200 # Node ID 7ed08f6da0552a97eae58c4876e2367f9a765586 # Parent 24b3f18ed9e2bea99ab482c493c3db769362ecf0 Heuristic algorithms for symmetric TSP (#386) diff git a/lemon/Makefile.am b/lemon/Makefile.am
a b 64 64 lemon/bucket_heap.h \ 65 65 lemon/capacity_scaling.h \ 66 66 lemon/cbc.h \ 67 lemon/christofides_tsp.h \ 67 68 lemon/circulation.h \ 68 69 lemon/clp.h \ 69 70 lemon/color.h \ … … 89 90 lemon/glpk.h \ 90 91 lemon/gomory_hu.h \ 91 92 lemon/graph_to_eps.h \ 93 lemon/greedy_tsp.h \ 92 94 lemon/grid_graph.h \ 93 95 lemon/hartmann_orlin_mmc.h \ 94 96 lemon/howard_mmc.h \ 95 97 lemon/hypercube_graph.h \ 98 lemon/insertion_tsp.h \ 96 99 lemon/karp_mmc.h \ 97 100 lemon/kruskal.h \ 98 101 lemon/hao_orlin.h \ … … 107 110 lemon/math.h \ 108 111 lemon/min_cost_arborescence.h \ 109 112 lemon/nauty_reader.h \ 113 lemon/nearest_neighbor_tsp.h \ 110 114 lemon/network_simplex.h \ 115 lemon/opt2_tsp.h \ 111 116 lemon/pairing_heap.h \ 112 117 lemon/path.h \ 113 118 lemon/planarity.h \ 
new file lemon/christofides_tsp.h
diff git a/lemon/christofides_tsp.h b/lemon/christofides_tsp.h new file mode 100644
 + 1 #ifndef LEMON_CHRISTOFIDES_TSP 2 #define LEMON_CHRISTOFIDES_TSP 3 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> 12 #include <lemon/tsp_utils.h> 13 14 namespace lemon { 15 16 namespace christofides_helper { 17 template <class L> 18 L vectorConvert(const std::vector<FullGraph::Node> &_path) { 19 return L(_path.begin(), _path.end()); 20 } 21 22 template <> 23 std::vector<FullGraph::Node> vectorConvert(const std::vector<FullGraph::Node> &_path) { 24 return _path; 25 } 26 } 27 28 template <typename CM> 29 class ChristofidesTsp { 30 private: 31 GRAPH_TYPEDEFS(SmartGraph); 32 33 public: 34 typedef typename CM::Value Cost; 35 typedef SmartGraph::EdgeMap<Cost> CostMap; 36 37 ChristofidesTsp(const FullGraph &gr, const CM &cost) : _cost(_gr), fullg(gr), fullcost(cost), nr(_gr) { 38 graphCopy(gr, _gr).nodeCrossRef(nr).edgeMap(cost, _cost).run(); 39 } 40 41 Cost run() { 42 _path.clear(); 43 44 SmartGraph::EdgeMap<bool> tree(_gr); 45 kruskal(_gr, _cost, tree); 46 47 FilterEdges<SmartGraph> treefiltered(_gr, tree); 48 InDegMap<FilterEdges<SmartGraph> > deg(treefiltered); 49 50 SmartGraph::NodeMap<bool> oddfilter(_gr, false); 51 FilterNodes<SmartGraph> oddNodes(_gr, oddfilter); 52 53 for (NodeIt n(_gr); n!=INVALID; ++n) { 54 if (deg[n]%2 == 1) { 55 oddNodes.enable(n); 56 } 57 } 58 59 NegMap<CostMap> negmap(_cost); 60 MaxWeightedPerfectMatching<FilterNodes<SmartGraph>, 61 NegMap<CostMap> > perfmatch(oddNodes, negmap); 62 perfmatch.run(); 63 64 for (FilterNodes<SmartGraph>::EdgeIt e(oddNodes); e!=INVALID; ++e) { 65 if (perfmatch.matching(e)) { 66 treefiltered.enable(_gr.addEdge(_gr.u(e), _gr.v(e))); 67 } 68 } 69 70 FilterEdges<SmartGraph>::NodeMap<bool> seen(treefiltered, false); 71 for (EulerIt<FilterEdges<SmartGraph> > e(treefiltered); e!=INVALID; ++e) { 72 if (seen[treefiltered.target(e)]==false) { 73 _path.push_back(nr[treefiltered.target(e)]); 74 seen[treefiltered.target(e)] = true; 75 } 76 } 77 78 _sum = fullcost[ fullg.edge(_path.back(), _path.front()) ]; 79 for (unsigned int i=0; i<_path.size()1; ++i) 80 _sum += fullcost[ fullg.edge(_path[i], _path[i+1]) ]; 81 82 return _sum; 83 } 84 85 template <typename L> 86 void tourNodes(L &container) { 87 container(christofides_helper::vectorConvert<L>(_path)); 88 } 89 90 template <template <typename> class L> 91 L<FullGraph::Node> tourNodes() { 92 return christofides_helper::vectorConvert<L<FullGraph::Node> >(_path); 93 } 94 95 const std::vector<Node>& tourNodes() { 96 return _path; 97 } 98 99 Path<FullGraph> tour() { 100 Path<FullGraph> p; 101 if (_path.size()<2) 102 return p; 103 104 for (unsigned int i=0; i<_path.size()1; ++i) { 105 p.addBack(fullg.arc(_path[i], _path[i+1])); 106 } 107 p.addBack(fullg.arc(_path.back(), _path.front())); 108 109 return p; 110 } 111 112 Cost tourCost() { 113 return _sum; 114 } 115 116 117 private: 118 SmartGraph _gr; 119 CostMap _cost; 120 Cost _sum; 121 const FullGraph &fullg; 122 const CM &fullcost; 123 std::vector<FullGraph::Node> _path; 124 SmartGraph::NodeMap<FullGraph::Node> nr; 125 }; 126 127 128 }; // namespace lemon 129 130 #endif 
new file lemon/greedy_tsp.h
diff git a/lemon/greedy_tsp.h b/lemon/greedy_tsp.h new file mode 100644
 + 1 #ifndef LEMON_GREEDY_TSP 2 #define LEMON_GREEDY_TSP 3 4 #include <lemon/path.h> 5 #include <lemon/full_graph.h> 6 #include <lemon/unionfind.h> 7 #include <lemon/tsp_utils.h> 8 #include <algorithm> 9 10 namespace lemon { 11 12 namespace greedy_tsp_helper { 13 14 template <typename CostMap> 15 class KeyComp { 16 typedef typename CostMap::Key Key; 17 const CostMap &cost; 18 19 public: 20 KeyComp(const CostMap &_cost) : cost(_cost) {} 21 22 bool operator() (const Key &a, const Key &b) const { 23 return cost[a] < cost[b]; 24 } 25 }; 26 27 28 template <class L> 29 L vectorConvert(const std::vector<FullGraph::Node> &_path) { 30 return L(_path.begin(), _path.end()); 31 } 32 33 template <> 34 std::vector<FullGraph::Node> vectorConvert(const std::vector<FullGraph::Node> &_path) { 35 return _path; 36 } 37 38 } 39 40 41 template <typename CM> 42 class GreedyTsp { 43 private: 44 GRAPH_TYPEDEFS(FullGraph); 45 46 public: 47 typedef CM CostMap; 48 typedef typename CM::Value Cost; 49 50 GreedyTsp(const FullGraph &gr, const CostMap &cost) : _gr(gr), _cost(cost) {} 51 52 Cost run() { 53 typedef UnionFind<FullGraph::NodeMap<int> > Union; 54 _nodes.clear(); 55 56 std::vector<int> path; 57 path.resize(_gr.nodeNum()*2, 1); 58 59 std::vector<typename CostMap::Key> sorted_edges; 60 sorted_edges.reserve(_gr.edgeNum()); 61 for (EdgeIt n(_gr); n != INVALID; ++n) 62 sorted_edges.push_back(n); 63 64 std::sort(sorted_edges.begin(), sorted_edges.end(), greedy_tsp_helper::KeyComp<CostMap>(_cost)); 65 66 FullGraph::NodeMap<int> nodemap(_gr); 67 Union unionfind(nodemap); 68 69 for (NodeIt n(_gr); n != INVALID; ++n) 70 unionfind.insert(n); 71 72 FullGraph::NodeMap<int> degree(_gr, 0); 73 74 int nodesNum = 0, i = 0; 75 76 while ( nodesNum != _gr.nodeNum()1 ) { 77 const Edge &e = sorted_edges[i]; 78 79 const Node u = _gr.u(e), 80 v = _gr.v(e); 81 82 if (degree[u]<=1 && degree[v]<=1) { 83 if (unionfind.join(u, v)) { 84 ++degree[u]; 85 ++degree[v]; 86 ++nodesNum; 87 88 const int uid = _gr.id(u), 89 vid = _gr.id(v); 90 91 92 path[uid*2 + (path[uid*2]==1 ? 0 : 1)] = vid; 93 path[vid*2 + (path[vid*2]==1 ? 0 : 1)] = uid; 94 } 95 } 96 97 ++i; 98 } 99 100 101 for (int i=0, n=1; i<_gr.nodeNum()*2; ++i) { 102 if (path[i] == 1) { 103 if (n==1) { 104 n = i; 105 } else { 106 path[n] = i/2; 107 path[i] = n/2; 108 break; 109 } 110 } 111 } 112 113 114 for (int i=0, j=0, last=1; i!=_gr.nodeNum(); ++i) { 115 _nodes.push_back(_gr.nodeFromId(j)); 116 117 if (path[2*j] != last) { 118 last = j; 119 j = path[2*j]; 120 } else { 121 last = j; 122 j = path[2*j+1]; 123 } 124 } 125 126 _sum = _cost[_gr.edge(_nodes.back(), _nodes.front())]; 127 for (unsigned int i=0; i<_nodes.size()1; ++i) 128 _sum += _cost[_gr.edge(_nodes[i], _nodes[i+1])]; 129 130 return _sum; 131 } 132 133 134 135 template <typename L> 136 void tourNodes(L &container) { 137 container(greedy_tsp_helper::vectorConvert<L>(_nodes)); 138 } 139 140 template <template <typename> class L> 141 L<Node> tourNodes() { 142 return greedy_tsp_helper::vectorConvert<L<Node> >(_nodes); 143 } 144 145 const std::vector<Node>& tourNodes() { 146 return _nodes; 147 } 148 149 Path<FullGraph> tour() { 150 Path<FullGraph> p; 151 if (_nodes.size()<2) 152 return p; 153 154 for (unsigned int i=0; i<_nodes.size()1; ++i) { 155 p.addBack(_gr.arc(_nodes[i], _nodes[i+1])); 156 } 157 158 p.addBack(_gr.arc(_nodes.back(), _nodes.front())); 159 160 return p; 161 } 162 163 Cost tourCost() { 164 return _sum; 165 } 166 167 168 private: 169 const FullGraph &_gr; 170 const CostMap &_cost; 171 Cost _sum; 172 std::vector<Node> _nodes; 173 }; 174 175 }; // namespace lemon 176 177 #endif 
new file lemon/insertion_tsp.h
diff git a/lemon/insertion_tsp.h b/lemon/insertion_tsp.h new file mode 100644
 + 1 #ifndef LEMON_INSERTION_TSP 2 #define LEMON_INSERTION_TSP 3 4 #include <lemon/full_graph.h> 5 #include <lemon/path.h> 6 #include <lemon/maps.h> 7 #include <lemon/random.h> 8 #include <lemon/tsp_utils.h> 9 #include <vector> 10 11 namespace lemon { 12 13 namespace insertion_tsp_helper { 14 15 template <class L> 16 L vectorConvert(const std::vector<FullGraph::Node> &_path) { 17 return L(_path.begin(), _path.end()); 18 }; 19 20 template <> 21 std::vector<FullGraph::Node> vectorConvert( 22 const std::vector<FullGraph::Node> &_path) { 23 return _path; 24 }; 25 26 }; 27 28 template <typename CM> 29 class InsertionTsp { 30 private: 31 GRAPH_TYPEDEFS(FullGraph); 32 33 public: 34 typedef CM CostMap; 35 typedef typename CM::Value Cost; 36 37 InsertionTsp(const FullGraph &gr, const CostMap &cost) : 38 _gr(gr), _cost(cost) {} 39 40 enum InsertionMethod { 41 INSERT_NEAREST, 42 INSERT_FARTHEST, 43 INSERT_CHEAPEST, 44 INSERT_RANDOM 45 }; 46 47 Cost run(InsertionMethod method = INSERT_FARTHEST) { 48 switch (method) { 49 case INSERT_NEAREST: 50 start<InitTour<true>, NearestSelection, DefaultInsert>(); 51 break; 52 case INSERT_FARTHEST: 53 start<InitTour<false>, FarthestSelection, DefaultInsert>(); 54 break; 55 case INSERT_CHEAPEST: 56 start<InitTour<true>, CheapestSelection, CheapestInsert>(); 57 break; 58 case INSERT_RANDOM: 59 start<InitTour<true>, RandomSelection, DefaultInsert>(); 60 break; 61 } 62 return sum; 63 } 64 65 template <typename L> 66 void tourNodes(L &container) { 67 container(insertion_tsp_helper::vectorConvert<L>(nodesPath)); 68 } 69 70 template <template <typename> class L> 71 L<Node> tourNodes() { 72 return insertion_tsp_helper::vectorConvert<L<Node> >(nodesPath); 73 } 74 75 const std::vector<Node>& tourNodes() { 76 return nodesPath; 77 } 78 79 Path<FullGraph> tour() { 80 Path<FullGraph> p; 81 if (nodesPath.size()<2) 82 return p; 83 84 for (unsigned int i=0; i<nodesPath.size()1; ++i) 85 p.addBack(_gr.arc(nodesPath[i], nodesPath[i+1])); 86 87 p.addBack(_gr.arc(nodesPath.back(), nodesPath.front())); 88 return p; 89 } 90 91 Cost tourCost() { 92 return sum; 93 } 94 95 96 private: 97 98 template <bool MIN> 99 class InitTour { 100 public: 101 InitTour(const FullGraph &gr, const CostMap &cost, 102 std::vector<Node> &used, std::vector<Node> ¬used, 103 Cost &fullcost) : 104 _gr(gr), _cost(cost), _used(used), _notused(notused), 105 _fullcost(fullcost) {} 106 107 std::vector<Node> init() const { 108 Edge min = (MIN) ? mapMin(_gr, _cost) : mapMax(_gr, _cost); 109 std::vector<Node> path; 110 path.push_back(_gr.u(min)); 111 path.push_back(_gr.v(min)); 112 113 _used.clear(); 114 _notused.clear(); 115 for (NodeIt n(_gr); n!=INVALID; ++n) { 116 if (n != _gr.u(min) && n != _gr.v(min)) { 117 _notused.push_back(n); 118 } 119 } 120 _used.push_back(_gr.u(min)); 121 _used.push_back(_gr.v(min)); 122 123 _fullcost = _cost[min]*2; 124 return path; 125 } 126 127 private: 128 const FullGraph &_gr; 129 const CostMap &_cost; 130 std::vector<Node> &_used; 131 std::vector<Node> &_notused; 132 Cost &_fullcost; 133 }; 134 135 class NearestSelection { 136 public: 137 NearestSelection(const FullGraph &gr, const CostMap &cost, 138 std::vector<Node> &used, std::vector<Node> ¬used) : 139 _gr(gr), _cost(cost), _used(used), _notused(notused) {} 140 141 Node select() const { 142 143 Cost insert_val = 144 std::numeric_limits<Cost>::max(); 145 int insert_node = 1; 146 147 for (unsigned int i=0; i<_notused.size(); ++i) { 148 Cost min_val = _cost[_gr.edge(_notused[i], _used[0])]; 149 int min_node = 0; 150 151 for (unsigned int j=1; j<_used.size(); ++j) { 152 if (min_val > _cost[_gr.edge(_notused[i], _used[j])]) { 153 min_val = _cost[_gr.edge(_notused[i], _used[j])]; 154 min_node = j; 155 } 156 } 157 158 if (insert_val > min_val) { 159 insert_val = min_val; 160 insert_node = i; 161 } 162 } 163 164 Node n = _notused[insert_node]; 165 _notused.erase(_notused.begin()+insert_node); 166 167 return n; 168 } 169 170 private: 171 const FullGraph &_gr; 172 const CostMap &_cost; 173 std::vector<Node> &_used; 174 std::vector<Node> &_notused; 175 }; 176 177 class FarthestSelection { 178 public: 179 FarthestSelection(const FullGraph &gr, const CostMap &cost, 180 std::vector<Node> &used, std::vector<Node> ¬used) : 181 _gr(gr), _cost(cost), _used(used), _notused(notused) {} 182 183 Node select() const { 184 185 Cost insert_val = 186 std::numeric_limits<Cost>::min(); 187 int insert_node = 1; 188 189 for (unsigned int i=0; i<_notused.size(); ++i) { 190 Cost min_val = _cost[_gr.edge(_notused[i], _used[0])]; 191 int min_node = 0; 192 193 for (unsigned int j=1; j<_used.size(); ++j) { 194 if (min_val > _cost[_gr.edge(_notused[i], _used[j])]) { 195 min_val = _cost[_gr.edge(_notused[i], _used[j])]; 196 min_node = j; 197 } 198 } 199 200 if (insert_val < min_val  insert_node == 1) { 201 insert_val = min_val; 202 insert_node = i; 203 } 204 } 205 206 Node n = _notused[insert_node]; 207 _notused.erase(_notused.begin()+insert_node); 208 209 return n; 210 } 211 212 private: 213 const FullGraph &_gr; 214 const CostMap &_cost; 215 std::vector<Node> &_used; 216 std::vector<Node> &_notused; 217 }; 218 219 220 class CheapestSelection { 221 private: 222 Cost costDiff(Node u, Node v, Node w) const { 223 return 224 _cost[_gr.edge(u, w)] + 225 _cost[_gr.edge(v, w)]  226 _cost[_gr.edge(u, v)]; 227 } 228 229 public: 230 CheapestSelection(const FullGraph &gr, const CostMap &cost, 231 std::vector<Node> &used, std::vector<Node> ¬used) : 232 _gr(gr), _cost(cost), _used(used), _notused(notused) {} 233 234 Cost select() const { 235 int insert_notused = 1; 236 int best_insert_index = 1; 237 Cost insert_val = 238 std::numeric_limits<Cost>::max(); 239 240 for (unsigned int i=0; i<_notused.size(); ++i) { 241 int min = i; 242 int best_insert_tmp = 0; 243 Cost min_val = 244 costDiff(_used.front(), _used.back(), _notused[i]); 245 246 for (unsigned int j=1; j<_used.size(); ++j) { 247 Cost tmp = 248 costDiff(_used[j1], _used[j], _notused[i]); 249 250 if (min_val > tmp) { 251 min = i; 252 min_val = tmp; 253 best_insert_tmp = j; 254 } 255 } 256 257 if (insert_val > min_val) { 258 insert_notused = min; 259 insert_val = min_val; 260 best_insert_index = best_insert_tmp; 261 } 262 } 263 264 _used.insert(_used.begin()+best_insert_index, _notused[insert_notused]); 265 _notused.erase(_notused.begin()+insert_notused); 266 267 return insert_val; 268 } 269 270 private: 271 const FullGraph &_gr; 272 const CostMap &_cost; 273 std::vector<Node> &_used; 274 std::vector<Node> &_notused; 275 }; 276 277 class RandomSelection { 278 public: 279 RandomSelection(const FullGraph &, const CostMap &, 280 std::vector<Node> &, std::vector<Node> ¬used) : 281 _notused(notused) { 282 rnd.seedFromTime(); 283 } 284 285 Node select() const { 286 const int index = rnd[_notused.size()]; 287 Node n = _notused[index]; 288 _notused.erase(_notused.begin()+index); 289 return n; 290 } 291 private: 292 std::vector<Node> &_notused; 293 }; 294 295 296 class DefaultInsert { 297 private: 298 Cost costDiff(Node u, Node v, Node w) const { 299 return 300 _cost[_gr.edge(u, w)] + 301 _cost[_gr.edge(v, w)]  302 _cost[_gr.edge(u, v)]; 303 } 304 305 public: 306 DefaultInsert(const FullGraph &gr, const CostMap &cost, 307 std::vector<Node> &path, Cost &fullcost) : 308 _gr(gr), _cost(cost), _path(path), _fullcost(fullcost) {} 309 310 void insert(Node n) const { 311 int min = 0; 312 Cost min_val = 313 costDiff(_path.front(), _path.back(), n); 314 315 for (unsigned int i=1; i<_path.size(); ++i) { 316 Cost tmp = costDiff(_path[i1], _path[i], n); 317 if (tmp < min_val) { 318 min = i; 319 min_val = tmp; 320 } 321 } 322 323 _path.insert(_path.begin()+min, n); 324 _fullcost += min_val; 325 } 326 327 private: 328 const FullGraph &_gr; 329 const CostMap &_cost; 330 std::vector<Node> &_path; 331 Cost &_fullcost; 332 }; 333 334 class CheapestInsert { 335 TEMPLATE_GRAPH_TYPEDEFS(FullGraph); 336 public: 337 CheapestInsert(const FullGraph &, const CostMap &, 338 std::vector<Node> &, Cost &fullcost) : 339 _fullcost(fullcost) {} 340 341 void insert(Cost diff) const { 342 _fullcost += diff; 343 } 344 345 private: 346 Cost &_fullcost; 347 }; 348 349 350 template <class InitFunctor, class SelectionFunctor, class InsertFunctor> 351 void start() { 352 InitFunctor init(_gr, _cost, nodesPath, notused, sum); 353 SelectionFunctor selectNode(_gr, _cost, nodesPath, notused); 354 InsertFunctor insertNode(_gr, _cost, nodesPath, sum); 355 356 nodesPath = init.init(); 357 358 for (int i=0; i<_gr.nodeNum()2; ++i) { 359 insertNode.insert(selectNode.select()); 360 } 361 362 sum = _cost[ _gr.edge(nodesPath.front(), nodesPath.back()) ]; 363 for (unsigned int i=0; i<nodesPath.size()1; ++i) 364 sum += _cost[ _gr.edge(nodesPath[i], nodesPath[i+1]) ]; 365 } 366 367 const FullGraph &_gr; 368 const CostMap &_cost; 369 std::vector<Node> notused; 370 std::vector<Node> nodesPath; 371 Cost sum; 372 }; 373 374 }; // namespace lemon 375 376 #endif 
new file lemon/nearest_neighbor_tsp.h
diff git a/lemon/nearest_neighbor_tsp.h b/lemon/nearest_neighbor_tsp.h new file mode 100644
 + 1 #ifndef LEMON_NEAREST_NEIGHBOUR_TSP 2 #define LEMON_NEAREST_NEIGHBOUR_TSP 3 4 #include <deque> 5 #include <lemon/full_graph.h> 6 #include <lemon/path.h> 7 #include <lemon/maps.h> 8 #include <lemon/tsp_utils.h> 9 10 namespace lemon { 11 12 namespace nn_helper { 13 template <class L> 14 L dequeConvert(const std::deque<FullGraph::Node> &_path) { 15 return L(_path.begin(), _path.end()); 16 } 17 18 template <> 19 std::deque<FullGraph::Node> dequeConvert(const std::deque<FullGraph::Node> &_path) { 20 return _path; 21 } 22 } 23 24 template <typename CM> 25 class NearestNeighborTsp { 26 private: 27 GRAPH_TYPEDEFS(FullGraph); 28 29 public: 30 typedef CM CostMap; 31 typedef typename CM::Value Cost; 32 33 NearestNeighborTsp(const FullGraph &gr, const CostMap &cost) : _gr(gr), _cost(cost) {} 34 35 Cost run() { 36 _path.clear(); 37 38 Edge min_edge1 = INVALID, 39 min_edge2 = INVALID; 40 41 min_edge1 = mapMin(_gr, _cost); 42 43 FullGraph::NodeMap<bool> used(_gr, false); 44 45 Node n1 = _gr.u(min_edge1), 46 n2 = _gr.v(min_edge1); 47 48 _path.push_back(n1); 49 _path.push_back(n2); 50 51 used[n1] = true; 52 used[n2] = true; 53 54 min_edge1 = INVALID; 55 56 while (int(_path.size()) != _gr.nodeNum()) { 57 if (min_edge1 == INVALID) { 58 for (IncEdgeIt e(_gr, n1); e!=INVALID; ++e) { 59 if (!used[_gr.runningNode(e)]) { 60 if (min_edge1==INVALID  _cost[min_edge1] > _cost[e]) 61 min_edge1 = e; 62 } 63 } 64 } 65 66 if (min_edge2 == INVALID) { 67 for (IncEdgeIt e(_gr, n2); e!=INVALID; ++e) { 68 if (!used[_gr.runningNode(e)]) { 69 if (min_edge2==INVALID  _cost[min_edge2] > _cost[e]) 70 min_edge2 = e; 71 } 72 } 73 } 74 75 if ( _cost[min_edge1] < _cost[min_edge2] ) { 76 n1 = (_gr.u(min_edge1) == n1) ? _gr.v(min_edge1) : _gr.u(min_edge1); 77 _path.push_front(n1); 78 79 used[n1] = true; 80 min_edge1 = INVALID; 81 82 if (_gr.u(min_edge2)==n1  _gr.v(min_edge2)==n1) 83 min_edge2 = INVALID; 84 } else { 85 n2 = (_gr.u(min_edge2) == n2) ? _gr.v(min_edge2) : _gr.u(min_edge2); 86 _path.push_back(n2); 87 88 used[n2] = true; 89 min_edge2 = INVALID; 90 91 if (_gr.u(min_edge1)==n2  _gr.v(min_edge1)==n2) 92 min_edge1 = INVALID; 93 } 94 } 95 96 _sum = _cost[ _gr.edge(_path.back(), _path.front()) ]; 97 for (unsigned int i=0; i<_path.size()1; ++i) 98 _sum += _cost[ _gr.edge(_path[i], _path[i+1]) ]; 99 100 return _sum; 101 } 102 103 104 template <typename L> 105 void tourNodes(L &container) { 106 container(nn_helper::dequeConvert<L>(_path)); 107 } 108 109 template <template <typename> class L> 110 L<Node> tourNodes() { 111 return nn_helper::dequeConvert<L<Node> >(_path); 112 } 113 114 const std::deque<Node>& tourNodes() { 115 return _path; 116 } 117 118 Path<FullGraph> tour() { 119 Path<FullGraph> p; 120 if (_path.size()<2) 121 return p; 122 123 for (unsigned int i=0; i<_path.size()1; ++i) { 124 p.addBack(_gr.arc(_path[i], _path[i+1])); 125 } 126 p.addBack(_gr.arc(_path.back(), _path.front())); 127 128 return p; 129 } 130 131 Cost tourCost() { 132 return _sum; 133 } 134 135 136 private: 137 const FullGraph &_gr; 138 const CostMap &_cost; 139 Cost _sum; 140 std::deque<Node> _path; 141 }; 142 143 144 }; // namespace lemon 145 146 #endif 
new file lemon/opt2_tsp.h
diff git a/lemon/opt2_tsp.h b/lemon/opt2_tsp.h new file mode 100644
 + 1 #ifndef LEMON_OPT2_TSP 2 #define LEMON_OPT2_TSP 3 4 #include <vector> 5 #include <lemon/full_graph.h> 6 #include <lemon/path.h> 7 #include <lemon/tsp_utils.h> 8 9 namespace lemon { 10 11 namespace opt2_helper { 12 template <class L> 13 L vectorConvert(const std::vector<FullGraph::Node> &_path) { 14 return L(_path.begin(), _path.end()); 15 } 16 17 template <> 18 std::vector<FullGraph::Node> vectorConvert(const std::vector<FullGraph::Node> &_path) { 19 return _path; 20 } 21 } 22 23 template <typename CM> 24 class Opt2Tsp { 25 private: 26 GRAPH_TYPEDEFS(FullGraph); 27 28 public: 29 typedef CM CostMap; 30 typedef typename CM::Value Cost; 31 32 33 Opt2Tsp(const FullGraph &gr, const CostMap &cost) : _gr(gr), _cost(cost), 34 tmppath(_gr.nodeNum()*2) { 35 36 for (int i=1; i<_gr.nodeNum()1; ++i) { 37 tmppath[2*i] = i1; 38 tmppath[2*i+1] = i+1; 39 } 40 tmppath[0] = _gr.nodeNum()1; 41 tmppath[1] = 1; 42 tmppath[2*(_gr.nodeNum()1)] = _gr.nodeNum()2; 43 tmppath[2*(_gr.nodeNum()1)+1] = 0; 44 } 45 46 Opt2Tsp(const FullGraph &gr, const CostMap &cost, const std::vector<Node> &path) : 47 _gr(gr), _cost(cost), tmppath(_gr.nodeNum()*2) { 48 49 for (unsigned int i=1; i<path.size()1; ++i) { 50 tmppath[2*_gr.id(path[i])] = _gr.id(path[i1]); 51 tmppath[2*_gr.id(path[i])+1] = _gr.id(path[i+1]); 52 } 53 54 tmppath[2*_gr.id(path[0])] = _gr.id(path.back()); 55 tmppath[2*_gr.id(path[0])+1] = _gr.id(path[1]); 56 tmppath[2*_gr.id(path.back())] = _gr.id(path[path.size()2]); 57 tmppath[2*_gr.id(path.back())+1] = _gr.id(path.front()); 58 } 59 60 private: 61 Cost c(int u, int v) { 62 return _cost[_gr.edge(_gr.nodeFromId(u), _gr.nodeFromId(v))]; 63 } 64 65 class It { 66 public: 67 It(const std::vector<int> &path, int i=0) : tmppath(path), act(i), last(tmppath[2*act]) {} 68 It(const std::vector<int> &path, int i, int l) : tmppath(path), act(i), last(l) {} 69 70 int next_index() const { 71 return (tmppath[2*act]==last)? 2*act+1 : 2*act; 72 } 73 74 int prev_index() const { 75 return (tmppath[2*act]==last)? 2*act : 2*act+1; 76 } 77 78 int next() const { 79 return tmppath[next_index()]; 80 } 81 82 int prev() const { 83 return tmppath[prev_index()]; 84 } 85 86 It& operator++() { 87 int tmp = act; 88 act = next(); 89 last = tmp; 90 return *this; 91 } 92 93 operator int() const { 94 return act; 95 } 96 97 private: 98 const std::vector<int> &tmppath; 99 int act; 100 int last; 101 }; 102 103 bool check(std::vector<int> &path, It i, It j) { 104 if (c(i, i.next()) + c(j, j.next()) > 105 c(i, j) + c(j.next(), i.next())) { 106 107 path[ It(path, i.next(), i).prev_index() ] = j.next(); 108 path[ It(path, j.next(), j).prev_index() ] = i.next(); 109 110 path[i.next_index()] = j; 111 path[j.next_index()] = i; 112 113 return true; 114 } 115 return false; 116 } 117 118 public: 119 120 Cost run() { 121 _path.clear(); 122 123 if (_gr.nodeNum()>3) { 124 125 opt2_tsp_label: 126 It i(tmppath); 127 It j(tmppath, i, i.prev()); 128 ++j; ++j; 129 for (; j.next()!=0; ++j) { 130 if (check(tmppath, i, j)) 131 goto opt2_tsp_label; 132 } 133 134 for (++i; i.next()!=0; ++i) { 135 It j(tmppath, i, i.prev()); 136 if (++j==0) 137 break; 138 if (++j==0) 139 break; 140 141 for (; j!=0; ++j) { 142 if (check(tmppath, i, j)) 143 goto opt2_tsp_label; 144 } 145 } 146 } 147 148 It k(tmppath); 149 _path.push_back(_gr.nodeFromId(k)); 150 for (++k; k!=0; ++k) 151 _path.push_back(_gr.nodeFromId(k)); 152 153 154 155 _sum = _cost[ _gr.edge(_path.back(), _path.front()) ]; 156 for (unsigned int i=0; i<_path.size()1; ++i) 157 _sum += _cost[ _gr.edge(_path[i], _path[i+1]) ]; 158 return _sum; 159 } 160 161 162 template <typename L> 163 void tourNodes(L &container) { 164 container(opt2_helper::vectorConvert<L>(_path)); 165 } 166 167 template <template <typename> class L> 168 L<Node> tourNodes() { 169 return opt2_helper::vectorConvert<L<Node> >(_path); 170 } 171 172 const std::vector<Node>& tourNodes() { 173 return _path; 174 } 175 176 Path<FullGraph> tour() { 177 Path<FullGraph> p; 178 if (_path.size()<2) 179 return p; 180 181 for (unsigned int i=0; i<_path.size()1; ++i) { 182 p.addBack(_gr.arc(_path[i], _path[i+1])); 183 } 184 p.addBack(_gr.arc(_path.back(), _path.front())); 185 return p; 186 } 187 188 Cost tourCost() { 189 return _sum; 190 } 191 192 193 private: 194 const FullGraph &_gr; 195 const CostMap &_cost; 196 Cost _sum; 197 std::vector<int> tmppath; 198 std::vector<Node> _path; 199 }; 200 201 202 }; // namespace lemon 203 204 #endif