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 to find a minimum cut in directed graphs.
45 /// Hao-Orlin calculates a minimum cut in a directed graph \f$
46 /// D=(V,A) \f$. It takes a fixed node \f$ source \in V \f$ and consists
47 /// of two phases: in the first phase it determines a minimum cut
48 /// with \f$ source \f$ on the source-side (i.e. a set \f$ X\subsetneq V
49 /// \f$ with \f$ source \in X \f$ and minimal out-degree) and in the
50 /// second phase it determines a minimum cut with \f$ source \f$ on the
51 /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \notin X \f$
52 /// and minimal out-degree). Obviously, the smaller of these two
53 /// cuts will be a minimum cut of \f$ D \f$. The algorithm is a
54 /// modified push-relabel preflow algorithm and our implementation
55 /// calculates the minimum cut in \f$ O(n^3) \f$ time (we use the
56 /// highest-label rule). The purpose of such an algorithm is testing
57 /// network reliability. For an undirected graph with \f$ n \f$
58 /// nodes and \f$ e \f$ edges you can use the algorithm of Nagamochi
59 /// and Ibaraki which solves the undirected problem in \f$ O(ne +
60 /// n^2 \log(n)) \f$ time: it is implemented in the MinCut algorithm
63 /// \param _Graph is the graph type of the algorithm.
64 /// \param _CapacityMap is an edge map of capacities which should
65 /// be any numreric type. The default type is _Graph::EdgeMap<int>.
66 /// \param _Tolerance is the handler of the inexact computation. The
67 /// default type for this is Tolerance<typename CapacityMap::Value>.
69 /// \author Attila Bernath and Balazs Dezso
71 template <typename _Graph, typename _CapacityMap, typename _Tolerance>
73 template <typename _Graph,
74 typename _CapacityMap = typename _Graph::template EdgeMap<int>,
75 typename _Tolerance = Tolerance<typename _CapacityMap::Value> >
81 typedef _CapacityMap CapacityMap;
82 typedef _Tolerance Tolerance;
84 typedef typename CapacityMap::Value Value;
87 typedef typename Graph::Node Node;
88 typedef typename Graph::NodeIt NodeIt;
89 typedef typename Graph::EdgeIt EdgeIt;
90 typedef typename Graph::OutEdgeIt OutEdgeIt;
91 typedef typename Graph::InEdgeIt InEdgeIt;
95 const CapacityMap* _capacity;
97 typedef typename Graph::template EdgeMap<Value> FlowMap;
101 Node _source, _target;
104 typedef ResGraphAdaptor<const Graph, Value, CapacityMap,
105 FlowMap, Tolerance> OutResGraph;
106 typedef typename OutResGraph::Edge OutResEdge;
108 OutResGraph* _out_res_graph;
110 typedef typename Graph::template NodeMap<OutResEdge> OutCurrentEdgeMap;
111 OutCurrentEdgeMap* _out_current_edge;
113 typedef RevGraphAdaptor<const Graph> RevGraph;
114 RevGraph* _rev_graph;
116 typedef ResGraphAdaptor<const RevGraph, Value, CapacityMap,
117 FlowMap, Tolerance> InResGraph;
118 typedef typename InResGraph::Edge InResEdge;
120 InResGraph* _in_res_graph;
122 typedef typename Graph::template NodeMap<InResEdge> InCurrentEdgeMap;
123 InCurrentEdgeMap* _in_current_edge;
126 typedef IterableBoolMap<Graph, Node> WakeMap;
129 typedef typename Graph::template NodeMap<int> DistMap;
132 typedef typename Graph::template NodeMap<Value> ExcessMap;
135 typedef typename Graph::template NodeMap<bool> SourceSetMap;
136 SourceSetMap* _source_set;
138 std::vector<int> _level_size;
141 std::vector<std::list<Node> > _active_nodes;
144 std::vector<std::list<Node> > _dormant;
149 typedef typename Graph::template NodeMap<bool> MinCutMap;
150 MinCutMap* _min_cut_map;
152 Tolerance _tolerance;
156 /// \brief Constructor
158 /// Constructor of the algorithm class.
159 HaoOrlin(const Graph& graph, const CapacityMap& capacity,
160 const Tolerance& tolerance = Tolerance()) :
161 _graph(&graph), _capacity(&capacity),
162 _preflow(0), _source(), _target(),
163 _out_res_graph(0), _out_current_edge(0),
164 _rev_graph(0), _in_res_graph(0), _in_current_edge(0),
165 _wake(0),_dist(0), _excess(0), _source_set(0),
166 _highest_active(), _active_nodes(), _dormant_max(), _dormant(),
167 _min_cut(), _min_cut_map(0), _tolerance(tolerance) {}
173 if (_in_current_edge) {
174 delete _in_current_edge;
177 delete _in_res_graph;
182 if (_out_current_edge) {
183 delete _out_current_edge;
185 if (_out_res_graph) {
186 delete _out_res_graph;
207 template <typename ResGraph, typename EdgeMap>
208 void findMinCut(const Node& target, bool out,
209 ResGraph& res_graph, EdgeMap& current_edge) {
210 typedef typename ResGraph::Edge ResEdge;
211 typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
213 for (typename Graph::EdgeIt it(*_graph); it != INVALID; ++it) {
216 for (NodeIt it(*_graph); it != INVALID; ++it) {
220 (*_source_set)[it] = false;
222 res_graph.firstOut(current_edge[it], it);
226 (*_dist)[target] = 0;
228 for (ResOutEdgeIt it(res_graph, _source); it != INVALID; ++it) {
229 Value delta = res_graph.rescap(it);
230 if (!_tolerance.positive(delta)) continue;
232 (*_excess)[res_graph.source(it)] -= delta;
233 res_graph.augment(it, delta);
234 Node a = res_graph.target(it);
235 if (!_tolerance.positive((*_excess)[a]) &&
236 (*_wake)[a] && a != _target) {
237 _active_nodes[(*_dist)[a]].push_front(a);
238 if (_highest_active < (*_dist)[a]) {
239 _highest_active = (*_dist)[a];
242 (*_excess)[a] += delta;
245 _dormant[0].push_front(_source);
246 (*_source_set)[_source] = true;
248 (*_wake)[_source] = false;
251 _level_size[1] = _node_num - 1;
255 while ((n = findActiveNode()) != INVALID) {
257 while (_tolerance.positive((*_excess)[n]) &&
258 (e = findAdmissibleEdge(n, res_graph, current_edge))
261 if ((*_excess)[n] < res_graph.rescap(e)) {
262 delta = (*_excess)[n];
264 delta = res_graph.rescap(e);
265 res_graph.nextOut(current_edge[n]);
267 if (!_tolerance.positive(delta)) continue;
268 res_graph.augment(e, delta);
269 (*_excess)[res_graph.source(e)] -= delta;
270 Node a = res_graph.target(e);
271 if (!_tolerance.positive((*_excess)[a]) && a != _target) {
272 _active_nodes[(*_dist)[a]].push_front(a);
274 (*_excess)[a] += delta;
276 if (_tolerance.positive((*_excess)[n])) {
277 relabel(n, res_graph, current_edge);
281 Value current_value = cutValue(out);
282 if (_min_cut > current_value){
284 for (NodeIt it(*_graph); it != INVALID; ++it) {
285 _min_cut_map->set(it, !(*_wake)[it]);
288 for (NodeIt it(*_graph); it != INVALID; ++it) {
289 _min_cut_map->set(it, (*_wake)[it]);
293 _min_cut = current_value;
296 } while (selectNewSink(res_graph));
299 template <typename ResGraph, typename EdgeMap>
300 void relabel(const Node& n, ResGraph& res_graph, EdgeMap& current_edge) {
301 typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
304 if (_level_size[k] == 1) {
306 for (NodeIt it(*_graph); it != INVALID; ++it) {
307 if ((*_wake)[it] && (*_dist)[it] >= k) {
308 (*_wake)[it] = false;
309 _dormant[_dormant_max].push_front(it);
310 --_level_size[(*_dist)[it]];
315 int new_dist = _node_num;
316 for (ResOutEdgeIt e(res_graph, n); e != INVALID; ++e) {
317 Node t = res_graph.target(e);
318 if ((*_wake)[t] && new_dist > (*_dist)[t]) {
319 new_dist = (*_dist)[t];
322 if (new_dist == _node_num) {
325 _dormant[_dormant_max].push_front(n);
326 --_level_size[(*_dist)[n]];
328 --_level_size[(*_dist)[n]];
329 (*_dist)[n] = new_dist + 1;
330 _highest_active = (*_dist)[n];
331 _active_nodes[_highest_active].push_front(n);
332 ++_level_size[(*_dist)[n]];
333 res_graph.firstOut(current_edge[n], n);
338 template <typename ResGraph>
339 bool selectNewSink(ResGraph& res_graph) {
340 typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
342 Node old_target = _target;
343 (*_wake)[_target] = false;
344 --_level_size[(*_dist)[_target]];
345 _dormant[0].push_front(_target);
346 (*_source_set)[_target] = true;
347 if ((int)_dormant[0].size() == _node_num){
352 bool wake_was_empty = false;
354 if(_wake->trueNum() == 0) {
355 while (!_dormant[_dormant_max].empty()){
356 (*_wake)[_dormant[_dormant_max].front()] = true;
357 ++_level_size[(*_dist)[_dormant[_dormant_max].front()]];
358 _dormant[_dormant_max].pop_front();
361 wake_was_empty = true;
364 int min_dist = std::numeric_limits<int>::max();
365 for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
366 if (min_dist > (*_dist)[it]){
368 min_dist = (*_dist)[it];
373 for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
374 if (_tolerance.positive((*_excess)[it])) {
375 if ((*_wake)[it] && it != _target) {
376 _active_nodes[(*_dist)[it]].push_front(it);
378 if (_highest_active < (*_dist)[it]) {
379 _highest_active = (*_dist)[it];
385 for (ResOutEdgeIt e(res_graph, old_target); e!=INVALID; ++e){
386 if (!(*_source_set)[res_graph.target(e)]) {
387 Value delta = res_graph.rescap(e);
388 if (!_tolerance.positive(delta)) continue;
389 res_graph.augment(e, delta);
390 (*_excess)[res_graph.source(e)] -= delta;
391 Node a = res_graph.target(e);
392 if (!_tolerance.positive((*_excess)[a]) &&
393 (*_wake)[a] && a != _target) {
394 _active_nodes[(*_dist)[a]].push_front(a);
395 if (_highest_active < (*_dist)[a]) {
396 _highest_active = (*_dist)[a];
399 (*_excess)[a] += delta;
406 Node findActiveNode() {
407 while (_highest_active > 0 && _active_nodes[_highest_active].empty()){
410 if( _highest_active > 0) {
411 Node n = _active_nodes[_highest_active].front();
412 _active_nodes[_highest_active].pop_front();
419 template <typename ResGraph, typename EdgeMap>
420 typename ResGraph::Edge findAdmissibleEdge(const Node& n,
422 EdgeMap& current_edge) {
423 typedef typename ResGraph::Edge ResEdge;
424 ResEdge e = current_edge[n];
425 while (e != INVALID &&
426 ((*_dist)[n] <= (*_dist)[res_graph.target(e)] ||
427 !(*_wake)[res_graph.target(e)])) {
428 res_graph.nextOut(e);
438 Value cutValue(bool out) {
441 for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
442 for (InEdgeIt e(*_graph, it); e != INVALID; ++e) {
443 if (!(*_wake)[_graph->source(e)]){
444 value += (*_capacity)[e];
449 for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
450 for (OutEdgeIt e(*_graph, it); e != INVALID; ++e) {
451 if (!(*_wake)[_graph->target(e)]){
452 value += (*_capacity)[e];
463 /// \name Execution control
464 /// The simplest way to execute the algorithm is to use
465 /// one of the member functions called \c run(...).
467 /// If you need more control on the execution,
468 /// first you must call \ref init(), then the \ref calculateIn() or
469 /// \ref calculateIn() functions.
473 /// \brief Initializes the internal data structures.
475 /// Initializes the internal data structures. It creates
476 /// the maps, residual graph adaptors and some bucket structures
477 /// for the algorithm.
479 init(NodeIt(*_graph));
482 /// \brief Initializes the internal data structures.
484 /// Initializes the internal data structures. It creates
485 /// the maps, residual graph adaptor and some bucket structures
486 /// for the algorithm. Node \c source is used as the push-relabel
487 /// algorithm's source.
488 void init(const Node& source) {
490 _node_num = countNodes(*_graph);
492 _dormant.resize(_node_num);
493 _level_size.resize(_node_num, 0);
494 _active_nodes.resize(_node_num);
497 _preflow = new FlowMap(*_graph);
500 _wake = new WakeMap(*_graph);
503 _dist = new DistMap(*_graph);
506 _excess = new ExcessMap(*_graph);
509 _source_set = new SourceSetMap(*_graph);
511 if (!_out_res_graph) {
512 _out_res_graph = new OutResGraph(*_graph, *_capacity, *_preflow);
514 if (!_out_current_edge) {
515 _out_current_edge = new OutCurrentEdgeMap(*_graph);
518 _rev_graph = new RevGraph(*_graph);
520 if (!_in_res_graph) {
521 _in_res_graph = new InResGraph(*_rev_graph, *_capacity, *_preflow);
523 if (!_in_current_edge) {
524 _in_current_edge = new InCurrentEdgeMap(*_graph);
527 _min_cut_map = new MinCutMap(*_graph);
530 _min_cut = std::numeric_limits<Value>::max();
534 /// \brief Calculates a minimum cut with \f$ source \f$ on the
537 /// \brief Calculates a minimum cut with \f$ source \f$ on the
538 /// source-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \in X
539 /// \f$ and minimal out-degree).
540 void calculateOut() {
541 for (NodeIt it(*_graph); it != INVALID; ++it) {
549 /// \brief Calculates a minimum cut with \f$ source \f$ on the
552 /// \brief Calculates a minimum cut with \f$ source \f$ on the
553 /// source-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \in X
554 /// \f$ and minimal out-degree). The \c target is the initial target
555 /// for the push-relabel algorithm.
556 void calculateOut(const Node& target) {
557 findMinCut(target, true, *_out_res_graph, *_out_current_edge);
560 /// \brief Calculates a minimum cut with \f$ source \f$ on the
563 /// \brief Calculates a minimum cut with \f$ source \f$ on the
564 /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \notin X
565 /// \f$ and minimal out-degree).
567 for (NodeIt it(*_graph); it != INVALID; ++it) {
575 /// \brief Calculates a minimum cut with \f$ source \f$ on the
578 /// \brief Calculates a minimum cut with \f$ source \f$ on the
579 /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \notin
580 /// X \f$ and minimal out-degree). The \c target is the initial
581 /// target for the push-relabel algorithm.
582 void calculateIn(const Node& target) {
583 findMinCut(target, false, *_in_res_graph, *_in_current_edge);
586 /// \brief Runs the algorithm.
588 /// Runs the algorithm. It finds nodes \c source and \c target
589 /// arbitrarily and then calls \ref init(), \ref calculateOut()
590 /// and \ref calculateIn().
593 for (NodeIt it(*_graph); it != INVALID; ++it) {
602 /// \brief Runs the algorithm.
604 /// Runs the algorithm. It uses the given \c source node, finds a
605 /// proper \c target and then calls the \ref init(), \ref
606 /// calculateOut() and \ref calculateIn().
607 void run(const Node& s) {
609 for (NodeIt it(*_graph); it != INVALID; ++it) {
618 /// \brief Runs the algorithm.
620 /// Runs the algorithm. It just calls the \ref init() and then
621 /// \ref calculateOut() and \ref calculateIn().
622 void run(const Node& s, const Node& t) {
630 /// \name Query Functions The result of the %HaoOrlin algorithm
631 /// can be obtained using these functions.
633 /// Before the use of these functions, either \ref run(), \ref
634 /// calculateOut() or \ref calculateIn() must be called.
638 /// \brief Returns the value of the minimum value cut.
640 /// Returns the value of the minimum value cut.
641 Value minCut() const {
646 /// \brief Returns a minimum cut.
648 /// Sets \c nodeMap to the characteristic vector of a minimum
649 /// value cut: it will give a nonempty set \f$ X\subsetneq V \f$
650 /// with minimal out-degree (i.e. \c nodeMap will be true exactly
651 /// for the nodes of \f$ X \f$. \pre nodeMap should be a
652 /// bool-valued node-map.
653 template <typename NodeMap>
654 Value minCut(NodeMap& nodeMap) const {
655 for (NodeIt it(*_graph); it != INVALID; ++it) {
656 nodeMap.set(it, (*_min_cut_map)[it]);
668 #endif //LEMON_HAO_ORLIN_H