[Lemon-commits] Gabor Varga: Heuristic algorithms for symmetric ...

Lemon HG hg at lemon.cs.elte.hu
Fri Mar 1 18:03:15 CET 2013


details:   http://lemon.cs.elte.hu/hg/lemon/rev/ae0b056593a7
changeset: 1199:ae0b056593a7
user:      Gabor Varga <f4c3 [at] inf.elte.hu>
date:      Sat Jan 08 21:59:56 2011 +0100
description:
	Heuristic algorithms for symmetric TSP (#386)

diffstat:

 lemon/Makefile.am            |    5 +
 lemon/christofides_tsp.h     |  129 ++++++++++++++
 lemon/greedy_tsp.h           |  176 ++++++++++++++++++++
 lemon/insertion_tsp.h        |  375 +++++++++++++++++++++++++++++++++++++++++++
 lemon/nearest_neighbor_tsp.h |  145 ++++++++++++++++
 lemon/opt2_tsp.h             |  203 +++++++++++++++++++++++
 6 files changed, 1033 insertions(+), 0 deletions(-)

diffs (truncated from 1088 to 300 lines):

diff --git a/lemon/Makefile.am b/lemon/Makefile.am
--- a/lemon/Makefile.am
+++ b/lemon/Makefile.am
@@ -64,6 +64,7 @@
 	lemon/bucket_heap.h \
 	lemon/capacity_scaling.h \
 	lemon/cbc.h \
+	lemon/christofides_tsp.h \
 	lemon/circulation.h \
 	lemon/clp.h \
 	lemon/color.h \
@@ -89,11 +90,13 @@
 	lemon/glpk.h \
 	lemon/gomory_hu.h \
 	lemon/graph_to_eps.h \
+	lemon/greedy_tsp.h \
 	lemon/grid_graph.h \
 	lemon/grosso_locatelli_pullan_mc.h \
 	lemon/hartmann_orlin_mmc.h \
 	lemon/howard_mmc.h \
 	lemon/hypercube_graph.h \
+	lemon/insertion_tsp.h \
 	lemon/karp_mmc.h \
 	lemon/kruskal.h \
 	lemon/hao_orlin.h \
@@ -110,7 +113,9 @@
 	lemon/max_cardinality_search.h \
 	lemon/nagamochi_ibaraki.h \
 	lemon/nauty_reader.h \
+	lemon/nearest_neighbor_tsp.h \
 	lemon/network_simplex.h \
+	lemon/opt2_tsp.h \
 	lemon/pairing_heap.h \
 	lemon/path.h \
 	lemon/planarity.h \
diff --git a/lemon/christofides_tsp.h b/lemon/christofides_tsp.h
new file mode 100644
--- /dev/null
+++ b/lemon/christofides_tsp.h
@@ -0,0 +1,129 @@
+#ifndef LEMON_CHRISTOFIDES_TSP_H
+#define LEMON_CHRISTOFIDES_TSP_H
+
+#include <lemon/full_graph.h>
+#include <lemon/smart_graph.h>
+#include <lemon/path.h>
+#include <lemon/kruskal.h>
+#include <lemon/matching.h>
+#include <lemon/adaptors.h>
+#include <lemon/maps.h>
+#include <lemon/euler.h>
+
+namespace lemon {
+  
+  namespace christofides_helper {
+    template <class L>
+    L vectorConvert(const std::vector<FullGraph::Node> &_path) {
+      return L(_path.begin(), _path.end());
+    }
+  
+    template <>
+    std::vector<FullGraph::Node> vectorConvert(const std::vector<FullGraph::Node> &_path) {
+      return _path;
+    }
+  }
+  
+  template <typename CM>
+  class ChristofidesTsp {
+    private:
+      GRAPH_TYPEDEFS(SmartGraph);
+
+    public:
+      typedef typename CM::Value Cost;
+      typedef SmartGraph::EdgeMap<Cost> CostMap;
+    
+      ChristofidesTsp(const FullGraph &gr, const CM &cost) : _cost(_gr), fullg(gr), fullcost(cost), nr(_gr) {
+        graphCopy(gr, _gr).nodeCrossRef(nr).edgeMap(cost, _cost).run();
+      }
+
+      Cost run() {
+        _path.clear();
+        
+        SmartGraph::EdgeMap<bool> tree(_gr);
+        kruskal(_gr, _cost, tree);
+        
+        FilterEdges<SmartGraph> treefiltered(_gr, tree);
+        InDegMap<FilterEdges<SmartGraph> > deg(treefiltered);
+        
+        SmartGraph::NodeMap<bool> oddfilter(_gr, false);
+        FilterNodes<SmartGraph> oddNodes(_gr, oddfilter);
+        
+        for (NodeIt n(_gr); n!=INVALID; ++n) {
+          if (deg[n]%2 == 1) {
+            oddNodes.enable(n);
+          }
+        }
+        
+        NegMap<CostMap> negmap(_cost);
+        MaxWeightedPerfectMatching<FilterNodes<SmartGraph>,
+                  NegMap<CostMap> > perfmatch(oddNodes, negmap);
+        perfmatch.run();
+        
+        for (FilterNodes<SmartGraph>::EdgeIt e(oddNodes); e!=INVALID; ++e) {
+          if (perfmatch.matching(e)) {
+            treefiltered.enable(_gr.addEdge(_gr.u(e), _gr.v(e)));
+          }
+        }
+        
+        FilterEdges<SmartGraph>::NodeMap<bool> seen(treefiltered, false);
+        for (EulerIt<FilterEdges<SmartGraph> > e(treefiltered); e!=INVALID; ++e) {
+          if (seen[treefiltered.target(e)]==false) {
+            _path.push_back(nr[treefiltered.target(e)]);
+            seen[treefiltered.target(e)] = true;
+          }
+        }
+
+        _sum = fullcost[ fullg.edge(_path.back(), _path.front()) ];
+        for (unsigned int i=0; i<_path.size()-1; ++i)
+          _sum += fullcost[ fullg.edge(_path[i], _path[i+1]) ];
+
+        return _sum;
+      }
+
+      template <typename L>
+      void tourNodes(L &container) {
+        container(christofides_helper::vectorConvert<L>(_path));
+      }
+      
+      template <template <typename> class L>
+      L<FullGraph::Node> tourNodes() {
+        return christofides_helper::vectorConvert<L<FullGraph::Node> >(_path);
+      }
+
+      const std::vector<Node>& tourNodes() {
+        return _path;
+      }
+      
+      Path<FullGraph> tour() {
+        Path<FullGraph> p;
+        if (_path.size()<2)
+          return p;
+
+        for (unsigned int i=0; i<_path.size()-1; ++i) {
+          p.addBack(fullg.arc(_path[i], _path[i+1]));
+        }
+        p.addBack(fullg.arc(_path.back(), _path.front()));
+        
+        return p;
+      }
+      
+      Cost tourCost() {
+        return _sum;
+      }
+      
+
+  private:
+    SmartGraph _gr;
+    CostMap _cost;
+    Cost _sum;
+    const FullGraph &fullg;
+    const CM &fullcost;
+    std::vector<FullGraph::Node> _path;
+    SmartGraph::NodeMap<FullGraph::Node> nr;
+  };
+
+
+}; // namespace lemon
+
+#endif
diff --git a/lemon/greedy_tsp.h b/lemon/greedy_tsp.h
new file mode 100644
--- /dev/null
+++ b/lemon/greedy_tsp.h
@@ -0,0 +1,176 @@
+#ifndef LEMON_GREEDY_TSP_H
+#define LEMON_GREEDY_TSP_H
+
+#include <lemon/path.h>
+#include <lemon/full_graph.h>
+#include <lemon/unionfind.h>
+#include <algorithm>
+
+namespace lemon {
+
+  namespace greedy_tsp_helper {
+
+    template <typename CostMap>
+    class KeyComp {
+      typedef typename CostMap::Key Key;
+      const CostMap &cost;
+      
+      public:
+        KeyComp(const CostMap &_cost) : cost(_cost) {}
+      
+        bool operator() (const Key &a, const Key &b) const {
+          return cost[a] < cost[b];
+        }
+    };
+
+  
+    template <class L>
+    L vectorConvert(const std::vector<FullGraph::Node> &_path) {
+      return L(_path.begin(), _path.end());
+    }
+  
+    template <>
+    std::vector<FullGraph::Node> vectorConvert(const std::vector<FullGraph::Node> &_path) {
+      return _path;
+    }
+    
+  }
+
+
+  template <typename CM>
+  class GreedyTsp {
+    private:
+      GRAPH_TYPEDEFS(FullGraph);
+    
+    public:
+      typedef CM CostMap;
+      typedef typename CM::Value Cost;
+      
+      GreedyTsp(const FullGraph &gr, const CostMap &cost) : _gr(gr), _cost(cost) {}  
+
+      Cost run() {
+        typedef UnionFind<FullGraph::NodeMap<int> > Union;
+        _nodes.clear();
+        
+        std::vector<int> path;
+        path.resize(_gr.nodeNum()*2, -1);
+        
+        std::vector<typename CostMap::Key> sorted_edges;
+        sorted_edges.reserve(_gr.edgeNum());
+        for (EdgeIt n(_gr); n != INVALID; ++n)
+          sorted_edges.push_back(n);
+
+        std::sort(sorted_edges.begin(), sorted_edges.end(), greedy_tsp_helper::KeyComp<CostMap>(_cost));
+
+        FullGraph::NodeMap<int> nodemap(_gr);
+        Union unionfind(nodemap);
+
+        for (NodeIt n(_gr); n != INVALID; ++n)
+          unionfind.insert(n);
+        
+        FullGraph::NodeMap<int> degree(_gr, 0);
+
+        int nodesNum = 0, i = 0;
+
+        while ( nodesNum != _gr.nodeNum()-1 ) {
+          const Edge &e = sorted_edges[i];
+          
+          const Node u = _gr.u(e),
+                     v = _gr.v(e);
+          
+          if (degree[u]<=1 && degree[v]<=1) {
+            if (unionfind.join(u, v)) {
+              ++degree[u];
+              ++degree[v];
+              ++nodesNum;
+              
+              const int uid = _gr.id(u),
+                        vid = _gr.id(v);
+              
+              
+              path[uid*2 + (path[uid*2]==-1 ? 0 : 1)] = vid;
+              path[vid*2 + (path[vid*2]==-1 ? 0 : 1)] = uid;
+            }
+          }
+
+          ++i;
+        }
+
+
+        for (int i=0, n=-1; i<_gr.nodeNum()*2; ++i) {
+          if (path[i] == -1) {
+            if (n==-1) {
+              n = i;
+            } else {
+              path[n] = i/2;
+              path[i] = n/2;
+              break;
+            }
+          }
+        }
+
+
+        for (int i=0, j=0, last=-1; i!=_gr.nodeNum(); ++i) {
+          _nodes.push_back(_gr.nodeFromId(j));
+          
+          if (path[2*j] != last) {
+            last = j;
+            j = path[2*j];
+          } else {
+            last = j;
+            j = path[2*j+1];
+          }
+        }
+
+        _sum = _cost[_gr.edge(_nodes.back(), _nodes.front())];
+        for (unsigned int i=0; i<_nodes.size()-1; ++i)



More information about the Lemon-commits mailing list