lemon/christofides_tsp.h
changeset 1141 a037254714b3
parent 1074 97d978243703
equal deleted inserted replaced
5:d52bf89e78f7 6:343df894a6e5
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library.
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     4  *
     5  * Copyright (C) 2003-2010
     5  * Copyright (C) 2003-2013
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     8  *
     9  * Permission to use, modify and distribute this software is granted
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    10  * provided that this copyright notice appears in all copies. For
    28 #include <lemon/kruskal.h>
    28 #include <lemon/kruskal.h>
    29 #include <lemon/matching.h>
    29 #include <lemon/matching.h>
    30 #include <lemon/euler.h>
    30 #include <lemon/euler.h>
    31 
    31 
    32 namespace lemon {
    32 namespace lemon {
    33   
    33 
    34   /// \ingroup tsp
    34   /// \ingroup tsp
    35   ///
    35   ///
    36   /// \brief Christofides algorithm for symmetric TSP.
    36   /// \brief Christofides algorithm for symmetric TSP.
    37   ///
    37   ///
    38   /// ChristofidesTsp implements Christofides' heuristic for solving
    38   /// ChristofidesTsp implements Christofides' heuristic for solving
   106         else if (_gr.nodeNum() == 2) {
   106         else if (_gr.nodeNum() == 2) {
   107           _path.push_back(_gr(0));
   107           _path.push_back(_gr(0));
   108           _path.push_back(_gr(1));
   108           _path.push_back(_gr(1));
   109           return _sum = 2 * _cost[_gr.edge(_gr(0), _gr(1))];
   109           return _sum = 2 * _cost[_gr.edge(_gr(0), _gr(1))];
   110         }
   110         }
   111         
   111 
   112         // Compute min. cost spanning tree
   112         // Compute min. cost spanning tree
   113         std::vector<Edge> tree;
   113         std::vector<Edge> tree;
   114         kruskal(_gr, _cost, std::back_inserter(tree));
   114         kruskal(_gr, _cost, std::back_inserter(tree));
   115         
   115 
   116         FullGraph::NodeMap<int> deg(_gr, 0);
   116         FullGraph::NodeMap<int> deg(_gr, 0);
   117         for (int i = 0; i != int(tree.size()); ++i) {
   117         for (int i = 0; i != int(tree.size()); ++i) {
   118           Edge e = tree[i];
   118           Edge e = tree[i];
   119           ++deg[_gr.u(e)];
   119           ++deg[_gr.u(e)];
   120           ++deg[_gr.v(e)];
   120           ++deg[_gr.v(e)];
   123         // Copy the induced subgraph of odd nodes
   123         // Copy the induced subgraph of odd nodes
   124         std::vector<Node> odd_nodes;
   124         std::vector<Node> odd_nodes;
   125         for (NodeIt u(_gr); u != INVALID; ++u) {
   125         for (NodeIt u(_gr); u != INVALID; ++u) {
   126           if (deg[u] % 2 == 1) odd_nodes.push_back(u);
   126           if (deg[u] % 2 == 1) odd_nodes.push_back(u);
   127         }
   127         }
   128   
   128 
   129         SmartGraph sgr;
   129         SmartGraph sgr;
   130         SmartGraph::EdgeMap<Cost> scost(sgr);
   130         SmartGraph::EdgeMap<Cost> scost(sgr);
   131         for (int i = 0; i != int(odd_nodes.size()); ++i) {
   131         for (int i = 0; i != int(odd_nodes.size()); ++i) {
   132           sgr.addNode();
   132           sgr.addNode();
   133         }
   133         }
   137             SmartGraph::Edge e =
   137             SmartGraph::Edge e =
   138               sgr.addEdge(sgr.nodeFromId(i), sgr.nodeFromId(j));
   138               sgr.addEdge(sgr.nodeFromId(i), sgr.nodeFromId(j));
   139             scost[e] = -_cost[_gr.edge(odd_nodes[i], odd_nodes[j])];
   139             scost[e] = -_cost[_gr.edge(odd_nodes[i], odd_nodes[j])];
   140           }
   140           }
   141         }
   141         }
   142         
   142 
   143         // Compute min. cost perfect matching
   143         // Compute min. cost perfect matching
   144         MaxWeightedPerfectMatching<SmartGraph, SmartGraph::EdgeMap<Cost> >
   144         MaxWeightedPerfectMatching<SmartGraph, SmartGraph::EdgeMap<Cost> >
   145           mwpm(sgr, scost);
   145           mwpm(sgr, scost);
   146         mwpm.run();
   146         mwpm.run();
   147         
   147 
   148         for (SmartGraph::EdgeIt e(sgr); e != INVALID; ++e) {
   148         for (SmartGraph::EdgeIt e(sgr); e != INVALID; ++e) {
   149           if (mwpm.matching(e)) {
   149           if (mwpm.matching(e)) {
   150             tree.push_back( _gr.edge(odd_nodes[sgr.id(sgr.u(e))],
   150             tree.push_back( _gr.edge(odd_nodes[sgr.id(sgr.u(e))],
   151                                      odd_nodes[sgr.id(sgr.v(e))]) );
   151                                      odd_nodes[sgr.id(sgr.v(e))]) );
   152           }
   152           }
   153         }
   153         }
   154         
   154 
   155         // Join the spanning tree and the matching        
   155         // Join the spanning tree and the matching
   156         sgr.clear();
   156         sgr.clear();
   157         for (int i = 0; i != _gr.nodeNum(); ++i) {
   157         for (int i = 0; i != _gr.nodeNum(); ++i) {
   158           sgr.addNode();
   158           sgr.addNode();
   159         }
   159         }
   160         for (int i = 0; i != int(tree.size()); ++i) {
   160         for (int i = 0; i != int(tree.size()); ++i) {
   180 
   180 
   181         return _sum;
   181         return _sum;
   182       }
   182       }
   183 
   183 
   184       /// @}
   184       /// @}
   185       
   185 
   186       /// \name Query Functions
   186       /// \name Query Functions
   187       /// @{
   187       /// @{
   188       
   188 
   189       /// \brief The total cost of the found tour.
   189       /// \brief The total cost of the found tour.
   190       ///
   190       ///
   191       /// This function returns the total cost of the found tour.
   191       /// This function returns the total cost of the found tour.
   192       ///
   192       ///
   193       /// \pre run() must be called before using this function.
   193       /// \pre run() must be called before using this function.
   194       Cost tourCost() const {
   194       Cost tourCost() const {
   195         return _sum;
   195         return _sum;
   196       }
   196       }
   197       
   197 
   198       /// \brief Returns a const reference to the node sequence of the
   198       /// \brief Returns a const reference to the node sequence of the
   199       /// found tour.
   199       /// found tour.
   200       ///
   200       ///
   201       /// This function returns a const reference to a vector
   201       /// This function returns a const reference to a vector
   202       /// that stores the node sequence of the found tour.
   202       /// that stores the node sequence of the found tour.
   225       /// \pre run() must be called before using this function.
   225       /// \pre run() must be called before using this function.
   226       template <typename Iterator>
   226       template <typename Iterator>
   227       void tourNodes(Iterator out) const {
   227       void tourNodes(Iterator out) const {
   228         std::copy(_path.begin(), _path.end(), out);
   228         std::copy(_path.begin(), _path.end(), out);
   229       }
   229       }
   230       
   230 
   231       /// \brief Gives back the found tour as a path.
   231       /// \brief Gives back the found tour as a path.
   232       ///
   232       ///
   233       /// This function copies the found tour as a list of arcs/edges into
   233       /// This function copies the found tour as a list of arcs/edges into
   234       /// the given \ref lemon::concepts::Path "path structure".
   234       /// the given \ref lemon::concepts::Path "path structure".
   235       ///
   235       ///
   242         }
   242         }
   243         if (int(_path.size()) >= 2) {
   243         if (int(_path.size()) >= 2) {
   244           path.addBack(_gr.arc(_path.back(), _path.front()));
   244           path.addBack(_gr.arc(_path.back(), _path.front()));
   245         }
   245         }
   246       }
   246       }
   247       
   247 
   248       /// @}
   248       /// @}
   249       
   249 
   250   };
   250   };
   251 
   251 
   252 }; // namespace lemon
   252 }; // namespace lemon
   253 
   253 
   254 #endif
   254 #endif