[Lemon-commits] deba: r3301 - in lemon/trunk: lemon test

Lemon SVN svn at lemon.cs.elte.hu
Sat Aug 11 18:34:43 CEST 2007


Author: deba
Date: Sat Aug 11 18:34:41 2007
New Revision: 3301

Added:
   lemon/trunk/lemon/pr_bipartite_matching.h
      - copied, changed from r3300, /lemon/trunk/lemon/bp_matching.h
Removed:
   lemon/trunk/lemon/bp_matching.h
Modified:
   lemon/trunk/lemon/Makefile.am
   lemon/trunk/lemon/bipartite_matching.h
   lemon/trunk/test/bipartite_matching_test.cc

Log:
Common interface for bipartite matchings
Some useful query function for push-relabel based matching

The naming should be rethink for these classes
for example: pr-ap prefix for push-relabel and augmenting path 
algorithms



Modified: lemon/trunk/lemon/Makefile.am
==============================================================================
--- lemon/trunk/lemon/Makefile.am	(original)
+++ lemon/trunk/lemon/Makefile.am	Sat Aug 11 18:34:41 2007
@@ -39,7 +39,6 @@
 	lemon/bfs.h \
 	lemon/bin_heap.h \
 	lemon/bipartite_matching.h \
-	lemon/bp_matching.h \
 	lemon/bpugraph_adaptor.h \
 	lemon/bucket_heap.h \
 	lemon/capacity_scaling.h \
@@ -103,6 +102,7 @@
 	lemon/polynomial.h \
 	lemon/preflow.h \
 	lemon/prim.h \
+	lemon/pr_bipartite_matching.h \
 	lemon/radix_heap.h \
 	lemon/radix_sort.h \
 	lemon/random.h \

Modified: lemon/trunk/lemon/bipartite_matching.h
==============================================================================
--- lemon/trunk/lemon/bipartite_matching.h	(original)
+++ lemon/trunk/lemon/bipartite_matching.h	Sat Aug 11 18:34:41 2007
@@ -29,6 +29,9 @@
 ///\ingroup matching
 ///\file
 ///\brief Maximum matching algorithms in bipartite graphs.
+///
+///\note The pr_bipartite_matching.h file also contains algorithms to
+///solve maximum cardinality bipartite matching problems.
 
 namespace lemon {
 
@@ -39,6 +42,11 @@
   /// Bipartite Max Cardinality Matching algorithm. This class implements
   /// the Hopcroft-Karp algorithm which has \f$ O(e\sqrt{n}) \f$ time
   /// complexity.
+  ///
+  /// \note In several cases the push-relabel based algorithms have
+  /// better runtime performance than the augmenting path based ones. 
+  ///
+  /// \see PrBipartiteMatching
   template <typename BpUGraph>
   class MaxBipartiteMatching {
   protected:
@@ -342,10 +350,64 @@
     
     ///@{
 
-    /// \brief Returns an minimum covering of the nodes.
+    /// \brief Set true all matching uedge in the map.
+    /// 
+    /// Set true all matching uedge in the map. It does not change the
+    /// value mapped to the other uedges.
+    /// \return The number of the matching edges.
+    template <typename MatchingMap>
+    int quickMatching(MatchingMap& mm) const {
+      for (ANodeIt it(*graph); it != INVALID; ++it) {
+        if (anode_matching[it] != INVALID) {
+          mm[anode_matching[it]] = true;
+        }
+      }
+      return matching_size;
+    }
+
+    /// \brief Set true all matching uedge in the map and the others to false.
+    /// 
+    /// Set true all matching uedge in the map and the others to false.
+    /// \return The number of the matching edges.
+    template <typename MatchingMap>
+    int matching(MatchingMap& mm) const {
+      for (UEdgeIt it(*graph); it != INVALID; ++it) {
+        mm[it] = it == anode_matching[graph->aNode(it)];
+      }
+      return matching_size;
+    }
+
+
+    /// \brief Return true if the given uedge is in the matching.
+    /// 
+    /// It returns true if the given uedge is in the matching.
+    bool matchingEdge(const UEdge& edge) const {
+      return anode_matching[graph->aNode(edge)] == edge;
+    }
+
+    /// \brief Returns the matching edge from the node.
+    /// 
+    /// Returns the matching edge from the node. If there is not such
+    /// edge it gives back \c INVALID.
+    UEdge matchingEdge(const Node& node) const {
+      if (graph->aNode(node)) {
+        return anode_matching[node];
+      } else {
+        return bnode_matching[node];
+      }
+    }
+
+    /// \brief Gives back the number of the matching edges.
+    ///
+    /// Gives back the number of the matching edges.
+    int matchingSize() const {
+      return matching_size;
+    }
+
+    /// \brief Returns a minimum covering of the nodes.
     ///
     /// The minimum covering set problem is the dual solution of the
-    /// maximum bipartite matching. It provides an solution for this
+    /// maximum bipartite matching. It provides a solution for this
     /// problem what is proof of the optimality of the matching.
     /// \return The size of the cover set.
     template <typename CoverMap>
@@ -397,58 +459,92 @@
       return size;
     }
 
-    /// \brief Set true all matching uedge in the map.
-    /// 
-    /// Set true all matching uedge in the map. It does not change the
-    /// value mapped to the other uedges.
-    /// \return The number of the matching edges.
-    template <typename MatchingMap>
-    int quickMatching(MatchingMap& mm) const {
+    /// \brief Gives back a barrier on the A-nodes
+    
+    /// The barrier is s subset of the nodes on the same side of the
+    /// graph, which size minus its neighbours is exactly the
+    /// unmatched nodes on the A-side.  
+    /// \retval barrier A WriteMap on the ANodes with bool value.
+    template <typename BarrierMap>
+    void aBarrier(BarrierMap& barrier) const {
+
+      typename Graph::template ANodeMap<bool> areached(*graph, false);
+      typename Graph::template BNodeMap<bool> breached(*graph, false);
+      
+      std::vector<Node> queue;
       for (ANodeIt it(*graph); it != INVALID; ++it) {
-        if (anode_matching[it] != INVALID) {
-          mm[anode_matching[it]] = true;
+        if (anode_matching[it] == INVALID) {
+          queue.push_back(it);
         }
       }
-      return matching_size;
-    }
 
-    /// \brief Set true all matching uedge in the map and the others to false.
-    /// 
-    /// Set true all matching uedge in the map and the others to false.
-    /// \return The number of the matching edges.
-    template <typename MatchingMap>
-    int matching(MatchingMap& mm) const {
-      for (UEdgeIt it(*graph); it != INVALID; ++it) {
-        mm[it] = it == anode_matching[graph->aNode(it)];
+      while (!queue.empty()) {
+        std::vector<Node> newqueue;
+        for (int i = 0; i < int(queue.size()); ++i) {
+          Node anode = queue[i];
+          for (IncEdgeIt jt(*graph, anode); jt != INVALID; ++jt) {
+            Node bnode = graph->bNode(jt);
+            if (breached[bnode]) continue;
+            breached[bnode] = true;
+            if (bnode_matching[bnode] != INVALID) {
+              Node newanode = graph->aNode(bnode_matching[bnode]);
+              if (!areached[newanode]) {
+                areached[newanode] = true;
+                newqueue.push_back(newanode);
+              }
+            }
+          }
+        }
+        queue.swap(newqueue);
+      }
+
+      for (ANodeIt it(*graph); it != INVALID; ++it) {
+        barrier[it] = areached[it] || anode_matching[it] == INVALID;
       }
-      return matching_size;
     }
 
+    /// \brief Gives back a barrier on the B-nodes
+    
+    /// The barrier is s subset of the nodes on the same side of the
+    /// graph, which size minus its neighbours is exactly the
+    /// unmatched nodes on the B-side.  
+    /// \retval barrier A WriteMap on the BNodes with bool value.
+    template <typename BarrierMap>
+    void bBarrier(BarrierMap& barrier) const {
 
-    /// \brief Return true if the given uedge is in the matching.
-    /// 
-    /// It returns true if the given uedge is in the matching.
-    bool matchingEdge(const UEdge& edge) const {
-      return anode_matching[graph->aNode(edge)] == edge;
-    }
+      typename Graph::template ANodeMap<bool> areached(*graph, false);
+      typename Graph::template BNodeMap<bool> breached(*graph, false);
+      
+      std::vector<Node> queue;
+      for (ANodeIt it(*graph); it != INVALID; ++it) {
+        if (anode_matching[it] == INVALID) {
+          queue.push_back(it);
+        }
+      }
 
-    /// \brief Returns the matching edge from the node.
-    /// 
-    /// Returns the matching edge from the node. If there is not such
-    /// edge it gives back \c INVALID.
-    UEdge matchingEdge(const Node& node) const {
-      if (graph->aNode(node)) {
-        return anode_matching[node];
-      } else {
-        return bnode_matching[node];
+      while (!queue.empty()) {
+        std::vector<Node> newqueue;
+        for (int i = 0; i < int(queue.size()); ++i) {
+          Node anode = queue[i];
+          for (IncEdgeIt jt(*graph, anode); jt != INVALID; ++jt) {
+            Node bnode = graph->bNode(jt);
+            if (breached[bnode]) continue;
+            breached[bnode] = true;
+            if (bnode_matching[bnode] != INVALID) {
+              Node newanode = graph->aNode(bnode_matching[bnode]);
+              if (!areached[newanode]) {
+                areached[newanode] = true;
+                newqueue.push_back(newanode);
+              }
+            }
+          }
+        }
+        queue.swap(newqueue);
       }
-    }
 
-    /// \brief Gives back the number of the matching edges.
-    ///
-    /// Gives back the number of the matching edges.
-    int matchingSize() const {
-      return matching_size;
+      for (BNodeIt it(*graph); it != INVALID; ++it) {
+        barrier[it] = !breached[it];
+      }
     }
 
     /// @}

Copied: lemon/trunk/lemon/pr_bipartite_matching.h (from r3300, /lemon/trunk/lemon/bp_matching.h)
==============================================================================
--- /lemon/trunk/lemon/bp_matching.h	(original)
+++ lemon/trunk/lemon/pr_bipartite_matching.h	Sat Aug 11 18:34:41 2007
@@ -16,66 +16,86 @@
  *
  */
 
-#ifndef LEMON_BP_MATCHING
-#define LEMON_BP_MATCHING
+#ifndef LEMON_PR_BIPARTITE_MATCHING
+#define LEMON_PR_BIPARTITE_MATCHING
 
 #include <lemon/graph_utils.h>
 #include <lemon/iterable_maps.h>
 #include <iostream>
 #include <queue>
-#include <lemon/counter.h>
 #include <lemon/elevator.h>
 
 ///\ingroup matching
 ///\file
 ///\brief Push-prelabel maximum matching algorithms in bipartite graphs.
 ///
-///\todo This file slightly conflicts with \ref lemon/bipartite_matching.h
-///\todo (Re)move the XYZ_TYPEDEFS macros
 namespace lemon {
 
-#define BIPARTITE_TYPEDEFS(Graph)		\
-  GRAPH_TYPEDEFS(Graph)				\
-    typedef Graph::ANodeIt ANodeIt;	\
-    typedef Graph::BNodeIt BNodeIt;
-
-#define UNDIRBIPARTITE_TYPEDEFS(Graph)		\
-  UNDIRGRAPH_TYPEDEFS(Graph)			\
-    typedef Graph::ANodeIt ANodeIt;	\
-    typedef Graph::BNodeIt BNodeIt;
-
-  template<class Graph,
-	   class MT=typename Graph::template ANodeMap<typename Graph::UEdge> >
-  class BpMatching {
+  ///Max cardinality matching algorithm based on push-relabel principle
+
+  ///\ingroup matching
+  ///Bipartite Max Cardinality Matching algorithm. This class uses the
+  ///push-relabel principle which in several cases has better runtime
+  ///performance than the augmenting path solutions.
+  ///
+  ///\author Alpar Juttner
+  template<class Graph>
+  class PrBipartiteMatching {
     typedef typename Graph::Node Node;
     typedef typename Graph::ANodeIt ANodeIt;
     typedef typename Graph::BNodeIt BNodeIt;
     typedef typename Graph::UEdge UEdge;
+    typedef typename Graph::UEdgeIt UEdgeIt;
     typedef typename Graph::IncEdgeIt IncEdgeIt;
     
     const Graph &_g;
     int _node_num;
-    MT &_matching;
+    int _matching_size;
+    int _empty_level;
+    
+    typename Graph::template ANodeMap<typename Graph::UEdge> _matching;
     Elevator<Graph,typename Graph::BNode> _levels;
     typename Graph::template BNodeMap<int> _cov;
 
   public:
-    BpMatching(const Graph &g, MT &matching) :
+
+    PrBipartiteMatching(const Graph &g) :
       _g(g),
       _node_num(countBNodes(g)),
-      _matching(matching),
+      _matching(g),
       _levels(g,_node_num),
       _cov(g,0)
     {
     }
     
-  private:
-    void init() 
-    {
-//     for(BNodeIt n(g);n!=INVALID;++n) cov[n]=0;
+    /// \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() and then one variant of the start()
+    /// member. 
+
+    /// @{
+
+    ///Initialize the data structures
+
+    ///This function constructs a prematching first, which is a
+    ///regular matching on the A-side of the graph, but on the B-side
+    ///each node could cover more matching edges. After that, the
+    ///B-nodes which multiple matched, will be pushed into the lowest
+    ///level of the Elevator. The remaning B-nodes will be pushed to
+    ///the consequent levels respect to a Bfs on following graph: the
+    ///nodes are the B-nodes of the original bipartite graph and two
+    ///nodes are adjacent if a node can pass over a matching edge to
+    ///an other node. The source of the Bfs are the lowest level
+    ///nodes. Last, the reached B-nodes without covered matching edge
+    ///becomes active.
+    void init() {
+      _matching_size=0;
+      _empty_level=_node_num;
       for(ANodeIt n(_g);n!=INVALID;++n)
 	if((_matching[n]=IncEdgeIt(_g,n))!=INVALID)
-	  ++_cov[_g.oppositeNode(n,_matching[n])];
+	  ++_cov[_g.bNode(_matching[n])];
 
       std::queue<Node> q;
       _levels.initStart();
@@ -109,17 +129,32 @@
 	if(_cov[n]<1&&_levels[n]<_node_num)
 	  _levels.activate(n);
     }
-  public:
-    int run() 
-    {
-      init();
 
+    ///Start the main phase of the algorithm
+    
+    ///This algorithm calculates the maximum matching with the
+    ///push-relabel principle. This function should be called just
+    ///after the init() function which already set the initial
+    ///prematching, the level function on the B-nodes and the active,
+    ///ie. unmatched B-nodes.
+    ///
+    ///The algorithm always takes highest active B-node, and it try to
+    ///find a B-node which is eligible to pass over one of it's
+    ///matching edge. This condition holds when the B-node is one
+    ///level lower, and the opposite node of it's matching edge is
+    ///adjacent to the highest active node. In this case the current
+    ///node steals the matching edge and becomes inactive. If there is
+    ///not eligible node then the highest active node should be lift
+    ///to the next proper level.
+    ///
+    ///The nodes should not lift higher than the number of the
+    ///B-nodes, if a node reach this level it remains unmatched. If
+    ///during the execution one level becomes empty the nodes above it
+    ///can be deactivated and lift to the highest level.
+    void start() {
       Node act;
       Node bact=INVALID;
       Node last_activated=INVALID;
-//       while((act=last_activated!=INVALID?
-// 	     last_activated:_levels.highestActive())
-// 	    !=INVALID)
       while((act=_levels.highestActive())!=INVALID) {
 	last_activated=INVALID;
 	int actlevel=_levels[act];
@@ -141,7 +176,6 @@
 	if(nlevel<_node_num) {
 	  if(nlevel>=actlevel)
 	    _levels.liftHighestActiveTo(nlevel+1);
-// 	    _levels.liftTo(act,nlevel+1);
 	  bact=_g.bNode(_matching[_g.aNode(bedge)]);
 	  if(--_cov[bact]<1) {
 	    _levels.activate(bact);
@@ -154,7 +188,6 @@
 	else {
 	  if(_node_num>actlevel) 
 	    _levels.liftHighestActiveTo(_node_num);
-//  	    _levels.liftTo(act,_node_num);
 	  _levels.deactivate(act); 
 	}
 
@@ -162,23 +195,29 @@
 	  _levels.liftToTop(actlevel);
       }
       
-      int ret=_node_num;
+      _matching_size = _node_num;
       for(ANodeIt n(_g);n!=INVALID;++n)
-	if(_matching[n]==INVALID) ret--;
+	if(_matching[n]==INVALID) _matching_size--;
 	else if (_cov[_g.bNode(_matching[n])]>1) {
 	  _cov[_g.bNode(_matching[n])]--;
-	  ret--;
+	  _matching_size--;
 	  _matching[n]=INVALID;
 	}
-      return ret;
     }
-    
-    ///\returns -1 if there is a perfect matching, or an empty level
-    ///if it doesn't exists
-    int runPerfect() 
-    {
-      init();
 
+    ///Start the algorithm to find a perfect matching
+
+    ///This function is close to identical to the simple start()
+    ///member function but it calculates just perfect matching.
+    ///However, the perfect property is only checked on the B-side of
+    ///the graph
+    ///
+    ///The main difference between the two function is the handling of
+    ///the empty levels. The simple start() function let the nodes
+    ///above the empty levels unmatched while this variant if it find
+    ///an empty level immediately terminates and gives back false
+    ///return value.
+    bool startPerfect() {
       Node act;
       Node bact=INVALID;
       Node last_activated=INVALID;
@@ -219,28 +258,179 @@
 	}
 
 	if(_levels.onLevel(actlevel)==0)
-	  return actlevel;
+	  _empty_level=actlevel;
+	  return false;
+      }
+      return true;
+    }
+  
+    ///Runs the algorithm
+    
+    ///Just a shortcut for the next code:
+    ///\code
+    /// init();
+    /// start();
+    ///\endcode
+    void run() {
+      init();
+      start();
+    }
+    
+    ///Runs the algorithm to find a perfect matching
+    
+    ///Just a shortcut for the next code:
+    ///\code
+    /// init();
+    /// startPerfect();
+    ///\endcode
+    ///
+    ///\note If the two nodesets of the graph have different size then
+    ///this algorithm checks the perfect property on the B-side.
+    bool runPerfect() {
+      init();
+      return startPerfect();
+    }
+
+    ///Runs the algorithm to find a perfect matching
+    
+    ///Just a shortcut for the next code:
+    ///\code
+    /// init();
+    /// startPerfect();
+    ///\endcode
+    ///
+    ///\note It checks that the size of the two nodesets are equal.
+    bool checkedRunPerfect() {
+      if (countANodes(_g) != _node_num) return false;
+      init();
+      return startPerfect();
+    }
+
+    ///@}
+
+    /// \name Query Functions
+    /// The result of the %Matching algorithm can be obtained using these
+    /// functions.\n
+    /// Before the use of these functions,
+    /// either run() or start() must be called.
+    ///@{
+
+    /// \brief Set true all matching uedge in the map.
+    /// 
+    /// Set true all matching uedge in the map. It does not change the
+    /// value mapped to the other uedges.
+    /// \return The number of the matching edges.
+    template <typename MatchingMap>
+    int quickMatching(MatchingMap& mm) const {
+      for (ANodeIt n(_g);n!=INVALID;++n) {
+        if (_matching[n]!=INVALID) mm.set(_matching[n],true);
+      }
+      return _matching_size;
+    }
+
+    ///\brief Set true all matching uedge in the map and the others to false.
+
+    ///Set true all matching uedge in the map and the others to false.
+    ///\return The number of the matching edges.
+    template<class MatchingMap>
+    int matching(MatchingMap& mm) const {
+      for (UEdgeIt e(_g);e!=INVALID;++e) {
+        mm.set(e,e==_matching[_g.aNode(e)]);
       }
-      return -1;
+      return _matching_size;
     }
- 
-    template<class GT>
-    void aBarrier(GT &bar,int empty_level=-1) 
+
+
+    ///Returns true if the given uedge is in the matching.
+
+    ///It returns true if the given uedge is in the matching.
+    ///
+    bool matchingEdge(const UEdge& e) const {
+      return _matching[_g.aNode(e)]==e;
+    }
+
+    ///Returns the matching edge from the node.
+
+    ///Returns the matching edge from the node. If there is not such
+    ///edge it gives back \c INVALID.  
+    ///\note If the parameter node is a B-node then the running time is
+    ///propotional to the degree of the node.
+    UEdge matchingEdge(const Node& n) const {
+      if (_g.aNode(n)) {
+        return _matching[n];
+      } else {
+	for (IncEdgeIt e(_g,n);e!=INVALID;++e)
+	  if (e==_matching[_g.aNode(e)]) return e;
+	return INVALID;
+      }
+    }
+
+    ///Gives back the number of the matching edges.
+
+    ///Gives back the number of the matching edges.
+    int matchingSize() const {
+      return _matching_size;
+    }
+
+    ///Gives back a barrier on the A-nodes
+    
+    ///The barrier is s subset of the nodes on the same side of the
+    ///graph. If we tried to find a perfect matching and it failed
+    ///then the barrier size will be greater than its neighbours. If
+    ///the maximum matching searched then the barrier size minus its
+    ///neighbours will be exactly the unmatched nodes on the A-side.
+    ///\retval bar A WriteMap on the ANodes with bool value.
+    template<class BarrierMap>
+    void aBarrier(BarrierMap &bar) const 
     {
-      if(empty_level==-1)
-	for(empty_level=0;_levels.onLevel(empty_level);empty_level++) ;
       for(ANodeIt n(_g);n!=INVALID;++n)
-	bar[n] = _matching[n]==INVALID ||
-	  _levels[_g.bNode(_matching[n])]<empty_level;  
+	bar.set(n,_matching[n]==INVALID ||
+	  _levels[_g.bNode(_matching[n])]<_empty_level);  
     }  
-    template<class GT>
-    void bBarrier(GT &bar, int empty_level=-1) 
+
+    ///Gives back a barrier on the B-nodes
+    
+    ///The barrier is s subset of the nodes on the same side of the
+    ///graph. If we tried to find a perfect matching and it failed
+    ///then the barrier size will be greater than its neighbours. If
+    ///the maximum matching searched then the barrier size minus its
+    ///neighbours will be exactly the unmatched nodes on the B-side.
+    ///\retval bar A WriteMap on the BNodes with bool value.
+    template<class BarrierMap>
+    void bBarrier(BarrierMap &bar) const
     {
-      if(empty_level==-1)
-	for(empty_level=0;_levels.onLevel(empty_level);empty_level++) ;
-      for(BNodeIt n(_g);n!=INVALID;++n) bar[n]=(_levels[n]>empty_level);  
-    }  
-  
+      for(BNodeIt n(_g);n!=INVALID;++n) bar.set(n,_levels[n]>=_empty_level);  
+    }
+
+    ///Returns a minimum covering of the nodes.
+
+    ///The minimum covering set problem is the dual solution of the
+    ///maximum bipartite matching. It provides a solution for this
+    ///problem what is proof of the optimality of the matching.
+    ///\param covering NodeMap of bool values, the nodes of the cover
+    ///set will set true while the others false.  
+    ///\return The size of the cover set.
+    ///\note This function can be called just after the algorithm have
+    ///already found a matching. 
+    template<class CoverMap>
+    int coverSet(CoverMap& covering) const {
+      int ret=0;
+      for(BNodeIt n(_g);n!=INVALID;++n) {
+	if (_levels[n]<_empty_level) { covering.set(n,true); ++ret; }
+	else covering.set(n,false);
+      }
+      for(ANodeIt n(_g);n!=INVALID;++n) {
+	if (_matching[n]!=INVALID &&
+	    _levels[_g.bNode(_matching[n])]>=_empty_level) 
+	  { covering.set(n,true); ++ret; }
+	else covering.set(n,false);
+      }
+      return ret;
+    }
+
+
+    /// @}
+    
   };
   
   
@@ -255,10 +445,10 @@
   ///\note The the implementation is based
   ///on the push-relabel principle.
   template<class Graph>
-  int maxBpMatching(const Graph &g)
+  int prBipartiteMatching(const Graph &g)
   {
-    typename Graph::template ANodeMap<typename Graph::UEdge> matching(g);
-    return maxBpMatching(g,matching);
+    PrBipartiteMatching<Graph> bpm(g);
+    return bpm.matchingSize();
   }
 
   ///Maximum cardinality matching in a bipartite graph
@@ -267,19 +457,19 @@
   ///This function finds a maximum cardinality matching
   ///in a bipartite graph \c g.
   ///\param g An undirected bipartite graph.
-  ///\retval matching A readwrite ANodeMap of value type \c Edge.
-  /// The found edges will be returned in this map,
-  /// i.e. for an \c ANode \c n,
-  /// the edge <tt>matching[n]</tt> is the one that covers the node \c n, or
-  /// \ref INVALID if it is uncovered.
+  ///\retval matching A write UEdgeMap of value type \c bool.
+  /// The found edges will be returned in this map.
   ///\return The cardinality of the maximum matching.
   ///
   ///\note The the implementation is based
   ///on the push-relabel principle.
   template<class Graph,class MT>
-  int maxBpMatching(const Graph &g,MT &matching) 
+  int prBipartiteMatching(const Graph &g,MT &matching) 
   {
-    return BpMatching<Graph,MT>(g,matching).run();
+    PrBipartiteMatching<Graph> bpm(g);
+    bpm.run();
+    bpm.matching(matching);
+    return bpm.matchingSize();
   }
 
   ///Maximum cardinality matching in a bipartite graph
@@ -288,11 +478,8 @@
   ///This function finds a maximum cardinality matching
   ///in a bipartite graph \c g.
   ///\param g An undirected bipartite graph.
-  ///\retval matching A readwrite ANodeMap of value type \c Edge.
-  /// The found edges will be returned in this map,
-  /// i.e. for an \c ANode \c n,
-  /// the edge <tt>matching[n]</tt> is the one that covers the node \c n, or
-  /// \ref INVALID if it is uncovered.
+  ///\retval matching A write UEdgeMap of value type \c bool.
+  /// The found edges will be returned in this map.
   ///\retval barrier A \c bool WriteMap on the BNodes. The map will be set
   /// exactly once for each BNode. The nodes with \c true value represent
   /// a barrier \e B, i.e. the cardinality of \e B minus the number of its
@@ -303,12 +490,13 @@
   ///\note The the implementation is based
   ///on the push-relabel principle.
   template<class Graph,class MT, class GT>
-  int maxBpMatching(const Graph &g,MT &matching,GT &barrier) 
+  int prBipartiteMatching(const Graph &g,MT &matching,GT &barrier) 
   {
-    BpMatching<Graph,MT> bpm(g,matching);
-    int ret=bpm.run();
-    bpm.barrier(barrier);
-    return ret;
+    PrBipartiteMatching<Graph> bpm(g);
+    bpm.run();
+    bpm.matching(matching);
+    bpm.bBarrier(barrier);
+    return bpm.matchingSize();
   }  
 
   ///Perfect matching in a bipartite graph
@@ -322,10 +510,10 @@
   ///\note The the implementation is based
   ///on the push-relabel principle.
   template<class Graph>
-  bool perfectBpMatching(const Graph &g)
+  bool prPerfectBipartiteMatching(const Graph &g)
   {
-    typename Graph::template ANodeMap<typename Graph::UEdge> matching(g);
-    return perfectBpMatching(g,matching);
+    PrBipartiteMatching<Graph> bpm(g);
+    return bpm.runPerfect();
   }
 
   ///Perfect matching in a bipartite graph
@@ -333,20 +521,21 @@
   ///\ingroup matching
   ///This function finds a perfect matching in a bipartite graph \c g.
   ///\param g An undirected bipartite graph.
-  ///\retval matching A readwrite ANodeMap of value type \c Edge.
-  /// The found edges will be returned in this map,
-  /// i.e. for an \c ANode \c n,
-  /// the edge <tt>matching[n]</tt> is the one that covers the node \c n.
-  /// The values are unspecified if the graph
+  ///\retval matching A write UEdgeMap of value type \c bool.
+  /// The found edges will be returned in this map.
+  /// The values are unchanged if the graph
   /// has no perfect matching.
   ///\return \c true iff \c g has a perfect matching.
   ///
   ///\note The the implementation is based
   ///on the push-relabel principle.
   template<class Graph,class MT>
-  bool perfectBpMatching(const Graph &g,MT &matching) 
+  bool prPerfectBipartiteMatching(const Graph &g,MT &matching) 
   {
-    return BpMatching<Graph,MT>(g,matching).runPerfect()<0;
+    PrBipartiteMatching<Graph> bpm(g);
+    bool ret = bpm.runPerfect();
+    if (ret) bpm.matching(matching);
+    return ret;
   }
 
   ///Perfect matching in a bipartite graph
@@ -354,29 +543,29 @@
   ///\ingroup matching
   ///This function finds a perfect matching in a bipartite graph \c g.
   ///\param g An undirected bipartite graph.
-  ///\retval matching A readwrite ANodeMap of value type \c Edge.
-  /// The found edges will be returned in this map,
-  /// i.e. for an \c ANode \c n,
-  /// the edge <tt>matching[n]</tt> is the one that covers the node \c n.
-  /// The values are unspecified if the graph
+  ///\retval matching A readwrite UEdgeMap of value type \c bool.
+  /// The found edges will be returned in this map.
+  /// The values are unchanged if the graph
   /// has no perfect matching.
   ///\retval barrier A \c bool WriteMap on the BNodes. The map will only
   /// be set if \c g has no perfect matching. In this case it is set 
   /// exactly once for each BNode. The nodes with \c true value represent
   /// a barrier, i.e. a subset \e B a of BNodes with the property that
-  /// the cardinality of \e B is greater than the numner of its neighbors.
+  /// the cardinality of \e B is greater than the number of its neighbors.
   ///\return \c true iff \c g has a perfect matching.
   ///
   ///\note The the implementation is based
   ///on the push-relabel principle.
   template<class Graph,class MT, class GT>
-  int perfectBpMatching(const Graph &g,MT &matching,GT &barrier) 
+  int prPerfectBipartiteMatching(const Graph &g,MT &matching,GT &barrier) 
   {
-    BpMatching<Graph,MT> bpm(g,matching);
-    int ret=bpm.run();
-    if(ret>=0)
-      bpm.barrier(barrier,ret);
-    return ret<0;
+    PrBipartiteMatching<Graph> bpm(g);
+    bool ret=bpm.runPerfect();
+    if(ret)
+      bpm.matching(matching);
+    else
+      bpm.bBarrier(barrier);
+    return ret;
   }  
 }
 

Modified: lemon/trunk/test/bipartite_matching_test.cc
==============================================================================
--- lemon/trunk/test/bipartite_matching_test.cc	(original)
+++ lemon/trunk/test/bipartite_matching_test.cc	Sat Aug 11 18:34:41 2007
@@ -24,6 +24,7 @@
 
 #include <lemon/bpugraph_adaptor.h>
 #include <lemon/bipartite_matching.h>
+#include <lemon/pr_bipartite_matching.h>
 
 #include <lemon/graph_utils.h>
 
@@ -111,6 +112,30 @@
   }
 
   {
+    PrBipartiteMatching<Graph> bpmatch(graph);
+
+    bpmatch.run();
+
+    Graph::UEdgeMap<bool> mm(graph);
+    Graph::NodeMap<bool> cs(graph);
+    
+    check(bpmatch.coverSet(cs) == bpmatch.matching(mm), "INVALID PRIMAL-DUAL");
+    
+    for (UEdgeIt it(graph); it != INVALID; ++it) {
+      check(cs[graph.aNode(it)] || cs[graph.bNode(it)], "INVALID DUAL");
+    }
+    
+    for (ANodeIt it(graph); it != INVALID; ++it) {
+      int num = 0;
+      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
+        if (mm[jt]) ++num;
+      }
+      check(num <= 1, "INVALID PRIMAL");
+    }
+    max_cardinality = bpmatch.matchingSize();
+  }
+
+  {
     Graph::UEdgeMap<bool> mm(graph);
 
     check(max_cardinality == maxBipartiteMatching(graph, mm),



More information about the Lemon-commits mailing list