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