lemon/greedy_tsp.h
author Gabor Varga <f4c3@inf.elte.hu>
Sat, 08 Jan 2011 21:59:56 +0100
changeset 1199 ae0b056593a7
child 1201 9a51db038228
permissions -rw-r--r--
Heuristic algorithms for symmetric TSP (#386)
f4c3@1199
     1
#ifndef LEMON_GREEDY_TSP_H
f4c3@1199
     2
#define LEMON_GREEDY_TSP_H
f4c3@1199
     3
f4c3@1199
     4
#include <lemon/path.h>
f4c3@1199
     5
#include <lemon/full_graph.h>
f4c3@1199
     6
#include <lemon/unionfind.h>
f4c3@1199
     7
#include <algorithm>
f4c3@1199
     8
f4c3@1199
     9
namespace lemon {
f4c3@1199
    10
f4c3@1199
    11
  namespace greedy_tsp_helper {
f4c3@1199
    12
f4c3@1199
    13
    template <typename CostMap>
f4c3@1199
    14
    class KeyComp {
f4c3@1199
    15
      typedef typename CostMap::Key Key;
f4c3@1199
    16
      const CostMap &cost;
f4c3@1199
    17
      
f4c3@1199
    18
      public:
f4c3@1199
    19
        KeyComp(const CostMap &_cost) : cost(_cost) {}
f4c3@1199
    20
      
f4c3@1199
    21
        bool operator() (const Key &a, const Key &b) const {
f4c3@1199
    22
          return cost[a] < cost[b];
f4c3@1199
    23
        }
f4c3@1199
    24
    };
f4c3@1199
    25
f4c3@1199
    26
  
f4c3@1199
    27
    template <class L>
f4c3@1199
    28
    L vectorConvert(const std::vector<FullGraph::Node> &_path) {
f4c3@1199
    29
      return L(_path.begin(), _path.end());
f4c3@1199
    30
    }
f4c3@1199
    31
  
f4c3@1199
    32
    template <>
f4c3@1199
    33
    std::vector<FullGraph::Node> vectorConvert(const std::vector<FullGraph::Node> &_path) {
f4c3@1199
    34
      return _path;
f4c3@1199
    35
    }
f4c3@1199
    36
    
f4c3@1199
    37
  }
f4c3@1199
    38
f4c3@1199
    39
f4c3@1199
    40
  template <typename CM>
f4c3@1199
    41
  class GreedyTsp {
f4c3@1199
    42
    private:
f4c3@1199
    43
      GRAPH_TYPEDEFS(FullGraph);
f4c3@1199
    44
    
f4c3@1199
    45
    public:
f4c3@1199
    46
      typedef CM CostMap;
f4c3@1199
    47
      typedef typename CM::Value Cost;
f4c3@1199
    48
      
f4c3@1199
    49
      GreedyTsp(const FullGraph &gr, const CostMap &cost) : _gr(gr), _cost(cost) {}  
f4c3@1199
    50
f4c3@1199
    51
      Cost run() {
f4c3@1199
    52
        typedef UnionFind<FullGraph::NodeMap<int> > Union;
f4c3@1199
    53
        _nodes.clear();
f4c3@1199
    54
        
f4c3@1199
    55
        std::vector<int> path;
f4c3@1199
    56
        path.resize(_gr.nodeNum()*2, -1);
f4c3@1199
    57
        
f4c3@1199
    58
        std::vector<typename CostMap::Key> sorted_edges;
f4c3@1199
    59
        sorted_edges.reserve(_gr.edgeNum());
f4c3@1199
    60
        for (EdgeIt n(_gr); n != INVALID; ++n)
f4c3@1199
    61
          sorted_edges.push_back(n);
f4c3@1199
    62
f4c3@1199
    63
        std::sort(sorted_edges.begin(), sorted_edges.end(), greedy_tsp_helper::KeyComp<CostMap>(_cost));
f4c3@1199
    64
f4c3@1199
    65
        FullGraph::NodeMap<int> nodemap(_gr);
f4c3@1199
    66
        Union unionfind(nodemap);
f4c3@1199
    67
f4c3@1199
    68
        for (NodeIt n(_gr); n != INVALID; ++n)
f4c3@1199
    69
          unionfind.insert(n);
f4c3@1199
    70
        
f4c3@1199
    71
        FullGraph::NodeMap<int> degree(_gr, 0);
f4c3@1199
    72
f4c3@1199
    73
        int nodesNum = 0, i = 0;
f4c3@1199
    74
f4c3@1199
    75
        while ( nodesNum != _gr.nodeNum()-1 ) {
f4c3@1199
    76
          const Edge &e = sorted_edges[i];
f4c3@1199
    77
          
f4c3@1199
    78
          const Node u = _gr.u(e),
f4c3@1199
    79
                     v = _gr.v(e);
f4c3@1199
    80
          
f4c3@1199
    81
          if (degree[u]<=1 && degree[v]<=1) {
f4c3@1199
    82
            if (unionfind.join(u, v)) {
f4c3@1199
    83
              ++degree[u];
f4c3@1199
    84
              ++degree[v];
f4c3@1199
    85
              ++nodesNum;
f4c3@1199
    86
              
f4c3@1199
    87
              const int uid = _gr.id(u),
f4c3@1199
    88
                        vid = _gr.id(v);
f4c3@1199
    89
              
f4c3@1199
    90
              
f4c3@1199
    91
              path[uid*2 + (path[uid*2]==-1 ? 0 : 1)] = vid;
f4c3@1199
    92
              path[vid*2 + (path[vid*2]==-1 ? 0 : 1)] = uid;
f4c3@1199
    93
            }
f4c3@1199
    94
          }
f4c3@1199
    95
f4c3@1199
    96
          ++i;
f4c3@1199
    97
        }
f4c3@1199
    98
f4c3@1199
    99
f4c3@1199
   100
        for (int i=0, n=-1; i<_gr.nodeNum()*2; ++i) {
f4c3@1199
   101
          if (path[i] == -1) {
f4c3@1199
   102
            if (n==-1) {
f4c3@1199
   103
              n = i;
f4c3@1199
   104
            } else {
f4c3@1199
   105
              path[n] = i/2;
f4c3@1199
   106
              path[i] = n/2;
f4c3@1199
   107
              break;
f4c3@1199
   108
            }
f4c3@1199
   109
          }
f4c3@1199
   110
        }
f4c3@1199
   111
f4c3@1199
   112
f4c3@1199
   113
        for (int i=0, j=0, last=-1; i!=_gr.nodeNum(); ++i) {
f4c3@1199
   114
          _nodes.push_back(_gr.nodeFromId(j));
f4c3@1199
   115
          
f4c3@1199
   116
          if (path[2*j] != last) {
f4c3@1199
   117
            last = j;
f4c3@1199
   118
            j = path[2*j];
f4c3@1199
   119
          } else {
f4c3@1199
   120
            last = j;
f4c3@1199
   121
            j = path[2*j+1];
f4c3@1199
   122
          }
f4c3@1199
   123
        }
f4c3@1199
   124
f4c3@1199
   125
        _sum = _cost[_gr.edge(_nodes.back(), _nodes.front())];
f4c3@1199
   126
        for (unsigned int i=0; i<_nodes.size()-1; ++i)
f4c3@1199
   127
          _sum += _cost[_gr.edge(_nodes[i], _nodes[i+1])];
f4c3@1199
   128
f4c3@1199
   129
        return _sum;
f4c3@1199
   130
      }
f4c3@1199
   131
f4c3@1199
   132
f4c3@1199
   133
f4c3@1199
   134
      template <typename L>
f4c3@1199
   135
      void tourNodes(L &container) {
f4c3@1199
   136
        container(greedy_tsp_helper::vectorConvert<L>(_nodes));
f4c3@1199
   137
      }
f4c3@1199
   138
      
f4c3@1199
   139
      template <template <typename> class L>
f4c3@1199
   140
      L<Node> tourNodes() {
f4c3@1199
   141
        return greedy_tsp_helper::vectorConvert<L<Node> >(_nodes);
f4c3@1199
   142
      }
f4c3@1199
   143
      
f4c3@1199
   144
      const std::vector<Node>& tourNodes() {
f4c3@1199
   145
        return _nodes;
f4c3@1199
   146
      }
f4c3@1199
   147
      
f4c3@1199
   148
      Path<FullGraph> tour() {
f4c3@1199
   149
        Path<FullGraph> p;
f4c3@1199
   150
        if (_nodes.size()<2)
f4c3@1199
   151
          return p;
f4c3@1199
   152
        
f4c3@1199
   153
        for (unsigned int i=0; i<_nodes.size()-1; ++i) {
f4c3@1199
   154
          p.addBack(_gr.arc(_nodes[i], _nodes[i+1]));
f4c3@1199
   155
        }
f4c3@1199
   156
        
f4c3@1199
   157
        p.addBack(_gr.arc(_nodes.back(), _nodes.front()));
f4c3@1199
   158
        
f4c3@1199
   159
        return p;
f4c3@1199
   160
      }
f4c3@1199
   161
      
f4c3@1199
   162
      Cost tourCost() {
f4c3@1199
   163
        return _sum;
f4c3@1199
   164
      }
f4c3@1199
   165
      
f4c3@1199
   166
f4c3@1199
   167
    private:
f4c3@1199
   168
      const FullGraph &_gr;
f4c3@1199
   169
      const CostMap &_cost;
f4c3@1199
   170
      Cost _sum;
f4c3@1199
   171
      std::vector<Node> _nodes;
f4c3@1199
   172
  };
f4c3@1199
   173
f4c3@1199
   174
}; // namespace lemon
f4c3@1199
   175
f4c3@1199
   176
#endif