[Lemon-commits] Peter Kovacs: Modify the interface of Suurballe ...
Lemon HG
hg at lemon.cs.elte.hu
Sat Apr 25 18:54:00 CEST 2009
details: http://lemon.cs.elte.hu/hg/lemon/rev/7c1324b35d89
changeset: 655:7c1324b35d89
user: Peter Kovacs <kpeter [at] inf.elte.hu>
date: Sat Apr 25 02:12:41 2009 +0200
description:
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.
diffstat:
lemon/suurballe.h | 205 +++++++++++++++++++++++++++++----------------------
test/suurballe_test.cc | 157 +++++++++++++++++++++++++-------------
tools/lgf-gen.cc | 9 +-
3 files changed, 222 insertions(+), 149 deletions(-)
diffs (truncated from 622 to 300 lines):
diff --git a/lemon/suurballe.h b/lemon/suurballe.h
--- a/lemon/suurballe.h
+++ b/lemon/suurballe.h
@@ -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;
}
More information about the Lemon-commits
mailing list