[Lemon-commits] [lemon_svn] deba: r2316 - hugo/trunk/lemon

Lemon SVN svn at lemon.cs.elte.hu
Mon Nov 6 20:51:45 CET 2006


Author: deba
Date: Wed Nov  9 13:07:00 2005
New Revision: 2316

Modified:
   hugo/trunk/lemon/belmann_ford.h

Log:
Path length limit for belmann_ford.h



Modified: hugo/trunk/lemon/belmann_ford.h
==============================================================================
--- hugo/trunk/lemon/belmann_ford.h	(original)
+++ hugo/trunk/lemon/belmann_ford.h	Wed Nov  9 13:07:00 2005
@@ -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<bool> MaskMap;
+    MaskMap *_mask;
+
+    std::vector<Node> _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<Node> nextProcess;
+      std::vector<Value> 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<Node> 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.
     ///    



More information about the Lemon-commits mailing list