Last change on this file since 2126:2c8adbee9fa6 was 2113:48ec8161f9e1, checked in by Balazs Dezso, 13 years ago

Some modification in the documentation.

File size: 10.9 KB
Line
1/* -*- C++ -*-
2 *
3 * This file is a part of LEMON, a generic C++ optimization library
4 *
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_EDMONDS_KARP_H
20#define LEMON_EDMONDS_KARP_H
21
22/// \file
23/// \ingroup flowalgs
24/// \brief Implementation of the Edmonds-Karp algorithm.
25
27#include <lemon/tolerance.h>
28#include <lemon/bfs.h>
29
30namespace lemon {
31
32  /// \ingroup flowalgs
33  /// \brief Edmonds-Karp algorithms class.
34  ///
35  /// This class provides an implementation of the \e Edmonds-Karp \e
36  /// algorithm producing a flow of maximum value in a directed
37  /// graph. The Edmonds-Karp algorithm is slower than the Preflow algorithm
38  /// but it has an advantage of the step-by-step execution control with
39  /// feasible flow solutions. The \e source node, the \e target node, the \e
40  /// capacity of the edges and the \e starting \e flow value of the
41  /// edges should be passed to the algorithm through the
42  /// constructor.
43  ///
44  /// The time complexity of the algorithm is \f$O(n * e^2) \f$ in
45  /// worst case.  Always try the preflow algorithm instead of this if
46  /// you just want to compute the optimal flow.
47  ///
48  /// \param _Graph The directed graph type the algorithm runs on.
49  /// \param _Number The number type of the capacities and the flow values.
50  /// \param _CapacityMap The capacity map type.
51  /// \param _FlowMap The flow map type.
52  /// \param _Tolerance The tolerance class to handle computation problems.
53  ///
54  /// \author Balazs Dezso
55#ifdef DOXYGEN
56  template <typename _Graph, typename _Number,
57            typename _CapacityMap, typename _FlowMap, typename _Tolerance>
58#else
59  template <typename _Graph, typename _Number,
60            typename _CapacityMap = typename _Graph::template EdgeMap<_Number>,
61            typename _FlowMap = typename _Graph::template EdgeMap<_Number>,
62            typename _Tolerance = Tolerance<_Number> >
63#endif
64  class EdmondsKarp {
65  public:
66
67    /// \brief \ref Exception for the case when the source equals the target.
68    ///
69    /// \ref Exception for the case when the source equals the target.
70    ///
71    class InvalidArgument : public lemon::LogicError {
72    public:
73      virtual const char* exceptionName() const {
74        return "lemon::EdmondsKarp::InvalidArgument";
75      }
76    };
77
78
79    /// \brief The graph type the algorithm runs on.
80    typedef _Graph Graph;
81    /// \brief The value type of the algorithms.
82    typedef _Number Number;
83    /// \brief The capacity map on the edges.
84    typedef _CapacityMap CapacityMap;
85    /// \brief The flow map on the edges.
86    typedef _FlowMap FlowMap;
87    /// \brief The tolerance used by the algorithm.
88    typedef _Tolerance Tolerance;
89
91                            FlowMap, Tolerance> ResGraph;
92
93  private:
94
95    typedef typename Graph::Node Node;
96    typedef typename Graph::Edge Edge;
97
98    typedef typename Graph::NodeIt NodeIt;
99    typedef typename Graph::EdgeIt EdgeIt;
100    typedef typename Graph::InEdgeIt InEdgeIt;
101    typedef typename Graph::OutEdgeIt OutEdgeIt;
102
103  public:
104
105    /// \brief The constructor of the class.
106    ///
107    /// The constructor of the class.
108    /// \param graph The directed graph the algorithm runs on.
109    /// \param source The source node.
110    /// \param target The target node.
111    /// \param capacity The capacity of the edges.
112    /// \param flow The flow of the edges.
113    /// \param tolerance Tolerance class.
114    EdmondsKarp(const Graph& graph, Node source, Node target,
115                const CapacityMap& capacity, FlowMap& flow,
116                const Tolerance& tolerance = Tolerance())
117      : _graph(graph), _capacity(capacity), _flow(flow),
118        _tolerance(tolerance), _resgraph(graph, capacity, flow, tolerance),
119        _source(source), _target(target)
120    {
121      if (_source == _target) {
122        throw InvalidArgument();
123      }
124    }
125
126    /// \brief Initializes the algorithm
127    ///
128    /// It sets the flow to empty flow.
129    void init() {
130      for (EdgeIt it(_graph); it != INVALID; ++it) {
131        _flow.set(it, 0);
132      }
133      _value = 0;
134    }
135
136    /// \brief Initializes the algorithm
137    ///
138    /// If the flow map initially flow this let the flow map
139    /// unchanged but the flow value will be set by the flow
140    /// on the outedges from the source.
141    void flowInit() {
142      _value = 0;
143      for (OutEdgeIt jt(_graph, _source); jt != INVALID; ++jt) {
144        _value += _flow[jt];
145      }
146      for (InEdgeIt jt(_graph, _source); jt != INVALID; ++jt) {
147        _value -= _flow[jt];
148      }
149    }
150
151    /// \brief Initializes the algorithm
152    ///
153    /// If the flow map initially flow this let the flow map
154    /// unchanged but the flow value will be set by the flow
155    /// on the outedges from the source. It also checks that
156    /// the flow map really contains a flow.
157    /// \return %True when the flow map really a flow.
158    bool checkedFlowInit() {
159      _value = 0;
160      for (OutEdgeIt jt(_graph, _source); jt != INVALID; ++jt) {
161        _value += _flow[jt];
162      }
163      for (InEdgeIt jt(_graph, _source); jt != INVALID; ++jt) {
164        _value -= _flow[jt];
165      }
166      for (NodeIt it(_graph); it != INVALID; ++it) {
167        if (it == _source || it == _target) continue;
168        Number outFlow = 0;
169        for (OutEdgeIt jt(_graph, it); jt != INVALID; ++jt) {
170          outFlow += _flow[jt];
171        }
172        Number inFlow = 0;
173        for (InEdgeIt jt(_graph, it); jt != INVALID; ++jt) {
174          inFlow += _flow[jt];
175        }
176        if (_tolerance.different(outFlow, inFlow)) {
177          return false;
178        }
179      }
180      for (EdgeIt it(_graph); it != INVALID; ++it) {
181        if (_tolerance.less(_flow[it], 0)) return false;
182        if (_tolerance.less(_capacity[it], _flow[it])) return false;
183      }
184      return true;
185    }
186
187    /// \brief Augment the solution on an edge shortest path.
188    ///
189    /// Augment the solution on an edge shortest path. It search an
190    /// edge shortest path between the source and the target
191    /// in the residual graph with the bfs algoritm.
192    /// Then it increase the flow on this path with the minimal residual
193    /// capacity on the path. If there is not such path it gives back
194    /// false.
195    /// \return %False when the augmenting is not success so the
196    /// current flow is a feasible and optimal solution.
197    bool augment() {
198      typename Bfs<ResGraph>
199      ::template DefDistMap<NullMap<Node, int> >
200      ::Create bfs(_resgraph);
201
202      NullMap<Node, int> distMap;
203      bfs.distMap(distMap);
204
205      bfs.init();
207      bfs.start(_target);
208
209      if (!bfs.reached(_target)) {
210        return false;
211      }
212      Number min = _resgraph.rescap(bfs.predEdge(_target));
213      for (Node it = bfs.predNode(_target); it != _source;
214           it = bfs.predNode(it)) {
215        if (min > _resgraph.rescap(bfs.predEdge(it))) {
216          min = _resgraph.rescap(bfs.predEdge(it));
217        }
218      }
219      for (Node it = _target; it != _source; it = bfs.predNode(it)) {
220        _resgraph.augment(bfs.predEdge(it), min);
221      }
222      _value += min;
223      return true;
224    }
225
226    /// \brief Executes the algorithm
227    ///
228    /// It runs augmenting phases until the optimal solution is reached.
229    void start() {
230      while (augment()) {}
231    }
232
233    /// \brief Gives back the current flow value.
234    ///
235    /// Gives back the current flow _value.
236    Number flowValue() const {
237      return _value;
238    }
239
240    /// \brief runs the algorithm.
241    ///
242    /// It is just a shorthand for:
243    ///
244    ///\code
245    /// ek.init();
246    /// ek.start();
247    ///\endcode
248    void run() {
249      init();
250      start();
251    }
252
253    /// \brief Returns a minimum value cut.
254    ///
255    /// Sets \c cut to the characteristic vector of a minimum value cut
256    /// It simply calls the minMinCut member.
257    /// \retval cut Write node bool map.
258    template <typename CutMap>
259    void minCut(CutMap& cut) const {
260      minMinCut(cut);
261    }
262
263    /// \brief Returns the inclusionwise minimum of the minimum value cuts.
264    ///
265    /// Sets \c cut to the characteristic vector of the minimum value cut
266    /// which is inclusionwise minimum. It is computed by processing a
267    /// bfs from the source node \c source in the residual graph.
268    /// \retval cut Write node bool map.
269    template <typename CutMap>
270    void minMinCut(CutMap& cut) const {
271
272      typename Bfs<ResGraph>
273      ::template DefDistMap<NullMap<Node, int> >
274      ::template DefProcessedMap<CutMap>
275      ::Create bfs(_resgraph);
276
277      NullMap<Node, int> distMap;
278      bfs.distMap(distMap);
279
280      bfs.processedMap(cut);
281
282      bfs.run(_source);
283    }
284
285    /// \brief Returns the inclusionwise minimum of the minimum value cuts.
286    ///
287    /// Sets \c cut to the characteristic vector of the minimum value cut
288    /// which is inclusionwise minimum. It is computed by processing a
289    /// bfs from the source node \c source in the residual graph.
290    /// \retval cut Write node bool map.
291    template <typename CutMap>
292    void maxMinCut(CutMap& cut) const {
293
295
296      RevGraph revgraph(_resgraph);
297
298      typename Bfs<RevGraph>
299      ::template DefDistMap<NullMap<Node, int> >
300      ::template DefPredMap<NullMap<Node, Edge> >
301      ::template DefProcessedMap<NotWriteMap<CutMap> >
302      ::Create bfs(revgraph);
303
304      NullMap<Node, int> distMap;
305      bfs.distMap(distMap);
306
307      NullMap<Node, Edge> predMap;
308      bfs.predMap(predMap);
309
310      NotWriteMap<CutMap> notcut(cut);
311      bfs.processedMap(notcut);
312
313      bfs.run(_target);
314    }
315
316    /// \brief Returns the source node.
317    ///
318    /// Returns the source node.
319    ///
320    Node source() const {
321      return _source;
322    }
323
324    /// \brief Returns the target node.
325    ///
326    /// Returns the target node.
327    ///
328    Node target() const {
329      return _target;
330    }
331
332    /// \brief Returns a reference to capacity map.
333    ///
334    /// Returns a reference to capacity map.
335    ///
336    const CapacityMap &capacityMap() const {
337      return *_capacity;
338    }
339
340    /// \brief Returns a reference to flow map.
341    ///
342    /// Returns a reference to flow map.
343    ///
344    const FlowMap &flowMap() const {
345      return *_flow;
346    }
347
348    /// \brief Returns the tolerance used by algorithm.
349    ///
350    /// Returns the tolerance used by algorithm.
351    const Tolerance& tolerance() const {
353    }
354
355  private:
356
357    const Graph& _graph;
358    const CapacityMap& _capacity;
359    FlowMap& _flow;
360    Tolerance _tolerance;
361
362    ResGraph _resgraph;
363    Node _source, _target;
364    Number _value;
365
366  };
367
368}
369
370#endif
Note: See TracBrowser for help on using the repository browser.