lemon/pr_bipartite_matching.h
author deba
Tue, 21 Aug 2007 13:22:21 +0000
changeset 2463 19651a04d056
parent 2462 7a096a6bf53a
child 2466 feb7974cf4ec
permissions -rw-r--r--
Query functions: aMatching and bMatching
Modified algorithm function interfaces
ANodeMap<UEdge> matching map
BNodeMap<bool> barrier map

Consistency between augmenting path and push-relabel algorithm
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2007
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_PR_BIPARTITE_MATCHING
    20 #define LEMON_PR_BIPARTITE_MATCHING
    21 
    22 #include <lemon/graph_utils.h>
    23 #include <lemon/iterable_maps.h>
    24 #include <iostream>
    25 #include <queue>
    26 #include <lemon/elevator.h>
    27 
    28 ///\ingroup matching
    29 ///\file
    30 ///\brief Push-prelabel maximum matching algorithms in bipartite graphs.
    31 ///
    32 namespace lemon {
    33 
    34   ///Max cardinality matching algorithm based on push-relabel principle
    35 
    36   ///\ingroup matching
    37   ///Bipartite Max Cardinality Matching algorithm. This class uses the
    38   ///push-relabel principle which in several cases has better runtime
    39   ///performance than the augmenting path solutions.
    40   ///
    41   ///\author Alpar Juttner
    42   template<class Graph>
    43   class PrBipartiteMatching {
    44     typedef typename Graph::Node Node;
    45     typedef typename Graph::ANodeIt ANodeIt;
    46     typedef typename Graph::BNodeIt BNodeIt;
    47     typedef typename Graph::UEdge UEdge;
    48     typedef typename Graph::UEdgeIt UEdgeIt;
    49     typedef typename Graph::IncEdgeIt IncEdgeIt;
    50     
    51     const Graph &_g;
    52     int _node_num;
    53     int _matching_size;
    54     int _empty_level;
    55     
    56     typename Graph::template ANodeMap<typename Graph::UEdge> _matching;
    57     Elevator<Graph,typename Graph::BNode> _levels;
    58     typename Graph::template BNodeMap<int> _cov;
    59 
    60   public:
    61 
    62     PrBipartiteMatching(const Graph &g) :
    63       _g(g),
    64       _node_num(countBNodes(g)),
    65       _matching(g),
    66       _levels(g,_node_num),
    67       _cov(g,0)
    68     {
    69     }
    70     
    71     /// \name Execution control 
    72     /// The simplest way to execute the algorithm is to use one of the
    73     /// member functions called \c run(). \n
    74     /// If you need more control on the execution, first
    75     /// you must call \ref init() and then one variant of the start()
    76     /// member. 
    77 
    78     /// @{
    79 
    80     ///Initialize the data structures
    81 
    82     ///This function constructs a prematching first, which is a
    83     ///regular matching on the A-side of the graph, but on the B-side
    84     ///each node could cover more matching edges. After that, the
    85     ///B-nodes which multiple matched, will be pushed into the lowest
    86     ///level of the Elevator. The remaning B-nodes will be pushed to
    87     ///the consequent levels respect to a Bfs on following graph: the
    88     ///nodes are the B-nodes of the original bipartite graph and two
    89     ///nodes are adjacent if a node can pass over a matching edge to
    90     ///an other node. The source of the Bfs are the lowest level
    91     ///nodes. Last, the reached B-nodes without covered matching edge
    92     ///becomes active.
    93     void init() {
    94       _matching_size=0;
    95       _empty_level=_node_num;
    96       for(ANodeIt n(_g);n!=INVALID;++n)
    97 	if((_matching[n]=IncEdgeIt(_g,n))!=INVALID)
    98 	  ++_cov[_g.bNode(_matching[n])];
    99 
   100       std::queue<Node> q;
   101       _levels.initStart();
   102       for(BNodeIt n(_g);n!=INVALID;++n)
   103 	if(_cov[n]>1) {
   104 	  _levels.initAddItem(n);
   105 	  q.push(n);
   106 	}
   107       int hlev=0;
   108       while(!q.empty()) {
   109 	Node n=q.front();
   110 	q.pop();
   111 	int nlev=_levels[n]+1;
   112 	for(IncEdgeIt e(_g,n);e!=INVALID;++e) {
   113 	  Node m=_g.runningNode(e);
   114 	  if(e==_matching[m]) {
   115 	    for(IncEdgeIt f(_g,m);f!=INVALID;++f) {
   116 	      Node r=_g.runningNode(f);
   117 	      if(_levels[r]>nlev) {
   118 		for(;nlev>hlev;hlev++)
   119 		  _levels.initNewLevel();
   120 		_levels.initAddItem(r);
   121 		q.push(r);
   122 	      }
   123 	    }
   124 	  }
   125 	}
   126       }
   127       _levels.initFinish();
   128       for(BNodeIt n(_g);n!=INVALID;++n)
   129 	if(_cov[n]<1&&_levels[n]<_node_num)
   130 	  _levels.activate(n);
   131     }
   132 
   133     ///Start the main phase of the algorithm
   134     
   135     ///This algorithm calculates the maximum matching with the
   136     ///push-relabel principle. This function should be called just
   137     ///after the init() function which already set the initial
   138     ///prematching, the level function on the B-nodes and the active,
   139     ///ie. unmatched B-nodes.
   140     ///
   141     ///The algorithm always takes highest active B-node, and it try to
   142     ///find a B-node which is eligible to pass over one of it's
   143     ///matching edge. This condition holds when the B-node is one
   144     ///level lower, and the opposite node of it's matching edge is
   145     ///adjacent to the highest active node. In this case the current
   146     ///node steals the matching edge and becomes inactive. If there is
   147     ///not eligible node then the highest active node should be lift
   148     ///to the next proper level.
   149     ///
   150     ///The nodes should not lift higher than the number of the
   151     ///B-nodes, if a node reach this level it remains unmatched. If
   152     ///during the execution one level becomes empty the nodes above it
   153     ///can be deactivated and lift to the highest level.
   154     void start() {
   155       Node act;
   156       Node bact=INVALID;
   157       Node last_activated=INVALID;
   158       while((act=_levels.highestActive())!=INVALID) {
   159 	last_activated=INVALID;
   160 	int actlevel=_levels[act];
   161 	
   162 	UEdge bedge=INVALID;
   163 	int nlevel=_node_num;
   164 	{
   165 	  int nnlevel;
   166 	  for(IncEdgeIt tbedge(_g,act);
   167 	      tbedge!=INVALID && nlevel>=actlevel;
   168 	      ++tbedge)
   169 	    if((nnlevel=_levels[_g.bNode(_matching[_g.runningNode(tbedge)])])<
   170 	       nlevel)
   171 	      {
   172 		nlevel=nnlevel;
   173 		bedge=tbedge;
   174 	      }
   175 	}
   176 	if(nlevel<_node_num) {
   177 	  if(nlevel>=actlevel)
   178 	    _levels.liftHighestActiveTo(nlevel+1);
   179 	  bact=_g.bNode(_matching[_g.aNode(bedge)]);
   180 	  if(--_cov[bact]<1) {
   181 	    _levels.activate(bact);
   182 	    last_activated=bact;
   183 	  }
   184 	  _matching[_g.aNode(bedge)]=bedge;
   185 	  _cov[act]=1;
   186 	  _levels.deactivate(act);
   187 	}
   188 	else {
   189 	  if(_node_num>actlevel) 
   190 	    _levels.liftHighestActiveTo(_node_num);
   191 	  _levels.deactivate(act); 
   192 	}
   193 
   194 	if(_levels.onLevel(actlevel)==0)
   195 	  _levels.liftToTop(actlevel);
   196       }
   197       
   198       _matching_size = _node_num;
   199       for(ANodeIt n(_g);n!=INVALID;++n)
   200 	if(_matching[n]==INVALID) _matching_size--;
   201 	else if (_cov[_g.bNode(_matching[n])]>1) {
   202 	  _cov[_g.bNode(_matching[n])]--;
   203 	  _matching_size--;
   204 	  _matching[n]=INVALID;
   205 	}
   206     }
   207 
   208     ///Start the algorithm to find a perfect matching
   209 
   210     ///This function is close to identical to the simple start()
   211     ///member function but it calculates just perfect matching.
   212     ///However, the perfect property is only checked on the B-side of
   213     ///the graph
   214     ///
   215     ///The main difference between the two function is the handling of
   216     ///the empty levels. The simple start() function let the nodes
   217     ///above the empty levels unmatched while this variant if it find
   218     ///an empty level immediately terminates and gives back false
   219     ///return value.
   220     bool startPerfect() {
   221       Node act;
   222       Node bact=INVALID;
   223       Node last_activated=INVALID;
   224       while((act=_levels.highestActive())!=INVALID) {
   225 	last_activated=INVALID;
   226 	int actlevel=_levels[act];
   227 	
   228 	UEdge bedge=INVALID;
   229 	int nlevel=_node_num;
   230 	{
   231 	  int nnlevel;
   232 	  for(IncEdgeIt tbedge(_g,act);
   233 	      tbedge!=INVALID && nlevel>=actlevel;
   234 	      ++tbedge)
   235 	    if((nnlevel=_levels[_g.bNode(_matching[_g.runningNode(tbedge)])])<
   236 	       nlevel)
   237 	      {
   238 		nlevel=nnlevel;
   239 		bedge=tbedge;
   240 	      }
   241 	}
   242 	if(nlevel<_node_num) {
   243 	  if(nlevel>=actlevel)
   244 	    _levels.liftHighestActiveTo(nlevel+1);
   245 	  bact=_g.bNode(_matching[_g.aNode(bedge)]);
   246 	  if(--_cov[bact]<1) {
   247 	    _levels.activate(bact);
   248 	    last_activated=bact;
   249 	  }
   250 	  _matching[_g.aNode(bedge)]=bedge;
   251 	  _cov[act]=1;
   252 	  _levels.deactivate(act);
   253 	}
   254 	else {
   255 	  if(_node_num>actlevel) 
   256 	    _levels.liftHighestActiveTo(_node_num);
   257 	  _levels.deactivate(act); 
   258 	}
   259 
   260 	if(_levels.onLevel(actlevel)==0)
   261 	  _empty_level=actlevel;
   262 	  return false;
   263       }
   264       return true;
   265     }
   266   
   267     ///Runs the algorithm
   268     
   269     ///Just a shortcut for the next code:
   270     ///\code
   271     /// init();
   272     /// start();
   273     ///\endcode
   274     void run() {
   275       init();
   276       start();
   277     }
   278     
   279     ///Runs the algorithm to find a perfect matching
   280     
   281     ///Just a shortcut for the next code:
   282     ///\code
   283     /// init();
   284     /// startPerfect();
   285     ///\endcode
   286     ///
   287     ///\note If the two nodesets of the graph have different size then
   288     ///this algorithm checks the perfect property on the B-side.
   289     bool runPerfect() {
   290       init();
   291       return startPerfect();
   292     }
   293 
   294     ///Runs the algorithm to find a perfect matching
   295     
   296     ///Just a shortcut for the next code:
   297     ///\code
   298     /// init();
   299     /// startPerfect();
   300     ///\endcode
   301     ///
   302     ///\note It checks that the size of the two nodesets are equal.
   303     bool checkedRunPerfect() {
   304       if (countANodes(_g) != _node_num) return false;
   305       init();
   306       return startPerfect();
   307     }
   308 
   309     ///@}
   310 
   311     /// \name Query Functions
   312     /// The result of the %Matching algorithm can be obtained using these
   313     /// functions.\n
   314     /// Before the use of these functions,
   315     /// either run() or start() must be called.
   316     ///@{
   317 
   318     ///Set true all matching uedge in the map.
   319 
   320     ///Set true all matching uedge in the map. It does not change the
   321     ///value mapped to the other uedges.
   322     ///\return The number of the matching edges.
   323     template <typename MatchingMap>
   324     int quickMatching(MatchingMap& mm) const {
   325       for (ANodeIt n(_g);n!=INVALID;++n) {
   326         if (_matching[n]!=INVALID) mm.set(_matching[n],true);
   327       }
   328       return _matching_size;
   329     }
   330 
   331     ///Set true all matching uedge in the map and the others to false.
   332 
   333     ///Set true all matching uedge in the map and the others to false.
   334     ///\return The number of the matching edges.
   335     template<class MatchingMap>
   336     int matching(MatchingMap& mm) const {
   337       for (UEdgeIt e(_g);e!=INVALID;++e) {
   338         mm.set(e,e==_matching[_g.aNode(e)]);
   339       }
   340       return _matching_size;
   341     }
   342 
   343     ///Gives back the matching in an ANodeMap.
   344 
   345     ///Gives back the matching in an ANodeMap. The parameter should
   346     ///be a write ANodeMap of UEdge values.
   347     ///\return The number of the matching edges.
   348     template<class MatchingMap>
   349     int aMatching(MatchingMap& mm) const {
   350       for (ANodeIt n(_g);n!=INVALID;++n) {
   351         mm.set(n,_matching[n]);
   352       }
   353       return _matching_size;
   354     }
   355 
   356     ///Gives back the matching in a BNodeMap.
   357 
   358     ///Gives back the matching in a BNodeMap. The parameter should
   359     ///be a write BNodeMap of UEdge values.
   360     ///\return The number of the matching edges.
   361     template<class MatchingMap>
   362     int bMatching(MatchingMap& mm) const {
   363       for (BNodeIt n(_g);n!=INVALID;++n) {
   364         mm.set(n,INVALID);
   365       }
   366       for (ANodeIt n(_g);n!=INVALID;++n) {
   367         if (_matching[n]!=INVALID)
   368 	  mm.set(_g.bNode(_matching[n]),_matching[n]);
   369       }
   370       return _matching_size;
   371     }
   372 
   373 
   374     ///Returns true if the given uedge is in the matching.
   375 
   376     ///It returns true if the given uedge is in the matching.
   377     ///
   378     bool matchingEdge(const UEdge& e) const {
   379       return _matching[_g.aNode(e)]==e;
   380     }
   381 
   382     ///Returns the matching edge from the node.
   383 
   384     ///Returns the matching edge from the node. If there is not such
   385     ///edge it gives back \c INVALID.  
   386     ///\note If the parameter node is a B-node then the running time is
   387     ///propotional to the degree of the node.
   388     UEdge matchingEdge(const Node& n) const {
   389       if (_g.aNode(n)) {
   390         return _matching[n];
   391       } else {
   392 	for (IncEdgeIt e(_g,n);e!=INVALID;++e)
   393 	  if (e==_matching[_g.aNode(e)]) return e;
   394 	return INVALID;
   395       }
   396     }
   397 
   398     ///Gives back the number of the matching edges.
   399 
   400     ///Gives back the number of the matching edges.
   401     int matchingSize() const {
   402       return _matching_size;
   403     }
   404 
   405     ///Gives back a barrier on the A-nodes
   406     
   407     ///The barrier is s subset of the nodes on the same side of the
   408     ///graph. If we tried to find a perfect matching and it failed
   409     ///then the barrier size will be greater than its neighbours. If
   410     ///the maximum matching searched then the barrier size minus its
   411     ///neighbours will be exactly the unmatched nodes on the A-side.
   412     ///\retval bar A WriteMap on the ANodes with bool value.
   413     template<class BarrierMap>
   414     void aBarrier(BarrierMap &bar) const 
   415     {
   416       for(ANodeIt n(_g);n!=INVALID;++n)
   417 	bar.set(n,_matching[n]==INVALID ||
   418 	  _levels[_g.bNode(_matching[n])]<_empty_level);  
   419     }  
   420 
   421     ///Gives back a barrier on the B-nodes
   422     
   423     ///The barrier is s subset of the nodes on the same side of the
   424     ///graph. If we tried to find a perfect matching and it failed
   425     ///then the barrier size will be greater than its neighbours. If
   426     ///the maximum matching searched then the barrier size minus its
   427     ///neighbours will be exactly the unmatched nodes on the B-side.
   428     ///\retval bar A WriteMap on the BNodes with bool value.
   429     template<class BarrierMap>
   430     void bBarrier(BarrierMap &bar) const
   431     {
   432       for(BNodeIt n(_g);n!=INVALID;++n) bar.set(n,_levels[n]>=_empty_level);  
   433     }
   434 
   435     ///Returns a minimum covering of the nodes.
   436 
   437     ///The minimum covering set problem is the dual solution of the
   438     ///maximum bipartite matching. It provides a solution for this
   439     ///problem what is proof of the optimality of the matching.
   440     ///\param covering NodeMap of bool values, the nodes of the cover
   441     ///set will set true while the others false.  
   442     ///\return The size of the cover set.
   443     ///\note This function can be called just after the algorithm have
   444     ///already found a matching. 
   445     template<class CoverMap>
   446     int coverSet(CoverMap& covering) const {
   447       int ret=0;
   448       for(BNodeIt n(_g);n!=INVALID;++n) {
   449 	if (_levels[n]<_empty_level) { covering.set(n,true); ++ret; }
   450 	else covering.set(n,false);
   451       }
   452       for(ANodeIt n(_g);n!=INVALID;++n) {
   453 	if (_matching[n]!=INVALID &&
   454 	    _levels[_g.bNode(_matching[n])]>=_empty_level) 
   455 	  { covering.set(n,true); ++ret; }
   456 	else covering.set(n,false);
   457       }
   458       return ret;
   459     }
   460 
   461 
   462     /// @}
   463     
   464   };
   465   
   466   
   467   ///Maximum cardinality of the matchings in a bipartite graph
   468 
   469   ///\ingroup matching
   470   ///This function finds the maximum cardinality of the matchings
   471   ///in a bipartite graph \c g.
   472   ///\param g An undirected bipartite graph.
   473   ///\return The cardinality of the maximum matching.
   474   ///
   475   ///\note The the implementation is based
   476   ///on the push-relabel principle.
   477   template<class Graph>
   478   int prBipartiteMatching(const Graph &g)
   479   {
   480     PrBipartiteMatching<Graph> bpm(g);
   481     return bpm.matchingSize();
   482   }
   483 
   484   ///Maximum cardinality matching in a bipartite graph
   485 
   486   ///\ingroup matching
   487   ///This function finds a maximum cardinality matching
   488   ///in a bipartite graph \c g.
   489   ///\param g An undirected bipartite graph.
   490   ///\retval matching A write ANodeMap of value type \c UEdge.
   491   /// The found edges will be returned in this map,
   492   /// i.e. for an \c ANode \c n the edge <tt>matching[n]</tt> is the one
   493   /// that covers the node \c n.
   494   ///\return The cardinality of the maximum matching.
   495   ///
   496   ///\note The the implementation is based
   497   ///on the push-relabel principle.
   498   template<class Graph,class MT>
   499   int prBipartiteMatching(const Graph &g,MT &matching) 
   500   {
   501     PrBipartiteMatching<Graph> bpm(g);
   502     bpm.run();
   503     bpm.aMatching(matching);
   504     return bpm.matchingSize();
   505   }
   506 
   507   ///Maximum cardinality matching in a bipartite graph
   508 
   509   ///\ingroup matching
   510   ///This function finds a maximum cardinality matching
   511   ///in a bipartite graph \c g.
   512   ///\param g An undirected bipartite graph.
   513   ///\retval matching A write ANodeMap of value type \c UEdge.
   514   /// The found edges will be returned in this map,
   515   /// i.e. for an \c ANode \c n the edge <tt>matching[n]</tt> is the one
   516   /// that covers the node \c n.
   517   ///\retval barrier A \c bool WriteMap on the BNodes. The map will be set
   518   /// exactly once for each BNode. The nodes with \c true value represent
   519   /// a barrier \e B, i.e. the cardinality of \e B minus the number of its
   520   /// neighbor is equal to the number of the <tt>BNode</tt>s minus the
   521   /// cardinality of the maximum matching.
   522   ///\return The cardinality of the maximum matching.
   523   ///
   524   ///\note The the implementation is based
   525   ///on the push-relabel principle.
   526   template<class Graph,class MT, class GT>
   527   int prBipartiteMatching(const Graph &g,MT &matching,GT &barrier) 
   528   {
   529     PrBipartiteMatching<Graph> bpm(g);
   530     bpm.run();
   531     bpm.aMatching(matching);
   532     bpm.bBarrier(barrier);
   533     return bpm.matchingSize();
   534   }  
   535 
   536   ///Perfect matching in a bipartite graph
   537 
   538   ///\ingroup matching
   539   ///This function checks whether the bipartite graph \c g
   540   ///has a perfect matching.
   541   ///\param g An undirected bipartite graph.
   542   ///\return \c true iff \c g has a perfect matching.
   543   ///
   544   ///\note The the implementation is based
   545   ///on the push-relabel principle.
   546   template<class Graph>
   547   bool prPerfectBipartiteMatching(const Graph &g)
   548   {
   549     PrBipartiteMatching<Graph> bpm(g);
   550     return bpm.runPerfect();
   551   }
   552 
   553   ///Perfect matching in a bipartite graph
   554 
   555   ///\ingroup matching
   556   ///This function finds a perfect matching in a bipartite graph \c g.
   557   ///\param g An undirected bipartite graph.
   558   ///\retval matching A write ANodeMap of value type \c UEdge.
   559   /// The found edges will be returned in this map,
   560   /// i.e. for an \c ANode \c n the edge <tt>matching[n]</tt> is the one
   561   /// that covers the node \c n.
   562   /// The values are unchanged if the graph
   563   /// has no perfect matching.
   564   ///\return \c true iff \c g has a perfect matching.
   565   ///
   566   ///\note The the implementation is based
   567   ///on the push-relabel principle.
   568   template<class Graph,class MT>
   569   bool prPerfectBipartiteMatching(const Graph &g,MT &matching) 
   570   {
   571     PrBipartiteMatching<Graph> bpm(g);
   572     bool ret = bpm.checkedRunPerfect();
   573     if (ret) bpm.aMatching(matching);
   574     return ret;
   575   }
   576 
   577   ///Perfect matching in a bipartite graph
   578 
   579   ///\ingroup matching
   580   ///This function finds a perfect matching in a bipartite graph \c g.
   581   ///\param g An undirected bipartite graph.
   582   ///\retval matching A write ANodeMap of value type \c UEdge.
   583   /// The found edges will be returned in this map,
   584   /// i.e. for an \c ANode \c n the edge <tt>matching[n]</tt> is the one
   585   /// that covers the node \c n.
   586   /// The values are unchanged if the graph
   587   /// has no perfect matching.
   588   ///\retval barrier A \c bool WriteMap on the BNodes. The map will only
   589   /// be set if \c g has no perfect matching. In this case it is set 
   590   /// exactly once for each BNode. The nodes with \c true value represent
   591   /// a barrier, i.e. a subset \e B a of BNodes with the property that
   592   /// the cardinality of \e B is greater than the number of its neighbors.
   593   ///\return \c true iff \c g has a perfect matching.
   594   ///
   595   ///\note The the implementation is based
   596   ///on the push-relabel principle.
   597   template<class Graph,class MT, class GT>
   598   bool prPerfectBipartiteMatching(const Graph &g,MT &matching,GT &barrier) 
   599   {
   600     PrBipartiteMatching<Graph> bpm(g);
   601     bool ret=bpm.checkedRunPerfect();
   602     if(ret)
   603       bpm.aMatching(matching);
   604     else
   605       bpm.bBarrier(barrier);
   606     return ret;
   607   }  
   608 }
   609 
   610 #endif