src/work/jacint/max_matching.h
author deba
Wed, 08 Sep 2004 12:06:45 +0000 (2004-09-08)
changeset 822 88226d9fe821
parent 586 04fdffd38e89
child 921 818510fa3d99
permissions -rw-r--r--
The MapFactories have been removed from the code because
if we use macros then they increases only the complexity.

The pair iterators of the maps are separeted from the maps.

Some macros and comments has been changed.
     1 // -*- C++ -*-
     2 #ifndef HUGO_MAX_MATCHING_H
     3 #define HUGO_MAX_MATCHING_H
     4 
     5 ///\ingroup galgs
     6 ///\file
     7 ///\brief Maximum matching algorithm.
     8 
     9 #include <queue>
    10 
    11 #include <invalid.h>
    12 #include <unionfind.h>
    13 
    14 namespace hugo {
    15 
    16   /// \addtogroup galgs
    17   /// @{
    18 
    19   ///Maximum matching algorithms class.
    20 
    21   ///This class provides Edmonds' alternating forest matching
    22   ///algorithm. The starting matching (if any) can be passed to the
    23   ///algorithm using read-in functions \ref readNMapNode, \ref
    24   ///readNMapEdge or \ref readEMapBool depending on the container. The
    25   ///resulting maximum matching can be attained by write-out functions
    26   ///\ref writeNMapNode, \ref writeNMapEdge or \ref writeEMapBool
    27   ///depending on the preferred container. 
    28   ///
    29   ///The dual side of a mathcing is a map of the nodes to
    30   ///MaxMatching::pos_enum, having values D, A and C showing the
    31   ///Gallai-Edmonds decomposition of the graph. The nodes in D induce
    32   ///a graph with factor-critical components, the nodes in A form the
    33   ///barrier, and the nodes in C induce a graph having a perfect
    34   ///matching. This decomposition can be attained by calling \ref
    35   ///writePos after running the algorithm. Before subsequent runs,
    36   ///the function \ref resetPos() must be called.
    37   ///
    38   ///\param Graph The undirected graph type the algorithm runs on.
    39   ///
    40   ///\author Jacint Szabo  
    41   template <typename Graph>
    42   class MaxMatching {
    43     typedef typename Graph::Node Node;
    44     typedef typename Graph::Edge Edge;
    45     typedef typename Graph::EdgeIt EdgeIt;
    46     typedef typename Graph::NodeIt NodeIt;
    47     typedef typename Graph::OutEdgeIt OutEdgeIt;
    48 
    49     typedef UnionFindEnum<Node, Graph::template NodeMap> UFE;
    50 
    51   public:
    52     
    53     ///Indicates the Gallai-Edmonds decomposition of the graph.
    54 
    55     ///Indicates the Gallai-Edmonds decomposition of the graph, which
    56     ///shows an upper bound on the size of a maximum matching. The
    57     ///nodes with pos_enum \c D induce a graph with factor-critical
    58     ///components, the nodes in \c A form the canonical barrier, and the
    59     ///nodes in \c C induce a graph having a perfect matching. 
    60     enum pos_enum {
    61       D=0,
    62       A=1,
    63       C=2
    64     }; 
    65 
    66   private:
    67 
    68     const Graph& G;
    69     typename Graph::template NodeMap<Node> mate;
    70     typename Graph::template NodeMap<pos_enum> position;
    71      
    72   public:
    73     
    74     MaxMatching(const Graph& _G) : G(_G), mate(_G,INVALID), position(_G,C) {}
    75 
    76     ///Runs Edmonds' algorithm.
    77 
    78     ///Runs Edmonds' algorithm for sparse graphs (edgeNum >=
    79     ///2*nodeNum), and a heuristical Edmonds' algorithm with a
    80     ///heuristic of postponing shrinks for dense graphs. \pre Before
    81     ///the subsequent calls \ref resetPos must be called.
    82     inline void run();
    83 
    84     ///Runs Edmonds' algorithm.
    85     
    86     ///If heur=0 it runs Edmonds' algorithm. If heur=1 it runs
    87     ///Edmonds' algorithm with a heuristic of postponing shrinks,
    88     ///giving a faster algorithm for dense graphs.  \pre Before the
    89     ///subsequent calls \ref resetPos must be called.
    90     void runEdmonds( int heur );
    91 
    92     ///Finds a greedy matching starting from the actual matching.
    93     
    94     ///Starting form the actual matching stored, it finds a maximal
    95     ///greedy matching.
    96     void greedyMatching();
    97 
    98     ///Returns the size of the actual matching stored.
    99 
   100     ///Returns the size of the actual matching stored. After \ref
   101     ///run() it returns the size of a maximum matching in the graph.
   102     int size () const;
   103 
   104     ///Resets the map storing the Gallai-Edmonds decomposition.
   105     
   106     ///Resets the map storing the Gallai-Edmonds decomposition of the
   107     ///graph, making it possible to run the algorithm. Must be called
   108     ///before all runs of the Edmonds algorithm, except for the first
   109     ///run.
   110     void resetPos();
   111 
   112     ///Resets the actual matching to the empty matching.
   113 
   114     ///Resets the actual matching to the empty matching.  
   115     ///
   116     void resetMatching();
   117 
   118     ///Reads a matching from a \c Node map of \c Nodes.
   119 
   120     ///Reads a matching from a \c Node map of \c Nodes. This map must be \e
   121     ///symmetric, i.e. if \c map[u]=v then \c map[v]=u must hold, and
   122     ///now \c uv is an edge of the matching.
   123     template<typename NMapN>
   124     void readNMapNode(NMapN& map) {
   125       NodeIt v;
   126       for( G.first(v); G.valid(v); G.next(v)) {
   127 	mate.set(v,map[v]);   
   128       } 
   129     } 
   130     
   131     ///Writes the stored matching to a \c Node map of \c Nodes.
   132 
   133     ///Writes the stored matching to a \c Node map of \c Nodes. The
   134     ///resulting map will be \e symmetric, i.e. if \c map[u]=v then \c
   135     ///map[v]=u will hold, and now \c uv is an edge of the matching.
   136     template<typename NMapN>
   137     void writeNMapNode (NMapN& map) const {
   138       NodeIt v;
   139       for( G.first(v); G.valid(v); G.next(v)) {
   140 	map.set(v,mate[v]);   
   141       } 
   142     } 
   143 
   144     ///Reads a matching from a \c Node map of \c Edges.
   145 
   146     ///Reads a matching from a \c Node map of incident \c Edges. This
   147     ///map must have the property that if \c G.bNode(map[u])=v then \c
   148     ///G.bNode(map[v])=u must hold, and now this edge is an edge of
   149     ///the matching.
   150     template<typename NMapE>
   151     void readNMapEdge(NMapE& map) {
   152       NodeIt v;
   153       for( G.first(v); G.valid(v); G.next(v)) {
   154 	Edge e=map[v];
   155 	if ( G.valid(e) )
   156 	  G.tail(e) == v ? mate.set(v,G.head(e)) : mate.set(v,G.tail(e)); 
   157       } 
   158     } 
   159     
   160     ///Writes the matching stored to a \c Node map of \c Edges.
   161 
   162     ///Writes the stored matching to a \c Node map of incident \c
   163     ///Edges. This map will have the property that if \c
   164     ///G.bNode(map[u])=v then \c G.bNode(map[v])=u holds, and now this
   165     ///edge is an edge of the matching.
   166     template<typename NMapE>
   167     void writeNMapEdge (NMapE& map)  const {
   168       typename Graph::template NodeMap<bool> todo(G,false); 
   169       NodeIt v;
   170       for( G.first(v); G.valid(v); G.next(v)) {
   171 	if ( mate[v]!=INVALID ) todo.set(v,true); 
   172       }
   173       NodeIt e;
   174       for( G.first(e); G.valid(e); G.next(e)) {
   175 	if ( todo[G.head(e)] && todo[G.tail(e)] ) {
   176 	  Node u=G.tail(e);
   177 	  Node v=G.head(e); 
   178 	  if ( mate[u]=v && mate[v]=u ) {
   179 	    map.set(u,e);
   180 	    map.set(v,e);
   181 	    todo.set(u,false);
   182 	    todo.set(v,false);
   183 	  }
   184 	}
   185       }
   186     } 
   187 
   188     ///Reads a matching from an \c Edge map of \c bools.
   189     
   190     ///Reads a matching from an \c Edge map of \c bools. This map must
   191     ///have the property that there are no two adjacent edges \c e, \c
   192     ///f with \c map[e]=map[f]=true. The edges \c e with \c
   193     ///map[e]=true form the matching.
   194     template<typename EMapB>
   195     void readEMapBool(EMapB& map) {
   196       EdgeIt e;
   197       for( G.first(e); G.valid(e); G.next(e)) {
   198 	if ( G.valid(e) ) {
   199 	  Node u=G.tail(e);	  
   200 	  Node v=G.head(e);
   201 	  mate.set(u,v);
   202 	  mate.set(v,u);
   203 	} 
   204       } 
   205     }
   206 
   207 
   208     ///Writes the matching stored to an \c Edge map of \c bools.
   209 
   210     ///Writes the matching stored to an \c Edge map of \c bools. This
   211     ///map will have the property that there are no two adjacent edges
   212     ///\c e, \c f with \c map[e]=map[f]=true. The edges \c e with \c
   213     ///map[e]=true form the matching.
   214     template<typename EMapB>
   215     void writeEMapBool (EMapB& map) const {
   216       typename Graph::template NodeMap<bool> todo(G,false); 
   217       NodeIt v;
   218       for( G.first(v); G.valid(v); G.next(v)) {
   219 	if ( mate[v]!=INVALID ) todo.set(v,true); 
   220       }
   221       
   222       NodeIt e;
   223       for( G.first(e); G.valid(e); G.next(e)) {
   224 	map.set(e,false);
   225 	if ( todo[G.head(e)] && todo[G.tail(e)] ) {
   226 	  Node u=G.tail(e);
   227 	  Node v=G.head(e); 
   228 	  if ( mate[u]=v && mate[v]=u ) {
   229 	    map.set(e,true);
   230 	    todo.set(u,false);
   231 	    todo.set(v,false);
   232 	  }
   233 	}
   234       }
   235     }
   236 
   237     ///Writes the canonical decomposition of the graph after running
   238     ///the algorithm.
   239 
   240     ///After calling any run methods of the class, and before calling
   241     ///\ref resetPos(), it writes the Gallai-Edmonds canonical
   242     ///decomposition of the graph. \c map must be a node map
   243     ///of \ref pos_enum 's.
   244     template<typename NMapEnum>
   245     void writePos (NMapEnum& map) const {
   246       NodeIt v;
   247       for( G.first(v); G.valid(v); G.next(v)) map.set(v,position[v]);
   248     }
   249 
   250   private: 
   251 
   252     void lateShrink(Node v, typename Graph::template NodeMap<Node>& ear,  
   253 		    UFE& blossom, UFE& tree);
   254 
   255     void normShrink(Node v, typename Graph::NodeMap<Node>& ear,  
   256 		    UFE& blossom, UFE& tree);
   257 
   258     bool noShrinkStep(Node x, typename Graph::NodeMap<Node>& ear,  
   259 		      UFE& blossom, UFE& tree, std::queue<Node>& Q);
   260 
   261     void shrinkStep(Node& top, Node& middle, Node& bottom, typename Graph::NodeMap<Node>& ear,  
   262 		    UFE& blossom, UFE& tree, std::queue<Node>& Q);
   263 
   264     void augment(Node x, typename Graph::NodeMap<Node>& ear,  
   265 		 UFE& blossom, UFE& tree);
   266 
   267   };
   268 
   269 
   270   // **********************************************************************
   271   //  IMPLEMENTATIONS
   272   // **********************************************************************
   273 
   274 
   275   template <typename Graph>
   276   void MaxMatching<Graph>::run() {
   277     if ( G.edgeNum() > 2*G.nodeNum() ) {
   278       greedyMatching();
   279       runEdmonds(1);
   280     } else runEdmonds(0);
   281   }
   282 
   283   template <typename Graph>
   284   void MaxMatching<Graph>::runEdmonds( int heur=1 ) {
   285       
   286     typename Graph::template NodeMap<Node> ear(G,INVALID); 
   287     //undefined for the base nodes of the blossoms (i.e. for the
   288     //representative elements of UFE blossom) and for the nodes in C
   289       
   290     typename UFE::MapType blossom_base(G);
   291     UFE blossom(blossom_base);
   292     typename UFE::MapType tree_base(G);
   293     UFE tree(tree_base);
   294 	
   295     NodeIt v;
   296     for( G.first(v); G.valid(v); G.next(v) ) {
   297       if ( position[v]==C && mate[v]==INVALID ) {
   298 	blossom.insert(v);
   299 	tree.insert(v); 
   300 	position.set(v,D);
   301 	if ( heur == 1 ) lateShrink( v, ear, blossom, tree );
   302 	else normShrink( v, ear, blossom, tree );
   303       }
   304     }
   305   }
   306     
   307   template <typename Graph>
   308   void MaxMatching<Graph>::lateShrink(Node v, typename Graph::template NodeMap<Node>& ear,  
   309 				      UFE& blossom, UFE& tree) {
   310      
   311     std::queue<Node> Q;   //queue of the totally unscanned nodes
   312     Q.push(v);  
   313     std::queue<Node> R;   
   314     //queue of the nodes which must be scanned for a possible shrink
   315       
   316     while ( !Q.empty() ) {
   317       Node x=Q.front();
   318       Q.pop();
   319       if ( noShrinkStep( x, ear, blossom, tree, Q ) ) return;
   320       else R.push(x);
   321     }
   322       
   323     while ( !R.empty() ) {
   324       Node x=R.front();
   325       R.pop();
   326 	
   327       OutEdgeIt e;
   328       for( G.first(e,x); G.valid(e); G.next(e) ) {
   329 	Node y=G.bNode(e);
   330 
   331 	if ( position[y] == D && blossom.find(x) != blossom.find(y) ) { 
   332 	  //x and y must be in the same tree
   333 	
   334 	  typename Graph::template NodeMap<bool> path(G,false);
   335 
   336 	  Node b=blossom.find(x);
   337 	  path.set(b,true);
   338 	  b=mate[b];
   339 	  while ( b!=INVALID ) { 
   340 	    b=blossom.find(ear[b]);
   341 	    path.set(b,true);
   342 	    b=mate[b];
   343 	  } //going till the root
   344 	
   345 	  Node top=y;
   346 	  Node middle=blossom.find(top);
   347 	  Node bottom=x;
   348 	  while ( !path[middle] )
   349 	    shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
   350 		  
   351 	  Node base=middle;
   352 	  top=x;
   353 	  middle=blossom.find(top);
   354 	  bottom=y;
   355 	  Node blossom_base=blossom.find(base);
   356 	  while ( middle!=blossom_base )
   357 	    shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
   358 		  
   359 	  blossom.makeRep(base);
   360 	} // if shrink is needed
   361 
   362 	while ( !Q.empty() ) {
   363 	  Node x=Q.front();
   364 	  Q.pop();
   365 	  if ( noShrinkStep(x, ear, blossom, tree, Q) ) return;
   366 	  else R.push(x);
   367 	}
   368       } //for e
   369     } // while ( !R.empty() )
   370   }
   371 
   372   template <typename Graph>
   373   void MaxMatching<Graph>::normShrink(Node v, typename Graph::NodeMap<Node>& ear,  
   374 				      UFE& blossom, UFE& tree) {
   375 
   376     std::queue<Node> Q;   //queue of the unscanned nodes
   377     Q.push(v);  
   378     while ( !Q.empty() ) {
   379       Node x=Q.front();
   380       Q.pop();
   381 	
   382       OutEdgeIt e;
   383       for( G.first(e,x); G.valid(e); G.next(e) ) {
   384 	Node y=G.bNode(e);
   385 	      
   386 	switch ( position[y] ) {
   387 	case D:          //x and y must be in the same tree
   388 	  if ( blossom.find(x) != blossom.find(y) ) { //shrink
   389 	    typename Graph::template NodeMap<bool> path(G,false);
   390 	      
   391 	    Node b=blossom.find(x);
   392 	    path.set(b,true);
   393 	    b=mate[b];
   394 	    while ( b!=INVALID ) { 
   395 	      b=blossom.find(ear[b]);
   396 	      path.set(b,true);
   397 	      b=mate[b];
   398 	    } //going till the root
   399 	
   400 	    Node top=y;
   401 	    Node middle=blossom.find(top);
   402 	    Node bottom=x;
   403 	    while ( !path[middle] )
   404 	      shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
   405 		
   406 	    Node base=middle;
   407 	    top=x;
   408 	    middle=blossom.find(top);
   409 	    bottom=y;
   410 	    Node blossom_base=blossom.find(base);
   411 	    while ( middle!=blossom_base )
   412 	      shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
   413 		
   414 	    blossom.makeRep(base);
   415 	  }
   416 	  break;
   417 	case C:
   418 	  if ( mate[y]!=INVALID ) {   //grow
   419 	    ear.set(y,x);
   420 	    Node w=mate[y];
   421 	    blossom.insert(w);
   422 	    position.set(y,A); 
   423 	    position.set(w,D); 
   424 	    tree.insert(y);
   425 	    tree.insert(w);
   426 	    tree.join(y,blossom.find(x));  
   427 	    tree.join(w,y);  
   428 	    Q.push(w);
   429 	  } else {                 //augment  
   430 	    augment(x, ear, blossom, tree);
   431 	    mate.set(x,y);
   432 	    mate.set(y,x);
   433 	    return;
   434 	  } //if 
   435 	  break;
   436 	default: break;
   437 	}
   438       }
   439     }
   440   }
   441 
   442   template <typename Graph>
   443   void MaxMatching<Graph>::greedyMatching() {
   444     NodeIt v;
   445     for( G.first(v); G.valid(v); G.next(v) )
   446       if ( mate[v]==INVALID ) {
   447 	OutEdgeIt e;
   448 	for( G.first(e,v); G.valid(e); G.next(e) ) {
   449 	  Node y=G.bNode(e);
   450 	  if ( mate[y]==INVALID && y!=v ) {
   451 	    mate.set(v,y);
   452 	    mate.set(y,v);
   453 	    break;
   454 	  }
   455 	}
   456       } 
   457   }
   458    
   459   template <typename Graph>
   460   int MaxMatching<Graph>::size() const {
   461     int s=0;
   462     NodeIt v;
   463     for(G.first(v); G.valid(v); G.next(v) ) {
   464       if ( G.valid(mate[v]) ) {
   465 	++s;
   466       }
   467     }
   468     return (int)s/2;
   469   }
   470 
   471   template <typename Graph>
   472   void MaxMatching<Graph>::resetPos() {
   473     NodeIt v;
   474     for( G.first(v); G.valid(v); G.next(v))
   475       position.set(v,C);      
   476   }
   477 
   478   template <typename Graph>
   479   void MaxMatching<Graph>::resetMatching() {
   480     NodeIt v;
   481     for( G.first(v); G.valid(v); G.next(v))
   482       mate.set(v,INVALID);      
   483   }
   484 
   485   template <typename Graph>
   486   bool MaxMatching<Graph>::noShrinkStep(Node x, typename Graph::NodeMap<Node>& ear,  
   487 					UFE& blossom, UFE& tree, std::queue<Node>& Q) {
   488     OutEdgeIt e;
   489     for( G.first(e,x); G.valid(e); G.next(e) ) {
   490       Node y=G.bNode(e);
   491 	
   492       if ( position[y]==C ) {
   493 	if ( mate[y]!=INVALID ) {       //grow
   494 	  ear.set(y,x);
   495 	  Node w=mate[y];
   496 	  blossom.insert(w);
   497 	  position.set(y,A);
   498 	  position.set(w,D);
   499 	  tree.insert(y);
   500 	  tree.insert(w);
   501 	  tree.join(y,blossom.find(x));  
   502 	  tree.join(w,y);  
   503 	  Q.push(w);
   504 	} else {                      //augment 
   505 	  augment(x, ear, blossom, tree);
   506 	  mate.set(x,y);
   507 	  mate.set(y,x);
   508 	  return true;
   509 	}
   510       }
   511     }
   512     return false;
   513   }
   514 
   515   template <typename Graph>
   516   void MaxMatching<Graph>::shrinkStep(Node& top, Node& middle, Node& bottom, typename Graph::NodeMap<Node>& ear,  
   517 				      UFE& blossom, UFE& tree, std::queue<Node>& Q) {
   518     ear.set(top,bottom);
   519     Node t=top;
   520     while ( t!=middle ) {
   521       Node u=mate[t];
   522       t=ear[u];
   523       ear.set(t,u);
   524     } 
   525     bottom=mate[middle];
   526     position.set(bottom,D);
   527     Q.push(bottom);
   528     top=ear[bottom];		
   529     Node oldmiddle=middle;
   530     middle=blossom.find(top);
   531     tree.erase(bottom);
   532     tree.erase(oldmiddle);
   533     blossom.insert(bottom);
   534     blossom.join(bottom, oldmiddle);
   535     blossom.join(top, oldmiddle);
   536   }
   537 
   538   template <typename Graph>
   539   void MaxMatching<Graph>::augment(Node x, typename Graph::NodeMap<Node>& ear,  
   540 				   UFE& blossom, UFE& tree) { 
   541     Node v=mate[x];
   542     while ( G.valid(v) ) {
   543 	
   544       Node u=ear[v];
   545       mate.set(v,u);
   546       Node tmp=v;
   547       v=mate[u];
   548       mate.set(u,tmp);
   549     }
   550     typename UFE::ItemIt it;
   551     for (tree.first(it,blossom.find(x)); tree.valid(it); tree.next(it)) {   
   552       if ( position[it] == D ) {
   553 	typename UFE::ItemIt b_it;
   554 	for (blossom.first(b_it,it); blossom.valid(b_it); blossom.next(b_it)) {  
   555 	  position.set( b_it ,C);
   556 	}
   557 	blossom.eraseClass(it);
   558       } else position.set( it ,C);
   559     }
   560     tree.eraseClass(x);
   561   }
   562 
   563 
   564 
   565   /// @}
   566   
   567 } //END OF NAMESPACE HUGO
   568 
   569 #endif //EDMONDS_H