[Lemon-commits] [lemon_svn] deba: r2673 - hugo/trunk/lemon
Lemon SVN
svn at lemon.cs.elte.hu
Mon Nov 6 20:54:22 CET 2006
Author: deba
Date: Mon Apr 3 18:34:23 2006
New Revision: 2673
Added:
hugo/trunk/lemon/edmonds_karp.h
Modified:
hugo/trunk/lemon/Makefile.am
hugo/trunk/lemon/graph_adaptor.h
Log:
Edmonds-Karp MaxFlow
ResGraphAdaptor with Tolerance
Modified: hugo/trunk/lemon/Makefile.am
==============================================================================
--- hugo/trunk/lemon/Makefile.am (original)
+++ hugo/trunk/lemon/Makefile.am Mon Apr 3 18:34:23 2006
@@ -35,6 +35,7 @@
dimacs.h \
dag_shortest_path.h \
edge_set.h \
+ edmonds_karp.h \
error.h \
eps.h \
fib_heap.h \
Added: hugo/trunk/lemon/edmonds_karp.h
==============================================================================
--- (empty file)
+++ hugo/trunk/lemon/edmonds_karp.h Mon Apr 3 18:34:23 2006
@@ -0,0 +1,390 @@
+/* -*- C++ -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2003-2006
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_EDMONDS_KARP_H
+#define LEMON_EDMONDS_KARP_H
+
+/// \file
+/// \ingroup flowalgs
+/// \brief Implementation of the Edmonds-Karp algorithm.
+
+#include <lemon/graph_adaptor.h>
+#include <lemon/tolerance.h>
+#include <lemon/bfs.h>
+
+namespace lemon {
+
+ /// \ingroup flowalgs
+ /// \brief Edmonds-Karp algorithms class.
+ ///
+ /// This class provides an implementation of the \e Edmonds-Karp \e
+ /// algorithm producing a flow of maximum value in a directed
+ /// graph. The Edmonds-Karp algorithm is slower than the Preflow algorithm
+ /// but it has an advantage of the step-by-step execution control with
+ /// feasible flow solutions. The \e source node, the \e target node, the \e
+ /// capacity of the edges and the \e starting \e flow value of the
+ /// edges should be passed to the algorithm through the
+ /// constructor. It is possible to change these quantities using the
+ /// functions \ref source, \ref target, \ref capacityMap and \ref
+ /// flowMap.
+ ///
+ /// The time complexity of the algorithm is O(n * e^2) in worst case.
+ /// Always try the preflow algorithm instead of this if you does not
+ /// have some additional reason than to compute the optimal flow which
+ /// has O(n^3) time complexity.
+ ///
+ /// \param _Graph The directed graph type the algorithm runs on.
+ /// \param _Number The number type of the capacities and the flow values.
+ /// \param _CapacityMap The capacity map type.
+ /// \param _FlowMap The flow map type.
+ /// \param _Tolerance The tolerance class to handle computation problems.
+ ///
+ /// \author Balazs Dezso
+ template <typename _Graph, typename _Number,
+ typename _CapacityMap = typename _Graph::template EdgeMap<_Number>,
+ typename _FlowMap = typename _Graph::template EdgeMap<_Number>,
+ typename _Tolerance = Tolerance<_Number> >
+ class EdmondsKarp {
+ public:
+
+ /// \brief \ref Exception for the case when the source equals the target.
+ ///
+ /// \ref Exception for the case when the source equals the target.
+ ///
+ class InvalidArgument : public lemon::LogicError {
+ public:
+ virtual const char* exceptionName() const {
+ return "lemon::EdmondsKarp::InvalidArgument";
+ }
+ };
+
+
+ /// \brief The graph type the algorithm runs on.
+ typedef _Graph Graph;
+ /// \brief The value type of the algorithms.
+ typedef _Number Number;
+ /// \brief The capacity map on the edges.
+ typedef _CapacityMap CapacityMap;
+ /// \brief The flow map on the edges.
+ typedef _FlowMap FlowMap;
+ /// \brief The tolerance used by the algorithm.
+ typedef _Tolerance Tolerance;
+
+ typedef ResGraphAdaptor<Graph, Number, CapacityMap,
+ FlowMap, Tolerance> ResGraph;
+
+ private:
+
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+
+ typedef typename Graph::NodeIt NodeIt;
+ typedef typename Graph::EdgeIt EdgeIt;
+ typedef typename Graph::InEdgeIt InEdgeIt;
+ typedef typename Graph::OutEdgeIt OutEdgeIt;
+
+ public:
+
+ /// \brief The constructor of the class.
+ ///
+ /// The constructor of the class.
+ /// \param _graph The directed graph the algorithm runs on.
+ /// \param _source The source node.
+ /// \param _target The target node.
+ /// \param _capacity The capacity of the edges.
+ /// \param _flow The flow of the edges.
+ /// \param _tolerance Tolerance class.
+ /// Except the graph, all of these parameters can be reset by
+ /// calling \ref source, \ref target, \ref capacityMap and \ref
+ /// flowMap, resp.
+ EdmondsKarp(const Graph& graph, Node source, Node target,
+ const CapacityMap& capacity, FlowMap& flow,
+ const Tolerance& tolerance = Tolerance())
+ : _graph(graph), _capacity(capacity), _flow(flow),
+ _tolerance(tolerance), _resgraph(graph, capacity, flow, tolerance),
+ _source(source), _target(target)
+ {
+ if (_source == _target) {
+ throw InvalidArgument();
+ }
+ }
+
+ /// \brief Initializes the algorithm
+ ///
+ /// It sets the flow to empty flow.
+ void init() {
+ for (EdgeIt it(_graph); it != INVALID; ++it) {
+ _flow.set(it, 0);
+ }
+ _value = 0;
+ }
+
+ /// \brief Initializes the algorithm
+ ///
+ /// If the flow map initially flow this let the flow map
+ /// unchanged but the flow value will be set by the flow
+ /// on the outedges from the source.
+ void flowInit() {
+ _value = 0;
+ for (OutEdgeIt jt(_graph, _source); jt != INVALID; ++jt) {
+ _value += _flow[jt];
+ }
+ for (InEdgeIt jt(_graph, _source); jt != INVALID; ++jt) {
+ _value -= _flow[jt];
+ }
+ }
+
+ /// \brief Initializes the algorithm
+ ///
+ /// If the flow map initially flow this let the flow map
+ /// unchanged but the flow value will be set by the flow
+ /// on the outedges from the source. It also checks that
+ /// the flow map really contains a flow.
+ /// \return %True when the flow map really a flow.
+ bool checkedFlowInit() {
+ _value = 0;
+ for (OutEdgeIt jt(_graph, _source); jt != INVALID; ++jt) {
+ _value += _flow[jt];
+ }
+ for (InEdgeIt jt(_graph, _source); jt != INVALID; ++jt) {
+ _value -= _flow[jt];
+ }
+ for (NodeIt it(_graph); it != INVALID; ++it) {
+ if (it == _source || it == _target) continue;
+ Number outFlow = 0;
+ for (OutEdgeIt jt(_graph, it); jt != INVALID; ++jt) {
+ outFlow += _flow[jt];
+ }
+ Number inFlow = 0;
+ for (InEdgeIt jt(_graph, it); jt != INVALID; ++jt) {
+ inFlow += _flow[jt];
+ }
+ if (_tolerance.different(outFlow, inFlow)) {
+ return false;
+ }
+ }
+ for (EdgeIt it(_graph); it != INVALID; ++it) {
+ if (_tolerance.less(_flow[it], 0)) return false;
+ if (_tolerance.less(_capacity[it], _flow[it])) return false;
+ }
+ return true;
+ }
+
+ /// \brief Augment the solution on an edge shortest path.
+ ///
+ /// Augment the solution on an edge shortest path. It search an
+ /// edge shortest path between the source and the target
+ /// in the residual graph with the bfs algoritm.
+ /// Then it increase the flow on this path with the minimal residual
+ /// capacity on the path. If there is not such path it gives back
+ /// false.
+ /// \return %False when the augmenting is not success so the
+ /// current flow is a feasible and optimal solution.
+ bool augment() {
+ typename Bfs<ResGraph>
+ ::template DefDistMap<NullMap<Node, int> >
+ ::Create bfs(_resgraph);
+
+ NullMap<Node, int> distMap;
+ bfs.distMap(distMap);
+
+ bfs.init();
+ bfs.addSource(_source);
+ bfs.start(_target);
+
+ if (!bfs.reached(_target)) {
+ return false;
+ }
+ Number min = _resgraph.rescap(bfs.predEdge(_target));
+ for (Node it = bfs.predNode(_target); it != _source;
+ it = bfs.predNode(it)) {
+ if (min > _resgraph.rescap(bfs.predEdge(it))) {
+ min = _resgraph.rescap(bfs.predEdge(it));
+ }
+ }
+ for (Node it = _target; it != _source; it = bfs.predNode(it)) {
+ _resgraph.augment(bfs.predEdge(it), min);
+ }
+ _value += min;
+ return true;
+ }
+
+ /// \brief Executes the algorithm
+ ///
+ /// It runs augmenting phases until the optimal solution is reached.
+ void start() {
+ while (augment()) {}
+ }
+
+ /// \brief Gives back the current flow value.
+ ///
+ /// Gives back the current flow _value.
+ Number flowValue() const {
+ return _value;
+ }
+
+ /// \brief runs the algorithm.
+ ///
+ /// It is just a shorthand for:
+ /// \code
+ /// ek.init();
+ /// ek.start();
+ /// \endcode
+ void run() {
+ init();
+ start();
+ }
+
+ /// \brief Returns a minimum value cut.
+ ///
+ /// Sets \c cut to the characteristic vector of a minimum value cut
+ /// It simply calls the minMinCut member.
+ template <typename CutMap>
+ void minCut(CutMap& cut) const {
+ minMinCut(cut);
+ }
+
+ /// \brief Returns the inclusionwise minimum of the minimum value cuts.
+ ///
+ /// Sets \c cut to the characteristic vector of the minimum value cut
+ /// which is inclusionwise minimum. It is computed by processing a
+ /// bfs from the source node \c source in the residual graph.
+ template <typename CutMap>
+ void minMinCut(CutMap& cut) const {
+
+ typename Bfs<ResGraph>
+ ::template DefDistMap<NullMap<Node, int> >
+ ::template DefProcessedMap<CutMap>
+ ::Create bfs(_resgraph);
+
+ NullMap<Node, int> distMap;
+ bfs.distMap(distMap);
+
+ bfs.processedMap(cut);
+
+ bfs.run(_source);
+ }
+
+ /// \brief Returns the inclusionwise minimum of the minimum value cuts.
+ ///
+ /// Sets \c cut to the characteristic vector of the minimum value cut
+ /// which is inclusionwise minimum. It is computed by processing a
+ /// bfs from the source node \c source in the residual graph.
+ template <typename CutMap>
+ void maxMinCut(CutMap& cut) const {
+
+ typedef RevGraphAdaptor<const ResGraph> RevGraph;
+
+ RevGraph revgraph(_resgraph);
+
+ typename Bfs<RevGraph>
+ ::template DefDistMap<NullMap<Node, int> >
+ ::template DefPredMap<NullMap<Node, Edge> >
+ ::template DefProcessedMap<NotWriteMap<CutMap> >
+ ::Create bfs(revgraph);
+
+ NullMap<Node, int> distMap;
+ bfs.distMap(distMap);
+
+ NullMap<Node, Edge> predMap;
+ bfs.predMap(predMap);
+
+ NotWriteMap<CutMap> notcut(cut);
+ bfs.processedMap(notcut);
+
+ bfs.run(_target);
+ }
+
+ /// \brief Sets the source node to \c _source.
+ ///
+ /// Sets the source node to \c _source.
+ void source(Node source) {
+ _source = source;
+ }
+
+ /// \brief Returns the source node.
+ ///
+ /// Returns the source node.
+ ///
+ Node source() const {
+ return _source;
+ }
+
+ /// \brief Sets the target node to \c target.
+ ///
+ /// Sets the target node to \c target.
+ void target(Node target) {
+ _target = target;
+ }
+
+ /// \brief Returns the target node.
+ ///
+ /// Returns the target node.
+ ///
+ Node target() const {
+ return _target;
+ }
+
+ /// \brief Sets the edge map of the capacities to _cap.
+ ///
+ /// Sets the edge map of the capacities to _cap.
+ ///
+ void capacityMap(const CapacityMap& capacity) {
+ _capacity = &capacity;
+ }
+
+ /// \brief Returns a reference to capacity map.
+ ///
+ /// Returns a reference to capacity map.
+ ///
+ const CapacityMap &capacityMap() const {
+ return *_capacity;
+ }
+
+ /// \brief Sets the edge map of the flows to \c flow.
+ ///
+ /// Sets the edge map of the flows to \c flow.
+ ///
+ void flowMap(FlowMap& flow) {
+ _flow = &flow;
+ }
+
+ /// \brief Returns a reference to flow map.
+ ///
+ /// Returns a reference to flow map.
+ ///
+ const FlowMap &flowMap() const {
+ return *_flow;
+ }
+
+ private:
+
+ const Graph& _graph;
+ const CapacityMap& _capacity;
+ FlowMap& _flow;
+ Tolerance _tolerance;
+
+ ResGraph _resgraph;
+ Node _source, _target;
+ Number _value;
+
+ };
+
+}
+
+#endif
Modified: hugo/trunk/lemon/graph_adaptor.h
==============================================================================
--- hugo/trunk/lemon/graph_adaptor.h (original)
+++ hugo/trunk/lemon/graph_adaptor.h Mon Apr 3 18:34:23 2006
@@ -34,6 +34,8 @@
#include <lemon/bits/graph_adaptor_extender.h>
#include <lemon/bits/graph_extender.h>
+#include <lemon/tolerance.h>
+
#include <iostream>
namespace lemon {
@@ -71,6 +73,9 @@
public:
GraphAdaptorBase(Graph& _graph) : graph(&_graph) { }
+
+ Graph& getGraph() { return *graph; }
+ const Graph& getGraph() const { return *graph; }
typedef typename Graph::Node Node;
typedef typename Graph::Edge Edge;
@@ -1422,41 +1427,52 @@
return UndirGraphAdaptor<const Graph>(graph);
}
- template<typename Graph, typename Number,
- typename CapacityMap, typename FlowMap>
+ template<typename Graph, typename Number,
+ typename CapacityMap, typename FlowMap,
+ typename Tolerance = Tolerance<Number> >
class ResForwardFilter {
const CapacityMap* capacity;
const FlowMap* flow;
+ Tolerance tolerance;
public:
typedef typename Graph::Edge Key;
typedef bool Value;
- ResForwardFilter(const CapacityMap& _capacity, const FlowMap& _flow)
- : capacity(&_capacity), flow(&_flow) { }
- ResForwardFilter() : capacity(0), flow(0) { }
+ ResForwardFilter(const CapacityMap& _capacity, const FlowMap& _flow,
+ const Tolerance& _tolerance = Tolerance())
+ : capacity(&_capacity), flow(&_flow), tolerance(_tolerance) { }
+
+ ResForwardFilter(const Tolerance& _tolerance)
+ : capacity(0), flow(0), tolerance(_tolerance) { }
+
void setCapacity(const CapacityMap& _capacity) { capacity = &_capacity; }
void setFlow(const FlowMap& _flow) { flow = &_flow; }
+
bool operator[](const typename Graph::Edge& e) const {
- return (Number((*flow)[e]) < Number((*capacity)[e]));
+ return tolerance.less((*flow)[e], (*capacity)[e]);
}
};
template<typename Graph, typename Number,
- typename CapacityMap, typename FlowMap>
+ typename CapacityMap, typename FlowMap,
+ typename Tolerance = Tolerance<Number> >
class ResBackwardFilter {
const CapacityMap* capacity;
const FlowMap* flow;
+ Tolerance tolerance;
public:
typedef typename Graph::Edge Key;
typedef bool Value;
- ResBackwardFilter(const CapacityMap& _capacity, const FlowMap& _flow)
- : capacity(&_capacity), flow(&_flow) { }
- ResBackwardFilter() : capacity(0), flow(0) { }
+ ResBackwardFilter(const CapacityMap& _capacity, const FlowMap& _flow,
+ const Tolerance& _tolerance = Tolerance())
+ : capacity(&_capacity), flow(&_flow), tolerance(_tolerance) { }
+ ResBackwardFilter(const Tolerance& _tolerance = Tolerance())
+ : capacity(0), flow(0), tolerance(_tolerance) { }
void setCapacity(const CapacityMap& _capacity) { capacity = &_capacity; }
void setFlow(const FlowMap& _flow) { flow = &_flow; }
bool operator[](const typename Graph::Edge& e) const {
- return (Number(0) < Number((*flow)[e]));
+ return tolerance.less(0, Number((*flow)[e]));
}
};
@@ -1497,21 +1513,22 @@
///\author Marton Makai
///
template<typename Graph, typename Number,
- typename CapacityMap, typename FlowMap>
+ typename CapacityMap, typename FlowMap,
+ typename Tolerance = Tolerance<Number> >
class ResGraphAdaptor :
public EdgeSubGraphAdaptor<
- UndirGraphAdaptor<Graph>,
- typename UndirGraphAdaptor<Graph>::template CombinedEdgeMap<
- ResForwardFilter<Graph, Number, CapacityMap, FlowMap>,
- ResBackwardFilter<Graph, Number, CapacityMap, FlowMap> > > {
+ UndirGraphAdaptor<const Graph>,
+ typename UndirGraphAdaptor<const Graph>::template CombinedEdgeMap<
+ ResForwardFilter<const Graph, Number, CapacityMap, FlowMap>,
+ ResBackwardFilter<const Graph, Number, CapacityMap, FlowMap> > > {
public:
- typedef UndirGraphAdaptor<Graph> UGraph;
+ typedef UndirGraphAdaptor<const Graph> UGraph;
- typedef ResForwardFilter<Graph, Number, CapacityMap, FlowMap>
+ typedef ResForwardFilter<const Graph, Number, CapacityMap, FlowMap>
ForwardFilter;
- typedef ResBackwardFilter<Graph, Number, CapacityMap, FlowMap>
+ typedef ResBackwardFilter<const Graph, Number, CapacityMap, FlowMap>
BackwardFilter;
typedef typename UGraph::
@@ -1544,44 +1561,77 @@
public:
- ResGraphAdaptor(Graph& _graph, const CapacityMap& _capacity,
- FlowMap& _flow)
- : Parent(), capacity(&_capacity), flow(&_flow),
- ugraph(_graph),
- forward_filter(_capacity, _flow),
- backward_filter(_capacity, _flow),
- edge_filter(forward_filter, backward_filter) {
+ const Graph& getGraph() const { return ugraph.getGraph(); }
+
+ /// \brief Constructor of the residual graph.
+ ///
+ /// Constructor of the residual graph. The parameters are the graph type,
+ /// the flow map, the capacity map and a tolerance object.
+ ResGraphAdaptor(const Graph& _graph, const CapacityMap& _capacity,
+ FlowMap& _flow, const Tolerance& _tolerance = Tolerance())
+ : Parent(), capacity(&_capacity), flow(&_flow), ugraph(_graph),
+ forward_filter(_capacity, _flow, _tolerance),
+ backward_filter(_capacity, _flow, _tolerance),
+ edge_filter(forward_filter, backward_filter)
+ {
Parent::setGraph(ugraph);
Parent::setEdgeFilterMap(edge_filter);
}
typedef typename Parent::Edge Edge;
+ /// \brief Gives back the residual capacity of the edge.
+ ///
+ /// Gives back the residual capacity of the edge.
+ Number rescap(const Edge& edge) const {
+ if (UGraph::direction(edge)) {
+ return (*capacity)[edge]-(*flow)[edge];
+ } else {
+ return (*flow)[edge];
+ }
+ }
+
+ /// \brief Augment on the given edge in the residual graph.
+ ///
+ /// Augment on the given edge in the residual graph. It increase
+ /// or decrease the flow on the original edge depend on the direction
+ /// of the residual edge.
void augment(const Edge& e, Number a) const {
if (UGraph::direction(e)) {
- flow->set(e, (*flow)[e]+a);
+ flow->set(e, (*flow)[e] + a);
} else {
- flow->set(e, (*flow)[e]-a);
+ flow->set(e, (*flow)[e] - a);
}
}
+ /// \brief Returns the direction of the edge.
+ ///
+ /// Returns true when the edge is same oriented as the original edge.
static bool forward(const Edge& e) {
return UGraph::direction(e);
}
+ /// \brief Returns the direction of the edge.
+ ///
+ /// Returns true when the edge is opposite oriented as the original edge.
static bool backward(const Edge& e) {
return !UGraph::direction(e);
}
+ /// \brief Gives back the forward oriented residual edge.
+ ///
+ /// Gives back the forward oriented residual edge.
static Edge forward(const typename Graph::Edge& e) {
return UGraph::direct(e, true);
}
+ /// \brief Gives back the backward oriented residual edge.
+ ///
+ /// Gives back the backward oriented residual edge.
static Edge backward(const typename Graph::Edge& e) {
return UGraph::direct(e, false);
}
-
/// \brief Residual capacity map.
///
/// In generic residual graphs the residual capacity can be obtained
@@ -1595,11 +1645,8 @@
ResCap(const ResGraphAdaptor& _res_graph)
: res_graph(&_res_graph) {}
- Number operator[](const Edge& e) const {
- if (ResGraphAdaptor::direction(e))
- return (*(res_graph->capacity))[e]-(*(res_graph->flow))[e];
- else
- return (*(res_graph->flow))[e];
+ Number operator[](const Edge& e) const {
+ return res_graph->rescap(e);
}
};
More information about the Lemon-commits
mailing list