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