Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/graphAlgorithms/mcFlo/scale.cpp
00001 // WORK IN PROGRESS - convert to implement the scaling algorithm
00002 // Coding started, but not yet complete.
00003 
00004 // usage: scale
00005 //
00006 // Scale reads a Wflograph from stdin, and computes a minimum cost
00007 // maximum flow between vertices 1 and n using the scaling algorithm
00008 //
00009 // This program is not bullet-proof. Caveat emptor.
00010 
00011 #include "stdinc.h"
00012 #include "Wflograph.h"
00013 #include "List.h"
00014 #include "Dheap.h"
00015 #include "dinic.h"
00016 
00017 using namespace grafalgo;
00018 
00019 void scale(flograph&);
00020 void initLabels(flograph&, int*);
00021 void findpath(flograph&, int*, list&);
00022 
00023 int main() {
00024         Wflograph wfg; cin >> wfg;
00025         lcap(wfg); cout << wfg;
00026 }
00027 
00028 class scale {
00029         flograph* wfg;            // graph we're finding flow on
00030         int*    lab;            // lab[u]=distance label for transformed costs
00031         int*    excess;         // excess[u]=excess flow entering u
00032         list*   slist;          // Source vertices
00033         list*   tlist;          // Sink vertices
00034         int     Delta;          // Current scaling factor
00035         vertex  cs;             // current source vertex
00036 
00037         int     findpath(vertex,list&); // find augmenting path
00038         void    augment(list&); // add flow to augmenting path
00039         int     newphase();     // prepare for a new phase
00040         int     initLabels();   // assign initial values to labels
00041 public: scale(flograph*);       // main program
00042 };
00043 
00044 scale::scale(flograph& wfg1) {
00045 void scale(flograph& wfg) {
00046 // Find minimum cost maximum flow in wfg using the scaling algorithm.
00047 // Assumes that the original graph has no negative cost cycles.
00048         int flo;
00049 
00050         vertex u; edge e; 
00051         flow maxcap;
00052         list p(wfg.m);
00053 
00054         wfg = &wfg1;
00055         lab = new int[wfg.n+1]; excess = new int[wfg.n+1];
00056         slist = new List(wfg.n); tlist = new List(wfg.n);
00057 
00058         for (u = 1; u <= wfg.n; u++) lab[u] = excess[u] = 0;
00059 
00060         // Initialize scaling factor
00061         maxcap = 0;
00062         for (e = 1; e <= wfg.m; e++) 
00063                 maxcap = max(maxcap,wfg.cap(wfg.tail(e),e));
00064         for (Delta = 1; 2*Delta <= maxcap; Delta <<= 1) {}
00065 
00066         // Determine a max flow so that we can initialize excess
00067         // values at s and t
00068         dinic(wfg,flo);
00069         for (e = wfg->firstAt(1); e != 0; e = wfg->nextAt(1,e)) 
00070                 excess[1] += wfg->f(1,e);
00071         excess[wfg->n] = -excess[1];
00072         for (e = wfg->firstAt(1); e != 0; e = wfg->nextAt(1,e)) {
00073                 u = wfg->tail(e); wfg->addflow(u,e,-(wfg->f(u,e)));
00074         }
00075 
00076         initLabels();
00077 
00078         while (newphase()) {
00079                 while (findpath(u,p))  {
00080                         augment(p);
00081                 }
00082                 Delta /= 2;
00083         }
00084         delete [] lab; delete [] excess;
00085         delete slist; delete tlist;
00086 }
00087 
00088 void initLabels() {
00089 // Compute values for labels that give non-negative transformed costs.
00090 // The labels are the least cost path distances from an imaginary
00091 // vertex with a length 0 edge to every vertex in the graph.
00092 // Uses the breadth-first scanning algorithm to compute shortest
00093 // paths.
00094         int pass;
00095         vertex v, w,last; edge e;
00096         vertex *p = new vertex[wfg.n+1];
00097         List q(wfg.n);
00098 
00099         for (v = 1; v <= wfg.n; v++) {
00100                 p[v] = 0; lab[v] = 0; q &= v;
00101         }
00102 
00103         pass = 0; last = wfg.n;
00104 
00105         while (!empty()) {
00106                 v = q.first(); q.removeFirst();
00107                 for (e = wfg.firstAt(v); e != 0; e = wfg.nextAt(v,e)) {
00108                         w = wfg.head(e);
00109                         if (w == v) continue;
00110                         if (lab[w] > lab[v] + wfg.cost(v,e)) {
00111                                 lab[w] = lab[v] + wfg.cost(v,e); p[w] = v;
00112                                 if (!q.member(w)) q.addLast(w);
00113                         }
00114                 }
00115                 if (v == last && !q.empty()) { pass++; last = q.last(); }
00116                 if (pass == wfg.n) Util::fatal("initLabels: negative cost cycle");
00117         }
00118 }
00119 
00120 void newPhase() {
00121 // Do start of phase processing.
00122 
00123         // identify unbalanced vertices
00124         slist.clear(); tlist.clear();
00125         for (u = 2; u < wfg->n; u++) {
00126                 if (excess[u] > 0) slist &= u;
00127                 else if (excess[u] < 0) tlist &= u;
00128         }
00129         // Put source and sink at end of lists.
00130         slist &= 1; tlist &= wfg->n;
00131 
00132 
00133         // If any edge violates labeling condition, add Delta units of
00134         // flow to it. This eliminates it from the residual graph for
00135         // the current scaling factor.
00136 
00137         vertex u,v; edge e;
00138 
00139         for (e = 1; e <= wfg.m; e++) {
00140                 u = wfg.tail(e); v = wfg.head(e);
00141                 if (wfg.res(u,e) >= Delta) {
00142                         if (wfg.cost(u,e) + lab[u] - lab[v] < 0) {
00143                                 wfg.addflow(u,e,Delta);
00144                                 excess[u] -= Delta; excess[v] += Delta;
00145                         }
00146                 }
00147                 if (wfg.res(v,e) >= Delta) {
00148                         if (wfg.cost(v,e) + lab[v] - lab[u] < 0) {
00149                                 wfg.addflow(v,e,Delta);
00150                                 excess[v] -= Delta; excess[u] += Delta;
00151                         }
00152                 }
00153         }
00154 }
00155 
00156 
00157 void findpath(flograph& wfg, int Delta, int* lab, list& p) {
00158 // Find a least cost augmenting path and update the labels.
00159         vertex u,v; edge e;
00160         edge *pathedge = new edge[wfg.n+1];
00161         int *c = new int[wfg.n+1];
00162         Dheap S(wfg.n,2);
00163 
00164         for (u = 1; u <= wfg.n; u++) { pathedge[u] = 0; c[u] = BIGINT; }
00165         c[1] = 0; S.insert(1,0);
00166         while (!S.empty()) {
00167                 u = S.deletemin();
00168                 for (e = wfg.first(u); e != 0; e = wfg.next(u,e)) {
00169                         if (wfg.res(u,e) < Delta) continue;
00170                         v = wfg.mate(u,e);
00171                         if (c[v] > c[u] + wfg.cost(u,e) + (lab[u] - lab[v])) {
00172                                 pathedge[v] = e;
00173                                 c[v] = c[u] +  wfg.cost(u,e) + (lab[u]-lab[v]);
00174                                 if (!S.member(v)) S.insert(v,c[v]);
00175                                 else S.changekey(v,c[v]);
00176                         }
00177                 }
00178         }
00179         p.clear();
00180         for (u = wfg.n; pathedge[u] != 0; u = wfg.mate(u,pathedge[u])) {
00181                 p.push(pathedge[u]);
00182         }
00183         for (u = 1; u <= wfg.n; u++) {
00184                 lab[u] += c[u];
00185         }
00186         delete [] pathedge; delete [] c;
00187         return;
00188 }
00189 
00190 void augment(Wflograph& wfg,p) {
00191 // Augment the flow wfg along the path p.
00192         vertex u; edge e;
00193         
00194         f = BIGINT;
00195         u = 1;
00196         for (e = p(1); e != 0; e = p.suc(e)) {
00197                 f = min(f,wfg.res(u,e)); u = wfg.mate(u,e);
00198         }
00199         u = 1;
00200         for (e = p(1); e != 0; e = p.suc(e)) {
00201                 wfg.addflow(u,e,f); u = wfg.mate(u,e);
00202         }
00203         return;
00204 }
00205 
 All Classes Files Functions Variables Typedefs Friends