# HG changeset patch
# User Peter Kovacs <kpeter@inf.elte.hu>
# Date 1240618361 -7200
# Node ID 7c1324b35d89a2ef91a42e14fae342b651db4549
# Parent  28f58740b6f8f168a125b9af4c4cf141400645d2
Modify the interface of Suurballe (#266, #181)

 - Move the parameters s and t from the constructor to the run()
   function. It makes the interface capable for multiple run(s,t,k)
   calls (possible improvement in the future) and it is more similar
   to Dijkstra.
 - Simliarly init() and findFlow(k) were replaced by init(s) and
   findFlow(t,k). The separation of parameters s and t is for the
   future plans of supporting multiple targets with one source node.
   For more information see #181.
 - LEMON_ASSERT for the Length type (check if it is integer).
 - Doc improvements.
 - Rearrange query functions.
 - Extend test file.

diff -r 28f58740b6f8 -r 7c1324b35d89 lemon/suurballe.h
--- a/lemon/suurballe.h	Sat Apr 25 18:25:59 2009 +0200
+++ b/lemon/suurballe.h	Sat Apr 25 02:12:41 2009 +0200
@@ -25,6 +25,7 @@
 /// nodes having minimum total length.
 
 #include <vector>
+#include <limits>
 #include <lemon/bin_heap.h>
 #include <lemon/path.h>
 #include <lemon/list_graph.h>
@@ -42,22 +43,26 @@
   /// finding arc-disjoint paths having minimum total length (cost)
   /// from a given source node to a given target node in a digraph.
   ///
-  /// In fact, this implementation is the specialization of the
-  /// \ref CapacityScaling "successive shortest path" algorithm.
+  /// Note that this problem is a special case of the \ref min_cost_flow
+  /// "minimum cost flow problem". This implementation is actually an
+  /// efficient specialized version of the \ref CapacityScaling
+  /// "Successive Shortest Path" algorithm directly for this problem.
+  /// Therefore this class provides query functions for flow values and
+  /// node potentials (the dual solution) just like the minimum cost flow
+  /// algorithms.
   ///
   /// \tparam GR The digraph type the algorithm runs on.
-  /// The default value is \c ListDigraph.
-  /// \tparam LEN The type of the length (cost) map.
-  /// The default value is <tt>Digraph::ArcMap<int></tt>.
+  /// \tparam LEN The type of the length map.
+  /// The default value is <tt>GR::ArcMap<int></tt>.
   ///
   /// \warning Length values should be \e non-negative \e integers.
   ///
   /// \note For finding node-disjoint paths this algorithm can be used
-  /// with \ref SplitNodes.
+  /// along with the \ref SplitNodes adaptor.
 #ifdef DOXYGEN
   template <typename GR, typename LEN>
 #else
-  template < typename GR = ListDigraph,
+  template < typename GR,
              typename LEN = typename GR::template ArcMap<int> >
 #endif
   class Suurballe
@@ -75,23 +80,28 @@
     typedef LEN LengthMap;
     /// The type of the lengths.
     typedef typename LengthMap::Value Length;
+#ifdef DOXYGEN
+    /// The type of the flow map.
+    typedef GR::ArcMap<int> FlowMap;
+    /// The type of the potential map.
+    typedef GR::NodeMap<Length> PotentialMap;
+#else
     /// The type of the flow map.
     typedef typename Digraph::template ArcMap<int> FlowMap;
     /// The type of the potential map.
     typedef typename Digraph::template NodeMap<Length> PotentialMap;
+#endif
+
     /// The type of the path structures.
-    typedef SimplePath<Digraph> Path;
+    typedef SimplePath<GR> Path;
 
   private:
 
-    /// \brief Special implementation of the Dijkstra algorithm
-    /// for finding shortest paths in the residual network.
-    ///
-    /// \ref ResidualDijkstra is a special implementation of the
-    /// \ref Dijkstra algorithm for finding shortest paths in the
-    /// residual network of the digraph with respect to the reduced arc
-    /// lengths and modifying the node potentials according to the
-    /// distance of the nodes.
+    // ResidualDijkstra is a special implementation of the
+    // Dijkstra algorithm for finding shortest paths in the
+    // residual network with respect to the reduced arc lengths
+    // and modifying the node potentials according to the
+    // distance of the nodes.
     class ResidualDijkstra
     {
       typedef typename Digraph::template NodeMap<int> HeapCrossRef;
@@ -120,14 +130,14 @@
     public:
 
       /// Constructor.
-      ResidualDijkstra( const Digraph &digraph,
+      ResidualDijkstra( const Digraph &graph,
                         const FlowMap &flow,
                         const LengthMap &length,
                         PotentialMap &potential,
                         PredMap &pred,
                         Node s, Node t ) :
-        _graph(digraph), _flow(flow), _length(length), _potential(potential),
-        _dist(digraph), _pred(pred), _s(s), _t(t) {}
+        _graph(graph), _flow(flow), _length(length), _potential(potential),
+        _dist(graph), _pred(pred), _s(s), _t(t) {}
 
       /// \brief Run the algorithm. It returns \c true if a path is found
       /// from the source node to the target node.
@@ -236,16 +246,16 @@
     ///
     /// Constructor.
     ///
-    /// \param digraph The digraph the algorithm runs on.
+    /// \param graph The digraph the algorithm runs on.
     /// \param length The length (cost) values of the arcs.
-    /// \param s The source node.
-    /// \param t The target node.
-    Suurballe( const Digraph &digraph,
-               const LengthMap &length,
-               Node s, Node t ) :
-      _graph(digraph), _length(length), _flow(0), _local_flow(false),
-      _potential(0), _local_potential(false), _source(s), _target(t),
-      _pred(digraph) {}
+    Suurballe( const Digraph &graph,
+               const LengthMap &length ) :
+      _graph(graph), _length(length), _flow(0), _local_flow(false),
+      _potential(0), _local_potential(false), _pred(graph)
+    {
+      LEMON_ASSERT(std::numeric_limits<Length>::is_integer,
+        "The length type of Suurballe must be integer");
+    }
 
     /// Destructor.
     ~Suurballe() {
@@ -257,9 +267,12 @@
     /// \brief Set the flow map.
     ///
     /// This function sets the flow map.
+    /// If it is not used before calling \ref run() or \ref init(),
+    /// an instance will be allocated automatically. The destructor
+    /// deallocates this automatically allocated map, of course.
     ///
-    /// The found flow contains only 0 and 1 values. It is the union of
-    /// the found arc-disjoint paths.
+    /// The found flow contains only 0 and 1 values, since it is the
+    /// union of the found arc-disjoint paths.
     ///
     /// \return <tt>(*this)</tt>
     Suurballe& flowMap(FlowMap &map) {
@@ -274,9 +287,12 @@
     /// \brief Set the potential map.
     ///
     /// This function sets the potential map.
+    /// If it is not used before calling \ref run() or \ref init(),
+    /// an instance will be allocated automatically. The destructor
+    /// deallocates this automatically allocated map, of course.
     ///
-    /// The potentials provide the dual solution of the underlying
-    /// minimum cost flow problem.
+    /// The node potentials provide the dual solution of the underlying
+    /// \ref min_cost_flow "minimum cost flow problem".
     ///
     /// \return <tt>(*this)</tt>
     Suurballe& potentialMap(PotentialMap &map) {
@@ -301,22 +317,24 @@
     ///
     /// This function runs the algorithm.
     ///
+    /// \param s The source node.
+    /// \param t The target node.
     /// \param k The number of paths to be found.
     ///
     /// \return \c k if there are at least \c k arc-disjoint paths from
     /// \c s to \c t in the digraph. Otherwise it returns the number of
     /// arc-disjoint paths found.
     ///
-    /// \note Apart from the return value, <tt>s.run(k)</tt> is just a
-    /// shortcut of the following code.
+    /// \note Apart from the return value, <tt>s.run(s, t, k)</tt> is
+    /// just a shortcut of the following code.
     /// \code
-    ///   s.init();
-    ///   s.findFlow(k);
+    ///   s.init(s);
+    ///   s.findFlow(t, k);
     ///   s.findPaths();
     /// \endcode
-    int run(int k = 2) {
-      init();
-      findFlow(k);
+    int run(const Node& s, const Node& t, int k = 2) {
+      init(s);
+      findFlow(t, k);
       findPaths();
       return _path_num;
     }
@@ -324,7 +342,11 @@
     /// \brief Initialize the algorithm.
     ///
     /// This function initializes the algorithm.
-    void init() {
+    ///
+    /// \param s The source node.
+    void init(const Node& s) {
+      _source = s;
+
       // Initialize maps
       if (!_flow) {
         _flow = new FlowMap(_graph);
@@ -336,25 +358,28 @@
       }
       for (ArcIt e(_graph); e != INVALID; ++e) (*_flow)[e] = 0;
       for (NodeIt n(_graph); n != INVALID; ++n) (*_potential)[n] = 0;
-
-      _dijkstra = new ResidualDijkstra( _graph, *_flow, _length,
-                                        *_potential, _pred,
-                                        _source, _target );
     }
 
-    /// \brief Execute the successive shortest path algorithm to find
-    /// an optimal flow.
+    /// \brief Execute the algorithm to find an optimal flow.
     ///
     /// This function executes the successive shortest path algorithm to
-    /// find a minimum cost flow, which is the union of \c k or less
+    /// find a minimum cost flow, which is the union of \c k (or less)
     /// arc-disjoint paths.
     ///
+    /// \param t The target node.
+    /// \param k The number of paths to be found.
+    ///
     /// \return \c k if there are at least \c k arc-disjoint paths from
-    /// \c s to \c t in the digraph. Otherwise it returns the number of
-    /// arc-disjoint paths found.
+    /// the source node to the given node \c t in the digraph.
+    /// Otherwise it returns the number of arc-disjoint paths found.
     ///
     /// \pre \ref init() must be called before using this function.
-    int findFlow(int k = 2) {
+    int findFlow(const Node& t, int k = 2) {
+      _target = t;
+      _dijkstra =
+        new ResidualDijkstra( _graph, *_flow, _length, *_potential, _pred,
+                              _source, _target );
+
       // Find shortest paths
       _path_num = 0;
       while (_path_num < k) {
@@ -380,13 +405,12 @@
 
     /// \brief Compute the paths from the flow.
     ///
-    /// This function computes the paths from the flow.
+    /// This function computes the paths from the found minimum cost flow,
+    /// which is the union of some arc-disjoint paths.
     ///
     /// \pre \ref init() and \ref findFlow() must be called before using
     /// this function.
     void findPaths() {
-      // Create the residual flow map (the union of the paths not found
-      // so far)
       FlowMap res_flow(_graph);
       for(ArcIt a(_graph); a != INVALID; ++a) res_flow[a] = (*_flow)[a];
 
@@ -413,10 +437,37 @@
 
     /// @{
 
-    /// \brief Return a const reference to the arc map storing the
+    /// \brief Return the total length of the found paths.
+    ///
+    /// This function returns the total length of the found paths, i.e.
+    /// the total cost of the found flow.
+    /// The complexity of the function is O(e).
+    ///
+    /// \pre \ref run() or \ref findFlow() must be called before using
+    /// this function.
+    Length totalLength() const {
+      Length c = 0;
+      for (ArcIt e(_graph); e != INVALID; ++e)
+        c += (*_flow)[e] * _length[e];
+      return c;
+    }
+
+    /// \brief Return the flow value on the given arc.
+    ///
+    /// This function returns the flow value on the given arc.
+    /// It is \c 1 if the arc is involved in one of the found arc-disjoint
+    /// paths, otherwise it is \c 0.
+    ///
+    /// \pre \ref run() or \ref findFlow() must be called before using
+    /// this function.
+    int flow(const Arc& arc) const {
+      return (*_flow)[arc];
+    }
+
+    /// \brief Return a const reference to an arc map storing the
     /// found flow.
     ///
-    /// This function returns a const reference to the arc map storing
+    /// This function returns a const reference to an arc map storing
     /// the flow that is the union of the found arc-disjoint paths.
     ///
     /// \pre \ref run() or \ref findFlow() must be called before using
@@ -425,34 +476,11 @@
       return *_flow;
     }
 
-    /// \brief Return a const reference to the node map storing the
-    /// found potentials (the dual solution).
-    ///
-    /// This function returns a const reference to the node map storing
-    /// the found potentials that provide the dual solution of the
-    /// underlying minimum cost flow problem.
-    ///
-    /// \pre \ref run() or \ref findFlow() must be called before using
-    /// this function.
-    const PotentialMap& potentialMap() const {
-      return *_potential;
-    }
-
-    /// \brief Return the flow on the given arc.
-    ///
-    /// This function returns the flow on the given arc.
-    /// It is \c 1 if the arc is involved in one of the found paths,
-    /// otherwise it is \c 0.
-    ///
-    /// \pre \ref run() or \ref findFlow() must be called before using
-    /// this function.
-    int flow(const Arc& arc) const {
-      return (*_flow)[arc];
-    }
-
     /// \brief Return the potential of the given node.
     ///
     /// This function returns the potential of the given node.
+    /// The node potentials provide the dual solution of the
+    /// underlying \ref min_cost_flow "minimum cost flow problem".
     ///
     /// \pre \ref run() or \ref findFlow() must be called before using
     /// this function.
@@ -460,18 +488,17 @@
       return (*_potential)[node];
     }
 
-    /// \brief Return the total length (cost) of the found paths (flow).
+    /// \brief Return a const reference to a node map storing the
+    /// found potentials (the dual solution).
     ///
-    /// This function returns the total length (cost) of the found paths
-    /// (flow). The complexity of the function is O(e).
+    /// This function returns a const reference to a node map storing
+    /// the found potentials that provide the dual solution of the
+    /// underlying \ref min_cost_flow "minimum cost flow problem".
     ///
     /// \pre \ref run() or \ref findFlow() must be called before using
     /// this function.
-    Length totalLength() const {
-      Length c = 0;
-      for (ArcIt e(_graph); e != INVALID; ++e)
-        c += (*_flow)[e] * _length[e];
-      return c;
+    const PotentialMap& potentialMap() const {
+      return *_potential;
     }
 
     /// \brief Return the number of the found paths.
@@ -488,7 +515,7 @@
     ///
     /// This function returns a const reference to the specified path.
     ///
-    /// \param i The function returns the \c i-th path.
+    /// \param i The function returns the <tt>i</tt>-th path.
     /// \c i must be between \c 0 and <tt>%pathNum()-1</tt>.
     ///
     /// \pre \ref run() or \ref findPaths() must be called before using
diff -r 28f58740b6f8 -r 7c1324b35d89 test/suurballe_test.cc
--- a/test/suurballe_test.cc	Sat Apr 25 18:25:59 2009 +0200
+++ b/test/suurballe_test.cc	Sat Apr 25 02:12:41 2009 +0200
@@ -22,6 +22,7 @@
 #include <lemon/lgf_reader.h>
 #include <lemon/path.h>
 #include <lemon/suurballe.h>
+#include <lemon/concepts/digraph.h>
 
 #include "test_tools.h"
 
@@ -29,47 +30,97 @@
 
 char test_lgf[] =
   "@nodes\n"
-  "label supply1 supply2 supply3\n"
-  "1     0        20      27\n"
-  "2     0       -4        0\n"
-  "3     0        0        0\n"
-  "4     0        0        0\n"
-  "5     0        9        0\n"
-  "6     0       -6        0\n"
-  "7     0        0        0\n"
-  "8     0        0        0\n"
-  "9     0        3        0\n"
-  "10    0       -2        0\n"
-  "11    0        0        0\n"
-  "12    0       -20     -27\n"
+  "label\n"
+  "1\n"
+  "2\n"
+  "3\n"
+  "4\n"
+  "5\n"
+  "6\n"
+  "7\n"
+  "8\n"
+  "9\n"
+  "10\n"
+  "11\n"
+  "12\n"
   "@arcs\n"
-  "      cost capacity lower1 lower2\n"
-  " 1  2  70  11       0      8\n"
-  " 1  3 150   3       0      1\n"
-  " 1  4  80  15       0      2\n"
-  " 2  8  80  12       0      0\n"
-  " 3  5 140   5       0      3\n"
-  " 4  6  60  10       0      1\n"
-  " 4  7  80   2       0      0\n"
-  " 4  8 110   3       0      0\n"
-  " 5  7  60  14       0      0\n"
-  " 5 11 120  12       0      0\n"
-  " 6  3   0   3       0      0\n"
-  " 6  9 140   4       0      0\n"
-  " 6 10  90   8       0      0\n"
-  " 7  1  30   5       0      0\n"
-  " 8 12  60  16       0      4\n"
-  " 9 12  50   6       0      0\n"
-  "10 12  70  13       0      5\n"
-  "10  2 100   7       0      0\n"
-  "10  7  60  10       0      0\n"
-  "11 10  20  14       0      6\n"
-  "12 11  30  10       0      0\n"
+  "      length\n"
+  " 1  2  70\n"
+  " 1  3 150\n"
+  " 1  4  80\n"
+  " 2  8  80\n"
+  " 3  5 140\n"
+  " 4  6  60\n"
+  " 4  7  80\n"
+  " 4  8 110\n"
+  " 5  7  60\n"
+  " 5 11 120\n"
+  " 6  3   0\n"
+  " 6  9 140\n"
+  " 6 10  90\n"
+  " 7  1  30\n"
+  " 8 12  60\n"
+  " 9 12  50\n"
+  "10 12  70\n"
+  "10  2 100\n"
+  "10  7  60\n"
+  "11 10  20\n"
+  "12 11  30\n"
   "@attributes\n"
   "source  1\n"
   "target 12\n"
   "@end\n";
 
+// Check the interface of Suurballe
+void checkSuurballeCompile()
+{
+  typedef int VType;
+  typedef concepts::Digraph Digraph;
+
+  typedef Digraph::Node Node;
+  typedef Digraph::Arc Arc;
+  typedef concepts::ReadMap<Arc, VType> LengthMap;
+  
+  typedef Suurballe<Digraph, LengthMap> SuurballeType;
+
+  Digraph g;
+  Node n;
+  Arc e;
+  LengthMap len;
+  SuurballeType::FlowMap flow(g);
+  SuurballeType::PotentialMap pi(g);
+
+  SuurballeType suurb_test(g, len);
+  const SuurballeType& const_suurb_test = suurb_test;
+
+  suurb_test
+    .flowMap(flow)
+    .potentialMap(pi);
+
+  int k;
+  k = suurb_test.run(n, n);
+  k = suurb_test.run(n, n, k);
+  suurb_test.init(n);
+  k = suurb_test.findFlow(n);
+  k = suurb_test.findFlow(n, k);
+  suurb_test.findPaths();
+  
+  int f;
+  VType c;
+  c = const_suurb_test.totalLength();
+  f = const_suurb_test.flow(e);
+  const SuurballeType::FlowMap& fm =
+    const_suurb_test.flowMap();
+  c = const_suurb_test.potential(n);
+  const SuurballeType::PotentialMap& pm =
+    const_suurb_test.potentialMap();
+  k = const_suurb_test.pathNum();
+  Path<Digraph> p = const_suurb_test.path(k);
+  
+  ignore_unused_variable_warning(fm);
+  ignore_unused_variable_warning(pm);
+}
+
 // Check the feasibility of the flow
 template <typename Digraph, typename FlowMap>
 bool checkFlow( const Digraph& gr, const FlowMap& flow,
@@ -118,7 +169,6 @@
 bool checkPath( const Digraph& gr, const Path& path,
                 typename Digraph::Node s, typename Digraph::Node t)
 {
-  // Check the "Complementary Slackness" optimality condition
   TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
   Node n = s;
   for (int i = 0; i < path.length(); ++i) {
@@ -136,58 +186,55 @@
   // Read the test digraph
   ListDigraph digraph;
   ListDigraph::ArcMap<int> length(digraph);
-  Node source, target;
+  Node s, t;
 
   std::istringstream input(test_lgf);
   DigraphReader<ListDigraph>(digraph, input).
-    arcMap("cost", length).
-    node("source", source).
-    node("target", target).
+    arcMap("length", length).
+    node("source", s).
+    node("target", t).
     run();
 
   // Find 2 paths
   {
-    Suurballe<ListDigraph> suurballe(digraph, length, source, target);
-    check(suurballe.run(2) == 2, "Wrong number of paths");
-    check(checkFlow(digraph, suurballe.flowMap(), source, target, 2),
+    Suurballe<ListDigraph> suurballe(digraph, length);
+    check(suurballe.run(s, t) == 2, "Wrong number of paths");
+    check(checkFlow(digraph, suurballe.flowMap(), s, t, 2),
           "The flow is not feasible");
     check(suurballe.totalLength() == 510, "The flow is not optimal");
     check(checkOptimality(digraph, length, suurballe.flowMap(),
                           suurballe.potentialMap()),
           "Wrong potentials");
     for (int i = 0; i < suurballe.pathNum(); ++i)
-      check(checkPath(digraph, suurballe.path(i), source, target),
-            "Wrong path");
+      check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
   }
 
   // Find 3 paths
   {
-    Suurballe<ListDigraph> suurballe(digraph, length, source, target);
-    check(suurballe.run(3) == 3, "Wrong number of paths");
-    check(checkFlow(digraph, suurballe.flowMap(), source, target, 3),
+    Suurballe<ListDigraph> suurballe(digraph, length);
+    check(suurballe.run(s, t, 3) == 3, "Wrong number of paths");
+    check(checkFlow(digraph, suurballe.flowMap(), s, t, 3),
           "The flow is not feasible");
     check(suurballe.totalLength() == 1040, "The flow is not optimal");
     check(checkOptimality(digraph, length, suurballe.flowMap(),
                           suurballe.potentialMap()),
           "Wrong potentials");
     for (int i = 0; i < suurballe.pathNum(); ++i)
-      check(checkPath(digraph, suurballe.path(i), source, target),
-            "Wrong path");
+      check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
   }
 
   // Find 5 paths (only 3 can be found)
   {
-    Suurballe<ListDigraph> suurballe(digraph, length, source, target);
-    check(suurballe.run(5) == 3, "Wrong number of paths");
-    check(checkFlow(digraph, suurballe.flowMap(), source, target, 3),
+    Suurballe<ListDigraph> suurballe(digraph, length);
+    check(suurballe.run(s, t, 5) == 3, "Wrong number of paths");
+    check(checkFlow(digraph, suurballe.flowMap(), s, t, 3),
           "The flow is not feasible");
     check(suurballe.totalLength() == 1040, "The flow is not optimal");
     check(checkOptimality(digraph, length, suurballe.flowMap(),
                           suurballe.potentialMap()),
           "Wrong potentials");
     for (int i = 0; i < suurballe.pathNum(); ++i)
-      check(checkPath(digraph, suurballe.path(i), source, target),
-            "Wrong path");
+      check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
   }
 
   return 0;
diff -r 28f58740b6f8 -r 7c1324b35d89 tools/lgf-gen.cc
--- a/tools/lgf-gen.cc	Sat Apr 25 18:25:59 2009 +0200
+++ b/tools/lgf-gen.cc	Sat Apr 25 02:12:41 2009 +0200
@@ -480,8 +480,8 @@
       Node b=g.v(*ei);
       g.erase(*ei);
       ConstMap<Arc,int> cegy(1);
-      Suurballe<ListGraph,ConstMap<Arc,int> > sur(g,cegy,a,b);
-      int k=sur.run(2);
+      Suurballe<ListGraph,ConstMap<Arc,int> > sur(g,cegy);
+      int k=sur.run(a,b,2);
       if(k<2 || sur.totalLength()>d)
         g.addEdge(a,b);
       else cnt++;
@@ -511,9 +511,8 @@
       Edge ne;
       if(e==INVALID) {
         ConstMap<Arc,int> cegy(1);
-        Suurballe<ListGraph,ConstMap<Arc,int> >
-          sur(g,cegy,pi->a,pi->b);
-        int k=sur.run(2);
+        Suurballe<ListGraph,ConstMap<Arc,int> > sur(g,cegy);
+        int k=sur.run(pi->a,pi->b,2);
         if(k<2 || sur.totalLength()>d)
           {
             ne=g.addEdge(pi->a,pi->b);