1.1 --- a/lemon/Makefile.am Tue Dec 02 10:31:20 2008 +0000
1.2 +++ b/lemon/Makefile.am Tue Dec 02 11:01:48 2008 +0000
1.3 @@ -36,6 +36,7 @@
1.4 lemon/grid_graph.h \
1.5 lemon/hypercube_graph.h \
1.6 lemon/kruskal.h \
1.7 + lemon/hao_orlin.h \
1.8 lemon/lgf_reader.h \
1.9 lemon/lgf_writer.h \
1.10 lemon/list_graph.h \
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/lemon/hao_orlin.h Tue Dec 02 11:01:48 2008 +0000
2.3 @@ -0,0 +1,966 @@
2.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
2.5 + *
2.6 + * This file is a part of LEMON, a generic C++ optimization library.
2.7 + *
2.8 + * Copyright (C) 2003-2008
2.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
2.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
2.11 + *
2.12 + * Permission to use, modify and distribute this software is granted
2.13 + * provided that this copyright notice appears in all copies. For
2.14 + * precise terms see the accompanying LICENSE file.
2.15 + *
2.16 + * This software is provided "AS IS" with no warranty of any kind,
2.17 + * express or implied, and with no claim as to its suitability for any
2.18 + * purpose.
2.19 + *
2.20 + */
2.21 +
2.22 +#ifndef LEMON_HAO_ORLIN_H
2.23 +#define LEMON_HAO_ORLIN_H
2.24 +
2.25 +#include <vector>
2.26 +#include <list>
2.27 +#include <limits>
2.28 +
2.29 +#include <lemon/maps.h>
2.30 +#include <lemon/core.h>
2.31 +#include <lemon/tolerance.h>
2.32 +
2.33 +/// \file
2.34 +/// \ingroup min_cut
2.35 +/// \brief Implementation of the Hao-Orlin algorithm.
2.36 +///
2.37 +/// Implementation of the Hao-Orlin algorithm class for testing network
2.38 +/// reliability.
2.39 +
2.40 +namespace lemon {
2.41 +
2.42 + /// \ingroup min_cut
2.43 + ///
2.44 + /// \brief %Hao-Orlin algorithm to find a minimum cut in directed graphs.
2.45 + ///
2.46 + /// Hao-Orlin calculates a minimum cut in a directed graph
2.47 + /// \f$D=(V,A)\f$. It takes a fixed node \f$ source \in V \f$ and
2.48 + /// consists of two phases: in the first phase it determines a
2.49 + /// minimum cut with \f$ source \f$ on the source-side (i.e. a set
2.50 + /// \f$ X\subsetneq V \f$ with \f$ source \in X \f$ and minimal
2.51 + /// out-degree) and in the second phase it determines a minimum cut
2.52 + /// with \f$ source \f$ on the sink-side (i.e. a set
2.53 + /// \f$ X\subsetneq V \f$ with \f$ source \notin X \f$ and minimal
2.54 + /// out-degree). Obviously, the smaller of these two cuts will be a
2.55 + /// minimum cut of \f$ D \f$. The algorithm is a modified
2.56 + /// push-relabel preflow algorithm and our implementation calculates
2.57 + /// the minimum cut in \f$ O(n^2\sqrt{m}) \f$ time (we use the
2.58 + /// highest-label rule), or in \f$O(nm)\f$ for unit capacities. The
2.59 + /// purpose of such algorithm is testing network reliability. For an
2.60 + /// undirected graph you can run just the first phase of the
2.61 + /// algorithm or you can use the algorithm of Nagamochi and Ibaraki
2.62 + /// which solves the undirected problem in
2.63 + /// \f$ O(nm + n^2 \log(n)) \f$ time: it is implemented in the
2.64 + /// NagamochiIbaraki algorithm class.
2.65 + ///
2.66 + /// \param _Digraph is the graph type of the algorithm.
2.67 + /// \param _CapacityMap is an edge map of capacities which should
2.68 + /// be any numreric type. The default type is _Digraph::ArcMap<int>.
2.69 + /// \param _Tolerance is the handler of the inexact computation. The
2.70 + /// default type for this is Tolerance<CapacityMap::Value>.
2.71 +#ifdef DOXYGEN
2.72 + template <typename _Digraph, typename _CapacityMap, typename _Tolerance>
2.73 +#else
2.74 + template <typename _Digraph,
2.75 + typename _CapacityMap = typename _Digraph::template ArcMap<int>,
2.76 + typename _Tolerance = Tolerance<typename _CapacityMap::Value> >
2.77 +#endif
2.78 + class HaoOrlin {
2.79 + private:
2.80 +
2.81 + typedef _Digraph Digraph;
2.82 + typedef _CapacityMap CapacityMap;
2.83 + typedef _Tolerance Tolerance;
2.84 +
2.85 + typedef typename CapacityMap::Value Value;
2.86 +
2.87 + TEMPLATE_GRAPH_TYPEDEFS(Digraph);
2.88 +
2.89 + const Digraph& _graph;
2.90 + const CapacityMap* _capacity;
2.91 +
2.92 + typedef typename Digraph::template ArcMap<Value> FlowMap;
2.93 + FlowMap* _flow;
2.94 +
2.95 + Node _source;
2.96 +
2.97 + int _node_num;
2.98 +
2.99 + // Bucketing structure
2.100 + std::vector<Node> _first, _last;
2.101 + typename Digraph::template NodeMap<Node>* _next;
2.102 + typename Digraph::template NodeMap<Node>* _prev;
2.103 + typename Digraph::template NodeMap<bool>* _active;
2.104 + typename Digraph::template NodeMap<int>* _bucket;
2.105 +
2.106 + std::vector<bool> _dormant;
2.107 +
2.108 + std::list<std::list<int> > _sets;
2.109 + std::list<int>::iterator _highest;
2.110 +
2.111 + typedef typename Digraph::template NodeMap<Value> ExcessMap;
2.112 + ExcessMap* _excess;
2.113 +
2.114 + typedef typename Digraph::template NodeMap<bool> SourceSetMap;
2.115 + SourceSetMap* _source_set;
2.116 +
2.117 + Value _min_cut;
2.118 +
2.119 + typedef typename Digraph::template NodeMap<bool> MinCutMap;
2.120 + MinCutMap* _min_cut_map;
2.121 +
2.122 + Tolerance _tolerance;
2.123 +
2.124 + public:
2.125 +
2.126 + /// \brief Constructor
2.127 + ///
2.128 + /// Constructor of the algorithm class.
2.129 + HaoOrlin(const Digraph& graph, const CapacityMap& capacity,
2.130 + const Tolerance& tolerance = Tolerance()) :
2.131 + _graph(graph), _capacity(&capacity), _flow(0), _source(),
2.132 + _node_num(), _first(), _last(), _next(0), _prev(0),
2.133 + _active(0), _bucket(0), _dormant(), _sets(), _highest(),
2.134 + _excess(0), _source_set(0), _min_cut(), _min_cut_map(0),
2.135 + _tolerance(tolerance) {}
2.136 +
2.137 + ~HaoOrlin() {
2.138 + if (_min_cut_map) {
2.139 + delete _min_cut_map;
2.140 + }
2.141 + if (_source_set) {
2.142 + delete _source_set;
2.143 + }
2.144 + if (_excess) {
2.145 + delete _excess;
2.146 + }
2.147 + if (_next) {
2.148 + delete _next;
2.149 + }
2.150 + if (_prev) {
2.151 + delete _prev;
2.152 + }
2.153 + if (_active) {
2.154 + delete _active;
2.155 + }
2.156 + if (_bucket) {
2.157 + delete _bucket;
2.158 + }
2.159 + if (_flow) {
2.160 + delete _flow;
2.161 + }
2.162 + }
2.163 +
2.164 + private:
2.165 +
2.166 + void activate(const Node& i) {
2.167 + _active->set(i, true);
2.168 +
2.169 + int bucket = (*_bucket)[i];
2.170 +
2.171 + if ((*_prev)[i] == INVALID || (*_active)[(*_prev)[i]]) return;
2.172 + //unlace
2.173 + _next->set((*_prev)[i], (*_next)[i]);
2.174 + if ((*_next)[i] != INVALID) {
2.175 + _prev->set((*_next)[i], (*_prev)[i]);
2.176 + } else {
2.177 + _last[bucket] = (*_prev)[i];
2.178 + }
2.179 + //lace
2.180 + _next->set(i, _first[bucket]);
2.181 + _prev->set(_first[bucket], i);
2.182 + _prev->set(i, INVALID);
2.183 + _first[bucket] = i;
2.184 + }
2.185 +
2.186 + void deactivate(const Node& i) {
2.187 + _active->set(i, false);
2.188 + int bucket = (*_bucket)[i];
2.189 +
2.190 + if ((*_next)[i] == INVALID || !(*_active)[(*_next)[i]]) return;
2.191 +
2.192 + //unlace
2.193 + _prev->set((*_next)[i], (*_prev)[i]);
2.194 + if ((*_prev)[i] != INVALID) {
2.195 + _next->set((*_prev)[i], (*_next)[i]);
2.196 + } else {
2.197 + _first[bucket] = (*_next)[i];
2.198 + }
2.199 + //lace
2.200 + _prev->set(i, _last[bucket]);
2.201 + _next->set(_last[bucket], i);
2.202 + _next->set(i, INVALID);
2.203 + _last[bucket] = i;
2.204 + }
2.205 +
2.206 + void addItem(const Node& i, int bucket) {
2.207 + (*_bucket)[i] = bucket;
2.208 + if (_last[bucket] != INVALID) {
2.209 + _prev->set(i, _last[bucket]);
2.210 + _next->set(_last[bucket], i);
2.211 + _next->set(i, INVALID);
2.212 + _last[bucket] = i;
2.213 + } else {
2.214 + _prev->set(i, INVALID);
2.215 + _first[bucket] = i;
2.216 + _next->set(i, INVALID);
2.217 + _last[bucket] = i;
2.218 + }
2.219 + }
2.220 +
2.221 + void findMinCutOut() {
2.222 +
2.223 + for (NodeIt n(_graph); n != INVALID; ++n) {
2.224 + _excess->set(n, 0);
2.225 + }
2.226 +
2.227 + for (ArcIt a(_graph); a != INVALID; ++a) {
2.228 + _flow->set(a, 0);
2.229 + }
2.230 +
2.231 + int bucket_num = 0;
2.232 + std::vector<Node> queue(_node_num);
2.233 + int qfirst = 0, qlast = 0, qsep = 0;
2.234 +
2.235 + {
2.236 + typename Digraph::template NodeMap<bool> reached(_graph, false);
2.237 +
2.238 + reached.set(_source, true);
2.239 + bool first_set = true;
2.240 +
2.241 + for (NodeIt t(_graph); t != INVALID; ++t) {
2.242 + if (reached[t]) continue;
2.243 + _sets.push_front(std::list<int>());
2.244 +
2.245 + queue[qlast++] = t;
2.246 + reached.set(t, true);
2.247 +
2.248 + while (qfirst != qlast) {
2.249 + if (qsep == qfirst) {
2.250 + ++bucket_num;
2.251 + _sets.front().push_front(bucket_num);
2.252 + _dormant[bucket_num] = !first_set;
2.253 + _first[bucket_num] = _last[bucket_num] = INVALID;
2.254 + qsep = qlast;
2.255 + }
2.256 +
2.257 + Node n = queue[qfirst++];
2.258 + addItem(n, bucket_num);
2.259 +
2.260 + for (InArcIt a(_graph, n); a != INVALID; ++a) {
2.261 + Node u = _graph.source(a);
2.262 + if (!reached[u] && _tolerance.positive((*_capacity)[a])) {
2.263 + reached.set(u, true);
2.264 + queue[qlast++] = u;
2.265 + }
2.266 + }
2.267 + }
2.268 + first_set = false;
2.269 + }
2.270 +
2.271 + ++bucket_num;
2.272 + _bucket->set(_source, 0);
2.273 + _dormant[0] = true;
2.274 + }
2.275 + _source_set->set(_source, true);
2.276 +
2.277 + Node target = _last[_sets.back().back()];
2.278 + {
2.279 + for (OutArcIt a(_graph, _source); a != INVALID; ++a) {
2.280 + if (_tolerance.positive((*_capacity)[a])) {
2.281 + Node u = _graph.target(a);
2.282 + _flow->set(a, (*_capacity)[a]);
2.283 + _excess->set(u, (*_excess)[u] + (*_capacity)[a]);
2.284 + if (!(*_active)[u] && u != _source) {
2.285 + activate(u);
2.286 + }
2.287 + }
2.288 + }
2.289 +
2.290 + if ((*_active)[target]) {
2.291 + deactivate(target);
2.292 + }
2.293 +
2.294 + _highest = _sets.back().begin();
2.295 + while (_highest != _sets.back().end() &&
2.296 + !(*_active)[_first[*_highest]]) {
2.297 + ++_highest;
2.298 + }
2.299 + }
2.300 +
2.301 + while (true) {
2.302 + while (_highest != _sets.back().end()) {
2.303 + Node n = _first[*_highest];
2.304 + Value excess = (*_excess)[n];
2.305 + int next_bucket = _node_num;
2.306 +
2.307 + int under_bucket;
2.308 + if (++std::list<int>::iterator(_highest) == _sets.back().end()) {
2.309 + under_bucket = -1;
2.310 + } else {
2.311 + under_bucket = *(++std::list<int>::iterator(_highest));
2.312 + }
2.313 +
2.314 + for (OutArcIt a(_graph, n); a != INVALID; ++a) {
2.315 + Node v = _graph.target(a);
2.316 + if (_dormant[(*_bucket)[v]]) continue;
2.317 + Value rem = (*_capacity)[a] - (*_flow)[a];
2.318 + if (!_tolerance.positive(rem)) continue;
2.319 + if ((*_bucket)[v] == under_bucket) {
2.320 + if (!(*_active)[v] && v != target) {
2.321 + activate(v);
2.322 + }
2.323 + if (!_tolerance.less(rem, excess)) {
2.324 + _flow->set(a, (*_flow)[a] + excess);
2.325 + _excess->set(v, (*_excess)[v] + excess);
2.326 + excess = 0;
2.327 + goto no_more_push;
2.328 + } else {
2.329 + excess -= rem;
2.330 + _excess->set(v, (*_excess)[v] + rem);
2.331 + _flow->set(a, (*_capacity)[a]);
2.332 + }
2.333 + } else if (next_bucket > (*_bucket)[v]) {
2.334 + next_bucket = (*_bucket)[v];
2.335 + }
2.336 + }
2.337 +
2.338 + for (InArcIt a(_graph, n); a != INVALID; ++a) {
2.339 + Node v = _graph.source(a);
2.340 + if (_dormant[(*_bucket)[v]]) continue;
2.341 + Value rem = (*_flow)[a];
2.342 + if (!_tolerance.positive(rem)) continue;
2.343 + if ((*_bucket)[v] == under_bucket) {
2.344 + if (!(*_active)[v] && v != target) {
2.345 + activate(v);
2.346 + }
2.347 + if (!_tolerance.less(rem, excess)) {
2.348 + _flow->set(a, (*_flow)[a] - excess);
2.349 + _excess->set(v, (*_excess)[v] + excess);
2.350 + excess = 0;
2.351 + goto no_more_push;
2.352 + } else {
2.353 + excess -= rem;
2.354 + _excess->set(v, (*_excess)[v] + rem);
2.355 + _flow->set(a, 0);
2.356 + }
2.357 + } else if (next_bucket > (*_bucket)[v]) {
2.358 + next_bucket = (*_bucket)[v];
2.359 + }
2.360 + }
2.361 +
2.362 + no_more_push:
2.363 +
2.364 + _excess->set(n, excess);
2.365 +
2.366 + if (excess != 0) {
2.367 + if ((*_next)[n] == INVALID) {
2.368 + typename std::list<std::list<int> >::iterator new_set =
2.369 + _sets.insert(--_sets.end(), std::list<int>());
2.370 + new_set->splice(new_set->end(), _sets.back(),
2.371 + _sets.back().begin(), ++_highest);
2.372 + for (std::list<int>::iterator it = new_set->begin();
2.373 + it != new_set->end(); ++it) {
2.374 + _dormant[*it] = true;
2.375 + }
2.376 + while (_highest != _sets.back().end() &&
2.377 + !(*_active)[_first[*_highest]]) {
2.378 + ++_highest;
2.379 + }
2.380 + } else if (next_bucket == _node_num) {
2.381 + _first[(*_bucket)[n]] = (*_next)[n];
2.382 + _prev->set((*_next)[n], INVALID);
2.383 +
2.384 + std::list<std::list<int> >::iterator new_set =
2.385 + _sets.insert(--_sets.end(), std::list<int>());
2.386 +
2.387 + new_set->push_front(bucket_num);
2.388 + _bucket->set(n, bucket_num);
2.389 + _first[bucket_num] = _last[bucket_num] = n;
2.390 + _next->set(n, INVALID);
2.391 + _prev->set(n, INVALID);
2.392 + _dormant[bucket_num] = true;
2.393 + ++bucket_num;
2.394 +
2.395 + while (_highest != _sets.back().end() &&
2.396 + !(*_active)[_first[*_highest]]) {
2.397 + ++_highest;
2.398 + }
2.399 + } else {
2.400 + _first[*_highest] = (*_next)[n];
2.401 + _prev->set((*_next)[n], INVALID);
2.402 +
2.403 + while (next_bucket != *_highest) {
2.404 + --_highest;
2.405 + }
2.406 +
2.407 + if (_highest == _sets.back().begin()) {
2.408 + _sets.back().push_front(bucket_num);
2.409 + _dormant[bucket_num] = false;
2.410 + _first[bucket_num] = _last[bucket_num] = INVALID;
2.411 + ++bucket_num;
2.412 + }
2.413 + --_highest;
2.414 +
2.415 + _bucket->set(n, *_highest);
2.416 + _next->set(n, _first[*_highest]);
2.417 + if (_first[*_highest] != INVALID) {
2.418 + _prev->set(_first[*_highest], n);
2.419 + } else {
2.420 + _last[*_highest] = n;
2.421 + }
2.422 + _first[*_highest] = n;
2.423 + }
2.424 + } else {
2.425 +
2.426 + deactivate(n);
2.427 + if (!(*_active)[_first[*_highest]]) {
2.428 + ++_highest;
2.429 + if (_highest != _sets.back().end() &&
2.430 + !(*_active)[_first[*_highest]]) {
2.431 + _highest = _sets.back().end();
2.432 + }
2.433 + }
2.434 + }
2.435 + }
2.436 +
2.437 + if ((*_excess)[target] < _min_cut) {
2.438 + _min_cut = (*_excess)[target];
2.439 + for (NodeIt i(_graph); i != INVALID; ++i) {
2.440 + _min_cut_map->set(i, true);
2.441 + }
2.442 + for (std::list<int>::iterator it = _sets.back().begin();
2.443 + it != _sets.back().end(); ++it) {
2.444 + Node n = _first[*it];
2.445 + while (n != INVALID) {
2.446 + _min_cut_map->set(n, false);
2.447 + n = (*_next)[n];
2.448 + }
2.449 + }
2.450 + }
2.451 +
2.452 + {
2.453 + Node new_target;
2.454 + if ((*_prev)[target] != INVALID || (*_next)[target] != INVALID) {
2.455 + if ((*_next)[target] == INVALID) {
2.456 + _last[(*_bucket)[target]] = (*_prev)[target];
2.457 + new_target = (*_prev)[target];
2.458 + } else {
2.459 + _prev->set((*_next)[target], (*_prev)[target]);
2.460 + new_target = (*_next)[target];
2.461 + }
2.462 + if ((*_prev)[target] == INVALID) {
2.463 + _first[(*_bucket)[target]] = (*_next)[target];
2.464 + } else {
2.465 + _next->set((*_prev)[target], (*_next)[target]);
2.466 + }
2.467 + } else {
2.468 + _sets.back().pop_back();
2.469 + if (_sets.back().empty()) {
2.470 + _sets.pop_back();
2.471 + if (_sets.empty())
2.472 + break;
2.473 + for (std::list<int>::iterator it = _sets.back().begin();
2.474 + it != _sets.back().end(); ++it) {
2.475 + _dormant[*it] = false;
2.476 + }
2.477 + }
2.478 + new_target = _last[_sets.back().back()];
2.479 + }
2.480 +
2.481 + _bucket->set(target, 0);
2.482 +
2.483 + _source_set->set(target, true);
2.484 + for (OutArcIt a(_graph, target); a != INVALID; ++a) {
2.485 + Value rem = (*_capacity)[a] - (*_flow)[a];
2.486 + if (!_tolerance.positive(rem)) continue;
2.487 + Node v = _graph.target(a);
2.488 + if (!(*_active)[v] && !(*_source_set)[v]) {
2.489 + activate(v);
2.490 + }
2.491 + _excess->set(v, (*_excess)[v] + rem);
2.492 + _flow->set(a, (*_capacity)[a]);
2.493 + }
2.494 +
2.495 + for (InArcIt a(_graph, target); a != INVALID; ++a) {
2.496 + Value rem = (*_flow)[a];
2.497 + if (!_tolerance.positive(rem)) continue;
2.498 + Node v = _graph.source(a);
2.499 + if (!(*_active)[v] && !(*_source_set)[v]) {
2.500 + activate(v);
2.501 + }
2.502 + _excess->set(v, (*_excess)[v] + rem);
2.503 + _flow->set(a, 0);
2.504 + }
2.505 +
2.506 + target = new_target;
2.507 + if ((*_active)[target]) {
2.508 + deactivate(target);
2.509 + }
2.510 +
2.511 + _highest = _sets.back().begin();
2.512 + while (_highest != _sets.back().end() &&
2.513 + !(*_active)[_first[*_highest]]) {
2.514 + ++_highest;
2.515 + }
2.516 + }
2.517 + }
2.518 + }
2.519 +
2.520 + void findMinCutIn() {
2.521 +
2.522 + for (NodeIt n(_graph); n != INVALID; ++n) {
2.523 + _excess->set(n, 0);
2.524 + }
2.525 +
2.526 + for (ArcIt a(_graph); a != INVALID; ++a) {
2.527 + _flow->set(a, 0);
2.528 + }
2.529 +
2.530 + int bucket_num = 0;
2.531 + std::vector<Node> queue(_node_num);
2.532 + int qfirst = 0, qlast = 0, qsep = 0;
2.533 +
2.534 + {
2.535 + typename Digraph::template NodeMap<bool> reached(_graph, false);
2.536 +
2.537 + reached.set(_source, true);
2.538 +
2.539 + bool first_set = true;
2.540 +
2.541 + for (NodeIt t(_graph); t != INVALID; ++t) {
2.542 + if (reached[t]) continue;
2.543 + _sets.push_front(std::list<int>());
2.544 +
2.545 + queue[qlast++] = t;
2.546 + reached.set(t, true);
2.547 +
2.548 + while (qfirst != qlast) {
2.549 + if (qsep == qfirst) {
2.550 + ++bucket_num;
2.551 + _sets.front().push_front(bucket_num);
2.552 + _dormant[bucket_num] = !first_set;
2.553 + _first[bucket_num] = _last[bucket_num] = INVALID;
2.554 + qsep = qlast;
2.555 + }
2.556 +
2.557 + Node n = queue[qfirst++];
2.558 + addItem(n, bucket_num);
2.559 +
2.560 + for (OutArcIt a(_graph, n); a != INVALID; ++a) {
2.561 + Node u = _graph.target(a);
2.562 + if (!reached[u] && _tolerance.positive((*_capacity)[a])) {
2.563 + reached.set(u, true);
2.564 + queue[qlast++] = u;
2.565 + }
2.566 + }
2.567 + }
2.568 + first_set = false;
2.569 + }
2.570 +
2.571 + ++bucket_num;
2.572 + _bucket->set(_source, 0);
2.573 + _dormant[0] = true;
2.574 + }
2.575 + _source_set->set(_source, true);
2.576 +
2.577 + Node target = _last[_sets.back().back()];
2.578 + {
2.579 + for (InArcIt a(_graph, _source); a != INVALID; ++a) {
2.580 + if (_tolerance.positive((*_capacity)[a])) {
2.581 + Node u = _graph.source(a);
2.582 + _flow->set(a, (*_capacity)[a]);
2.583 + _excess->set(u, (*_excess)[u] + (*_capacity)[a]);
2.584 + if (!(*_active)[u] && u != _source) {
2.585 + activate(u);
2.586 + }
2.587 + }
2.588 + }
2.589 + if ((*_active)[target]) {
2.590 + deactivate(target);
2.591 + }
2.592 +
2.593 + _highest = _sets.back().begin();
2.594 + while (_highest != _sets.back().end() &&
2.595 + !(*_active)[_first[*_highest]]) {
2.596 + ++_highest;
2.597 + }
2.598 + }
2.599 +
2.600 +
2.601 + while (true) {
2.602 + while (_highest != _sets.back().end()) {
2.603 + Node n = _first[*_highest];
2.604 + Value excess = (*_excess)[n];
2.605 + int next_bucket = _node_num;
2.606 +
2.607 + int under_bucket;
2.608 + if (++std::list<int>::iterator(_highest) == _sets.back().end()) {
2.609 + under_bucket = -1;
2.610 + } else {
2.611 + under_bucket = *(++std::list<int>::iterator(_highest));
2.612 + }
2.613 +
2.614 + for (InArcIt a(_graph, n); a != INVALID; ++a) {
2.615 + Node v = _graph.source(a);
2.616 + if (_dormant[(*_bucket)[v]]) continue;
2.617 + Value rem = (*_capacity)[a] - (*_flow)[a];
2.618 + if (!_tolerance.positive(rem)) continue;
2.619 + if ((*_bucket)[v] == under_bucket) {
2.620 + if (!(*_active)[v] && v != target) {
2.621 + activate(v);
2.622 + }
2.623 + if (!_tolerance.less(rem, excess)) {
2.624 + _flow->set(a, (*_flow)[a] + excess);
2.625 + _excess->set(v, (*_excess)[v] + excess);
2.626 + excess = 0;
2.627 + goto no_more_push;
2.628 + } else {
2.629 + excess -= rem;
2.630 + _excess->set(v, (*_excess)[v] + rem);
2.631 + _flow->set(a, (*_capacity)[a]);
2.632 + }
2.633 + } else if (next_bucket > (*_bucket)[v]) {
2.634 + next_bucket = (*_bucket)[v];
2.635 + }
2.636 + }
2.637 +
2.638 + for (OutArcIt a(_graph, n); a != INVALID; ++a) {
2.639 + Node v = _graph.target(a);
2.640 + if (_dormant[(*_bucket)[v]]) continue;
2.641 + Value rem = (*_flow)[a];
2.642 + if (!_tolerance.positive(rem)) continue;
2.643 + if ((*_bucket)[v] == under_bucket) {
2.644 + if (!(*_active)[v] && v != target) {
2.645 + activate(v);
2.646 + }
2.647 + if (!_tolerance.less(rem, excess)) {
2.648 + _flow->set(a, (*_flow)[a] - excess);
2.649 + _excess->set(v, (*_excess)[v] + excess);
2.650 + excess = 0;
2.651 + goto no_more_push;
2.652 + } else {
2.653 + excess -= rem;
2.654 + _excess->set(v, (*_excess)[v] + rem);
2.655 + _flow->set(a, 0);
2.656 + }
2.657 + } else if (next_bucket > (*_bucket)[v]) {
2.658 + next_bucket = (*_bucket)[v];
2.659 + }
2.660 + }
2.661 +
2.662 + no_more_push:
2.663 +
2.664 + _excess->set(n, excess);
2.665 +
2.666 + if (excess != 0) {
2.667 + if ((*_next)[n] == INVALID) {
2.668 + typename std::list<std::list<int> >::iterator new_set =
2.669 + _sets.insert(--_sets.end(), std::list<int>());
2.670 + new_set->splice(new_set->end(), _sets.back(),
2.671 + _sets.back().begin(), ++_highest);
2.672 + for (std::list<int>::iterator it = new_set->begin();
2.673 + it != new_set->end(); ++it) {
2.674 + _dormant[*it] = true;
2.675 + }
2.676 + while (_highest != _sets.back().end() &&
2.677 + !(*_active)[_first[*_highest]]) {
2.678 + ++_highest;
2.679 + }
2.680 + } else if (next_bucket == _node_num) {
2.681 + _first[(*_bucket)[n]] = (*_next)[n];
2.682 + _prev->set((*_next)[n], INVALID);
2.683 +
2.684 + std::list<std::list<int> >::iterator new_set =
2.685 + _sets.insert(--_sets.end(), std::list<int>());
2.686 +
2.687 + new_set->push_front(bucket_num);
2.688 + _bucket->set(n, bucket_num);
2.689 + _first[bucket_num] = _last[bucket_num] = n;
2.690 + _next->set(n, INVALID);
2.691 + _prev->set(n, INVALID);
2.692 + _dormant[bucket_num] = true;
2.693 + ++bucket_num;
2.694 +
2.695 + while (_highest != _sets.back().end() &&
2.696 + !(*_active)[_first[*_highest]]) {
2.697 + ++_highest;
2.698 + }
2.699 + } else {
2.700 + _first[*_highest] = (*_next)[n];
2.701 + _prev->set((*_next)[n], INVALID);
2.702 +
2.703 + while (next_bucket != *_highest) {
2.704 + --_highest;
2.705 + }
2.706 + if (_highest == _sets.back().begin()) {
2.707 + _sets.back().push_front(bucket_num);
2.708 + _dormant[bucket_num] = false;
2.709 + _first[bucket_num] = _last[bucket_num] = INVALID;
2.710 + ++bucket_num;
2.711 + }
2.712 + --_highest;
2.713 +
2.714 + _bucket->set(n, *_highest);
2.715 + _next->set(n, _first[*_highest]);
2.716 + if (_first[*_highest] != INVALID) {
2.717 + _prev->set(_first[*_highest], n);
2.718 + } else {
2.719 + _last[*_highest] = n;
2.720 + }
2.721 + _first[*_highest] = n;
2.722 + }
2.723 + } else {
2.724 +
2.725 + deactivate(n);
2.726 + if (!(*_active)[_first[*_highest]]) {
2.727 + ++_highest;
2.728 + if (_highest != _sets.back().end() &&
2.729 + !(*_active)[_first[*_highest]]) {
2.730 + _highest = _sets.back().end();
2.731 + }
2.732 + }
2.733 + }
2.734 + }
2.735 +
2.736 + if ((*_excess)[target] < _min_cut) {
2.737 + _min_cut = (*_excess)[target];
2.738 + for (NodeIt i(_graph); i != INVALID; ++i) {
2.739 + _min_cut_map->set(i, false);
2.740 + }
2.741 + for (std::list<int>::iterator it = _sets.back().begin();
2.742 + it != _sets.back().end(); ++it) {
2.743 + Node n = _first[*it];
2.744 + while (n != INVALID) {
2.745 + _min_cut_map->set(n, true);
2.746 + n = (*_next)[n];
2.747 + }
2.748 + }
2.749 + }
2.750 +
2.751 + {
2.752 + Node new_target;
2.753 + if ((*_prev)[target] != INVALID || (*_next)[target] != INVALID) {
2.754 + if ((*_next)[target] == INVALID) {
2.755 + _last[(*_bucket)[target]] = (*_prev)[target];
2.756 + new_target = (*_prev)[target];
2.757 + } else {
2.758 + _prev->set((*_next)[target], (*_prev)[target]);
2.759 + new_target = (*_next)[target];
2.760 + }
2.761 + if ((*_prev)[target] == INVALID) {
2.762 + _first[(*_bucket)[target]] = (*_next)[target];
2.763 + } else {
2.764 + _next->set((*_prev)[target], (*_next)[target]);
2.765 + }
2.766 + } else {
2.767 + _sets.back().pop_back();
2.768 + if (_sets.back().empty()) {
2.769 + _sets.pop_back();
2.770 + if (_sets.empty())
2.771 + break;
2.772 + for (std::list<int>::iterator it = _sets.back().begin();
2.773 + it != _sets.back().end(); ++it) {
2.774 + _dormant[*it] = false;
2.775 + }
2.776 + }
2.777 + new_target = _last[_sets.back().back()];
2.778 + }
2.779 +
2.780 + _bucket->set(target, 0);
2.781 +
2.782 + _source_set->set(target, true);
2.783 + for (InArcIt a(_graph, target); a != INVALID; ++a) {
2.784 + Value rem = (*_capacity)[a] - (*_flow)[a];
2.785 + if (!_tolerance.positive(rem)) continue;
2.786 + Node v = _graph.source(a);
2.787 + if (!(*_active)[v] && !(*_source_set)[v]) {
2.788 + activate(v);
2.789 + }
2.790 + _excess->set(v, (*_excess)[v] + rem);
2.791 + _flow->set(a, (*_capacity)[a]);
2.792 + }
2.793 +
2.794 + for (OutArcIt a(_graph, target); a != INVALID; ++a) {
2.795 + Value rem = (*_flow)[a];
2.796 + if (!_tolerance.positive(rem)) continue;
2.797 + Node v = _graph.target(a);
2.798 + if (!(*_active)[v] && !(*_source_set)[v]) {
2.799 + activate(v);
2.800 + }
2.801 + _excess->set(v, (*_excess)[v] + rem);
2.802 + _flow->set(a, 0);
2.803 + }
2.804 +
2.805 + target = new_target;
2.806 + if ((*_active)[target]) {
2.807 + deactivate(target);
2.808 + }
2.809 +
2.810 + _highest = _sets.back().begin();
2.811 + while (_highest != _sets.back().end() &&
2.812 + !(*_active)[_first[*_highest]]) {
2.813 + ++_highest;
2.814 + }
2.815 + }
2.816 + }
2.817 + }
2.818 +
2.819 + public:
2.820 +
2.821 + /// \name Execution control
2.822 + /// The simplest way to execute the algorithm is to use
2.823 + /// one of the member functions called \c run(...).
2.824 + /// \n
2.825 + /// If you need more control on the execution,
2.826 + /// first you must call \ref init(), then the \ref calculateIn() or
2.827 + /// \ref calculateOut() functions.
2.828 +
2.829 + /// @{
2.830 +
2.831 + /// \brief Initializes the internal data structures.
2.832 + ///
2.833 + /// Initializes the internal data structures. It creates
2.834 + /// the maps, residual graph adaptors and some bucket structures
2.835 + /// for the algorithm.
2.836 + void init() {
2.837 + init(NodeIt(_graph));
2.838 + }
2.839 +
2.840 + /// \brief Initializes the internal data structures.
2.841 + ///
2.842 + /// Initializes the internal data structures. It creates
2.843 + /// the maps, residual graph adaptor and some bucket structures
2.844 + /// for the algorithm. Node \c source is used as the push-relabel
2.845 + /// algorithm's source.
2.846 + void init(const Node& source) {
2.847 + _source = source;
2.848 +
2.849 + _node_num = countNodes(_graph);
2.850 +
2.851 + _first.resize(_node_num);
2.852 + _last.resize(_node_num);
2.853 +
2.854 + _dormant.resize(_node_num);
2.855 +
2.856 + if (!_flow) {
2.857 + _flow = new FlowMap(_graph);
2.858 + }
2.859 + if (!_next) {
2.860 + _next = new typename Digraph::template NodeMap<Node>(_graph);
2.861 + }
2.862 + if (!_prev) {
2.863 + _prev = new typename Digraph::template NodeMap<Node>(_graph);
2.864 + }
2.865 + if (!_active) {
2.866 + _active = new typename Digraph::template NodeMap<bool>(_graph);
2.867 + }
2.868 + if (!_bucket) {
2.869 + _bucket = new typename Digraph::template NodeMap<int>(_graph);
2.870 + }
2.871 + if (!_excess) {
2.872 + _excess = new ExcessMap(_graph);
2.873 + }
2.874 + if (!_source_set) {
2.875 + _source_set = new SourceSetMap(_graph);
2.876 + }
2.877 + if (!_min_cut_map) {
2.878 + _min_cut_map = new MinCutMap(_graph);
2.879 + }
2.880 +
2.881 + _min_cut = std::numeric_limits<Value>::max();
2.882 + }
2.883 +
2.884 +
2.885 + /// \brief Calculates a minimum cut with \f$ source \f$ on the
2.886 + /// source-side.
2.887 + ///
2.888 + /// Calculates a minimum cut with \f$ source \f$ on the
2.889 + /// source-side (i.e. a set \f$ X\subsetneq V \f$ with
2.890 + /// \f$ source \in X \f$ and minimal out-degree).
2.891 + void calculateOut() {
2.892 + findMinCutOut();
2.893 + }
2.894 +
2.895 + /// \brief Calculates a minimum cut with \f$ source \f$ on the
2.896 + /// target-side.
2.897 + ///
2.898 + /// Calculates a minimum cut with \f$ source \f$ on the
2.899 + /// target-side (i.e. a set \f$ X\subsetneq V \f$ with
2.900 + /// \f$ source \in X \f$ and minimal out-degree).
2.901 + void calculateIn() {
2.902 + findMinCutIn();
2.903 + }
2.904 +
2.905 +
2.906 + /// \brief Runs the algorithm.
2.907 + ///
2.908 + /// Runs the algorithm. It finds nodes \c source and \c target
2.909 + /// arbitrarily and then calls \ref init(), \ref calculateOut()
2.910 + /// and \ref calculateIn().
2.911 + void run() {
2.912 + init();
2.913 + calculateOut();
2.914 + calculateIn();
2.915 + }
2.916 +
2.917 + /// \brief Runs the algorithm.
2.918 + ///
2.919 + /// Runs the algorithm. It uses the given \c source node, finds a
2.920 + /// proper \c target and then calls the \ref init(), \ref
2.921 + /// calculateOut() and \ref calculateIn().
2.922 + void run(const Node& s) {
2.923 + init(s);
2.924 + calculateOut();
2.925 + calculateIn();
2.926 + }
2.927 +
2.928 + /// @}
2.929 +
2.930 + /// \name Query Functions
2.931 + /// The result of the %HaoOrlin algorithm
2.932 + /// can be obtained using these functions.
2.933 + /// \n
2.934 + /// Before using these functions, either \ref run(), \ref
2.935 + /// calculateOut() or \ref calculateIn() must be called.
2.936 +
2.937 + /// @{
2.938 +
2.939 + /// \brief Returns the value of the minimum value cut.
2.940 + ///
2.941 + /// Returns the value of the minimum value cut.
2.942 + Value minCutValue() const {
2.943 + return _min_cut;
2.944 + }
2.945 +
2.946 +
2.947 + /// \brief Returns a minimum cut.
2.948 + ///
2.949 + /// Sets \c nodeMap to the characteristic vector of a minimum
2.950 + /// value cut: it will give a nonempty set \f$ X\subsetneq V \f$
2.951 + /// with minimal out-degree (i.e. \c nodeMap will be true exactly
2.952 + /// for the nodes of \f$ X \f$). \pre nodeMap should be a
2.953 + /// bool-valued node-map.
2.954 + template <typename NodeMap>
2.955 + Value minCutMap(NodeMap& nodeMap) const {
2.956 + for (NodeIt it(_graph); it != INVALID; ++it) {
2.957 + nodeMap.set(it, (*_min_cut_map)[it]);
2.958 + }
2.959 + return _min_cut;
2.960 + }
2.961 +
2.962 + /// @}
2.963 +
2.964 + }; //class HaoOrlin
2.965 +
2.966 +
2.967 +} //namespace lemon
2.968 +
2.969 +#endif //LEMON_HAO_ORLIN_H
3.1 --- a/test/CMakeLists.txt Tue Dec 02 10:31:20 2008 +0000
3.2 +++ b/test/CMakeLists.txt Tue Dec 02 11:01:48 2008 +0000
3.3 @@ -13,6 +13,7 @@
3.4 graph_copy_test
3.5 graph_test
3.6 graph_utils_test
3.7 + hao_orlin_test
3.8 heap_test
3.9 kruskal_test
3.10 maps_test
4.1 --- a/test/Makefile.am Tue Dec 02 10:31:20 2008 +0000
4.2 +++ b/test/Makefile.am Tue Dec 02 11:01:48 2008 +0000
4.3 @@ -21,6 +21,7 @@
4.4 test/graph_utils_test \
4.5 test/heap_test \
4.6 test/kruskal_test \
4.7 + test/hao_orlin_test \
4.8 test/maps_test \
4.9 test/max_matching_test \
4.10 test/random_test \
4.11 @@ -48,6 +49,7 @@
4.12 test_graph_utils_test_SOURCES = test/graph_utils_test.cc
4.13 test_heap_test_SOURCES = test/heap_test.cc
4.14 test_kruskal_test_SOURCES = test/kruskal_test.cc
4.15 +test_hao_orlin_test_SOURCES = test/hao_orlin_test.cc
4.16 test_maps_test_SOURCES = test/maps_test.cc
4.17 test_max_matching_test_SOURCES = test/max_matching_test.cc
4.18 test_path_test_SOURCES = test/path_test.cc
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/test/hao_orlin_test.cc Tue Dec 02 11:01:48 2008 +0000
5.3 @@ -0,0 +1,63 @@
5.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
5.5 + *
5.6 + * This file is a part of LEMON, a generic C++ optimization library.
5.7 + *
5.8 + * Copyright (C) 2003-2008
5.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
5.11 + *
5.12 + * Permission to use, modify and distribute this software is granted
5.13 + * provided that this copyright notice appears in all copies. For
5.14 + * precise terms see the accompanying LICENSE file.
5.15 + *
5.16 + * This software is provided "AS IS" with no warranty of any kind,
5.17 + * express or implied, and with no claim as to its suitability for any
5.18 + * purpose.
5.19 + *
5.20 + */
5.21 +
5.22 +#include <sstream>
5.23 +
5.24 +#include <lemon/smart_graph.h>
5.25 +#include <lemon/hao_orlin.h>
5.26 +
5.27 +#include <lemon/lgf_reader.h>
5.28 +#include "test_tools.h"
5.29 +
5.30 +using namespace lemon;
5.31 +using namespace std;
5.32 +
5.33 +const std::string lgf =
5.34 + "@nodes\n"
5.35 + "label\n"
5.36 + "0\n"
5.37 + "1\n"
5.38 + "2\n"
5.39 + "3\n"
5.40 + "4\n"
5.41 + "5\n"
5.42 + "@edges\n"
5.43 + " label capacity\n"
5.44 + "0 1 0 2\n"
5.45 + "1 2 1 2\n"
5.46 + "2 0 2 2\n"
5.47 + "3 4 3 2\n"
5.48 + "4 5 4 2\n"
5.49 + "5 3 5 2\n"
5.50 + "2 3 6 3\n";
5.51 +
5.52 +int main() {
5.53 + SmartGraph graph;
5.54 + SmartGraph::EdgeMap<int> capacity(graph);
5.55 +
5.56 + istringstream lgfs(lgf);
5.57 + graphReader(graph, lgfs).
5.58 + edgeMap("capacity", capacity).run();
5.59 +
5.60 + HaoOrlin<SmartGraph, SmartGraph::EdgeMap<int> > ho(graph, capacity);
5.61 + ho.run();
5.62 +
5.63 + check(ho.minCutValue() == 3, "Wrong cut value");
5.64 +
5.65 + return 0;
5.66 +}