# HG changeset patch # User deba # Date 1131538020 0 # Node ID dca4c8a54e0a266ad5479247ceb22fd36bc51057 # Parent 9f052750753f358d7faa9e59f93b2ffcb1ebb2ee Path length limit for belmann_ford.h diff -r 9f052750753f -r dca4c8a54e0a lemon/belmann_ford.h --- a/lemon/belmann_ford.h Tue Nov 08 10:12:45 2005 +0000 +++ b/lemon/belmann_ford.h Wed Nov 09 12:07:00 2005 +0000 @@ -203,7 +203,7 @@ typedef typename Graph::Node Node; typedef typename Graph::NodeIt NodeIt; typedef typename Graph::Edge Edge; - typedef typename Graph::EdgeIt EdgeIt; + typedef typename Graph::OutEdgeIt OutEdgeIt; /// \brief The type of the length of the edges. typedef typename _Traits::LengthMap::Value Value; @@ -230,6 +230,11 @@ ///Indicates if \ref _dist is locally allocated (\c true) or not. bool local_dist; + typedef typename Graph::template NodeMap MaskMap; + MaskMap *_mask; + + std::vector _process; + /// Creates the maps if necessary. void create_maps() { if(!_pred) { @@ -240,6 +245,7 @@ local_dist = true; _dist = Traits::createDistMap(*graph); } + _mask = new MaskMap(*graph, false); } public : @@ -324,6 +330,7 @@ ~BelmannFord() { if(local_pred) delete _pred; if(local_dist) delete _dist; + delete _mask; } /// \brief Sets the length map. @@ -388,6 +395,12 @@ _pred->set(it, INVALID); _dist->set(it, value); } + _process.clear(); + if (OperationTraits::less(value, OperationTraits::infinity())) { + for (NodeIt it(*graph); it != INVALID; ++it) { + _process.push_back(it); + } + } } /// \brief Adds a new source node. @@ -396,6 +409,77 @@ /// It just sets the distance of the node to the given value. void addSource(Node source, Value dst = OperationTraits::zero()) { _dist->set(source, dst); + if (!(*_mask)[source]) { + _process.push_back(source); + _mask->set(source, true); + } + } + + /// \brief Executes one round from the belmann ford algorithm. + /// + /// If the algoritm calculated the distances in the previous round + /// strictly for all at most k length pathes then it will calculate the + /// distances strictly for all at most k + 1 length pathes. With k + /// iteration this function calculates the at most k length pathes. + bool processNextRound() { + for (int i = 0; i < (int)_process.size(); ++i) { + _mask->set(_process[i], false); + } + std::vector nextProcess; + std::vector values(_process.size()); + for (int i = 0; i < (int)_process.size(); ++i) { + values[i] = _dist[_process[i]]; + } + for (int i = 0; i < (int)_process.size(); ++i) { + for (OutEdgeIt it(*graph, _process[i]); it != INVALID; ++it) { + Node target = graph->target(it); + Value relaxed = OperationTraits::plus(values[i], (*length)[it]); + if (OperationTraits::less(relaxed, (*_dist)[target])) { + _pred->set(target, it); + _dist->set(target, relaxed); + if (!(*_mask)[target]) { + _mask->set(target, true); + nextProcess.push_back(target); + } + } + } + } + _process.swap(nextProcess); + return _process.empty(); + } + + /// \brief Executes one weak round from the belmann ford algorithm. + /// + /// If the algorithm calculated the distances in the + /// previous round at least for all at most k length pathes then it will + /// calculate the distances at least for all at most k + 1 length pathes. + /// This function does not make possible to calculate strictly the + /// at most k length minimal pathes, this way it called just weak round. + bool processNextWeakRound() { + for (int i = 0; i < (int)_process.size(); ++i) { + _mask->set(_process[i], false); + } + std::vector nextProcess; + for (int i = 0; i < (int)_process.size(); ++i) { + for (OutEdgeIt it(*graph, _process[i]); it != INVALID; ++it) { + Node target = graph->target(it); + Value relaxed = + OperationTraits::plus((*_dist)[_process[i]], (*length)[it]); + if (OperationTraits::less(relaxed, (*_dist)[target])) { + _pred->set(target, it); + _dist->set(target, relaxed); + if (!(*_mask)[target]) { + _mask->set(target, true); + nextProcess.push_back(target); + } + } + } + } + for (int i = 0; i < (int)nextProcess.size(); ++i) { + _mask->set(nextProcess[i], false); + } + _process.swap(nextProcess); + return _process.empty(); } /// \brief Executes the algorithm. @@ -411,19 +495,7 @@ void start() { int num = countNodes(*graph) - 1; for (int i = 0; i < num; ++i) { - bool done = true; - for (EdgeIt it(*graph); it != INVALID; ++it) { - Node source = graph->source(it); - Node target = graph->target(it); - Value relaxed = - OperationTraits::plus((*_dist)[source], (*length)[it]); - if (OperationTraits::less(relaxed, (*_dist)[target])) { - _pred->set(target, it); - _dist->set(target, relaxed); - done = false; - } - } - if (done) return; + if (processNextWeakRound()) break; } } @@ -441,22 +513,26 @@ bool checkedStart() { int num = countNodes(*graph); for (int i = 0; i < num; ++i) { - bool done = true; - for (EdgeIt it(*graph); it != INVALID; ++it) { - Node source = graph->source(it); - Node target = graph->target(it); - Value relaxed = - OperationTraits::plus((*_dist)[source], (*length)[it]); - if (OperationTraits::less(relaxed, (*_dist)[target])) { - _pred->set(target, it); - _dist->set(target, relaxed); - done = false; - } - } - if (done) return true; + if (processNextWeakRound()) return true; } return false; } + + /// \brief Executes the algorithm with path length limit. + /// + /// \pre init() must be called and at least one node should be added + /// with addSource() before using this function. + /// + /// This method runs the %BelmannFord algorithm from the root node(s) + /// in order to compute the shortest path with at most \c length edge + /// long pathes to each node. The algorithm computes + /// - The shortest path tree. + /// - The limited distance of each node from the root(s). + void limitedStart(int length) { + for (int i = 0; i < length; ++i) { + if (processNextRound()) break; + } + } /// \brief Runs %BelmannFord algorithm from node \c s. ///