alpar@357: /* -*- C++ -*- alpar@357: * alpar@357: * This file is a part of LEMON, a generic C++ optimization library alpar@357: * alpar@357: * Copyright (C) 2003-2008 alpar@357: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@357: * (Egervary Research Group on Combinatorial Optimization, EGRES). alpar@357: * alpar@357: * Permission to use, modify and distribute this software is granted alpar@357: * provided that this copyright notice appears in all copies. For alpar@357: * precise terms see the accompanying LICENSE file. alpar@357: * alpar@357: * This software is provided "AS IS" with no warranty of any kind, alpar@357: * express or implied, and with no claim as to its suitability for any alpar@357: * purpose. alpar@357: * alpar@357: */ alpar@357: alpar@357: #ifndef LEMON_SUURBALLE_H alpar@357: #define LEMON_SUURBALLE_H alpar@357: alpar@357: ///\ingroup shortest_path alpar@357: ///\file alpar@357: ///\brief An algorithm for finding arc-disjoint paths between two alpar@357: /// nodes having minimum total length. alpar@357: alpar@357: #include alpar@357: #include alpar@357: #include alpar@357: alpar@357: namespace lemon { alpar@357: alpar@357: /// \addtogroup shortest_path alpar@357: /// @{ alpar@357: kpeter@358: /// \brief Algorithm for finding arc-disjoint paths between two nodes kpeter@358: /// having minimum total length. alpar@357: /// alpar@357: /// \ref lemon::Suurballe "Suurballe" implements an algorithm for alpar@357: /// finding arc-disjoint paths having minimum total length (cost) kpeter@358: /// from a given source node to a given target node in a digraph. alpar@357: /// alpar@357: /// In fact, this implementation is the specialization of the alpar@357: /// \ref CapacityScaling "successive shortest path" algorithm. alpar@357: /// kpeter@358: /// \tparam Digraph The digraph type the algorithm runs on. kpeter@358: /// The default value is \c ListDigraph. alpar@357: /// \tparam LengthMap The type of the length (cost) map. kpeter@358: /// The default value is Digraph::ArcMap. alpar@357: /// alpar@357: /// \warning Length values should be \e non-negative \e integers. alpar@357: /// alpar@357: /// \note For finding node-disjoint paths this algorithm can be used alpar@357: /// with \ref SplitDigraphAdaptor. kpeter@358: #ifdef DOXYGEN kpeter@358: template kpeter@358: #else kpeter@358: template < typename Digraph = ListDigraph, alpar@357: typename LengthMap = typename Digraph::template ArcMap > kpeter@358: #endif alpar@357: class Suurballe alpar@357: { alpar@357: TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); alpar@357: alpar@357: typedef typename LengthMap::Value Length; alpar@357: typedef ConstMap ConstArcMap; alpar@357: typedef typename Digraph::template NodeMap PredMap; alpar@357: alpar@357: public: alpar@357: alpar@357: /// The type of the flow map. alpar@357: typedef typename Digraph::template ArcMap FlowMap; alpar@357: /// The type of the potential map. alpar@357: typedef typename Digraph::template NodeMap PotentialMap; alpar@357: /// The type of the path structures. alpar@357: typedef SimplePath Path; alpar@357: alpar@357: private: alpar@357: kpeter@358: /// \brief Special implementation of the Dijkstra algorithm alpar@357: /// for finding shortest paths in the residual network. alpar@357: /// alpar@357: /// \ref ResidualDijkstra is a special implementation of the alpar@357: /// \ref Dijkstra algorithm for finding shortest paths in the alpar@357: /// residual network of the digraph with respect to the reduced arc alpar@357: /// lengths and modifying the node potentials according to the alpar@357: /// distance of the nodes. alpar@357: class ResidualDijkstra alpar@357: { alpar@357: typedef typename Digraph::template NodeMap HeapCrossRef; alpar@357: typedef BinHeap Heap; alpar@357: alpar@357: private: alpar@357: kpeter@358: // The digraph the algorithm runs on alpar@357: const Digraph &_graph; alpar@357: alpar@357: // The main maps alpar@357: const FlowMap &_flow; alpar@357: const LengthMap &_length; alpar@357: PotentialMap &_potential; alpar@357: alpar@357: // The distance map alpar@357: PotentialMap _dist; alpar@357: // The pred arc map alpar@357: PredMap &_pred; alpar@357: // The processed (i.e. permanently labeled) nodes alpar@357: std::vector _proc_nodes; alpar@357: alpar@357: Node _s; alpar@357: Node _t; alpar@357: alpar@357: public: alpar@357: alpar@357: /// Constructor. alpar@357: ResidualDijkstra( const Digraph &digraph, alpar@357: const FlowMap &flow, alpar@357: const LengthMap &length, alpar@357: PotentialMap &potential, alpar@357: PredMap &pred, alpar@357: Node s, Node t ) : alpar@357: _graph(digraph), _flow(flow), _length(length), _potential(potential), alpar@357: _dist(digraph), _pred(pred), _s(s), _t(t) {} alpar@357: kpeter@358: /// \brief Run the algorithm. It returns \c true if a path is found alpar@357: /// from the source node to the target node. alpar@357: bool run() { alpar@357: HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP); alpar@357: Heap heap(heap_cross_ref); alpar@357: heap.push(_s, 0); alpar@357: _pred[_s] = INVALID; alpar@357: _proc_nodes.clear(); alpar@357: kpeter@358: // Process nodes alpar@357: while (!heap.empty() && heap.top() != _t) { alpar@357: Node u = heap.top(), v; alpar@357: Length d = heap.prio() + _potential[u], nd; alpar@357: _dist[u] = heap.prio(); alpar@357: heap.pop(); alpar@357: _proc_nodes.push_back(u); alpar@357: kpeter@358: // Traverse outgoing arcs alpar@357: for (OutArcIt e(_graph, u); e != INVALID; ++e) { alpar@357: if (_flow[e] == 0) { alpar@357: v = _graph.target(e); alpar@357: switch(heap.state(v)) { alpar@357: case Heap::PRE_HEAP: alpar@357: heap.push(v, d + _length[e] - _potential[v]); alpar@357: _pred[v] = e; alpar@357: break; alpar@357: case Heap::IN_HEAP: alpar@357: nd = d + _length[e] - _potential[v]; alpar@357: if (nd < heap[v]) { alpar@357: heap.decrease(v, nd); alpar@357: _pred[v] = e; alpar@357: } alpar@357: break; alpar@357: case Heap::POST_HEAP: alpar@357: break; alpar@357: } alpar@357: } alpar@357: } alpar@357: kpeter@358: // Traverse incoming arcs alpar@357: for (InArcIt e(_graph, u); e != INVALID; ++e) { alpar@357: if (_flow[e] == 1) { alpar@357: v = _graph.source(e); alpar@357: switch(heap.state(v)) { alpar@357: case Heap::PRE_HEAP: alpar@357: heap.push(v, d - _length[e] - _potential[v]); alpar@357: _pred[v] = e; alpar@357: break; alpar@357: case Heap::IN_HEAP: alpar@357: nd = d - _length[e] - _potential[v]; alpar@357: if (nd < heap[v]) { alpar@357: heap.decrease(v, nd); alpar@357: _pred[v] = e; alpar@357: } alpar@357: break; alpar@357: case Heap::POST_HEAP: alpar@357: break; alpar@357: } alpar@357: } alpar@357: } alpar@357: } alpar@357: if (heap.empty()) return false; alpar@357: kpeter@358: // Update potentials of processed nodes alpar@357: Length t_dist = heap.prio(); alpar@357: for (int i = 0; i < int(_proc_nodes.size()); ++i) alpar@357: _potential[_proc_nodes[i]] += _dist[_proc_nodes[i]] - t_dist; alpar@357: return true; alpar@357: } alpar@357: alpar@357: }; //class ResidualDijkstra alpar@357: alpar@357: private: alpar@357: kpeter@358: // The digraph the algorithm runs on alpar@357: const Digraph &_graph; alpar@357: // The length map alpar@357: const LengthMap &_length; alpar@357: alpar@357: // Arc map of the current flow alpar@357: FlowMap *_flow; alpar@357: bool _local_flow; alpar@357: // Node map of the current potentials alpar@357: PotentialMap *_potential; alpar@357: bool _local_potential; alpar@357: alpar@357: // The source node alpar@357: Node _source; alpar@357: // The target node alpar@357: Node _target; alpar@357: alpar@357: // Container to store the found paths alpar@357: std::vector< SimplePath > paths; alpar@357: int _path_num; alpar@357: alpar@357: // The pred arc map alpar@357: PredMap _pred; alpar@357: // Implementation of the Dijkstra algorithm for finding augmenting alpar@357: // shortest paths in the residual network alpar@357: ResidualDijkstra *_dijkstra; alpar@357: alpar@357: public: alpar@357: alpar@357: /// \brief Constructor. alpar@357: /// alpar@357: /// Constructor. alpar@357: /// kpeter@358: /// \param digraph The digraph the algorithm runs on. alpar@357: /// \param length The length (cost) values of the arcs. alpar@357: /// \param s The source node. alpar@357: /// \param t The target node. alpar@357: Suurballe( const Digraph &digraph, alpar@357: const LengthMap &length, alpar@357: Node s, Node t ) : alpar@357: _graph(digraph), _length(length), _flow(0), _local_flow(false), alpar@357: _potential(0), _local_potential(false), _source(s), _target(t), alpar@357: _pred(digraph) {} alpar@357: alpar@357: /// Destructor. alpar@357: ~Suurballe() { alpar@357: if (_local_flow) delete _flow; alpar@357: if (_local_potential) delete _potential; alpar@357: delete _dijkstra; alpar@357: } alpar@357: kpeter@358: /// \brief Set the flow map. alpar@357: /// kpeter@358: /// This function sets the flow map. alpar@357: /// alpar@357: /// The found flow contains only 0 and 1 values. It is the union of alpar@357: /// the found arc-disjoint paths. alpar@357: /// alpar@357: /// \return \c (*this) alpar@357: Suurballe& flowMap(FlowMap &map) { alpar@357: if (_local_flow) { alpar@357: delete _flow; alpar@357: _local_flow = false; alpar@357: } alpar@357: _flow = ↦ alpar@357: return *this; alpar@357: } alpar@357: kpeter@358: /// \brief Set the potential map. alpar@357: /// kpeter@358: /// This function sets the potential map. alpar@357: /// alpar@357: /// The potentials provide the dual solution of the underlying alpar@357: /// minimum cost flow problem. alpar@357: /// alpar@357: /// \return \c (*this) alpar@357: Suurballe& potentialMap(PotentialMap &map) { alpar@357: if (_local_potential) { alpar@357: delete _potential; alpar@357: _local_potential = false; alpar@357: } alpar@357: _potential = ↦ alpar@357: return *this; alpar@357: } alpar@357: alpar@357: /// \name Execution control alpar@357: /// The simplest way to execute the algorithm is to call the run() alpar@357: /// function. alpar@357: /// \n alpar@357: /// If you only need the flow that is the union of the found alpar@357: /// arc-disjoint paths, you may call init() and findFlow(). alpar@357: alpar@357: /// @{ alpar@357: kpeter@358: /// \brief Run the algorithm. alpar@357: /// kpeter@358: /// This function runs the algorithm. alpar@357: /// alpar@357: /// \param k The number of paths to be found. alpar@357: /// kpeter@358: /// \return \c k if there are at least \c k arc-disjoint paths from kpeter@358: /// \c s to \c t in the digraph. Otherwise it returns the number of alpar@357: /// arc-disjoint paths found. alpar@357: /// alpar@357: /// \note Apart from the return value, s.run(k) is just a alpar@357: /// shortcut of the following code. alpar@357: /// \code alpar@357: /// s.init(); alpar@357: /// s.findFlow(k); alpar@357: /// s.findPaths(); alpar@357: /// \endcode alpar@357: int run(int k = 2) { alpar@357: init(); alpar@357: findFlow(k); alpar@357: findPaths(); alpar@357: return _path_num; alpar@357: } alpar@357: kpeter@358: /// \brief Initialize the algorithm. alpar@357: /// kpeter@358: /// This function initializes the algorithm. alpar@357: void init() { kpeter@358: // Initialize maps alpar@357: if (!_flow) { alpar@357: _flow = new FlowMap(_graph); alpar@357: _local_flow = true; alpar@357: } alpar@357: if (!_potential) { alpar@357: _potential = new PotentialMap(_graph); alpar@357: _local_potential = true; alpar@357: } alpar@357: for (ArcIt e(_graph); e != INVALID; ++e) (*_flow)[e] = 0; alpar@357: for (NodeIt n(_graph); n != INVALID; ++n) (*_potential)[n] = 0; alpar@357: alpar@357: _dijkstra = new ResidualDijkstra( _graph, *_flow, _length, alpar@357: *_potential, _pred, alpar@357: _source, _target ); alpar@357: } alpar@357: kpeter@358: /// \brief Execute the successive shortest path algorithm to find alpar@357: /// an optimal flow. alpar@357: /// kpeter@358: /// This function executes the successive shortest path algorithm to kpeter@358: /// find a minimum cost flow, which is the union of \c k or less alpar@357: /// arc-disjoint paths. alpar@357: /// kpeter@358: /// \return \c k if there are at least \c k arc-disjoint paths from kpeter@358: /// \c s to \c t in the digraph. Otherwise it returns the number of alpar@357: /// arc-disjoint paths found. alpar@357: /// alpar@357: /// \pre \ref init() must be called before using this function. alpar@357: int findFlow(int k = 2) { kpeter@358: // Find shortest paths alpar@357: _path_num = 0; alpar@357: while (_path_num < k) { kpeter@358: // Run Dijkstra alpar@357: if (!_dijkstra->run()) break; alpar@357: ++_path_num; alpar@357: kpeter@358: // Set the flow along the found shortest path alpar@357: Node u = _target; alpar@357: Arc e; alpar@357: while ((e = _pred[u]) != INVALID) { alpar@357: if (u == _graph.target(e)) { alpar@357: (*_flow)[e] = 1; alpar@357: u = _graph.source(e); alpar@357: } else { alpar@357: (*_flow)[e] = 0; alpar@357: u = _graph.target(e); alpar@357: } alpar@357: } alpar@357: } alpar@357: return _path_num; alpar@357: } alpar@357: kpeter@358: /// \brief Compute the paths from the flow. alpar@357: /// kpeter@358: /// This function computes the paths from the flow. alpar@357: /// alpar@357: /// \pre \ref init() and \ref findFlow() must be called before using alpar@357: /// this function. alpar@357: void findPaths() { kpeter@358: // Create the residual flow map (the union of the paths not found kpeter@358: // so far) alpar@357: FlowMap res_flow(_graph); kpeter@358: for(ArcIt a(_graph); a != INVALID; ++a) res_flow[a] = (*_flow)[a]; alpar@357: alpar@357: paths.clear(); alpar@357: paths.resize(_path_num); alpar@357: for (int i = 0; i < _path_num; ++i) { alpar@357: Node n = _source; alpar@357: while (n != _target) { alpar@357: OutArcIt e(_graph, n); alpar@357: for ( ; res_flow[e] == 0; ++e) ; alpar@357: n = _graph.target(e); alpar@357: paths[i].addBack(e); alpar@357: res_flow[e] = 0; alpar@357: } alpar@357: } alpar@357: } alpar@357: alpar@357: /// @} alpar@357: alpar@357: /// \name Query Functions kpeter@358: /// The results of the algorithm can be obtained using these alpar@357: /// functions. alpar@357: /// \n The algorithm should be executed before using them. alpar@357: alpar@357: /// @{ alpar@357: kpeter@358: /// \brief Return a const reference to the arc map storing the alpar@357: /// found flow. alpar@357: /// kpeter@358: /// This function returns a const reference to the arc map storing kpeter@358: /// the flow that is the union of the found arc-disjoint paths. alpar@357: /// kpeter@358: /// \pre \ref run() or \ref findFlow() must be called before using kpeter@358: /// this function. alpar@357: const FlowMap& flowMap() const { alpar@357: return *_flow; alpar@357: } alpar@357: kpeter@358: /// \brief Return a const reference to the node map storing the alpar@357: /// found potentials (the dual solution). alpar@357: /// kpeter@358: /// This function returns a const reference to the node map storing kpeter@358: /// the found potentials that provide the dual solution of the kpeter@358: /// underlying minimum cost flow problem. alpar@357: /// kpeter@358: /// \pre \ref run() or \ref findFlow() must be called before using kpeter@358: /// this function. alpar@357: const PotentialMap& potentialMap() const { alpar@357: return *_potential; alpar@357: } alpar@357: kpeter@358: /// \brief Return the flow on the given arc. alpar@357: /// kpeter@358: /// This function returns the flow on the given arc. alpar@357: /// It is \c 1 if the arc is involved in one of the found paths, alpar@357: /// otherwise it is \c 0. alpar@357: /// kpeter@358: /// \pre \ref run() or \ref findFlow() must be called before using kpeter@358: /// this function. alpar@357: int flow(const Arc& arc) const { alpar@357: return (*_flow)[arc]; alpar@357: } alpar@357: kpeter@358: /// \brief Return the potential of the given node. alpar@357: /// kpeter@358: /// This function returns the potential of the given node. alpar@357: /// kpeter@358: /// \pre \ref run() or \ref findFlow() must be called before using kpeter@358: /// this function. alpar@357: Length potential(const Node& node) const { alpar@357: return (*_potential)[node]; alpar@357: } alpar@357: kpeter@358: /// \brief Return the total length (cost) of the found paths (flow). alpar@357: /// kpeter@358: /// This function returns the total length (cost) of the found paths kpeter@358: /// (flow). The complexity of the function is \f$ O(e) \f$. alpar@357: /// kpeter@358: /// \pre \ref run() or \ref findFlow() must be called before using kpeter@358: /// this function. alpar@357: Length totalLength() const { alpar@357: Length c = 0; alpar@357: for (ArcIt e(_graph); e != INVALID; ++e) alpar@357: c += (*_flow)[e] * _length[e]; alpar@357: return c; alpar@357: } alpar@357: kpeter@358: /// \brief Return the number of the found paths. alpar@357: /// kpeter@358: /// This function returns the number of the found paths. alpar@357: /// kpeter@358: /// \pre \ref run() or \ref findFlow() must be called before using kpeter@358: /// this function. alpar@357: int pathNum() const { alpar@357: return _path_num; alpar@357: } alpar@357: kpeter@358: /// \brief Return a const reference to the specified path. alpar@357: /// kpeter@358: /// This function returns a const reference to the specified path. alpar@357: /// alpar@357: /// \param i The function returns the \c i-th path. alpar@357: /// \c i must be between \c 0 and %pathNum()-1. alpar@357: /// kpeter@358: /// \pre \ref run() or \ref findPaths() must be called before using kpeter@358: /// this function. alpar@357: Path path(int i) const { alpar@357: return paths[i]; alpar@357: } alpar@357: alpar@357: /// @} alpar@357: alpar@357: }; //class Suurballe alpar@357: alpar@357: ///@} alpar@357: alpar@357: } //namespace lemon alpar@357: alpar@357: #endif //LEMON_SUURBALLE_H