Main Page   Class Hierarchy   Compound List   File List   Contact   Download   Symbolic Constraints   Examples  

ghc_tree.c

00001 #include <stdlib.h>
00002 #include <stdio.h>
00003 #include "graph.h"
00004 
00005 
00006 static node **active;
00007 static long *number;
00008 static long max_dist, bound;
00009 static BOOL co_check;
00010 
00011   /* This maxflow version is for undirected graphs and
00012      computes maximum flow only, i.e. the resulting flow
00013      is not computed for all edges, the graph structure
00014      is expected to be initialized already, the function
00015      "init_maxflow" must be called first, then "maxflow"
00016      may be called any number of times, the function 
00017      "fini_maxflow" should be called after the final 
00018      maxflow call.                                      */
00019 
00020 
00021 BOOL init_maxflow (long n)
00022 {
00023   active = (node **) malloc ((n+1L) * sizeof (node *));
00024     /* holds stacks of active nodes arranged by distances */ 
00025   if (active == (node **) 0)
00026    { printf ("Unable to allocate memory\n");
00027      return (FALSE);
00028    }
00029   number = (long *) malloc ((n+1L) * sizeof (long));
00030     /* counts occurences of node distances in set 
00031        of alive nodes, i.e. nodes not contained in
00032        the set of nodes disconnected from the sink */ 
00033   if (number == (long *) 0)
00034    { printf ("Unable to allocate memory\n");
00035      return (FALSE);
00036    }
00037   co_check = TRUE;
00038   return (TRUE);
00039 
00040 } /* init_maxflow */
00041 
00042 
00043 void fini_maxflow ()
00044 {
00045   free (active);
00046   free (number);
00047 
00048 } /* fini_maxflow */
00049 
00050 
00051 void global_relabel (graph *gr, node *tptr)
00052 { 
00053   /* breadth first search to get exact distance labels
00054      from sink with reordering of stack of active nodes */
00055 
00056   node *front, *rear, *nptr, **ptr;
00057   edge *eptr;
00058   long n, level, count, i;
00059 
00060   n = gr->n_nodes;
00061   for (nptr = &(gr->nodes[n-1L]); nptr >= gr->nodes; nptr--)
00062     { nptr->unmarked = TRUE;
00063       nptr->stack_link = NILN;
00064       nptr->scan_ptr = nptr->first_edge;
00065     }
00066   tptr->unmarked = FALSE;
00067      /* initialize stack of active nodes */
00068   for (ptr = &(active[n]); ptr >= active; ptr--)
00069     *ptr = NILN;
00070   for (i = 0L; i <= n; i++)
00071     number[i] = 0L;
00072   max_dist = 0L;
00073   count = 1L;     /* number of alive nodes */
00074   front = tptr;
00075   rear = front;
00076 
00077  bfs_next:
00078   level = rear->dist + 1L;
00079   eptr = rear->first_edge;
00080   while (eptr != NILE)
00081      { nptr = eptr->adjac;
00082        if (nptr->alive && nptr->unmarked
00083                        && eptr->back->rcap > EPS) 
00084         { nptr->unmarked = FALSE;
00085           nptr->dist = level;
00086           ++count;
00087           ++number[level];
00088           if (nptr->excess > EPS)
00089            { nptr->stack_link = active[level];
00090              active[level] = nptr;
00091              max_dist = level;
00092            }
00093           front->bfs_link = nptr;
00094           front = nptr;
00095         }
00096        eptr = eptr->next;
00097      }
00098   if (front == rear)
00099     goto bfs_ready;
00100        
00101   rear = rear->bfs_link;
00102   goto bfs_next;
00103 
00104  bfs_ready: 
00105 
00106   if (count < bound)
00107    { /* identify nodes that are marked alive but have
00108         not been reached by BFS and mark them as dead  */
00109      for (nptr = &(gr->nodes[n-1L]); nptr >= gr->nodes; nptr--)
00110        if (nptr->unmarked && nptr->alive)
00111         { nptr->dist = n;
00112           nptr->alive = FALSE;
00113         }
00114      bound = count;
00115    }
00116 
00117 } /* global_relabel */
00118 
00119 
00120 double maxflow (graph *gr, node *s_ptr, node *t_ptr)
00121 {
00122   /* Determines maximum flow and minimum cut between nodes
00123      s (= *s_ptr) and t (= *t_ptr) in an undirected graph  
00124 
00125      References:
00126      ----------
00127      A. Goldberg/ E. Tarjan: "A New Approach to the
00128      Maximum Flow Problem", in Proc. 18th ACM Symp. 
00129      on Theory of Computing, 1986.
00130   */
00131   node *aptr, *nptr, *q_front, *q_rear;
00132   node **ptr;
00133   edge *eptr;
00134   long n, m, m0, level, i, n_discharge;
00135   double incre;
00136   long count, dist, dmin, *upper, *lower;
00137   double cap;
00138   char any;
00139    
00140   /* node ids range from 1 to n, node array indices  
00141      range from 0 to n-1                             */
00142 
00143   n = gr->n_nodes;
00144   for (nptr = &(gr->nodes[n-1L]); nptr >= gr->nodes; nptr--)
00145     {  nptr->scan_ptr = nptr->first_edge;
00146        /* 
00147        fprintf (stderr, "number of edges:%d\n", gr->n_edges);
00148        fprintf (stderr, "number of edges0:%d\n", gr->n_edges0);
00149           */
00150        if (nptr->scan_ptr == NILE)
00151         { fprintf (stderr, "isolated node in input graph\n");
00152           return (FALSE);
00153         }
00154        nptr->excess = 0.0L;
00155        nptr->stack_link = NILN;
00156        nptr->alive = TRUE;
00157        nptr->unmarked = TRUE;
00158     }
00159   m = gr->n_edges;
00160   m0 = gr->n_edges0;
00161   for (eptr = &(gr->edges[m-1L]); eptr >= gr->edges; eptr--)
00162      eptr->rcap = eptr->cap;
00163   for (eptr = &(gr->edges[m0+m-1L]); eptr >= &(gr->edges[m0]); eptr--)
00164      eptr->rcap = eptr->cap;
00165       
00166   for (i = n; i >= 0L; i--)
00167     { number[i] = 0L;
00168       active[i] = NILN;
00169     }
00170   t_ptr->dist = 0L;
00171 
00172     /* breadth first search to get exact distances 
00173        from sink and for test of graph connectivity */
00174 
00175   t_ptr->unmarked = FALSE; 
00176   q_front = t_ptr;
00177   q_rear = q_front;
00178  bfs_next:
00179   level = q_rear->dist + 1L;
00180   eptr = q_rear->first_edge;
00181   while (eptr != NILE)
00182      { if (eptr->adjac->unmarked && eptr->back->rcap > EPS)
00183         { nptr = eptr->adjac;
00184           nptr->unmarked = FALSE;
00185           nptr->dist = level;
00186           ++number[level];
00187           q_front->bfs_link = nptr;
00188           q_front = nptr;
00189         }
00190        eptr = eptr->next;
00191      }
00192   if (q_rear == q_front)
00193     goto bfs_ready;
00194 
00195   q_rear = q_rear->bfs_link;
00196   goto bfs_next;
00197 
00198  bfs_ready:
00199   if (co_check)
00200    { co_check = FALSE;
00201      for (nptr = &(gr->nodes[n-1]); nptr >= gr->nodes; --nptr)
00202        if (nptr->unmarked)
00203         { fprintf (stderr,"Input graph not connected\n");
00204           return (-1.0L);
00205         }
00206    }
00207 
00208 
00209   s_ptr->dist = n; /* number[0] and number[n] not required */
00210   t_ptr->dist = 0L;
00211   t_ptr->excess = 1.0L;  /* to be subtracted again */
00212 
00213 
00214   /* initial preflow push from source node */
00215 
00216   max_dist = 0L;  /* = max_dist of active nodes */
00217   eptr = s_ptr->first_edge;
00218   while (eptr != NILE)
00219      { nptr = eptr->adjac;
00220        cap = eptr->rcap;
00221        nptr->excess += cap;
00222        s_ptr->excess -= cap;
00223        eptr->back->rcap += cap;
00224        eptr->rcap = 0.0L;
00225 
00226        if (nptr != t_ptr && nptr->excess <= cap + EPS) 
00227         { /* push node nptr onto stack for nptr->dist,
00228              but only once in case of double edges     */
00229           nptr->stack_link = active[nptr->dist];
00230           active[nptr->dist] = nptr;
00231           if (nptr->dist > max_dist)
00232             max_dist = nptr->dist;
00233         }
00234        eptr = eptr->next;
00235      }
00236 
00237   s_ptr->alive = FALSE;
00238   bound = n; 
00239   n_discharge = 0L;
00240 
00241   /* main loop */
00242 
00243   do { /* get maximum distance active node */
00244        aptr = active[max_dist];
00245        while (aptr != NILN)
00246          { active[max_dist] = aptr->stack_link;
00247            eptr = aptr->scan_ptr;
00248 
00249            edge_scan:  /* for current active node  */
00250              nptr = eptr->adjac;
00251              if (nptr->dist == aptr->dist - 1L &&
00252                  eptr->rcap > EPS) 
00253               { incre = aptr->excess;
00254                 if (incre <= eptr->rcap)
00255                  { /* perform a non saturating push */
00256                    eptr->rcap -= incre;
00257                    eptr->back->rcap += incre;
00258                    aptr->excess = 0.0L;
00259                    nptr->excess += incre;
00260                    if (nptr->excess <= incre + EPS)
00261                     { /* push nptr onto active stack */
00262                       nptr->stack_link = active[nptr->dist];
00263                       active[nptr->dist] = nptr;
00264                     }
00265                    aptr->scan_ptr = eptr;
00266                    goto node_ready;
00267                  }
00268                 else
00269                  { /* perform a saturating push */
00270                    incre = eptr->rcap;
00271                    eptr->back->rcap += incre; 
00272                    aptr->excess -= incre;
00273                    nptr->excess += incre;
00274                    eptr->rcap = 0.0L;
00275                    if (nptr->excess <= incre + EPS)
00276                     { /* push nptr onto active stack */
00277                       nptr->stack_link = active[nptr->dist];
00278                       active[nptr->dist] = nptr;
00279                     }
00280                    if (aptr->excess <= EPS)
00281                     { aptr->scan_ptr = eptr;
00282                       goto node_ready;
00283                     }
00284                  }
00285               }
00286              if (eptr->next == NILE) 
00287               { /* all incident arcs scanned, but node still
00288                    has positive excess, check if for all nptr       
00289                    nptr->dist != aptr->dist                  */
00290 
00291                 if (number[aptr->dist] == 1L)
00292                  { /* put all nodes v with dist[v] >= dist[a] 
00293                       into the set of "dead" nodes since they
00294                       are disconnected from the sink          */
00295                      
00296                    for (nptr = &(gr->nodes[n-1L]);
00297                         nptr >= gr->nodes; nptr--)
00298                      if (nptr->alive &&
00299                          nptr->dist > aptr->dist)
00300                       { --number[nptr->dist];
00301                         active[nptr->dist] = NILN; 
00302                         nptr->alive = FALSE; 
00303                         nptr->dist = n;
00304                         --bound;
00305                       }
00306                    --number[aptr->dist];
00307                    active[aptr->dist] = NILN;
00308                    aptr->alive = FALSE;
00309                    aptr->dist = n;
00310                    --bound;
00311                    goto node_ready;
00312                  }
00313                 else
00314                  { /* determine new label value */
00315                    dmin = n;
00316                    aptr->scan_ptr = NILE;
00317                    eptr = aptr->first_edge;
00318                    while (eptr != NILE)
00319                       { if (eptr->adjac->dist < dmin
00320                             && eptr->rcap > EPS)
00321                          { dmin = eptr->adjac->dist;
00322                            if (aptr->scan_ptr == NILE)
00323                              aptr->scan_ptr = eptr;
00324                          }
00325                         eptr = eptr->next;
00326                       }
00327                    if (++dmin < bound)
00328                     { /* ordinary relabel operation */
00329                       --number[aptr->dist];
00330                       aptr->dist = dmin;
00331                       ++number[dmin];
00332                       max_dist = dmin;
00333                       eptr = aptr->scan_ptr;
00334                       goto edge_scan;
00335                     }
00336                    else
00337                     { aptr->alive = FALSE;
00338                       --number[aptr->dist];
00339                       aptr->dist = n;
00340                       --bound;
00341                       goto node_ready;
00342                     }
00343                  }
00344               }
00345              else
00346               { eptr = eptr->next;
00347                 goto edge_scan;
00348               }
00349 
00350           node_ready: 
00351            ++n_discharge;
00352            if (n_discharge == n)
00353             { n_discharge = 0L;
00354               global_relabel (gr, t_ptr);
00355             }
00356            aptr = active[max_dist];
00357          } /* aptr != NILN */ 
00358        --max_dist;
00359      } 
00360   while (max_dist > 0L);  
00361 
00362   return (t_ptr->excess - 1.0L);
00363 }
00364 
00365 BOOL ghc_tree (graph *gr)
00366 {
00367   /* Determines Gomory/Hu cut tree for input graph with
00368      capacitated edges, the tree structures is represented
00369      by parent pointers which are part of the node structure,
00370      the capacity of a tree edge is stored at the child node,
00371      the root of the cut tree is the first node in the list
00372      of graph nodes (&gr->nodes[0]). The implementation is
00373      described in [1].
00374      
00375      References:
00376      ----------
00377      1) D. Gusfield: "Very Simple Algorithms and Programs for
00378         All Pairs Network Flow Analysis", Computer Science Di-
00379         vision, University of California, Davis, 1987.
00380      
00381      2) R.E. Gomory and T.C. Hu: "Multi-Terminal Network Flows",
00382         SIAM J. Applied Math. 9 (1961), 551-570.
00383 
00384    */
00385 
00386   node *nptr, *nptr1, *nptrn, *sptr, *tptr;
00387   edge *eptr;
00388   long n, m;
00389   double maxfl;
00390 
00391   
00392   n = gr->n_nodes;
00393   m = gr->n_edges;
00394 
00395   if (! init_maxflow (n))
00396     return (FALSE);
00397 
00398   nptr1 = gr->nodes;
00399   nptrn = &(gr->nodes[n-1L]);
00400   for (nptr = nptrn; nptr >= nptr1; nptr--)
00401     nptr->parent = nptr1;
00402 
00403   for (sptr = &(gr->nodes[1L]); sptr <= nptrn; sptr++)
00404     { tptr = sptr->parent;
00405       maxfl = maxflow (gr, sptr, tptr);
00406       if (maxfl < 0L)
00407         return (FALSE);
00408       
00409       sptr->mincap = maxfl;
00410       for (nptr = &(gr->nodes[1L]); nptr <= nptrn; nptr++)
00411         if (nptr != sptr &&  
00412             ! nptr->alive && nptr->parent == tptr)
00413           nptr->parent = sptr;
00414       if (! tptr->parent->alive)
00415        { sptr->parent = tptr->parent;
00416          tptr->parent = sptr;
00417          sptr->mincap = tptr->mincap;
00418          tptr->mincap = maxfl;
00419        }
00420     }
00421   fini_maxflow ();
00422 
00423 } /* ghc_tree */
Generated on Mon Mar 28 22:03:48 2011 for SCIL by  doxygen 1.6.3