lemon/insertion_tsp.h
author Peter Kovacs <kpeter@inf.elte.hu>
Sat, 08 Jan 2011 22:51:16 +0100
changeset 1201 9a51db038228
parent 1199 ae0b056593a7
child 1202 ef200e268af2
permissions -rw-r--r--
Document and greatly improve TSP algorithms (#386)

- Add LEMON headers.
- Add Doxygen doc for all classes and their members.
- Clarify and unify the public API of the algorithms.
- Various small improvements in the implementations to make
them clearer and faster.
- Avoid using adaptors in ChristofidesTsp.
kpeter@1201
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
kpeter@1201
     2
 *
kpeter@1201
     3
 * This file is a part of LEMON, a generic C++ optimization library.
kpeter@1201
     4
 *
kpeter@1201
     5
 * Copyright (C) 2003-2010
kpeter@1201
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
kpeter@1201
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
kpeter@1201
     8
 *
kpeter@1201
     9
 * Permission to use, modify and distribute this software is granted
kpeter@1201
    10
 * provided that this copyright notice appears in all copies. For
kpeter@1201
    11
 * precise terms see the accompanying LICENSE file.
kpeter@1201
    12
 *
kpeter@1201
    13
 * This software is provided "AS IS" with no warranty of any kind,
kpeter@1201
    14
 * express or implied, and with no claim as to its suitability for any
kpeter@1201
    15
 * purpose.
kpeter@1201
    16
 *
kpeter@1201
    17
 */
kpeter@1201
    18
f4c3@1199
    19
#ifndef LEMON_INSERTION_TSP_H
f4c3@1199
    20
#define LEMON_INSERTION_TSP_H
f4c3@1199
    21
kpeter@1201
    22
/// \ingroup tsp
kpeter@1201
    23
/// \file
kpeter@1201
    24
/// \brief Insertion algorithm for symmetric TSP
kpeter@1201
    25
kpeter@1201
    26
#include <vector>
f4c3@1199
    27
#include <lemon/full_graph.h>
f4c3@1199
    28
#include <lemon/maps.h>
f4c3@1199
    29
#include <lemon/random.h>
f4c3@1199
    30
f4c3@1199
    31
namespace lemon {
f4c3@1199
    32
kpeter@1201
    33
  /// \brief Insertion algorithm for symmetric TSP.
kpeter@1201
    34
  ///
kpeter@1201
    35
  /// InsertionTsp implements the insertion heuristic for solving
kpeter@1201
    36
  /// symmetric \ref tsp "TSP".
kpeter@1201
    37
  ///
kpeter@1201
    38
  /// This is a basic TSP heuristic that has many variants.
kpeter@1201
    39
  /// It starts with a subtour containing a few nodes of the graph and it
kpeter@1201
    40
  /// iteratively inserts the other nodes into this subtour according to a
kpeter@1201
    41
  /// certain node selection rule.
kpeter@1201
    42
  ///
kpeter@1201
    43
  /// This implementation provides four different node selection rules,
kpeter@1201
    44
  /// from which the most powerful one is used by default.
kpeter@1201
    45
  /// For more information, see \ref SelectionRule.
kpeter@1201
    46
  ///
kpeter@1201
    47
  /// \tparam CM Type of the cost map.
kpeter@1201
    48
  template <typename CM>
kpeter@1201
    49
  class InsertionTsp
kpeter@1201
    50
  {
kpeter@1201
    51
    public:
f4c3@1199
    52
kpeter@1201
    53
      /// Type of the cost map
f4c3@1199
    54
      typedef CM CostMap;
kpeter@1201
    55
      /// Type of the edge costs
f4c3@1199
    56
      typedef typename CM::Value Cost;
f4c3@1199
    57
f4c3@1199
    58
    private:
f4c3@1199
    59
kpeter@1201
    60
      GRAPH_TYPEDEFS(FullGraph);
kpeter@1201
    61
kpeter@1201
    62
      const FullGraph &_gr;
kpeter@1201
    63
      const CostMap &_cost;
kpeter@1201
    64
      std::vector<Node> _notused;
kpeter@1201
    65
      std::vector<Node> _path;
kpeter@1201
    66
      Cost _sum;
kpeter@1201
    67
kpeter@1201
    68
    public:
kpeter@1201
    69
kpeter@1201
    70
      /// \brief Constants for specifying the node selection rule.
kpeter@1201
    71
      ///
kpeter@1201
    72
      /// Enum type containing constants for specifying the node selection
kpeter@1201
    73
      /// rule for the \ref run() function.
kpeter@1201
    74
      ///
kpeter@1201
    75
      /// During the algorithm, nodes are selected for addition to the current
kpeter@1201
    76
      /// subtour according to the applied rule.
kpeter@1201
    77
      /// In general, the FARTHEST yields the best tours, thus it is the
kpeter@1201
    78
      /// default option. RANDOM usually gives somewhat worse results, but
kpeter@1201
    79
      /// it is much faster than the others and it is the most robust.
kpeter@1201
    80
      ///
kpeter@1201
    81
      /// The desired selection rule can be specified as a parameter of the
kpeter@1201
    82
      /// \ref run() function.
kpeter@1201
    83
      enum SelectionRule {
kpeter@1201
    84
kpeter@1201
    85
        /// An unvisited node having minimum distance from the current
kpeter@1201
    86
        /// subtour is selected at each step.
kpeter@1201
    87
        /// The algorithm runs in O(n<sup>3</sup>) time using this
kpeter@1201
    88
        /// selection rule.
kpeter@1201
    89
        NEAREST,
kpeter@1201
    90
kpeter@1201
    91
        /// An unvisited node having maximum distance from the current
kpeter@1201
    92
        /// subtour is selected at each step.
kpeter@1201
    93
        /// The algorithm runs in O(n<sup>3</sup>) time using this
kpeter@1201
    94
        /// selection rule.
kpeter@1201
    95
        FARTHEST,
kpeter@1201
    96
kpeter@1201
    97
        /// An unvisited node whose insertion results in the least
kpeter@1201
    98
        /// increase of the subtour's total cost is selected at each step.
kpeter@1201
    99
        /// The algorithm runs in O(n<sup>3</sup>) time using this
kpeter@1201
   100
        /// selection rule.
kpeter@1201
   101
        CHEAPEST,
kpeter@1201
   102
kpeter@1201
   103
        /// An unvisited node is selected randomly without any evaluation
kpeter@1201
   104
        /// at each step.
kpeter@1201
   105
        /// The global \ref rnd "random number generator instance" is used.
kpeter@1201
   106
        /// You can seed it before executing the algorithm, if you
kpeter@1201
   107
        /// would like to.
kpeter@1201
   108
        /// The algorithm runs in O(n<sup>2</sup>) time using this
kpeter@1201
   109
        /// selection rule.
kpeter@1201
   110
        RANDOM
kpeter@1201
   111
      };
kpeter@1201
   112
kpeter@1201
   113
    public:
kpeter@1201
   114
kpeter@1201
   115
      /// \brief Constructor
kpeter@1201
   116
      ///
kpeter@1201
   117
      /// Constructor.
kpeter@1201
   118
      /// \param gr The \ref FullGraph "full graph" the algorithm runs on.
kpeter@1201
   119
      /// \param cost The cost map.
kpeter@1201
   120
      InsertionTsp(const FullGraph &gr, const CostMap &cost)
kpeter@1201
   121
        : _gr(gr), _cost(cost) {}
kpeter@1201
   122
kpeter@1201
   123
      /// \name Execution Control
kpeter@1201
   124
      /// @{
kpeter@1201
   125
kpeter@1201
   126
      /// \brief Runs the algorithm.
kpeter@1201
   127
      ///
kpeter@1201
   128
      /// This function runs the algorithm.
kpeter@1201
   129
      ///
kpeter@1201
   130
      /// \param rule The node selection rule. For more information, see
kpeter@1201
   131
      /// \ref SelectionRule.
kpeter@1201
   132
      ///
kpeter@1201
   133
      /// \return The total cost of the found tour.
kpeter@1201
   134
      Cost run(SelectionRule rule = FARTHEST) {
kpeter@1201
   135
        _path.clear();
kpeter@1201
   136
kpeter@1201
   137
        if (_gr.nodeNum() == 0) return _sum = 0;
kpeter@1201
   138
        else if (_gr.nodeNum() == 1) {
kpeter@1201
   139
          _path.push_back(_gr(0));
kpeter@1201
   140
          return _sum = 0;
kpeter@1201
   141
        }
kpeter@1201
   142
kpeter@1201
   143
        switch (rule) {
kpeter@1201
   144
          case NEAREST:
kpeter@1201
   145
            init(true);
kpeter@1201
   146
            start<NearestSelection, DefaultInsertion>();
kpeter@1201
   147
            break;
kpeter@1201
   148
          case FARTHEST:
kpeter@1201
   149
            init(false);
kpeter@1201
   150
            start<FarthestSelection, DefaultInsertion>();
kpeter@1201
   151
            break;
kpeter@1201
   152
          case CHEAPEST:
kpeter@1201
   153
            init(true);
kpeter@1201
   154
            start<CheapestSelection, CheapestInsertion>();
kpeter@1201
   155
            break;
kpeter@1201
   156
          case RANDOM:
kpeter@1201
   157
            init(true);
kpeter@1201
   158
            start<RandomSelection, DefaultInsertion>();
kpeter@1201
   159
            break;
kpeter@1201
   160
        }
kpeter@1201
   161
        return _sum;
kpeter@1201
   162
      }
kpeter@1201
   163
kpeter@1201
   164
      /// @}
kpeter@1201
   165
kpeter@1201
   166
      /// \name Query Functions
kpeter@1201
   167
      /// @{
kpeter@1201
   168
kpeter@1201
   169
      /// \brief The total cost of the found tour.
kpeter@1201
   170
      ///
kpeter@1201
   171
      /// This function returns the total cost of the found tour.
kpeter@1201
   172
      ///
kpeter@1201
   173
      /// \pre run() must be called before using this function.
kpeter@1201
   174
      Cost tourCost() const {
kpeter@1201
   175
        return _sum;
kpeter@1201
   176
      }
kpeter@1201
   177
kpeter@1201
   178
      /// \brief Returns a const reference to the node sequence of the
kpeter@1201
   179
      /// found tour.
kpeter@1201
   180
      ///
kpeter@1201
   181
      /// This function returns a const reference to the internal structure
kpeter@1201
   182
      /// that stores the node sequence of the found tour.
kpeter@1201
   183
      ///
kpeter@1201
   184
      /// \pre run() must be called before using this function.
kpeter@1201
   185
      const std::vector<Node>& tourNodes() const {
kpeter@1201
   186
        return _path;
kpeter@1201
   187
      }
kpeter@1201
   188
kpeter@1201
   189
      /// \brief Gives back the node sequence of the found tour.
kpeter@1201
   190
      ///
kpeter@1201
   191
      /// This function copies the node sequence of the found tour into
kpeter@1201
   192
      /// the given standard container.
kpeter@1201
   193
      ///
kpeter@1201
   194
      /// \pre run() must be called before using this function.
kpeter@1201
   195
      template <typename Container>
kpeter@1201
   196
      void tourNodes(Container &container) const {
kpeter@1201
   197
        container.assign(_path.begin(), _path.end());
kpeter@1201
   198
      }
kpeter@1201
   199
kpeter@1201
   200
      /// \brief Gives back the found tour as a path.
kpeter@1201
   201
      ///
kpeter@1201
   202
      /// This function copies the found tour as a list of arcs/edges into
kpeter@1201
   203
      /// the given \ref concept::Path "path structure".
kpeter@1201
   204
      ///
kpeter@1201
   205
      /// \pre run() must be called before using this function.
kpeter@1201
   206
      template <typename Path>
kpeter@1201
   207
      void tour(Path &path) const {
kpeter@1201
   208
        path.clear();
kpeter@1201
   209
        for (int i = 0; i < int(_path.size()) - 1; ++i) {
kpeter@1201
   210
          path.addBack(_gr.arc(_path[i], _path[i+1]));
kpeter@1201
   211
        }
kpeter@1201
   212
        if (int(_path.size()) >= 2) {
kpeter@1201
   213
          path.addBack(_gr.arc(_path.back(), _path.front()));
kpeter@1201
   214
        }
kpeter@1201
   215
      }
kpeter@1201
   216
kpeter@1201
   217
      /// @}
kpeter@1201
   218
kpeter@1201
   219
    private:
kpeter@1201
   220
kpeter@1201
   221
      // Initializes the algorithm
kpeter@1201
   222
      void init(bool min) {
kpeter@1201
   223
        Edge min_edge = min ? mapMin(_gr, _cost) : mapMax(_gr, _cost);
kpeter@1201
   224
kpeter@1201
   225
        _path.clear();
kpeter@1201
   226
        _path.push_back(_gr.u(min_edge));
kpeter@1201
   227
        _path.push_back(_gr.v(min_edge));
kpeter@1201
   228
kpeter@1201
   229
        _notused.clear();
kpeter@1201
   230
        for (NodeIt n(_gr); n!=INVALID; ++n) {
kpeter@1201
   231
          if (n != _gr.u(min_edge) && n != _gr.v(min_edge)) {
kpeter@1201
   232
            _notused.push_back(n);
kpeter@1201
   233
          }
kpeter@1201
   234
        }
kpeter@1201
   235
kpeter@1201
   236
        _sum = _cost[min_edge] * 2;
kpeter@1201
   237
      }
kpeter@1201
   238
kpeter@1201
   239
      // Executes the algorithm
kpeter@1201
   240
      template <class SelectionFunctor, class InsertionFunctor>
kpeter@1201
   241
      void start() {
kpeter@1201
   242
        SelectionFunctor selectNode(_gr, _cost, _path, _notused);
kpeter@1201
   243
        InsertionFunctor insertNode(_gr, _cost, _path, _sum);
kpeter@1201
   244
kpeter@1201
   245
        for (int i=0; i<_gr.nodeNum()-2; ++i) {
kpeter@1201
   246
          insertNode.insert(selectNode.select());
kpeter@1201
   247
        }
kpeter@1201
   248
kpeter@1201
   249
        _sum = _cost[_gr.edge(_path.back(), _path.front())];
kpeter@1201
   250
        for (int i = 0; i < int(_path.size())-1; ++i) {
kpeter@1201
   251
          _sum += _cost[_gr.edge(_path[i], _path[i+1])];
kpeter@1201
   252
        }
kpeter@1201
   253
      }
kpeter@1201
   254
kpeter@1201
   255
kpeter@1201
   256
      // Implementation of the nearest selection rule
kpeter@1201
   257
      class NearestSelection {
f4c3@1199
   258
        public:
kpeter@1201
   259
          NearestSelection(const FullGraph &gr, const CostMap &cost,
kpeter@1201
   260
                           std::vector<Node> &path, std::vector<Node> &notused)
kpeter@1201
   261
            : _gr(gr), _cost(cost), _path(path), _notused(notused) {}
f4c3@1199
   262
kpeter@1201
   263
          Node select() const {
kpeter@1201
   264
            Cost insert_val = 0;
kpeter@1201
   265
            int insert_node = -1;
kpeter@1201
   266
kpeter@1201
   267
            for (unsigned int i=0; i<_notused.size(); ++i) {
kpeter@1201
   268
              Cost min_val = _cost[_gr.edge(_notused[i], _path[0])];
kpeter@1201
   269
              int min_node = 0;
kpeter@1201
   270
kpeter@1201
   271
              for (unsigned int j=1; j<_path.size(); ++j) {
kpeter@1201
   272
                Cost curr = _cost[_gr.edge(_notused[i], _path[j])];
kpeter@1201
   273
                if (min_val > curr) {
kpeter@1201
   274
                    min_val = curr;
kpeter@1201
   275
                    min_node = j;
kpeter@1201
   276
                }
kpeter@1201
   277
              }
kpeter@1201
   278
kpeter@1201
   279
              if (insert_val > min_val || insert_node == -1) {
kpeter@1201
   280
                insert_val = min_val;
kpeter@1201
   281
                insert_node = i;
f4c3@1199
   282
              }
f4c3@1199
   283
            }
kpeter@1201
   284
kpeter@1201
   285
            Node n = _notused[insert_node];
kpeter@1201
   286
            _notused.erase(_notused.begin()+insert_node);
kpeter@1201
   287
kpeter@1201
   288
            return n;
f4c3@1199
   289
          }
f4c3@1199
   290
f4c3@1199
   291
        private:
f4c3@1199
   292
          const FullGraph &_gr;
f4c3@1199
   293
          const CostMap &_cost;
kpeter@1201
   294
          std::vector<Node> &_path;
f4c3@1199
   295
          std::vector<Node> &_notused;
f4c3@1199
   296
      };
f4c3@1199
   297
kpeter@1201
   298
kpeter@1201
   299
      // Implementation of the farthest selection rule
f4c3@1199
   300
      class FarthestSelection {
f4c3@1199
   301
        public:
f4c3@1199
   302
          FarthestSelection(const FullGraph &gr, const CostMap &cost,
kpeter@1201
   303
                            std::vector<Node> &path, std::vector<Node> &notused)
kpeter@1201
   304
            : _gr(gr), _cost(cost), _path(path), _notused(notused) {}
kpeter@1201
   305
f4c3@1199
   306
          Node select() const {
kpeter@1201
   307
            Cost insert_val = 0;
kpeter@1201
   308
            int insert_node = -1;
f4c3@1199
   309
f4c3@1199
   310
            for (unsigned int i=0; i<_notused.size(); ++i) {
kpeter@1201
   311
              Cost min_val = _cost[_gr.edge(_notused[i], _path[0])];
f4c3@1199
   312
              int min_node = 0;
kpeter@1201
   313
kpeter@1201
   314
              for (unsigned int j=1; j<_path.size(); ++j) {
kpeter@1201
   315
                Cost curr = _cost[_gr.edge(_notused[i], _path[j])];
kpeter@1201
   316
                if (min_val > curr) {
kpeter@1201
   317
                  min_val = curr;
f4c3@1199
   318
                  min_node = j;
f4c3@1199
   319
                }
f4c3@1199
   320
              }
kpeter@1201
   321
f4c3@1199
   322
              if (insert_val < min_val || insert_node == -1) {
f4c3@1199
   323
                insert_val = min_val;
f4c3@1199
   324
                insert_node = i;
f4c3@1199
   325
              }
f4c3@1199
   326
            }
kpeter@1201
   327
f4c3@1199
   328
            Node n = _notused[insert_node];
f4c3@1199
   329
            _notused.erase(_notused.begin()+insert_node);
kpeter@1201
   330
f4c3@1199
   331
            return n;
f4c3@1199
   332
          }
kpeter@1201
   333
f4c3@1199
   334
        private:
f4c3@1199
   335
          const FullGraph &_gr;
f4c3@1199
   336
          const CostMap &_cost;
kpeter@1201
   337
          std::vector<Node> &_path;
f4c3@1199
   338
          std::vector<Node> &_notused;
f4c3@1199
   339
      };
f4c3@1199
   340
f4c3@1199
   341
kpeter@1201
   342
      // Implementation of the cheapest selection rule
f4c3@1199
   343
      class CheapestSelection {
f4c3@1199
   344
        private:
f4c3@1199
   345
          Cost costDiff(Node u, Node v, Node w) const {
kpeter@1201
   346
            return
f4c3@1199
   347
              _cost[_gr.edge(u, w)] +
f4c3@1199
   348
              _cost[_gr.edge(v, w)] -
f4c3@1199
   349
              _cost[_gr.edge(u, v)];
f4c3@1199
   350
          }
f4c3@1199
   351
f4c3@1199
   352
        public:
f4c3@1199
   353
          CheapestSelection(const FullGraph &gr, const CostMap &cost,
kpeter@1201
   354
                            std::vector<Node> &path, std::vector<Node> &notused)
kpeter@1201
   355
            : _gr(gr), _cost(cost), _path(path), _notused(notused) {}
kpeter@1201
   356
f4c3@1199
   357
          Cost select() const {
f4c3@1199
   358
            int insert_notused = -1;
f4c3@1199
   359
            int best_insert_index = -1;
kpeter@1201
   360
            Cost insert_val = 0;
kpeter@1201
   361
f4c3@1199
   362
            for (unsigned int i=0; i<_notused.size(); ++i) {
f4c3@1199
   363
              int min = i;
f4c3@1199
   364
              int best_insert_tmp = 0;
f4c3@1199
   365
              Cost min_val =
kpeter@1201
   366
                costDiff(_path.front(), _path.back(), _notused[i]);
kpeter@1201
   367
kpeter@1201
   368
              for (unsigned int j=1; j<_path.size(); ++j) {
f4c3@1199
   369
                Cost tmp =
kpeter@1201
   370
                  costDiff(_path[j-1], _path[j], _notused[i]);
f4c3@1199
   371
f4c3@1199
   372
                if (min_val > tmp) {
f4c3@1199
   373
                  min = i;
f4c3@1199
   374
                  min_val = tmp;
f4c3@1199
   375
                  best_insert_tmp = j;
f4c3@1199
   376
                }
f4c3@1199
   377
              }
f4c3@1199
   378
kpeter@1201
   379
              if (insert_val > min_val || insert_notused == -1) {
f4c3@1199
   380
                insert_notused = min;
f4c3@1199
   381
                insert_val = min_val;
f4c3@1199
   382
                best_insert_index = best_insert_tmp;
f4c3@1199
   383
              }
f4c3@1199
   384
            }
f4c3@1199
   385
kpeter@1201
   386
            _path.insert(_path.begin()+best_insert_index,
kpeter@1201
   387
                         _notused[insert_notused]);
f4c3@1199
   388
            _notused.erase(_notused.begin()+insert_notused);
f4c3@1199
   389
f4c3@1199
   390
            return insert_val;
f4c3@1199
   391
          }
kpeter@1201
   392
f4c3@1199
   393
        private:
f4c3@1199
   394
          const FullGraph &_gr;
f4c3@1199
   395
          const CostMap &_cost;
kpeter@1201
   396
          std::vector<Node> &_path;
f4c3@1199
   397
          std::vector<Node> &_notused;
f4c3@1199
   398
      };
f4c3@1199
   399
kpeter@1201
   400
      // Implementation of the random selection rule
f4c3@1199
   401
      class RandomSelection {
f4c3@1199
   402
        public:
f4c3@1199
   403
          RandomSelection(const FullGraph &, const CostMap &,
kpeter@1201
   404
                          std::vector<Node> &, std::vector<Node> &notused)
kpeter@1201
   405
            : _notused(notused) {}
kpeter@1201
   406
f4c3@1199
   407
          Node select() const {
f4c3@1199
   408
            const int index = rnd[_notused.size()];
f4c3@1199
   409
            Node n = _notused[index];
f4c3@1199
   410
            _notused.erase(_notused.begin()+index);
f4c3@1199
   411
            return n;
f4c3@1199
   412
          }
f4c3@1199
   413
        private:
f4c3@1199
   414
          std::vector<Node> &_notused;
f4c3@1199
   415
      };
f4c3@1199
   416
f4c3@1199
   417
kpeter@1201
   418
      // Implementation of the default insertion method
kpeter@1201
   419
      class DefaultInsertion {
f4c3@1199
   420
        private:
f4c3@1199
   421
          Cost costDiff(Node u, Node v, Node w) const {
kpeter@1201
   422
            return
f4c3@1199
   423
              _cost[_gr.edge(u, w)] +
f4c3@1199
   424
              _cost[_gr.edge(v, w)] -
f4c3@1199
   425
              _cost[_gr.edge(u, v)];
f4c3@1199
   426
          }
kpeter@1201
   427
f4c3@1199
   428
        public:
kpeter@1201
   429
          DefaultInsertion(const FullGraph &gr, const CostMap &cost,
kpeter@1201
   430
                           std::vector<Node> &path, Cost &total_cost) :
kpeter@1201
   431
            _gr(gr), _cost(cost), _path(path), _total(total_cost) {}
kpeter@1201
   432
f4c3@1199
   433
          void insert(Node n) const {
f4c3@1199
   434
            int min = 0;
f4c3@1199
   435
            Cost min_val =
f4c3@1199
   436
              costDiff(_path.front(), _path.back(), n);
kpeter@1201
   437
f4c3@1199
   438
            for (unsigned int i=1; i<_path.size(); ++i) {
f4c3@1199
   439
              Cost tmp = costDiff(_path[i-1], _path[i], n);
f4c3@1199
   440
              if (tmp < min_val) {
f4c3@1199
   441
                min = i;
f4c3@1199
   442
                min_val = tmp;
f4c3@1199
   443
              }
f4c3@1199
   444
            }
kpeter@1201
   445
f4c3@1199
   446
            _path.insert(_path.begin()+min, n);
kpeter@1201
   447
            _total += min_val;
f4c3@1199
   448
          }
kpeter@1201
   449
f4c3@1199
   450
        private:
f4c3@1199
   451
          const FullGraph &_gr;
f4c3@1199
   452
          const CostMap &_cost;
f4c3@1199
   453
          std::vector<Node> &_path;
kpeter@1201
   454
          Cost &_total;
f4c3@1199
   455
      };
kpeter@1201
   456
kpeter@1201
   457
      // Implementation of a special insertion method for the cheapest
kpeter@1201
   458
      // selection rule
kpeter@1201
   459
      class CheapestInsertion {
f4c3@1199
   460
        TEMPLATE_GRAPH_TYPEDEFS(FullGraph);
f4c3@1199
   461
        public:
kpeter@1201
   462
          CheapestInsertion(const FullGraph &, const CostMap &,
kpeter@1201
   463
                            std::vector<Node> &, Cost &total_cost) :
kpeter@1201
   464
            _total(total_cost) {}
kpeter@1201
   465
f4c3@1199
   466
          void insert(Cost diff) const {
kpeter@1201
   467
            _total += diff;
f4c3@1199
   468
          }
f4c3@1199
   469
f4c3@1199
   470
        private:
kpeter@1201
   471
          Cost &_total;
kpeter@1201
   472
      };
kpeter@1201
   473
f4c3@1199
   474
  };
kpeter@1201
   475
f4c3@1199
   476
}; // namespace lemon
f4c3@1199
   477
f4c3@1199
   478
#endif