Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/graphAlgorithms/maxFlo/dinicDtrees.cpp
00001 #include "dinicDtrees.h"
00002 
00003 dinicDtrees::dinicDtrees(Flograph& fg1, int& floVal) : fg(&fg1) {
00004         level  = new int[fg->n()+1]; nextEdge = new int[fg->n()+1];
00005         upEdge = new int[fg->n()+1]; dt = new Dtrees(fg->n());
00006 
00007         for (vertex u = 1; u <= fg->n(); u++) {
00008                 dt->addcost(u,Util::BIGINT32);
00009                 level[u] = nextEdge[u] = upEdge[u] = 0;
00010         }
00011 
00012         floVal = 0;
00013         while (newPhase()) {
00014                 while (findPath()) floVal += augment();
00015         }
00016         delete [] level; delete[] upEdge; delete [] nextEdge; delete dt;
00017 }
00018 
00019 dinicDtrees::dinicDtrees(Flograph& fg1, int& floVal, string& stats) : fg(&fg1) {
00020         level  = new int[fg->n()+1]; nextEdge = new int[fg->n()+1];
00021         upEdge = new int[fg->n()+1]; dt = new Dtrees(fg->n());
00022 
00023         for (vertex u = 1; u <= fg->n(); u++) {
00024                 dt->addcost(u,Util::BIGINT32);
00025                 level[u] = nextEdge[u] = upEdge[u] = 0;
00026         }
00027 
00028         floVal = 0;
00029         numPhase = numPaths = 0; avgPathLength = 0; phaseTime = pathTime = 0;
00030         uint32_t t1, t2, t3;
00031         t1 = Util::getTime();
00032         while (newPhase()) {
00033                 t2 = Util::getTime(); phaseTime += (t2-t1);
00034                 numPhase++;
00035                 while (findPath()) {
00036                         t3 = Util::getTime(); pathTime += (t3-t2);
00037                         numPaths++; avgPathLength += level[fg->snk()];
00038 
00039                         floVal += augment();
00040                         t2 = Util::getTime();
00041                 }
00042                 t3 = Util::getTime(); pathTime += (t3-t2);
00043                 t1 = Util::getTime();
00044         }
00045         t2 = Util::getTime(); phaseTime += (t2-t1);
00046         avgPathLength /= numPaths;
00047         stringstream ss;
00048         ss << numPhase << " " << numPaths << " " << avgPathLength
00049            << " " << phaseTime << " " << pathTime;
00050         stats = ss.str();
00051 
00052         delete [] level; delete[] upEdge; delete [] nextEdge; delete dt;
00053 }
00054 
00055 bool dinicDtrees::findPath() {
00056 // Find an augmenting path.
00057         vertex u, v; edge e;
00058 
00059         while (nextEdge[fg->src()] != 0) {
00060                 u = dt->findroot(fg->src()); e = nextEdge[u];
00061                 while (1) { // look for forward path
00062                         if (u == fg->snk()) return true;
00063                         if (e == 0) { nextEdge[u] = 0; break; }
00064                         v = fg->mate(u,e);
00065                         if (fg->res(u,e) > 0 && level[v] == level[u] + 1
00066                             && nextEdge[v] != 0) {
00067                                 dt->addcost(u,fg->res(u,e) - dt->nodeCost(u));
00068                                 dt->link(u,v); upEdge[u] = e;
00069                                 nextEdge[u] = e;
00070                                 u = dt->findroot(fg->src()); e = nextEdge[u];
00071                         } else {
00072                                 e = fg->nextAt(u,e);
00073                         }
00074                 }
00075                 // prune dead-end
00076                 for (e = fg->firstAt(u); e != 0; e = fg->nextAt(u,e)) {
00077                         v = fg->mate(u,e);
00078                         if (u != dt->parent(v) || e != upEdge[v]) continue;
00079                         dt->cut(v); upEdge[v] = 0;
00080                         fg->addFlow(v,e,
00081                                 (fg->cap(v,e)-dt->nodeCost(v)) - fg->f(v,e));
00082                         dt->addcost(v,Util::BIGINT32 - dt->nodeCost(v));
00083                 }
00084         }
00085         return false;
00086 }
00087 
00088 int dinicDtrees::augment() {
00089 // Add flow to the source-sink path defined by the path in the
00090 // dynamic trees data structure
00091         vertex u; edge e;
00092 
00093         NodeCostPair p = dt->findcost(fg->src());
00094         int flo = p.c;
00095         dt->addcost(fg->src(),-flo);
00096         for (p = dt->findcost(fg->src()); p.c==0; p = dt->findcost(fg->src())) {
00097                 u = p.x; e = upEdge[u];
00098                 fg->addFlow(u,e,fg->cap(u,e) - fg->f(u,e));
00099                 dt->cut(u);
00100                 dt->addcost(u,Util::BIGINT32);
00101                 upEdge[u] = 0;
00102         }
00103         return flo;
00104 }
00105 
00106 bool dinicDtrees::newPhase() {
00107 // Prepare for a new phase. Return the number of edges in the source/sink
00108 // path, or 0 if none exists.
00109         vertex u, v; edge e;
00110         List q(fg->n());
00111         for (u = 1; u <= fg->n(); u++) {
00112                 nextEdge[u] = fg->firstAt(u);
00113                 if (dt->parent(u) != 0) { // cleanup from previous phase
00114                         e = upEdge[u];
00115                         fg->addFlow(u,e,
00116                                 (fg->cap(u,e)-dt->nodeCost(u)) - fg->f(u,e));
00117                         dt->cut(u);
00118                         dt->addcost(u,Util::BIGINT32 - dt->nodeCost(u));
00119                         upEdge[u] = 0;
00120                 }
00121                 level[u] = fg->n();
00122         }
00123         q.addLast(fg->src()); level[fg->src()] = 0;
00124         while (!q.empty()) {
00125                 u = q.first(); q.removeFirst();
00126                 for (e = fg->firstAt(u); e != 0; e = fg->nextAt(u,e)) {
00127                         v = fg->mate(u,e);
00128                         if (fg->res(u,e) > 0 && level[v] == fg->n()) {
00129                                 level[v] = level[u] + 1; q.addLast(v);
00130                                 if (v == fg->snk()) return true;
00131                         }
00132                 }
00133         }
00134         return false;
00135 }
 All Classes Files Functions Variables Typedefs Friends