2 * lemon/hao_orlin.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
17 #ifndef LEMON_HAO_ORLIN_H
18 #define LEMON_HAO_ORLIN_H
24 #include <lemon/maps.h>
25 #include <lemon/graph_utils.h>
26 #include <lemon/graph_adaptor.h>
27 #include <lemon/iterable_maps.h>
32 /// Implementation of the Hao-Orlin algorithms class for testing network
37 /// \addtogroup flowalgs
40 /// %Hao-Orlin algorithm for calculate minimum cut in directed graphs.
42 /// Hao-Orlin calculates the minimum cut in directed graphs. It
43 /// separates the nodes of the graph into two disjoint sets and the
44 /// summary of the edge capacities go from the first set to the
45 /// second set is the minimum. The algorithm is a modified
46 /// push-relabel preflow algorithm and it calculates the minimum cat
47 /// in \f$ O(n^3) \f$ time. The purpose of such algorithm is testing
48 /// network reliability. For sparse undirected graph you can use the
49 /// algorithm of Nagamochi and Ibraki which solves the undirected
50 /// problem in \f$ O(n^3) \f$ time.
52 /// \author Attila Bernath and Balazs Dezso
53 template <typename _Graph,
54 typename _CapacityMap = typename _Graph::template EdgeMap<int>,
55 typename _Tolerance = Tolerance<typename _CapacityMap::Value> >
60 typedef _CapacityMap CapacityMap;
61 typedef _Tolerance Tolerance;
63 typedef typename CapacityMap::Value Value;
66 typedef typename Graph::Node Node;
67 typedef typename Graph::NodeIt NodeIt;
68 typedef typename Graph::EdgeIt EdgeIt;
69 typedef typename Graph::OutEdgeIt OutEdgeIt;
70 typedef typename Graph::InEdgeIt InEdgeIt;
73 const CapacityMap* _capacity;
75 typedef typename Graph::template EdgeMap<Value> FlowMap;
79 Node _source, _target;
82 typedef ResGraphAdaptor<const Graph, Value, CapacityMap,
83 FlowMap, Tolerance> ResGraph;
84 typedef typename ResGraph::Node ResNode;
85 typedef typename ResGraph::NodeIt ResNodeIt;
86 typedef typename ResGraph::EdgeIt ResEdgeIt;
87 typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
88 typedef typename ResGraph::Edge ResEdge;
89 typedef typename ResGraph::InEdgeIt ResInEdgeIt;
93 typedef typename Graph::template NodeMap<ResEdge> CurrentArcMap;
94 CurrentArcMap* _current_arc;
97 typedef IterableBoolMap<Graph, Node> WakeMap;
100 typedef typename Graph::template NodeMap<int> DistMap;
103 typedef typename Graph::template NodeMap<Value> ExcessMap;
106 typedef typename Graph::template NodeMap<bool> SourceSetMap;
107 SourceSetMap* _source_set;
109 std::vector<int> _level_size;
112 std::vector<std::list<Node> > _active_nodes;
115 std::vector<std::list<Node> > _dormant;
120 typedef typename Graph::template NodeMap<bool> MinCutMap;
121 MinCutMap* _min_cut_map;
123 Tolerance _tolerance;
127 HaoOrlin(const Graph& graph, const CapacityMap& capacity,
128 const Tolerance& tolerance = Tolerance()) :
129 _graph(&graph), _capacity(&capacity),
130 _preflow(0), _source(), _target(), _res_graph(0), _current_arc(0),
131 _wake(0),_dist(0), _excess(0), _source_set(0),
132 _highest_active(), _active_nodes(), _dormant_max(), _dormant(),
133 _min_cut(), _min_cut_map(0), _tolerance(tolerance) {}
164 void relabel(Node i) {
166 if (_level_size[k] == 1) {
168 for (NodeIt it(*_graph); it != INVALID; ++it) {
169 if ((*_wake)[it] && (*_dist)[it] >= k) {
170 (*_wake)[it] = false;
171 _dormant[_dormant_max].push_front(it);
172 --_level_size[(*_dist)[it]];
177 ResOutEdgeIt e(*_res_graph, i);
178 while (e != INVALID && !(*_wake)[_res_graph->target(e)]) {
185 _dormant[_dormant_max].push_front(i);
186 --_level_size[(*_dist)[i]];
188 Node j = _res_graph->target(e);
189 int new_dist = (*_dist)[j];
191 while (e != INVALID){
192 Node j = _res_graph->target(e);
193 if ((*_wake)[j] && new_dist > (*_dist)[j]) {
194 new_dist = (*_dist)[j];
198 --_level_size[(*_dist)[i]];
199 (*_dist)[i] = new_dist + 1;
200 _highest_active = (*_dist)[i];
201 _active_nodes[_highest_active].push_front(i);
202 ++_level_size[(*_dist)[i]];
203 _res_graph->firstOut((*_current_arc)[i], i);
208 bool selectNewSink(){
209 Node old_target = _target;
210 (*_wake)[_target] = false;
211 --_level_size[(*_dist)[_target]];
212 _dormant[0].push_front(_target);
213 (*_source_set)[_target] = true;
214 if ((int)_dormant[0].size() == _node_num){
219 bool wake_was_empty = false;
221 if(_wake->trueNum() == 0) {
222 while (!_dormant[_dormant_max].empty()){
223 (*_wake)[_dormant[_dormant_max].front()] = true;
224 ++_level_size[(*_dist)[_dormant[_dormant_max].front()]];
225 _dormant[_dormant_max].pop_front();
228 wake_was_empty = true;
231 int min_dist = std::numeric_limits<int>::max();
232 for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
233 if (min_dist > (*_dist)[it]){
235 min_dist = (*_dist)[it];
240 for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
241 if (_tolerance.positive((*_excess)[it])) {
242 if ((*_wake)[it] && it != _target) {
243 _active_nodes[(*_dist)[it]].push_front(it);
245 if (_highest_active < (*_dist)[it]) {
246 _highest_active = (*_dist)[it];
252 for (ResOutEdgeIt e(*_res_graph, old_target); e!=INVALID; ++e){
253 if (!(*_source_set)[_res_graph->target(e)]){
254 push(e, _res_graph->rescap(e));
261 Node findActiveNode() {
262 while (_highest_active > 0 && _active_nodes[_highest_active].empty()){
265 if( _highest_active > 0) {
266 Node n = _active_nodes[_highest_active].front();
267 _active_nodes[_highest_active].pop_front();
274 ResEdge findAdmissibleEdge(const Node& n){
275 ResEdge e = (*_current_arc)[n];
276 while (e != INVALID &&
277 ((*_dist)[n] <= (*_dist)[_res_graph->target(e)] ||
278 !(*_wake)[_res_graph->target(e)])) {
279 _res_graph->nextOut(e);
282 (*_current_arc)[n] = e;
289 void push(ResEdge& e,const Value& delta){
290 _res_graph->augment(e, delta);
291 if (!_tolerance.positive(delta)) return;
293 (*_excess)[_res_graph->source(e)] -= delta;
294 Node a = _res_graph->target(e);
295 if (!_tolerance.positive((*_excess)[a]) && (*_wake)[a] && a != _target) {
296 _active_nodes[(*_dist)[a]].push_front(a);
297 if (_highest_active < (*_dist)[a]) {
298 _highest_active = (*_dist)[a];
301 (*_excess)[a] += delta;
306 for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
307 for (InEdgeIt e(*_graph, it); e != INVALID; ++e) {
308 if (!(*_wake)[_graph->source(e)]){
309 value += (*_capacity)[e];
318 /// \brief Initializes the internal data structures.
320 /// Initializes the internal data structures. It creates
321 /// the maps, residual graph adaptor and some bucket structures
322 /// for the algorithm.
324 init(NodeIt(*_graph));
327 /// \brief Initializes the internal data structures.
329 /// Initializes the internal data structures. It creates
330 /// the maps, residual graph adaptor and some bucket structures
331 /// for the algorithm. The \c source node is used as the push-relabel
332 /// algorithm's source.
333 void init(const Node& source) {
335 _node_num = countNodes(*_graph);
337 _dormant.resize(_node_num);
338 _level_size.resize(_node_num, 0);
339 _active_nodes.resize(_node_num);
342 _preflow = new FlowMap(*_graph);
345 _wake = new WakeMap(*_graph);
348 _dist = new DistMap(*_graph);
351 _excess = new ExcessMap(*_graph);
354 _source_set = new SourceSetMap(*_graph);
357 _current_arc = new CurrentArcMap(*_graph);
360 _min_cut_map = new MinCutMap(*_graph);
363 _res_graph = new ResGraph(*_graph, *_capacity, *_preflow);
366 _min_cut = std::numeric_limits<Value>::max();
370 /// \brief Calculates the minimum cut with the \c source node
371 /// in the first partition.
373 /// Calculates the minimum cut with the \c source node
374 /// in the first partition.
375 void calculateOut() {
376 for (NodeIt it(*_graph); it != INVALID; ++it) {
384 /// \brief Calculates the minimum cut with the \c source node
385 /// in the first partition.
387 /// Calculates the minimum cut with the \c source node
388 /// in the first partition. The \c target is the initial target
389 /// for the push-relabel algorithm.
390 void calculateOut(const Node& target) {
391 for (NodeIt it(*_graph); it != INVALID; ++it) {
395 (*_source_set)[it] = false;
397 _res_graph->firstOut((*_current_arc)[it], it);
401 (*_dist)[target] = 0;
403 for (ResOutEdgeIt it(*_res_graph, _source); it != INVALID; ++it) {
404 push(it, _res_graph->rescap(it));
407 _dormant[0].push_front(_source);
408 (*_source_set)[_source] = true;
410 (*_wake)[_source]=false;
413 _level_size[1] = _node_num - 1;
417 while ((n = findActiveNode()) != INVALID) {
419 while (_tolerance.positive((*_excess)[n]) &&
420 (e = findAdmissibleEdge(n)) != INVALID){
422 if ((*_excess)[n] < _res_graph->rescap(e)) {
423 delta = (*_excess)[n];
425 delta = _res_graph->rescap(e);
426 _res_graph->nextOut((*_current_arc)[n]);
428 if (!_tolerance.positive(delta)) continue;
429 _res_graph->augment(e, delta);
430 (*_excess)[_res_graph->source(e)] -= delta;
431 Node a = _res_graph->target(e);
432 if (!_tolerance.positive((*_excess)[a]) && a != _target) {
433 _active_nodes[(*_dist)[a]].push_front(a);
435 (*_excess)[a] += delta;
437 if (_tolerance.positive((*_excess)[n])) {
442 Value current_value = cutValue();
443 if (_min_cut > current_value){
444 for (NodeIt it(*_graph); it != INVALID; ++it) {
445 _min_cut_map->set(it, !(*_wake)[it]);
448 _min_cut = current_value;
451 } while (selectNewSink());
455 for (NodeIt it(*_graph); it != INVALID; ++it) {
465 for (NodeIt it(*_graph); it != INVALID; ++it) {
474 void run(const Node& s) {
476 for (NodeIt it(*_graph); it != INVALID; ++it) {
485 void run(const Node& s, const Node& t) {
491 /// \brief Returns the value of the minimum value cut with node \c
492 /// source on the source side.
494 /// Returns the value of the minimum value cut with node \c source
495 /// on the source side. This function can be called after running
497 Value minCut() const {
502 /// \brief Returns a minimum value cut.
504 /// Sets \c nodeMap to the characteristic vector of a minimum
505 /// value cut with node \c source on the source side. This
506 /// function can be called after running \ref findMinCut.
507 /// \pre nodeMap should be a bool-valued node-map.
508 template <typename NodeMap>
509 Value minCut(NodeMap& nodeMap) const {
510 for (NodeIt it(*_graph); it != INVALID; ++it) {
511 nodeMap.set(it, (*_min_cut_map)[it]);
521 #endif //LEMON_HAO_ORLIN_H