OpenADFortTk (including Open64 and OpenAnalysis references)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
mfmc_solve.cxx
Go to the documentation of this file.
1 /*
2 
3  Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved.
4 
5  This program is free software; you can redistribute it and/or modify it
6  under the terms of version 2 of the GNU General Public License as
7  published by the Free Software Foundation.
8 
9  This program is distributed in the hope that it would be useful, but
10  WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13  Further, this software is distributed without any warranty that it is
14  free of the rightful claim of any third person regarding infringement
15  or the like. Any license provided herein, whether implied or
16  otherwise, applies only to this software file. Patent licenses, if
17  any, provided herein do not apply to combinations of this program with
18  other software, or any other product whatsoever.
19 
20  You should have received a copy of the GNU General Public License along
21  with this program; if not, write the Free Software Foundation, Inc., 59
22  Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 
24  Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky,
25  Mountain View, CA 94043, or:
26 
27  http://www.sgi.com
28 
29  For further information regarding this notice, see:
30 
31  http://oss.sgi.com/projects/GenInfo/NoticeExplan
32 
33 */
34 
35 
36 /* ----------------------------------------------------------------------
37  * This code adapted by Robert Kennedy from a Push-Relabel
38  * implementation developed in 1994 at the Stanford University
39  * department of Computer Science by Boris Cherkassky and Andrew
40  * Goldberg ([email protected]).
41  *
42  * The program implements the "highest level" node selection strategy
43  * with the global relabeling and gap relabeling heuristics.
44  * ----------------------------------------------------------------------
45  */
46 #if 0
47 
48 #include <sys/types.h>
49 #include <sys/times.h>
50 
51 #include "mfmc_defs.h"
52 
53 #define GLOB_UPDT_FREQ 1.0
54 
55 /* global variables */
56 
57 static INT32 n; /* number of nodes */
58 static MFMC_NODE *nodes; /* array of nodes */
59 static MFMC_ARC *arcs; /* array of arcs */
60 static MFMC_LAYER *layers; /* array of layers */
61 static INT64 *cap; /* array of capacities */
62 static MFMC_NODE *source; /* origin */
63 static MFMC_NODE *sink; /* destination */
64 static MFMC_STATS *stats; /* statistics */
65 static MFMC_NODE **queue; /* queue for storing nodes */
66 static MFMC_NODE **q_read, **q_write; /* queue pointers */
67 
68 static INT32 lmax; /* maximal layer */
69 static INT32 lmax_push; /* maximal layer with excess node */
70 static INT32 lmin_push; /* minimal layer with excess node */
71 
72 static INT64 biggest_flow; /* upper bound on the flow value */
73 /*--- initialization */
74 
75 /*********************************************************************/
76 /* */
77 /* current processor time in seconds */
78 /* difference between two calls is processor time spent by your code */
79 /* needs: <sys/types.h>, <sys/times.h> */
80 /* depends on compiler and OS */
81 /* */
82 /*********************************************************************/
83 
84 float timer(void)
85 {
86  struct tms hold;
87 
88  times(&hold);
89  return (float) hold.tms_utime / 60.0;
90 }
91 
92 static BOOL
93 pr_init(INT32 n_p, /* number of nodes */
94  MFMC_NODE *nodes_p, /* array of nodes */
95  MFMC_ARC *arcs_p, /* array of arcs */
96  INT64 *cap_p, /* array of given capacities */
97  MFMC_NODE *source_p, /* the source node */
98  MFMC_NODE *sink_p, /* the sink node */
99  MFMC_NODE **queue_p, /* the BFS node queue */
100  MFMC_LAYER *layers_p, /* distance level structure */
101  MFMC_STATS *stats_p, /* statistics block */
102  INT64 flow_upper_bound) /* flow value upper bound */
103 
104 {
105  MFMC_NODE *i; /* current node */
106 
107  n = n_p;
108  nodes = nodes_p;
109  arcs = arcs_p;
110  cap = cap_p;
111  source = source_p;
112  sink = sink_p;
113  stats = stats_p;
114  queue = queue_p;
115  layers = layers_p;
116 
117  for (i = nodes; i < nodes + n; i++) {
118  i->excess = 0;
119  }
120 
121  source->excess = biggest_flow = flow_upper_bound;
122 
123  lmax = n - 1;
124 
125  return MFMC_NO_ERROR;
126 } /* end of initialization */
127 
128 
129 /*--- global rank update - breadth first search */
130 
131 static void
132 def_ranks (void)
133 
134 {
135  MFMC_NODE *i, *j, *jn; /* current nodes */
136  MFMC_ARC *a; /* current arc */
137  MFMC_LAYER *l; /* current layer */
138  INT32 j_rank; /* rank of node j */
139 
140  stats->n_up++; /* statistics */
141 
142  /* initialization */
143  for (i = nodes; i < nodes + n; i++) {
144  i->rank = n;
145  }
146 
147  sink->rank = 0;
148 
149  *queue = sink;
150 
151  for (l = layers; l <= layers + lmax; l++) {
152  l->push_first = NULL;
153  l->trans_first = NULL;
154  }
155 
156  lmax = lmax_push = 0;
157  lmin_push = n;
158 
159  /* breadth first search */
160  for (q_read = queue, q_write = queue + 1;
161  q_read != q_write;
162  q_read++) {
163  /* scanning arcs incident to node i */
164  i = *q_read;
165  j_rank = i->rank + 1;
166 
167  for (a = i->first; a != NULL; a = a->next) {
168  j = a->head;
169 
170  if (j->rank == n) {
171  /* j is not labelled */
172  if (a->reverse->r_cap > 0 ) {
173  /* arc (j, i) is not saturated */
174  j->rank = j_rank;
175  j->current = j->first;
176 
177  l = layers + j_rank;
178  if (j_rank > lmax) lmax = j_rank;
179 
180  if (j->excess > 0) {
181  j->nl_next = l->push_first;
182  l->push_first = j;
183  if (j_rank > lmax_push) lmax_push = j_rank;
184  if (j_rank < lmin_push) lmin_push = j_rank;
185  }
186  else {
187  /* j->excess == 0 */
188  jn = l->trans_first;
189  j->nl_next = jn;
190  if (jn != NULL) jn->nl_prev = j;
191  l->trans_first = j;
192  }
193 
194  /* put j to scanning queue */
195  *q_write = j;
196  q_write++;
197  }
198  }
199  } /* node "i" is scanned */
200  } /* end of scanning queue */
201 } /* end of global update */
202 
203 /*--- removing excessive flow - second phase of PR-algorithm */
204 
205 static void
206 prefl_to_flow (void)
207 
208 {
209  MFMC_NODE *i,*j, *ir, *is, *it, *front; /* current nodes */
210  MFMC_ARC *a; /* current arc */
211  INT64 path_cap; /* path capacity */
212  BOOL path, out_of_path; /* flags */
213 
214  /* initialization */
215  for (i = nodes + n; i >= nodes; i--) {
216  i->current = i->first;
217  i->nl_next = NULL;
218  }
219 
220  /* removing flow from excessive nodes */
221  for (i = nodes; i < nodes + n; i ++) {
222  if (i->excess <= 0 || i == source || i == sink) continue;
223 
224  /* i - has positive excess */
225  for (front = i; i->excess > 0;) {
226  /* looking for path from i to the source
227  (cycle may occur) */
228 
229  while (front != source) {
230  for (a = front->current; ; a = a->next) {
231  if (cap[a - arcs] == 0 &&
232  a->r_cap > 0)
233  break;
234  }
235  front->current = a;
236 
237  j = a->head;
238 
239  front->nl_next = j;
240  front = j;
241 
242  if (j->nl_next != NULL)
243  /* cycle is found */
244  break;
245  } /* while (front != source) */
246 
247  /* either path from i to the source or cycle is found */
248 
249  if (front == source) {
250  path = TRUE;
251  is = i;
252  path_cap = i->excess;
253  }
254  else {
255  path = FALSE;
256  is = j;
257  path_cap = biggest_flow;
258  }
259 
260  /* finding capacity of the path (cycle) */
261 
262  front = ir = is;
263 
264  do {
265  a = ir->current;
266 
267  if (a->r_cap < path_cap) {
268  front = ir;
269  path_cap = a ->r_cap;
270  }
271  ir = ir->nl_next;
272 
273  } while (ir != j);
274 
275  if (path) i->excess -= path_cap;
276 
277  /* reducing flows along the path */
278 
279  ir = is;
280  out_of_path = 0;
281 
282  do {
283  a = ir->current;
284  a->r_cap -= path_cap;
285  a->reverse->r_cap += path_cap;
286 
287  it = ir->nl_next;
288 
289  if (ir == front) out_of_path = 1;
290  if (out_of_path) ir->nl_next = NULL;
291 
292  ir = it;
293 
294  } while (ir != j);
295 
296  } /* now excess of i is 0 */
297  }
298 } /* end of prefl_to_flow */
299 
300 /*--- cleaning beyond the gap */
301 
302 static BOOL
303 gap (MFMC_LAYER *le) /* pointer to the empty layer */
304 
305 {
306  MFMC_LAYER *l; /* current layer */
307  MFMC_NODE *i; /* current nodes */
308  INT32 r; /* rank of the layer before l */
309  BOOL cc; /* cc = TRUE - no nodes with positive excess before
310  the gap */
311 
312  stats->n_gap++; /* statistics */
313 
314  r = (le - layers) - 1;
315 
316  /* putting ranks beyond the gap to "infinity" */
317 
318  for (l = le + 1; l <= layers + lmax; l++) {
319  for (i = l->push_first; i != NULL; i = i->nl_next) {
320  i->rank = n;
321  stats->n_gnode ++; /* statistics */
322  }
323 
324  for (i = l->trans_first; i != NULL; i = i->nl_next) {
325  i->rank = n;
326  stats->n_gnode ++; /* statistics */
327  }
328 
329  l->push_first = l->trans_first = NULL;
330  }
331 
332  cc = (lmin_push > r) ? TRUE : FALSE;
333 
334  lmax = r;
335  lmax_push = r;
336 
337  return cc;
338 } /* end of gap */
339 
340 
341 /*--- pushing flow from node i */
342 
343 static BOOL
344 push (MFMC_NODE *i)
345 
346 {
347  MFMC_NODE *j; /* sucsessor of i */
348  MFMC_NODE *j_next, *j_prev; /* j's sucsessor and predecessor in layer list */
349  INT32 j_rank; /* rank of the next layer */
350  MFMC_LAYER *lj; /* j's layer */
351  MFMC_ARC *a; /* current arc (i,j) */
352  INT64 fl; /* flow to push through the arc */
353 
354  j_rank = i->rank - 1;
355 
356  /* scanning arcs outgoing from i */
357 
358  for (a = i->current; a != NULL; a = a->next) {
359  if (a->r_cap > 0) {
360  /* "a" is not saturated */
361 
362  j = a->head;
363  if (j->rank == j_rank) {
364  /* j belongs to the next layer */
365 
366  fl = MIN(i->excess, a->r_cap);
367 
368  a->r_cap -= fl;
369  a->reverse->r_cap += fl;
370  stats->n_push ++; /* statistics */
371 
372  if (j_rank > 0) {
373  lj = layers + j_rank;
374 
375  if (j->excess == 0) {
376  /* before current push j had zero excess */
377 
378  /* remove j from the list of transit nodes */
379  j_next = j->nl_next;
380 
381  if (lj->trans_first == j)
382  /* j starts the list */
383  lj->trans_first = j_next;
384  else {
385  /* j is not the first */
386  j_prev = j->nl_prev;
387  j_prev->nl_next = j_next;
388  if (j_next != NULL)
389  j_next->nl_prev = j_prev;
390  }
391 
392  /* put j to the push-list */
393  j->nl_next = lj->push_first;
394  lj->push_first = j;
395 
396  if (j_rank < lmin_push)
397  lmin_push = j_rank;
398  } /* j->excess == 0 */
399  } /* j->rank > 0 */
400 
401  j->excess += fl;
402  i->excess -= fl;
403 
404  if (i->excess == 0) break;
405 
406  } /* j belongs to the next layer */
407  } /* a is not saturated */
408  } /* end of scanning arcs from i */
409 
410  i->current = a;
411 
412  return a == NULL;
413 } /* end of push */
414 
415 /*--- relabeling node i */
416 
417 static INT32
418 relabel (MFMC_NODE *i)
419 
420 {
421  MFMC_NODE *j; /* sucsessor of i */
422  INT32 j_rank; /* minimal rank of a node available from j */
423  MFMC_ARC *a; /* current arc */
424  MFMC_ARC *a_j; /* an arc which leads to the node with minimal rank */
425  MFMC_LAYER *l; /* layer for node i */
426 
427  stats->n_rel++; /* statistics */
428 
429  i->rank = j_rank = n;
430 
431  /* looking for a node with minimal rank available from i */
432 
433  for (a = i->first; a != NULL; a = a->next) {
434  if (a->r_cap > 0) {
435  j = a->head;
436 
437  if (j->rank < j_rank)
438  {
439  j_rank = j->rank;
440  a_j = a;
441  }
442  }
443  }
444 
445  if (j_rank < n) {
446  i->rank = ++j_rank;
447  i->current = a_j;
448 
449  l = layers + j_rank;
450 
451  if (i->excess > 0) {
452  i->nl_next = l->push_first;
453  l->push_first = i;
454  if (j_rank > lmax_push) lmax_push = j_rank;
455  if (j_rank < lmin_push) lmin_push = j_rank;
456  }
457  else {
458  j = l->trans_first;
459  i->nl_next = j;
460  if (j != 0) j->nl_prev = i;
461  l->trans_first = i;
462  }
463 
464  if (j_rank > lmax) lmax = j_rank;
465  } /* end of j_rank < n */
466 
467  return j_rank;
468 } /* end of relabel */
469 
470 
471 /* entry point */
472 
473 BOOL
475  MFMC_NODE *nodes_p,
476  MFMC_ARC *arcs_p,
477  INT64 *cap_p,
478  MFMC_NODE *source_p,
479  MFMC_NODE *sink_p,
480  MFMC_NODE **queue_p,
481  MFMC_LAYER *layers_p,
482  INT64 flow_upper_bound,
483  MFMC_STATS *stats_p,
484  INT64 *fl)
485 
486 {
487  MFMC_NODE *i; /* current node */
488  MFMC_NODE *j; /* i-sucsessor in layer list */
489  INT32 i_rank; /* rank of i */
490  MFMC_LAYER *l; /* current layer */
491  INT32 n_r; /* the number of recent relabels */
492  BOOL cc; /* condition code */
493  MFMC_STATS stat_buf; /* local buffer in case user doesn't care */
494 
495  if (stats_p != NULL) {
496  stats_p->time = timer();
497  }
498  cc = pr_init(n_p, nodes_p, arcs_p, cap_p, source_p, sink_p,
499  queue_p, layers_p,
500  (stats_p != NULL ? stats_p : &stat_buf),
501  flow_upper_bound);
502 
503  if (cc != MFMC_NO_ERROR) return cc;
504 
505  def_ranks();
506 
507  n_r = 0;
508 
509  /* highest level method */
510 
511  while (lmax_push >= lmin_push) {
512  /* main loop */
513  l = layers + lmax_push;
514 
515  i = l->push_first;
516 
517  if (i == NULL) {
518  /* nothing to push from this level */
519  lmax_push --;
520  }
521  else {
522  l->push_first = i->nl_next;
523 
524  cc = push(i);
525 
526  if (cc) { /* i must be relabeled */
527 
528  relabel(i);
529  n_r ++;
530 
531  if (l->push_first == NULL &&
532  l->trans_first == NULL) {
533  /* gap is found */
534  gap ( l );
535  }
536 
537  /* checking the necessity of global update */
538  if (n_r > GLOB_UPDT_FREQ * (float) n) {
539  /* it is time for global update */
540  def_ranks ();
541  n_r = 0;
542  }
543  }
544  else { /* excess is pushed out of i */
545  j = l->trans_first;
546  i->nl_next = j;
547  l->trans_first = i;
548  if (j != NULL) j->nl_prev = i;
549  }
550  }
551  } /* end of the main loop */
552 
553 #if 1
554  *fl = sink->excess;
555 #else
556  *fl += sink->excess;
557 #endif
558 
559  prefl_to_flow();
560 
561  if (stats_p != NULL) {
562  stats_p->time = timer() - stats_p->time;
563  }
564 
565  return MFMC_NO_ERROR;
566 } /* end of constructing flow */
567 
568 #endif