deba@2211
|
1 |
/* -*- C++ -*-
|
deba@2211
|
2 |
*
|
deba@2225
|
3 |
* This file is a part of LEMON, a generic C++ optimization library
|
deba@2225
|
4 |
*
|
deba@2225
|
5 |
* Copyright (C) 2003-2006
|
deba@2225
|
6 |
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
|
deba@2211
|
7 |
* (Egervary Research Group on Combinatorial Optimization, EGRES).
|
deba@2211
|
8 |
*
|
deba@2211
|
9 |
* Permission to use, modify and distribute this software is granted
|
deba@2211
|
10 |
* provided that this copyright notice appears in all copies. For
|
deba@2211
|
11 |
* precise terms see the accompanying LICENSE file.
|
deba@2211
|
12 |
*
|
deba@2211
|
13 |
* This software is provided "AS IS" with no warranty of any kind,
|
deba@2211
|
14 |
* express or implied, and with no claim as to its suitability for any
|
deba@2211
|
15 |
* purpose.
|
deba@2211
|
16 |
*
|
deba@2211
|
17 |
*/
|
deba@2211
|
18 |
|
deba@2211
|
19 |
#ifndef LEMON_HAO_ORLIN_H
|
deba@2211
|
20 |
#define LEMON_HAO_ORLIN_H
|
deba@2211
|
21 |
|
deba@2340
|
22 |
#include <cassert>
|
deba@2340
|
23 |
|
deba@2340
|
24 |
|
deba@2340
|
25 |
|
deba@2211
|
26 |
#include <vector>
|
deba@2211
|
27 |
#include <queue>
|
deba@2340
|
28 |
#include <list>
|
deba@2211
|
29 |
#include <limits>
|
deba@2211
|
30 |
|
deba@2211
|
31 |
#include <lemon/maps.h>
|
deba@2211
|
32 |
#include <lemon/graph_utils.h>
|
deba@2211
|
33 |
#include <lemon/graph_adaptor.h>
|
deba@2211
|
34 |
#include <lemon/iterable_maps.h>
|
deba@2211
|
35 |
|
deba@2211
|
36 |
/// \file
|
deba@2376
|
37 |
/// \ingroup min_cut
|
deba@2225
|
38 |
/// \brief Implementation of the Hao-Orlin algorithm.
|
deba@2225
|
39 |
///
|
deba@2225
|
40 |
/// Implementation of the HaoOrlin algorithms class for testing network
|
deba@2211
|
41 |
/// reliability.
|
deba@2211
|
42 |
|
deba@2211
|
43 |
namespace lemon {
|
deba@2211
|
44 |
|
deba@2376
|
45 |
/// \ingroup min_cut
|
deba@2225
|
46 |
///
|
athos@2228
|
47 |
/// \brief %Hao-Orlin algorithm to find a minimum cut in directed graphs.
|
deba@2211
|
48 |
///
|
athos@2273
|
49 |
/// Hao-Orlin calculates a minimum cut in a directed graph
|
athos@2273
|
50 |
/// \f$ D=(V,A) \f$. It takes a fixed node \f$ source \in V \f$ and consists
|
athos@2228
|
51 |
/// of two phases: in the first phase it determines a minimum cut
|
athos@2273
|
52 |
/// with \f$ source \f$ on the source-side (i.e. a set \f$ X\subsetneq V \f$
|
athos@2273
|
53 |
/// with \f$ source \in X \f$ and minimal out-degree) and in the
|
athos@2228
|
54 |
/// second phase it determines a minimum cut with \f$ source \f$ on the
|
athos@2228
|
55 |
/// sink-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \notin X \f$
|
athos@2228
|
56 |
/// and minimal out-degree). Obviously, the smaller of these two
|
athos@2228
|
57 |
/// cuts will be a minimum cut of \f$ D \f$. The algorithm is a
|
athos@2228
|
58 |
/// modified push-relabel preflow algorithm and our implementation
|
athos@2228
|
59 |
/// calculates the minimum cut in \f$ O(n^3) \f$ time (we use the
|
athos@2228
|
60 |
/// highest-label rule). The purpose of such an algorithm is testing
|
athos@2228
|
61 |
/// network reliability. For an undirected graph with \f$ n \f$
|
athos@2228
|
62 |
/// nodes and \f$ e \f$ edges you can use the algorithm of Nagamochi
|
athos@2273
|
63 |
/// and Ibaraki which solves the undirected problem in
|
athos@2273
|
64 |
/// \f$ O(ne + n^2 \log(n)) \f$ time: it is implemented in the MinCut
|
athos@2273
|
65 |
/// algorithm
|
athos@2228
|
66 |
/// class.
|
deba@2225
|
67 |
///
|
deba@2225
|
68 |
/// \param _Graph is the graph type of the algorithm.
|
deba@2225
|
69 |
/// \param _CapacityMap is an edge map of capacities which should
|
deba@2225
|
70 |
/// be any numreric type. The default type is _Graph::EdgeMap<int>.
|
deba@2225
|
71 |
/// \param _Tolerance is the handler of the inexact computation. The
|
athos@2228
|
72 |
/// default type for this is Tolerance<typename CapacityMap::Value>.
|
deba@2211
|
73 |
///
|
deba@2211
|
74 |
/// \author Attila Bernath and Balazs Dezso
|
deba@2225
|
75 |
#ifdef DOXYGEN
|
deba@2225
|
76 |
template <typename _Graph, typename _CapacityMap, typename _Tolerance>
|
deba@2225
|
77 |
#else
|
deba@2211
|
78 |
template <typename _Graph,
|
deba@2211
|
79 |
typename _CapacityMap = typename _Graph::template EdgeMap<int>,
|
deba@2211
|
80 |
typename _Tolerance = Tolerance<typename _CapacityMap::Value> >
|
deba@2225
|
81 |
#endif
|
deba@2211
|
82 |
class HaoOrlin {
|
deba@2211
|
83 |
protected:
|
deba@2211
|
84 |
|
deba@2211
|
85 |
typedef _Graph Graph;
|
deba@2211
|
86 |
typedef _CapacityMap CapacityMap;
|
deba@2211
|
87 |
typedef _Tolerance Tolerance;
|
deba@2211
|
88 |
|
deba@2211
|
89 |
typedef typename CapacityMap::Value Value;
|
deba@2211
|
90 |
|
deba@2211
|
91 |
|
deba@2211
|
92 |
typedef typename Graph::Node Node;
|
deba@2211
|
93 |
typedef typename Graph::NodeIt NodeIt;
|
deba@2211
|
94 |
typedef typename Graph::EdgeIt EdgeIt;
|
deba@2211
|
95 |
typedef typename Graph::OutEdgeIt OutEdgeIt;
|
deba@2211
|
96 |
typedef typename Graph::InEdgeIt InEdgeIt;
|
deba@2211
|
97 |
|
deba@2211
|
98 |
const Graph* _graph;
|
deba@2225
|
99 |
|
deba@2211
|
100 |
const CapacityMap* _capacity;
|
deba@2211
|
101 |
|
deba@2211
|
102 |
typedef typename Graph::template EdgeMap<Value> FlowMap;
|
deba@2211
|
103 |
|
deba@2211
|
104 |
FlowMap* _preflow;
|
deba@2211
|
105 |
|
deba@2211
|
106 |
Node _source, _target;
|
deba@2211
|
107 |
int _node_num;
|
deba@2211
|
108 |
|
deba@2211
|
109 |
typedef ResGraphAdaptor<const Graph, Value, CapacityMap,
|
deba@2225
|
110 |
FlowMap, Tolerance> OutResGraph;
|
deba@2225
|
111 |
typedef typename OutResGraph::Edge OutResEdge;
|
deba@2225
|
112 |
|
deba@2225
|
113 |
OutResGraph* _out_res_graph;
|
deba@2211
|
114 |
|
deba@2225
|
115 |
typedef RevGraphAdaptor<const Graph> RevGraph;
|
deba@2225
|
116 |
RevGraph* _rev_graph;
|
deba@2225
|
117 |
|
deba@2225
|
118 |
typedef ResGraphAdaptor<const RevGraph, Value, CapacityMap,
|
deba@2225
|
119 |
FlowMap, Tolerance> InResGraph;
|
deba@2225
|
120 |
typedef typename InResGraph::Edge InResEdge;
|
deba@2225
|
121 |
|
deba@2225
|
122 |
InResGraph* _in_res_graph;
|
deba@2225
|
123 |
|
deba@2211
|
124 |
typedef IterableBoolMap<Graph, Node> WakeMap;
|
deba@2211
|
125 |
WakeMap* _wake;
|
deba@2211
|
126 |
|
deba@2211
|
127 |
typedef typename Graph::template NodeMap<int> DistMap;
|
deba@2211
|
128 |
DistMap* _dist;
|
deba@2211
|
129 |
|
deba@2211
|
130 |
typedef typename Graph::template NodeMap<Value> ExcessMap;
|
deba@2211
|
131 |
ExcessMap* _excess;
|
deba@2211
|
132 |
|
deba@2211
|
133 |
typedef typename Graph::template NodeMap<bool> SourceSetMap;
|
deba@2211
|
134 |
SourceSetMap* _source_set;
|
deba@2211
|
135 |
|
deba@2211
|
136 |
std::vector<int> _level_size;
|
deba@2211
|
137 |
|
deba@2211
|
138 |
int _highest_active;
|
deba@2211
|
139 |
std::vector<std::list<Node> > _active_nodes;
|
deba@2211
|
140 |
|
deba@2211
|
141 |
int _dormant_max;
|
deba@2211
|
142 |
std::vector<std::list<Node> > _dormant;
|
deba@2211
|
143 |
|
deba@2211
|
144 |
|
deba@2211
|
145 |
Value _min_cut;
|
deba@2211
|
146 |
|
deba@2211
|
147 |
typedef typename Graph::template NodeMap<bool> MinCutMap;
|
deba@2211
|
148 |
MinCutMap* _min_cut_map;
|
deba@2211
|
149 |
|
deba@2211
|
150 |
Tolerance _tolerance;
|
deba@2211
|
151 |
|
deba@2211
|
152 |
public:
|
deba@2211
|
153 |
|
deba@2225
|
154 |
/// \brief Constructor
|
deba@2225
|
155 |
///
|
deba@2225
|
156 |
/// Constructor of the algorithm class.
|
deba@2211
|
157 |
HaoOrlin(const Graph& graph, const CapacityMap& capacity,
|
deba@2211
|
158 |
const Tolerance& tolerance = Tolerance()) :
|
deba@2211
|
159 |
_graph(&graph), _capacity(&capacity),
|
deba@2225
|
160 |
_preflow(0), _source(), _target(),
|
deba@2340
|
161 |
_out_res_graph(0), _rev_graph(0), _in_res_graph(0),
|
deba@2211
|
162 |
_wake(0),_dist(0), _excess(0), _source_set(0),
|
deba@2211
|
163 |
_highest_active(), _active_nodes(), _dormant_max(), _dormant(),
|
deba@2211
|
164 |
_min_cut(), _min_cut_map(0), _tolerance(tolerance) {}
|
deba@2211
|
165 |
|
deba@2211
|
166 |
~HaoOrlin() {
|
deba@2211
|
167 |
if (_min_cut_map) {
|
deba@2211
|
168 |
delete _min_cut_map;
|
deba@2211
|
169 |
}
|
deba@2225
|
170 |
if (_in_res_graph) {
|
deba@2225
|
171 |
delete _in_res_graph;
|
deba@2225
|
172 |
}
|
deba@2225
|
173 |
if (_rev_graph) {
|
deba@2225
|
174 |
delete _rev_graph;
|
deba@2225
|
175 |
}
|
deba@2225
|
176 |
if (_out_res_graph) {
|
deba@2225
|
177 |
delete _out_res_graph;
|
deba@2211
|
178 |
}
|
deba@2211
|
179 |
if (_source_set) {
|
deba@2211
|
180 |
delete _source_set;
|
deba@2211
|
181 |
}
|
deba@2211
|
182 |
if (_excess) {
|
deba@2211
|
183 |
delete _excess;
|
deba@2211
|
184 |
}
|
deba@2211
|
185 |
if (_dist) {
|
deba@2211
|
186 |
delete _dist;
|
deba@2211
|
187 |
}
|
deba@2211
|
188 |
if (_wake) {
|
deba@2211
|
189 |
delete _wake;
|
deba@2211
|
190 |
}
|
deba@2211
|
191 |
if (_preflow) {
|
deba@2211
|
192 |
delete _preflow;
|
deba@2211
|
193 |
}
|
deba@2211
|
194 |
}
|
deba@2211
|
195 |
|
deba@2211
|
196 |
private:
|
deba@2211
|
197 |
|
deba@2340
|
198 |
template <typename ResGraph>
|
deba@2340
|
199 |
void findMinCut(const Node& target, bool out, ResGraph& res_graph) {
|
deba@2340
|
200 |
typedef typename Graph::Node Node;
|
deba@2225
|
201 |
typedef typename ResGraph::Edge ResEdge;
|
deba@2225
|
202 |
typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
|
deba@2225
|
203 |
|
deba@2225
|
204 |
for (typename Graph::EdgeIt it(*_graph); it != INVALID; ++it) {
|
deba@2225
|
205 |
(*_preflow)[it] = 0;
|
deba@2225
|
206 |
}
|
deba@2225
|
207 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2225
|
208 |
(*_wake)[it] = true;
|
deba@2225
|
209 |
(*_dist)[it] = 1;
|
deba@2225
|
210 |
(*_excess)[it] = 0;
|
deba@2225
|
211 |
(*_source_set)[it] = false;
|
deba@2225
|
212 |
}
|
deba@2225
|
213 |
|
deba@2225
|
214 |
_dormant[0].push_front(_source);
|
deba@2225
|
215 |
(*_source_set)[_source] = true;
|
deba@2225
|
216 |
_dormant_max = 0;
|
deba@2225
|
217 |
(*_wake)[_source] = false;
|
deba@2225
|
218 |
|
deba@2225
|
219 |
_level_size[0] = 1;
|
deba@2225
|
220 |
_level_size[1] = _node_num - 1;
|
deba@2225
|
221 |
|
deba@2340
|
222 |
_target = target;
|
deba@2340
|
223 |
(*_dist)[target] = 0;
|
deba@2340
|
224 |
|
deba@2340
|
225 |
for (ResOutEdgeIt it(res_graph, _source); it != INVALID; ++it) {
|
deba@2340
|
226 |
Value delta = res_graph.rescap(it);
|
deba@2340
|
227 |
(*_excess)[_source] -= delta;
|
deba@2340
|
228 |
res_graph.augment(it, delta);
|
deba@2340
|
229 |
Node a = res_graph.target(it);
|
deba@2340
|
230 |
if ((*_excess)[a] == 0 && (*_wake)[a] && a != _target) {
|
deba@2340
|
231 |
_active_nodes[(*_dist)[a]].push_front(a);
|
deba@2340
|
232 |
if (_highest_active < (*_dist)[a]) {
|
deba@2340
|
233 |
_highest_active = (*_dist)[a];
|
deba@2340
|
234 |
}
|
deba@2340
|
235 |
}
|
deba@2340
|
236 |
(*_excess)[a] += delta;
|
deba@2340
|
237 |
}
|
deba@2340
|
238 |
|
deba@2340
|
239 |
|
deba@2225
|
240 |
do {
|
deba@2225
|
241 |
Node n;
|
deba@2225
|
242 |
while ((n = findActiveNode()) != INVALID) {
|
deba@2340
|
243 |
for (ResOutEdgeIt e(res_graph, n); e != INVALID; ++e) {
|
deba@2340
|
244 |
Node a = res_graph.target(e);
|
deba@2340
|
245 |
if ((*_dist)[a] >= (*_dist)[n] || !(*_wake)[a]) continue;
|
deba@2340
|
246 |
Value delta = res_graph.rescap(e);
|
deba@2340
|
247 |
if (_tolerance.positive((*_excess)[n] - delta)) {
|
deba@2340
|
248 |
(*_excess)[n] -= delta;
|
deba@2340
|
249 |
} else {
|
deba@2225
|
250 |
delta = (*_excess)[n];
|
deba@2340
|
251 |
(*_excess)[n] = 0;
|
deba@2225
|
252 |
}
|
deba@2225
|
253 |
res_graph.augment(e, delta);
|
deba@2340
|
254 |
if ((*_excess)[a] == 0 && a != _target) {
|
deba@2225
|
255 |
_active_nodes[(*_dist)[a]].push_front(a);
|
deba@2225
|
256 |
}
|
deba@2225
|
257 |
(*_excess)[a] += delta;
|
deba@2340
|
258 |
if ((*_excess)[n] == 0) break;
|
deba@2225
|
259 |
}
|
deba@2340
|
260 |
if ((*_excess)[n] != 0) {
|
deba@2340
|
261 |
relabel(n, res_graph);
|
deba@2225
|
262 |
}
|
deba@2225
|
263 |
}
|
deba@2225
|
264 |
|
deba@2225
|
265 |
Value current_value = cutValue(out);
|
deba@2225
|
266 |
if (_min_cut > current_value){
|
deba@2225
|
267 |
if (out) {
|
deba@2225
|
268 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2225
|
269 |
_min_cut_map->set(it, !(*_wake)[it]);
|
deba@2225
|
270 |
}
|
deba@2225
|
271 |
} else {
|
deba@2225
|
272 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2225
|
273 |
_min_cut_map->set(it, (*_wake)[it]);
|
deba@2225
|
274 |
}
|
deba@2225
|
275 |
}
|
deba@2225
|
276 |
|
deba@2225
|
277 |
_min_cut = current_value;
|
deba@2225
|
278 |
}
|
deba@2225
|
279 |
|
deba@2225
|
280 |
} while (selectNewSink(res_graph));
|
deba@2225
|
281 |
}
|
deba@2225
|
282 |
|
deba@2340
|
283 |
template <typename ResGraph>
|
deba@2340
|
284 |
void relabel(const Node& n, ResGraph& res_graph) {
|
deba@2225
|
285 |
typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
|
deba@2225
|
286 |
|
deba@2225
|
287 |
int k = (*_dist)[n];
|
deba@2211
|
288 |
if (_level_size[k] == 1) {
|
deba@2211
|
289 |
++_dormant_max;
|
deba@2211
|
290 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2211
|
291 |
if ((*_wake)[it] && (*_dist)[it] >= k) {
|
deba@2211
|
292 |
(*_wake)[it] = false;
|
deba@2211
|
293 |
_dormant[_dormant_max].push_front(it);
|
deba@2211
|
294 |
--_level_size[(*_dist)[it]];
|
deba@2211
|
295 |
}
|
deba@2211
|
296 |
}
|
deba@2340
|
297 |
--_highest_active;
|
deba@2225
|
298 |
} else {
|
deba@2225
|
299 |
int new_dist = _node_num;
|
deba@2225
|
300 |
for (ResOutEdgeIt e(res_graph, n); e != INVALID; ++e) {
|
deba@2225
|
301 |
Node t = res_graph.target(e);
|
deba@2225
|
302 |
if ((*_wake)[t] && new_dist > (*_dist)[t]) {
|
deba@2225
|
303 |
new_dist = (*_dist)[t];
|
deba@2225
|
304 |
}
|
deba@2225
|
305 |
}
|
deba@2225
|
306 |
if (new_dist == _node_num) {
|
deba@2211
|
307 |
++_dormant_max;
|
deba@2225
|
308 |
(*_wake)[n] = false;
|
deba@2225
|
309 |
_dormant[_dormant_max].push_front(n);
|
deba@2225
|
310 |
--_level_size[(*_dist)[n]];
|
deba@2225
|
311 |
} else {
|
deba@2225
|
312 |
--_level_size[(*_dist)[n]];
|
deba@2225
|
313 |
(*_dist)[n] = new_dist + 1;
|
deba@2225
|
314 |
_highest_active = (*_dist)[n];
|
deba@2225
|
315 |
_active_nodes[_highest_active].push_front(n);
|
deba@2225
|
316 |
++_level_size[(*_dist)[n]];
|
deba@2211
|
317 |
}
|
deba@2211
|
318 |
}
|
deba@2211
|
319 |
}
|
deba@2211
|
320 |
|
deba@2225
|
321 |
template <typename ResGraph>
|
deba@2225
|
322 |
bool selectNewSink(ResGraph& res_graph) {
|
deba@2225
|
323 |
typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
|
deba@2225
|
324 |
|
deba@2211
|
325 |
Node old_target = _target;
|
deba@2211
|
326 |
(*_wake)[_target] = false;
|
deba@2211
|
327 |
--_level_size[(*_dist)[_target]];
|
deba@2211
|
328 |
_dormant[0].push_front(_target);
|
deba@2211
|
329 |
(*_source_set)[_target] = true;
|
deba@2211
|
330 |
if ((int)_dormant[0].size() == _node_num){
|
deba@2211
|
331 |
_dormant[0].clear();
|
deba@2211
|
332 |
return false;
|
deba@2211
|
333 |
}
|
deba@2211
|
334 |
|
deba@2211
|
335 |
bool wake_was_empty = false;
|
deba@2211
|
336 |
|
deba@2211
|
337 |
if(_wake->trueNum() == 0) {
|
deba@2211
|
338 |
while (!_dormant[_dormant_max].empty()){
|
deba@2211
|
339 |
(*_wake)[_dormant[_dormant_max].front()] = true;
|
deba@2211
|
340 |
++_level_size[(*_dist)[_dormant[_dormant_max].front()]];
|
deba@2211
|
341 |
_dormant[_dormant_max].pop_front();
|
deba@2211
|
342 |
}
|
deba@2211
|
343 |
--_dormant_max;
|
deba@2211
|
344 |
wake_was_empty = true;
|
deba@2211
|
345 |
}
|
deba@2211
|
346 |
|
deba@2211
|
347 |
int min_dist = std::numeric_limits<int>::max();
|
deba@2211
|
348 |
for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
|
deba@2211
|
349 |
if (min_dist > (*_dist)[it]){
|
deba@2211
|
350 |
_target = it;
|
deba@2211
|
351 |
min_dist = (*_dist)[it];
|
deba@2211
|
352 |
}
|
deba@2211
|
353 |
}
|
deba@2211
|
354 |
|
deba@2211
|
355 |
if (wake_was_empty){
|
deba@2211
|
356 |
for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
|
deba@2340
|
357 |
if ((*_excess)[it] != 0 && it != _target) {
|
deba@2340
|
358 |
_active_nodes[(*_dist)[it]].push_front(it);
|
deba@2340
|
359 |
if (_highest_active < (*_dist)[it]) {
|
deba@2340
|
360 |
_highest_active = (*_dist)[it];
|
deba@2211
|
361 |
}
|
deba@2211
|
362 |
}
|
deba@2211
|
363 |
}
|
deba@2211
|
364 |
}
|
deba@2211
|
365 |
|
deba@2340
|
366 |
Node n = old_target;
|
deba@2340
|
367 |
for (ResOutEdgeIt e(res_graph, n); e != INVALID; ++e){
|
deba@2340
|
368 |
Node a = res_graph.target(e);
|
deba@2340
|
369 |
if (!(*_wake)[a]) continue;
|
deba@2340
|
370 |
Value delta = res_graph.rescap(e);
|
deba@2340
|
371 |
res_graph.augment(e, delta);
|
deba@2340
|
372 |
(*_excess)[n] -= delta;
|
deba@2340
|
373 |
if ((*_excess)[a] == 0 && (*_wake)[a] && a != _target) {
|
deba@2340
|
374 |
_active_nodes[(*_dist)[a]].push_front(a);
|
deba@2340
|
375 |
if (_highest_active < (*_dist)[a]) {
|
deba@2340
|
376 |
_highest_active = (*_dist)[a];
|
deba@2225
|
377 |
}
|
deba@2340
|
378 |
}
|
deba@2340
|
379 |
(*_excess)[a] += delta;
|
deba@2211
|
380 |
}
|
deba@2211
|
381 |
|
deba@2211
|
382 |
return true;
|
deba@2211
|
383 |
}
|
deba@2340
|
384 |
|
deba@2211
|
385 |
Node findActiveNode() {
|
deba@2211
|
386 |
while (_highest_active > 0 && _active_nodes[_highest_active].empty()){
|
deba@2211
|
387 |
--_highest_active;
|
deba@2211
|
388 |
}
|
deba@2211
|
389 |
if( _highest_active > 0) {
|
deba@2211
|
390 |
Node n = _active_nodes[_highest_active].front();
|
deba@2211
|
391 |
_active_nodes[_highest_active].pop_front();
|
deba@2211
|
392 |
return n;
|
deba@2211
|
393 |
} else {
|
deba@2211
|
394 |
return INVALID;
|
deba@2211
|
395 |
}
|
deba@2211
|
396 |
}
|
deba@2211
|
397 |
|
deba@2225
|
398 |
Value cutValue(bool out) {
|
deba@2225
|
399 |
Value value = 0;
|
deba@2225
|
400 |
if (out) {
|
deba@2225
|
401 |
for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
|
deba@2225
|
402 |
for (InEdgeIt e(*_graph, it); e != INVALID; ++e) {
|
deba@2225
|
403 |
if (!(*_wake)[_graph->source(e)]){
|
deba@2225
|
404 |
value += (*_capacity)[e];
|
deba@2225
|
405 |
}
|
deba@2225
|
406 |
}
|
deba@2225
|
407 |
}
|
deba@2225
|
408 |
} else {
|
deba@2225
|
409 |
for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
|
deba@2225
|
410 |
for (OutEdgeIt e(*_graph, it); e != INVALID; ++e) {
|
deba@2225
|
411 |
if (!(*_wake)[_graph->target(e)]){
|
deba@2225
|
412 |
value += (*_capacity)[e];
|
deba@2225
|
413 |
}
|
deba@2225
|
414 |
}
|
deba@2211
|
415 |
}
|
deba@2211
|
416 |
}
|
deba@2225
|
417 |
return value;
|
deba@2211
|
418 |
}
|
deba@2225
|
419 |
|
deba@2211
|
420 |
|
deba@2211
|
421 |
public:
|
deba@2211
|
422 |
|
deba@2225
|
423 |
/// \name Execution control
|
deba@2225
|
424 |
/// The simplest way to execute the algorithm is to use
|
deba@2225
|
425 |
/// one of the member functions called \c run(...).
|
deba@2225
|
426 |
/// \n
|
deba@2225
|
427 |
/// If you need more control on the execution,
|
deba@2225
|
428 |
/// first you must call \ref init(), then the \ref calculateIn() or
|
deba@2225
|
429 |
/// \ref calculateIn() functions.
|
deba@2225
|
430 |
|
deba@2225
|
431 |
/// @{
|
deba@2225
|
432 |
|
deba@2211
|
433 |
/// \brief Initializes the internal data structures.
|
deba@2211
|
434 |
///
|
deba@2211
|
435 |
/// Initializes the internal data structures. It creates
|
deba@2225
|
436 |
/// the maps, residual graph adaptors and some bucket structures
|
deba@2211
|
437 |
/// for the algorithm.
|
deba@2211
|
438 |
void init() {
|
deba@2211
|
439 |
init(NodeIt(*_graph));
|
deba@2211
|
440 |
}
|
deba@2211
|
441 |
|
deba@2211
|
442 |
/// \brief Initializes the internal data structures.
|
deba@2211
|
443 |
///
|
deba@2211
|
444 |
/// Initializes the internal data structures. It creates
|
deba@2211
|
445 |
/// the maps, residual graph adaptor and some bucket structures
|
athos@2228
|
446 |
/// for the algorithm. Node \c source is used as the push-relabel
|
deba@2211
|
447 |
/// algorithm's source.
|
deba@2211
|
448 |
void init(const Node& source) {
|
deba@2211
|
449 |
_source = source;
|
deba@2211
|
450 |
_node_num = countNodes(*_graph);
|
deba@2211
|
451 |
|
deba@2211
|
452 |
_dormant.resize(_node_num);
|
deba@2211
|
453 |
_level_size.resize(_node_num, 0);
|
deba@2211
|
454 |
_active_nodes.resize(_node_num);
|
deba@2211
|
455 |
|
deba@2211
|
456 |
if (!_preflow) {
|
deba@2211
|
457 |
_preflow = new FlowMap(*_graph);
|
deba@2211
|
458 |
}
|
deba@2211
|
459 |
if (!_wake) {
|
deba@2211
|
460 |
_wake = new WakeMap(*_graph);
|
deba@2211
|
461 |
}
|
deba@2211
|
462 |
if (!_dist) {
|
deba@2211
|
463 |
_dist = new DistMap(*_graph);
|
deba@2211
|
464 |
}
|
deba@2211
|
465 |
if (!_excess) {
|
deba@2211
|
466 |
_excess = new ExcessMap(*_graph);
|
deba@2211
|
467 |
}
|
deba@2211
|
468 |
if (!_source_set) {
|
deba@2211
|
469 |
_source_set = new SourceSetMap(*_graph);
|
deba@2211
|
470 |
}
|
deba@2225
|
471 |
if (!_out_res_graph) {
|
deba@2225
|
472 |
_out_res_graph = new OutResGraph(*_graph, *_capacity, *_preflow);
|
deba@2225
|
473 |
}
|
deba@2225
|
474 |
if (!_rev_graph) {
|
deba@2225
|
475 |
_rev_graph = new RevGraph(*_graph);
|
deba@2225
|
476 |
}
|
deba@2225
|
477 |
if (!_in_res_graph) {
|
deba@2225
|
478 |
_in_res_graph = new InResGraph(*_rev_graph, *_capacity, *_preflow);
|
deba@2225
|
479 |
}
|
deba@2211
|
480 |
if (!_min_cut_map) {
|
deba@2211
|
481 |
_min_cut_map = new MinCutMap(*_graph);
|
deba@2211
|
482 |
}
|
deba@2211
|
483 |
|
deba@2211
|
484 |
_min_cut = std::numeric_limits<Value>::max();
|
deba@2211
|
485 |
}
|
deba@2211
|
486 |
|
deba@2211
|
487 |
|
athos@2228
|
488 |
/// \brief Calculates a minimum cut with \f$ source \f$ on the
|
athos@2228
|
489 |
/// source-side.
|
deba@2211
|
490 |
///
|
athos@2228
|
491 |
/// \brief Calculates a minimum cut with \f$ source \f$ on the
|
athos@2273
|
492 |
/// source-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \in X \f$
|
athos@2273
|
493 |
/// and minimal out-degree).
|
deba@2211
|
494 |
void calculateOut() {
|
deba@2211
|
495 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2211
|
496 |
if (it != _source) {
|
deba@2211
|
497 |
calculateOut(it);
|
deba@2211
|
498 |
return;
|
deba@2211
|
499 |
}
|
deba@2211
|
500 |
}
|
deba@2211
|
501 |
}
|
deba@2211
|
502 |
|
athos@2228
|
503 |
/// \brief Calculates a minimum cut with \f$ source \f$ on the
|
athos@2228
|
504 |
/// source-side.
|
deba@2211
|
505 |
///
|
athos@2228
|
506 |
/// \brief Calculates a minimum cut with \f$ source \f$ on the
|
athos@2273
|
507 |
/// source-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \in X \f$
|
athos@2273
|
508 |
/// and minimal out-degree). The \c target is the initial target
|
deba@2211
|
509 |
/// for the push-relabel algorithm.
|
deba@2211
|
510 |
void calculateOut(const Node& target) {
|
deba@2340
|
511 |
findMinCut(target, true, *_out_res_graph);
|
deba@2211
|
512 |
}
|
deba@2211
|
513 |
|
athos@2228
|
514 |
/// \brief Calculates a minimum cut with \f$ source \f$ on the
|
athos@2228
|
515 |
/// sink-side.
|
deba@2225
|
516 |
///
|
athos@2228
|
517 |
/// \brief Calculates a minimum cut with \f$ source \f$ on the
|
athos@2273
|
518 |
/// sink-side (i.e. a set \f$ X\subsetneq V \f$ with
|
athos@2273
|
519 |
/// \f$ source \notin X \f$
|
athos@2273
|
520 |
/// and minimal out-degree).
|
deba@2211
|
521 |
void calculateIn() {
|
deba@2211
|
522 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2211
|
523 |
if (it != _source) {
|
deba@2211
|
524 |
calculateIn(it);
|
deba@2211
|
525 |
return;
|
deba@2211
|
526 |
}
|
deba@2211
|
527 |
}
|
deba@2211
|
528 |
}
|
deba@2211
|
529 |
|
athos@2228
|
530 |
/// \brief Calculates a minimum cut with \f$ source \f$ on the
|
athos@2228
|
531 |
/// sink-side.
|
deba@2225
|
532 |
///
|
athos@2228
|
533 |
/// \brief Calculates a minimum cut with \f$ source \f$ on the
|
athos@2273
|
534 |
/// sink-side (i.e. a set \f$ X\subsetneq V
|
athos@2273
|
535 |
/// \f$ with \f$ source \notin X \f$ and minimal out-degree).
|
athos@2273
|
536 |
/// The \c target is the initial
|
athos@2228
|
537 |
/// target for the push-relabel algorithm.
|
deba@2225
|
538 |
void calculateIn(const Node& target) {
|
deba@2340
|
539 |
findMinCut(target, false, *_in_res_graph);
|
deba@2225
|
540 |
}
|
deba@2225
|
541 |
|
deba@2225
|
542 |
/// \brief Runs the algorithm.
|
deba@2225
|
543 |
///
|
athos@2228
|
544 |
/// Runs the algorithm. It finds nodes \c source and \c target
|
athos@2228
|
545 |
/// arbitrarily and then calls \ref init(), \ref calculateOut()
|
athos@2228
|
546 |
/// and \ref calculateIn().
|
deba@2211
|
547 |
void run() {
|
deba@2211
|
548 |
init();
|
deba@2211
|
549 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2211
|
550 |
if (it != _source) {
|
deba@2225
|
551 |
calculateOut(it);
|
deba@2225
|
552 |
calculateIn(it);
|
deba@2211
|
553 |
return;
|
deba@2211
|
554 |
}
|
deba@2211
|
555 |
}
|
deba@2211
|
556 |
}
|
deba@2211
|
557 |
|
deba@2225
|
558 |
/// \brief Runs the algorithm.
|
deba@2225
|
559 |
///
|
athos@2228
|
560 |
/// Runs the algorithm. It uses the given \c source node, finds a
|
athos@2228
|
561 |
/// proper \c target and then calls the \ref init(), \ref
|
athos@2228
|
562 |
/// calculateOut() and \ref calculateIn().
|
deba@2211
|
563 |
void run(const Node& s) {
|
deba@2211
|
564 |
init(s);
|
deba@2211
|
565 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2211
|
566 |
if (it != _source) {
|
deba@2225
|
567 |
calculateOut(it);
|
deba@2225
|
568 |
calculateIn(it);
|
deba@2211
|
569 |
return;
|
deba@2211
|
570 |
}
|
deba@2211
|
571 |
}
|
deba@2211
|
572 |
}
|
deba@2211
|
573 |
|
deba@2225
|
574 |
/// \brief Runs the algorithm.
|
deba@2225
|
575 |
///
|
deba@2225
|
576 |
/// Runs the algorithm. It just calls the \ref init() and then
|
deba@2225
|
577 |
/// \ref calculateOut() and \ref calculateIn().
|
deba@2211
|
578 |
void run(const Node& s, const Node& t) {
|
deba@2225
|
579 |
init(s);
|
deba@2225
|
580 |
calculateOut(t);
|
deba@2225
|
581 |
calculateIn(t);
|
deba@2211
|
582 |
}
|
deba@2225
|
583 |
|
deba@2225
|
584 |
/// @}
|
deba@2211
|
585 |
|
athos@2275
|
586 |
/// \name Query Functions
|
athos@2275
|
587 |
/// The result of the %HaoOrlin algorithm
|
deba@2225
|
588 |
/// can be obtained using these functions.
|
deba@2225
|
589 |
/// \n
|
athos@2275
|
590 |
/// Before using these functions, either \ref run(), \ref
|
deba@2225
|
591 |
/// calculateOut() or \ref calculateIn() must be called.
|
deba@2225
|
592 |
|
deba@2225
|
593 |
/// @{
|
deba@2225
|
594 |
|
deba@2225
|
595 |
/// \brief Returns the value of the minimum value cut.
|
deba@2211
|
596 |
///
|
deba@2225
|
597 |
/// Returns the value of the minimum value cut.
|
deba@2211
|
598 |
Value minCut() const {
|
deba@2211
|
599 |
return _min_cut;
|
deba@2211
|
600 |
}
|
deba@2211
|
601 |
|
deba@2211
|
602 |
|
athos@2228
|
603 |
/// \brief Returns a minimum cut.
|
deba@2211
|
604 |
///
|
deba@2211
|
605 |
/// Sets \c nodeMap to the characteristic vector of a minimum
|
athos@2228
|
606 |
/// value cut: it will give a nonempty set \f$ X\subsetneq V \f$
|
athos@2228
|
607 |
/// with minimal out-degree (i.e. \c nodeMap will be true exactly
|
athos@2275
|
608 |
/// for the nodes of \f$ X \f$). \pre nodeMap should be a
|
athos@2228
|
609 |
/// bool-valued node-map.
|
deba@2211
|
610 |
template <typename NodeMap>
|
deba@2211
|
611 |
Value minCut(NodeMap& nodeMap) const {
|
deba@2211
|
612 |
for (NodeIt it(*_graph); it != INVALID; ++it) {
|
deba@2211
|
613 |
nodeMap.set(it, (*_min_cut_map)[it]);
|
deba@2211
|
614 |
}
|
deba@2211
|
615 |
return minCut();
|
deba@2211
|
616 |
}
|
deba@2225
|
617 |
|
deba@2225
|
618 |
/// @}
|
deba@2211
|
619 |
|
deba@2211
|
620 |
}; //class HaoOrlin
|
deba@2211
|
621 |
|
deba@2211
|
622 |
|
deba@2211
|
623 |
} //namespace lemon
|
deba@2211
|
624 |
|
deba@2211
|
625 |
#endif //LEMON_HAO_ORLIN_H
|