lemon/insertion_tsp.h
changeset 1036 dff32ce3db71
parent 1034 ef200e268af2
child 1037 d3dcc49e6403
equal deleted inserted replaced
2:53efd5c9a659 3:672d580c328f
    22 /// \ingroup tsp
    22 /// \ingroup tsp
    23 /// \file
    23 /// \file
    24 /// \brief Insertion algorithm for symmetric TSP
    24 /// \brief Insertion algorithm for symmetric TSP
    25 
    25 
    26 #include <vector>
    26 #include <vector>
       
    27 #include <functional>
    27 #include <lemon/full_graph.h>
    28 #include <lemon/full_graph.h>
    28 #include <lemon/maps.h>
    29 #include <lemon/maps.h>
    29 #include <lemon/random.h>
    30 #include <lemon/random.h>
    30 
    31 
    31 namespace lemon {
    32 namespace lemon {
    35   /// \brief Insertion algorithm for symmetric TSP.
    36   /// \brief Insertion algorithm for symmetric TSP.
    36   ///
    37   ///
    37   /// InsertionTsp implements the insertion heuristic for solving
    38   /// InsertionTsp implements the insertion heuristic for solving
    38   /// symmetric \ref tsp "TSP".
    39   /// symmetric \ref tsp "TSP".
    39   ///
    40   ///
    40   /// This is a basic TSP heuristic that has many variants.
    41   /// This is a fast and effective tour construction method that has
       
    42   /// many variants.
    41   /// It starts with a subtour containing a few nodes of the graph and it
    43   /// It starts with a subtour containing a few nodes of the graph and it
    42   /// iteratively inserts the other nodes into this subtour according to a
    44   /// iteratively inserts the other nodes into this subtour according to a
    43   /// certain node selection rule.
    45   /// certain node selection rule.
    44   ///
    46   ///
    45   /// This implementation provides four different node selection rules,
    47   /// This method is among the fastest TSP algorithms, and it typically
    46   /// from which the most powerful one is used by default.
    48   /// provides quite good solutions (usually much better than
       
    49   /// \ref NearestNeighborTsp and \ref GreedyTsp).
       
    50   ///
       
    51   /// InsertionTsp implements four different node selection rules,
       
    52   /// from which the most effective one (\e farthest \e node \e selection)
       
    53   /// is used by default.
       
    54   /// With this choice, the algorithm runs in O(n<sup>2</sup>) time.
    47   /// For more information, see \ref SelectionRule.
    55   /// For more information, see \ref SelectionRule.
    48   ///
    56   ///
    49   /// \tparam CM Type of the cost map.
    57   /// \tparam CM Type of the cost map.
    50   template <typename CM>
    58   template <typename CM>
    51   class InsertionTsp
    59   class InsertionTsp
    62       GRAPH_TYPEDEFS(FullGraph);
    70       GRAPH_TYPEDEFS(FullGraph);
    63 
    71 
    64       const FullGraph &_gr;
    72       const FullGraph &_gr;
    65       const CostMap &_cost;
    73       const CostMap &_cost;
    66       std::vector<Node> _notused;
    74       std::vector<Node> _notused;
    67       std::vector<Node> _path;
    75       std::vector<Node> _tour;
    68       Cost _sum;
    76       Cost _sum;
    69 
    77 
    70     public:
    78     public:
    71 
    79 
    72       /// \brief Constants for specifying the node selection rule.
    80       /// \brief Constants for specifying the node selection rule.
    74       /// Enum type containing constants for specifying the node selection
    82       /// Enum type containing constants for specifying the node selection
    75       /// rule for the \ref run() function.
    83       /// rule for the \ref run() function.
    76       ///
    84       ///
    77       /// During the algorithm, nodes are selected for addition to the current
    85       /// During the algorithm, nodes are selected for addition to the current
    78       /// subtour according to the applied rule.
    86       /// subtour according to the applied rule.
    79       /// In general, the FARTHEST method yields the best tours, thus it is the
    87       /// The FARTHEST method is one of the fastest selection rules, and
    80       /// default option. The RANDOM rule usually gives somewhat worse results,
    88       /// it is typically the most effective, thus it is the default
    81       /// but it is much faster than the others and it is the most robust.
    89       /// option. The RANDOM rule usually gives slightly worse results,
       
    90       /// but it is more robust.
    82       ///
    91       ///
    83       /// The desired selection rule can be specified as a parameter of the
    92       /// The desired selection rule can be specified as a parameter of the
    84       /// \ref run() function.
    93       /// \ref run() function.
    85       enum SelectionRule {
    94       enum SelectionRule {
    86 
    95 
    87         /// An unvisited node having minimum distance from the current
    96         /// An unvisited node having minimum distance from the current
    88         /// subtour is selected at each step.
    97         /// subtour is selected at each step.
    89         /// The algorithm runs in O(n<sup>3</sup>) time using this
    98         /// The algorithm runs in O(n<sup>2</sup>) time using this
    90         /// selection rule.
    99         /// selection rule.
    91         NEAREST,
   100         NEAREST,
    92 
   101 
    93         /// An unvisited node having maximum distance from the current
   102         /// An unvisited node having maximum distance from the current
    94         /// subtour is selected at each step.
   103         /// subtour is selected at each step.
    95         /// The algorithm runs in O(n<sup>3</sup>) time using this
   104         /// The algorithm runs in O(n<sup>2</sup>) time using this
    96         /// selection rule.
   105         /// selection rule.
    97         FARTHEST,
   106         FARTHEST,
    98 
   107 
    99         /// An unvisited node whose insertion results in the least
   108         /// An unvisited node whose insertion results in the least
   100         /// increase of the subtour's total cost is selected at each step.
   109         /// increase of the subtour's total cost is selected at each step.
   101         /// The algorithm runs in O(n<sup>3</sup>) time using this
   110         /// The algorithm runs in O(n<sup>3</sup>) time using this
   102         /// selection rule.
   111         /// selection rule, but in most cases, it is almost as fast as
       
   112         /// with other rules.
   103         CHEAPEST,
   113         CHEAPEST,
   104 
   114 
   105         /// An unvisited node is selected randomly without any evaluation
   115         /// An unvisited node is selected randomly without any evaluation
   106         /// at each step.
   116         /// at each step.
   107         /// The global \ref rnd "random number generator instance" is used.
   117         /// The global \ref rnd "random number generator instance" is used.
   132       /// \param rule The node selection rule. For more information, see
   142       /// \param rule The node selection rule. For more information, see
   133       /// \ref SelectionRule.
   143       /// \ref SelectionRule.
   134       ///
   144       ///
   135       /// \return The total cost of the found tour.
   145       /// \return The total cost of the found tour.
   136       Cost run(SelectionRule rule = FARTHEST) {
   146       Cost run(SelectionRule rule = FARTHEST) {
   137         _path.clear();
   147         _tour.clear();
   138 
   148 
   139         if (_gr.nodeNum() == 0) return _sum = 0;
   149         if (_gr.nodeNum() == 0) return _sum = 0;
   140         else if (_gr.nodeNum() == 1) {
   150         else if (_gr.nodeNum() == 1) {
   141           _path.push_back(_gr(0));
   151           _tour.push_back(_gr(0));
   142           return _sum = 0;
   152           return _sum = 0;
   143         }
   153         }
   144 
   154 
   145         switch (rule) {
   155         switch (rule) {
   146           case NEAREST:
   156           case NEAREST:
   147             init(true);
   157             init(true);
   148             start<NearestSelection, DefaultInsertion>();
   158             start<ComparingSelection<std::less<Cost> >,
       
   159                   DefaultInsertion>();
   149             break;
   160             break;
   150           case FARTHEST:
   161           case FARTHEST:
   151             init(false);
   162             init(false);
   152             start<FarthestSelection, DefaultInsertion>();
   163             start<ComparingSelection<std::greater<Cost> >,
       
   164                   DefaultInsertion>();
   153             break;
   165             break;
   154           case CHEAPEST:
   166           case CHEAPEST:
   155             init(true);
   167             init(true);
   156             start<CheapestSelection, CheapestInsertion>();
   168             start<CheapestSelection, CheapestInsertion>();
   157             break;
   169             break;
   183       /// This function returns a const reference to a vector
   195       /// This function returns a const reference to a vector
   184       /// that stores the node sequence of the found tour.
   196       /// that stores the node sequence of the found tour.
   185       ///
   197       ///
   186       /// \pre run() must be called before using this function.
   198       /// \pre run() must be called before using this function.
   187       const std::vector<Node>& tourNodes() const {
   199       const std::vector<Node>& tourNodes() const {
   188         return _path;
   200         return _tour;
   189       }
   201       }
   190 
   202 
   191       /// \brief Gives back the node sequence of the found tour.
   203       /// \brief Gives back the node sequence of the found tour.
   192       ///
   204       ///
   193       /// This function copies the node sequence of the found tour into
   205       /// This function copies the node sequence of the found tour into
   194       /// the given standard container.
   206       /// the given standard container.
   195       ///
   207       ///
   196       /// \pre run() must be called before using this function.
   208       /// \pre run() must be called before using this function.
   197       template <typename Container>
   209       template <typename Container>
   198       void tourNodes(Container &container) const {
   210       void tourNodes(Container &container) const {
   199         container.assign(_path.begin(), _path.end());
   211         container.assign(_tour.begin(), _tour.end());
   200       }
   212       }
   201 
   213 
   202       /// \brief Gives back the found tour as a path.
   214       /// \brief Gives back the found tour as a path.
   203       ///
   215       ///
   204       /// This function copies the found tour as a list of arcs/edges into
   216       /// This function copies the found tour as a list of arcs/edges into
   206       ///
   218       ///
   207       /// \pre run() must be called before using this function.
   219       /// \pre run() must be called before using this function.
   208       template <typename Path>
   220       template <typename Path>
   209       void tour(Path &path) const {
   221       void tour(Path &path) const {
   210         path.clear();
   222         path.clear();
   211         for (int i = 0; i < int(_path.size()) - 1; ++i) {
   223         for (int i = 0; i < int(_tour.size()) - 1; ++i) {
   212           path.addBack(_gr.arc(_path[i], _path[i+1]));
   224           path.addBack(_gr.arc(_tour[i], _tour[i+1]));
   213         }
   225         }
   214         if (int(_path.size()) >= 2) {
   226         if (int(_tour.size()) >= 2) {
   215           path.addBack(_gr.arc(_path.back(), _path.front()));
   227           path.addBack(_gr.arc(_tour.back(), _tour.front()));
   216         }
   228         }
   217       }
   229       }
   218 
   230 
   219       /// @}
   231       /// @}
   220 
   232 
   222 
   234 
   223       // Initializes the algorithm
   235       // Initializes the algorithm
   224       void init(bool min) {
   236       void init(bool min) {
   225         Edge min_edge = min ? mapMin(_gr, _cost) : mapMax(_gr, _cost);
   237         Edge min_edge = min ? mapMin(_gr, _cost) : mapMax(_gr, _cost);
   226 
   238 
   227         _path.clear();
   239         _tour.clear();
   228         _path.push_back(_gr.u(min_edge));
   240         _tour.push_back(_gr.u(min_edge));
   229         _path.push_back(_gr.v(min_edge));
   241         _tour.push_back(_gr.v(min_edge));
   230 
   242 
   231         _notused.clear();
   243         _notused.clear();
   232         for (NodeIt n(_gr); n!=INVALID; ++n) {
   244         for (NodeIt n(_gr); n!=INVALID; ++n) {
   233           if (n != _gr.u(min_edge) && n != _gr.v(min_edge)) {
   245           if (n != _gr.u(min_edge) && n != _gr.v(min_edge)) {
   234             _notused.push_back(n);
   246             _notused.push_back(n);
   239       }
   251       }
   240 
   252 
   241       // Executes the algorithm
   253       // Executes the algorithm
   242       template <class SelectionFunctor, class InsertionFunctor>
   254       template <class SelectionFunctor, class InsertionFunctor>
   243       void start() {
   255       void start() {
   244         SelectionFunctor selectNode(_gr, _cost, _path, _notused);
   256         SelectionFunctor selectNode(_gr, _cost, _tour, _notused);
   245         InsertionFunctor insertNode(_gr, _cost, _path, _sum);
   257         InsertionFunctor insertNode(_gr, _cost, _tour, _sum);
   246 
   258 
   247         for (int i=0; i<_gr.nodeNum()-2; ++i) {
   259         for (int i=0; i<_gr.nodeNum()-2; ++i) {
   248           insertNode.insert(selectNode.select());
   260           insertNode.insert(selectNode.select());
   249         }
   261         }
   250 
   262 
   251         _sum = _cost[_gr.edge(_path.back(), _path.front())];
   263         _sum = _cost[_gr.edge(_tour.back(), _tour.front())];
   252         for (int i = 0; i < int(_path.size())-1; ++i) {
   264         for (int i = 0; i < int(_tour.size())-1; ++i) {
   253           _sum += _cost[_gr.edge(_path[i], _path[i+1])];
   265           _sum += _cost[_gr.edge(_tour[i], _tour[i+1])];
   254         }
   266         }
   255       }
   267       }
   256 
   268 
   257 
   269 
   258       // Implementation of the nearest selection rule
   270       // Implementation of the nearest and farthest selection rule
   259       class NearestSelection {
   271       template <typename Comparator>
       
   272       class ComparingSelection {
   260         public:
   273         public:
   261           NearestSelection(const FullGraph &gr, const CostMap &cost,
   274           ComparingSelection(const FullGraph &gr, const CostMap &cost,
   262                            std::vector<Node> &path, std::vector<Node> &notused)
   275                   std::vector<Node> &tour, std::vector<Node> &notused)
   263             : _gr(gr), _cost(cost), _path(path), _notused(notused) {}
   276             : _gr(gr), _cost(cost), _tour(tour), _notused(notused),
   264 
   277               _dist(gr, 0), _compare()
   265           Node select() const {
   278           {
   266             Cost insert_val = 0;
   279             // Compute initial distances for the unused nodes
   267             int insert_node = -1;
       
   268 
       
   269             for (unsigned int i=0; i<_notused.size(); ++i) {
   280             for (unsigned int i=0; i<_notused.size(); ++i) {
   270               Cost min_val = _cost[_gr.edge(_notused[i], _path[0])];
   281               Node u = _notused[i];
   271               int min_node = 0;
   282               Cost min_dist = _cost[_gr.edge(u, _tour[0])];
   272 
   283               for (unsigned int j=1; j<_tour.size(); ++j) {
   273               for (unsigned int j=1; j<_path.size(); ++j) {
   284                 Cost curr = _cost[_gr.edge(u, _tour[j])];
   274                 Cost curr = _cost[_gr.edge(_notused[i], _path[j])];
   285                 if (curr < min_dist) {
   275                 if (min_val > curr) {
   286                   min_dist = curr;
   276                     min_val = curr;
       
   277                     min_node = j;
       
   278                 }
   287                 }
   279               }
   288               }
   280 
   289               _dist[u] = min_dist;
   281               if (insert_val > min_val || insert_node == -1) {
   290             }
   282                 insert_val = min_val;
   291           }
   283                 insert_node = i;
   292 
   284               }
   293           Node select() {
   285             }
   294 
   286 
   295             // Select an used node with minimum distance
   287             Node n = _notused[insert_node];
   296             Cost ins_dist = 0;
   288             _notused.erase(_notused.begin()+insert_node);
   297             int ins_node = -1;
   289 
   298             for (unsigned int i=0; i<_notused.size(); ++i) {
   290             return n;
   299               Cost curr = _dist[_notused[i]];
       
   300               if (_compare(curr, ins_dist) || ins_node == -1) {
       
   301                 ins_dist = curr;
       
   302                 ins_node = i;
       
   303               }
       
   304             }
       
   305 
       
   306             // Remove the selected node from the unused vector
       
   307             Node sn = _notused[ins_node];
       
   308             _notused[ins_node] = _notused.back();
       
   309             _notused.pop_back();
       
   310 
       
   311             // Update the distances of the remaining nodes
       
   312             for (unsigned int i=0; i<_notused.size(); ++i) {
       
   313               Node u = _notused[i];
       
   314               Cost nc = _cost[_gr.edge(sn, u)];
       
   315               if (nc < _dist[u]) {
       
   316                 _dist[u] = nc;
       
   317               }
       
   318             }
       
   319 
       
   320             return sn;
   291           }
   321           }
   292 
   322 
   293         private:
   323         private:
   294           const FullGraph &_gr;
   324           const FullGraph &_gr;
   295           const CostMap &_cost;
   325           const CostMap &_cost;
   296           std::vector<Node> &_path;
   326           std::vector<Node> &_tour;
   297           std::vector<Node> &_notused;
   327           std::vector<Node> &_notused;
       
   328           FullGraph::NodeMap<Cost> _dist;
       
   329           Comparator _compare;
   298       };
   330       };
   299 
       
   300 
       
   301       // Implementation of the farthest selection rule
       
   302       class FarthestSelection {
       
   303         public:
       
   304           FarthestSelection(const FullGraph &gr, const CostMap &cost,
       
   305                             std::vector<Node> &path, std::vector<Node> &notused)
       
   306             : _gr(gr), _cost(cost), _path(path), _notused(notused) {}
       
   307 
       
   308           Node select() const {
       
   309             Cost insert_val = 0;
       
   310             int insert_node = -1;
       
   311 
       
   312             for (unsigned int i=0; i<_notused.size(); ++i) {
       
   313               Cost min_val = _cost[_gr.edge(_notused[i], _path[0])];
       
   314               int min_node = 0;
       
   315 
       
   316               for (unsigned int j=1; j<_path.size(); ++j) {
       
   317                 Cost curr = _cost[_gr.edge(_notused[i], _path[j])];
       
   318                 if (min_val > curr) {
       
   319                   min_val = curr;
       
   320                   min_node = j;
       
   321                 }
       
   322               }
       
   323 
       
   324               if (insert_val < min_val || insert_node == -1) {
       
   325                 insert_val = min_val;
       
   326                 insert_node = i;
       
   327               }
       
   328             }
       
   329 
       
   330             Node n = _notused[insert_node];
       
   331             _notused.erase(_notused.begin()+insert_node);
       
   332 
       
   333             return n;
       
   334           }
       
   335 
       
   336         private:
       
   337           const FullGraph &_gr;
       
   338           const CostMap &_cost;
       
   339           std::vector<Node> &_path;
       
   340           std::vector<Node> &_notused;
       
   341       };
       
   342 
       
   343 
   331 
   344       // Implementation of the cheapest selection rule
   332       // Implementation of the cheapest selection rule
   345       class CheapestSelection {
   333       class CheapestSelection {
   346         private:
   334         private:
   347           Cost costDiff(Node u, Node v, Node w) const {
   335           Cost costDiff(Node u, Node v, Node w) const {
   351               _cost[_gr.edge(u, v)];
   339               _cost[_gr.edge(u, v)];
   352           }
   340           }
   353 
   341 
   354         public:
   342         public:
   355           CheapestSelection(const FullGraph &gr, const CostMap &cost,
   343           CheapestSelection(const FullGraph &gr, const CostMap &cost,
   356                             std::vector<Node> &path, std::vector<Node> &notused)
   344                             std::vector<Node> &tour, std::vector<Node> &notused)
   357             : _gr(gr), _cost(cost), _path(path), _notused(notused) {}
   345             : _gr(gr), _cost(cost), _tour(tour), _notused(notused),
   358 
   346               _ins_cost(gr, 0), _ins_pos(gr, -1)
   359           Cost select() const {
   347           {
   360             int insert_notused = -1;
   348             // Compute insertion cost and position for the unused nodes
   361             int best_insert_index = -1;
       
   362             Cost insert_val = 0;
       
   363 
       
   364             for (unsigned int i=0; i<_notused.size(); ++i) {
   349             for (unsigned int i=0; i<_notused.size(); ++i) {
   365               int min = i;
   350               Node u = _notused[i];
   366               int best_insert_tmp = 0;
   351               Cost min_cost = costDiff(_tour.back(), _tour.front(), u);
   367               Cost min_val =
   352               int min_pos = 0;              
   368                 costDiff(_path.front(), _path.back(), _notused[i]);
   353               for (unsigned int j=1; j<_tour.size(); ++j) {
   369 
   354                 Cost curr_cost = costDiff(_tour[j-1], _tour[j], u);
   370               for (unsigned int j=1; j<_path.size(); ++j) {
   355                 if (curr_cost < min_cost) {
   371                 Cost tmp =
   356                   min_cost = curr_cost;
   372                   costDiff(_path[j-1], _path[j], _notused[i]);
   357                   min_pos = j;
   373 
       
   374                 if (min_val > tmp) {
       
   375                   min = i;
       
   376                   min_val = tmp;
       
   377                   best_insert_tmp = j;
       
   378                 }
   358                 }
   379               }
   359               }
   380 
   360               _ins_cost[u] = min_cost;
   381               if (insert_val > min_val || insert_notused == -1) {
   361               _ins_pos[u] = min_pos;
   382                 insert_notused = min;
   362             }
   383                 insert_val = min_val;
   363           }
   384                 best_insert_index = best_insert_tmp;
   364 
   385               }
   365           Cost select() {
   386             }
   366 
   387 
   367             // Select an used node with minimum insertion cost
   388             _path.insert(_path.begin()+best_insert_index,
   368             Cost min_cost = 0;
   389                          _notused[insert_notused]);
   369             int min_node = -1;
   390             _notused.erase(_notused.begin()+insert_notused);
   370             for (unsigned int i=0; i<_notused.size(); ++i) {
   391 
   371               Cost curr_cost = _ins_cost[_notused[i]];
   392             return insert_val;
   372               if (curr_cost < min_cost || min_node == -1) {
       
   373                 min_cost = curr_cost;
       
   374                 min_node = i;
       
   375               }
       
   376             }
       
   377 
       
   378             // Remove the selected node from the unused vector
       
   379             Node sn = _notused[min_node];
       
   380             _notused[min_node] = _notused.back();
       
   381             _notused.pop_back();
       
   382             
       
   383             // Insert the selected node into the tour
       
   384             const int ipos = _ins_pos[sn];
       
   385             _tour.insert(_tour.begin() + ipos, sn);
       
   386 
       
   387             // Update the insertion cost and position of the remaining nodes
       
   388             for (unsigned int i=0; i<_notused.size(); ++i) {
       
   389               Node u = _notused[i];
       
   390               Cost curr_cost = _ins_cost[u];
       
   391               int curr_pos = _ins_pos[u];
       
   392 
       
   393               int ipos_prev = ipos == 0 ? _tour.size()-1 : ipos-1;
       
   394               int ipos_next = ipos == int(_tour.size())-1 ? 0 : ipos+1;
       
   395               Cost nc1 = costDiff(_tour[ipos_prev], _tour[ipos], u);
       
   396               Cost nc2 = costDiff(_tour[ipos], _tour[ipos_next], u);
       
   397               
       
   398               if (nc1 <= curr_cost || nc2 <= curr_cost) {
       
   399                 // A new position is better than the old one
       
   400                 if (nc1 <= nc2) {
       
   401                   curr_cost = nc1;
       
   402                   curr_pos = ipos;
       
   403                 } else {
       
   404                   curr_cost = nc2;
       
   405                   curr_pos = ipos_next;
       
   406                 }
       
   407               }
       
   408               else {
       
   409                 if (curr_pos == ipos) {
       
   410                   // The minimum should be found again
       
   411                   curr_cost = costDiff(_tour.back(), _tour.front(), u);
       
   412                   curr_pos = 0;              
       
   413                   for (unsigned int j=1; j<_tour.size(); ++j) {
       
   414                     Cost tmp_cost = costDiff(_tour[j-1], _tour[j], u);
       
   415                     if (tmp_cost < curr_cost) {
       
   416                       curr_cost = tmp_cost;
       
   417                       curr_pos = j;
       
   418                     }
       
   419                   }
       
   420                 }
       
   421                 else if (curr_pos > ipos) {
       
   422                   ++curr_pos;
       
   423                 }
       
   424               }
       
   425               
       
   426               _ins_cost[u] = curr_cost;
       
   427               _ins_pos[u] = curr_pos;
       
   428             }
       
   429 
       
   430             return min_cost;
   393           }
   431           }
   394 
   432 
   395         private:
   433         private:
   396           const FullGraph &_gr;
   434           const FullGraph &_gr;
   397           const CostMap &_cost;
   435           const CostMap &_cost;
   398           std::vector<Node> &_path;
   436           std::vector<Node> &_tour;
   399           std::vector<Node> &_notused;
   437           std::vector<Node> &_notused;
       
   438           FullGraph::NodeMap<Cost> _ins_cost;
       
   439           FullGraph::NodeMap<int> _ins_pos;
   400       };
   440       };
   401 
   441 
   402       // Implementation of the random selection rule
   442       // Implementation of the random selection rule
   403       class RandomSelection {
   443       class RandomSelection {
   404         public:
   444         public:
   407             : _notused(notused) {}
   447             : _notused(notused) {}
   408 
   448 
   409           Node select() const {
   449           Node select() const {
   410             const int index = rnd[_notused.size()];
   450             const int index = rnd[_notused.size()];
   411             Node n = _notused[index];
   451             Node n = _notused[index];
   412             _notused.erase(_notused.begin()+index);
   452             _notused[index] = _notused.back();
       
   453             _notused.pop_back();
   413             return n;
   454             return n;
   414           }
   455           }
       
   456 
   415         private:
   457         private:
   416           std::vector<Node> &_notused;
   458           std::vector<Node> &_notused;
   417       };
   459       };
   418 
   460 
   419 
   461 
   427               _cost[_gr.edge(u, v)];
   469               _cost[_gr.edge(u, v)];
   428           }
   470           }
   429 
   471 
   430         public:
   472         public:
   431           DefaultInsertion(const FullGraph &gr, const CostMap &cost,
   473           DefaultInsertion(const FullGraph &gr, const CostMap &cost,
   432                            std::vector<Node> &path, Cost &total_cost) :
   474                            std::vector<Node> &tour, Cost &total_cost) :
   433             _gr(gr), _cost(cost), _path(path), _total(total_cost) {}
   475             _gr(gr), _cost(cost), _tour(tour), _total(total_cost) {}
   434 
   476 
   435           void insert(Node n) const {
   477           void insert(Node n) const {
   436             int min = 0;
   478             int min = 0;
   437             Cost min_val =
   479             Cost min_val =
   438               costDiff(_path.front(), _path.back(), n);
   480               costDiff(_tour.front(), _tour.back(), n);
   439 
   481 
   440             for (unsigned int i=1; i<_path.size(); ++i) {
   482             for (unsigned int i=1; i<_tour.size(); ++i) {
   441               Cost tmp = costDiff(_path[i-1], _path[i], n);
   483               Cost tmp = costDiff(_tour[i-1], _tour[i], n);
   442               if (tmp < min_val) {
   484               if (tmp < min_val) {
   443                 min = i;
   485                 min = i;
   444                 min_val = tmp;
   486                 min_val = tmp;
   445               }
   487               }
   446             }
   488             }
   447 
   489 
   448             _path.insert(_path.begin()+min, n);
   490             _tour.insert(_tour.begin()+min, n);
   449             _total += min_val;
   491             _total += min_val;
   450           }
   492           }
   451 
   493 
   452         private:
   494         private:
   453           const FullGraph &_gr;
   495           const FullGraph &_gr;
   454           const CostMap &_cost;
   496           const CostMap &_cost;
   455           std::vector<Node> &_path;
   497           std::vector<Node> &_tour;
   456           Cost &_total;
   498           Cost &_total;
   457       };
   499       };
   458 
   500 
   459       // Implementation of a special insertion method for the cheapest
   501       // Implementation of a special insertion method for the cheapest
   460       // selection rule
   502       // selection rule