Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/graphAlgorithms/mcFlo/lcap.cpp
00001 #include "lcap.h"
00002 
00003 using namespace grafalgo;
00004 
00005 lcap::lcap(Wflograph& wfg1, flow& flowVal, floCost& flowCost, bool mostNeg) : wfg(&wfg1) {
00006 // Find minimum cost, flow in wfg using the least-cost augmenting path
00007 // algorithm.  If the mostNeg flag is true, the algorithm finds a
00008 // flow with the largest negative cost. Otherwise, it finds a min
00009 // cost, max flow.  Returns flow value in floVal and cost in floCost.
00010 
00011         lab = new int[wfg->n()+1];
00012         pEdge = new edge[wfg->n()+1];
00013 
00014         initLabels();
00015         flowVal = flowCost = 0;
00016         while (findpath()) {
00017                 flow nuFlo; floCost pathCost;
00018                 pathRcapCost(nuFlo,pathCost);
00019                 if (mostNeg && pathCost >= 0) break;
00020                 augment(nuFlo);
00021                 flowVal += nuFlo; flowCost += nuFlo*pathCost;
00022         }
00023         delete [] lab; delete [] pEdge;
00024 }
00025 
00026 
00027 void lcap::initLabels() {
00028 // Compute values for labels that give non-negative transformed costs.
00029 // The labels are the least cost path distances from an imaginary
00030 // vertex with a length 0 edge to every vertex in the graph.
00031 // Uses the breadth-first scanning algorithm to compute shortest
00032 // paths.
00033         int pass;
00034         vertex u, v,last; edge e;
00035         List q(wfg->n());
00036 
00037         for (u = 1; u <= wfg->n(); u++) {
00038                 pEdge[u] = 0; lab[u] = 0; q.addLast(u);
00039         }
00040         pass = 0; last = q.last();
00041         while (!q.empty()) {
00042                 u = q.first(); q.removeFirst();
00043                 for (e = wfg->firstAt(u); e != 0; e = wfg->nextAt(u,e)) {
00044                         v = wfg->head(e);
00045                         if (v == u) continue;
00046                         if (lab[v] > lab[u] + wfg->cost(u,e)) {
00047                                 lab[v] = lab[u] + wfg->cost(u,e); pEdge[v] = e;
00048                                 if (!q.member(v)) q.addLast(v);
00049                         }
00050                 }
00051                 if (u == last && !q.empty()) { pass++; last = q.last(); }
00052                 if (pass == wfg->n())
00053                         Util::fatal("initLabels: negative cost cycle");
00054         }
00055 }
00056 
00057 bool lcap::findpath() {
00058 // Find a least cost augmenting path.
00059         vertex u,v; edge e;
00060         int c[wfg->n()+1]; Dheap S(wfg->n(),4);
00061 
00062         for (u = 1; u <= wfg->n(); u++) { pEdge[u] = 0; c[u] = Util::BIGINT32; }
00063         c[wfg->src()] = 0; S.insert(wfg->src(),0);
00064         while (!S.empty()) {
00065                 u = S.deletemin();
00066                 for (e = wfg->firstAt(u); e != 0; e = wfg->nextAt(u,e)) {
00067                         if (wfg->res(u,e) == 0) continue;
00068                         v = wfg->mate(u,e);
00069                         if (c[v] > c[u] + wfg->cost(u,e) + (lab[u] - lab[v])) {
00070                                 pEdge[v] = e;
00071                                 c[v] = c[u] +  wfg->cost(u,e) + (lab[u] - lab[v]);
00072                                 if (!S.member(v)) S.insert(v,c[v]);
00073                                 else S.changekey(v,c[v]);
00074                         }
00075                 }
00076         }
00077         // update labels for next round
00078         for (u = 1; u <= wfg->n(); u++) lab[u] += c[u];
00079         return (pEdge[wfg->snk()] != 0 ? true : false);
00080 }
00081 
00082 void lcap::pathRcapCost(flow& rcap, floCost& pc) {
00083 // Return the residual capacity and cost of the path defined by pEdge
00084 // in rcap and pc.
00085         vertex u, v; edge e;
00086 
00087         rcap = Util::BIGINT32; pc = 0;
00088         u = wfg->snk(); e = pEdge[u];
00089         while (u != wfg->src()) {
00090                 v = wfg->mate(u,e);
00091                 rcap = min(rcap,wfg->res(v,e)); pc += wfg->cost(v,e);
00092                 u = v; e = pEdge[u];
00093         }
00094 }
00095 
00096 void lcap::augment(flow& f) {
00097 // Add f units of flow to the path defined by pEdge.
00098         vertex u, v; edge e;
00099 
00100         u = wfg->snk(); e = pEdge[u];
00101         while (u != wfg->src()) {
00102                 v = wfg->mate(u,e);
00103                 wfg->addFlow(v,e,f);
00104                 u = v; e = pEdge[u];
00105         }
00106 }
 All Classes Files Functions Variables Typedefs Friends