Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/graphAlgorithms/match/edmonds.cpp
00001 #include "edmonds.h"
00002 
00003 using namespace grafalgo;
00004 
00005 // Find a maximum size matching in the graph graf and
00006 // return it as a list of edges.
00007 edmonds::edmonds(Graph& graf1, Dlist& match1, int &size)
00008                  : graf(&graf1), match(&match1) {
00009         vertex u, v; edge e;
00010         blossoms = new Partition(graf->n()); // set per blossom
00011         augpath = new RlistSet(graf->m());    // reversible list
00012         origin = new vertex[graf->n()+1];    // original vertex for each blossom
00013         bridge = new BridgePair[graf->n()+1];// edge that formed a blossom
00014         state = new stype[graf->n()+1];      // state used in path search
00015         pEdge = new edge[graf->n()+1];       // edge to parent in tree
00016         mEdge = new edge[graf->n()+1];       // incident matching edge (if any)
00017         mark = new bool[graf->n()+1];        // mark bits used by nca
00018         
00019         mSize = stepCount = blossomCount = pathInitTime = pathFindTime = 0;
00020         int t1, t2, t3;
00021         t1 = Util::getTime();
00022         // Create initial maximal (not maximum) matching
00023         for (u = 1; u <= graf->n(); u++) {
00024                 mEdge[u] = 0; mark[u] = false;
00025         }
00026         match->clear(); size = 0;
00027         for (e = graf->first(); e != 0; e = graf->next(e)) {
00028                 u = graf->left(e); v = graf->right(e);
00029                 if (mEdge[u] == 0 && mEdge[v] == 0) {
00030                         mEdge[u] = mEdge[v] = e;
00031                         match->addLast(e); mSize++;
00032                 }
00033         }
00034         iSize = mSize;
00035                 
00036         t2 = Util::getTime();
00037         imatchTime = (t2-t1);
00038         while((e = findpath()) != 0) { augment(e); mSize++; }
00039         size = mSize;
00040         t3 = Util::getTime();
00041         rmatchTime = (t3-t2);
00042 
00043         delete blossoms; delete augpath; delete [] origin;
00044         delete [] bridge; delete [] pEdge; delete [] mEdge; delete[] mark;
00045 }
00046 
00047 void edmonds::augment(edge e) {
00048 // Modify the matching by augmenting along the path defined by
00049 // the list in the augpath data structure whose last element is e.
00050         while (true) {
00051                 edge e1 = augpath->first(e);
00052                 if (match->member(e1)) match->remove(e1);
00053                 else {
00054                         match->addLast(e1);
00055                         mEdge[graf->left(e1)] = mEdge[graf->right(e1)] = e1;
00056                 }
00057                 if (e == augpath->first(e)) break;
00058                 e = augpath->pop(e);
00059         }
00060 }
00061 
00062 // If u and v are in the same tree, return their nearest common
00063 // ancestor in the current "condensed graph". To avoid excessive
00064 // search time, search upwards from both vertices in parallel, using
00065 // mark bits to identify the nca. Before returning, clear the mark
00066 // bits by traversing the paths a second time. The mark bits are
00067 // initialized in the constructor.
00068 vertex edmonds::nca(vertex u, vertex v) {
00069         vertex x,px,y,py,result;
00070 
00071         // first pass to find the nca
00072         x = u; px = (pEdge[x] != 0 ? graf->mate(x,pEdge[x]) : 0);
00073         y = v; py = (pEdge[y] != 0 ? graf->mate(y,pEdge[y]) : 0);
00074         while (true) {
00075                 if (x == y) { result = x; break; }
00076                 if (px == 0 &&  py == 0) { result = 0; break; }
00077                 if (px != 0) {
00078                         if (mark[x]) { result = x; break; }
00079                         mark[x] = true;
00080                         x = origin[blossoms->find(px)];
00081                         px = (pEdge[x] != 0 ? graf->mate(x,pEdge[x]) : 0);
00082                 }
00083                 if (py != 0) {
00084                         if (mark[y]) { result = y; break; }
00085                         mark[y] = true;
00086                         y = origin[blossoms->find(py)];
00087                         py = (pEdge[y] != 0 ? graf->mate(y,pEdge[y]) : 0);
00088                 }
00089         }
00090         // second pass to clear mark bits
00091         x = u, y = v; 
00092         while (mark[x] || mark[y]) {
00093                 mark[x] = mark[y] = false;
00094                 px = (pEdge[x] != 0 ? graf->mate(x,pEdge[x]) : 0);
00095                 py = (pEdge[y] != 0 ? graf->mate(y,pEdge[y]) : 0);
00096                 x = (px == 0 ? x : origin[blossoms->find(px)]);
00097                 y = (py == 0 ? y : origin[blossoms->find(py)]);
00098         }
00099         return result;
00100 }
00101 
00102 edge edmonds::path(vertex a, vertex b) {
00103 // Find path joining a and b defined by parent pointers and bridges.
00104 // A is assumed to be a descendant of b, and the path to b from a
00105 // is assumed to pass through the matching edge incident to a.
00106 // Return path in the augpath data structure.
00107         vertex pa, p2a, da; edge e, e1, e2;
00108         if (a == b) return 0;
00109         if (state[a] == even) {
00110                 e1 = pEdge[a];  
00111                 pa = graf->mate(a,e1);
00112                 if (pa == b) return e1;
00113                 e2 = pEdge[pa]; 
00114                 p2a = graf->mate(pa,e2);
00115                 e = augpath->join(e1,e2);
00116                 e = augpath->join(e,path(p2a,b));
00117                 return e;
00118         } else {
00119                 e = bridge[a].e; da = bridge[a].v;
00120                 e = augpath->join(augpath->reverse(path(da,a)),e);
00121                 e = augpath->join(e,path(graf->mate(da,e),b));
00122                 return e;
00123         }
00124 }
00125 
00126 // Search for an augmenting path in the graph graf.
00127 // On success, the path data structure will include a list
00128 // that forms the augmenting path. In this case, the last
00129 // edge in the list is returned as the function value.
00130 // On failure, returns 0.
00131 edge edmonds::findpath() {
00132         vertex u,v,vp,w,wp,x,y; edge e, f;
00133 
00134         int t1, t2, t3;
00135         t1 = Util::getTime();
00136 
00137         blossoms->clear();
00138         for (u = 1; u <= graf->n(); u++) {
00139                 state[u] = even; pEdge[u] = 0; origin[u] = u;
00140         }
00141 
00142         for (e = match->first(); e != 0; e = match->next(e)) {
00143                 u = graf->left(e); v = graf->right(e);
00144                 state[u] = state[v] = unreached;
00145         }
00146         List q(graf->m()); // list of edges to be processed in main loop
00147         for (e = 1; e <= graf->m(); e++) {
00148                 if (state[graf->left(e)] == even ||
00149                     state[graf->right(e)] == even)
00150                         q.addLast(e);
00151         }
00152 
00153         t2 = Util::getTime();
00154         pathInitTime += (t2-t1);
00155         while (!q.empty()) {
00156                 stepCount++;
00157                 e = q.first(); q.removeFirst();
00158                 v = graf->left(e); vp = origin[blossoms->find(v)];
00159                 if (state[vp] != even) {
00160                         v = graf->right(e); vp = origin[blossoms->find(v)];
00161                 }
00162                 w = graf->mate(v,e); wp = origin[blossoms->find(w)];
00163                 if (vp == wp) continue; // skip internal edges in a blossom
00164                 if (state[wp] == unreached) {
00165                         // w is not contained in a blossom and is matched
00166                         // so extend tree and add newly eligible edges to q
00167                         x = graf->mate(w,mEdge[w]);
00168                         state[w] = odd;  pEdge[w] = e;
00169                         state[x] = even; pEdge[x] = mEdge[w];
00170                         for (f = graf->firstAt(x); f != 0;
00171                              f = graf->nextAt(x,f)) {
00172                                 if ((f != mEdge[x]) && !q.member(f))
00173                                         q.addLast(f);
00174                         }
00175                         continue;
00176                 }
00177                 u = nca(vp,wp);
00178                 if (state[wp] == even && u == 0) {
00179                         // vp, wp are different trees - construct path & return
00180                         x = vp;
00181                         while (pEdge[x] != 0) {
00182                                 x = origin[blossoms->find(
00183                                                 graf->mate(x,pEdge[x]))];
00184                         }
00185                         y = wp;
00186                         while (pEdge[y] != 0) {
00187                                 y = origin[blossoms->find(
00188                                                 graf->mate(y,pEdge[y]))];
00189                         }
00190                         e = augpath->join(augpath->reverse(path(v,x)),e);
00191                         e = augpath->join(e,path(w,y));
00192                         t3 = Util::getTime();
00193                         pathFindTime += (t3-t2);
00194                         return e;
00195                 } else if (state[wp] == even) {
00196                         // vp and wp are in same tree - collapse blossom
00197                         blossomCount++;
00198                         x = vp;
00199                         while (x != u) {
00200                                 origin[blossoms->link(
00201                                         blossoms->find(x),
00202                                         blossoms->find(u))] = u;
00203                                 if (state[x] == odd) {
00204                                         bridge[x].e = e; bridge[x].v = v;
00205                                         for (f = graf->firstAt(x); f != 0;
00206                                              f = graf->nextAt(x,f))
00207                                                 if (!q.member(f)) q.addLast(f);
00208                                 }
00209                                 x = origin[blossoms->find(
00210                                                 graf->mate(x,pEdge[x]))];
00211                         }
00212                         x = wp;
00213                         while (x != u) {
00214                                 origin[blossoms->link(
00215                                         blossoms->find(x),
00216                                         blossoms->find(u))] = u;
00217                                 if (state[x] == odd) {
00218                                         bridge[x].e = e; bridge[x].v = w;
00219                                         for (f = graf->firstAt(x); f != 0;
00220                                              f = graf->nextAt(x,f))
00221                                                 if (!q.member(f)) q.addLast(f);
00222                                 }
00223                                 x = origin[blossoms->find(
00224                                                 graf->mate(x,pEdge[x]))];
00225                         }
00226                 } 
00227         }
00228         t3 = Util::getTime();
00229         pathFindTime += (t3-t2);
00230         return 0;
00231 }
00232 
00239 string& edmonds::statString(bool verbose, string& s) {
00240         stringstream ss;
00241         if (verbose) {
00242                 ss << "iSize=" << iSize << " ";
00243                 ss << "mSize=" << mSize << " ";
00244                 ss << "stepCount=" << stepCount << " ";
00245                 ss << "blossomCount=" << blossomCount << " ";
00246                 ss << "imatchTime=" << imatchTime << " ";
00247                 ss << "rmatchTime=" << rmatchTime << " ";
00248                 ss << "pathInitTime=" << pathInitTime << " ";
00249                 ss << "pathFindTime=" << pathFindTime;
00250         } else {
00251                 ss << iSize << " " << mSize << " ";
00252                 ss << stepCount << " " << blossomCount << " ";
00253                 ss << imatchTime << " "<< rmatchTime << " ";
00254                 ss << pathInitTime << " " << pathFindTime;
00255         }
00256         s = ss.str();
00257         return s;
00258 }
 All Classes Files Functions Variables Typedefs Friends