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