Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/graphAlgorithms/mcFlo/cycRed.cpp
00001 #include "cycRed.h"
00002 
00003 using namespace grafalgo;
00004 
00005 // Find minimum cost, maximum flow in wfg using
00006 // the cycle reduction algorithm. 
00007 cycRed::cycRed(Wflograph& wfg1, flow& floVal, cost& floCost) : wfg(&wfg1) {
00008         vertex u;
00009 
00010         pEdge = new edge[wfg->n()+1];
00011         mark = new int[wfg->n()+1];
00012 
00013         dinicDtrees x(*wfg,floVal);
00014 
00015         while ((u = findCyc()) != 0) augment(u);
00016 
00017         floCost = 0;
00018         for (edge e = 1; e <= wfg->m(); e++) {
00019                 vertex u = wfg->tail(e);
00020                 floCost += wfg->f(u,e)*wfg->cost(u,e);
00021         }
00022 }
00023 
00024 void cycRed::augment(vertex z) {
00025 // Add flow to cycle defined by pEdge pointers that includes z.
00026         vertex u, v; edge e; flow f;
00027 
00028         // determine residual capacity of cycle
00029         f = Util::BIGINT32;
00030         u = z; e = pEdge[u];
00031         do {
00032                 v = wfg->mate(u,e);
00033                 f = min(f,wfg->res(v,e));
00034                 u = v; e = pEdge[u];
00035         } while (u != z);
00036 
00037         // add flow to saturate cycle
00038         u = z; e = pEdge[u];
00039         do {
00040                 v = wfg->mate(u,e);
00041                 wfg->addFlow(v,e,f);
00042                 u = v; e = pEdge[u];
00043         } while (u != z);
00044 }
00045 
00046 vertex cycRed::findCyc() {
00047 // Find a negative cost cycle in the residual graph.
00048 // If a cycle is found, return some vertex on the cycle,
00049 // else 0. In the case there is a cycle, you can traverse
00050 // the cycle by following pEdge pointers from the returned vertex.
00051 
00052         vertex u,v,last; edge e;
00053         int c[wfg->n()+1];
00054         List q(wfg->n());
00055 
00056         for (u = 1; u <= wfg->n(); u++) { 
00057                 pEdge[u] = 0; c[u] = 0; q.addLast(u);
00058         }
00059 
00060         last = q.last(); // each pass completes when last removed from q
00061         while (!q.empty()) {
00062                 u = q.first(); q.removeFirst();
00063                 for (e = wfg->firstAt(u); e != 0; e = wfg->nextAt(u,e)) {
00064                         if (wfg->res(u,e) == 0) continue;
00065                         v = wfg->mate(u,e);
00066                         if (c[v] > c[u] + wfg->cost(u,e)) {
00067                                 pEdge[v] = e;
00068                                 c[v] = c[u] +  wfg->cost(u,e);
00069                                 if (!q.member(v)) q.addLast(v);
00070                         }
00071                 }
00072 
00073                 if (u == last) {
00074                         v = cycleCheck();
00075                         if (v != 0) return v;
00076                         last = q.last();
00077                 }
00078         }
00079         return 0;
00080 }
00081 
00082 vertex cycRed::cycleCheck() {
00083 // If there is a cycle defined by the pEdge pointers, return
00084 // some vertex on the cycle, else null.
00085         vertex u,v; edge e; int cm;
00086 
00087         for (u = 1; u <= wfg->n(); u++) { mark[u] = 0; }
00088         u = 1; cm = 1;
00089         while(u <= wfg->n()) {
00090                 // follow parent pointers from u, marking new vertices
00091                 // seen with the value of cm, so we can recognize a loop
00092                 v = u; 
00093                 while (mark[v] == 0) {
00094                         mark[v] = cm;
00095                         e = pEdge[v];
00096                         if (e == 0) break;
00097                         v = wfg->mate(v,e);
00098                 }
00099                 if (mark[v] == cm && e != 0) return v;
00100                 
00101                 // find next unmarked vertex 
00102                 while (u <= wfg->n() && mark[u] != 0) u++;
00103                 cm++;
00104         }
00105         return 0;
00106 }
 All Classes Files Functions Variables Typedefs Friends