lemon/suurballe.h
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 16 Oct 2009 01:06:16 +0200
changeset 853 ec0b1b423b8b
parent 852 30c77d1c0cba
child 854 9a7e4e606f83
permissions -rw-r--r--
Rework and improve Suurballe (#323)

- Improve the implementation: use a specific, faster variant of
residual Dijkstra for the first search.
- Some reorganizatiopn to make the code simpler.
- Small doc improvements.
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     5  * Copyright (C) 2003-2009
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_SUURBALLE_H
    20 #define LEMON_SUURBALLE_H
    21 
    22 ///\ingroup shortest_path
    23 ///\file
    24 ///\brief An algorithm for finding arc-disjoint paths between two
    25 /// nodes having minimum total length.
    26 
    27 #include <vector>
    28 #include <limits>
    29 #include <lemon/bin_heap.h>
    30 #include <lemon/path.h>
    31 #include <lemon/list_graph.h>
    32 #include <lemon/maps.h>
    33 
    34 namespace lemon {
    35 
    36   /// \addtogroup shortest_path
    37   /// @{
    38 
    39   /// \brief Algorithm for finding arc-disjoint paths between two nodes
    40   /// having minimum total length.
    41   ///
    42   /// \ref lemon::Suurballe "Suurballe" implements an algorithm for
    43   /// finding arc-disjoint paths having minimum total length (cost)
    44   /// from a given source node to a given target node in a digraph.
    45   ///
    46   /// Note that this problem is a special case of the \ref min_cost_flow
    47   /// "minimum cost flow problem". This implementation is actually an
    48   /// efficient specialized version of the \ref CapacityScaling
    49   /// "successive shortest path" algorithm directly for this problem.
    50   /// Therefore this class provides query functions for flow values and
    51   /// node potentials (the dual solution) just like the minimum cost flow
    52   /// algorithms.
    53   ///
    54   /// \tparam GR The digraph type the algorithm runs on.
    55   /// \tparam LEN The type of the length map.
    56   /// The default value is <tt>GR::ArcMap<int></tt>.
    57   ///
    58   /// \warning Length values should be \e non-negative.
    59   ///
    60   /// \note For finding \e node-disjoint paths, this algorithm can be used
    61   /// along with the \ref SplitNodes adaptor.
    62 #ifdef DOXYGEN
    63   template <typename GR, typename LEN>
    64 #else
    65   template < typename GR,
    66              typename LEN = typename GR::template ArcMap<int> >
    67 #endif
    68   class Suurballe
    69   {
    70     TEMPLATE_DIGRAPH_TYPEDEFS(GR);
    71 
    72     typedef ConstMap<Arc, int> ConstArcMap;
    73     typedef typename GR::template NodeMap<Arc> PredMap;
    74 
    75   public:
    76 
    77     /// The type of the digraph the algorithm runs on.
    78     typedef GR Digraph;
    79     /// The type of the length map.
    80     typedef LEN LengthMap;
    81     /// The type of the lengths.
    82     typedef typename LengthMap::Value Length;
    83 #ifdef DOXYGEN
    84     /// The type of the flow map.
    85     typedef GR::ArcMap<int> FlowMap;
    86     /// The type of the potential map.
    87     typedef GR::NodeMap<Length> PotentialMap;
    88 #else
    89     /// The type of the flow map.
    90     typedef typename Digraph::template ArcMap<int> FlowMap;
    91     /// The type of the potential map.
    92     typedef typename Digraph::template NodeMap<Length> PotentialMap;
    93 #endif
    94 
    95     /// The type of the path structures.
    96     typedef SimplePath<GR> Path;
    97 
    98   private:
    99 
   100     // ResidualDijkstra is a special implementation of the
   101     // Dijkstra algorithm for finding shortest paths in the
   102     // residual network with respect to the reduced arc lengths
   103     // and modifying the node potentials according to the
   104     // distance of the nodes.
   105     class ResidualDijkstra
   106     {
   107       typedef typename Digraph::template NodeMap<int> HeapCrossRef;
   108       typedef BinHeap<Length, HeapCrossRef> Heap;
   109 
   110     private:
   111 
   112       const Digraph &_graph;
   113       const LengthMap &_length;
   114       const FlowMap &_flow;
   115       PotentialMap &_pi;
   116       PredMap &_pred;
   117       Node _s;
   118       Node _t;
   119       
   120       PotentialMap _dist;
   121       std::vector<Node> _proc_nodes;
   122 
   123     public:
   124 
   125       // Constructor
   126       ResidualDijkstra(Suurballe &srb) :
   127         _graph(srb._graph), _length(srb._length),
   128         _flow(*srb._flow), _pi(*srb._potential), _pred(srb._pred), 
   129         _s(srb._s), _t(srb._t), _dist(_graph) {}
   130         
   131       // Run the algorithm and return true if a path is found
   132       // from the source node to the target node.
   133       bool run(int cnt) {
   134         return cnt == 0 ? startFirst() : start();
   135       }
   136 
   137     private:
   138     
   139       // Execute the algorithm for the first time (the flow and potential
   140       // functions have to be identically zero).
   141       bool startFirst() {
   142         HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
   143         Heap heap(heap_cross_ref);
   144         heap.push(_s, 0);
   145         _pred[_s] = INVALID;
   146         _proc_nodes.clear();
   147 
   148         // Process nodes
   149         while (!heap.empty() && heap.top() != _t) {
   150           Node u = heap.top(), v;
   151           Length d = heap.prio(), dn;
   152           _dist[u] = heap.prio();
   153           _proc_nodes.push_back(u);
   154           heap.pop();
   155 
   156           // Traverse outgoing arcs
   157           for (OutArcIt e(_graph, u); e != INVALID; ++e) {
   158             v = _graph.target(e);
   159             switch(heap.state(v)) {
   160               case Heap::PRE_HEAP:
   161                 heap.push(v, d + _length[e]);
   162                 _pred[v] = e;
   163                 break;
   164               case Heap::IN_HEAP:
   165                 dn = d + _length[e];
   166                 if (dn < heap[v]) {
   167                   heap.decrease(v, dn);
   168                   _pred[v] = e;
   169                 }
   170                 break;
   171               case Heap::POST_HEAP:
   172                 break;
   173             }
   174           }
   175         }
   176         if (heap.empty()) return false;
   177 
   178         // Update potentials of processed nodes
   179         Length t_dist = heap.prio();
   180         for (int i = 0; i < int(_proc_nodes.size()); ++i)
   181           _pi[_proc_nodes[i]] = _dist[_proc_nodes[i]] - t_dist;
   182         return true;
   183       }
   184 
   185       // Execute the algorithm.
   186       bool start() {
   187         HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
   188         Heap heap(heap_cross_ref);
   189         heap.push(_s, 0);
   190         _pred[_s] = INVALID;
   191         _proc_nodes.clear();
   192 
   193         // Process nodes
   194         while (!heap.empty() && heap.top() != _t) {
   195           Node u = heap.top(), v;
   196           Length d = heap.prio() + _pi[u], dn;
   197           _dist[u] = heap.prio();
   198           _proc_nodes.push_back(u);
   199           heap.pop();
   200 
   201           // Traverse outgoing arcs
   202           for (OutArcIt e(_graph, u); e != INVALID; ++e) {
   203             if (_flow[e] == 0) {
   204               v = _graph.target(e);
   205               switch(heap.state(v)) {
   206                 case Heap::PRE_HEAP:
   207                   heap.push(v, d + _length[e] - _pi[v]);
   208                   _pred[v] = e;
   209                   break;
   210                 case Heap::IN_HEAP:
   211                   dn = d + _length[e] - _pi[v];
   212                   if (dn < heap[v]) {
   213                     heap.decrease(v, dn);
   214                     _pred[v] = e;
   215                   }
   216                   break;
   217                 case Heap::POST_HEAP:
   218                   break;
   219               }
   220             }
   221           }
   222 
   223           // Traverse incoming arcs
   224           for (InArcIt e(_graph, u); e != INVALID; ++e) {
   225             if (_flow[e] == 1) {
   226               v = _graph.source(e);
   227               switch(heap.state(v)) {
   228                 case Heap::PRE_HEAP:
   229                   heap.push(v, d - _length[e] - _pi[v]);
   230                   _pred[v] = e;
   231                   break;
   232                 case Heap::IN_HEAP:
   233                   dn = d - _length[e] - _pi[v];
   234                   if (dn < heap[v]) {
   235                     heap.decrease(v, dn);
   236                     _pred[v] = e;
   237                   }
   238                   break;
   239                 case Heap::POST_HEAP:
   240                   break;
   241               }
   242             }
   243           }
   244         }
   245         if (heap.empty()) return false;
   246 
   247         // Update potentials of processed nodes
   248         Length t_dist = heap.prio();
   249         for (int i = 0; i < int(_proc_nodes.size()); ++i)
   250           _pi[_proc_nodes[i]] += _dist[_proc_nodes[i]] - t_dist;
   251         return true;
   252       }
   253 
   254     }; //class ResidualDijkstra
   255 
   256   private:
   257 
   258     // The digraph the algorithm runs on
   259     const Digraph &_graph;
   260     // The length map
   261     const LengthMap &_length;
   262 
   263     // Arc map of the current flow
   264     FlowMap *_flow;
   265     bool _local_flow;
   266     // Node map of the current potentials
   267     PotentialMap *_potential;
   268     bool _local_potential;
   269 
   270     // The source node
   271     Node _s;
   272     // The target node
   273     Node _t;
   274 
   275     // Container to store the found paths
   276     std::vector<Path> _paths;
   277     int _path_num;
   278 
   279     // The pred arc map
   280     PredMap _pred;
   281 
   282   public:
   283 
   284     /// \brief Constructor.
   285     ///
   286     /// Constructor.
   287     ///
   288     /// \param graph The digraph the algorithm runs on.
   289     /// \param length The length (cost) values of the arcs.
   290     Suurballe( const Digraph &graph,
   291                const LengthMap &length ) :
   292       _graph(graph), _length(length), _flow(0), _local_flow(false),
   293       _potential(0), _local_potential(false), _pred(graph)
   294     {}
   295 
   296     /// Destructor.
   297     ~Suurballe() {
   298       if (_local_flow) delete _flow;
   299       if (_local_potential) delete _potential;
   300     }
   301 
   302     /// \brief Set the flow map.
   303     ///
   304     /// This function sets the flow map.
   305     /// If it is not used before calling \ref run() or \ref init(),
   306     /// an instance will be allocated automatically. The destructor
   307     /// deallocates this automatically allocated map, of course.
   308     ///
   309     /// The found flow contains only 0 and 1 values, since it is the
   310     /// union of the found arc-disjoint paths.
   311     ///
   312     /// \return <tt>(*this)</tt>
   313     Suurballe& flowMap(FlowMap &map) {
   314       if (_local_flow) {
   315         delete _flow;
   316         _local_flow = false;
   317       }
   318       _flow = &map;
   319       return *this;
   320     }
   321 
   322     /// \brief Set the potential map.
   323     ///
   324     /// This function sets the potential map.
   325     /// If it is not used before calling \ref run() or \ref init(),
   326     /// an instance will be allocated automatically. The destructor
   327     /// deallocates this automatically allocated map, of course.
   328     ///
   329     /// The node potentials provide the dual solution of the underlying
   330     /// \ref min_cost_flow "minimum cost flow problem".
   331     ///
   332     /// \return <tt>(*this)</tt>
   333     Suurballe& potentialMap(PotentialMap &map) {
   334       if (_local_potential) {
   335         delete _potential;
   336         _local_potential = false;
   337       }
   338       _potential = &map;
   339       return *this;
   340     }
   341 
   342     /// \name Execution Control
   343     /// The simplest way to execute the algorithm is to call the run()
   344     /// function.
   345     /// \n
   346     /// If you only need the flow that is the union of the found
   347     /// arc-disjoint paths, you may call init() and findFlow().
   348 
   349     /// @{
   350 
   351     /// \brief Run the algorithm.
   352     ///
   353     /// This function runs the algorithm.
   354     ///
   355     /// \param s The source node.
   356     /// \param t The target node.
   357     /// \param k The number of paths to be found.
   358     ///
   359     /// \return \c k if there are at least \c k arc-disjoint paths from
   360     /// \c s to \c t in the digraph. Otherwise it returns the number of
   361     /// arc-disjoint paths found.
   362     ///
   363     /// \note Apart from the return value, <tt>s.run(s, t, k)</tt> is
   364     /// just a shortcut of the following code.
   365     /// \code
   366     ///   s.init(s);
   367     ///   s.findFlow(t, k);
   368     ///   s.findPaths();
   369     /// \endcode
   370     int run(const Node& s, const Node& t, int k = 2) {
   371       init(s);
   372       findFlow(t, k);
   373       findPaths();
   374       return _path_num;
   375     }
   376 
   377     /// \brief Initialize the algorithm.
   378     ///
   379     /// This function initializes the algorithm.
   380     ///
   381     /// \param s The source node.
   382     void init(const Node& s) {
   383       _s = s;
   384 
   385       // Initialize maps
   386       if (!_flow) {
   387         _flow = new FlowMap(_graph);
   388         _local_flow = true;
   389       }
   390       if (!_potential) {
   391         _potential = new PotentialMap(_graph);
   392         _local_potential = true;
   393       }
   394       for (ArcIt e(_graph); e != INVALID; ++e) (*_flow)[e] = 0;
   395       for (NodeIt n(_graph); n != INVALID; ++n) (*_potential)[n] = 0;
   396     }
   397 
   398     /// \brief Execute the algorithm to find an optimal flow.
   399     ///
   400     /// This function executes the successive shortest path algorithm to
   401     /// find a minimum cost flow, which is the union of \c k (or less)
   402     /// arc-disjoint paths.
   403     ///
   404     /// \param t The target node.
   405     /// \param k The number of paths to be found.
   406     ///
   407     /// \return \c k if there are at least \c k arc-disjoint paths from
   408     /// the source node to the given node \c t in the digraph.
   409     /// Otherwise it returns the number of arc-disjoint paths found.
   410     ///
   411     /// \pre \ref init() must be called before using this function.
   412     int findFlow(const Node& t, int k = 2) {
   413       _t = t;
   414       ResidualDijkstra dijkstra(*this);
   415 
   416       // Find shortest paths
   417       _path_num = 0;
   418       while (_path_num < k) {
   419         // Run Dijkstra
   420         if (!dijkstra.run(_path_num)) break;
   421         ++_path_num;
   422 
   423         // Set the flow along the found shortest path
   424         Node u = _t;
   425         Arc e;
   426         while ((e = _pred[u]) != INVALID) {
   427           if (u == _graph.target(e)) {
   428             (*_flow)[e] = 1;
   429             u = _graph.source(e);
   430           } else {
   431             (*_flow)[e] = 0;
   432             u = _graph.target(e);
   433           }
   434         }
   435       }
   436       return _path_num;
   437     }
   438 
   439     /// \brief Compute the paths from the flow.
   440     ///
   441     /// This function computes arc-disjoint paths from the found minimum
   442     /// cost flow, which is the union of them.
   443     ///
   444     /// \pre \ref init() and \ref findFlow() must be called before using
   445     /// this function.
   446     void findPaths() {
   447       FlowMap res_flow(_graph);
   448       for(ArcIt a(_graph); a != INVALID; ++a) res_flow[a] = (*_flow)[a];
   449 
   450       _paths.clear();
   451       _paths.resize(_path_num);
   452       for (int i = 0; i < _path_num; ++i) {
   453         Node n = _s;
   454         while (n != _t) {
   455           OutArcIt e(_graph, n);
   456           for ( ; res_flow[e] == 0; ++e) ;
   457           n = _graph.target(e);
   458           _paths[i].addBack(e);
   459           res_flow[e] = 0;
   460         }
   461       }
   462     }
   463 
   464     /// @}
   465 
   466     /// \name Query Functions
   467     /// The results of the algorithm can be obtained using these
   468     /// functions.
   469     /// \n The algorithm should be executed before using them.
   470 
   471     /// @{
   472 
   473     /// \brief Return the total length of the found paths.
   474     ///
   475     /// This function returns the total length of the found paths, i.e.
   476     /// the total cost of the found flow.
   477     /// The complexity of the function is O(e).
   478     ///
   479     /// \pre \ref run() or \ref findFlow() must be called before using
   480     /// this function.
   481     Length totalLength() const {
   482       Length c = 0;
   483       for (ArcIt e(_graph); e != INVALID; ++e)
   484         c += (*_flow)[e] * _length[e];
   485       return c;
   486     }
   487 
   488     /// \brief Return the flow value on the given arc.
   489     ///
   490     /// This function returns the flow value on the given arc.
   491     /// It is \c 1 if the arc is involved in one of the found arc-disjoint
   492     /// paths, otherwise it is \c 0.
   493     ///
   494     /// \pre \ref run() or \ref findFlow() must be called before using
   495     /// this function.
   496     int flow(const Arc& arc) const {
   497       return (*_flow)[arc];
   498     }
   499 
   500     /// \brief Return a const reference to an arc map storing the
   501     /// found flow.
   502     ///
   503     /// This function returns a const reference to an arc map storing
   504     /// the flow that is the union of the found arc-disjoint paths.
   505     ///
   506     /// \pre \ref run() or \ref findFlow() must be called before using
   507     /// this function.
   508     const FlowMap& flowMap() const {
   509       return *_flow;
   510     }
   511 
   512     /// \brief Return the potential of the given node.
   513     ///
   514     /// This function returns the potential of the given node.
   515     /// The node potentials provide the dual solution of the
   516     /// underlying \ref min_cost_flow "minimum cost flow problem".
   517     ///
   518     /// \pre \ref run() or \ref findFlow() must be called before using
   519     /// this function.
   520     Length potential(const Node& node) const {
   521       return (*_potential)[node];
   522     }
   523 
   524     /// \brief Return a const reference to a node map storing the
   525     /// found potentials (the dual solution).
   526     ///
   527     /// This function returns a const reference to a node map storing
   528     /// the found potentials that provide the dual solution of the
   529     /// underlying \ref min_cost_flow "minimum cost flow problem".
   530     ///
   531     /// \pre \ref run() or \ref findFlow() must be called before using
   532     /// this function.
   533     const PotentialMap& potentialMap() const {
   534       return *_potential;
   535     }
   536 
   537     /// \brief Return the number of the found paths.
   538     ///
   539     /// This function returns the number of the found paths.
   540     ///
   541     /// \pre \ref run() or \ref findFlow() must be called before using
   542     /// this function.
   543     int pathNum() const {
   544       return _path_num;
   545     }
   546 
   547     /// \brief Return a const reference to the specified path.
   548     ///
   549     /// This function returns a const reference to the specified path.
   550     ///
   551     /// \param i The function returns the <tt>i</tt>-th path.
   552     /// \c i must be between \c 0 and <tt>%pathNum()-1</tt>.
   553     ///
   554     /// \pre \ref run() or \ref findPaths() must be called before using
   555     /// this function.
   556     const Path& path(int i) const {
   557       return _paths[i];
   558     }
   559 
   560     /// @}
   561 
   562   }; //class Suurballe
   563 
   564   ///@}
   565 
   566 } //namespace lemon
   567 
   568 #endif //LEMON_SUURBALLE_H