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