lemon/suurballe.h
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 16 Oct 2009 02:32:30 +0200
changeset 927 9a7e4e606f83
parent 926 ec0b1b423b8b
child 931 abb95d48e89e
permissions -rw-r--r--
Add a fullInit() function to Suurballe (#181, #323)
to provide faster handling of multiple targets.
A start() function is also added, just for the sake of
convenience.
     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/dijkstra.h>
    33 #include <lemon/maps.h>
    34 
    35 namespace lemon {
    36 
    37   /// \addtogroup shortest_path
    38   /// @{
    39 
    40   /// \brief Algorithm for finding arc-disjoint paths between two nodes
    41   /// having minimum total length.
    42   ///
    43   /// \ref lemon::Suurballe "Suurballe" implements an algorithm for
    44   /// finding arc-disjoint paths having minimum total length (cost)
    45   /// from a given source node to a given target node in a digraph.
    46   ///
    47   /// Note that this problem is a special case of the \ref min_cost_flow
    48   /// "minimum cost flow problem". This implementation is actually an
    49   /// efficient specialized version of the \ref CapacityScaling
    50   /// "successive shortest path" algorithm directly for this problem.
    51   /// Therefore this class provides query functions for flow values and
    52   /// node potentials (the dual solution) just like the minimum cost flow
    53   /// algorithms.
    54   ///
    55   /// \tparam GR The digraph type the algorithm runs on.
    56   /// \tparam LEN The type of the length map.
    57   /// The default value is <tt>GR::ArcMap<int></tt>.
    58   ///
    59   /// \warning Length values should be \e non-negative.
    60   ///
    61   /// \note For finding \e node-disjoint paths, this algorithm can be used
    62   /// along with the \ref SplitNodes adaptor.
    63 #ifdef DOXYGEN
    64   template <typename GR, typename LEN>
    65 #else
    66   template < typename GR,
    67              typename LEN = typename GR::template ArcMap<int> >
    68 #endif
    69   class Suurballe
    70   {
    71     TEMPLATE_DIGRAPH_TYPEDEFS(GR);
    72 
    73     typedef ConstMap<Arc, int> ConstArcMap;
    74     typedef typename GR::template NodeMap<Arc> PredMap;
    75 
    76   public:
    77 
    78     /// The type of the digraph the algorithm runs on.
    79     typedef GR Digraph;
    80     /// The type of the length map.
    81     typedef LEN LengthMap;
    82     /// The type of the lengths.
    83     typedef typename LengthMap::Value Length;
    84 #ifdef DOXYGEN
    85     /// The type of the flow map.
    86     typedef GR::ArcMap<int> FlowMap;
    87     /// The type of the potential map.
    88     typedef GR::NodeMap<Length> PotentialMap;
    89 #else
    90     /// The type of the flow map.
    91     typedef typename Digraph::template ArcMap<int> FlowMap;
    92     /// The type of the potential map.
    93     typedef typename Digraph::template NodeMap<Length> PotentialMap;
    94 #endif
    95 
    96     /// The type of the path structures.
    97     typedef SimplePath<GR> Path;
    98 
    99   private:
   100 
   101     typedef typename Digraph::template NodeMap<int> HeapCrossRef;
   102     typedef BinHeap<Length, HeapCrossRef> Heap;
   103 
   104     // ResidualDijkstra is a special implementation of the
   105     // Dijkstra algorithm for finding shortest paths in the
   106     // residual network with respect to the reduced arc lengths
   107     // and modifying the node potentials according to the
   108     // distance of the nodes.
   109     class ResidualDijkstra
   110     {
   111     private:
   112 
   113       const Digraph &_graph;
   114       const LengthMap &_length;
   115       const FlowMap &_flow;
   116       PotentialMap &_pi;
   117       PredMap &_pred;
   118       Node _s;
   119       Node _t;
   120       
   121       PotentialMap _dist;
   122       std::vector<Node> _proc_nodes;
   123 
   124     public:
   125 
   126       // Constructor
   127       ResidualDijkstra(Suurballe &srb) :
   128         _graph(srb._graph), _length(srb._length),
   129         _flow(*srb._flow), _pi(*srb._potential), _pred(srb._pred), 
   130         _s(srb._s), _t(srb._t), _dist(_graph) {}
   131         
   132       // Run the algorithm and return true if a path is found
   133       // from the source node to the target node.
   134       bool run(int cnt) {
   135         return cnt == 0 ? startFirst() : start();
   136       }
   137 
   138     private:
   139     
   140       // Execute the algorithm for the first time (the flow and potential
   141       // functions have to be identically zero).
   142       bool startFirst() {
   143         HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
   144         Heap heap(heap_cross_ref);
   145         heap.push(_s, 0);
   146         _pred[_s] = INVALID;
   147         _proc_nodes.clear();
   148 
   149         // Process nodes
   150         while (!heap.empty() && heap.top() != _t) {
   151           Node u = heap.top(), v;
   152           Length d = heap.prio(), dn;
   153           _dist[u] = heap.prio();
   154           _proc_nodes.push_back(u);
   155           heap.pop();
   156 
   157           // Traverse outgoing arcs
   158           for (OutArcIt e(_graph, u); e != INVALID; ++e) {
   159             v = _graph.target(e);
   160             switch(heap.state(v)) {
   161               case Heap::PRE_HEAP:
   162                 heap.push(v, d + _length[e]);
   163                 _pred[v] = e;
   164                 break;
   165               case Heap::IN_HEAP:
   166                 dn = d + _length[e];
   167                 if (dn < heap[v]) {
   168                   heap.decrease(v, dn);
   169                   _pred[v] = e;
   170                 }
   171                 break;
   172               case Heap::POST_HEAP:
   173                 break;
   174             }
   175           }
   176         }
   177         if (heap.empty()) return false;
   178 
   179         // Update potentials of processed nodes
   180         Length t_dist = heap.prio();
   181         for (int i = 0; i < int(_proc_nodes.size()); ++i)
   182           _pi[_proc_nodes[i]] = _dist[_proc_nodes[i]] - t_dist;
   183         return true;
   184       }
   185 
   186       // Execute the algorithm.
   187       bool start() {
   188         HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
   189         Heap heap(heap_cross_ref);
   190         heap.push(_s, 0);
   191         _pred[_s] = INVALID;
   192         _proc_nodes.clear();
   193 
   194         // Process nodes
   195         while (!heap.empty() && heap.top() != _t) {
   196           Node u = heap.top(), v;
   197           Length d = heap.prio() + _pi[u], dn;
   198           _dist[u] = heap.prio();
   199           _proc_nodes.push_back(u);
   200           heap.pop();
   201 
   202           // Traverse outgoing arcs
   203           for (OutArcIt e(_graph, u); e != INVALID; ++e) {
   204             if (_flow[e] == 0) {
   205               v = _graph.target(e);
   206               switch(heap.state(v)) {
   207                 case Heap::PRE_HEAP:
   208                   heap.push(v, d + _length[e] - _pi[v]);
   209                   _pred[v] = e;
   210                   break;
   211                 case Heap::IN_HEAP:
   212                   dn = d + _length[e] - _pi[v];
   213                   if (dn < heap[v]) {
   214                     heap.decrease(v, dn);
   215                     _pred[v] = e;
   216                   }
   217                   break;
   218                 case Heap::POST_HEAP:
   219                   break;
   220               }
   221             }
   222           }
   223 
   224           // Traverse incoming arcs
   225           for (InArcIt e(_graph, u); e != INVALID; ++e) {
   226             if (_flow[e] == 1) {
   227               v = _graph.source(e);
   228               switch(heap.state(v)) {
   229                 case Heap::PRE_HEAP:
   230                   heap.push(v, d - _length[e] - _pi[v]);
   231                   _pred[v] = e;
   232                   break;
   233                 case Heap::IN_HEAP:
   234                   dn = d - _length[e] - _pi[v];
   235                   if (dn < heap[v]) {
   236                     heap.decrease(v, dn);
   237                     _pred[v] = e;
   238                   }
   239                   break;
   240                 case Heap::POST_HEAP:
   241                   break;
   242               }
   243             }
   244           }
   245         }
   246         if (heap.empty()) return false;
   247 
   248         // Update potentials of processed nodes
   249         Length t_dist = heap.prio();
   250         for (int i = 0; i < int(_proc_nodes.size()); ++i)
   251           _pi[_proc_nodes[i]] += _dist[_proc_nodes[i]] - t_dist;
   252         return true;
   253       }
   254 
   255     }; //class ResidualDijkstra
   256 
   257   private:
   258 
   259     // The digraph the algorithm runs on
   260     const Digraph &_graph;
   261     // The length map
   262     const LengthMap &_length;
   263 
   264     // Arc map of the current flow
   265     FlowMap *_flow;
   266     bool _local_flow;
   267     // Node map of the current potentials
   268     PotentialMap *_potential;
   269     bool _local_potential;
   270 
   271     // The source node
   272     Node _s;
   273     // The target node
   274     Node _t;
   275 
   276     // Container to store the found paths
   277     std::vector<Path> _paths;
   278     int _path_num;
   279 
   280     // The pred arc map
   281     PredMap _pred;
   282     
   283     // Data for full init
   284     PotentialMap *_init_dist;
   285     PredMap *_init_pred;
   286     bool _full_init;
   287 
   288   public:
   289 
   290     /// \brief Constructor.
   291     ///
   292     /// Constructor.
   293     ///
   294     /// \param graph The digraph the algorithm runs on.
   295     /// \param length The length (cost) values of the arcs.
   296     Suurballe( const Digraph &graph,
   297                const LengthMap &length ) :
   298       _graph(graph), _length(length), _flow(0), _local_flow(false),
   299       _potential(0), _local_potential(false), _pred(graph),
   300       _init_dist(0), _init_pred(0)
   301     {}
   302 
   303     /// Destructor.
   304     ~Suurballe() {
   305       if (_local_flow) delete _flow;
   306       if (_local_potential) delete _potential;
   307       delete _init_dist;
   308       delete _init_pred;
   309     }
   310 
   311     /// \brief Set the flow map.
   312     ///
   313     /// This function sets the flow map.
   314     /// If it is not used before calling \ref run() or \ref init(),
   315     /// an instance will be allocated automatically. The destructor
   316     /// deallocates this automatically allocated map, of course.
   317     ///
   318     /// The found flow contains only 0 and 1 values, since it is the
   319     /// union of the found arc-disjoint paths.
   320     ///
   321     /// \return <tt>(*this)</tt>
   322     Suurballe& flowMap(FlowMap &map) {
   323       if (_local_flow) {
   324         delete _flow;
   325         _local_flow = false;
   326       }
   327       _flow = &map;
   328       return *this;
   329     }
   330 
   331     /// \brief Set the potential map.
   332     ///
   333     /// This function sets the potential map.
   334     /// If it is not used before calling \ref run() or \ref init(),
   335     /// an instance will be allocated automatically. The destructor
   336     /// deallocates this automatically allocated map, of course.
   337     ///
   338     /// The node potentials provide the dual solution of the underlying
   339     /// \ref min_cost_flow "minimum cost flow problem".
   340     ///
   341     /// \return <tt>(*this)</tt>
   342     Suurballe& potentialMap(PotentialMap &map) {
   343       if (_local_potential) {
   344         delete _potential;
   345         _local_potential = false;
   346       }
   347       _potential = &map;
   348       return *this;
   349     }
   350 
   351     /// \name Execution Control
   352     /// The simplest way to execute the algorithm is to call the run()
   353     /// function.\n
   354     /// If you need to execute the algorithm many times using the same
   355     /// source node, then you may call fullInit() once and start()
   356     /// for each target node.\n
   357     /// If you only need the flow that is the union of the found
   358     /// arc-disjoint paths, then you may call findFlow() instead of
   359     /// start().
   360 
   361     /// @{
   362 
   363     /// \brief Run the algorithm.
   364     ///
   365     /// This function runs the algorithm.
   366     ///
   367     /// \param s The source node.
   368     /// \param t The target node.
   369     /// \param k The number of paths to be found.
   370     ///
   371     /// \return \c k if there are at least \c k arc-disjoint paths from
   372     /// \c s to \c t in the digraph. Otherwise it returns the number of
   373     /// arc-disjoint paths found.
   374     ///
   375     /// \note Apart from the return value, <tt>s.run(s, t, k)</tt> is
   376     /// just a shortcut of the following code.
   377     /// \code
   378     ///   s.init(s);
   379     ///   s.start(t, k);
   380     /// \endcode
   381     int run(const Node& s, const Node& t, int k = 2) {
   382       init(s);
   383       start(t, k);
   384       return _path_num;
   385     }
   386 
   387     /// \brief Initialize the algorithm.
   388     ///
   389     /// This function initializes the algorithm with the given source node.
   390     ///
   391     /// \param s The source node.
   392     void init(const Node& s) {
   393       _s = s;
   394 
   395       // Initialize maps
   396       if (!_flow) {
   397         _flow = new FlowMap(_graph);
   398         _local_flow = true;
   399       }
   400       if (!_potential) {
   401         _potential = new PotentialMap(_graph);
   402         _local_potential = true;
   403       }
   404       _full_init = false;
   405     }
   406 
   407     /// \brief Initialize the algorithm and perform Dijkstra.
   408     ///
   409     /// This function initializes the algorithm and performs a full
   410     /// Dijkstra search from the given source node. It makes consecutive
   411     /// executions of \ref start() "start(t, k)" faster, since they
   412     /// have to perform %Dijkstra only k-1 times.
   413     ///
   414     /// This initialization is usually worth using instead of \ref init()
   415     /// if the algorithm is executed many times using the same source node.
   416     ///
   417     /// \param s The source node.
   418     void fullInit(const Node& s) {
   419       // Initialize maps
   420       init(s);
   421       if (!_init_dist) {
   422         _init_dist = new PotentialMap(_graph);
   423       }
   424       if (!_init_pred) {
   425         _init_pred = new PredMap(_graph);
   426       }
   427 
   428       // Run a full Dijkstra
   429       typename Dijkstra<Digraph, LengthMap>
   430         ::template SetStandardHeap<Heap>
   431         ::template SetDistMap<PotentialMap>
   432         ::template SetPredMap<PredMap>
   433         ::Create dijk(_graph, _length);
   434       dijk.distMap(*_init_dist).predMap(*_init_pred);
   435       dijk.run(s);
   436       
   437       _full_init = true;
   438     }
   439 
   440     /// \brief Execute the algorithm.
   441     ///
   442     /// This function executes the algorithm.
   443     ///
   444     /// \param t The target node.
   445     /// \param k The number of paths to be found.
   446     ///
   447     /// \return \c k if there are at least \c k arc-disjoint paths from
   448     /// \c s to \c t in the digraph. Otherwise it returns the number of
   449     /// arc-disjoint paths found.
   450     ///
   451     /// \note Apart from the return value, <tt>s.start(t, k)</tt> is
   452     /// just a shortcut of the following code.
   453     /// \code
   454     ///   s.findFlow(t, k);
   455     ///   s.findPaths();
   456     /// \endcode
   457     int start(const Node& t, int k = 2) {
   458       findFlow(t, k);
   459       findPaths();
   460       return _path_num;
   461     }
   462 
   463     /// \brief Execute the algorithm to find an optimal flow.
   464     ///
   465     /// This function executes the successive shortest path algorithm to
   466     /// find a minimum cost flow, which is the union of \c k (or less)
   467     /// arc-disjoint paths.
   468     ///
   469     /// \param t The target node.
   470     /// \param k The number of paths to be found.
   471     ///
   472     /// \return \c k if there are at least \c k arc-disjoint paths from
   473     /// the source node to the given node \c t in the digraph.
   474     /// Otherwise it returns the number of arc-disjoint paths found.
   475     ///
   476     /// \pre \ref init() must be called before using this function.
   477     int findFlow(const Node& t, int k = 2) {
   478       _t = t;
   479       ResidualDijkstra dijkstra(*this);
   480       
   481       // Initialization
   482       for (ArcIt e(_graph); e != INVALID; ++e) {
   483         (*_flow)[e] = 0;
   484       }
   485       if (_full_init) {
   486         for (NodeIt n(_graph); n != INVALID; ++n) {
   487           (*_potential)[n] = (*_init_dist)[n];
   488         }
   489         Node u = _t;
   490         Arc e;
   491         while ((e = (*_init_pred)[u]) != INVALID) {
   492           (*_flow)[e] = 1;
   493           u = _graph.source(e);
   494         }        
   495         _path_num = 1;
   496       } else {
   497         for (NodeIt n(_graph); n != INVALID; ++n) {
   498           (*_potential)[n] = 0;
   499         }
   500         _path_num = 0;
   501       }
   502 
   503       // Find shortest paths
   504       while (_path_num < k) {
   505         // Run Dijkstra
   506         if (!dijkstra.run(_path_num)) break;
   507         ++_path_num;
   508 
   509         // Set the flow along the found shortest path
   510         Node u = _t;
   511         Arc e;
   512         while ((e = _pred[u]) != INVALID) {
   513           if (u == _graph.target(e)) {
   514             (*_flow)[e] = 1;
   515             u = _graph.source(e);
   516           } else {
   517             (*_flow)[e] = 0;
   518             u = _graph.target(e);
   519           }
   520         }
   521       }
   522       return _path_num;
   523     }
   524 
   525     /// \brief Compute the paths from the flow.
   526     ///
   527     /// This function computes arc-disjoint paths from the found minimum
   528     /// cost flow, which is the union of them.
   529     ///
   530     /// \pre \ref init() and \ref findFlow() must be called before using
   531     /// this function.
   532     void findPaths() {
   533       FlowMap res_flow(_graph);
   534       for(ArcIt a(_graph); a != INVALID; ++a) res_flow[a] = (*_flow)[a];
   535 
   536       _paths.clear();
   537       _paths.resize(_path_num);
   538       for (int i = 0; i < _path_num; ++i) {
   539         Node n = _s;
   540         while (n != _t) {
   541           OutArcIt e(_graph, n);
   542           for ( ; res_flow[e] == 0; ++e) ;
   543           n = _graph.target(e);
   544           _paths[i].addBack(e);
   545           res_flow[e] = 0;
   546         }
   547       }
   548     }
   549 
   550     /// @}
   551 
   552     /// \name Query Functions
   553     /// The results of the algorithm can be obtained using these
   554     /// functions.
   555     /// \n The algorithm should be executed before using them.
   556 
   557     /// @{
   558 
   559     /// \brief Return the total length of the found paths.
   560     ///
   561     /// This function returns the total length of the found paths, i.e.
   562     /// the total cost of the found flow.
   563     /// The complexity of the function is O(e).
   564     ///
   565     /// \pre \ref run() or \ref findFlow() must be called before using
   566     /// this function.
   567     Length totalLength() const {
   568       Length c = 0;
   569       for (ArcIt e(_graph); e != INVALID; ++e)
   570         c += (*_flow)[e] * _length[e];
   571       return c;
   572     }
   573 
   574     /// \brief Return the flow value on the given arc.
   575     ///
   576     /// This function returns the flow value on the given arc.
   577     /// It is \c 1 if the arc is involved in one of the found arc-disjoint
   578     /// paths, otherwise it is \c 0.
   579     ///
   580     /// \pre \ref run() or \ref findFlow() must be called before using
   581     /// this function.
   582     int flow(const Arc& arc) const {
   583       return (*_flow)[arc];
   584     }
   585 
   586     /// \brief Return a const reference to an arc map storing the
   587     /// found flow.
   588     ///
   589     /// This function returns a const reference to an arc map storing
   590     /// the flow that is the union of the found arc-disjoint paths.
   591     ///
   592     /// \pre \ref run() or \ref findFlow() must be called before using
   593     /// this function.
   594     const FlowMap& flowMap() const {
   595       return *_flow;
   596     }
   597 
   598     /// \brief Return the potential of the given node.
   599     ///
   600     /// This function returns the potential of the given node.
   601     /// The node potentials provide the dual solution of the
   602     /// underlying \ref min_cost_flow "minimum cost flow problem".
   603     ///
   604     /// \pre \ref run() or \ref findFlow() must be called before using
   605     /// this function.
   606     Length potential(const Node& node) const {
   607       return (*_potential)[node];
   608     }
   609 
   610     /// \brief Return a const reference to a node map storing the
   611     /// found potentials (the dual solution).
   612     ///
   613     /// This function returns a const reference to a node map storing
   614     /// the found potentials that provide the dual solution of the
   615     /// underlying \ref min_cost_flow "minimum cost flow problem".
   616     ///
   617     /// \pre \ref run() or \ref findFlow() must be called before using
   618     /// this function.
   619     const PotentialMap& potentialMap() const {
   620       return *_potential;
   621     }
   622 
   623     /// \brief Return the number of the found paths.
   624     ///
   625     /// This function returns the number of the found paths.
   626     ///
   627     /// \pre \ref run() or \ref findFlow() must be called before using
   628     /// this function.
   629     int pathNum() const {
   630       return _path_num;
   631     }
   632 
   633     /// \brief Return a const reference to the specified path.
   634     ///
   635     /// This function returns a const reference to the specified path.
   636     ///
   637     /// \param i The function returns the <tt>i</tt>-th path.
   638     /// \c i must be between \c 0 and <tt>%pathNum()-1</tt>.
   639     ///
   640     /// \pre \ref run() or \ref findPaths() must be called before using
   641     /// this function.
   642     const Path& path(int i) const {
   643       return _paths[i];
   644     }
   645 
   646     /// @}
   647 
   648   }; //class Suurballe
   649 
   650   ///@}
   651 
   652 } //namespace lemon
   653 
   654 #endif //LEMON_SUURBALLE_H