lemon/insertion_tsp.h
author Gabor Varga <f4c3@inf.elte.hu>
Sat, 08 Jan 2011 21:59:56 +0100
changeset 1031 ae0b056593a7
child 1033 9a51db038228
permissions -rw-r--r--
Heuristic algorithms for symmetric TSP (#386)
f4c3@1031
     1
#ifndef LEMON_INSERTION_TSP_H
f4c3@1031
     2
#define LEMON_INSERTION_TSP_H
f4c3@1031
     3
f4c3@1031
     4
#include <lemon/full_graph.h>
f4c3@1031
     5
#include <lemon/path.h>
f4c3@1031
     6
#include <lemon/maps.h>
f4c3@1031
     7
#include <lemon/random.h>
f4c3@1031
     8
#include <vector>
f4c3@1031
     9
f4c3@1031
    10
namespace lemon {
f4c3@1031
    11
f4c3@1031
    12
  namespace insertion_tsp_helper {
f4c3@1031
    13
  
f4c3@1031
    14
    template <class L>
f4c3@1031
    15
    L vectorConvert(const std::vector<FullGraph::Node> &_path) {
f4c3@1031
    16
      return L(_path.begin(), _path.end());
f4c3@1031
    17
    };
f4c3@1031
    18
  
f4c3@1031
    19
    template <>
f4c3@1031
    20
    std::vector<FullGraph::Node> vectorConvert(
f4c3@1031
    21
        const std::vector<FullGraph::Node> &_path) {
f4c3@1031
    22
      return _path;
f4c3@1031
    23
    };
f4c3@1031
    24
    
f4c3@1031
    25
  };
f4c3@1031
    26
f4c3@1031
    27
  template <typename CM>
f4c3@1031
    28
  class InsertionTsp {
f4c3@1031
    29
    private:
f4c3@1031
    30
      GRAPH_TYPEDEFS(FullGraph);
f4c3@1031
    31
f4c3@1031
    32
    public:      
f4c3@1031
    33
      typedef CM CostMap;
f4c3@1031
    34
      typedef typename CM::Value Cost;
f4c3@1031
    35
      
f4c3@1031
    36
      InsertionTsp(const FullGraph &gr, const CostMap &cost) : 
f4c3@1031
    37
            _gr(gr), _cost(cost) {}
f4c3@1031
    38
      
f4c3@1031
    39
      enum InsertionMethod {
f4c3@1031
    40
        INSERT_NEAREST,
f4c3@1031
    41
        INSERT_FARTHEST,
f4c3@1031
    42
        INSERT_CHEAPEST,
f4c3@1031
    43
        INSERT_RANDOM
f4c3@1031
    44
      };     
f4c3@1031
    45
      
f4c3@1031
    46
      Cost run(InsertionMethod method = INSERT_FARTHEST) {
f4c3@1031
    47
        switch (method) {
f4c3@1031
    48
          case INSERT_NEAREST:
f4c3@1031
    49
            start<InitTour<true>, NearestSelection, DefaultInsert>();
f4c3@1031
    50
            break;
f4c3@1031
    51
          case INSERT_FARTHEST:
f4c3@1031
    52
            start<InitTour<false>, FarthestSelection, DefaultInsert>();
f4c3@1031
    53
            break;
f4c3@1031
    54
          case INSERT_CHEAPEST:
f4c3@1031
    55
            start<InitTour<true>, CheapestSelection, CheapestInsert>();
f4c3@1031
    56
            break;
f4c3@1031
    57
          case INSERT_RANDOM:
f4c3@1031
    58
            start<InitTour<true>, RandomSelection, DefaultInsert>();
f4c3@1031
    59
            break;
f4c3@1031
    60
        }
f4c3@1031
    61
        return sum;
f4c3@1031
    62
      }
f4c3@1031
    63
f4c3@1031
    64
      template <typename L>
f4c3@1031
    65
      void tourNodes(L &container) {
f4c3@1031
    66
        container(insertion_tsp_helper::vectorConvert<L>(nodesPath));
f4c3@1031
    67
      }
f4c3@1031
    68
      
f4c3@1031
    69
      template <template <typename> class L>
f4c3@1031
    70
      L<Node> tourNodes() {
f4c3@1031
    71
        return insertion_tsp_helper::vectorConvert<L<Node> >(nodesPath);
f4c3@1031
    72
      }
f4c3@1031
    73
      
f4c3@1031
    74
      const std::vector<Node>& tourNodes() {
f4c3@1031
    75
        return nodesPath;
f4c3@1031
    76
      }
f4c3@1031
    77
      
f4c3@1031
    78
      Path<FullGraph> tour() {
f4c3@1031
    79
        Path<FullGraph> p;
f4c3@1031
    80
        if (nodesPath.size()<2)
f4c3@1031
    81
          return p;
f4c3@1031
    82
        
f4c3@1031
    83
        for (unsigned int i=0; i<nodesPath.size()-1; ++i)
f4c3@1031
    84
          p.addBack(_gr.arc(nodesPath[i], nodesPath[i+1]));
f4c3@1031
    85
        
f4c3@1031
    86
        p.addBack(_gr.arc(nodesPath.back(), nodesPath.front()));
f4c3@1031
    87
        return p;
f4c3@1031
    88
      }
f4c3@1031
    89
      
f4c3@1031
    90
      Cost tourCost() {
f4c3@1031
    91
        return sum;
f4c3@1031
    92
      }
f4c3@1031
    93
f4c3@1031
    94
f4c3@1031
    95
    private:
f4c3@1031
    96
f4c3@1031
    97
      template <bool MIN>
f4c3@1031
    98
      class InitTour {
f4c3@1031
    99
        public:
f4c3@1031
   100
          InitTour(const FullGraph &gr, const CostMap &cost,
f4c3@1031
   101
                   std::vector<Node> &used, std::vector<Node> &notused,
f4c3@1031
   102
                   Cost &fullcost) :
f4c3@1031
   103
              _gr(gr), _cost(cost), _used(used), _notused(notused),
f4c3@1031
   104
              _fullcost(fullcost) {}
f4c3@1031
   105
f4c3@1031
   106
          std::vector<Node> init() const {
f4c3@1031
   107
            Edge min = (MIN) ? mapMin(_gr, _cost) : mapMax(_gr, _cost);
f4c3@1031
   108
            std::vector<Node> path;
f4c3@1031
   109
            path.push_back(_gr.u(min));
f4c3@1031
   110
            path.push_back(_gr.v(min));
f4c3@1031
   111
            
f4c3@1031
   112
            _used.clear();
f4c3@1031
   113
            _notused.clear();
f4c3@1031
   114
            for (NodeIt n(_gr); n!=INVALID; ++n) {
f4c3@1031
   115
              if (n != _gr.u(min) && n != _gr.v(min)) {
f4c3@1031
   116
                _notused.push_back(n);
f4c3@1031
   117
              }
f4c3@1031
   118
            }
f4c3@1031
   119
            _used.push_back(_gr.u(min));
f4c3@1031
   120
            _used.push_back(_gr.v(min));
f4c3@1031
   121
            
f4c3@1031
   122
            _fullcost = _cost[min]*2;
f4c3@1031
   123
            return path;
f4c3@1031
   124
          }
f4c3@1031
   125
f4c3@1031
   126
        private:
f4c3@1031
   127
          const FullGraph &_gr;
f4c3@1031
   128
          const CostMap &_cost;
f4c3@1031
   129
          std::vector<Node> &_used;
f4c3@1031
   130
          std::vector<Node> &_notused;
f4c3@1031
   131
          Cost &_fullcost;
f4c3@1031
   132
      };
f4c3@1031
   133
f4c3@1031
   134
      class NearestSelection {
f4c3@1031
   135
        public:
f4c3@1031
   136
          NearestSelection(const FullGraph &gr, const CostMap &cost,
f4c3@1031
   137
                           std::vector<Node> &used, std::vector<Node> &notused) : 
f4c3@1031
   138
              _gr(gr), _cost(cost), _used(used), _notused(notused) {}
f4c3@1031
   139
      
f4c3@1031
   140
          Node select() const {
f4c3@1031
   141
f4c3@1031
   142
            Cost insert_val =
f4c3@1031
   143
              std::numeric_limits<Cost>::max();
f4c3@1031
   144
            int insert_node = -1;
f4c3@1031
   145
            
f4c3@1031
   146
            for (unsigned int i=0; i<_notused.size(); ++i) {
f4c3@1031
   147
              Cost min_val = _cost[_gr.edge(_notused[i], _used[0])];
f4c3@1031
   148
              int min_node = 0;
f4c3@1031
   149
            
f4c3@1031
   150
              for (unsigned int j=1; j<_used.size(); ++j) {
f4c3@1031
   151
                if (min_val > _cost[_gr.edge(_notused[i], _used[j])]) {
f4c3@1031
   152
                    min_val = _cost[_gr.edge(_notused[i], _used[j])];
f4c3@1031
   153
                    min_node = j;
f4c3@1031
   154
                }
f4c3@1031
   155
              }
f4c3@1031
   156
              
f4c3@1031
   157
              if (insert_val > min_val) {
f4c3@1031
   158
                insert_val = min_val;
f4c3@1031
   159
                insert_node = i;
f4c3@1031
   160
              }
f4c3@1031
   161
            }
f4c3@1031
   162
            
f4c3@1031
   163
            Node n = _notused[insert_node];
f4c3@1031
   164
            _notused.erase(_notused.begin()+insert_node);
f4c3@1031
   165
            
f4c3@1031
   166
            return n;
f4c3@1031
   167
          }
f4c3@1031
   168
          
f4c3@1031
   169
        private:
f4c3@1031
   170
          const FullGraph &_gr;
f4c3@1031
   171
          const CostMap &_cost;
f4c3@1031
   172
          std::vector<Node> &_used;
f4c3@1031
   173
          std::vector<Node> &_notused;
f4c3@1031
   174
      };
f4c3@1031
   175
f4c3@1031
   176
      class FarthestSelection {
f4c3@1031
   177
        public:
f4c3@1031
   178
          FarthestSelection(const FullGraph &gr, const CostMap &cost,
f4c3@1031
   179
                            std::vector<Node> &used, std::vector<Node> &notused) : 
f4c3@1031
   180
              _gr(gr), _cost(cost), _used(used), _notused(notused) {}
f4c3@1031
   181
      
f4c3@1031
   182
          Node select() const {
f4c3@1031
   183
f4c3@1031
   184
            Cost insert_val =
f4c3@1031
   185
              std::numeric_limits<Cost>::min();
f4c3@1031
   186
            int insert_node = -1;
f4c3@1031
   187
            
f4c3@1031
   188
            for (unsigned int i=0; i<_notused.size(); ++i) {
f4c3@1031
   189
              Cost min_val = _cost[_gr.edge(_notused[i], _used[0])];
f4c3@1031
   190
              int min_node = 0;
f4c3@1031
   191
              
f4c3@1031
   192
              for (unsigned int j=1; j<_used.size(); ++j) {
f4c3@1031
   193
                if (min_val > _cost[_gr.edge(_notused[i], _used[j])]) {
f4c3@1031
   194
                  min_val = _cost[_gr.edge(_notused[i], _used[j])];
f4c3@1031
   195
                  min_node = j;
f4c3@1031
   196
                }
f4c3@1031
   197
              }
f4c3@1031
   198
              
f4c3@1031
   199
              if (insert_val < min_val || insert_node == -1) {
f4c3@1031
   200
                insert_val = min_val;
f4c3@1031
   201
                insert_node = i;
f4c3@1031
   202
              }
f4c3@1031
   203
            }
f4c3@1031
   204
            
f4c3@1031
   205
            Node n = _notused[insert_node];
f4c3@1031
   206
            _notused.erase(_notused.begin()+insert_node);
f4c3@1031
   207
            
f4c3@1031
   208
            return n;
f4c3@1031
   209
          }
f4c3@1031
   210
          
f4c3@1031
   211
        private:
f4c3@1031
   212
          const FullGraph &_gr;
f4c3@1031
   213
          const CostMap &_cost;
f4c3@1031
   214
          std::vector<Node> &_used;
f4c3@1031
   215
          std::vector<Node> &_notused;
f4c3@1031
   216
      };
f4c3@1031
   217
f4c3@1031
   218
f4c3@1031
   219
      class CheapestSelection {
f4c3@1031
   220
        private:
f4c3@1031
   221
          Cost costDiff(Node u, Node v, Node w) const {
f4c3@1031
   222
            return 
f4c3@1031
   223
              _cost[_gr.edge(u, w)] +
f4c3@1031
   224
              _cost[_gr.edge(v, w)] -
f4c3@1031
   225
              _cost[_gr.edge(u, v)];
f4c3@1031
   226
          }
f4c3@1031
   227
f4c3@1031
   228
        public:
f4c3@1031
   229
          CheapestSelection(const FullGraph &gr, const CostMap &cost,
f4c3@1031
   230
                            std::vector<Node> &used, std::vector<Node> &notused) : 
f4c3@1031
   231
              _gr(gr), _cost(cost), _used(used), _notused(notused) {}
f4c3@1031
   232
        
f4c3@1031
   233
          Cost select() const {
f4c3@1031
   234
            int insert_notused = -1;
f4c3@1031
   235
            int best_insert_index = -1;
f4c3@1031
   236
            Cost insert_val =
f4c3@1031
   237
              std::numeric_limits<Cost>::max();
f4c3@1031
   238
            
f4c3@1031
   239
            for (unsigned int i=0; i<_notused.size(); ++i) {
f4c3@1031
   240
              int min = i;
f4c3@1031
   241
              int best_insert_tmp = 0;
f4c3@1031
   242
              Cost min_val =
f4c3@1031
   243
                costDiff(_used.front(), _used.back(), _notused[i]);
f4c3@1031
   244
              
f4c3@1031
   245
              for (unsigned int j=1; j<_used.size(); ++j) {
f4c3@1031
   246
                Cost tmp =
f4c3@1031
   247
                  costDiff(_used[j-1], _used[j], _notused[i]);
f4c3@1031
   248
f4c3@1031
   249
                if (min_val > tmp) {
f4c3@1031
   250
                  min = i;
f4c3@1031
   251
                  min_val = tmp;
f4c3@1031
   252
                  best_insert_tmp = j;
f4c3@1031
   253
                }
f4c3@1031
   254
              }
f4c3@1031
   255
f4c3@1031
   256
              if (insert_val > min_val) {
f4c3@1031
   257
                insert_notused = min;
f4c3@1031
   258
                insert_val = min_val;
f4c3@1031
   259
                best_insert_index = best_insert_tmp;
f4c3@1031
   260
              }
f4c3@1031
   261
            }
f4c3@1031
   262
f4c3@1031
   263
            _used.insert(_used.begin()+best_insert_index, _notused[insert_notused]);
f4c3@1031
   264
            _notused.erase(_notused.begin()+insert_notused);
f4c3@1031
   265
f4c3@1031
   266
            return insert_val;
f4c3@1031
   267
          }
f4c3@1031
   268
          
f4c3@1031
   269
        private:
f4c3@1031
   270
          const FullGraph &_gr;
f4c3@1031
   271
          const CostMap &_cost;
f4c3@1031
   272
          std::vector<Node> &_used;
f4c3@1031
   273
          std::vector<Node> &_notused;
f4c3@1031
   274
      };
f4c3@1031
   275
f4c3@1031
   276
      class RandomSelection {
f4c3@1031
   277
        public:
f4c3@1031
   278
          RandomSelection(const FullGraph &, const CostMap &,
f4c3@1031
   279
                            std::vector<Node> &, std::vector<Node> &notused) : 
f4c3@1031
   280
                           _notused(notused) {
f4c3@1031
   281
            rnd.seedFromTime();
f4c3@1031
   282
          }
f4c3@1031
   283
          
f4c3@1031
   284
          Node select() const {
f4c3@1031
   285
            const int index = rnd[_notused.size()];
f4c3@1031
   286
            Node n = _notused[index];
f4c3@1031
   287
            _notused.erase(_notused.begin()+index);
f4c3@1031
   288
            return n;
f4c3@1031
   289
          }
f4c3@1031
   290
        private:
f4c3@1031
   291
          std::vector<Node> &_notused;
f4c3@1031
   292
      };
f4c3@1031
   293
f4c3@1031
   294
f4c3@1031
   295
      class DefaultInsert {
f4c3@1031
   296
        private:
f4c3@1031
   297
          Cost costDiff(Node u, Node v, Node w) const {
f4c3@1031
   298
            return 
f4c3@1031
   299
              _cost[_gr.edge(u, w)] +
f4c3@1031
   300
              _cost[_gr.edge(v, w)] -
f4c3@1031
   301
              _cost[_gr.edge(u, v)];
f4c3@1031
   302
          }
f4c3@1031
   303
  
f4c3@1031
   304
        public:
f4c3@1031
   305
          DefaultInsert(const FullGraph &gr, const CostMap &cost,
f4c3@1031
   306
                        std::vector<Node> &path, Cost &fullcost) : 
f4c3@1031
   307
            _gr(gr), _cost(cost), _path(path), _fullcost(fullcost) {}
f4c3@1031
   308
          
f4c3@1031
   309
          void insert(Node n) const {
f4c3@1031
   310
            int min = 0;
f4c3@1031
   311
            Cost min_val =
f4c3@1031
   312
              costDiff(_path.front(), _path.back(), n);
f4c3@1031
   313
            
f4c3@1031
   314
            for (unsigned int i=1; i<_path.size(); ++i) {
f4c3@1031
   315
              Cost tmp = costDiff(_path[i-1], _path[i], n);
f4c3@1031
   316
              if (tmp < min_val) {
f4c3@1031
   317
                min = i;
f4c3@1031
   318
                min_val = tmp;
f4c3@1031
   319
              }
f4c3@1031
   320
            }
f4c3@1031
   321
            
f4c3@1031
   322
            _path.insert(_path.begin()+min, n);
f4c3@1031
   323
            _fullcost += min_val;
f4c3@1031
   324
          }
f4c3@1031
   325
        
f4c3@1031
   326
        private:
f4c3@1031
   327
          const FullGraph &_gr;
f4c3@1031
   328
          const CostMap &_cost;
f4c3@1031
   329
          std::vector<Node> &_path;
f4c3@1031
   330
          Cost &_fullcost;
f4c3@1031
   331
      };
f4c3@1031
   332
  
f4c3@1031
   333
      class CheapestInsert {
f4c3@1031
   334
        TEMPLATE_GRAPH_TYPEDEFS(FullGraph);
f4c3@1031
   335
        public:
f4c3@1031
   336
          CheapestInsert(const FullGraph &, const CostMap &,
f4c3@1031
   337
                         std::vector<Node> &, Cost &fullcost) : 
f4c3@1031
   338
            _fullcost(fullcost) {}
f4c3@1031
   339
          
f4c3@1031
   340
          void insert(Cost diff) const {
f4c3@1031
   341
            _fullcost += diff;
f4c3@1031
   342
          }
f4c3@1031
   343
f4c3@1031
   344
        private:
f4c3@1031
   345
          Cost &_fullcost;
f4c3@1031
   346
      };  
f4c3@1031
   347
      
f4c3@1031
   348
      
f4c3@1031
   349
      template <class InitFunctor, class SelectionFunctor, class InsertFunctor>
f4c3@1031
   350
      void start() {
f4c3@1031
   351
        InitFunctor init(_gr, _cost, nodesPath, notused, sum);
f4c3@1031
   352
        SelectionFunctor selectNode(_gr, _cost, nodesPath, notused);
f4c3@1031
   353
        InsertFunctor insertNode(_gr, _cost, nodesPath, sum);
f4c3@1031
   354
        
f4c3@1031
   355
        nodesPath = init.init();
f4c3@1031
   356
        
f4c3@1031
   357
        for (int i=0; i<_gr.nodeNum()-2; ++i) {
f4c3@1031
   358
          insertNode.insert(selectNode.select());
f4c3@1031
   359
        }
f4c3@1031
   360
        
f4c3@1031
   361
        sum = _cost[ _gr.edge(nodesPath.front(), nodesPath.back()) ];
f4c3@1031
   362
        for (unsigned int i=0; i<nodesPath.size()-1; ++i)
f4c3@1031
   363
          sum += _cost[ _gr.edge(nodesPath[i], nodesPath[i+1]) ];
f4c3@1031
   364
      }
f4c3@1031
   365
    
f4c3@1031
   366
      const FullGraph &_gr;
f4c3@1031
   367
      const CostMap &_cost;
f4c3@1031
   368
      std::vector<Node> notused;
f4c3@1031
   369
      std::vector<Node> nodesPath;
f4c3@1031
   370
      Cost sum;
f4c3@1031
   371
  };
f4c3@1031
   372
  
f4c3@1031
   373
}; // namespace lemon
f4c3@1031
   374
f4c3@1031
   375
#endif