alpar@404: /* -*- mode: C++; indent-tabs-mode: nil; -*- alpar@404: * alpar@404: * This file is a part of LEMON, a generic C++ optimization library. alpar@404: * alpar@463: * Copyright (C) 2003-2009 alpar@404: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@404: * (Egervary Research Group on Combinatorial Optimization, EGRES). alpar@404: * alpar@404: * Permission to use, modify and distribute this software is granted alpar@404: * provided that this copyright notice appears in all copies. For alpar@404: * precise terms see the accompanying LICENSE file. alpar@404: * alpar@404: * This software is provided "AS IS" with no warranty of any kind, alpar@404: * express or implied, and with no claim as to its suitability for any alpar@404: * purpose. alpar@404: * alpar@404: */ alpar@404: alpar@404: #ifndef LEMON_PREFLOW_H alpar@404: #define LEMON_PREFLOW_H alpar@404: alpar@404: #include alpar@404: #include alpar@404: alpar@404: /// \file alpar@404: /// \ingroup max_flow alpar@404: /// \brief Implementation of the preflow algorithm. alpar@404: alpar@404: namespace lemon { alpar@404: alpar@404: /// \brief Default traits class of Preflow class. alpar@404: /// alpar@404: /// Default traits class of Preflow class. kpeter@525: /// \tparam GR Digraph type. kpeter@606: /// \tparam CAP Capacity map type. kpeter@606: template alpar@404: struct PreflowDefaultTraits { alpar@404: kpeter@408: /// \brief The type of the digraph the algorithm runs on. kpeter@525: typedef GR Digraph; alpar@404: alpar@404: /// \brief The type of the map that stores the arc capacities. alpar@404: /// alpar@404: /// The type of the map that stores the arc capacities. alpar@404: /// It must meet the \ref concepts::ReadMap "ReadMap" concept. kpeter@606: typedef CAP CapacityMap; alpar@404: kpeter@408: /// \brief The type of the flow values. kpeter@688: typedef typename CapacityMap::Value Value; alpar@404: kpeter@408: /// \brief The type of the map that stores the flow values. alpar@404: /// kpeter@408: /// The type of the map that stores the flow values. alpar@404: /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept. kpeter@688: typedef typename Digraph::template ArcMap FlowMap; alpar@404: alpar@404: /// \brief Instantiates a FlowMap. alpar@404: /// alpar@404: /// This function instantiates a \ref FlowMap. kpeter@657: /// \param digraph The digraph for which we would like to define alpar@404: /// the flow map. alpar@404: static FlowMap* createFlowMap(const Digraph& digraph) { alpar@404: return new FlowMap(digraph); alpar@404: } alpar@404: kpeter@408: /// \brief The elevator type used by Preflow algorithm. alpar@404: /// alpar@404: /// The elevator type used by Preflow algorithm. alpar@404: /// alpar@404: /// \sa Elevator alpar@404: /// \sa LinkedElevator alpar@404: typedef LinkedElevator Elevator; alpar@404: alpar@404: /// \brief Instantiates an Elevator. alpar@404: /// kpeter@408: /// This function instantiates an \ref Elevator. kpeter@657: /// \param digraph The digraph for which we would like to define alpar@404: /// the elevator. alpar@404: /// \param max_level The maximum level of the elevator. alpar@404: static Elevator* createElevator(const Digraph& digraph, int max_level) { alpar@404: return new Elevator(digraph, max_level); alpar@404: } alpar@404: alpar@404: /// \brief The tolerance used by the algorithm alpar@404: /// alpar@404: /// The tolerance used by the algorithm to handle inexact computation. kpeter@688: typedef lemon::Tolerance Tolerance; alpar@404: alpar@404: }; alpar@404: alpar@404: alpar@404: /// \ingroup max_flow alpar@404: /// kpeter@408: /// \brief %Preflow algorithm class. alpar@404: /// kpeter@408: /// This class provides an implementation of Goldberg-Tarjan's \e preflow kpeter@606: /// \e push-relabel algorithm producing a \ref max_flow kpeter@606: /// "flow of maximum value" in a digraph. kpeter@606: /// The preflow algorithms are the fastest known maximum alpar@404: /// flow algorithms. The current implementation use a mixture of the alpar@404: /// \e "highest label" and the \e "bound decrease" heuristics. alpar@404: /// The worst case time complexity of the algorithm is \f$O(n^2\sqrt{e})\f$. alpar@404: /// kpeter@408: /// The algorithm consists of two phases. After the first phase kpeter@408: /// the maximum flow value and the minimum cut is obtained. The kpeter@408: /// second phase constructs a feasible maximum flow on each arc. alpar@404: /// kpeter@525: /// \tparam GR The type of the digraph the algorithm runs on. kpeter@606: /// \tparam CAP The type of the capacity map. The default map kpeter@525: /// type is \ref concepts::Digraph::ArcMap "GR::ArcMap". alpar@404: #ifdef DOXYGEN kpeter@606: template alpar@404: #else kpeter@525: template , kpeter@606: typename TR = PreflowDefaultTraits > alpar@404: #endif alpar@404: class Preflow { alpar@404: public: alpar@404: kpeter@408: ///The \ref PreflowDefaultTraits "traits class" of the algorithm. kpeter@525: typedef TR Traits; kpeter@408: ///The type of the digraph the algorithm runs on. alpar@404: typedef typename Traits::Digraph Digraph; kpeter@408: ///The type of the capacity map. alpar@404: typedef typename Traits::CapacityMap CapacityMap; kpeter@408: ///The type of the flow values. kpeter@688: typedef typename Traits::Value Value; alpar@404: kpeter@408: ///The type of the flow map. alpar@404: typedef typename Traits::FlowMap FlowMap; kpeter@408: ///The type of the elevator. alpar@404: typedef typename Traits::Elevator Elevator; kpeter@408: ///The type of the tolerance. alpar@404: typedef typename Traits::Tolerance Tolerance; alpar@404: alpar@404: private: alpar@404: alpar@404: TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); alpar@404: alpar@404: const Digraph& _graph; alpar@404: const CapacityMap* _capacity; alpar@404: alpar@404: int _node_num; alpar@404: alpar@404: Node _source, _target; alpar@404: alpar@404: FlowMap* _flow; alpar@404: bool _local_flow; alpar@404: alpar@404: Elevator* _level; alpar@404: bool _local_level; alpar@404: kpeter@688: typedef typename Digraph::template NodeMap ExcessMap; alpar@404: ExcessMap* _excess; alpar@404: alpar@404: Tolerance _tolerance; alpar@404: alpar@404: bool _phase; alpar@404: alpar@404: alpar@404: void createStructures() { alpar@404: _node_num = countNodes(_graph); alpar@404: alpar@404: if (!_flow) { alpar@404: _flow = Traits::createFlowMap(_graph); alpar@404: _local_flow = true; alpar@404: } alpar@404: if (!_level) { alpar@404: _level = Traits::createElevator(_graph, _node_num); alpar@404: _local_level = true; alpar@404: } alpar@404: if (!_excess) { alpar@404: _excess = new ExcessMap(_graph); alpar@404: } alpar@404: } alpar@404: alpar@404: void destroyStructures() { alpar@404: if (_local_flow) { alpar@404: delete _flow; alpar@404: } alpar@404: if (_local_level) { alpar@404: delete _level; alpar@404: } alpar@404: if (_excess) { alpar@404: delete _excess; alpar@404: } alpar@404: } alpar@404: alpar@404: public: alpar@404: alpar@404: typedef Preflow Create; alpar@404: kpeter@408: ///\name Named Template Parameters alpar@404: alpar@404: ///@{ alpar@404: kpeter@606: template alpar@406: struct SetFlowMapTraits : public Traits { kpeter@606: typedef T FlowMap; alpar@404: static FlowMap *createFlowMap(const Digraph&) { alpar@405: LEMON_ASSERT(false, "FlowMap is not initialized"); alpar@405: return 0; // ignore warnings alpar@404: } alpar@404: }; alpar@404: alpar@404: /// \brief \ref named-templ-param "Named parameter" for setting alpar@404: /// FlowMap type alpar@404: /// alpar@404: /// \ref named-templ-param "Named parameter" for setting FlowMap kpeter@408: /// type. kpeter@606: template alpar@406: struct SetFlowMap kpeter@606: : public Preflow > { alpar@404: typedef Preflow > Create; alpar@404: }; alpar@404: kpeter@606: template alpar@406: struct SetElevatorTraits : public Traits { kpeter@606: typedef T Elevator; alpar@404: static Elevator *createElevator(const Digraph&, int) { alpar@405: LEMON_ASSERT(false, "Elevator is not initialized"); alpar@405: return 0; // ignore warnings alpar@404: } alpar@404: }; alpar@404: alpar@404: /// \brief \ref named-templ-param "Named parameter" for setting alpar@404: /// Elevator type alpar@404: /// alpar@404: /// \ref named-templ-param "Named parameter" for setting Elevator kpeter@408: /// type. If this named parameter is used, then an external kpeter@408: /// elevator object must be passed to the algorithm using the kpeter@408: /// \ref elevator(Elevator&) "elevator()" function before calling kpeter@408: /// \ref run() or \ref init(). kpeter@408: /// \sa SetStandardElevator kpeter@606: template alpar@406: struct SetElevator kpeter@606: : public Preflow > { alpar@404: typedef Preflow > Create; alpar@404: }; alpar@404: kpeter@606: template alpar@406: struct SetStandardElevatorTraits : public Traits { kpeter@606: typedef T Elevator; alpar@404: static Elevator *createElevator(const Digraph& digraph, int max_level) { alpar@404: return new Elevator(digraph, max_level); alpar@404: } alpar@404: }; alpar@404: alpar@404: /// \brief \ref named-templ-param "Named parameter" for setting kpeter@408: /// Elevator type with automatic allocation alpar@404: /// alpar@404: /// \ref named-templ-param "Named parameter" for setting Elevator kpeter@408: /// type with automatic allocation. kpeter@408: /// The Elevator should have standard constructor interface to be kpeter@408: /// able to automatically created by the algorithm (i.e. the kpeter@408: /// digraph and the maximum level should be passed to it). kpeter@408: /// However an external elevator object could also be passed to the kpeter@408: /// algorithm with the \ref elevator(Elevator&) "elevator()" function kpeter@408: /// before calling \ref run() or \ref init(). kpeter@408: /// \sa SetElevator kpeter@606: template alpar@406: struct SetStandardElevator alpar@404: : public Preflow > { alpar@404: typedef Preflow > Create; alpar@404: }; alpar@404: alpar@404: /// @} alpar@404: alpar@404: protected: alpar@404: alpar@404: Preflow() {} alpar@404: alpar@404: public: alpar@404: alpar@404: alpar@404: /// \brief The constructor of the class. alpar@404: /// alpar@404: /// The constructor of the class. alpar@404: /// \param digraph The digraph the algorithm runs on. alpar@404: /// \param capacity The capacity of the arcs. alpar@404: /// \param source The source node. alpar@404: /// \param target The target node. alpar@404: Preflow(const Digraph& digraph, const CapacityMap& capacity, kpeter@408: Node source, Node target) alpar@404: : _graph(digraph), _capacity(&capacity), alpar@404: _node_num(0), _source(source), _target(target), alpar@404: _flow(0), _local_flow(false), alpar@404: _level(0), _local_level(false), alpar@404: _excess(0), _tolerance(), _phase() {} alpar@404: kpeter@408: /// \brief Destructor. alpar@404: /// alpar@404: /// Destructor. alpar@404: ~Preflow() { alpar@404: destroyStructures(); alpar@404: } alpar@404: alpar@404: /// \brief Sets the capacity map. alpar@404: /// alpar@404: /// Sets the capacity map. kpeter@408: /// \return (*this) alpar@404: Preflow& capacityMap(const CapacityMap& map) { alpar@404: _capacity = ↦ alpar@404: return *this; alpar@404: } alpar@404: alpar@404: /// \brief Sets the flow map. alpar@404: /// alpar@404: /// Sets the flow map. kpeter@408: /// If you don't use this function before calling \ref run() or kpeter@408: /// \ref init(), an instance will be allocated automatically. kpeter@408: /// The destructor deallocates this automatically allocated map, kpeter@408: /// of course. kpeter@408: /// \return (*this) alpar@404: Preflow& flowMap(FlowMap& map) { alpar@404: if (_local_flow) { alpar@404: delete _flow; alpar@404: _local_flow = false; alpar@404: } alpar@404: _flow = ↦ alpar@404: return *this; alpar@404: } alpar@404: kpeter@408: /// \brief Sets the source node. alpar@404: /// kpeter@408: /// Sets the source node. kpeter@408: /// \return (*this) kpeter@408: Preflow& source(const Node& node) { kpeter@408: _source = node; kpeter@408: return *this; alpar@404: } alpar@404: kpeter@408: /// \brief Sets the target node. alpar@404: /// kpeter@408: /// Sets the target node. kpeter@408: /// \return (*this) kpeter@408: Preflow& target(const Node& node) { kpeter@408: _target = node; kpeter@408: return *this; kpeter@408: } kpeter@408: kpeter@408: /// \brief Sets the elevator used by algorithm. kpeter@408: /// kpeter@408: /// Sets the elevator used by algorithm. kpeter@408: /// If you don't use this function before calling \ref run() or kpeter@408: /// \ref init(), an instance will be allocated automatically. kpeter@408: /// The destructor deallocates this automatically allocated elevator, kpeter@408: /// of course. kpeter@408: /// \return (*this) alpar@404: Preflow& elevator(Elevator& elevator) { alpar@404: if (_local_level) { alpar@404: delete _level; alpar@404: _local_level = false; alpar@404: } alpar@404: _level = &elevator; alpar@404: return *this; alpar@404: } alpar@404: kpeter@408: /// \brief Returns a const reference to the elevator. alpar@404: /// kpeter@408: /// Returns a const reference to the elevator. kpeter@408: /// kpeter@408: /// \pre Either \ref run() or \ref init() must be called before kpeter@408: /// using this function. kpeter@437: const Elevator& elevator() const { alpar@404: return *_level; alpar@404: } alpar@404: alpar@404: /// \brief Sets the tolerance used by algorithm. alpar@404: /// alpar@404: /// Sets the tolerance used by algorithm. alpar@404: Preflow& tolerance(const Tolerance& tolerance) const { alpar@404: _tolerance = tolerance; alpar@404: return *this; alpar@404: } alpar@404: kpeter@408: /// \brief Returns a const reference to the tolerance. alpar@404: /// kpeter@408: /// Returns a const reference to the tolerance. alpar@404: const Tolerance& tolerance() const { alpar@404: return tolerance; alpar@404: } alpar@404: kpeter@408: /// \name Execution Control kpeter@408: /// The simplest way to execute the preflow algorithm is to use kpeter@408: /// \ref run() or \ref runMinCut().\n kpeter@408: /// If you need more control on the initial solution or the execution, kpeter@408: /// first you have to call one of the \ref init() functions, then kpeter@408: /// \ref startFirstPhase() and if you need it \ref startSecondPhase(). alpar@404: alpar@404: ///@{ alpar@404: alpar@404: /// \brief Initializes the internal data structures. alpar@404: /// kpeter@408: /// Initializes the internal data structures and sets the initial kpeter@408: /// flow to zero on each arc. alpar@404: void init() { alpar@404: createStructures(); alpar@404: alpar@404: _phase = true; alpar@404: for (NodeIt n(_graph); n != INVALID; ++n) { kpeter@628: (*_excess)[n] = 0; alpar@404: } alpar@404: alpar@404: for (ArcIt e(_graph); e != INVALID; ++e) { alpar@404: _flow->set(e, 0); alpar@404: } alpar@404: alpar@404: typename Digraph::template NodeMap reached(_graph, false); alpar@404: alpar@404: _level->initStart(); alpar@404: _level->initAddItem(_target); alpar@404: alpar@404: std::vector queue; kpeter@628: reached[_source] = true; alpar@404: alpar@404: queue.push_back(_target); kpeter@628: reached[_target] = true; alpar@404: while (!queue.empty()) { alpar@404: _level->initNewLevel(); alpar@404: std::vector nqueue; alpar@404: for (int i = 0; i < int(queue.size()); ++i) { alpar@404: Node n = queue[i]; alpar@404: for (InArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Node u = _graph.source(e); alpar@404: if (!reached[u] && _tolerance.positive((*_capacity)[e])) { kpeter@628: reached[u] = true; alpar@404: _level->initAddItem(u); alpar@404: nqueue.push_back(u); alpar@404: } alpar@404: } alpar@404: } alpar@404: queue.swap(nqueue); alpar@404: } alpar@404: _level->initFinish(); alpar@404: alpar@404: for (OutArcIt e(_graph, _source); e != INVALID; ++e) { alpar@404: if (_tolerance.positive((*_capacity)[e])) { alpar@404: Node u = _graph.target(e); alpar@404: if ((*_level)[u] == _level->maxLevel()) continue; alpar@404: _flow->set(e, (*_capacity)[e]); kpeter@628: (*_excess)[u] += (*_capacity)[e]; alpar@404: if (u != _target && !_level->active(u)) { alpar@404: _level->activate(u); alpar@404: } alpar@404: } alpar@404: } alpar@404: } alpar@404: kpeter@408: /// \brief Initializes the internal data structures using the kpeter@408: /// given flow map. alpar@404: /// alpar@404: /// Initializes the internal data structures and sets the initial alpar@404: /// flow to the given \c flowMap. The \c flowMap should contain a kpeter@408: /// flow or at least a preflow, i.e. at each node excluding the kpeter@408: /// source node the incoming flow should greater or equal to the alpar@404: /// outgoing flow. kpeter@408: /// \return \c false if the given \c flowMap is not a preflow. alpar@404: template kpeter@407: bool init(const FlowMap& flowMap) { alpar@404: createStructures(); alpar@404: alpar@404: for (ArcIt e(_graph); e != INVALID; ++e) { alpar@404: _flow->set(e, flowMap[e]); alpar@404: } alpar@404: alpar@404: for (NodeIt n(_graph); n != INVALID; ++n) { kpeter@688: Value excess = 0; alpar@404: for (InArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: excess += (*_flow)[e]; alpar@404: } alpar@404: for (OutArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: excess -= (*_flow)[e]; alpar@404: } alpar@404: if (excess < 0 && n != _source) return false; kpeter@628: (*_excess)[n] = excess; alpar@404: } alpar@404: alpar@404: typename Digraph::template NodeMap reached(_graph, false); alpar@404: alpar@404: _level->initStart(); alpar@404: _level->initAddItem(_target); alpar@404: alpar@404: std::vector queue; kpeter@628: reached[_source] = true; alpar@404: alpar@404: queue.push_back(_target); kpeter@628: reached[_target] = true; alpar@404: while (!queue.empty()) { alpar@404: _level->initNewLevel(); alpar@404: std::vector nqueue; alpar@404: for (int i = 0; i < int(queue.size()); ++i) { alpar@404: Node n = queue[i]; alpar@404: for (InArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Node u = _graph.source(e); alpar@404: if (!reached[u] && alpar@404: _tolerance.positive((*_capacity)[e] - (*_flow)[e])) { kpeter@628: reached[u] = true; alpar@404: _level->initAddItem(u); alpar@404: nqueue.push_back(u); alpar@404: } alpar@404: } alpar@404: for (OutArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Node v = _graph.target(e); alpar@404: if (!reached[v] && _tolerance.positive((*_flow)[e])) { kpeter@628: reached[v] = true; alpar@404: _level->initAddItem(v); alpar@404: nqueue.push_back(v); alpar@404: } alpar@404: } alpar@404: } alpar@404: queue.swap(nqueue); alpar@404: } alpar@404: _level->initFinish(); alpar@404: alpar@404: for (OutArcIt e(_graph, _source); e != INVALID; ++e) { kpeter@688: Value rem = (*_capacity)[e] - (*_flow)[e]; alpar@404: if (_tolerance.positive(rem)) { alpar@404: Node u = _graph.target(e); alpar@404: if ((*_level)[u] == _level->maxLevel()) continue; alpar@404: _flow->set(e, (*_capacity)[e]); kpeter@628: (*_excess)[u] += rem; alpar@404: if (u != _target && !_level->active(u)) { alpar@404: _level->activate(u); alpar@404: } alpar@404: } alpar@404: } alpar@404: for (InArcIt e(_graph, _source); e != INVALID; ++e) { kpeter@688: Value rem = (*_flow)[e]; alpar@404: if (_tolerance.positive(rem)) { alpar@404: Node v = _graph.source(e); alpar@404: if ((*_level)[v] == _level->maxLevel()) continue; alpar@404: _flow->set(e, 0); kpeter@628: (*_excess)[v] += rem; alpar@404: if (v != _target && !_level->active(v)) { alpar@404: _level->activate(v); alpar@404: } alpar@404: } alpar@404: } alpar@404: return true; alpar@404: } alpar@404: alpar@404: /// \brief Starts the first phase of the preflow algorithm. alpar@404: /// alpar@404: /// The preflow algorithm consists of two phases, this method runs alpar@404: /// the first phase. After the first phase the maximum flow value alpar@404: /// and a minimum value cut can already be computed, although a alpar@404: /// maximum flow is not yet obtained. So after calling this method alpar@404: /// \ref flowValue() returns the value of a maximum flow and \ref alpar@404: /// minCut() returns a minimum cut. kpeter@408: /// \pre One of the \ref init() functions must be called before kpeter@408: /// using this function. alpar@404: void startFirstPhase() { alpar@404: _phase = true; alpar@404: alpar@404: Node n = _level->highestActive(); alpar@404: int level = _level->highestActiveLevel(); alpar@404: while (n != INVALID) { alpar@404: int num = _node_num; alpar@404: alpar@404: while (num > 0 && n != INVALID) { kpeter@688: Value excess = (*_excess)[n]; alpar@404: int new_level = _level->maxLevel(); alpar@404: alpar@404: for (OutArcIt e(_graph, n); e != INVALID; ++e) { kpeter@688: Value rem = (*_capacity)[e] - (*_flow)[e]; alpar@404: if (!_tolerance.positive(rem)) continue; alpar@404: Node v = _graph.target(e); alpar@404: if ((*_level)[v] < level) { alpar@404: if (!_level->active(v) && v != _target) { alpar@404: _level->activate(v); alpar@404: } alpar@404: if (!_tolerance.less(rem, excess)) { alpar@404: _flow->set(e, (*_flow)[e] + excess); kpeter@628: (*_excess)[v] += excess; alpar@404: excess = 0; alpar@404: goto no_more_push_1; alpar@404: } else { alpar@404: excess -= rem; kpeter@628: (*_excess)[v] += rem; alpar@404: _flow->set(e, (*_capacity)[e]); alpar@404: } alpar@404: } else if (new_level > (*_level)[v]) { alpar@404: new_level = (*_level)[v]; alpar@404: } alpar@404: } alpar@404: alpar@404: for (InArcIt e(_graph, n); e != INVALID; ++e) { kpeter@688: Value rem = (*_flow)[e]; alpar@404: if (!_tolerance.positive(rem)) continue; alpar@404: Node v = _graph.source(e); alpar@404: if ((*_level)[v] < level) { alpar@404: if (!_level->active(v) && v != _target) { alpar@404: _level->activate(v); alpar@404: } alpar@404: if (!_tolerance.less(rem, excess)) { alpar@404: _flow->set(e, (*_flow)[e] - excess); kpeter@628: (*_excess)[v] += excess; alpar@404: excess = 0; alpar@404: goto no_more_push_1; alpar@404: } else { alpar@404: excess -= rem; kpeter@628: (*_excess)[v] += rem; alpar@404: _flow->set(e, 0); alpar@404: } alpar@404: } else if (new_level > (*_level)[v]) { alpar@404: new_level = (*_level)[v]; alpar@404: } alpar@404: } alpar@404: alpar@404: no_more_push_1: alpar@404: kpeter@628: (*_excess)[n] = excess; alpar@404: alpar@404: if (excess != 0) { alpar@404: if (new_level + 1 < _level->maxLevel()) { alpar@404: _level->liftHighestActive(new_level + 1); alpar@404: } else { alpar@404: _level->liftHighestActiveToTop(); alpar@404: } alpar@404: if (_level->emptyLevel(level)) { alpar@404: _level->liftToTop(level); alpar@404: } alpar@404: } else { alpar@404: _level->deactivate(n); alpar@404: } alpar@404: alpar@404: n = _level->highestActive(); alpar@404: level = _level->highestActiveLevel(); alpar@404: --num; alpar@404: } alpar@404: alpar@404: num = _node_num * 20; alpar@404: while (num > 0 && n != INVALID) { kpeter@688: Value excess = (*_excess)[n]; alpar@404: int new_level = _level->maxLevel(); alpar@404: alpar@404: for (OutArcIt e(_graph, n); e != INVALID; ++e) { kpeter@688: Value rem = (*_capacity)[e] - (*_flow)[e]; alpar@404: if (!_tolerance.positive(rem)) continue; alpar@404: Node v = _graph.target(e); alpar@404: if ((*_level)[v] < level) { alpar@404: if (!_level->active(v) && v != _target) { alpar@404: _level->activate(v); alpar@404: } alpar@404: if (!_tolerance.less(rem, excess)) { alpar@404: _flow->set(e, (*_flow)[e] + excess); kpeter@628: (*_excess)[v] += excess; alpar@404: excess = 0; alpar@404: goto no_more_push_2; alpar@404: } else { alpar@404: excess -= rem; kpeter@628: (*_excess)[v] += rem; alpar@404: _flow->set(e, (*_capacity)[e]); alpar@404: } alpar@404: } else if (new_level > (*_level)[v]) { alpar@404: new_level = (*_level)[v]; alpar@404: } alpar@404: } alpar@404: alpar@404: for (InArcIt e(_graph, n); e != INVALID; ++e) { kpeter@688: Value rem = (*_flow)[e]; alpar@404: if (!_tolerance.positive(rem)) continue; alpar@404: Node v = _graph.source(e); alpar@404: if ((*_level)[v] < level) { alpar@404: if (!_level->active(v) && v != _target) { alpar@404: _level->activate(v); alpar@404: } alpar@404: if (!_tolerance.less(rem, excess)) { alpar@404: _flow->set(e, (*_flow)[e] - excess); kpeter@628: (*_excess)[v] += excess; alpar@404: excess = 0; alpar@404: goto no_more_push_2; alpar@404: } else { alpar@404: excess -= rem; kpeter@628: (*_excess)[v] += rem; alpar@404: _flow->set(e, 0); alpar@404: } alpar@404: } else if (new_level > (*_level)[v]) { alpar@404: new_level = (*_level)[v]; alpar@404: } alpar@404: } alpar@404: alpar@404: no_more_push_2: alpar@404: kpeter@628: (*_excess)[n] = excess; alpar@404: alpar@404: if (excess != 0) { alpar@404: if (new_level + 1 < _level->maxLevel()) { alpar@404: _level->liftActiveOn(level, new_level + 1); alpar@404: } else { alpar@404: _level->liftActiveToTop(level); alpar@404: } alpar@404: if (_level->emptyLevel(level)) { alpar@404: _level->liftToTop(level); alpar@404: } alpar@404: } else { alpar@404: _level->deactivate(n); alpar@404: } alpar@404: alpar@404: while (level >= 0 && _level->activeFree(level)) { alpar@404: --level; alpar@404: } alpar@404: if (level == -1) { alpar@404: n = _level->highestActive(); alpar@404: level = _level->highestActiveLevel(); alpar@404: } else { alpar@404: n = _level->activeOn(level); alpar@404: } alpar@404: --num; alpar@404: } alpar@404: } alpar@404: } alpar@404: alpar@404: /// \brief Starts the second phase of the preflow algorithm. alpar@404: /// alpar@404: /// The preflow algorithm consists of two phases, this method runs kpeter@408: /// the second phase. After calling one of the \ref init() functions kpeter@408: /// and \ref startFirstPhase() and then \ref startSecondPhase(), kpeter@408: /// \ref flowMap() returns a maximum flow, \ref flowValue() returns the alpar@404: /// value of a maximum flow, \ref minCut() returns a minimum cut kpeter@408: /// \pre One of the \ref init() functions and \ref startFirstPhase() kpeter@408: /// must be called before using this function. alpar@404: void startSecondPhase() { alpar@404: _phase = false; alpar@404: alpar@404: typename Digraph::template NodeMap reached(_graph); alpar@404: for (NodeIt n(_graph); n != INVALID; ++n) { kpeter@628: reached[n] = (*_level)[n] < _level->maxLevel(); alpar@404: } alpar@404: alpar@404: _level->initStart(); alpar@404: _level->initAddItem(_source); alpar@404: alpar@404: std::vector queue; alpar@404: queue.push_back(_source); kpeter@628: reached[_source] = true; alpar@404: alpar@404: while (!queue.empty()) { alpar@404: _level->initNewLevel(); alpar@404: std::vector nqueue; alpar@404: for (int i = 0; i < int(queue.size()); ++i) { alpar@404: Node n = queue[i]; alpar@404: for (OutArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Node v = _graph.target(e); alpar@404: if (!reached[v] && _tolerance.positive((*_flow)[e])) { kpeter@628: reached[v] = true; alpar@404: _level->initAddItem(v); alpar@404: nqueue.push_back(v); alpar@404: } alpar@404: } alpar@404: for (InArcIt e(_graph, n); e != INVALID; ++e) { alpar@404: Node u = _graph.source(e); alpar@404: if (!reached[u] && alpar@404: _tolerance.positive((*_capacity)[e] - (*_flow)[e])) { kpeter@628: reached[u] = true; alpar@404: _level->initAddItem(u); alpar@404: nqueue.push_back(u); alpar@404: } alpar@404: } alpar@404: } alpar@404: queue.swap(nqueue); alpar@404: } alpar@404: _level->initFinish(); alpar@404: alpar@404: for (NodeIt n(_graph); n != INVALID; ++n) { alpar@404: if (!reached[n]) { alpar@404: _level->dirtyTopButOne(n); alpar@404: } else if ((*_excess)[n] > 0 && _target != n) { alpar@404: _level->activate(n); alpar@404: } alpar@404: } alpar@404: alpar@404: Node n; alpar@404: while ((n = _level->highestActive()) != INVALID) { kpeter@688: Value excess = (*_excess)[n]; alpar@404: int level = _level->highestActiveLevel(); alpar@404: int new_level = _level->maxLevel(); alpar@404: alpar@404: for (OutArcIt e(_graph, n); e != INVALID; ++e) { kpeter@688: Value rem = (*_capacity)[e] - (*_flow)[e]; alpar@404: if (!_tolerance.positive(rem)) continue; alpar@404: Node v = _graph.target(e); alpar@404: if ((*_level)[v] < level) { alpar@404: if (!_level->active(v) && v != _source) { alpar@404: _level->activate(v); alpar@404: } alpar@404: if (!_tolerance.less(rem, excess)) { alpar@404: _flow->set(e, (*_flow)[e] + excess); kpeter@628: (*_excess)[v] += excess; alpar@404: excess = 0; alpar@404: goto no_more_push; alpar@404: } else { alpar@404: excess -= rem; kpeter@628: (*_excess)[v] += rem; alpar@404: _flow->set(e, (*_capacity)[e]); alpar@404: } alpar@404: } else if (new_level > (*_level)[v]) { alpar@404: new_level = (*_level)[v]; alpar@404: } alpar@404: } alpar@404: alpar@404: for (InArcIt e(_graph, n); e != INVALID; ++e) { kpeter@688: Value rem = (*_flow)[e]; alpar@404: if (!_tolerance.positive(rem)) continue; alpar@404: Node v = _graph.source(e); alpar@404: if ((*_level)[v] < level) { alpar@404: if (!_level->active(v) && v != _source) { alpar@404: _level->activate(v); alpar@404: } alpar@404: if (!_tolerance.less(rem, excess)) { alpar@404: _flow->set(e, (*_flow)[e] - excess); kpeter@628: (*_excess)[v] += excess; alpar@404: excess = 0; alpar@404: goto no_more_push; alpar@404: } else { alpar@404: excess -= rem; kpeter@628: (*_excess)[v] += rem; alpar@404: _flow->set(e, 0); alpar@404: } alpar@404: } else if (new_level > (*_level)[v]) { alpar@404: new_level = (*_level)[v]; alpar@404: } alpar@404: } alpar@404: alpar@404: no_more_push: alpar@404: kpeter@628: (*_excess)[n] = excess; alpar@404: alpar@404: if (excess != 0) { alpar@404: if (new_level + 1 < _level->maxLevel()) { alpar@404: _level->liftHighestActive(new_level + 1); alpar@404: } else { alpar@404: // Calculation error alpar@404: _level->liftHighestActiveToTop(); alpar@404: } alpar@404: if (_level->emptyLevel(level)) { alpar@404: // Calculation error alpar@404: _level->liftToTop(level); alpar@404: } alpar@404: } else { alpar@404: _level->deactivate(n); alpar@404: } alpar@404: alpar@404: } alpar@404: } alpar@404: alpar@404: /// \brief Runs the preflow algorithm. alpar@404: /// alpar@404: /// Runs the preflow algorithm. alpar@404: /// \note pf.run() is just a shortcut of the following code. alpar@404: /// \code alpar@404: /// pf.init(); alpar@404: /// pf.startFirstPhase(); alpar@404: /// pf.startSecondPhase(); alpar@404: /// \endcode alpar@404: void run() { alpar@404: init(); alpar@404: startFirstPhase(); alpar@404: startSecondPhase(); alpar@404: } alpar@404: alpar@404: /// \brief Runs the preflow algorithm to compute the minimum cut. alpar@404: /// alpar@404: /// Runs the preflow algorithm to compute the minimum cut. alpar@404: /// \note pf.runMinCut() is just a shortcut of the following code. alpar@404: /// \code alpar@404: /// pf.init(); alpar@404: /// pf.startFirstPhase(); alpar@404: /// \endcode alpar@404: void runMinCut() { alpar@404: init(); alpar@404: startFirstPhase(); alpar@404: } alpar@404: alpar@404: /// @} alpar@404: alpar@404: /// \name Query Functions kpeter@408: /// The results of the preflow algorithm can be obtained using these alpar@404: /// functions.\n kpeter@408: /// Either one of the \ref run() "run*()" functions or one of the kpeter@408: /// \ref startFirstPhase() "start*()" functions should be called kpeter@408: /// before using them. alpar@404: alpar@404: ///@{ alpar@404: alpar@404: /// \brief Returns the value of the maximum flow. alpar@404: /// alpar@404: /// Returns the value of the maximum flow by returning the excess kpeter@408: /// of the target node. This value equals to the value of kpeter@408: /// the maximum flow already after the first phase of the algorithm. kpeter@408: /// kpeter@408: /// \pre Either \ref run() or \ref init() must be called before kpeter@408: /// using this function. kpeter@688: Value flowValue() const { alpar@404: return (*_excess)[_target]; alpar@404: } alpar@404: kpeter@688: /// \brief Returns the flow value on the given arc. alpar@404: /// kpeter@688: /// Returns the flow value on the given arc. This method can kpeter@408: /// be called after the second phase of the algorithm. kpeter@408: /// kpeter@408: /// \pre Either \ref run() or \ref init() must be called before kpeter@408: /// using this function. kpeter@688: Value flow(const Arc& arc) const { kpeter@408: return (*_flow)[arc]; kpeter@408: } kpeter@408: kpeter@408: /// \brief Returns a const reference to the flow map. kpeter@408: /// kpeter@408: /// Returns a const reference to the arc map storing the found flow. kpeter@408: /// This method can be called after the second phase of the algorithm. kpeter@408: /// kpeter@408: /// \pre Either \ref run() or \ref init() must be called before kpeter@408: /// using this function. kpeter@437: const FlowMap& flowMap() const { kpeter@408: return *_flow; kpeter@408: } kpeter@408: kpeter@408: /// \brief Returns \c true when the node is on the source side of the kpeter@408: /// minimum cut. kpeter@408: /// kpeter@408: /// Returns true when the node is on the source side of the found kpeter@408: /// minimum cut. This method can be called both after running \ref alpar@404: /// startFirstPhase() and \ref startSecondPhase(). kpeter@408: /// kpeter@408: /// \pre Either \ref run() or \ref init() must be called before kpeter@408: /// using this function. alpar@404: bool minCut(const Node& node) const { alpar@404: return ((*_level)[node] == _level->maxLevel()) == _phase; alpar@404: } alpar@404: kpeter@408: /// \brief Gives back a minimum value cut. alpar@404: /// kpeter@408: /// Sets \c cutMap to the characteristic vector of a minimum value kpeter@408: /// cut. \c cutMap should be a \ref concepts::WriteMap "writable" kpeter@408: /// node map with \c bool (or convertible) value type. kpeter@408: /// kpeter@408: /// This method can be called both after running \ref startFirstPhase() kpeter@408: /// and \ref startSecondPhase(). The result after the second phase kpeter@408: /// could be slightly different if inexact computation is used. kpeter@408: /// kpeter@408: /// \note This function calls \ref minCut() for each node, so it runs in kpeter@606: /// O(n) time. kpeter@408: /// kpeter@408: /// \pre Either \ref run() or \ref init() must be called before kpeter@408: /// using this function. alpar@404: template alpar@404: void minCutMap(CutMap& cutMap) const { alpar@404: for (NodeIt n(_graph); n != INVALID; ++n) { alpar@404: cutMap.set(n, minCut(n)); alpar@404: } alpar@404: } alpar@404: alpar@404: /// @} alpar@404: }; alpar@404: } alpar@404: alpar@404: #endif