Scippy

SCIP

Solving Constraint Integer Programs

grphmcut.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2015 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file probdata_stp.c
17  * @brief Minimum cut routine for Steiner problems
18  * @author Gerald Gamrath
19  * @author Thorsten Koch
20  * @author Daniel Rehfeldt
21  *
22  * This file implements a graph minimum cut routine for Steiner problems. For more details see \ref MINCUT page.
23  *
24  * @page MINCUT Graph minimum cut routine
25  *
26  * The implemented algorithm is described in "A Faster Algorithm for Finding the Minimum Cut in a Graph" by Hao and Orlin.
27  *
28  * A list of all interface methods can be found in grph.h.
29  */
30 
31 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32 
33 
34 #include <stdio.h>
35 #include <assert.h>
36 #include <stdlib.h>
37 #include "portab.h"
38 #include "grph.h"
39 
40 #define DEBUG 0 /* 0 = No, 1 = Validation, 2 = Show flow */
41 #define STATIST 0
42 
43 #ifdef NDEBUG
44 #undef STATIST
45 #undef DEBUG
46 #define STATIST 0
47 #define DEBUG 0
48 #endif
49 
50 #define Q_LAST -1 /* Last Element of Queue */
51 #define Q_NMOQ -2 /* Not a Member Of the Queue */
52 
53 #if DEBUG
54 static int is_valid(const GRAPH*, const int, const int, const int*, const int *);
55 static void show_flow(const GRAPH*, const int*, const int*);
56 #endif
57 #if STATIST
58 static void cut_statist(void);
59 static void cut_sum(const GRAPH*, const int*, const int*);
60 #endif
61 
62 #if STATIST
63 static int s_pushes = 0;
64 static int n_pushes = 0;
65 static int m_pushes = 0;
66 static int x_pushes = 0;
67 static int relabels = 0;
68 static int s_sleeps = 0;
69 static int m_sleeps = 0;
70 static int searches = 0;
71 static int cutsums = 0;
72 #endif
73 
74 /*---------------------------------------------------------------------------*/
75 /*--- Name : GRAPH MINimumCUT INITialise ---*/
76 /*--- Function : Holt den Speicher fuer die Hilfsarrays die wir brauchen. ---*/
77 /*--- Parameter: Graph ---*/
78 /*--- Returns : Nichts ---*/
79 /*---------------------------------------------------------------------------*/
80 SCIP_RETCODE graph_mincut_init(
81  SCIP* scip, /**< SCIP data structure */
82  GRAPH* p /**< graph data structure */
83  )
84 {
85  assert(p != NULL);
86  assert(p->mincut_dist == NULL);
87  assert(p->mincut_head == NULL);
88  assert(p->mincut_numb == NULL);
89  assert(p->mincut_prev == NULL);
90  assert(p->mincut_next == NULL);
91  assert(p->mincut_temp == NULL);
92  assert(p->mincut_e == NULL);
93  assert(p->mincut_x == NULL);
94  assert(p->mincut_r == NULL);
95 
96  SCIP_CALL( SCIPallocMemoryArray(scip, &(p->mincut_dist), p->knots) );
97  SCIP_CALL( SCIPallocMemoryArray(scip, &(p->mincut_head), p->knots) );
98  SCIP_CALL( SCIPallocMemoryArray(scip, &(p->mincut_numb), p->knots) );
99  SCIP_CALL( SCIPallocMemoryArray(scip, &(p->mincut_prev), p->knots) );
100  SCIP_CALL( SCIPallocMemoryArray(scip, &(p->mincut_next), p->knots) );
101  SCIP_CALL( SCIPallocMemoryArray(scip, &(p->mincut_temp), p->knots) );
102  SCIP_CALL( SCIPallocMemoryArray(scip, &(p->mincut_e), p->knots) );
103  SCIP_CALL( SCIPallocMemoryArray(scip, &(p->mincut_x), p->edges) );
104  SCIP_CALL( SCIPallocMemoryArray(scip, &(p->mincut_r), p->edges) );
105 
106  return SCIP_OKAY;
107 }
108 
109 /*---------------------------------------------------------------------------*/
110 /*--- Name : GRAPH MINimumCUT EXIT ---*/
111 /*--- Function : Gibt den Speicher fuer die Hilfsarrays wieder frei. ---*/
112 /*--- Parameter: Keine ---*/
113 /*--- Returns : Nichts ---*/
114 /*---------------------------------------------------------------------------*/
116  SCIP* scip, /**< SCIP data structure */
117  GRAPH* p /**< graph data structure */
118  )
119 {
120  assert(p->mincut_dist != NULL);
121  assert(p->mincut_head != NULL);
122  assert(p->mincut_numb != NULL);
123  assert(p->mincut_prev != NULL);
124  assert(p->mincut_next != NULL);
125  assert(p->mincut_temp != NULL);
126  assert(p->mincut_e != NULL);
127  assert(p->mincut_x != NULL);
128  assert(p->mincut_r != NULL);
129 
130  SCIPfreeMemoryArray(scip, &(p->mincut_dist));
131  SCIPfreeMemoryArray(scip, &(p->mincut_head));
132  SCIPfreeMemoryArray(scip, &(p->mincut_numb));
133  SCIPfreeMemoryArray(scip, &(p->mincut_prev));
134  SCIPfreeMemoryArray(scip, &(p->mincut_next));
135  SCIPfreeMemoryArray(scip, &(p->mincut_temp));
136  SCIPfreeMemoryArray(scip, &(p->mincut_e));
137  SCIPfreeMemoryArray(scip, &(p->mincut_x));
138  SCIPfreeMemoryArray(scip, &(p->mincut_r));
139 
140 #if STATIST
141  cut_statist();
142 #endif
143 }
144 
145 inline static void delete(
146  const int knot,
147  int* q_dist,
148  int* q_head,
149  int* q_prev,
150  int* q_next)
151 {
152  assert(knot >= 0);
153  assert(q_dist != NULL);
154  assert(q_head != NULL);
155  assert(q_prev != NULL);
156  assert(q_next != NULL);
157  assert(q_dist[knot] > 0);
158 
159  if (q_next[knot] != Q_NMOQ)
160  {
161  /* Etwa Erster ?
162  */
163  if (q_prev[knot] == Q_LAST)
164  {
165  assert(q_dist[knot] >= 0);
166  assert(q_head[q_dist[knot]] == knot);
167 
168  q_head[q_dist[knot]] = q_next[knot];
169  }
170  else
171  {
172  assert(q_prev[knot] >= 0);
173  assert(q_next[q_prev[knot]] == knot);
174 
175  q_next[q_prev[knot]] = q_next[knot];
176  }
177 
178  /* Sind wir auch nicht letzter ?
179  */
180  if (q_next[knot] != Q_LAST)
181  {
182  assert(q_next[knot] >= 0);
183  assert(q_prev[q_next[knot]] == knot);
184 
185  q_prev[q_next[knot]] = q_prev[knot];
186  }
187  q_next[knot] = Q_NMOQ;
188  q_prev[knot] = Q_NMOQ;
189  }
190  assert(q_next[knot] == Q_NMOQ);
191  assert(q_prev[knot] == Q_NMOQ);
192 }
193 
194 inline static int insert(
195  const int knot,
196  int* q_dist,
197  int* q_head,
198  int* q_prev,
199  int* q_next,
200  int dmin)
201 {
202  assert(knot >= 0);
203  assert(q_dist != NULL);
204  assert(q_head != NULL);
205  assert(q_prev != NULL);
206  assert(q_next != NULL);
207  assert(q_dist[knot] > 0);
208  assert(dmin >= 1);
209 
210  if (q_prev[knot] == Q_NMOQ)
211  {
212  q_prev[knot] = Q_LAST;
213  q_next[knot] = q_head[q_dist[knot]];
214 
215  if (q_next[knot] != Q_LAST)
216  q_prev[q_next[knot]] = knot;
217 
218  q_head[q_dist[knot]] = knot;
219 
220  if (q_dist[knot] < dmin)
221  dmin = q_dist[knot];
222  }
223  assert(q_next[knot] != Q_NMOQ);
224  assert(q_prev[knot] != Q_NMOQ);
225  assert(q_dist[knot] >= dmin);
226 
227  return(dmin);
228 }
229 
230 static int bfs(
231  const GRAPH* p,
232  const int s,
233  const int t,
234  int* q_dist,
235  int* q_numb,
236  int* q_temp,
237  int* w)
238 {
239  int i;
240  int j;
241  int k;
242  int l;
243  int visited = 0;
244 
245  assert(q_temp != NULL);
246  assert(q_dist != NULL);
247  assert(q_numb != NULL);
248  assert(w != NULL);
249  assert(s >= 0);
250  assert(s < p->knots);
251  assert(t >= 0);
252  assert(t < p->knots);
253 
254  /* Beginnen wir bei der Senke
255  * (Sie ist sich selbst unendlich nah).
256  */
257  q_temp[visited++] = t;
258  q_dist[t] = 0;
259 
260  /* Solange noch schon besuchte Knoten da sind, von denen aus nicht
261  * versucht wurde weiter zu kommen:
262  */
263  for(j = 0; (j < visited) && (visited < p->knots); j++)
264  {
265  assert(visited < p->knots);
266  assert(j < visited);
267 
268  i = q_temp[j];
269 
270  assert(i >= 0);
271  assert(i < p->knots);
272  assert(q_dist[i] >= 0);
273  assert(q_dist[i] < visited);
274  assert(w[i] == 0);
275 
276  assert((j == 0) || (q_dist[i] >= q_dist[q_temp[j - 1]]));
277  assert((j == visited - 1) || (q_dist[i] <= q_dist[q_temp[j + 1]]));
278 
279  /* Wo koennen wir den ueberall hin:
280  */
281  for(k = p->outbeg[i]; k != EAT_LAST; k = p->oeat[k])
282  {
283  /* Wo gehts hin ? Nach Knote l.
284  */
285  l = p->head[k];
286 
287  /* Waren wir da noch nicht ?
288  */
289  assert(!w[l] || (q_dist[l] >= 0));
290 
291  if (q_dist[l] < 0)
292  {
293  q_dist[l] = q_dist[i] + 1;
294  q_temp[visited++] = l;
295  q_numb[q_dist[l]]++;
296 
297  assert(q_dist[l] < p->knots);
298  }
299  }
300  }
301  return(visited);
302 }
303 
304 
305 /*---------------------------------------------------------------------------*/
306 /*--- Name : INITialise LABELS ---*/
307 /*--- Function : Fuehrt eine BFS durch um die Distanzen der Knoten von ---*/
308 /*--- der Senke zu ermitten. Kanten ohne Kapazitaet werden ---*/
309 /*--- nicht beruecksichtigt, ebenso Knoten die nur ueber die ---*/
310 /*--- Quelle zu erreichen sind. ---*/
311 /*--- Parameter: Graph, Quelle, Senke, Kantenkapazitaeten. ---*/
312 /*--- Returns : Anzahl der Aktiven (Erreichbaren) Knoten, ---*/
313 /*--- Fuellt a[] mit den Nummern dieser Knoten und d[] mit den ---*/
314 /*--- Entfernungen der zugehoerigen Knoten zur Senke. ---*/
315 /*--- a[] ist aufsteigend sortiert. ---*/
316 /*---------------------------------------------------------------------------*/
317 static void initialise(
318  const GRAPH* p,
319  const int s,
320  const int t,
321  const int* capa,
322  int* q_dist,
323  int* q_numb,
324  int* q_head,
325  int* q_prev,
326  int* q_next,
327  int* q_temp,
328  int* excess,
329  int* transx,
330  int* residi,
331  int* w,
332  int* dmax)
333 {
334 
335  int i;
336  int j;
337  int k;
338 
339  assert(p != NULL);
340  assert(s >= 0);
341  assert(s < p->knots);
342  assert(t >= 0);
343  assert(t < p->knots);
344  assert(s != t);
345  assert(capa != NULL);
346  assert(w != NULL);
347  assert(q_head != NULL);
348  assert(q_dist != NULL);
349  assert(q_numb != NULL);
350  assert(q_prev != NULL);
351  assert(q_next != NULL);
352  assert(q_temp != NULL);
353  assert(excess != NULL);
354  assert(transx != NULL);
355  assert(residi != NULL);
356  assert(p->mincut_r != NULL);
357  assert(p->mincut_x != NULL);
358 
359  /* Knotenarrays Initialisieren
360  */
361  *dmax = 1;
362 
363  for(i = 0; i < p->knots; i++)
364  {
365  excess[i] = 0;
366  w [i] = 0;
367  q_prev[i] = Q_NMOQ;
368  q_next[i] = Q_NMOQ;
369  q_head[i] = Q_LAST;
370  q_numb[i] = 0;
371  q_dist[i] = -1;
372  }
373  /* Jetzt die Kantenarrays.
374  */
375  for(k = 0; k < p->edges; k++)
376  {
377  transx[k] = 0;
378  residi[k] = capa[k];
379  }
380  /* Jetzt noch dist und numb.
381  */
382  (void)bfs(p, s, t, q_dist, q_numb, q_temp, w);
383 
384  /* Alles was wir nicht erreichen konnten schlafen legen.
385  */
386  for(i = 0; i < p->knots; i++)
387  if (q_dist[i] < 0)
388  w[i] = *dmax + 1;
389 
390  /* Quelle einschlaefern
391  */
392  w[s] = 1; /* dmax */
393 
394  /* Falls wir die Quelle s nicht erreichen konnten sind wir fertig.
395  */
396  if (q_dist[s] < 0)
397  return;
398 
399  assert(w[s] > 0);
400  assert(q_dist[s] > 0);
401  assert(w[t] == 0);
402  assert(q_dist[t] == 0);
403 
404  /* Label der Quelle abziehen
405  */
406  q_numb[q_dist[s]]--;
407 
408  /* Von der Quelle alles wegschieben wofuer Kapazitaeten da sind.
409  */
410  for(k = p->outbeg[s]; k != EAT_LAST; k = p->oeat[k])
411  {
412  if (capa[k] == 0)
413  continue;
414 
415  j = p->head[k];
416  transx[k] = capa[k];
417  residi[k] = 0; /* -= transx[k] */
418 
419  residi[Edge_anti(k)] += transx[k]; /* Ueberfluessig weil w[s] == 1 */
420  excess[j] += transx[k];
421 
422  if (j != t)
423  (void)insert(j, q_dist, q_head, q_prev, q_next, 1);
424 
425  assert(w[j] == 0);
426  assert(excess[j] > 0);
427  assert((j == t) || (q_next[j] != Q_NMOQ));
428  assert((j == t) || (q_prev[j] != Q_NMOQ));
429 
430  assert((p->mincut_r)[k] + (p->mincut_r)[Edge_anti(k)] == capa[k] + capa[Edge_anti(k)]);
431  assert((p->mincut_x)[k] >= 0);
432  assert((p->mincut_x)[k] <= capa[k]);
433  assert((p->mincut_r)[k] == capa[k] - (p->mincut_x)[k] + (p->mincut_x)[Edge_anti(k)]);
434  }
435 #if DEBUG > 1
436  show_flow(p, capa, w);
437 #endif
438 #if DEBUG > 0
439  assert(is_valid(p, s, t, capa, w));
440 #endif
441 }
442 
443 static void reinitialise(
444  const GRAPH* p,
445  const int s,
446  const int t,
447  const int* capa,
448  int* q_dist,
449  int* q_numb,
450  int* q_head,
451  int* q_prev,
452  int* q_next,
453  int* q_temp,
454  int* excess,
455  int* transx,
456  int* residi,
457  int* w,
458  int* dmax)
459 {
460  int wt;
461  int i;
462  int j;
463  int k;
464  int visited;
465 
466  assert(p != NULL);
467  assert(s >= 0);
468  assert(s < p->knots);
469  assert(t >= 0);
470  assert(t < p->knots);
471  assert(s != t);
472  assert(capa != NULL);
473  assert(w != NULL);
474  assert(q_head != NULL);
475  assert(q_dist != NULL);
476  assert(q_numb != NULL);
477  assert(q_prev != NULL);
478  assert(q_next != NULL);
479  assert(q_temp != NULL);
480  assert(excess != NULL);
481  assert(transx != NULL);
482  assert(residi != NULL);
483 
484  /* Knotenarrays Initialisieren
485  */
486  assert(w[s]);
487 
488  wt = (w[t] == 0) ? p->knots + 1 : w[t];
489  *dmax = 1;
490 
491  for(i = 0; i < p->knots; i++)
492  {
493  q_numb[i] = 0;
494  q_head[i] = Q_LAST;
495  q_next[i] = Q_NMOQ;
496  q_prev[i] = Q_NMOQ;
497 
498  if ((w[i] == 0) || (w[i] >= wt))
499  {
500  w [i] = 0;
501  q_dist[i] = -1;
502  }
503  if (w[i] > *dmax)
504  *dmax = w[i];
505  }
506  /* Jetzt noch dist und numb.
507  */
508  visited = bfs(p, s, t, q_dist, q_numb, q_temp, w);
509 
510  /* Alles was wir nicht erreichen konnten schlafen legen.
511  */
512  for(i = 0; i < p->knots; i++)
513  if (q_dist[i] < 0)
514  w[i] = *dmax + 1;
515 
516  /* Jetzt die Kantenarrays und ggf. e updaten.
517  */
518  for(k = 0; k < p->edges; k += 2)
519  {
520  i = p->head[k];
521  j = p->tail[k];
522 
523  if (!w[i] && !w[j])
524  {
525  assert(w[s]);
526 
527  excess[i] += transx[k + 1] - transx[k];
528  excess[j] += transx[k] - transx[k + 1];
529  transx[k] = 0;
530  residi[k] = capa[k];
531  transx[k + 1] = 0;
532  residi[k + 1] = capa[k + 1];
533  }
534  }
535  assert(w[t] == 0);
536  assert(q_dist[t] == 0);
537  assert(q_temp[0] == t);
538 
539  /* Jetzt noch die mit Excess einsortieren.
540  */
541  for(i = 1; i < visited; i++)
542  {
543  assert(w[q_temp[i]] == 0);
544  assert(q_temp[i] != s);
545  assert(q_temp[i] != t);
546 
547  if (excess[q_temp[i]] > 0)
548  (void)insert(q_temp[i], q_dist, q_head, q_prev, q_next, 1);
549  }
550 #if DEBUG > 1
551  show_flow(p, capa, w);
552 #endif
553 #if DEBUG > 0
554  assert(is_valid(p, s, t, capa, w));
555 #endif
556 }
557 
558 /*---------------------------------------------------------------------------*/
559 /*--- Name : GRAPH MINimumCUT EXECute ---*/
560 /*--- Function : Fuehrt den Mincut Algorithmus durch und findet ---*/
561 /*--- (hoffentlich) einen Minimalen (s,t) Schnitt im Graphen. ---*/
562 /*--- Parameter: Graph, Quelle, Senke, Kantenkapazitaeten, Zustandsarray, ---*/
563 /*--- Flag um vorhandenen Fluss zu belassen. ---*/
564 /*--- Returns : Nichts, fuellt aber w[] mit nicht Nulleintraegen fuer ---*/
565 /*--- die Knoten, die auf der Quellenseite des Schnittes ---*/
566 /*--- liegen und Null fuer die auf der Senkenseite. ---*/
567 /*---------------------------------------------------------------------------*/
569  GRAPH* p,
570  int s,
571  int t,
572  const int* capa,
573  int* w,
574  int rerun)
575 {
576  int min_dist;
577  int min_capa;
578  int min_knot;
579  int min_arc;
580  int dmax;
581  int i;
582  int k;
583  int dmin = 1;
584  int* dist;
585  int* head;
586  int* numb;
587  int* prev;
588  int* next;
589  int* temp;
590  int* e;
591  int* x;
592  int* r;
593 
594  assert(p != NULL);
595  assert(s >= 0);
596  assert(s < p->knots);
597  assert(t >= 0);
598  assert(t < p->knots);
599  assert(s != t);
600  assert(capa != NULL);
601  assert(w != NULL);
602  assert(p->mincut_dist != NULL);
603  assert(p->mincut_numb != NULL);
604  assert(p->mincut_head != NULL);
605  assert(p->mincut_prev != NULL);
606  assert(p->mincut_next != NULL);
607  assert(p->mincut_temp != NULL);
608  assert(p->mincut_e != NULL);
609  assert(p->mincut_x != NULL);
610  assert(p->mincut_r != NULL);
611 
612  dist = p->mincut_dist;
613  head = p->mincut_head;
614  numb = p->mincut_numb;
615  prev = p->mincut_prev;
616  next = p->mincut_next;
617  temp = p->mincut_temp;
618  e = p->mincut_e;
619  x = p->mincut_x;
620  r = p->mincut_r;
621 
622 #if DEBUG > 0
623  (void)printf("graph_mincut_exec(p, s=%d, t=%d, capa, w, rerun=%d)\n",
624  s, t, rerun);
625 #endif
626 
627  if (!rerun)
628  initialise(p, s, t, capa, dist, numb, head, prev, next, temp, e, x, r, w, &dmax);
629  else
630  reinitialise(p, s, t, capa, dist, numb, head, prev, next, temp, e, x, r, w, &dmax);
631 
632  /* Solange wir nicht fertig sind ...
633  */
634  for(;;)
635  {
636 #if DEBUG > 0
637  assert(is_valid(p, s, t, capa, w));
638 #endif
639 #if STATIST
640  searches++;
641 #endif
642 
643  /* Kein Knoten, keine Arbeit !
644  */
645  while((dmin < p->knots) && (head[dmin] == Q_LAST))
646  dmin++;
647 
648  if (dmin == p->knots)
649  break;
650 
651  /* Hole den naechsten Knoten mit Ueberschuss hervor.
652  */
653  i = head[dmin];
654 
655  assert(prev[i] == Q_LAST);
656  assert(w[i] == 0);
657  assert(i != t);
658  assert(i != s);
659 
660  /* Wenn es von i aus eine gangbare Kante gibt, versuche den
661  * Ueberschuss wegzuschieben.
662  * (Gangbar = hat Kapazitaet und ist in Bezug auf d[] eins abschuessig).
663  */
664  min_knot = -1;
665  min_dist = p->knots;
666  min_capa = 0;
667  min_arc = -1;
668 
669  for(k = p->outbeg[i]; k != EAT_LAST; k = p->oeat[k])
670  {
671  /* Hat k keine Kapazitaet oder geht zu einem eingeschlafenen Knoten ?
672  * --- Dann vergiss es !
673  */
674  if ((r[k] <= 0) || (w[p->head[k]]))
675  continue;
676 
677  /* Fuhert k nach oben ?
678  * --- Dann keine Chance was runterzuschieben, aber wir Merken uns
679  * den Koten, denn vielleicht steigen wird ja noch auf.
680  */
681  if (dist[i] != dist[p->head[k]] + 1)
682  {
683  assert(dist[i] <= dist[p->head[k]]); /* Warum funktioniert das ? tut es das ? */
684 
685  if ((dist[p->head[k]] < min_dist)
686  || ((dist[p->head[k]] == min_dist) && (r[k] > min_capa)))
687  {
688  min_knot = p->head[k];
689  min_dist = dist[min_knot];
690  min_capa = r[k];
691  min_arc = k;
692  }
693  continue;
694  }
695 
696  /* Druecke delta := min{ e(i), r(i,j) } Einheiten Fluss von
697  * Knoten i nach Knoten j.
698  */
699  assert(Min(e[i], r[k]) > 0);
700 
701  /* Mehr Kapazitaet als Ueberschuss ?
702  */
703  if (e[i] <= r[k])
704  {
705 #if STATIST
706  (e[i] == r[k]) ? x_pushes++ : n_pushes++;
707 #endif
708  x[k] += e[i];
709  r[k] -= e[i];
710  r[Edge_anti(k)] += e[i];
711  e[p->head[k]] += e[i];
712  e[i] = 0; /* -= e[i] */
713 
714  assert(e[p->head[k]] > 0);
715  assert(w[p->head[k]] == 0);
716 
717  if (p->head[k] != t)
718  dmin = insert(p->head[k], dist, head, prev, next, dmin);
719 
720  assert(r[k] + r[Edge_anti(k)] == capa[k] + capa[Edge_anti(k)]);
721  assert(r[k] == capa[k] - x[k] + x[Edge_anti(k)]);
722 
723  /* Kein Ueberschuss uebrig, mit dem Knoten sind wir erstmal fertig.
724  */
725  break;
726  }
727 
728  /* Mehr Ueberschuss als Kapazitaet.
729  */
730  r[Edge_anti(k)] += r[k];
731  e[p->head[k]] += r[k];
732  e[i] -= r[k];
733  x[k] += r[k];
734  r[k] = 0; /* -= r[k] */
735 
736  if (p->head[k] != t)
737  dmin = insert(p->head[k], dist, head, prev, next, dmin);
738 
739  assert(r[k] + r[Edge_anti(k)] == capa[k] + capa[Edge_anti(k)]);
740  assert(r[k] == capa[k] - x[k] + x[Edge_anti(k)]);
741  assert(e[i] > 0);
742 
743 #if STATIST
744  s_pushes++;
745 #endif
746  }
747 
748  /* Kein Ueberschuss mehr, dann Knoten aus der aktiv Liste entfernen.
749  */
750  if (e[i] == 0)
751  {
752  delete(i, dist, head, prev, next);
753 
754  assert(prev[i] == Q_NMOQ);
755  assert(next[i] == Q_NMOQ);
756 
757  continue;
758  }
759  /* Wir sind den Ueberschuss nicht losgeworden, also muss Knoten i
760  * hochgelegt werden (relabel).
761  */
762  assert(numb[dist[i]] > 0);
763 
764  if (numb[dist[i]] == 1)
765  {
766  dmax++;
767 
768  assert(dmax <= p->knots);
769 
770  for(k = 0; k < p->knots; k++)
771  {
772  /* Kleinergleich um Knoten i auch zu erwischen.
773  */
774  if (!w[k] && (dist[i] <= dist[k]))
775  {
776  numb[dist[k]]--;
777  w[k] = dmax;
778 
779  delete(k, dist, head, prev, next);
780 
781  assert(prev[k] == Q_NMOQ);
782  assert(next[k] == Q_NMOQ);
783  }
784  }
785 #if STATIST
786  m_sleeps++;
787 #endif
788  continue;
789  }
790  /* Wir setzen d[i] um Eins hoeher als den Tiefsten drumherum der
791  * aktiv ist und noch Kapazitaet auf der Leitung hat.
792  */
793 
794  /* Keine Kapazitaeten mehr ?
795  * --- Dann i einschlaefern.
796  */
797  if (min_knot == -1)
798  {
799  numb[dist[i]]--;
800  w[i] = ++dmax;
801 
802  assert(dmax <= p->knots);
803 
804  delete(i, dist, head, prev, next);
805 
806  assert(prev[i] == Q_NMOQ);
807  assert(next[i] == Q_NMOQ);
808 #if STATIST
809  s_sleeps++;
810 #endif
811  }
812  else
813  {
814  assert(min_dist < p->knots);
815  assert(min_capa > 0);
816  assert(min_knot >= 0);
817  assert(min_arc >= 0);
818 
819  delete(i, dist, head, prev, next);
820 
821  numb[dist[i]]--;
822 
823  dist[i] = min_dist + 1;
824 
825  (void)insert(i, dist, head, prev, next, dmin);
826 
827  numb[dist[i]]++;
828 
829  assert(dist[i] < p->knots);
830 
831  assert(min_capa > 0);
832  assert(min_capa == r[min_arc]);
833  assert(p->head[min_arc] == min_knot);
834  assert(p->tail[min_arc] == i);
835  assert(dist[i] == dist[min_knot] + 1);
836  assert(w[min_knot] == 0);
837 
838  /* Wenn die Kante die wir uns gemerkt haben, genug Kapazitaet hat
839  * um den Knoten zu erledigen, dann bringen wir es hinter uns.
840  */
841  if (e[i] <= min_capa)
842  {
843  x[min_arc] += e[i];
844  r[min_arc] -= e[i];
845  r[Edge_anti(min_arc)] += e[i];
846  e[min_knot] += e[i];
847  e[i] = 0; /* -= e[i] */
848 
849  if (p->head[min_arc] != t)
850  dmin = insert(p->head[min_arc], dist, head, prev, next, dmin);
851 
852  delete(i, dist, head, prev, next);
853 
854  assert(r[min_arc] + r[Edge_anti(min_arc)] == capa[min_arc] + capa[Edge_anti(min_arc)]);
855  assert(r[min_arc] >= 0);
856  assert(r[min_arc] == capa[min_arc] - x[min_arc] + x[Edge_anti(min_arc)]);
857 #if STATIST
858  m_pushes++;
859 #endif
860  }
861 #if STATIST
862  relabels++;
863 #endif
864  }
865  }
866  assert(w[s]);
867  assert(!w[t]);
868 
869 #if STATIST
870  cut_sum(p, capa, w);
871 #endif
872 #if DEBUG > 1
873  show_flow(p, capa, w);
874 #endif
875 #if DEBUG > 0
876  assert(is_valid(p, s, t, capa, w));
877 #endif
878 }
879 
880 #if STATIST
881 static void cut_statist(void)
882 {
883  (void)printf("Mincut Statistics:\n");
884  (void)printf("Node-Searches=%d, Cut Sums=%d\n",
885  searches, cutsums);
886  (void)printf("S-Pushes=%d, N-Pushes=%d, X-Pushes=%d, M-Pushes=%d\n",
887  s_pushes, n_pushes, x_pushes, m_pushes);
888  (void)printf("Relabels=%d, S-Sleeps=%d, M-Sleeps=%d\n\n",
889  relabels, s_sleeps, m_sleeps);
890 
891  s_pushes = 0;
892  n_pushes = 0;
893  x_pushes = 0;
894  m_pushes = 0;
895  relabels = 0;
896  s_sleeps = 0;
897  m_sleeps = 0;
898  searches = 0;
899  cutsums = 0;
900 }
901 
902 static void cut_sum(
903  const GRAPH* p,
904  const int* capa,
905  const int* w)
906 {
907  int sum = 0;
908  int i;
909  int j;
910  int k;
911 
912  assert(p != NULL);
913  assert(capa != NULL);
914  assert(w != NULL);
915 
916  for(k = 0; k < p->edges; k++)
917  {
918  i = p->head[k];
919  j = p->tail[k];
920 
921  if ((w[i] && !w[j]) || (!w[i] && w[j]))
922  sum += capa[k];
923  }
924 #if DEBUG > 0
925  (void)printf("Cut Sum=%d\n", sum);
926 #endif
927  cutsums += sum;
928 }
929 #endif
930 
931 #if DEBUG > 0
932 static int is_valid(
933  const GRAPH* p,
934  const int s,
935  const int t,
936  const int* capa,
937  const int* w)
938 {
939  int* e;
940  int* r;
941  int* x;
942  int j;
943  int k;
944 
945  assert(p != NULL);
946  assert(p->mincut_e != NULL);
947  assert(p->mincut_r != NULL);
948  assert(p->mincut_x != NULL);
949 
950  e = p->mincut_e;
951  r = p->mincut_r;
952  x = p->mincut_x;
953 
954  for(j = 0; j < p->knots; j++)
955  {
956 #if 0
957  if ((q[j] >= 0) && (a[q[j]] != j))
958  return((void)fprintf(stderr, "Queue Error 1 Knot %d\n", j), FALSE);
959 
960  if (!w[j] && (q[j] < 0) && (e[j] > 0) && (j != t))
961  return((void)fprintf(stderr, "Queue Error 2 Knot %d\n", j), FALSE);
962 
963  if (!w[j] && (q[j] >= 0) && (e[j] == 0))
964  return((void)fprintf(stderr, "Queue Error 3 Knot %d\n", j), FALSE);
965 
966  if (w[j] && (q[j] >= 0))
967  return((void)fprintf(stderr, "Queue Error 4 Knot %d\n", j), FALSE);
968 #endif
969  if (e[j] < 0)
970  return((void)fprintf(stderr, "Negativ Execess Knot %d\n", j), FALSE);
971 
972  if (p->mincut_dist[j] >= p->knots)
973  return((void)fprintf(stderr, "Distance too big Knot %d\n", j), FALSE);
974 
975  /* Extended Dormacy Property
976  */
977  for(k = p->outbeg[j]; k != EAT_LAST; k = p->oeat[k])
978  {
979  if (r[k] > 0)
980  {
981  if ((w[j] && !w[p->head[k]]) || (w[j] && (w[j] < w[p->head[k]])))
982  {
983  (void)printf("k=%d r[k]=%d head=%d tail=%d w[h]=%d w[t]=%d\n",
984  k, r[k], p->head[k], p->tail[k], w[p->head[k]], w[p->tail[k]]);
985 
986  return((void)fprintf(stderr, "Extended Dormacy Violation Knot %d\n", j), FALSE);
987  }
988  }
989  }
990  }
991  for(j = 0; j < p->edges; j++)
992  {
993  if (r[j] < 0)
994  return((void)fprintf(stderr, "Negativ Residual Edge %d\n", j), FALSE);
995 
996  if (x[j] < 0)
997  return((void)fprintf(stderr, "Negativ Flow Edge %d\n", j), FALSE);
998 
999  if (r[j] + r[Edge_anti(j)] != capa[j] + capa[Edge_anti(j)])
1000  return((void)fprintf(stderr, "Wrong Capacity Equation Edge %d\n", j), FALSE);
1001 
1002  if (r[j] != capa[j] - x[j] + x[Edge_anti(j)])
1003  return((void)fprintf(stderr, "Wrong Residual Equation Edge %d\n", j), FALSE);
1004  }
1005  return(TRUE);
1006 }
1007 
1008 static void show_flow(
1009  const GRAPH* p,
1010  const int* capa,
1011  const int* w)
1012 {
1013  int j;
1014  int* head;
1015  int* numb;
1016  int* prev;
1017  int* next;
1018  int* e;
1019  int* x;
1020  int* r;
1021 
1022  assert(p != NULL);
1023  assert(w != NULL);
1024  assert(p->mincut_numb != NULL);
1025  assert(p->mincut_head != NULL);
1026  assert(p->mincut_prev != NULL);
1027  assert(p->mincut_next != NULL);
1028  assert(p->mincut_e != NULL);
1029  assert(p->mincut_x != NULL);
1030  assert(p->mincut_r != NULL);
1031 
1032  head = p->mincut_head;
1033  numb = p->mincut_numb;
1034  prev = p->mincut_prev;
1035  next = p->mincut_next;
1036  e = p->mincut_e;
1037  x = p->mincut_x;
1038  r = p->mincut_r;
1039 
1040 
1041 
1042  (void)printf(" ");
1043  for(j = 0; j < p->edges; j++)
1044  (void)printf("%6d ", j);
1045  (void)fputc('\n', stdout);
1046 
1047  (void)printf("ta:");
1048  for(j = 0; j < p->edges; j++)
1049  (void)printf("%6d ", p->tail[j]);
1050  (void)fputc('\n', stdout);
1051 
1052  (void)printf("he:");
1053  for(j = 0; j < p->edges; j++)
1054  (void)printf("%6d ", p->head[j]);
1055  (void)fputc('\n', stdout);
1056 
1057  (void)printf("x: ");
1058  for(j = 0; j < p->edges; j++)
1059  (void)printf("%6d ", x[j]);
1060  (void)fputc('\n', stdout);
1061 
1062  (void)printf("r: ");
1063  for(j = 0; j < p->edges; j++)
1064  (void)printf("%6d ", r[j]);
1065  (void)fputc('\n', stdout);
1066 
1067  (void)printf("ca:");
1068  for(j = 0; j < p->edges; j++)
1069  (void)printf("%6d ", capa[j]);
1070  (void)fputc('\n', stdout);
1071 
1072  (void)printf("w: ");
1073  for(j = 0; j < p->knots; j++)
1074  (void)printf("%2d ", w[j]);
1075  (void)fputc('\n', stdout);
1076 
1077  (void)printf("d: ");
1078  for(j = 0; j < p->knots; j++)
1079  (void)printf("%2d ", p->mincut_dist[j]);
1080  (void)fputc('\n', stdout);
1081 
1082  (void)printf("n: ");
1083  for(j = 0; j < p->knots; j++)
1084  (void)printf("%2d ", numb[j]);
1085  (void)fputc('\n', stdout);
1086 
1087  (void)printf("h: ");
1088  for(j = 0; j < p->knots; j++)
1089  (void)printf("%2d ", head[j]);
1090  (void)fputc('\n', stdout);
1091 
1092  (void)printf("p: ");
1093  for(j = 0; j < p->knots; j++)
1094  (void)printf("%2d ", prev[j]);
1095  (void)fputc('\n', stdout);
1096 
1097  (void)printf("n: ");
1098  for(j = 0; j < p->knots; j++)
1099  (void)printf("%2d ", next[j]);
1100  (void)fputc('\n', stdout);
1101 
1102  (void)printf("e: ");
1103  for(j = 0; j < p->knots; j++)
1104  (void)printf("%2d ", e[j]);
1105  (void)fputc('\n', stdout);
1106 }
1107 
1108 #endif /* DEBUG > 0 */
static void reinitialise(const GRAPH *p, const int s, const int t, const int *capa, int *q_dist, int *q_numb, int *q_head, int *q_prev, int *q_next, int *q_temp, int *excess, int *transx, int *residi, int *w, int *dmax)
Definition: grphmcut.c:443
Definition: grph.h:55
#define TRUE
Definition: portab.h:34
void graph_mincut_exec(GRAPH *p, int s, int t, const int *capa, int *w, int rerun)
Definition: grphmcut.c:568
#define Q_LAST
Definition: grphmcut.c:50
int * mincut_r
Definition: grph.h:111
#define EAT_LAST
Definition: grph.h:31
#define Edge_anti(a)
Definition: grph.h:161
int * oeat
Definition: grph.h:100
static int insert(const int knot, int *q_dist, int *q_head, int *q_prev, int *q_next, int dmin)
Definition: grphmcut.c:194
int * head
Definition: grph.h:94
#define Min(a, b)
Definition: portab.h:51
#define FALSE
Definition: portab.h:37
int * mincut_prev
Definition: grph.h:106
int * outbeg
Definition: grph.h:77
int * tail
Definition: grph.h:93
int knots
Definition: grph.h:61
SCIP_RETCODE graph_mincut_init(SCIP *scip, GRAPH *p)
Definition: grphmcut.c:80
int * mincut_temp
Definition: grph.h:108
int * mincut_e
Definition: grph.h:109
includes various files containing graph methods used for Steiner problems
Portable defintions.
static void initialise(const GRAPH *p, const int s, const int t, const int *capa, int *q_dist, int *q_numb, int *q_head, int *q_prev, int *q_next, int *q_temp, int *excess, int *transx, int *residi, int *w, int *dmax)
Definition: grphmcut.c:317
void graph_mincut_exit(SCIP *scip, GRAPH *p)
Definition: grphmcut.c:115
int * mincut_dist
Definition: grph.h:103
int * mincut_x
Definition: grph.h:110
int * mincut_next
Definition: grph.h:107
int edges
Definition: grph.h:89
#define Q_NMOQ
Definition: grphmcut.c:51
int * mincut_head
Definition: grph.h:104
static int bfs(const GRAPH *p, const int s, const int t, int *q_dist, int *q_numb, int *q_temp, int *w)
Definition: grphmcut.c:230
int * mincut_numb
Definition: grph.h:105