COIN-OR::LEMON - Graph Library

Ticket #386: 386-tsp-7ed08f6da055.patch

File 386-tsp-7ed08f6da055.patch, 29.8 KB (added by Peter Kovacs, 10 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  
    6464        lemon/bucket_heap.h \
    6565        lemon/capacity_scaling.h \
    6666        lemon/cbc.h \
     67        lemon/christofides_tsp.h \
    6768        lemon/circulation.h \
    6869        lemon/clp.h \
    6970        lemon/color.h \
     
    8990        lemon/glpk.h \
    9091        lemon/gomory_hu.h \
    9192        lemon/graph_to_eps.h \
     93        lemon/greedy_tsp.h \
    9294        lemon/grid_graph.h \
    9395        lemon/hartmann_orlin_mmc.h \
    9496        lemon/howard_mmc.h \
    9597        lemon/hypercube_graph.h \
     98        lemon/insertion_tsp.h \
    9699        lemon/karp_mmc.h \
    97100        lemon/kruskal.h \
    98101        lemon/hao_orlin.h \
     
    107110        lemon/math.h \
    108111        lemon/min_cost_arborescence.h \
    109112        lemon/nauty_reader.h \
     113        lemon/nearest_neighbor_tsp.h \
    110114        lemon/network_simplex.h \
     115        lemon/opt2_tsp.h \
    111116        lemon/pairing_heap.h \
    112117        lemon/path.h \
    113118        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
     14namespace 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
     10namespace 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
     11namespace 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> &notused,
     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> &notused) :
     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> &notused) :
     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> &notused) :
     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[j-1], _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> &notused) :
     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[i-1], _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
     10namespace 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
     9namespace 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] = i-1;
     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[i-1]);
     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
     125opt2_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