src/work/marci/bfs_iterator.h
changeset 597 a6e2b02f496a
parent 560 5adcef1d7bcc
equal deleted inserted replaced
8:055a58cb9557 9:4d50edcdb08b
     8 
     8 
     9 #include <hugo/invalid.h>
     9 #include <hugo/invalid.h>
    10 
    10 
    11 namespace hugo {
    11 namespace hugo {
    12 
    12 
       
    13   /// Bfs searches for the nodes wich are not marked in 
       
    14   /// \c reached_map
       
    15   /// Reached have to work as read-write bool Node-map.
    13   template <typename Graph, /*typename OutEdgeIt,*/ 
    16   template <typename Graph, /*typename OutEdgeIt,*/ 
    14 	    typename ReachedMap/*=typename Graph::NodeMap<bool>*/ >
    17 	    typename ReachedMap/*=typename Graph::NodeMap<bool>*/ >
    15   class BfsIterator {
    18   class BfsIterator {
    16   protected:
    19   protected:
    17     typedef typename Graph::Node Node;
    20     typedef typename Graph::Node Node;
    21     ReachedMap& reached;
    24     ReachedMap& reached;
    22     bool b_node_newly_reached;
    25     bool b_node_newly_reached;
    23     OutEdgeIt actual_edge;
    26     OutEdgeIt actual_edge;
    24     bool own_reached_map;
    27     bool own_reached_map;
    25   public:
    28   public:
       
    29     /// In that constructor \c _reached have to be a reference 
       
    30     /// for a bool Node-map. The algorithm will search in a bfs order for 
       
    31     /// the nodes which are \c false initially
    26     BfsIterator(const Graph& _graph, ReachedMap& _reached) : 
    32     BfsIterator(const Graph& _graph, ReachedMap& _reached) : 
    27       graph(&_graph), reached(_reached), 
    33       graph(&_graph), reached(_reached), 
    28       own_reached_map(false) { }
    34       own_reached_map(false) { }
       
    35     /// The same as above, but the map storing the reached nodes 
       
    36     /// is constructed dynamically to everywhere false.
    29     BfsIterator(const Graph& _graph) : 
    37     BfsIterator(const Graph& _graph) : 
    30       graph(&_graph), reached(*(new ReachedMap(*graph /*, false*/))), 
    38       graph(&_graph), reached(*(new ReachedMap(*graph /*, false*/))), 
    31       own_reached_map(true) { }
    39       own_reached_map(true) { }
       
    40     /// The storing the reached nodes have to be destroyed if 
       
    41     /// it was constructed dynamically
    32     ~BfsIterator() { if (own_reached_map) delete &reached; }
    42     ~BfsIterator() { if (own_reached_map) delete &reached; }
    33     /// This method markes s reached.
    43     /// This method markes \c s reached.
    34     /// If the queue is empty, then s is pushed in the bfs queue 
    44     /// If the queue is empty, then \c s is pushed in the bfs queue 
    35     /// and the first OutEdgeIt is processed.
    45     /// and the first out-edge is processed.
    36     /// If the queue is not empty, then s is simply pushed.
    46     /// If the queue is not empty, then \c s is simply pushed.
    37     void pushAndSetReached(Node s) { 
    47     void pushAndSetReached(Node s) { 
    38       reached.set(s, true);
    48       reached.set(s, true);
    39       if (bfs_queue.empty()) {
    49       if (bfs_queue.empty()) {
    40 	bfs_queue.push(s);
    50 	bfs_queue.push(s);
    41 	graph->first(actual_edge, s);
    51 	graph->first(actual_edge, s);
    85 	  }
    95 	  }
    86 	}
    96 	}
    87       }
    97       }
    88       return *this;
    98       return *this;
    89     }
    99     }
       
   100     ///
    90     bool finished() const { return bfs_queue.empty(); }
   101     bool finished() const { return bfs_queue.empty(); }
    91     /// The conversion operator makes for converting the bfs-iterator 
   102     /// The conversion operator makes for converting the bfs-iterator 
    92     /// to an \c out-edge-iterator.
   103     /// to an \c out-edge-iterator.
       
   104     ///\bug Edge have to be in HUGO 0.2
    93     operator OutEdgeIt() const { return actual_edge; }
   105     operator OutEdgeIt() const { return actual_edge; }
       
   106     ///
    94     bool isBNodeNewlyReached() const { return b_node_newly_reached; }
   107     bool isBNodeNewlyReached() const { return b_node_newly_reached; }
       
   108     ///
    95     bool isANodeExamined() const { return !(graph->valid(actual_edge)); }
   109     bool isANodeExamined() const { return !(graph->valid(actual_edge)); }
       
   110     ///
    96     Node aNode() const { return bfs_queue.front(); }
   111     Node aNode() const { return bfs_queue.front(); }
       
   112     ///
    97     Node bNode() const { return graph->bNode(actual_edge); }
   113     Node bNode() const { return graph->bNode(actual_edge); }
       
   114     ///
    98     const ReachedMap& getReachedMap() const { return reached; }
   115     const ReachedMap& getReachedMap() const { return reached; }
       
   116     ///
    99     const std::queue<Node>& getBfsQueue() const { return bfs_queue; }
   117     const std::queue<Node>& getBfsQueue() const { return bfs_queue; }
   100   };  
   118   };  
   101 
   119 
   102   /// Bfs searches from s for the nodes wich are not marked in 
   120   /// Bfs searches for the nodes wich are not marked in 
   103   /// \c reached_map
   121   /// \c reached_map
   104   /// Reached is a read-write bool-map, Pred is a write-nodemap 
   122   /// Reached have to work as a read-write bool Node-map, 
   105   /// and dist is an rw-nodemap, have to be.
   123   /// Pred is a write Edge Node-map and
       
   124   /// Dist is a read-write int Node-map, have to be. 
       
   125   ///\todo In fact onsly simple operations requirement are needed for 
       
   126   /// Dist::Value.
   106   template <typename Graph, 
   127   template <typename Graph, 
   107 	    typename ReachedMap=typename Graph::template NodeMap<bool>, 
   128 	    typename ReachedMap=typename Graph::template NodeMap<bool>, 
   108 	    typename PredMap
   129 	    typename PredMap
   109 	    =typename Graph::template NodeMap<typename Graph::Edge>, 
   130 	    =typename Graph::template NodeMap<typename Graph::Edge>, 
   110 	    typename DistMap=typename Graph::template NodeMap<int> > 
   131 	    typename DistMap=typename Graph::template NodeMap<int> > 
   113   protected:
   134   protected:
   114     typedef typename Parent::Node Node;
   135     typedef typename Parent::Node Node;
   115     PredMap& pred;
   136     PredMap& pred;
   116     DistMap& dist;
   137     DistMap& dist;
   117   public:
   138   public:
       
   139     /// The algorithm will search in a bfs order for 
       
   140     /// the nodes which are \c false initially. 
       
   141     /// The constructor makes no initial changes on the maps.
   118     Bfs<Graph, ReachedMap, PredMap, DistMap>(const Graph& _graph, ReachedMap& _reached, PredMap& _pred, DistMap& _dist) : BfsIterator<Graph, ReachedMap>(_graph, _reached), pred(&_pred), dist(&_dist) { }
   142     Bfs<Graph, ReachedMap, PredMap, DistMap>(const Graph& _graph, ReachedMap& _reached, PredMap& _pred, DistMap& _dist) : BfsIterator<Graph, ReachedMap>(_graph, _reached), pred(&_pred), dist(&_dist) { }
   119     /// s is marked to be reached and pushed in the bfs queue.
   143     /// \c s is marked to be reached and pushed in the bfs queue.
   120     /// If the queue is empty, then the first out-edge is processed.
   144     /// If the queue is empty, then the first out-edge is processed.
   121     /// If s was not marked previously, then 
   145     /// If \c s was not marked previously, then 
   122     /// in addition its pred is set to be INVALID, and dist to 0. 
   146     /// in addition its pred is set to be \c INVALID, and dist to \c 0. 
   123     /// if s was marked previuosly, then it is simply pushed.
   147     /// if \c s was marked previuosly, then it is simply pushed.
   124     void push(Node s) { 
   148     void push(Node s) { 
   125       if (this->reached[s]) {
   149       if (this->reached[s]) {
   126 	Parent::pushAndSetReached(s);
   150 	Parent::pushAndSetReached(s);
   127       } else {
   151       } else {
   128 	Parent::pushAndSetReached(s);
   152 	Parent::pushAndSetReached(s);
   129 	pred.set(s, INVALID);
   153 	pred.set(s, INVALID);
   130 	dist.set(s, 0);
   154 	dist.set(s, 0);
   131       }
   155       }
   132     }
   156     }
   133     /// A bfs is processed from s.
   157     /// A bfs is processed from \c s.
   134     void run(Node s) {
   158     void run(Node s) {
   135       push(s);
   159       push(s);
   136       while (!this->finished()) this->operator++();
   160       while (!this->finished()) this->operator++();
   137     }
   161     }
       
   162     /// Beside the bfs iteration, \c pred and \dist are saved in a 
       
   163     /// newly reached node. 
   138     Bfs<Graph, ReachedMap, PredMap, DistMap> operator++() {
   164     Bfs<Graph, ReachedMap, PredMap, DistMap> operator++() {
   139       Parent::operator++();
   165       Parent::operator++();
   140       if (this->graph->valid(this->actual_edge) && this->b_node_newly_reached) 
   166       if (this->graph->valid(this->actual_edge) && this->b_node_newly_reached) 
   141       {
   167       {
   142 	pred.set(this->bNode(), this->actual_edge);
   168 	pred.set(this->bNode(), this->actual_edge);
   143 	dist.set(this->bNode(), dist[this->aNode()]);
   169 	dist.set(this->bNode(), dist[this->aNode()]);
   144       }
   170       }
   145       return *this;
   171       return *this;
   146     }
   172     }
       
   173     ///
   147     const PredMap& getPredMap() const { return pred; }
   174     const PredMap& getPredMap() const { return pred; }
       
   175     ///
   148     const DistMap& getDistMap() const { return dist; }
   176     const DistMap& getDistMap() const { return dist; }
   149   };
   177   };
   150 
   178 
       
   179   /// Dfs searches for the nodes wich are not marked in 
       
   180   /// \c reached_map
       
   181   /// Reached have to be a read-write bool Node-map.
   151   template <typename Graph, /*typename OutEdgeIt,*/ 
   182   template <typename Graph, /*typename OutEdgeIt,*/ 
   152 	    typename ReachedMap/*=typename Graph::NodeMap<bool>*/ >
   183 	    typename ReachedMap/*=typename Graph::NodeMap<bool>*/ >
   153   class DfsIterator {
   184   class DfsIterator {
   154   protected:
   185   protected:
   155     typedef typename Graph::Node Node;
   186     typedef typename Graph::Node Node;
   160     OutEdgeIt actual_edge;
   191     OutEdgeIt actual_edge;
   161     Node actual_node;
   192     Node actual_node;
   162     ReachedMap& reached;
   193     ReachedMap& reached;
   163     bool own_reached_map;
   194     bool own_reached_map;
   164   public:
   195   public:
       
   196     /// In that constructor \c _reached have to be a reference 
       
   197     /// for a bool Node-map. The algorithm will search in a dfs order for 
       
   198     /// the nodes which are \c false initially
   165     DfsIterator(const Graph& _graph, ReachedMap& _reached) : 
   199     DfsIterator(const Graph& _graph, ReachedMap& _reached) : 
   166       graph(&_graph), reached(_reached), 
   200       graph(&_graph), reached(_reached), 
   167       own_reached_map(false) { }
   201       own_reached_map(false) { }
       
   202     /// The same as above, but the map of reached nodes is 
       
   203     /// constructed dynamically 
       
   204     /// to everywhere false.
   168     DfsIterator(const Graph& _graph) : 
   205     DfsIterator(const Graph& _graph) : 
   169       graph(&_graph), reached(*(new ReachedMap(*graph /*, false*/))), 
   206       graph(&_graph), reached(*(new ReachedMap(*graph /*, false*/))), 
   170       own_reached_map(true) { }
   207       own_reached_map(true) { }
   171     ~DfsIterator() { if (own_reached_map) delete &reached; }
   208     ~DfsIterator() { if (own_reached_map) delete &reached; }
       
   209     /// This method markes s reached and first out-edge is processed.
   172     void pushAndSetReached(Node s) { 
   210     void pushAndSetReached(Node s) { 
   173       actual_node=s;
   211       actual_node=s;
   174       reached.set(s, true);
   212       reached.set(s, true);
   175       OutEdgeIt e;
   213       OutEdgeIt e;
   176       graph->first(e, s);
   214       graph->first(e, s);
   177       dfs_stack.push(e); 
   215       dfs_stack.push(e); 
   178     }
   216     }
       
   217     /// As \c DfsIterator<Graph, ReachedMap> works as an edge-iterator, 
       
   218     /// its \c operator++() iterates on the edges in a dfs order.
   179     DfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>& 
   219     DfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>& 
   180     operator++() { 
   220     operator++() { 
   181       actual_edge=dfs_stack.top();
   221       actual_edge=dfs_stack.top();
   182       //actual_node=G.aNode(actual_edge);
   222       //actual_node=G.aNode(actual_edge);
   183       if (graph->valid(actual_edge)/*.valid()*/) { 
   223       if (graph->valid(actual_edge)/*.valid()*/) { 
   198 	//actual_node=G.aNode(dfs_stack.top());
   238 	//actual_node=G.aNode(dfs_stack.top());
   199 	dfs_stack.pop();
   239 	dfs_stack.pop();
   200       }
   240       }
   201       return *this;
   241       return *this;
   202     }
   242     }
       
   243     ///
   203     bool finished() const { return dfs_stack.empty(); }
   244     bool finished() const { return dfs_stack.empty(); }
       
   245     ///
   204     operator OutEdgeIt() const { return actual_edge; }
   246     operator OutEdgeIt() const { return actual_edge; }
       
   247     ///
   205     bool isBNodeNewlyReached() const { return b_node_newly_reached; }
   248     bool isBNodeNewlyReached() const { return b_node_newly_reached; }
       
   249     ///
   206     bool isANodeExamined() const { return !(graph->valid(actual_edge)); }
   250     bool isANodeExamined() const { return !(graph->valid(actual_edge)); }
       
   251     ///
   207     Node aNode() const { return actual_node; /*FIXME*/}
   252     Node aNode() const { return actual_node; /*FIXME*/}
       
   253     ///
   208     Node bNode() const { return graph->bNode(actual_edge); }
   254     Node bNode() const { return graph->bNode(actual_edge); }
       
   255     ///
   209     const ReachedMap& getReachedMap() const { return reached; }
   256     const ReachedMap& getReachedMap() const { return reached; }
       
   257     ///
   210     const std::stack<OutEdgeIt>& getDfsStack() const { return dfs_stack; }
   258     const std::stack<OutEdgeIt>& getDfsStack() const { return dfs_stack; }
   211   };
   259   };
   212 
   260 
   213   /// Dfs searches from s for the nodes wich are not marked in 
   261   /// Dfs searches for the nodes wich are not marked in 
   214   /// \c reached_map
   262   /// \c reached_map
   215   /// Reached is a read-write bool-map, Pred is a write-nodemap, have to be.
   263   /// Reached is a read-write bool Node-map, 
       
   264   /// Pred is a write Node-map, have to be.
   216   template <typename Graph, 
   265   template <typename Graph, 
   217 	    typename ReachedMap=typename Graph::template NodeMap<bool>, 
   266 	    typename ReachedMap=typename Graph::template NodeMap<bool>, 
   218 	    typename PredMap
   267 	    typename PredMap
   219 	    =typename Graph::template NodeMap<typename Graph::Edge> > 
   268 	    =typename Graph::template NodeMap<typename Graph::Edge> > 
   220   class Dfs : public DfsIterator<Graph, ReachedMap> {
   269   class Dfs : public DfsIterator<Graph, ReachedMap> {
   221     typedef DfsIterator<Graph, ReachedMap> Parent;
   270     typedef DfsIterator<Graph, ReachedMap> Parent;
   222   protected:
   271   protected:
   223     typedef typename Parent::Node Node;
   272     typedef typename Parent::Node Node;
   224     PredMap& pred;
   273     PredMap& pred;
   225   public:
   274   public:
       
   275     /// The algorithm will search in a dfs order for 
       
   276     /// the nodes which are \c false initially. 
       
   277     /// The constructor makes no initial changes on the maps.
   226     Dfs<Graph, ReachedMap, PredMap>(const Graph& _graph, ReachedMap& _reached, PredMap& _pred) : DfsIterator<Graph, ReachedMap>(_graph, _reached), pred(&_pred) { }
   278     Dfs<Graph, ReachedMap, PredMap>(const Graph& _graph, ReachedMap& _reached, PredMap& _pred) : DfsIterator<Graph, ReachedMap>(_graph, _reached), pred(&_pred) { }
   227     /// s is marked to be reached and pushed in the bfs queue.
   279     /// \c s is marked to be reached and pushed in the bfs queue.
   228     /// If the queue is empty, then the first out-edge is processed.
   280     /// If the queue is empty, then the first out-edge is processed.
   229     /// If s was not marked previously, then 
   281     /// If \c s was not marked previously, then 
   230     /// in addition its pred is set to be INVALID. 
   282     /// in addition its pred is set to be \c INVALID. 
   231     /// if s was marked previuosly, then it is simply pushed.
   283     /// if \c s was marked previuosly, then it is simply pushed.
   232     void push(Node s) { 
   284     void push(Node s) { 
   233       if (this->reached[s]) {
   285       if (this->reached[s]) {
   234 	Parent::pushAndSetReached(s);
   286 	Parent::pushAndSetReached(s);
   235       } else {
   287       } else {
   236 	Parent::pushAndSetReached(s);
   288 	Parent::pushAndSetReached(s);
   237 	pred.set(s, INVALID);
   289 	pred.set(s, INVALID);
   238       }
   290       }
   239     }
   291     }
   240     /// A bfs is processed from s.
   292     /// A bfs is processed from \c s.
   241     void run(Node s) {
   293     void run(Node s) {
   242       push(s);
   294       push(s);
   243       while (!this->finished()) this->operator++();
   295       while (!this->finished()) this->operator++();
   244     }
   296     }
       
   297     /// Beside the dfs iteration, \c pred is saved in a 
       
   298     /// newly reached node. 
   245     Dfs<Graph, ReachedMap, PredMap> operator++() {
   299     Dfs<Graph, ReachedMap, PredMap> operator++() {
   246       Parent::operator++();
   300       Parent::operator++();
   247       if (this->graph->valid(this->actual_edge) && this->b_node_newly_reached) 
   301       if (this->graph->valid(this->actual_edge) && this->b_node_newly_reached) 
   248       {
   302       {
   249 	pred.set(this->bNode(), this->actual_edge);
   303 	pred.set(this->bNode(), this->actual_edge);
   250       }
   304       }
   251       return *this;
   305       return *this;
   252     }
   306     }
       
   307     ///
   253     const PredMap& getPredMap() const { return pred; }
   308     const PredMap& getPredMap() const { return pred; }
   254   };
   309   };
   255 
   310 
   256 
   311 
   257 } // namespace hugo
   312 } // namespace hugo