[Lemon-commits] deba: r3081 - in hugo/trunk: demo lemon

Lemon SVN svn at lemon.cs.elte.hu
Tue Nov 21 19:22:09 CET 2006


Author: deba
Date: Tue Nov 21 19:22:08 2006
New Revision: 3081

Modified:
   hugo/trunk/demo/topology_demo.cc
   hugo/trunk/lemon/bfs.h
   hugo/trunk/lemon/topology.h

Log:
BfsVisitor
Bipartite partitions based on visitors

topology_demo.cc => scaleToA4 works without extra parameters




Modified: hugo/trunk/demo/topology_demo.cc
==============================================================================
--- hugo/trunk/demo/topology_demo.cc	(original)
+++ hugo/trunk/demo/topology_demo.cc	Tue Nov 21 19:22:08 2006
@@ -36,6 +36,7 @@
 /// \include topology_demo.cc
 
 using namespace lemon;
+using namespace lemon::dim2;
 using namespace std;
 
 
@@ -49,7 +50,7 @@
   typedef Graph::Node Node;
 
   Graph graph;
-  Graph::NodeMap<dim2::Point<double> > coords(graph);
+  Graph::NodeMap<Point<double> > coords(graph);
 
   UGraphReader<Graph>("u_components.lgf", graph).
     readNodeMap("coordinates_x", xMap(coords)).
@@ -63,7 +64,6 @@
 
   graphToEps(graph, "connected_components.eps").undirected().
     coords(coords).scaleToA4().enableParallel().
-    parEdgeDist(20.0).edgeWidthScale(2.0).nodeScale(20.0).
     nodeColors(composeMap(palette, compMap)).run();
 
   std::cout << "Result: connected_components.eps" << std::endl;
@@ -74,7 +74,7 @@
   typedef Graph::Node Node;
 
   Graph graph;
-  Graph::NodeMap<dim2::Point<double> > coords(graph);
+  Graph::NodeMap<Point<double> > coords(graph);
 
   GraphReader<Graph>("dir_components.lgf", graph).
     readNodeMap("coordinates_x", xMap(coords)).
@@ -89,9 +89,7 @@
   stronglyConnectedCutEdges(graph, cutMap);
 
   graphToEps(graph, "strongly_connected_components.eps").
-    coords(coords).scaleToA4().enableParallel().
-    drawArrows().arrowWidth(10.0).arrowLength(10.0).
-    parEdgeDist(20.0).edgeWidthScale(2.0).nodeScale(20.0).
+    coords(coords).scaleToA4().enableParallel().drawArrows().
     nodeColors(composeMap(palette, compMap)).
     edgeColors(composeMap(functorMap(&color), cutMap)).run();
 
@@ -104,7 +102,7 @@
   typedef Graph::UEdge UEdge;
 
   Graph graph;
-  Graph::NodeMap<dim2::Point<double> > coords(graph);
+  Graph::NodeMap<Point<double> > coords(graph);
 
   UGraphReader<Graph>("u_components.lgf", graph).
     readNodeMap("coordinates_x", xMap(coords)).
@@ -120,7 +118,6 @@
 
   graphToEps(graph, "bi_node_connected_components.eps").undirected().
     coords(coords).scaleToA4().enableParallel().
-    parEdgeDist(20.0).edgeWidthScale(5.0).nodeScale(20.0).
     edgeColors(composeMap(palette, compMap)).
     nodeColors(composeMap(functorMap(&color), cutMap)).
     run();
@@ -134,7 +131,7 @@
   typedef Graph::UEdge UEdge;
 
   Graph graph;
-  Graph::NodeMap<dim2::Point<double> > coords(graph);
+  Graph::NodeMap<Point<double> > coords(graph);
 
   UGraphReader<Graph>("u_components.lgf", graph).
     readNodeMap("coordinates_x", xMap(coords)).
@@ -150,7 +147,6 @@
 
   graphToEps(graph, "bi_edge_connected_components.eps").undirected().
     coords(coords).scaleToA4().enableParallel().
-    parEdgeDist(20.0).edgeWidthScale(2.0).nodeScale(20.0).
     nodeColors(composeMap(palette, compMap)).
     edgeColors(composeMap(functorMap(&color), cutMap)).run();
   
@@ -163,7 +159,7 @@
   typedef Graph::UEdge UEdge;
 
   Graph graph;
-  Graph::NodeMap<dim2::Point<double> > coords(graph);
+  Graph::NodeMap<Point<double> > coords(graph);
 
   UGraphReader<Graph>("partitions.lgf", graph).
     readNodeMap("coordinates_x", xMap(coords)).
@@ -177,7 +173,6 @@
 
   graphToEps(graph, "bipartite_partitions.eps").undirected().
     coords(coords).scaleToA4().enableParallel().
-    parEdgeDist(20.0).edgeWidthScale(2.0).nodeScale(20.0).
     nodeColors(composeMap(functorMap(&color), partMap)).run();
   
   std::cout << "Result: bipartite_partitions.eps" << std::endl;

Modified: hugo/trunk/lemon/bfs.h
==============================================================================
--- hugo/trunk/lemon/bfs.h	(original)
+++ hugo/trunk/lemon/bfs.h	Tue Nov 21 19:22:08 2006
@@ -587,9 +587,9 @@
       while ( !emptyQueue() ) processNextNode();
     }
     
-    ///Executes the algorithm until \c dest is reached.
+    ///Executes the algorithm until \c dest is the next node to processed.
 
-    ///Executes the algorithm until \c dest is reached.
+    ///Executes the algorithm until \c dest is the next node to processed.
     ///
     ///\pre init() must be called and at least one node should be added
     ///with addSource() before using this function.
@@ -614,8 +614,9 @@
     ///\pre init() must be called and at least one node should be added
     ///with addSource() before using this function.
     ///
-    ///\param nm must be a bool (or convertible) node map. The algorithm
-    ///will stop when it reaches a node \c v with <tt>nm[v]==true</tt>.
+    ///\param nm must be a bool (or convertible) node map. The
+    ///algorithm will stop when for the next processable node \c v is
+    ///<tt>nm[v]</tt> true.
     ///\todo query the reached target
     template<class NM>
     void start(const NM &nm)
@@ -633,11 +634,11 @@
     ///- The shortest path tree.
     ///- The distance of each node from the root.
     ///
-    ///\note d.run(s) is just a shortcut of the following code.
+    ///\note b.run(s) is just a shortcut of the following code.
     ///\code
-    ///  d.init();
-    ///  d.addSource(s);
-    ///  d.start();
+    ///  b.init();
+    ///  b.addSource(s);
+    ///  b.start();
     ///\endcode
     void run(Node s) {
       init();
@@ -651,12 +652,12 @@
     ///
     ///\return The length of the shortest s---t path if there exists one,
     ///0 otherwise.
-    ///\note Apart from the return value, d.run(s) is
+    ///\note Apart from the return value, b.run(s) is
     ///just a shortcut of the following code.
     ///\code
-    ///  d.init();
-    ///  d.addSource(s);
-    ///  d.start(t);
+    ///  b.init();
+    ///  b.addSource(s);
+    ///  b.start(t);
     ///\endcode
     int run(Node s,Node t) {
       init();
@@ -671,7 +672,7 @@
     ///The result of the %BFS algorithm can be obtained using these
     ///functions.\n
     ///Before the use of these functions,
-    ///either run() or start() must be called.
+    ///either run() or start() must be calleb.
     
     ///@{
 
@@ -943,7 +944,7 @@
     ///The type of the map that stores the dists of the nodes.
     typedef typename TR::DistMap DistMap;
 
-public:
+  public:
     /// Constructor.
     BfsWizard() : TR() {}
 
@@ -1104,6 +1105,495 @@
     return BfsWizard<BfsWizardBase<GR> >(g,s);
   }
 
+#ifdef DOXYGEN
+  /// \brief Visitor class for bfs.
+  ///  
+  /// It gives a simple interface for a functional interface for bfs 
+  /// traversal. The traversal on a linear data structure. 
+  template <typename _Graph>
+  struct BfsVisitor {
+    typedef _Graph Graph;
+    typedef typename Graph::Edge Edge;
+    typedef typename Graph::Node Node;
+    /// \brief Called when the edge reach a node.
+    /// 
+    /// It is called when the bfs find an edge which target is not
+    /// reached yet.
+    void discover(const Edge& edge) {}
+    /// \brief Called when the node reached first time.
+    /// 
+    /// It is Called when the node reached first time.
+    void reach(const Node& node) {}
+    /// \brief Called when the edge examined but target of the edge 
+    /// already discovered.
+    /// 
+    /// It called when the edge examined but the target of the edge 
+    /// already discovered.
+    void examine(const Edge& edge) {}
+    /// \brief Called for the source node of the bfs.
+    /// 
+    /// It is called for the source node of the bfs.
+    void start(const Node& node) {}
+    /// \brief Called when the node processed.
+    /// 
+    /// It is Called when the node processed.
+    void process(const Node& node) {}
+  };
+#else
+  template <typename _Graph>
+  struct BfsVisitor {
+    typedef _Graph Graph;
+    typedef typename Graph::Edge Edge;
+    typedef typename Graph::Node Node;
+    void discover(const Edge&) {}
+    void reach(const Node&) {}
+    void examine(const Edge&) {}
+    void start(const Node&) {}
+    void process(const Node&) {}
+
+    template <typename _Visitor>
+    struct Constraints {
+      void constraints() {
+	Edge edge;
+	Node node;
+	visitor.discover(edge);
+	visitor.reach(node);
+	visitor.examine(edge);
+	visitor.start(node);
+        visitor.process(node);
+      }
+      _Visitor& visitor;
+    };
+  };
+#endif
+
+  /// \brief Default traits class of BfsVisit class.
+  ///
+  /// Default traits class of BfsVisit class.
+  /// \param _Graph Graph type.
+  template<class _Graph>
+  struct BfsVisitDefaultTraits {
+
+    /// \brief The graph type the algorithm runs on. 
+    typedef _Graph Graph;
+
+    /// \brief The type of the map that indicates which nodes are reached.
+    /// 
+    /// The type of the map that indicates which nodes are reached.
+    /// It must meet the \ref concepts::WriteMap "WriteMap" concept.
+    /// \todo named parameter to set this type, function to read and write.
+    typedef typename Graph::template NodeMap<bool> ReachedMap;
+
+    /// \brief Instantiates a ReachedMap.
+    ///
+    /// This function instantiates a \ref ReachedMap. 
+    /// \param graph is the graph, to which
+    /// we would like to define the \ref ReachedMap.
+    static ReachedMap *createReachedMap(const Graph &graph) {
+      return new ReachedMap(graph);
+    }
+
+  };
+  
+  /// %BFS Visit algorithm class.
+  
+  /// \ingroup flowalgs
+  /// This class provides an efficient implementation of the %BFS algorithm
+  /// with visitor interface.
+  ///
+  /// The %BfsVisit class provides an alternative interface to the Bfs
+  /// class. It works with callback mechanism, the BfsVisit object calls
+  /// on every bfs event the \c Visitor class member functions. 
+  ///
+  /// \param _Graph The graph type the algorithm runs on. The default value is
+  /// \ref ListGraph. The value of _Graph is not used directly by Bfs, it
+  /// is only passed to \ref BfsDefaultTraits.
+  /// \param _Visitor The Visitor object for the algorithm. The 
+  /// \ref BfsVisitor "BfsVisitor<_Graph>" is an empty Visitor which
+  /// does not observe the Bfs events. If you want to observe the bfs
+  /// events you should implement your own Visitor class.
+  /// \param _Traits Traits class to set various data types used by the 
+  /// algorithm. The default traits class is
+  /// \ref BfsVisitDefaultTraits "BfsVisitDefaultTraits<_Graph>".
+  /// See \ref BfsVisitDefaultTraits for the documentation of
+  /// a Bfs visit traits class.
+  ///
+  /// \author Jacint Szabo, Alpar Juttner and Balazs Dezso
+#ifdef DOXYGEN
+  template <typename _Graph, typename _Visitor, typename _Traits>
+#else
+  template <typename _Graph = ListGraph,
+	    typename _Visitor = BfsVisitor<_Graph>,
+	    typename _Traits = BfsDefaultTraits<_Graph> >
+#endif
+  class BfsVisit {
+  public:
+    
+    /// \brief \ref Exception for uninitialized parameters.
+    ///
+    /// This error represents problems in the initialization
+    /// of the parameters of the algorithms.
+    class UninitializedParameter : public lemon::UninitializedParameter {
+    public:
+      virtual const char* what() const throw() 
+      {
+	return "lemon::BfsVisit::UninitializedParameter";
+      }
+    };
+
+    typedef _Traits Traits;
+
+    typedef typename Traits::Graph Graph;
+
+    typedef _Visitor Visitor;
+
+    ///The type of the map indicating which nodes are reached.
+    typedef typename Traits::ReachedMap ReachedMap;
+
+  private:
+
+    typedef typename Graph::Node Node;
+    typedef typename Graph::NodeIt NodeIt;
+    typedef typename Graph::Edge Edge;
+    typedef typename Graph::OutEdgeIt OutEdgeIt;
+
+    /// Pointer to the underlying graph.
+    const Graph *_graph;
+    /// Pointer to the visitor object.
+    Visitor *_visitor;
+    ///Pointer to the map of reached status of the nodes.
+    ReachedMap *_reached;
+    ///Indicates if \ref _reached is locally allocated (\c true) or not.
+    bool local_reached;
+
+    std::vector<typename Graph::Node> _list;
+    int _list_front, _list_back;
+
+    /// \brief Creates the maps if necessary.
+    ///
+    /// Creates the maps if necessary.
+    void create_maps() {
+      if(!_reached) {
+	local_reached = true;
+	_reached = Traits::createReachedMap(*_graph);
+      }
+    }
+
+  protected:
+
+    BfsVisit() {}
+    
+  public:
+
+    typedef BfsVisit Create;
+
+    /// \name Named template parameters
+
+    ///@{
+    template <class T>
+    struct DefReachedMapTraits : public Traits {
+      typedef T ReachedMap;
+      static ReachedMap *createReachedMap(const Graph &graph) {
+	throw UninitializedParameter();
+      }
+    };
+    /// \brief \ref named-templ-param "Named parameter" for setting 
+    /// ReachedMap type
+    ///
+    /// \ref named-templ-param "Named parameter" for setting ReachedMap type
+    template <class T>
+    struct DefReachedMap : public BfsVisit< Graph, Visitor,
+					    DefReachedMapTraits<T> > {
+      typedef BfsVisit< Graph, Visitor, DefReachedMapTraits<T> > Create;
+    };
+    ///@}
+
+  public:      
+    
+    /// \brief Constructor.
+    ///
+    /// Constructor.
+    ///
+    /// \param graph the graph the algorithm will run on.
+    /// \param visitor The visitor of the algorithm.
+    ///
+    BfsVisit(const Graph& graph, Visitor& visitor) 
+      : _graph(&graph), _visitor(&visitor),
+	_reached(0), local_reached(false) {}
+    
+    /// \brief Destructor.
+    ///
+    /// Destructor.
+    ~BfsVisit() {
+      if(local_reached) delete _reached;
+    }
+
+    /// \brief Sets the map indicating if a node is reached.
+    ///
+    /// Sets the map indicating if a node is reached.
+    /// If you don't use this function before calling \ref run(),
+    /// it will allocate one. The destuctor deallocates this
+    /// automatically allocated map, of course.
+    /// \return <tt> (*this) </tt>
+    BfsVisit &reachedMap(ReachedMap &m) {
+      if(local_reached) {
+	delete _reached;
+	local_reached = false;
+      }
+      _reached = &m;
+      return *this;
+    }
+
+  public:
+    /// \name Execution control
+    /// The simplest way to execute the algorithm is to use
+    /// one of the member functions called \c run(...).
+    /// \n
+    /// If you need more control on the execution,
+    /// first you must call \ref init(), then you can adda source node
+    /// with \ref addSource().
+    /// Finally \ref start() will perform the actual path
+    /// computation.
+
+    /// @{
+    /// \brief Initializes the internal data structures.
+    ///
+    /// Initializes the internal data structures.
+    ///
+    void init() {
+      create_maps();
+      _list.resize(countNodes(*_graph));
+      _list_front = _list_back = -1;
+      for (NodeIt u(*_graph) ; u != INVALID ; ++u) {
+	_reached->set(u, false);
+      }
+    }
+    
+    /// \brief Adds a new source node.
+    ///
+    /// Adds a new source node to the set of nodes to be processed.
+    void addSource(Node s) {
+      if(!(*_reached)[s]) {
+	  _reached->set(s,true);
+	  _visitor->start(s);
+	  _visitor->reach(s);
+          _list[++_list_back] = s;
+	}
+    }
+    
+    /// \brief Processes the next node.
+    ///
+    /// Processes the next node.
+    ///
+    /// \return The processed node.
+    ///
+    /// \pre The queue must not be empty!
+    Node processNextNode() { 
+      Node n = _list[++_list_front];
+      _visitor->process(n);
+      Edge e;
+      for (_graph->firstOut(e, n); e != INVALID; _graph->nextOut(e)) {
+        Node m = _graph->target(e);
+        if (!(*_reached)[m]) {
+          _visitor->discover(e);
+          _visitor->reach(m);
+          _reached->set(m, true);
+          _list[++_list_back] = m;
+        } else {
+          _visitor->examine(e);
+        }
+      }
+      return n;
+    }
+
+    /// \brief Processes the next node.
+    ///
+    /// Processes the next node. And checks that the given target node
+    /// is reached. If the target node is reachable from the processed
+    /// node then the reached parameter will be set true. The reached
+    /// parameter should be initially false.
+    ///
+    /// \param target The target node.
+    /// \retval reached Indicates that the target node is reached.
+    /// \return The processed node.
+    ///
+    /// \warning The queue must not be empty!
+    Node processNextNode(Node target, bool& reached) {
+      Node n = _list[++_list_front];
+      _visitor->process(n);
+      Edge e;
+      for (_graph->firstOut(e, n); e != INVALID; _graph->nextOut(e)) {
+        Node m = _graph->target(e);
+        if (!(*_reached)[m]) {
+          _visitor->discover(e);
+          _visitor->reach(m);
+          _reached->set(m, true);
+          _list[++_list_back] = m;
+          reached = reached || (target == m);
+        } else {
+          _visitor->examine(e);
+        }
+      }
+      return n;
+    }
+
+    /// \brief Processes the next node.
+    ///
+    /// Processes the next node. And checks that at least one of
+    /// reached node has true value in the \c nm nodemap. If one node
+    /// with true value is reachable from the processed node then the
+    /// reached parameter will be set true. The reached parameter
+    /// should be initially false.
+    ///
+    /// \param target The nodemaps of possible targets.
+    /// \retval reached Indicates that one of the target nodes is reached.
+    /// \return The processed node.
+    ///
+    /// \warning The queue must not be empty!
+    template <typename NM>
+    Node processNextNode(const NM& nm, bool& reached) {
+      Node n = _list[++_list_front];
+      _visitor->process(n);
+      Edge e;
+      for (_graph->firstOut(e, n); e != INVALID; _graph->nextOut(e)) {
+        Node m = _graph->target(e);
+        if (!(*_reached)[m]) {
+          _visitor->discover(e);
+          _visitor->reach(m);
+          _reached->set(m, true);
+          _list[++_list_back] = m;
+          reached = reached || nm[m];
+        } else {
+          _visitor->examine(e);
+        }
+      }
+      return n;
+    }
+
+    /// \brief Next node to be processed.
+    ///
+    /// Next node to be processed.
+    ///
+    /// \return The next node to be processed or INVALID if the stack is
+    /// empty.
+    Node nextNode() { 
+      return _list_front != _list_back ? _list[_list_front + 1] : INVALID;
+    }
+
+    /// \brief Returns \c false if there are nodes
+    /// to be processed in the queue
+    ///
+    /// Returns \c false if there are nodes
+    /// to be processed in the queue
+    bool emptyQueue() { return _list_front == _list_back; }
+
+    /// \brief Returns the number of the nodes to be processed.
+    ///
+    /// Returns the number of the nodes to be processed in the queue.
+    int queueSize() { return _list_back - _list_front; }
+    
+    /// \brief Executes the algorithm.
+    ///
+    /// Executes the algorithm.
+    ///
+    /// \pre init() must be called and at least one node should be added
+    /// with addSource() before using this function.
+    void start() {
+      while ( !emptyQueue() ) processNextNode();
+    }
+    
+    /// \brief Executes the algorithm until \c dest will be next processed.
+    ///
+    /// Executes the algorithm until \c dest will be next processed.
+    ///
+    /// \pre init() must be called and at least one node should be added
+    /// with addSource() before using this function.
+    void start(Node dest) {
+      bool reached = false;
+      while (!emptyQueue() && !reached) { 
+	processNextNode(dest, reached);
+      }
+    }
+    
+    /// \brief Executes the algorithm until a condition is met.
+    ///
+    /// Executes the algorithm until a condition is met.
+    ///
+    /// \pre init() must be called and at least one node should be added
+    /// with addSource() before using this function.
+    ///
+    ///\param nm must be a bool (or convertible) node map. The
+    ///algorithm will stop when it reaches a node \c v with
+    ///<tt>nm[v]</tt> true.
+    template <typename NM>
+    void start(const NM &nm) {
+      bool reached = false;
+      while (!emptyQueue() && !reached) {
+        processNextNode(nm, reached);
+      }
+    }
+
+    /// \brief Runs %BFSVisit algorithm from node \c s.
+    ///
+    /// This method runs the %BFS algorithm from a root node \c s.
+    /// \note b.run(s) is just a shortcut of the following code.
+    ///\code
+    ///   b.init();
+    ///   b.addSource(s);
+    ///   b.start();
+    ///\endcode
+    void run(Node s) {
+      init();
+      addSource(s);
+      start();
+    }
+
+    /// \brief Runs %BFSVisit algorithm to visit all nodes in the graph.
+    ///    
+    /// This method runs the %BFS algorithm in order to
+    /// compute the %BFS path to each node. The algorithm computes
+    /// - The %BFS tree.
+    /// - The distance of each node from the root in the %BFS tree.
+    ///
+    ///\note b.run() is just a shortcut of the following code.
+    ///\code
+    ///  b.init();
+    ///  for (NodeIt it(graph); it != INVALID; ++it) {
+    ///    if (!b.reached(it)) {
+    ///      b.addSource(it);
+    ///      b.start();
+    ///    }
+    ///  }
+    ///\endcode
+    void run() {
+      init();
+      for (NodeIt it(*_graph); it != INVALID; ++it) {
+        if (!reached(it)) {
+          addSource(it);
+          start();
+        }
+      }
+    }
+    ///@}
+
+    /// \name Query Functions
+    /// The result of the %BFS algorithm can be obtained using these
+    /// functions.\n
+    /// Before the use of these functions,
+    /// either run() or start() must be called.
+    ///@{
+
+    /// \brief Checks if a node is reachable from the root.
+    ///
+    /// Returns \c true if \c v is reachable from the root(s).
+    /// \warning The source nodes are inditated as unreachable.
+    /// \pre Either \ref run() or \ref start()
+    /// must be called before using this function.
+    ///
+    bool reached(Node v) { return (*_reached)[v]; }
+    ///@}
+  };
+
 } //END OF NAMESPACE LEMON
 
 #endif

Modified: hugo/trunk/lemon/topology.h
==============================================================================
--- hugo/trunk/lemon/topology.h	(original)
+++ hugo/trunk/lemon/topology.h	Tue Nov 21 19:22:08 2006
@@ -1389,6 +1389,64 @@
     return true;
   }
 
+  namespace _topology_bits {
+
+    template <typename Graph>
+    class BipartiteVisitor : public BfsVisitor<Graph> {
+    public:
+      typedef typename Graph::Edge Edge;
+      typedef typename Graph::Node Node;
+
+      BipartiteVisitor(const Graph& graph, bool& bipartite) 
+        : _graph(graph), _part(graph), _bipartite(bipartite) {}
+      
+      void start(const Node& node) {
+        _part[node] = true;
+      }
+      void discover(const Edge& edge) {
+        _part.set(_graph.target(edge), !_part[_graph.source(edge)]);
+      }
+      void examine(const Edge& edge) {
+        _bipartite = _bipartite && 
+          _part[_graph.target(edge)] != _part[_graph.source(edge)];
+      }
+
+    private:
+
+      const Graph& _graph;
+      typename Graph::template NodeMap<bool> _part;
+      bool& _bipartite;
+    };
+
+    template <typename Graph, typename PartMap>
+    class BipartitePartitionsVisitor : public BfsVisitor<Graph> {
+    public:
+      typedef typename Graph::Edge Edge;
+      typedef typename Graph::Node Node;
+
+      BipartitePartitionsVisitor(const Graph& graph, 
+                                 PartMap& part, bool& bipartite) 
+        : _graph(graph), _part(part), _bipartite(bipartite) {}
+      
+      void start(const Node& node) {
+        _part.set(node, true);
+      }
+      void discover(const Edge& edge) {
+        _part.set(_graph.target(edge), !_part[_graph.source(edge)]);
+      }
+      void examine(const Edge& edge) {
+        _bipartite = _bipartite && 
+          _part[_graph.target(edge)] != _part[_graph.source(edge)];
+      }
+
+    private:
+
+      const Graph& _graph;
+      PartMap& _part;
+      bool& _bipartite;
+    };
+  }
+
   /// \ingroup topology
   ///
   /// \brief Check if the given undirected graph is bipartite or not
@@ -1402,21 +1460,29 @@
   /// \author Balazs Attila Mihaly  
   template<typename UGraph>
   inline bool bipartite(const UGraph &graph){
+    using namespace _topology_bits;
+
     checkConcept<concepts::UGraph, UGraph>();
     
     typedef typename UGraph::NodeIt NodeIt;
     typedef typename UGraph::EdgeIt EdgeIt;
     
-    Bfs<UGraph> bfs(graph);
+    bool bipartite = true;
+
+    BipartiteVisitor<UGraph> 
+      visitor(graph, bipartite);
+    BfsVisit<UGraph, BipartiteVisitor<UGraph> > 
+      bfs(graph, visitor);
     bfs.init();
-    for(NodeIt i(graph);i!=INVALID;++i){
-      if(!bfs.reached(i)){
-	bfs.run(i);
+    for(NodeIt it(graph); it != INVALID; ++it) {
+      if(!bfs.reached(it)){
+	bfs.addSource(it);
+        while (!bfs.emptyQueue()) {
+          bfs.processNextNode();
+          if (!bipartite) return false;
+        }
       }
     }
-    for(EdgeIt i(graph);i!=INVALID;++i){
-      if(bfs.dist(graph.source(i))==bfs.dist(graph.target(i)))return false;
-    }
     return true;
   }
   
@@ -1439,25 +1505,80 @@
   /// \image latex bipartite_partitions.eps "Bipartite partititions" width=\textwidth
   template<typename UGraph, typename NodeMap>
   inline bool bipartitePartitions(const UGraph &graph, NodeMap &partMap){
+    using namespace _topology_bits;
+
     checkConcept<concepts::UGraph, UGraph>();
     
     typedef typename UGraph::Node Node;
     typedef typename UGraph::NodeIt NodeIt;
     typedef typename UGraph::EdgeIt EdgeIt;
-  
-    Bfs<UGraph> bfs(graph);
+
+    bool bipartite = true;
+
+    BipartitePartitionsVisitor<UGraph, NodeMap> 
+      visitor(graph, partMap, bipartite);
+    BfsVisit<UGraph, BipartitePartitionsVisitor<UGraph, NodeMap> > 
+      bfs(graph, visitor);
     bfs.init();
-    for(NodeIt i(graph);i!=INVALID;++i){
-      if(!bfs.reached(i)){
-	bfs.addSource(i);
-	for(Node j=bfs.processNextNode();!bfs.emptyQueue();
-	    j=bfs.processNextNode()){
-	  partMap.set(j,bfs.dist(j)%2==0);
-	}
+    for(NodeIt it(graph); it != INVALID; ++it) {
+      if(!bfs.reached(it)){
+	bfs.addSource(it);
+        while (!bfs.emptyQueue()) {
+          bfs.processNextNode();
+          if (!bipartite) return false;
+        }
+      }
+    }
+    return true;
+  }
+
+  /// \brief Returns true when there is not loop edge in the graph.
+  ///
+  /// Returns true when there is not loop edge in the graph.
+  template <typename Graph>
+  bool loopFree(const Graph& graph) {
+    for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
+      if (graph.source(it) == graph.target(it)) return false;
+    }
+    return true;
+  }
+
+  /// \brief Returns true when there is not parallel edges in the graph.
+  ///
+  /// Returns true when there is not parallel edges in the graph.
+  template <typename Graph>
+  bool parallelFree(const Graph& graph) {
+    typename Graph::template NodeMap<bool> reached(graph, false);
+    for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
+      for (typename Graph::OutEdgeIt e(graph, n); e != INVALID; ++e) {
+        if (reached[graph.target(e)]) return false;
+        reached.set(graph.target(e), true);
+      }
+      for (typename Graph::OutEdgeIt e(graph, n); e != INVALID; ++e) {
+        reached.set(graph.target(e), false);
       }
     }
-    for(EdgeIt i(graph);i!=INVALID;++i){
-      if(bfs.dist(graph.source(i)) == bfs.dist(graph.target(i)))return false;
+    return true;
+  }
+
+  /// \brief Returns true when there is not loop edge and parallel
+  /// edges in the graph.
+  ///
+  /// Returns true when there is not loop edge and parallel edges in
+  /// the graph.
+  template <typename Graph>
+  bool simpleGraph(const Graph& graph) {
+    typename Graph::template NodeMap<bool> reached(graph, false);
+    for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
+      reached.set(n, true);
+      for (typename Graph::OutEdgeIt e(graph, n); e != INVALID; ++e) {
+        if (reached[graph.target(e)]) return false;
+        reached.set(graph.target(e), true);
+      }
+      for (typename Graph::OutEdgeIt e(graph, n); e != INVALID; ++e) {
+        reached.set(graph.target(e), false);
+      }
+      reached.set(n, false);
     }
     return true;
   }



More information about the Lemon-commits mailing list