COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/work/marci/bfs_mm.h @ 1267:a93f94dbe3d3

Last change on this file since 1267:a93f94dbe3d3 was 987:87f7c54892df, checked in by Alpar Juttner, 20 years ago

Naming changes:

File size: 18.5 KB
RevLine 
[602]1// -*- c++ -*-
[921]2#ifndef LEMON_BFS_DFS_H
3#define LEMON_BFS_DFS_H
[602]4
[615]5/// \ingroup galgs
6/// \file
7/// \brief Bfs and dfs iterators.
[604]8///
[615]9/// This file contains bfs and dfs iterator classes.
[604]10///
[615]11// /// \author Marton Makai
[604]12
[602]13#include <queue>
14#include <stack>
15#include <utility>
16
[921]17#include <lemon/invalid.h>
[602]18
[921]19namespace lemon {
[944]20  namespace marci {
[602]21
22  /// Bfs searches for the nodes wich are not marked in
23  /// \c reached_map
[944]24  /// RM have to be a read-write bool node-map.
[615]25  /// \ingroup galgs
[602]26  template <typename Graph, /*typename OutEdgeIt,*/
[944]27            typename RM/*=typename Graph::NodeMap<bool>*/ >
[602]28  class BfsIterator {
[944]29  public:
30    typedef RM ReachedMap;
[602]31  protected:
32    typedef typename Graph::Node Node;
[777]33    typedef typename Graph::Edge Edge;
[602]34    typedef typename Graph::OutEdgeIt OutEdgeIt;
35    const Graph* graph;
36    std::queue<Node> bfs_queue;
[944]37    ReachedMap* reached_map;
[602]38    bool b_node_newly_reached;
[944]39    //OutEdgeIt actual_edge;
[777]40    Edge actual_edge;
[944]41    /// \e
42    BfsIterator(const Graph& _graph) : graph(&_graph), reached_map(0) { }
43    /// RM have to be set before any bfs operation.
44    BfsIterator<Graph, RM>& setReached(RM& _reached_map) {
45      reached_map=&_reached_map;
46    }
[602]47  public:
[944]48    /// In that constructor \c _reached_map have to be a reference
[650]49    /// for a bool bode-map. The algorithm will search for the
50    /// initially \c false nodes
51    /// in a bfs order.
[944]52    BfsIterator(const Graph& _graph, ReachedMap& _reached_map) :
53      graph(&_graph), reached_map(&_reached_map) { }
[602]54    /// The same as above, but the map storing the reached nodes
55    /// is constructed dynamically to everywhere false.
[650]56    /// \deprecated
[944]57//     BfsIterator(const Graph& _graph) :
58//       graph(&_graph), reached_map(new ReachedMap(*graph /*, false*/)),
59//       own_reached_map(true) { }
60//     /// The map storing the reached nodes have to be destroyed if
61//     /// it was constructed dynamically
62//     ~BfsIterator() { if (own_reached_map) delete reached_map; }
[602]63    /// This method markes \c s reached.
64    /// If the queue is empty, then \c s is pushed in the bfs queue
65    /// and the first out-edge is processed.
66    /// If the queue is not empty, then \c s is simply pushed.
[777]67    BfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>& pushAndSetReached(Node s) {
[944]68      reached_map->set(s, true);
[602]69      if (bfs_queue.empty()) {
70        bfs_queue.push(s);
[777]71        actual_edge=OutEdgeIt(*graph, s);
72        //graph->first(actual_edge, s);
[774]73        if (actual_edge!=INVALID) {
[986]74          Node w=graph->target(actual_edge);
[944]75          if (!(*reached_map)[w]) {
[602]76            bfs_queue.push(w);
[944]77            reached_map->set(w, true);
[602]78            b_node_newly_reached=true;
79          } else {
80            b_node_newly_reached=false;
81          }
82        }
83      } else {
84        bfs_queue.push(s);
85      }
[777]86      return *this;
[602]87    }
88    /// As \c BfsIterator<Graph, ReachedMap> works as an edge-iterator,
89    /// its \c operator++() iterates on the edges in a bfs order.
90    BfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>&
91    operator++() {
[774]92      if (actual_edge!=INVALID) {
[777]93        actual_edge=++OutEdgeIt(*graph, actual_edge);
94        //++actual_edge;
[774]95        if (actual_edge!=INVALID) {
[986]96          Node w=graph->target(actual_edge);
[944]97          if (!(*reached_map)[w]) {
[602]98            bfs_queue.push(w);
[944]99            reached_map->set(w, true);
[602]100            b_node_newly_reached=true;
101          } else {
102            b_node_newly_reached=false;
103          }
104        }
105      } else {
106        bfs_queue.pop();
107        if (!bfs_queue.empty()) {
[777]108          actual_edge=OutEdgeIt(*graph, bfs_queue.front());
109          //graph->first(actual_edge, bfs_queue.front());
[774]110          if (actual_edge!=INVALID) {
[986]111            Node w=graph->target(actual_edge);
[944]112            if (!(*reached_map)[w]) {
[602]113              bfs_queue.push(w);
[944]114              reached_map->set(w, true);
[602]115              b_node_newly_reached=true;
116            } else {
117              b_node_newly_reached=false;
118            }
119          }
120        }
121      }
122      return *this;
123    }
[646]124    /// Returns true iff the algorithm is finished.
[602]125    bool finished() const { return bfs_queue.empty(); }
126    /// The conversion operator makes for converting the bfs-iterator
127    /// to an \c out-edge-iterator.
[921]128    ///\bug Edge have to be in LEMON 0.2
[777]129    operator Edge() const { return actual_edge; }
[646]130    /// Returns if b-node has been reached just now.
[602]131    bool isBNodeNewlyReached() const { return b_node_newly_reached; }
[646]132    /// Returns if a-node is examined.
[774]133    bool isANodeExamined() const { return actual_edge==INVALID; }
[646]134    /// Returns a-node of the actual edge, so does if the edge is invalid.
[986]135    Node source() const { return bfs_queue.front(); }
[646]136    /// \pre The actual edge have to be valid.
[986]137    Node target() const { return graph->target(actual_edge); }
[615]138    /// Guess what?
[650]139    /// \deprecated
[944]140    const ReachedMap& reachedMap() const { return *reached_map; }
141    /// Guess what?
142    /// \deprecated
[987]143    typename ReachedMap::Value reached(const Node& n) const {
[944]144      return (*reached_map)[n];
145    }
[615]146    /// Guess what?
[650]147    /// \deprecated
[602]148    const std::queue<Node>& getBfsQueue() const { return bfs_queue; }
[615]149  };
[602]150
151  /// Bfs searches for the nodes wich are not marked in
152  /// \c reached_map
[944]153  /// RM have to work as a read-write bool Node-map,
154  /// PM is a write edge node-map and
155  /// PNM is a write node node-map and
156  /// DM is a read-write node-map of integral value, have to be.
[615]157  /// \ingroup galgs
[602]158  template <typename Graph,
[944]159            typename RM=typename Graph::template NodeMap<bool>,
160            typename PM
[602]161            =typename Graph::template NodeMap<typename Graph::Edge>,
[944]162            typename PNM
163            =typename Graph::template NodeMap<typename Graph::Node>,
164            typename DM=typename Graph::template NodeMap<int> >
165  class Bfs : public BfsIterator<Graph, RM> {
166    typedef BfsIterator<Graph, RM> Parent;
167  public:
168    typedef RM ReachedMap;
169    typedef PM PredMap;
170    typedef PNM PredNodeMap;
171    typedef DM DistMap;
[602]172  protected:
173    typedef typename Parent::Node Node;
[944]174    PredMap* pred_map;
175    PredNodeMap* pred_node_map;
176    DistMap* dist_map;
177    /// \e
178    Bfs<Graph, RM, PM, PNM, DM>
179    (const Graph& _graph) : BfsIterator<Graph, RM>(_graph) { }
180    /// PM have to be set before any bfs operation.
181    Bfs<Graph, RM, PM, PNM, DM>&
182    setPredMap(PredMap& _pred_map) {
183      pred_map=&_pred_map;
184    }
185    /// PredNodeMap have to be set before any bfs operation.
186    Bfs<Graph, RM, PM, PNM, DM>&
187    setPredNodeMap(PredNodeMap& _pred_node_map) {
188      pred_node_map=&_pred_node_map;
189    }
190    /// DistMap have to be set before any bfs operation.
191    Bfs<Graph, RM, PM, PNM, DM>&
192    setDistMap(DistMap& _dist_map) {
193      dist_map=&_dist_map;
194    }
[602]195  public:
196    /// The algorithm will search in a bfs order for
197    /// the nodes which are \c false initially.
198    /// The constructor makes no initial changes on the maps.
[944]199    Bfs<Graph, RM, PM, PNM, DM>
200    (const Graph& _graph, ReachedMap& _reached_map,
201     PredMap& _pred_map, PredNodeMap& _pred_node_map,
202     DistMap& _dist_map) : BfsIterator<Graph, RM>(_graph, _reached_map),
203      pred_map(&_pred_map), pred_node_map(&_pred_node_map),
204                           dist_map(&_dist_map) { }
[602]205    /// \c s is marked to be reached and pushed in the bfs queue.
206    /// If the queue is empty, then the first out-edge is processed.
207    /// If \c s was not marked previously, then
[944]208    /// in addition its pred_map is set to be \c INVALID,
209    /// and dist_map to \c 0.
[602]210    /// if \c s was marked previuosly, then it is simply pushed.
[944]211    Bfs<Graph, RM, PM, PNM, DM>& push(Node s) {
212      if ((*(this->reached_map))[s]) {
[602]213        Parent::pushAndSetReached(s);
214      } else {
215        Parent::pushAndSetReached(s);
[944]216        pred_map->set(s, INVALID);
217        pred_node_map->set(s, INVALID);
218        dist_map->set(s, 0);
[602]219      }
[777]220      return *this;
[602]221    }
222    /// A bfs is processed from \c s.
[944]223    Bfs<Graph, RM, PM, PNM, DM>& run(Node s) {
[602]224      push(s);
225      while (!this->finished()) this->operator++();
[777]226      return *this;
[602]227    }
[944]228    /// Beside the bfs iteration, \c pred_map and \dist_map are saved in a
[602]229    /// newly reached node.
[944]230    Bfs<Graph, RM, PM, PNM, DM>& operator++() {
[602]231      Parent::operator++();
[944]232      if ((this->actual_edge)!=INVALID && this->b_node_newly_reached)
[602]233      {
[986]234        pred_map->set(this->target(), this->actual_edge);
235        pred_node_map->set(this->target(), this->source());
236        dist_map->set(this->target(), (*dist_map)[this->source()]);
[602]237      }
238      return *this;
239    }
[615]240    /// Guess what?
[650]241    /// \deprecated
[944]242    const PredMap& predMap() const { return *pred_map; }
243    /// Guess what?
244    /// \deprecated
[987]245    typename PredMap::Value pred(const Node& n) const {
[944]246      return (*pred_map)[n];
247    }
248    /// Guess what?
249    /// \deprecated
250    const PredNodeMap& predNodeMap() const { return *pred_node_map; }
251    /// Guess what?
252    /// \deprecated
[987]253    typename PredNodeMap::Value predNode(const Node& n) const {
[944]254      return (*pred_node_map)[n];
255    }
[615]256    /// Guess what?
[650]257    /// \deprecated
[944]258    const DistMap& distMap() const { return *dist_map; }
259    /// Guess what?
260    /// \deprecated
[987]261    typename DistMap::Value dist(const Node& n) const {
[944]262      return (*dist_map)[n];
263    }
[602]264  };
265
[944]266//   template <typename Graph,
267//          typename RM=typename Graph::template NodeMap<bool>,
268//          typename PM
269//          =typename Graph::template NodeMap<typename Graph::Edge>,
270//          typename PredNodeMap
271//          =typename Graph::template NodeMap<typename Graph::Node>,
272//          typename DistMap=typename Graph::template NodeMap<int> >
273//     class BfsWizard : public Bfs<Graph> {
274//     public:
275//       typedef Bfs<Graph, PM, PredNodeMap, DistMap> Parent;
276//     protected:
277//       typedef typename Parent::Node Node;
278//       bool own_reached_map;
279//       bool own_pred_map;
280//       bool own_pred_node_map;
281//       bool own_dist_map;
282
283//       BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
284//       makeRreached() {
285//      own_reached_map=true;
286//      reached=new ReachedMap(*graph, false);
287//       }
288//       BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
289//       deleteReachedMap() {
290//      own_reached_map=false;
291//      delete reached;
292//       }
293
294//       BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
295//       makePM() {
296//      own_pred_map=true;
297//      pred_map=new PM(*graph, INVALID);
298//       }
299//       BfsWizard<Graph, ReachedMap, PM, PredNodeMap, DistMap>&
300//       deletePM() {
301//      own_pred_map=false;
302//      delete pred_map;
303//       }
304
305//       BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
306//       makePredNodeMap() {
307//      own_pred_node_map=true;
308//      pred_node_map=new PredNodeMap(*graph, INVALID);
309//       }
310//       BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
311//       deletePredNodeMap() {
312//      own_pred_node_map=false;
313//      delete pred_node_map;
314//       }
315
316//       BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
317//       makeDistMap() {
318//      own_dist_map=true;
319//      dist_map=new DistMap(*graph, 0);
320//       }
321//       BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
322//       deleteDistMap() {
323//      own_dist_map=false;
324//      delete dist_map;
325//       }
326
327//     public:
328//       /// User friendly Bfs class.
329//       /// The maps which are not explicitly given by the user are
330//       /// constructed with false, INVALID, INVALID and 0 values.
331//       /// For the user defined maps, the values are not modified, and
332//       /// the bfs is processed without any preset on maps. Therefore,
333//       /// the bfs will search only the nodes which are set false previously
334//       /// in reached, and in the nodes wich are not newly reached by the
335//       /// search, the map values are not modified.
336//       BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>
337//       (const Graph& _graph) :
338//      own_reached_map(false),
339//      own_pred_map(false),
340//      own_pred_node_map(false),
341//      own_dist_map(false) {
342//       }
343
344//       /// \e
345//       ~BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>() {
346//      if (own_reached_map) deleteReachedMap();
347//      if (own_pred_map) deletePM();
348//      if (own_pred_node_map) deletePredNodeMap();
349//      if (own_dist_map) deleteDistMap();
350//       }
351
352//       /// \e
353//       BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
354//       setReachedMap(ReachedMap& _reached) {
355//      if (own_reached_map) deleteReachedMap();
356//      Parent::setReachedMap(_reached);
357//       }
358//       /// \e
359//       BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
360//       setPM(PM& _pred) {
361//      if (own_pred_map) deletePM();
362//      Parent::setPM(_pred);
363//       }
364//       /// \e
365//       BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
366//       setPredNodeMap(PredNodeMap& _pred_node) {
367//      if (own_pred_node_map) deletePredNodeMap();
368//      Parent::setPredNodeMap(_pred_node);
369//       }
370//       /// \e
371//       BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
372//       setDistMap(DistMap& _dist) {
373//      if (own_dist_map) deleteDistMap();
374//      Parent::setDistMap(_dist);
375//       }
376
377//       /// \e
378//       BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
379//       push(Node s) {
380//      if (!reached) makeReachedMap();
381//      if (!pred_map) makePMMap();
382//      if (!pred_node_map) makePredNodeMap();
383//      if (!dist_map) makeDistMap();
384//      push(s);
385//      return *this;
386//       }
387
388//       /// \e
389//       BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
390//       operator++() {
391//      if (!reached) makeRM();
392//      if (!pred_map) makePMMap();
393//      if (!pred_node_map) makePredNodeMap();
394//      if (!dist_map) makeDistMap();
395//      ++(*this);
396//      return *this;
397//       }
398
399//       /// \e
400//       BfsWizard<Graph, RM, PM, PredNodeMap, DistMap>&
401//       run(Node s) {
402//      if (!reached) makeRM();
403//      if (!pred_map) makePMMap();
404//      if (!pred_node_map) makePredNodeMap();
405//      if (!dist_map) makeDistMap();
406//      run(s);
407//      return *this;
408//       }
409     
410//     };
411
412
[602]413  /// Dfs searches for the nodes wich are not marked in
414  /// \c reached_map
415  /// Reached have to be a read-write bool Node-map.
[615]416  /// \ingroup galgs
[602]417  template <typename Graph, /*typename OutEdgeIt,*/
418            typename ReachedMap/*=typename Graph::NodeMap<bool>*/ >
419  class DfsIterator {
420  protected:
421    typedef typename Graph::Node Node;
[777]422    typedef typename Graph::Edge Edge;
[602]423    typedef typename Graph::OutEdgeIt OutEdgeIt;
424    const Graph* graph;
425    std::stack<OutEdgeIt> dfs_stack;
426    bool b_node_newly_reached;
[777]427    Edge actual_edge;
[602]428    Node actual_node;
429    ReachedMap& reached;
430    bool own_reached_map;
431  public:
432    /// In that constructor \c _reached have to be a reference
[650]433    /// for a bool node-map. The algorithm will search in a dfs order for
[602]434    /// the nodes which are \c false initially
435    DfsIterator(const Graph& _graph, ReachedMap& _reached) :
436      graph(&_graph), reached(_reached),
437      own_reached_map(false) { }
438    /// The same as above, but the map of reached nodes is
439    /// constructed dynamically
440    /// to everywhere false.
441    DfsIterator(const Graph& _graph) :
442      graph(&_graph), reached(*(new ReachedMap(*graph /*, false*/))),
443      own_reached_map(true) { }
444    ~DfsIterator() { if (own_reached_map) delete &reached; }
445    /// This method markes s reached and first out-edge is processed.
[777]446    DfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>& pushAndSetReached(Node s) {
[602]447      actual_node=s;
448      reached.set(s, true);
[777]449      OutEdgeIt e(*graph, s);
450      //graph->first(e, s);
[602]451      dfs_stack.push(e);
[777]452      return *this;
[602]453    }
454    /// As \c DfsIterator<Graph, ReachedMap> works as an edge-iterator,
455    /// its \c operator++() iterates on the edges in a dfs order.
456    DfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>&
457    operator++() {
458      actual_edge=dfs_stack.top();
[774]459      if (actual_edge!=INVALID/*.valid()*/) {
[986]460        Node w=graph->target(actual_edge);
[602]461        actual_node=w;
462        if (!reached[w]) {
[777]463          OutEdgeIt e(*graph, w);
464          //graph->first(e, w);
[602]465          dfs_stack.push(e);
466          reached.set(w, true);
467          b_node_newly_reached=true;
468        } else {
[986]469          actual_node=graph->source(actual_edge);
[774]470          ++dfs_stack.top();
[602]471          b_node_newly_reached=false;
472        }
473      } else {
474        //actual_node=G.aNode(dfs_stack.top());
475        dfs_stack.pop();
476      }
477      return *this;
478    }
[646]479    /// Returns true iff the algorithm is finished.
[602]480    bool finished() const { return dfs_stack.empty(); }
[646]481    /// The conversion operator makes for converting the bfs-iterator
482    /// to an \c out-edge-iterator.
[921]483    ///\bug Edge have to be in LEMON 0.2
[777]484    operator Edge() const { return actual_edge; }
[646]485    /// Returns if b-node has been reached just now.
[602]486    bool isBNodeNewlyReached() const { return b_node_newly_reached; }
[646]487    /// Returns if a-node is examined.
[774]488    bool isANodeExamined() const { return actual_edge==INVALID; }
[646]489    /// Returns a-node of the actual edge, so does if the edge is invalid.
[986]490    Node source() const { return actual_node; /*FIXME*/}
[646]491    /// Returns b-node of the actual edge.
492    /// \pre The actual edge have to be valid.
[986]493    Node target() const { return graph->target(actual_edge); }
[615]494    /// Guess what?
[650]495    /// \deprecated
[602]496    const ReachedMap& getReachedMap() const { return reached; }
[615]497    /// Guess what?
[650]498    /// \deprecated
[602]499    const std::stack<OutEdgeIt>& getDfsStack() const { return dfs_stack; }
500  };
501
502  /// Dfs searches for the nodes wich are not marked in
503  /// \c reached_map
[650]504  /// Reached is a read-write bool node-map,
505  /// Pred is a write node-map, have to be.
[615]506  /// \ingroup galgs
[602]507  template <typename Graph,
508            typename ReachedMap=typename Graph::template NodeMap<bool>,
509            typename PredMap
510            =typename Graph::template NodeMap<typename Graph::Edge> >
511  class Dfs : public DfsIterator<Graph, ReachedMap> {
512    typedef DfsIterator<Graph, ReachedMap> Parent;
513  protected:
514    typedef typename Parent::Node Node;
515    PredMap& pred;
516  public:
517    /// The algorithm will search in a dfs order for
518    /// the nodes which are \c false initially.
519    /// The constructor makes no initial changes on the maps.
[671]520    Dfs<Graph, ReachedMap, PredMap>(const Graph& _graph, ReachedMap& _reached, PredMap& _pred) : DfsIterator<Graph, ReachedMap>(_graph, _reached), pred(_pred) { }
[602]521    /// \c s is marked to be reached and pushed in the bfs queue.
522    /// If the queue is empty, then the first out-edge is processed.
523    /// If \c s was not marked previously, then
524    /// in addition its pred is set to be \c INVALID.
525    /// if \c s was marked previuosly, then it is simply pushed.
[777]526    Dfs<Graph, ReachedMap, PredMap>& push(Node s) {
[602]527      if (this->reached[s]) {
528        Parent::pushAndSetReached(s);
529      } else {
530        Parent::pushAndSetReached(s);
531        pred.set(s, INVALID);
532      }
[777]533      return *this;
[602]534    }
535    /// A bfs is processed from \c s.
[777]536    Dfs<Graph, ReachedMap, PredMap>& run(Node s) {
[602]537      push(s);
538      while (!this->finished()) this->operator++();
[777]539      return *this;
[602]540    }
541    /// Beside the dfs iteration, \c pred is saved in a
542    /// newly reached node.
[604]543    Dfs<Graph, ReachedMap, PredMap>& operator++() {
[602]544      Parent::operator++();
545      if (this->graph->valid(this->actual_edge) && this->b_node_newly_reached)
546      {
[986]547        pred.set(this->target(), this->actual_edge);
[602]548      }
549      return *this;
550    }
[615]551    /// Guess what?
[650]552    /// \deprecated
[602]553    const PredMap& getPredMap() const { return pred; }
554  };
555
[944]556  } // namespace marci
[921]557} // namespace lemon
[602]558
[921]559#endif //LEMON_BFS_DFS_H
Note: See TracBrowser for help on using the repository browser.