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
31 #include <lemon/maps.h>
32 #include <lemon/graph_utils.h>
33 #include <lemon/graph_adaptor.h>
34 #include <lemon/iterable_maps.h>
38 /// \brief Implementation of the Hao-Orlin algorithm.
40 /// Implementation of the HaoOrlin algorithms class for testing network
47 /// \brief %Hao-Orlin algorithm to find a minimum cut in directed graphs.
49 /// Hao-Orlin calculates a minimum cut in a directed graph
50 /// \f$ D=(V,A) \f$. It takes a fixed node \f$ source \in V \f$ and consists
51 /// of two phases: in the first phase it determines a minimum cut
52 /// with \f$ source \f$ on the source-side (i.e. a set \f$ X\subsetneq V \f$
53 /// with \f$ source \in X \f$ and minimal out-degree) and in the
54 /// second phase it determines a minimum cut with \f$ source \f$ on the
55 /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \notin X \f$
56 /// and minimal out-degree). Obviously, the smaller of these two
57 /// cuts will be a minimum cut of \f$ D \f$. The algorithm is a
58 /// modified push-relabel preflow algorithm and our implementation
59 /// calculates the minimum cut in \f$ O(n^3) \f$ time (we use the
60 /// highest-label rule). The purpose of such an algorithm is testing
61 /// network reliability. For an undirected graph with \f$ n \f$
62 /// nodes and \f$ e \f$ edges you can use the algorithm of Nagamochi
63 /// and Ibaraki which solves the undirected problem in
64 /// \f$ O(ne + n^2 \log(n)) \f$ time: it is implemented in the MinCut
68 /// \param _Graph is the graph type of the algorithm.
69 /// \param _CapacityMap is an edge map of capacities which should
70 /// be any numreric type. The default type is _Graph::EdgeMap<int>.
71 /// \param _Tolerance is the handler of the inexact computation. The
72 /// default type for this is Tolerance<typename CapacityMap::Value>.
74 /// \author Attila Bernath and Balazs Dezso
76 template <typename _Graph, typename _CapacityMap, typename _Tolerance>
78 template <typename _Graph,
79 typename _CapacityMap = typename _Graph::template EdgeMap<int>,
80 typename _Tolerance = Tolerance<typename _CapacityMap::Value> >
86 typedef _CapacityMap CapacityMap;
87 typedef _Tolerance Tolerance;
89 typedef typename CapacityMap::Value Value;
92 typedef typename Graph::Node Node;
93 typedef typename Graph::NodeIt NodeIt;
94 typedef typename Graph::EdgeIt EdgeIt;
95 typedef typename Graph::OutEdgeIt OutEdgeIt;
96 typedef typename Graph::InEdgeIt InEdgeIt;
100 const CapacityMap* _capacity;
102 typedef typename Graph::template EdgeMap<Value> FlowMap;
106 Node _source, _target;
109 typedef ResGraphAdaptor<const Graph, Value, CapacityMap,
110 FlowMap, Tolerance> OutResGraph;
111 typedef typename OutResGraph::Edge OutResEdge;
113 OutResGraph* _out_res_graph;
115 typedef RevGraphAdaptor<const Graph> RevGraph;
116 RevGraph* _rev_graph;
118 typedef ResGraphAdaptor<const RevGraph, Value, CapacityMap,
119 FlowMap, Tolerance> InResGraph;
120 typedef typename InResGraph::Edge InResEdge;
122 InResGraph* _in_res_graph;
124 typedef IterableBoolMap<Graph, Node> WakeMap;
127 typedef typename Graph::template NodeMap<int> DistMap;
130 typedef typename Graph::template NodeMap<Value> ExcessMap;
133 typedef typename Graph::template NodeMap<bool> SourceSetMap;
134 SourceSetMap* _source_set;
136 std::vector<int> _level_size;
139 std::vector<std::list<Node> > _active_nodes;
142 std::vector<std::list<Node> > _dormant;
147 typedef typename Graph::template NodeMap<bool> MinCutMap;
148 MinCutMap* _min_cut_map;
150 Tolerance _tolerance;
154 /// \brief Constructor
156 /// Constructor of the algorithm class.
157 HaoOrlin(const Graph& graph, const CapacityMap& capacity,
158 const Tolerance& tolerance = Tolerance()) :
159 _graph(&graph), _capacity(&capacity),
160 _preflow(0), _source(), _target(),
161 _out_res_graph(0), _rev_graph(0), _in_res_graph(0),
162 _wake(0),_dist(0), _excess(0), _source_set(0),
163 _highest_active(), _active_nodes(), _dormant_max(), _dormant(),
164 _min_cut(), _min_cut_map(0), _tolerance(tolerance) {}
171 delete _in_res_graph;
176 if (_out_res_graph) {
177 delete _out_res_graph;
198 template <typename ResGraph>
199 void findMinCut(const Node& target, bool out, ResGraph& res_graph) {
200 typedef typename Graph::Node Node;
201 typedef typename ResGraph::Edge ResEdge;
202 typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
204 for (typename Graph::EdgeIt it(*_graph); it != INVALID; ++it) {
207 for (NodeIt it(*_graph); it != INVALID; ++it) {
211 (*_source_set)[it] = false;
214 _dormant[0].push_front(_source);
215 (*_source_set)[_source] = true;
217 (*_wake)[_source] = false;
220 _level_size[1] = _node_num - 1;
223 (*_dist)[target] = 0;
225 for (ResOutEdgeIt it(res_graph, _source); it != INVALID; ++it) {
226 Value delta = res_graph.rescap(it);
227 (*_excess)[_source] -= delta;
228 res_graph.augment(it, delta);
229 Node a = res_graph.target(it);
230 if ((*_excess)[a] == 0 && (*_wake)[a] && a != _target) {
231 _active_nodes[(*_dist)[a]].push_front(a);
232 if (_highest_active < (*_dist)[a]) {
233 _highest_active = (*_dist)[a];
236 (*_excess)[a] += delta;
242 while ((n = findActiveNode()) != INVALID) {
243 for (ResOutEdgeIt e(res_graph, n); e != INVALID; ++e) {
244 Node a = res_graph.target(e);
245 if ((*_dist)[a] >= (*_dist)[n] || !(*_wake)[a]) continue;
246 Value delta = res_graph.rescap(e);
247 if (_tolerance.positive((*_excess)[n] - delta)) {
248 (*_excess)[n] -= delta;
250 delta = (*_excess)[n];
253 res_graph.augment(e, delta);
254 if ((*_excess)[a] == 0 && a != _target) {
255 _active_nodes[(*_dist)[a]].push_front(a);
257 (*_excess)[a] += delta;
258 if ((*_excess)[n] == 0) break;
260 if ((*_excess)[n] != 0) {
261 relabel(n, res_graph);
265 Value current_value = cutValue(out);
266 if (_min_cut > current_value){
268 for (NodeIt it(*_graph); it != INVALID; ++it) {
269 _min_cut_map->set(it, !(*_wake)[it]);
272 for (NodeIt it(*_graph); it != INVALID; ++it) {
273 _min_cut_map->set(it, (*_wake)[it]);
277 _min_cut = current_value;
280 } while (selectNewSink(res_graph));
283 template <typename ResGraph>
284 void relabel(const Node& n, ResGraph& res_graph) {
285 typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
288 if (_level_size[k] == 1) {
290 for (NodeIt it(*_graph); it != INVALID; ++it) {
291 if ((*_wake)[it] && (*_dist)[it] >= k) {
292 (*_wake)[it] = false;
293 _dormant[_dormant_max].push_front(it);
294 --_level_size[(*_dist)[it]];
299 int new_dist = _node_num;
300 for (ResOutEdgeIt e(res_graph, n); e != INVALID; ++e) {
301 Node t = res_graph.target(e);
302 if ((*_wake)[t] && new_dist > (*_dist)[t]) {
303 new_dist = (*_dist)[t];
306 if (new_dist == _node_num) {
309 _dormant[_dormant_max].push_front(n);
310 --_level_size[(*_dist)[n]];
312 --_level_size[(*_dist)[n]];
313 (*_dist)[n] = new_dist + 1;
314 _highest_active = (*_dist)[n];
315 _active_nodes[_highest_active].push_front(n);
316 ++_level_size[(*_dist)[n]];
321 template <typename ResGraph>
322 bool selectNewSink(ResGraph& res_graph) {
323 typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
325 Node old_target = _target;
326 (*_wake)[_target] = false;
327 --_level_size[(*_dist)[_target]];
328 _dormant[0].push_front(_target);
329 (*_source_set)[_target] = true;
330 if ((int)_dormant[0].size() == _node_num){
335 bool wake_was_empty = false;
337 if(_wake->trueNum() == 0) {
338 while (!_dormant[_dormant_max].empty()){
339 (*_wake)[_dormant[_dormant_max].front()] = true;
340 ++_level_size[(*_dist)[_dormant[_dormant_max].front()]];
341 _dormant[_dormant_max].pop_front();
344 wake_was_empty = true;
347 int min_dist = std::numeric_limits<int>::max();
348 for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
349 if (min_dist > (*_dist)[it]){
351 min_dist = (*_dist)[it];
356 for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
357 if ((*_excess)[it] != 0 && it != _target) {
358 _active_nodes[(*_dist)[it]].push_front(it);
359 if (_highest_active < (*_dist)[it]) {
360 _highest_active = (*_dist)[it];
367 for (ResOutEdgeIt e(res_graph, n); e != INVALID; ++e){
368 Node a = res_graph.target(e);
369 if (!(*_wake)[a]) continue;
370 Value delta = res_graph.rescap(e);
371 res_graph.augment(e, delta);
372 (*_excess)[n] -= delta;
373 if ((*_excess)[a] == 0 && (*_wake)[a] && a != _target) {
374 _active_nodes[(*_dist)[a]].push_front(a);
375 if (_highest_active < (*_dist)[a]) {
376 _highest_active = (*_dist)[a];
379 (*_excess)[a] += delta;
385 Node findActiveNode() {
386 while (_highest_active > 0 && _active_nodes[_highest_active].empty()){
389 if( _highest_active > 0) {
390 Node n = _active_nodes[_highest_active].front();
391 _active_nodes[_highest_active].pop_front();
398 Value cutValue(bool out) {
401 for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
402 for (InEdgeIt e(*_graph, it); e != INVALID; ++e) {
403 if (!(*_wake)[_graph->source(e)]){
404 value += (*_capacity)[e];
409 for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
410 for (OutEdgeIt e(*_graph, it); e != INVALID; ++e) {
411 if (!(*_wake)[_graph->target(e)]){
412 value += (*_capacity)[e];
423 /// \name Execution control
424 /// The simplest way to execute the algorithm is to use
425 /// one of the member functions called \c run(...).
427 /// If you need more control on the execution,
428 /// first you must call \ref init(), then the \ref calculateIn() or
429 /// \ref calculateIn() functions.
433 /// \brief Initializes the internal data structures.
435 /// Initializes the internal data structures. It creates
436 /// the maps, residual graph adaptors and some bucket structures
437 /// for the algorithm.
439 init(NodeIt(*_graph));
442 /// \brief Initializes the internal data structures.
444 /// Initializes the internal data structures. It creates
445 /// the maps, residual graph adaptor and some bucket structures
446 /// for the algorithm. Node \c source is used as the push-relabel
447 /// algorithm's source.
448 void init(const Node& source) {
450 _node_num = countNodes(*_graph);
452 _dormant.resize(_node_num);
453 _level_size.resize(_node_num, 0);
454 _active_nodes.resize(_node_num);
457 _preflow = new FlowMap(*_graph);
460 _wake = new WakeMap(*_graph);
463 _dist = new DistMap(*_graph);
466 _excess = new ExcessMap(*_graph);
469 _source_set = new SourceSetMap(*_graph);
471 if (!_out_res_graph) {
472 _out_res_graph = new OutResGraph(*_graph, *_capacity, *_preflow);
475 _rev_graph = new RevGraph(*_graph);
477 if (!_in_res_graph) {
478 _in_res_graph = new InResGraph(*_rev_graph, *_capacity, *_preflow);
481 _min_cut_map = new MinCutMap(*_graph);
484 _min_cut = std::numeric_limits<Value>::max();
488 /// \brief Calculates a minimum cut with \f$ source \f$ on the
491 /// \brief Calculates a minimum cut with \f$ source \f$ on the
492 /// source-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \in X \f$
493 /// and minimal out-degree).
494 void calculateOut() {
495 for (NodeIt it(*_graph); it != INVALID; ++it) {
503 /// \brief Calculates a minimum cut with \f$ source \f$ on the
506 /// \brief Calculates a minimum cut with \f$ source \f$ on the
507 /// source-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \in X \f$
508 /// and minimal out-degree). The \c target is the initial target
509 /// for the push-relabel algorithm.
510 void calculateOut(const Node& target) {
511 findMinCut(target, true, *_out_res_graph);
514 /// \brief Calculates a minimum cut with \f$ source \f$ on the
517 /// \brief Calculates a minimum cut with \f$ source \f$ on the
518 /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with
519 /// \f$ source \notin X \f$
520 /// and minimal out-degree).
522 for (NodeIt it(*_graph); it != INVALID; ++it) {
530 /// \brief Calculates a minimum cut with \f$ source \f$ on the
533 /// \brief Calculates a minimum cut with \f$ source \f$ on the
534 /// sink-side (i.e. a set \f$ X\subsetneq V
535 /// \f$ with \f$ source \notin X \f$ and minimal out-degree).
536 /// The \c target is the initial
537 /// target for the push-relabel algorithm.
538 void calculateIn(const Node& target) {
539 findMinCut(target, false, *_in_res_graph);
542 /// \brief Runs the algorithm.
544 /// Runs the algorithm. It finds nodes \c source and \c target
545 /// arbitrarily and then calls \ref init(), \ref calculateOut()
546 /// and \ref calculateIn().
549 for (NodeIt it(*_graph); it != INVALID; ++it) {
558 /// \brief Runs the algorithm.
560 /// Runs the algorithm. It uses the given \c source node, finds a
561 /// proper \c target and then calls the \ref init(), \ref
562 /// calculateOut() and \ref calculateIn().
563 void run(const Node& s) {
565 for (NodeIt it(*_graph); it != INVALID; ++it) {
574 /// \brief Runs the algorithm.
576 /// Runs the algorithm. It just calls the \ref init() and then
577 /// \ref calculateOut() and \ref calculateIn().
578 void run(const Node& s, const Node& t) {
586 /// \name Query Functions
587 /// The result of the %HaoOrlin algorithm
588 /// can be obtained using these functions.
590 /// Before using these functions, either \ref run(), \ref
591 /// calculateOut() or \ref calculateIn() must be called.
595 /// \brief Returns the value of the minimum value cut.
597 /// Returns the value of the minimum value cut.
598 Value minCut() const {
603 /// \brief Returns a minimum cut.
605 /// Sets \c nodeMap to the characteristic vector of a minimum
606 /// value cut: it will give a nonempty set \f$ X\subsetneq V \f$
607 /// with minimal out-degree (i.e. \c nodeMap will be true exactly
608 /// for the nodes of \f$ X \f$). \pre nodeMap should be a
609 /// bool-valued node-map.
610 template <typename NodeMap>
611 Value minCut(NodeMap& nodeMap) const {
612 for (NodeIt it(*_graph); it != INVALID; ++it) {
613 nodeMap.set(it, (*_min_cut_map)[it]);
625 #endif //LEMON_HAO_ORLIN_H