home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / leda / src / graph_al / _maxflow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-15  |  14.1 KB  |  530 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  2.1.1                                                 11-15-1991
  4. +
  5. +
  6. +  _maxflow.c
  7. +
  8. +
  9. +  Copyright (c) 1991  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15. /******************************************************************************\
  16. *                                                                              *
  17. *  MAX_FLOW                                                                    *
  18. *                                                                              *
  19. *  Max Flow Algorithm, using the Goldberg-Tarjan algorithm, Journal ACM 35,    *
  20. *  Oct 1988, p921-940 .                                                        *
  21. *                                                                              *
  22. *  Applies push steps to vertices with positive preflow, based on              *
  23. *  distance labels.  Uses FIFO rule (implemented by FIFO queue)                *
  24. *  for selecting a vertex with +ve preflow. )                                  *
  25. *                                                                              *
  26. *                                                                              *
  27. *  Implemented by                                                              *
  28. *                                                                              *
  29. *  Joseph Cheriyan & Stefan Naeher                                             *
  30. *                                                                              *
  31. *  Fachbereich Informatik                                                      *
  32. *  Universitaet des Saarlandes                                                 *
  33. *  6600 Saarbruecken                                                           *
  34. *                                                                              *
  35. \******************************************************************************/
  36.  
  37. #include <LEDA/graph_alg.h>
  38.  
  39. static
  40. void gt_bfs2(node s_vert, int dist_s_vert, 
  41.              const graph& G, node s, const edge_array(int)& cap,
  42.              edge_array(int)& flow, node_array(int)& dist);
  43.  
  44.  
  45. int MAX_FLOW(graph& G, node s, node t, const edge_array(int)& cap, 
  46.                                              edge_array(int)& flow) 
  47. {
  48.  
  49. /* Computes a maximum flow from source s to sink t, using
  50.    Goldberg-Tarjan algorithm [Journal ACM 35 (Oct 1988) p921-940].
  51.    ( Applies push steps to vertices with positive preflow, based on 
  52.      distance labels.  Uses FIFO rule (implemented by FIFO queue) 
  53.      for selecting a vertex with +ve preflow. )
  54.  
  55.    input:   cap[e]  gives capacity of edge e 
  56.  
  57.    output:  flow[e] flow on edge e
  58.             returns total flow into sink
  59.  
  60.    node_arrays used by the algorithm:
  61.    dist[v]   = lower bound on shortest distance from v to t
  62.    excess[v] = (total incoming preflow[v]) - (total outgoing preflow[v])
  63.  
  64.    Implemented by  Joseph Cheriyan & Stefan Naeher.
  65. */
  66.  
  67.  
  68. int heuristic = 1;
  69.  
  70.   /*
  71.             heuristic == parameter for heuristic suggested by Goldberg
  72.              to speed up algorithm 
  73.             0 == no heuristic
  74.             1 == compute exact distance labels after every N relabel steps
  75.            +i == compute exact distance labels after every N*i relabel steps
  76.            -i == compute exact distance labels after every N/i relabel steps
  77.  
  78.   */
  79.  
  80. node_array(int)       dist(G,0);
  81. node_array(int)       excess(G,0);
  82.  
  83. list(node) U;     // FIFO Queue used for selecting vertex with +ve preflow
  84. node     v,w;
  85. edge     e;
  86.  
  87. G.make_undirected();
  88.  
  89. int N = G.number_of_nodes();
  90.  
  91. int num_relabels = 0;
  92.  
  93. if (heuristic < -N || heuristic > N) 
  94.     heuristic = 0;
  95. else
  96.     heuristic = ((heuristic >= 0) ? N*heuristic : N/(-heuristic));
  97.  
  98. int  limit_heur = heuristic;
  99.  
  100. if (s == t) error_handler(1,"gt_max_flow: source == sink");
  101.  
  102. forall_edges(e,G)  flow[e] = 0;
  103.  
  104. forall_adj_edges(e,s)
  105. if (source(e) == s)
  106.   { v = target(e);
  107.     flow[e] = cap[e];
  108.     excess[v] += flow[e];
  109.     if (v!=s && v!=t) U.append(v);
  110.   }
  111.  
  112. dist[s] = N;
  113.  
  114. while (! U.empty() )      /* main loop */
  115.   v = U.pop();
  116.  
  117.   int delta;
  118.  
  119.   while ((excess[v] > 0) && G.next_adj_edge(e,v))
  120.     { // push flow along each edge e = (v,w) in the residual graph with
  121.       // dist[v] == dist[w] + 1
  122.   
  123.       if (v == source(e))
  124.       { w = target(e);
  125.  
  126.         if ((dist[v]==dist[w]+1) 
  127.         && (delta = Min(cap[e]-flow[e],excess[v])) 
  128.         && (dist[v] < N))
  129.         // pushes towards s that increase flow[e] are not allowed
  130.  
  131.         { if ((excess[w] == 0) && (w != t)) U.append(w);
  132.           flow[e] += delta;
  133.           excess[w] += delta;
  134.           excess[v] -= delta;
  135.          }
  136.        }
  137.       else
  138.       { w = source(e);
  139.         if ((dist[v] == dist[w]+1) && (delta = Min(flow[e],excess[v])))
  140.         { if ((excess[w] == 0) && (w != t) && (w != s)) U.append(w);
  141.           flow[e] -= delta;
  142.           excess[w] += delta;
  143.           excess[v] -= delta;
  144.          }
  145.        }
  146.   
  147.     }  // while ( (excess[v] > 0) && ...)
  148.   
  149.   
  150.   if (excess[v] > 0)
  151.   {
  152.     // relabel vertex v (i.e. update dist[v]) because all
  153.     // admissible edges in the residual graph have been saturated 
  154.  
  155.     num_relabels++;
  156.   
  157.     if ( heuristic 
  158.         && (num_relabels == limit_heur))
  159.     {
  160.       limit_heur += heuristic;
  161.  
  162.       // heuristic suggested by Goldberg to reduce number of relabels:
  163.       // periodically compute exact dist[] labels by two backward bfs 
  164.       // one starting at t and another starting at s
  165.  
  166.      node x;
  167.  
  168.      forall_nodes(x,G)
  169.      dist[x] = Infinity;
  170.  
  171.      gt_bfs2(t,0,G,s,cap,flow,dist);
  172.      gt_bfs2(s,N,G,s,cap,flow,dist);
  173.  
  174.     }
  175.                   
  176.     else
  177.    
  178.     {
  179.      int min_dist = Infinity;
  180.      forall_adj_edges(e,v)
  181.        {
  182.          if ((source(e) == v) && ((cap[e] - flow[e]) > 0) && (dist[v] < N))
  183.            //pushes towards s that increase flow[e] are not allowed
  184.            min_dist = Min(min_dist,dist[target(e)]);
  185.  
  186.          if ((target(e) == v) && (flow[e] > 0))
  187.            min_dist = Min(min_dist,dist[source(e)]);
  188.         }
  189.       if (min_dist != Infinity) min_dist++;
  190.       dist[v] = min_dist;
  191.  
  192.      } // else
  193.          
  194.       U.push(v);
  195.       G.init_adj_iterator(v);
  196.      
  197.     } // if (excess[v] > 0)
  198.  
  199.  }  // while (!U.empty())  
  200.        
  201.    
  202.  
  203. //code to verify that flow is legal
  204.  
  205.  
  206. /*
  207. int tot_s_flow = 0;
  208. forall_adj_edges(e,s)  
  209.    if (source(e) == s)   tot_s_flow += cap[e];
  210. if (tot_s_flow != (excess[s] + excess[t]))
  211.  { cout << "gt_max_flow: total out cap s != excess[s] + excess[t]\n";
  212.    forall_nodes(v,G)
  213.      if ((excess[v] != 0) && (v != t) && (v != s))
  214.       cout << "gt_max_flow: v!=s,t has excess[v]=" << excess[v] << "\n";
  215.   }
  216. */
  217.  
  218.  
  219. G.make_directed();
  220.  
  221. heuristic = num_relabels;
  222.  
  223. int result = excess[t];  //returns value of maximum flow from s to t
  224.  
  225. return result; 
  226.   
  227. } // procedure gt_max_flow
  228.  
  229.  
  230. //procedure to perform backward bfs starting at vertex s_vert with 
  231. //distance label dist_s_vert
  232.  
  233. static
  234. void gt_bfs2(node s_vert, int dist_s_vert,
  235.              const graph& G, node s, const edge_array(int)& cap,
  236.              edge_array(int)& flow, node_array(int)& dist)
  237. {
  238.   node x,y;
  239.   edge e;
  240.   list(node) bfs_Q;
  241.   int c;
  242.  
  243.   dist[s_vert] = dist_s_vert;
  244.   bfs_Q.append(s_vert);
  245.   while (x = bfs_Q.pop())
  246.     {
  247.       forall_adj_edges(e,x)
  248.         {
  249.           if (x == source(e)) 
  250.         { y = target(e); 
  251.                   c = flow[e]; }
  252.           else 
  253.         { y = source(e); 
  254.                   c = cap[e] - flow[e]; }
  255.  
  256.           if ( c > 0  && dist[y] == Infinity
  257.                       && !(x == target(e) && (s_vert == s)) )
  258.           // while doing bfs with s_vert==s, 
  259.           // only edges with flow[e]>0 are reachable from s
  260.  
  261.           { dist[y] = dist[x] + 1;
  262.             bfs_Q.append(y);
  263.             G.init_adj_iterator(y);
  264.  
  265.         //next statement is not really needed, but is added for
  266.         //protection, to ensure that s does not get relabelled by
  267.         //bfs starting at t; this may lead to decrease in d[v]!
  268.         if (y == s) dist[y] = G.number_of_nodes();
  269.            }
  270.  
  271.          }  //forall (e,...)
  272.  
  273.      }  //while (x == bfs_Q.pop())
  274.  
  275. }  //end gt_bfs2
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282. #ifndef NO_REAL_GRAPH_ALG
  283.  
  284.  
  285. static
  286. void gt_bfs1(node s_vert, int dist_s_vert, 
  287.              const graph& G, node s, const edge_array(real)& cap,
  288.              edge_array(real)& flow, node_array(int)& dist);
  289.  
  290.  
  291.  
  292. real MAX_FLOW(graph& G, node s, node t, const edge_array(real)& cap, 
  293.                                               edge_array(real)& flow) 
  294. {
  295. int heuristic = 1;
  296.  
  297. /* Computes a maximum flow from source s to sink t, using
  298.    Goldberg-Tarjan algorithm [Journal ACM 35 (Oct 1988) p921-940].
  299.    ( Applies push steps to vertices with positive preflow, based on 
  300.      distance labels.  Uses FIFO rule (implemented by FIFO queue) 
  301.      for selecting a vertex with +ve preflow. )
  302.  
  303.    input:   cap[e]  gives capacity of edge e 
  304.  
  305.             heuristic == parameter for heuristic suggested by Goldberg
  306.              to speed up algorithm 
  307.             0 == no heuristic
  308.             1 == compute exact distance labels after every N relabel steps
  309.            +i == compute exact distance labels after every N*i relabel steps
  310.            -i == compute exact distance labels after every N/i relabel steps
  311.  
  312.    output:  flow[e] flow on edge e
  313.         heuristic = number of relabels
  314.  
  315.             returns total flow into sink
  316.  
  317.    node_arrays used by the algorithm:
  318.    dist[v]   = lower bound on shortest distance from v to t
  319.    excess[v] = (total incoming preflow[v]) - (total outgoing preflow[v])
  320.  
  321.    Implemented by  Joseph Cheriyan & Stefan Naeher.
  322. */
  323.  
  324.  
  325.  
  326. node_array(int)       dist(G,0);
  327. node_array(real)      excess(G,0);
  328.  
  329. list(node) U;     // FIFO Queue used for selecting vertex with +ve preflow
  330. node     v,w;
  331. edge     e;
  332.  
  333. G.make_undirected();
  334.  
  335. int N = G.number_of_nodes();
  336.  
  337. int num_relabels = 0;
  338.  
  339. if (heuristic < -N || heuristic > N) 
  340.     heuristic = 0;
  341. else
  342.     heuristic = ((heuristic >= 0) ? N*heuristic : N/(-heuristic));
  343.  
  344. int  limit_heur = heuristic;
  345.  
  346. if (s == t) error_handler(1,"gt_max_flow: source == sink");
  347.  
  348. forall_edges(e,G)  flow[e] = 0;
  349.  
  350. forall_adj_edges(e,s)
  351. if (source(e) == s)
  352.   { v = target(e);
  353.     flow[e] = cap[e];
  354.     excess[v] += flow[e];
  355.     if (v!=s && v!=t) U.append(v);
  356.   }
  357.  
  358. dist[s] = N;
  359.  
  360. while (! U.empty() )      /* main loop */
  361.   v = U.pop();
  362.  
  363.   real delta;
  364.  
  365.   while ((excess[v] > 0) && G.next_adj_edge(e,v))
  366.     { // push flow along each edge e = (v,w) in the residual graph with
  367.       // dist[v] == dist[w] + 1
  368.   
  369.       if (v == source(e))
  370.       { w = target(e);
  371.         real d = cap[e] - flow[e];
  372.         delta = Min(d,excess[v]);
  373.         if ((dist[v]==dist[w]+1) && (delta > 0) && (dist[v] < N))
  374.         // pushes towards s that increase flow[e] are not allowed
  375.         { if ((excess[w] == 0) && (w != t)) U.append(w);
  376.           flow[e] += delta;
  377.           excess[w] += delta;
  378.           excess[v] -= delta;
  379.          }
  380.        }
  381.       else
  382.       { w = source(e);
  383.         delta = Min(flow[e],excess[v]);
  384.         if ((dist[v] == dist[w]+1) && (delta > 0))
  385.         { if ((excess[w] == 0) && (w != t) && (w != s)) U.append(w);
  386.           flow[e] -= delta;
  387.           excess[w] += delta;
  388.           excess[v] -= delta;
  389.          }
  390.        }
  391.   
  392.     }  // while ( (excess[v] > 0) && ...)
  393.   
  394.   
  395.   if (excess[v] > 0)
  396.   {
  397.     // relabel vertex v (i.e. update dist[v]) because all
  398.     // admissible edges in the residual graph have been saturated 
  399.  
  400.     num_relabels++;
  401.   
  402.     if ( heuristic 
  403.         && (num_relabels == limit_heur))
  404.     {
  405.       limit_heur += heuristic;
  406.  
  407.       // heuristic suggested by Goldberg to reduce number of relabels:
  408.       // periodically compute exact dist[] labels by two backward bfs 
  409.       // one starting at t and another starting at s
  410.  
  411.      node x;
  412.  
  413.      forall_nodes(x,G)
  414.      dist[x] = Infinity;
  415.  
  416.      gt_bfs1(t,0,G,s,cap,flow,dist);
  417.      gt_bfs1(s,N,G,s,cap,flow,dist);
  418.  
  419.     }
  420.                   
  421.     else
  422.    
  423.     {
  424.      int min_dist = Infinity;
  425.      forall_adj_edges(e,v)
  426.        {
  427.          real r = cap[e] - flow[e];
  428.  
  429.          if ((source(e) == v) && (r > 0) && (dist[v] < N))
  430.            //pushes towards s that increase flow[e] are not allowed
  431.            min_dist = Min(min_dist,dist[target(e)]);
  432.  
  433.  
  434.          if ((target(e) == v) && (flow[e] > 0))
  435.            min_dist = Min(min_dist,dist[source(e)]);
  436.         }
  437.       if (min_dist != Infinity) min_dist++;
  438.       dist[v] = min_dist;
  439.  
  440.      } // else
  441.          
  442.       U.push(v);
  443.       G.init_adj_iterator(v);
  444.      
  445.     } // if (excess[v] > 0)
  446.  
  447.  }  // while (!U.empty())  
  448.        
  449.    
  450.  
  451. //code to verify that flow is legal
  452.  
  453. /*
  454.  
  455. real tot_s_flow = 0;
  456. forall_adj_edges(e,s)  
  457.    if (source(e) == s)   tot_s_flow += cap[e];
  458. if (tot_s_flow != (excess[s] + excess[t]))
  459.  { cout << "gt_max_flow: total out cap s != excess[s] + excess[t]\n";
  460.    forall_nodes(v,G)
  461.      if ((excess[v] != 0) && (v != t) && (v != s))
  462.       cout << "gt_max_flow: v!=s,t has excess[v]=" << excess[v] << "\n";
  463.   }
  464.  
  465. */
  466.  
  467. G.make_directed();
  468.  
  469. heuristic = num_relabels;
  470.  
  471. real result = excess[t];  //returns value of maximum flow from s to t
  472.  
  473. return result; 
  474.   
  475. } // procedure gt_max_flow
  476.  
  477.  
  478. //procedure to perform backward bfs starting at vertex s_vert with 
  479. //distance label dist_s_vert
  480.  
  481. static
  482. void gt_bfs1(node s_vert, int dist_s_vert,
  483.             const graph& G, node s, const edge_array(real)& cap,
  484.             edge_array(real)& flow, node_array(int)& dist)
  485. {
  486.   node x,y;
  487.   edge e;
  488.   list(node) bfs_Q;
  489.   real c;
  490.  
  491.   dist[s_vert] = dist_s_vert;
  492.   bfs_Q.append(s_vert);
  493.   while (x = bfs_Q.pop())
  494.     {
  495.       forall_adj_edges(e,x)
  496.         {
  497.           if (x == source(e)) 
  498.         { y = target(e); 
  499.                   c = flow[e]; }
  500.           else 
  501.         { y = source(e); 
  502.                   c = cap[e] - flow[e]; }
  503.  
  504.           if ( c > 0  && dist[y] == Infinity
  505.                       && !(x == target(e) && (s_vert == s)) )
  506.           // while doing bfs with s_vert==s, 
  507.           // only edges with flow[e]>0 are reachable from s
  508.  
  509.           { dist[y] = dist[x] + 1;
  510.             bfs_Q.append(y);
  511.             G.init_adj_iterator(y);
  512.  
  513.         //next statement is not really needed, but is added for
  514.         //protection, to ensure that s does not get relabelled by
  515.         //bfs starting at t; this may lead to decrease in d[v]!
  516.         if (y == s) dist[y] = G.number_of_nodes();
  517.            }
  518.  
  519.          }  //forall(e,...)
  520.  
  521.      }  //while(x == bfs_Q.pop())
  522.  
  523. }  //end procedure gt_bfs1
  524.  
  525.  
  526. #endif
  527.