Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

max_matching.h

Go to the documentation of this file.
00001 /* -*- C++ -*-
00002  * lemon/max_matching.h - Part of LEMON, a generic C++ optimization library
00003  *
00004  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
00005  * (Egervary Research Group on Combinatorial Optimization, EGRES).
00006  *
00007  * Permission to use, modify and distribute this software is granted
00008  * provided that this copyright notice appears in all copies. For
00009  * precise terms see the accompanying LICENSE file.
00010  *
00011  * This software is provided "AS IS" with no warranty of any kind,
00012  * express or implied, and with no claim as to its suitability for any
00013  * purpose.
00014  *
00015  */
00016 
00017 #ifndef LEMON_MAX_MATCHING_H
00018 #define LEMON_MAX_MATCHING_H
00019 
00020 #include <queue>
00021 #include <lemon/invalid.h>
00022 #include <lemon/unionfind.h>
00023 #include <lemon/graph_utils.h>
00024 
00028 
00029 namespace lemon {
00030 
00033 
00035 
00055   template <typename Graph>
00056   class MaxMatching {
00057 
00058   protected:
00059 
00060     typedef typename Graph::Node Node;
00061     typedef typename Graph::Edge Edge;
00062     typedef typename Graph::UndirEdge UndirEdge;
00063     typedef typename Graph::UndirEdgeIt UndirEdgeIt;
00064     typedef typename Graph::NodeIt NodeIt;
00065     typedef typename Graph::IncEdgeIt IncEdgeIt;
00066 
00067     typedef UnionFindEnum<Node, Graph::template NodeMap> UFE;
00068 
00069   public:
00070     
00072 
00078     enum pos_enum {
00079       D=0,
00080       A=1,
00081       C=2
00082     }; 
00083 
00084   protected:
00085 
00086     static const int HEUR_density=2;
00087     const Graph& g;
00088     typename Graph::template NodeMap<Node> _mate;
00089     typename Graph::template NodeMap<pos_enum> position;
00090      
00091   public:
00092     
00093     MaxMatching(const Graph& _g) : g(_g), _mate(_g,INVALID), position(_g) {}
00094 
00096 
00100     void run() {
00101       if ( countUndirEdges(g) < HEUR_density*countNodes(g) ) {
00102         greedyMatching();
00103         runEdmonds(0);
00104       } else runEdmonds(1);
00105     }
00106 
00107 
00109     
00113     void runEdmonds( int heur = 1 ) {
00114       
00115       for(NodeIt v(g); v!=INVALID; ++v)
00116         position.set(v,C);      
00117       
00118       typename Graph::template NodeMap<Node> ear(g,INVALID); 
00119       //undefined for the base nodes of the blossoms (i.e. for the
00120       //representative elements of UFE blossom) and for the nodes in C 
00121       
00122       typename UFE::MapType blossom_base(g);
00123       UFE blossom(blossom_base);
00124       typename UFE::MapType tree_base(g);
00125       UFE tree(tree_base);
00126       //If these UFE's would be members of the class then also
00127       //blossom_base and tree_base should be a member.
00128       
00129       for(NodeIt v(g); v!=INVALID; ++v) {
00130         if ( position[v]==C && _mate[v]==INVALID ) {
00131           blossom.insert(v);
00132           tree.insert(v); 
00133           position.set(v,D);
00134           if ( heur == 1 ) lateShrink( v, ear, blossom, tree );
00135           else normShrink( v, ear, blossom, tree );
00136         }
00137       }
00138     }
00139 
00140 
00142     
00145     void greedyMatching() {
00146       for(NodeIt v(g); v!=INVALID; ++v)
00147         if ( _mate[v]==INVALID ) {
00148           for( IncEdgeIt e(g,v); e!=INVALID ; ++e ) {
00149             Node y=g.runningNode(e);
00150             if ( _mate[y]==INVALID && y!=v ) {
00151               _mate.set(v,y);
00152               _mate.set(y,v);
00153               break;
00154             }
00155           }
00156         } 
00157     }
00158 
00160 
00163     int size() const {
00164       int s=0;
00165       for(NodeIt v(g); v!=INVALID; ++v) {
00166         if ( _mate[v]!=INVALID ) {
00167           ++s;
00168         }
00169       }
00170       return s/2;
00171     }
00172 
00173 
00175 
00178     void resetMatching() {
00179       for(NodeIt v(g); v!=INVALID; ++v)
00180         _mate.set(v,INVALID);      
00181     }
00182 
00184 
00187     Node mate(Node& node) const {
00188       return _mate[node];
00189     } 
00190 
00192 
00196     template<typename NMapN>
00197     void readNMapNode(NMapN& map) {
00198       for(NodeIt v(g); v!=INVALID; ++v) {
00199         _mate.set(v,map[v]);   
00200       } 
00201     } 
00202     
00204 
00208     template<typename NMapN>
00209     void writeNMapNode (NMapN& map) const {
00210       for(NodeIt v(g); v!=INVALID; ++v) {
00211         map.set(v,_mate[v]);   
00212       } 
00213     } 
00214 
00216 
00222     template<typename NMapE>
00223     void readNMapEdge(NMapE& map) {
00224      for(NodeIt v(g); v!=INVALID; ++v) {
00225        UndirEdge e=map[v];
00226         if ( e!=INVALID )
00227           _mate.set(v,g.oppositeNode(v,e));
00228       } 
00229     } 
00230     
00232 
00238     template<typename NMapE>
00239     void writeNMapEdge (NMapE& map)  const {
00240       typename Graph::template NodeMap<bool> todo(g,true); 
00241       for(NodeIt v(g); v!=INVALID; ++v) {
00242         if ( todo[v] && _mate[v]!=INVALID ) {
00243           Node u=_mate[v];
00244           for(IncEdgeIt e(g,v); e!=INVALID; ++e) {
00245             if ( g.runningNode(e) == u ) {
00246               map.set(u,e);
00247               map.set(v,e);
00248               todo.set(u,false);
00249               todo.set(v,false);
00250               break;
00251             }
00252           }
00253         }
00254       } 
00255     }
00256 
00257 
00259     
00264     template<typename EMapB>
00265     void readEMapBool(EMapB& map) {
00266       for(UndirEdgeIt e(g); e!=INVALID; ++e) {
00267         if ( map[e] ) {
00268           Node u=g.source(e);     
00269           Node v=g.target(e);
00270           _mate.set(u,v);
00271           _mate.set(v,u);
00272         } 
00273       } 
00274     }
00275 
00276 
00278 
00283     template<typename EMapB>
00284     void writeEMapBool (EMapB& map) const {
00285       for(UndirEdgeIt e(g); e!=INVALID; ++e) map.set(e,false);
00286 
00287       typename Graph::template NodeMap<bool> todo(g,true); 
00288       for(NodeIt v(g); v!=INVALID; ++v) {
00289         if ( todo[v] && _mate[v]!=INVALID ) {
00290           Node u=_mate[v];
00291           for(IncEdgeIt e(g,v); e!=INVALID; ++e) {
00292             if ( g.runningNode(e) == u ) {
00293               map.set(e,true);
00294               todo.set(u,false);
00295               todo.set(v,false);
00296               break;
00297             }
00298           }
00299         }
00300       } 
00301     }
00302 
00303 
00306 
00310     template<typename NMapEnum>
00311     void writePos (NMapEnum& map) const {
00312       for(NodeIt v(g); v!=INVALID; ++v)  map.set(v,position[v]);
00313     }
00314 
00315   private: 
00316 
00317  
00318     void lateShrink(Node v, typename Graph::template NodeMap<Node>& ear,  
00319                     UFE& blossom, UFE& tree);
00320 
00321     void normShrink(Node v, typename Graph::template NodeMap<Node>& ear,  
00322                     UFE& blossom, UFE& tree);
00323 
00324     bool noShrinkStep(Node x, typename Graph::template NodeMap<Node>& ear,  
00325                       UFE& blossom, UFE& tree, std::queue<Node>& Q);
00326 
00327     void shrinkStep(Node& top, Node& middle, Node& bottom,
00328                     typename Graph::template NodeMap<Node>& ear,  
00329                     UFE& blossom, UFE& tree, std::queue<Node>& Q);
00330 
00331     void augment(Node x, typename Graph::template NodeMap<Node>& ear,  
00332                  UFE& blossom, UFE& tree);
00333 
00334   };
00335 
00336 
00337   // **********************************************************************
00338   //  IMPLEMENTATIONS
00339   // **********************************************************************
00340 
00341 
00342   template <typename Graph>
00343   void MaxMatching<Graph>::lateShrink(Node v, typename Graph::template NodeMap<Node>& ear,  
00344                                       UFE& blossom, UFE& tree) {
00345 
00346     std::queue<Node> Q;   //queue of the totally unscanned nodes
00347     Q.push(v);  
00348     std::queue<Node> R;   
00349     //queue of the nodes which must be scanned for a possible shrink
00350       
00351     while ( !Q.empty() ) {
00352       Node x=Q.front();
00353       Q.pop();
00354       if ( noShrinkStep( x, ear, blossom, tree, Q ) ) return;
00355       else R.push(x);
00356     }
00357       
00358     while ( !R.empty() ) {
00359       Node x=R.front();
00360       R.pop();
00361         
00362       for( IncEdgeIt e(g,x); e!=INVALID ; ++e ) {
00363         Node y=g.runningNode(e);
00364 
00365         if ( position[y] == D && blossom.find(x) != blossom.find(y) ) { 
00366           //x and y must be in the same tree
00367         
00368           typename Graph::template NodeMap<bool> path(g,false);
00369 
00370           Node b=blossom.find(x);
00371           path.set(b,true);
00372           b=_mate[b];
00373           while ( b!=INVALID ) { 
00374             b=blossom.find(ear[b]);
00375             path.set(b,true);
00376             b=_mate[b];
00377           } //going till the root
00378         
00379           Node top=y;
00380           Node middle=blossom.find(top);
00381           Node bottom=x;
00382           while ( !path[middle] )
00383             shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
00384                   
00385           Node base=middle;
00386           top=x;
00387           middle=blossom.find(top);
00388           bottom=y;
00389           Node blossom_base=blossom.find(base);
00390           while ( middle!=blossom_base )
00391             shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
00392                   
00393           blossom.makeRep(base);
00394         } // if shrink is needed
00395 
00396         while ( !Q.empty() ) {
00397           Node x=Q.front();
00398           Q.pop();
00399           if ( noShrinkStep(x, ear, blossom, tree, Q) ) return;
00400           else R.push(x);
00401         }
00402       } //for e
00403     } // while ( !R.empty() )
00404   }
00405 
00406 
00407   template <typename Graph>
00408   void MaxMatching<Graph>::normShrink(Node v,
00409                                       typename Graph::template
00410                                       NodeMap<Node>& ear,  
00411                                       UFE& blossom, UFE& tree) {
00412     std::queue<Node> Q;   //queue of the unscanned nodes
00413     Q.push(v);  
00414     while ( !Q.empty() ) {
00415 
00416       Node x=Q.front();
00417       Q.pop();
00418         
00419       for( IncEdgeIt e(g,x); e!=INVALID; ++e ) {
00420         Node y=g.runningNode(e);
00421               
00422         switch ( position[y] ) {
00423         case D:          //x and y must be in the same tree
00424 
00425           if ( blossom.find(x) != blossom.find(y) ) { //shrink
00426             typename Graph::template NodeMap<bool> path(g,false);
00427               
00428             Node b=blossom.find(x);
00429             path.set(b,true);
00430             b=_mate[b];
00431             while ( b!=INVALID ) { 
00432               b=blossom.find(ear[b]);
00433               path.set(b,true);
00434               b=_mate[b];
00435             } //going till the root
00436         
00437             Node top=y;
00438             Node middle=blossom.find(top);
00439             Node bottom=x;
00440             while ( !path[middle] )
00441               shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
00442                 
00443             Node base=middle;
00444             top=x;
00445             middle=blossom.find(top);
00446             bottom=y;
00447             Node blossom_base=blossom.find(base);
00448             while ( middle!=blossom_base )
00449               shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
00450                 
00451             blossom.makeRep(base);
00452           }
00453           break;
00454         case C:
00455           if ( _mate[y]!=INVALID ) {   //grow
00456 
00457             ear.set(y,x);
00458             Node w=_mate[y];
00459             blossom.insert(w);
00460             position.set(y,A); 
00461             position.set(w,D); 
00462             tree.insert(y);
00463             tree.insert(w);
00464             tree.join(y,blossom.find(x));  
00465             tree.join(w,y);  
00466             Q.push(w);
00467           } else {                 //augment  
00468             augment(x, ear, blossom, tree);
00469             _mate.set(x,y);
00470             _mate.set(y,x);
00471             return;
00472           } //if 
00473           break;
00474         default: break;
00475         }
00476       }
00477     }
00478   }
00479 
00480   template <typename Graph>
00481   bool MaxMatching<Graph>::noShrinkStep(Node x,
00482                                         typename Graph::template 
00483                                         NodeMap<Node>& ear,  
00484                                         UFE& blossom, UFE& tree,
00485                                         std::queue<Node>& Q) {
00486     for( IncEdgeIt e(g,x); e!= INVALID; ++e ) {
00487       Node y=g.runningNode(e);
00488         
00489       if ( position[y]==C ) {
00490         if ( _mate[y]!=INVALID ) {       //grow
00491           ear.set(y,x);
00492           Node w=_mate[y];
00493           blossom.insert(w);
00494           position.set(y,A);
00495           position.set(w,D);
00496           tree.insert(y);
00497           tree.insert(w);
00498           tree.join(y,blossom.find(x));  
00499           tree.join(w,y);  
00500           Q.push(w);
00501         } else {                      //augment 
00502           augment(x, ear, blossom, tree);
00503           _mate.set(x,y);
00504           _mate.set(y,x);
00505           return true;
00506         }
00507       }
00508     }
00509     return false;
00510   }
00511 
00512   template <typename Graph>
00513   void MaxMatching<Graph>::shrinkStep(Node& top, Node& middle, Node& bottom,
00514                                       typename Graph::template
00515                                       NodeMap<Node>& ear,  
00516                                       UFE& blossom, UFE& tree,
00517                                       std::queue<Node>& Q) {
00518     ear.set(top,bottom);
00519     Node t=top;
00520     while ( t!=middle ) {
00521       Node u=_mate[t];
00522       t=ear[u];
00523       ear.set(t,u);
00524     } 
00525     bottom=_mate[middle];
00526     position.set(bottom,D);
00527     Q.push(bottom);
00528     top=ear[bottom];            
00529     Node oldmiddle=middle;
00530     middle=blossom.find(top);
00531     tree.erase(bottom);
00532     tree.erase(oldmiddle);
00533     blossom.insert(bottom);
00534     blossom.join(bottom, oldmiddle);
00535     blossom.join(top, oldmiddle);
00536   }
00537 
00538   template <typename Graph>
00539   void MaxMatching<Graph>::augment(Node x,
00540                                    typename Graph::template NodeMap<Node>& ear,  
00541                                    UFE& blossom, UFE& tree) { 
00542     Node v=_mate[x];
00543     while ( v!=INVALID ) {
00544         
00545       Node u=ear[v];
00546       _mate.set(v,u);
00547       Node tmp=v;
00548       v=_mate[u];
00549       _mate.set(u,tmp);
00550     }
00551     typename UFE::ItemIt it;
00552     for (tree.first(it,blossom.find(x)); tree.valid(it); tree.next(it)) {   
00553       if ( position[it] == D ) {
00554         typename UFE::ItemIt b_it;
00555         for (blossom.first(b_it,it); blossom.valid(b_it); blossom.next(b_it)) {  
00556           position.set( b_it ,C);
00557         }
00558         blossom.eraseClass(it);
00559       } else position.set( it ,C);
00560     }
00561     tree.eraseClass(x);
00562 
00563   }
00564 
00566   
00567 } //END OF NAMESPACE LEMON
00568 
00569 #endif //LEMON_MAX_MATCHING_H

Generated on Sat Aug 27 14:14:54 2005 for LEMON by  doxygen 1.4.4