3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
19 #ifndef LEMON_HAO_ORLIN_H
20 #define LEMON_HAO_ORLIN_H
26 #include <lemon/maps.h>
27 #include <lemon/graph_utils.h>
28 #include <lemon/graph_adaptor.h>
29 #include <lemon/iterable_maps.h>
34 /// \brief Implementation of the Hao-Orlin algorithm.
36 /// Implementation of the HaoOrlin algorithms class for testing network
43 /// \brief %Hao-Orlin algorithm for calculate minimum cut in directed graphs.
45 /// Hao-Orlin calculates the minimum cut in directed graphs. It
46 /// separates the nodes of the graph into two disjoint sets,
47 /// \f$ V_{out} \f$ and \f$ V_{in} \f$. This separation is the minimum
48 /// cut if the summary of the edge capacities which source is in
49 /// \f$ V_{out} \f$ and the target is in \f$ V_{in} \f$ is the
50 /// minimum. The algorithm is a modified push-relabel preflow
51 /// algorithm and it calculates the minimum cut in \f$ O(n^3) \f$
52 /// time. The purpose of such algorithm is testing network
53 /// reliability. For sparse undirected graph you can use the
54 /// algorithm of Nagamochi and Ibaraki which solves the undirected
55 /// problem in \f$ O(ne + n^2 \log(n)) \f$ time and it is implemented in the
56 /// MinCut algorithm class.
58 /// \param _Graph is the graph type of the algorithm.
59 /// \param _CapacityMap is an edge map of capacities which should
60 /// be any numreric type. The default type is _Graph::EdgeMap<int>.
61 /// \param _Tolerance is the handler of the inexact computation. The
62 /// default type for it is Tolerance<typename CapacityMap::Value>.
64 /// \author Attila Bernath and Balazs Dezso
66 template <typename _Graph, typename _CapacityMap, typename _Tolerance>
68 template <typename _Graph,
69 typename _CapacityMap = typename _Graph::template EdgeMap<int>,
70 typename _Tolerance = Tolerance<typename _CapacityMap::Value> >
76 typedef _CapacityMap CapacityMap;
77 typedef _Tolerance Tolerance;
79 typedef typename CapacityMap::Value Value;
82 typedef typename Graph::Node Node;
83 typedef typename Graph::NodeIt NodeIt;
84 typedef typename Graph::EdgeIt EdgeIt;
85 typedef typename Graph::OutEdgeIt OutEdgeIt;
86 typedef typename Graph::InEdgeIt InEdgeIt;
90 const CapacityMap* _capacity;
92 typedef typename Graph::template EdgeMap<Value> FlowMap;
96 Node _source, _target;
99 typedef ResGraphAdaptor<const Graph, Value, CapacityMap,
100 FlowMap, Tolerance> OutResGraph;
101 typedef typename OutResGraph::Edge OutResEdge;
103 OutResGraph* _out_res_graph;
105 typedef typename Graph::template NodeMap<OutResEdge> OutCurrentEdgeMap;
106 OutCurrentEdgeMap* _out_current_edge;
108 typedef RevGraphAdaptor<const Graph> RevGraph;
109 RevGraph* _rev_graph;
111 typedef ResGraphAdaptor<const RevGraph, Value, CapacityMap,
112 FlowMap, Tolerance> InResGraph;
113 typedef typename InResGraph::Edge InResEdge;
115 InResGraph* _in_res_graph;
117 typedef typename Graph::template NodeMap<InResEdge> InCurrentEdgeMap;
118 InCurrentEdgeMap* _in_current_edge;
121 typedef IterableBoolMap<Graph, Node> WakeMap;
124 typedef typename Graph::template NodeMap<int> DistMap;
127 typedef typename Graph::template NodeMap<Value> ExcessMap;
130 typedef typename Graph::template NodeMap<bool> SourceSetMap;
131 SourceSetMap* _source_set;
133 std::vector<int> _level_size;
136 std::vector<std::list<Node> > _active_nodes;
139 std::vector<std::list<Node> > _dormant;
144 typedef typename Graph::template NodeMap<bool> MinCutMap;
145 MinCutMap* _min_cut_map;
147 Tolerance _tolerance;
151 /// \brief Constructor
153 /// Constructor of the algorithm class.
154 HaoOrlin(const Graph& graph, const CapacityMap& capacity,
155 const Tolerance& tolerance = Tolerance()) :
156 _graph(&graph), _capacity(&capacity),
157 _preflow(0), _source(), _target(),
158 _out_res_graph(0), _out_current_edge(0),
159 _rev_graph(0), _in_res_graph(0), _in_current_edge(0),
160 _wake(0),_dist(0), _excess(0), _source_set(0),
161 _highest_active(), _active_nodes(), _dormant_max(), _dormant(),
162 _min_cut(), _min_cut_map(0), _tolerance(tolerance) {}
168 if (_in_current_edge) {
169 delete _in_current_edge;
172 delete _in_res_graph;
177 if (_out_current_edge) {
178 delete _out_current_edge;
180 if (_out_res_graph) {
181 delete _out_res_graph;
202 template <typename ResGraph, typename EdgeMap>
203 void findMinCut(const Node& target, bool out,
204 ResGraph& res_graph, EdgeMap& current_edge) {
205 typedef typename ResGraph::Edge ResEdge;
206 typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
208 for (typename Graph::EdgeIt it(*_graph); it != INVALID; ++it) {
211 for (NodeIt it(*_graph); it != INVALID; ++it) {
215 (*_source_set)[it] = false;
217 res_graph.firstOut(current_edge[it], it);
221 (*_dist)[target] = 0;
223 for (ResOutEdgeIt it(res_graph, _source); it != INVALID; ++it) {
224 Value delta = res_graph.rescap(it);
225 if (!_tolerance.positive(delta)) continue;
227 (*_excess)[res_graph.source(it)] -= delta;
228 res_graph.augment(it, delta);
229 Node a = res_graph.target(it);
230 if (!_tolerance.positive((*_excess)[a]) &&
231 (*_wake)[a] && a != _target) {
232 _active_nodes[(*_dist)[a]].push_front(a);
233 if (_highest_active < (*_dist)[a]) {
234 _highest_active = (*_dist)[a];
237 (*_excess)[a] += delta;
240 _dormant[0].push_front(_source);
241 (*_source_set)[_source] = true;
243 (*_wake)[_source] = false;
246 _level_size[1] = _node_num - 1;
250 while ((n = findActiveNode()) != INVALID) {
252 while (_tolerance.positive((*_excess)[n]) &&
253 (e = findAdmissibleEdge(n, res_graph, current_edge))
256 if ((*_excess)[n] < res_graph.rescap(e)) {
257 delta = (*_excess)[n];
259 delta = res_graph.rescap(e);
260 res_graph.nextOut(current_edge[n]);
262 if (!_tolerance.positive(delta)) continue;
263 res_graph.augment(e, delta);
264 (*_excess)[res_graph.source(e)] -= delta;
265 Node a = res_graph.target(e);
266 if (!_tolerance.positive((*_excess)[a]) && a != _target) {
267 _active_nodes[(*_dist)[a]].push_front(a);
269 (*_excess)[a] += delta;
271 if (_tolerance.positive((*_excess)[n])) {
272 relabel(n, res_graph, current_edge);
276 Value current_value = cutValue(out);
277 if (_min_cut > current_value){
279 for (NodeIt it(*_graph); it != INVALID; ++it) {
280 _min_cut_map->set(it, !(*_wake)[it]);
283 for (NodeIt it(*_graph); it != INVALID; ++it) {
284 _min_cut_map->set(it, (*_wake)[it]);
288 _min_cut = current_value;
291 } while (selectNewSink(res_graph));
294 template <typename ResGraph, typename EdgeMap>
295 void relabel(const Node& n, ResGraph& res_graph, EdgeMap& current_edge) {
296 typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
299 if (_level_size[k] == 1) {
301 for (NodeIt it(*_graph); it != INVALID; ++it) {
302 if ((*_wake)[it] && (*_dist)[it] >= k) {
303 (*_wake)[it] = false;
304 _dormant[_dormant_max].push_front(it);
305 --_level_size[(*_dist)[it]];
310 int new_dist = _node_num;
311 for (ResOutEdgeIt e(res_graph, n); e != INVALID; ++e) {
312 Node t = res_graph.target(e);
313 if ((*_wake)[t] && new_dist > (*_dist)[t]) {
314 new_dist = (*_dist)[t];
317 if (new_dist == _node_num) {
320 _dormant[_dormant_max].push_front(n);
321 --_level_size[(*_dist)[n]];
323 --_level_size[(*_dist)[n]];
324 (*_dist)[n] = new_dist + 1;
325 _highest_active = (*_dist)[n];
326 _active_nodes[_highest_active].push_front(n);
327 ++_level_size[(*_dist)[n]];
328 res_graph.firstOut(current_edge[n], n);
333 template <typename ResGraph>
334 bool selectNewSink(ResGraph& res_graph) {
335 typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
337 Node old_target = _target;
338 (*_wake)[_target] = false;
339 --_level_size[(*_dist)[_target]];
340 _dormant[0].push_front(_target);
341 (*_source_set)[_target] = true;
342 if ((int)_dormant[0].size() == _node_num){
347 bool wake_was_empty = false;
349 if(_wake->trueNum() == 0) {
350 while (!_dormant[_dormant_max].empty()){
351 (*_wake)[_dormant[_dormant_max].front()] = true;
352 ++_level_size[(*_dist)[_dormant[_dormant_max].front()]];
353 _dormant[_dormant_max].pop_front();
356 wake_was_empty = true;
359 int min_dist = std::numeric_limits<int>::max();
360 for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
361 if (min_dist > (*_dist)[it]){
363 min_dist = (*_dist)[it];
368 for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
369 if (_tolerance.positive((*_excess)[it])) {
370 if ((*_wake)[it] && it != _target) {
371 _active_nodes[(*_dist)[it]].push_front(it);
373 if (_highest_active < (*_dist)[it]) {
374 _highest_active = (*_dist)[it];
380 for (ResOutEdgeIt e(res_graph, old_target); e!=INVALID; ++e){
381 if (!(*_source_set)[res_graph.target(e)]) {
382 Value delta = res_graph.rescap(e);
383 if (!_tolerance.positive(delta)) continue;
384 res_graph.augment(e, delta);
385 (*_excess)[res_graph.source(e)] -= delta;
386 Node a = res_graph.target(e);
387 if (!_tolerance.positive((*_excess)[a]) &&
388 (*_wake)[a] && a != _target) {
389 _active_nodes[(*_dist)[a]].push_front(a);
390 if (_highest_active < (*_dist)[a]) {
391 _highest_active = (*_dist)[a];
394 (*_excess)[a] += delta;
401 Node findActiveNode() {
402 while (_highest_active > 0 && _active_nodes[_highest_active].empty()){
405 if( _highest_active > 0) {
406 Node n = _active_nodes[_highest_active].front();
407 _active_nodes[_highest_active].pop_front();
414 template <typename ResGraph, typename EdgeMap>
415 typename ResGraph::Edge findAdmissibleEdge(const Node& n,
417 EdgeMap& current_edge) {
418 typedef typename ResGraph::Edge ResEdge;
419 ResEdge e = current_edge[n];
420 while (e != INVALID &&
421 ((*_dist)[n] <= (*_dist)[res_graph.target(e)] ||
422 !(*_wake)[res_graph.target(e)])) {
423 res_graph.nextOut(e);
433 Value cutValue(bool out) {
436 for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
437 for (InEdgeIt e(*_graph, it); e != INVALID; ++e) {
438 if (!(*_wake)[_graph->source(e)]){
439 value += (*_capacity)[e];
444 for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
445 for (OutEdgeIt e(*_graph, it); e != INVALID; ++e) {
446 if (!(*_wake)[_graph->target(e)]){
447 value += (*_capacity)[e];
458 /// \name Execution control
459 /// The simplest way to execute the algorithm is to use
460 /// one of the member functions called \c run(...).
462 /// If you need more control on the execution,
463 /// first you must call \ref init(), then the \ref calculateIn() or
464 /// \ref calculateIn() functions.
468 /// \brief Initializes the internal data structures.
470 /// Initializes the internal data structures. It creates
471 /// the maps, residual graph adaptors and some bucket structures
472 /// for the algorithm.
474 init(NodeIt(*_graph));
477 /// \brief Initializes the internal data structures.
479 /// Initializes the internal data structures. It creates
480 /// the maps, residual graph adaptor and some bucket structures
481 /// for the algorithm. The \c source node is used as the push-relabel
482 /// algorithm's source.
483 void init(const Node& source) {
485 _node_num = countNodes(*_graph);
487 _dormant.resize(_node_num);
488 _level_size.resize(_node_num, 0);
489 _active_nodes.resize(_node_num);
492 _preflow = new FlowMap(*_graph);
495 _wake = new WakeMap(*_graph);
498 _dist = new DistMap(*_graph);
501 _excess = new ExcessMap(*_graph);
504 _source_set = new SourceSetMap(*_graph);
506 if (!_out_res_graph) {
507 _out_res_graph = new OutResGraph(*_graph, *_capacity, *_preflow);
509 if (!_out_current_edge) {
510 _out_current_edge = new OutCurrentEdgeMap(*_graph);
513 _rev_graph = new RevGraph(*_graph);
515 if (!_in_res_graph) {
516 _in_res_graph = new InResGraph(*_rev_graph, *_capacity, *_preflow);
518 if (!_in_current_edge) {
519 _in_current_edge = new InCurrentEdgeMap(*_graph);
522 _min_cut_map = new MinCutMap(*_graph);
525 _min_cut = std::numeric_limits<Value>::max();
529 /// \brief Calculates the minimum cut with the \c source node
530 /// in the \f$ V_{out} \f$.
532 /// Calculates the minimum cut with the \c source node
533 /// in the \f$ V_{out} \f$.
534 void calculateOut() {
535 for (NodeIt it(*_graph); it != INVALID; ++it) {
543 /// \brief Calculates the minimum cut with the \c source node
544 /// in the \f$ V_{out} \f$.
546 /// Calculates the minimum cut with the \c source node
547 /// in the \f$ V_{out} \f$. The \c target is the initial target
548 /// for the push-relabel algorithm.
549 void calculateOut(const Node& target) {
550 findMinCut(target, true, *_out_res_graph, *_out_current_edge);
553 /// \brief Calculates the minimum cut with the \c source node
554 /// in the \f$ V_{in} \f$.
556 /// Calculates the minimum cut with the \c source node
557 /// in the \f$ V_{in} \f$.
559 for (NodeIt it(*_graph); it != INVALID; ++it) {
567 /// \brief Calculates the minimum cut with the \c source node
568 /// in the \f$ V_{in} \f$.
570 /// Calculates the minimum cut with the \c source node
571 /// in the \f$ V_{in} \f$. The \c target is the initial target
572 /// for the push-relabel algorithm.
573 void calculateIn(const Node& target) {
574 findMinCut(target, false, *_in_res_graph, *_in_current_edge);
577 /// \brief Runs the algorithm.
579 /// Runs the algorithm. It finds a proper \c source and \c target
580 /// and then calls the \ref init(), \ref calculateOut() and \ref
584 for (NodeIt it(*_graph); it != INVALID; ++it) {
593 /// \brief Runs the algorithm.
595 /// Runs the algorithm. It finds a proper \c target and then calls
596 /// the \ref init(), \ref calculateOut() and \ref calculateIn().
597 void run(const Node& s) {
599 for (NodeIt it(*_graph); it != INVALID; ++it) {
608 /// \brief Runs the algorithm.
610 /// Runs the algorithm. It just calls the \ref init() and then
611 /// \ref calculateOut() and \ref calculateIn().
612 void run(const Node& s, const Node& t) {
620 /// \name Query Functions The result of the %HaoOrlin algorithm
621 /// can be obtained using these functions.
623 /// Before the use of these functions, either \ref run(), \ref
624 /// calculateOut() or \ref calculateIn() must be called.
628 /// \brief Returns the value of the minimum value cut.
630 /// Returns the value of the minimum value cut.
631 Value minCut() const {
636 /// \brief Returns a minimum value cut.
638 /// Sets \c nodeMap to the characteristic vector of a minimum
639 /// value cut. The nodes in \f$ V_{out} \f$ will be set true and
640 /// the nodes in \f$ V_{in} \f$ will be set false.
641 /// \pre nodeMap should be a bool-valued node-map.
642 template <typename NodeMap>
643 Value minCut(NodeMap& nodeMap) const {
644 for (NodeIt it(*_graph); it != INVALID; ++it) {
645 nodeMap.set(it, (*_min_cut_map)[it]);
657 #endif //LEMON_HAO_ORLIN_H