Scippy

SCIP

Solving Constraint Integer Programs

reduce_alt.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 reduce_alt.c
17  * @brief Altenative based reduction tests for Steiner problems
18  * @author Thorsten Koch
19  * @author Stephen Maher
20  * @author Daniel Rehfeldt
21  *
22  * This file implements alternative-based reduction techniques for several Steiner problems.
23  * All tests can be found in "A Generic Approach to Solving the Steiner Tree Problem and Variants" by Daniel Rehfeldt.
24  *
25  * A list of all interface methods can be found in grph.h.
26  *
27  */
28 
29 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <assert.h>
35 #include "grph.h"
36 #include "probdata_stp.h"
37 #include "scip/scip.h"
38 
39 #define CNSNN 25
40 #define KNOTFREQ 100
41 #define KNOTLIMIT 1e+20
42 
43 
44 #if 0
45 /** for debug purposes only */
46 static
47 SCIP_RETCODE printGraph(
48  SCIP* scip,
49  const GRAPH* graph, /**< Graph to be printed */
50  const char* filename, /**< Name of the output file */
51  int* result
52  )
53 {
54  char label[SCIP_MAXSTRLEN];
55  FILE* file;
56  int e;
57  int n;
58  int m;
59  char* stnodes;
60  SCIP_CALL( SCIPallocBufferArray(scip, &stnodes, graph->knots ) );
61 
62  assert(graph != NULL);
63  file = fopen((filename != NULL) ? filename : "graphX.gml", "w");
64 
65  for( e = 0; e < graph->knots; e++ )
66  {
67  stnodes[e] = FALSE;
68  }
69  for( e = 0; e < graph->edges; e++ )
70  {
71  if( 1 )
72  {
73  stnodes[graph->tail[e]] = TRUE;
74  stnodes[graph->head[e]] = TRUE;
75  }
76  }
77 
78  /* write GML format opening, undirected */
79  SCIPgmlWriteOpening(file, FALSE);
80 
81  /* write all nodes, discriminate between root, terminals and the other nodes */
82  e = 0;
83  m = 0;
84  for( n = 0; n < graph->knots; ++n )
85  {
86  if( stnodes[n] )
87  {
88  if( n == graph->source[0] )
89  {
90  (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "(%d) Root", n);
91  SCIPgmlWriteNode(file, (unsigned int)n, label, "rectangle", "#666666", NULL);
92  m = 1;
93  }
94  else if( graph->term[n] == 0 )
95  {
96  (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "(%d) Terminal %d", n, e + 1);
97  SCIPgmlWriteNode(file, (unsigned int)n, label, "circle", "#ff0000", NULL);
98  e += 1;
99  }
100  else
101  {
102  (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "(%d) Node %d", n, n + 1 - e - m);
103  SCIPgmlWriteNode(file, (unsigned int)n, label, "circle", "#336699", NULL);
104  }
105 
106  }
107  }
108 
109  /* write all edges (undirected) */
110  for( e = 0; e < graph->edges; e ++ )
111  {
112  if( 1 )
113  {
114  (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%8.2f", graph->cost[e]);
115  SCIPgmlWriteEdge(file, (unsigned int)graph->tail[e], (unsigned int)graph->head[e], label, "#ff0000");
116  }
117  }
118  SCIPfreeBufferArray(scip, &stnodes);
119  /* write GML format closing */
120  SCIPgmlWriteClosing(file);
121 
122  return SCIP_OKAY;
123 }
124 
125 #endif
126 
127 /* can edge be deleted in SD test in case of equality? If so, 'forbidden' array is adapted */
128 static
129 SCIP_Bool sddeltable(
130  SCIP* scip,
131  GRAPH* g,
132  PATH* path,
133  int* vbase,
134  int* forbidden,
135  int tpos,
136  int hpos,
137  int tail,
138  int head,
139  int edge,
140  int nnodes
141  )
142 {
143 #if 0
144  int e;
145 #endif
146 
147  assert(g != NULL);
148  assert(path != NULL);
149  assert(scip != NULL);
150  assert(vbase != NULL);
151  assert(forbidden != NULL);
152 
153  assert(tpos >= 0);
154  assert(hpos >= 0);
155  assert(tail >= 0);
156  assert(head >= 0);
157  assert(edge >= 0);
158  assert(nnodes >= 0);
159 
160  return FALSE;
161 
162 #if 0 /* @todo */
163  /* edge between non-terminals */
164  if( !Is_term(g->term[tail]) && !Is_term(g->term[head]) )
165  {
166  printf("deletable! \n");
167  return TRUE;
168  }
169 
170  /* has edge been marked as forbidden? */
171  if( forbidden[edge] )
172  return FALSE;
173 
174  /* edge between a terminal and a non terminal */
175  if( !Is_term(g->term[tail]) || !Is_term(g->term[head]) )
176  {
177 #if 0
178  int k;
179  int base;
180  int shift;
181  int antiedge;
182 
183  antiedge = flipedge(edge);
184 #endif
185 
186  /* check whether edge is used in shortest path */
187 
188  if( !Is_term(g->term[tail]) && Is_term(g->term[head]) )
189  {
190  e = path[tail + tpos * nnodes].edge;
191 
192  assert(g->ieat[e] != EAT_FREE);
193  assert(g->head[e] == tail);
194 
195  if( g->tail[e] == head )
196  return FALSE;
197 #if 0
198  k = tail;
199  base = vbase[tail + tpos * nnodes];
200  shift = tpos * nnodes;
201  while( k != base )
202  {
203  e = path[k + shift].edge;
204 
205  assert(g->ieat[e] != EAT_FREE);
206 
207  if( e == edge || e == antiedge || g->ieat[e] == EAT_FREE )
208  return FALSE;
209 
210  k = g->tail[e];
211  }
212 #endif
213  }
214  else if( Is_term(g->term[tail]) && !Is_term(g->term[head]) )
215  {
216  e = path[head + hpos * nnodes].edge;
217 
218  assert(g->ieat[e] != EAT_FREE);
219  assert(g->head[e] == head);
220 
221  if( g->tail[e] == tail )
222  return FALSE;
223  }
224  }
225 
226  /* update forbidden edges */
227 
228  if( Is_term(g->term[head]) )
229  {
230 
231  SCIP_Real ecost = g->cost[edge];
232  for( e = g->outbeg[tail]; e != EAT_LAST; e = g->oeat[e] )
233  {
234  assert(e >= 0);
235 
236  if( SCIPisEQ(scip, g->cost[e], ecost) )
237  {
238  if( forbidden[e] == FALSE && Is_term(g->term[g->head[e]]) )
239  {
240  forbidden[e] = TRUE;
241  forbidden[flipedge(e)] = TRUE;
242  }
243  }
244  }
245  }
246 
247  if( Is_term(g->term[tail]) )
248  {
249 
250  SCIP_Real ecost = g->cost[edge];
251  for( e = g->outbeg[head]; e != EAT_LAST; e = g->oeat[e] )
252  {
253  assert(e >= 0);
254 
255  if( SCIPisEQ(scip, g->cost[e], ecost) )
256  {
257  if( forbidden[e] == FALSE && Is_term(g->term[g->head[e]]) )
258  {
259  forbidden[e] = TRUE;
260  forbidden[flipedge(e)] = TRUE;
261  }
262  }
263  }
264  }
265  printf("deletable! \n");
266  return TRUE;
267 #endif
268 }
269 
270 
271 static
273  SCIP* scip,
274  PATH* vnoi,
275  SCIP_Real* termdist,
276  SCIP_Real ecost,
277  int* vbase,
278  int* neighbterms,
279  int i,
280  int nnodes
281  )
282 {
283  int k;
284  int pos = i;
285  int nnterms = 0;
286 
287  assert(scip != NULL);
288  assert(vnoi != NULL);
289  assert(vbase != NULL);
290  assert(termdist != NULL);
291  assert(neighbterms != NULL);
292 
293  for( k = 0; k < 4; k++ )
294  {
295  if( SCIPisLT(scip, vnoi[pos].dist, ecost) )
296  {
297  neighbterms[nnterms] = vbase[pos];
298  termdist[nnterms++] = vnoi[pos].dist;
299  }
300  else
301  {
302  break;
303  }
304  pos += nnodes;
305  }
306 
307  return nnterms;
308 }
309 
310 static
312  SCIP* scip,
313  PATH* vnoi,
314  SCIP_Real* termdist,
315  SCIP_Real ecost,
316  int* vbase,
317  int* neighbterms,
318  int i,
319  int nnodes
320  )
321 {
322  int k;
323  int pos = i;
324  int nnterms = 0;
325 
326  assert(scip != NULL);
327  assert(vnoi != NULL);
328  assert(vbase != NULL);
329  assert(termdist != NULL);
330  assert(neighbterms != NULL);
331 
332  for( k = 0; k < 4; k++ )
333  {
334  if( SCIPisLE(scip, vnoi[pos].dist, ecost) )
335  {
336  neighbterms[nnterms] = vbase[pos];
337  termdist[nnterms++] = vnoi[pos].dist;
338  }
339  else
340  {
341  break;
342  }
343  pos += nnodes;
344  }
345 
346  return nnterms;
347 }
348 
349 
350 static int issmaller(
351  SCIP* scip,
352  const double* pathdist,
353  const double* pathtran,
354  int a,
355  int b)
356 {
357  return (SCIPisLT(scip, pathdist[a], pathdist[b]) || (!SCIPisGT(scip, pathdist[a], pathdist[b]) && SCIPisLT(scip, pathtran[a], pathtran[b])));
358 }
359 static int islarger(
360  SCIP* scip,
361  const double* pathdist,
362  const double* pathtran,
363  int a,
364  int b)
365 {
366  return (SCIPisGT(scip, pathdist[a], pathdist[b]) || (!SCIPisLT(scip, pathdist[a], pathdist[b]) && SCIPisGT(scip, pathtran[a], pathtran[b])));
367 }
368 /*---------------------------------------------------------------------------*/
369 /*--- Name : get NEAREST knot ---*/
370 /*--- Function : Holt das oberste Element vom Heap (den Knoten mit der ---*/
371 /*--- geringsten Entfernung zu den bereits Verbundenen) ---*/
372 /*--- Parameter: Derzeitige Entfernungen und benutzte Kanten ---*/
373 /*--- Returns : Nummer des bewussten Knotens ---*/
374 /*---------------------------------------------------------------------------*/
375 inline static int nearest(
376  SCIP* scip,
377  int* heap,
378  int* state,
379  int* count, /* pointer to store number of elements of heap */
380  const double* pathdist,
381  const double* pathtran)
382 {
383  int k;
384  int t;
385  int c;
386  int j;
387 
388  /* Heap shift down
389  * (Oberstes Element runter und korrigieren)
390  */
391  k = heap[1];
392  j = 1;
393  c = 2;
394  heap[1] = heap[(*count)--];
395  state[heap[1]] = 1;
396 
397  if ((*count) > 2)
398  if (islarger(scip, pathdist, pathtran, heap[2], heap[3]))
399  c++;
400 
401  while((c <= (*count)) && islarger(scip, pathdist, pathtran, heap[j], heap[c]))
402  {
403  t = heap[c];
404  heap[c] = heap[j];
405  heap[j] = t;
406  state[heap[j]] = j;
407  state[heap[c]] = c;
408  j = c;
409  c += c;
410 
411  if ((c + 1) <= (*count))
412  if (issmaller(scip, pathdist, pathtran, heap[c + 1], heap[c]))
413  c++;
414  }
415  return(k);
416 }
417 
418 
419 /** insert respectively change element in heap */
420 inline static void correct(
421  SCIP* scip,
422  int* heap,
423  int* state,
424  int* count, /* pointer to store number of elements of heap */
425  double* pathdist,
426  double* pathtran,
427  int l)
428 {
429  int t;
430  int c;
431  int j;
432 
433  /* Ist der Knoten noch ganz frisch ?
434  */
435  if (state[l] == UNKNOWN)
436  {
437  heap[++(*count)] = l;
438  state[l] = (*count);
439  }
440 
441  /* Heap shift up
442  */
443  j = state[l];
444  c = j / 2;
445 
446  while((j > 1) && (islarger(scip, pathdist, pathtran, heap[c], heap[j])))
447  {
448  t = heap[c];
449  heap[c] = heap[j];
450  heap[j] = t;
451  state[heap[j]] = j;
452  state[heap[c]] = c;
453  j = c;
454  c = j / 2;
455  }
456 
457 }
458 
459 
460 /** Dijkstra's algorithm for shortest path or minimum spanning tree */
461 static
463  SCIP* scip,
464  const GRAPH* p,
465  int start,
466  const double* cost,
467  const double* randarr,
468  int* heap,
469  int* state,
470  int* count, /* pointer to store number of elements of heap */
471  double* pathdist,
472  double* pathtran,
473  double* pathrand
474  )
475 {
476  int k;
477  int m;
478  int i;
479  int done = 0;
480  double tran;
481  double dist;
482  double temprand;
483 
484  assert(scip != NULL);
485  assert(p != NULL);
486  assert(start >= 0);
487  assert(start < p->knots);
488  assert(heap != NULL);
489  assert(state != NULL);
490  assert(pathdist != NULL);
491  assert(pathtran != NULL);
492  assert(cost != NULL);
493  assert(count != NULL);
494  assert(*count >= 0);
495 
496  /* Kein Baum ohne Knoten
497  */
498  if (p->knots == 0)
499  return;
500 
501  (*count) = 0;
502 
503  /* Erstmal alles auf null, unbekannt und weit weg
504  */
505  for(i = 0; i < p->knots; i++)
506  {
507  state[i] = UNKNOWN;
508  pathdist[i] = FARAWAY;
509  pathtran[i] = FARAWAY;
510  }
511  /* Startknoten in den Heap
512  */
513  k = start;
514  pathdist[k] = 0.0;
515  pathtran[k] = 0.0;
516  pathrand[k] = 0.0;
517 
518  /* Wenn nur ein Knoten drin ist funktioniert der Heap nicht sehr gut,
519  * weil dann fuer genau 0 Elemente Platz ist.
520  */
521  if (p->knots > 1)
522  {
523  (*count) = 1;
524  heap[(*count)] = k;
525  state[k] = (*count);
526 
527  /* Wenn nichts mehr auf dem Heap ist, sind wir fertig
528  * und jetzt erstmal Hula Loop
529  */
530  while((*count) > 0)
531  {
532  /* Na, wer ist der Naechste ?
533  */
534  k = nearest(scip, heap, state, count, pathdist, pathtran);
535 
536  /* Wieder einen erledigt
537  */
538  state[k] = CONNECT;
539 
540  if (p->mark[k] == 2)
541  if (++done >= p->grad[start])
542  break;
543 
544  /* Verbunden Knoten berichtigen ...
545  *
546  * Wenn ein Knoten noch nicht erledigt ist
547  * werden wir dann auf diesem Wege besser ?
548  */
549  for(i = p->outbeg[k]; i != EAT_LAST; i = p->oeat[i])
550  {
551  m = p->head[i];
552 
553  /* 1. Ist der Knoten noch nicht festgelegt ?
554  * Ist der wohlmoeglich tabu ?
555  */
556  if ((state[m]) && (p->mark[m]))
557  {
558  /* 2. Ist es ueberhaupt eine Verbesserung diesen Weg zu nehmen ?
559  * Wenn ja, dann muss die Entferung kuerzer sein.
560  */
561  /* The special distance is the length of the longest path between two terminals (elementary path)
562  * contained in the path between knots i and j.
563  * - tran measures the distance between two terminals.
564  * - dist stores the current longest elementary path.
565  */
566  if( Is_term(p->term[m]) )
567  {
568  tran = 0.0;
569  temprand = 0.0;
570  }
571  else
572  {
573  tran = pathtran[k] + cost[i];
574  temprand = pathrand[k] + randarr[i];
575  }
576 
577  if( SCIPisGE(scip, pathdist[k], pathtran[k] + cost[i]) )
578  dist = pathdist[k];
579  else
580  dist = pathtran[k] + cost[i];
581 
582  if( SCIPisLT(scip, dist, pathdist[m])
583  || (SCIPisEQ(scip, dist, pathdist[m]) && SCIPisLT(scip, tran, pathtran[m])) )
584  {
585  pathdist[m] = dist;
586  pathtran[m] = tran;
587  pathrand[m] = temprand;
588 
589  correct(scip, heap, state, count, pathdist, pathtran, m);
590  }
591  }
592  }
593  }
594  }
595 }
596 
597 /** Special distance test */
598 SCIP_RETCODE sd_red(
599  SCIP* scip, /**< SCIP data structure */
600  GRAPH* g, /**< graph data structure */
601  PATH* vnoi, /**< Voronoi data structure */
602  SCIP_Real* edgepreds, /**< array to store edge predecessors of auxiliary graph */
603  SCIP_Real* mstsdist, /**< array to store mst distances in auxiliary graph */
604  int* heap, /**< array representing a heap */
605  int* state, /**< array to indicate whether a node has been scanned during SP calculation */
606  int* vbase, /**< Voronoi base to each vertex */
607  int* nodesid, /**< array to map nodes in auxiliary graph to original ones */
608  int* nodesorg, /**< array to map terminals of original graph vertices of auxiliary graph */
609  int* forbidden, /**< array to mark whether an edge may be eliminated */
610  int* nelims /**< point to store number of deleted edges */
611  )
612 {
613  GRAPH* netgraph;
614  PATH* mst;
615  SCIP_Real* termdist1;
616  SCIP_Real* termdist2;
617  SCIP_Real ecost;
618  SCIP_Real dist;
619 
620  int* neighbterms1;
621  int* neighbterms2;
622  int e;
623  int i;
624  int j;
625  int k;
626  int l;
627  int i2;
628  int tj;
629  int tk;
630  int ne;
631  int nj;
632  int nk;
633  int id1;
634  int id2;
635  int enext;
636  int nnodes;
637  int nterms;
638  int nedges;
639  int nnterms1;
640  int nnterms2;
641  int maxnedges;
642 
643  assert(g != NULL);
644  assert(scip != NULL);
645  assert(heap != NULL);
646  assert(vnoi != NULL);
647  assert(state != NULL);
648  assert(vbase != NULL);
649  assert(nelims != NULL);
650  assert(nodesid != NULL);
651  assert(mstsdist != NULL);
652  assert(nodesorg != NULL);
653  assert(edgepreds != NULL);
654  assert(forbidden != NULL);
655 
656  nnodes = g->knots;
657  nterms = g->terms;
658  nedges = g->edges;
659  *nelims = 0;
660  maxnedges = MIN(nedges, (nterms - 1) * nterms);
661 
662  /* only one terminal left? */
663  if( nterms == 1 )
664  return SCIP_OKAY;
665 
666  SCIP_CALL( SCIPallocBufferArray(scip, &termdist1, 4) );
667  SCIP_CALL( SCIPallocBufferArray(scip, &termdist2, 4) );
668  SCIP_CALL( SCIPallocBufferArray(scip, &neighbterms1, 4) );
669  SCIP_CALL( SCIPallocBufferArray(scip, &neighbterms2, 4) );
670 
671  /* compute nearest four terminals to all non-terminals */
672  getnext4terms(scip, g, g->cost, g->cost, vnoi, vbase, heap, state);
673 #if 0
674  int tpos;
675  int base;
676  int shift;
677  int x = 0;
678  for( tpos = 0; tpos < 4; tpos++ )
679  {
680  for( k = 0; k < nnodes; k++ )
681  {
682  if( Is_term(g->term[k]) || !g->mark[k] )
683  continue;
684 
685 
686  base = vbase[k + tpos * nnodes];
687  if( base == -1 )
688  continue;
689  shift = tpos * nnodes;
690  x = 0;
691  printf("in %d\n", base);
692  i = k;
693  while( i != base )
694  {
695  if( x++ >= 10000 )
696  {
697  printf("FAIL k: %d, tpos: %d, base: %d\n",k, tpos, base);
698  assert(0);
699  }
700  e = vnoi[i + shift].edge;
701 
702  assert(g->ieat[e] != EAT_FREE);
703 
704  i = g->tail[e];
705  }
706  }
707  }
708 #endif
709 #if 0
710  if( 1 )
711  {
712  SCIP_Real** pathdist = NULL;
713  int** pathedge = NULL;
714  SCIP_CALL( SCIPallocBufferArray(scip, &pathdist, nnodes) );
715  SCIP_CALL( SCIPallocBufferArray(scip, &pathedge, nnodes) );
716  BMSclearMemoryArray(pathdist, nnodes);
717  BMSclearMemoryArray(pathedge, nnodes);
718 
719  for( k = 0; k < nnodes; k++ )
720  {
721  g->mark[k] = (g->grad[k] > 0);
722 
723  if( 1 || !Is_term(g->term[k]) )
724  {
725  SCIP_CALL( SCIPallocBufferArray(scip, &(pathdist[k]), nnodes) ); /*lint !e866*/
726  SCIP_CALL( SCIPallocBufferArray(scip, &(pathedge[k]), nnodes) ); /*lint !e866*/
727  }
728  }
729  SCIP_CALL( SCIPprobdataPrintGraph2(g, "exgraph.gml", NULL) );
730  for( k = 0; k < nnodes; k++ )
731  {
732  if( (1 || !Is_term(g->term[k])) && g->mark[k] )
733  {
734  assert(pathdist[k] != NULL);
735  assert(pathedge[k] != NULL);
736  graph_path_execX(scip, g, k, g->cost, pathdist[k], pathedge[k]);
737  if( !Is_term(g->term[k]) )
738  continue;
739  j = vbase[k];
740  i = j;
741 
742  printf("x %f, %f ", pathdist[k][i], vnoi[k].dist);
743  printf("node terminal %d, %d \n\n", k, i);
744  assert(Is_term(g->term[i]));
745  if( !SCIPisEQ(scip, pathdist[k][i], vnoi[k].dist ) )
746  {
747  printf("FAILS0 %f, %f ", pathdist[k][i], vnoi[k].dist);
748  printf("node terminal %d, %d \n\n", k, i);
749 
750  assert(0);
751  }
752 
753  i = vbase[k + nnodes];
754  printf("x2 %f, %f ", pathdist[k][i], vnoi[k + nnodes].dist);
755  printf("node terminal %d, %d \n\n", k, i);
756  assert(Is_term(g->term[i]));
757  if( i != -1 && !SCIPisEQ(scip, pathdist[k][i], vnoi[k + nnodes].dist ) )
758  {
759  printf("FAILS1 %f, %f ", pathdist[k][i], vnoi[k + nnodes].dist);
760  printf("node terminal %d, %d \n\n", k, i);
761  assert(0);
762  }
763  i = vbase[k + 2 * nnodes];
764  printf("x3 %f, %f ", pathdist[k][i], vnoi[k + 2 * nnodes].dist);
765  printf("node terminal %d, %d \n\n", k, i);
766  assert(Is_term(g->term[i]));
767  if( i != -1 && !SCIPisEQ(scip, pathdist[k][i], vnoi[k + 2 * nnodes].dist ) )
768  {
769  printf("FAILS2 %f, %f ", pathdist[k][i], vnoi[k + 2 * nnodes].dist);
770  printf("node terminal %d, %d \n\n", k, i);
771  assert(0);
772  }
773 
774  i = vbase[k + 3 * nnodes];
775  printf("x4 %f, %f ", pathdist[k][i], vnoi[k + 3 * nnodes].dist);
776  printf("node terminal %d, %d \n\n", k, i);
777  assert(i == -1 || Is_term(g->term[i]));
778  if( i != -1 && SCIPisLT(scip, pathdist[k][i], vnoi[k + 3 * nnodes].dist ) )
779  {
780  printf("FAILS3 %f, %f ", pathdist[k][i], vnoi[k + 3 * nnodes].dist);
781  printf("node terminal %d, %d \n\n", k, i);
782  }
783 
784  }
785  }
786 
787  for( k = nnodes - 1; k >= 0; k-- )
788  {
789  SCIPfreeBufferArrayNull(scip, &(pathedge[k]));
790  SCIPfreeBufferArrayNull(scip, &(pathdist[k]));
791  }
792 
793  SCIPfreeBufferArray(scip, &pathedge);
794  SCIPfreeBufferArray(scip, &pathdist);
795 
796  }
797 #endif
798  /* construct auxiliary graph to compute paths between terminals */
799 
800  /* initialize the new graph */
801  SCIP_CALL( graph_init(scip, &netgraph, nterms, maxnedges, 1, 0) );
802 
803  j = 0;
804  for( k = 0; k < nnodes; k++ )
805  {
806  if( Is_term(g->term[k]) && g->grad[k] > 0 )
807  {
808  graph_knot_add(netgraph, -1);
809  nodesid[k] = j;
810  mstsdist[j] = -1.0;
811  netgraph->mark[j] = TRUE;
812  nodesorg[j++] = k;
813  }
814  else
815  {
816  nodesid[k] = UNKNOWN;
817  }
818  forbidden[k] = FALSE;
819  edgepreds[k] = -1.0;
820  }
821 
822  for( k = nnodes - 1; k < nedges; k++ )
823  {
824  forbidden[k] = FALSE;
825  edgepreds[k] = -1.0;
826  }
827 
828  assert(netgraph->knots == j);
829  assert(netgraph->knots == nterms);
830 
831  for( k = 0; k < nnodes; k++ )
832  {
833  i = vbase[k];
834  id1 = nodesid[i];
835 
836  for( e = g->outbeg[k]; e != EAT_LAST; e = g->oeat[e] )
837  {
838  if( i != vbase[g->head[e]] )
839  {
840  i2 = vbase[g->head[e]];
841  id2 = nodesid[i2];
842 
843  assert(id1 >= 0);
844  assert(id2 >= 0);
845  assert(Is_term(g->term[i]));
846  assert(Is_term(g->term[i2]));
847 
848  for( ne = netgraph->outbeg[id1]; ne != EAT_LAST; ne = netgraph->oeat[ne] )
849  if( netgraph->head[ne] == id2 )
850  break;
851 
852  /* cost of the edge in the auxiliary graph */
853  ecost = g->cost[e] + vnoi[g->head[e]].dist + vnoi[g->tail[e]].dist;
854 
855  /* does edge already exist? */
856  if( ne != EAT_LAST )
857  {
858  assert(ne >= 0);
859  assert(netgraph->tail[ne] == id1);
860  assert(netgraph->head[ne] == id2);
861 
862  /* is the new edge better than the existing one? */
863  if( SCIPisGT(scip, netgraph->cost[ne], ecost) )
864  {
865  netgraph->cost[ne] = ecost;
866  netgraph->cost[Edge_anti(ne)] = ecost;
867  edgepreds[ne] = e;
868  edgepreds[flipedge(ne)] = flipedge(e);
869 
870  assert(ne <= maxnedges);
871  }
872  }
873  else
874  {
875  edgepreds[netgraph->edges] = e;
876  edgepreds[netgraph->edges + 1] = flipedge(e);
877  graph_edge_add(scip, netgraph, id1, id2, ecost, ecost);
878 
879  assert(netgraph->edges <= maxnedges);
880  }
881  }
882  }
883  }
884 
885  /* compute MST on netgraph */
886  graph_knot_chg(netgraph, 0, 0);
887  netgraph->source[0] = 0;
888 
889  SCIP_CALL( SCIPallocBufferArray(scip, &mst, nterms) );
890  SCIP_CALL( graph_path_init(scip, netgraph) );
891 
892  graph_path_exec(scip, netgraph, MST_MODE, 0, netgraph->cost, mst);
893 
894  /* mark (original) edges of MST */
895  for( k = 1; k < netgraph->knots; k++ )
896  {
897  assert(mst[k].edge != -1);
898  assert((int) edgepreds[mst[k].edge] != -1);
899  assert((int) edgepreds[flipedge(mst[k].edge)] != -1);
900 
901  e = (int) edgepreds[mst[k].edge];
902 
903  assert(vbase[g->tail[e]] == nodesorg[k] || vbase[g->head[e]] == nodesorg[k]);
904 
905  if( Is_term(g->tail[e]) && Is_term(g->head[e]) )
906  {
907  forbidden[e] = TRUE;
908  forbidden[flipedge(e)] = TRUE;
909  }
910 #if 0
911  i1 = g->tail[e];
912  i2 = g->head[e];
913  while( i1 != vbase[i1] )
914  {
915  e = vnoi[i1].edge;
916  forbidden[e] = TRUE;
917  forbidden[flipedge(e)] = TRUE;
918  i1 = g->tail[e];
919  }
920 
921  while( i2 != vbase[i2] )
922  {
923  e = vnoi[i2].edge;
924  forbidden[e] = TRUE;
925  forbidden[flipedge(e)] = TRUE;
926  i2 = g->tail[e];
927  }
928 #endif
929  }
930 
931  /* traverse all edges */
932  for( i = 0; i < nnodes; i++ )
933  {
934  if( !g->mark[i] )
935  continue;
936 
937  nnterms1 = 1;
938  if( Is_term(g->term[i]) )
939  {
940  termdist1[0] = 0.0;
941  neighbterms1[0] = i;
942  }
943 
944  enext = g->outbeg[i];
945  while( enext != EAT_LAST )
946  {
947  e = enext;
948  i2 = g->head[e];
949  enext = g->oeat[e];
950 
951  if( i2 < i || !g->mark[i2] )
952  continue;
953 
954  ecost = g->cost[e];
955 
956  /* is i a terminal? If not, get three closest terminals of distance smaller ecost */
957  if( !Is_term(g->term[i]) )
958  {
959 #if 0
960  if( Is_term(g->term[i2]) )
961  nnterms1 = getcloseterms(scip, vnoi, termdist1, ecost, vbase, neighbterms1, i, nnodes);
962  else
963  nnterms2 = getlecloseterms(scip, vnoi, termdist2, ecost, vbase, neighbterms2, i2, nnodes);
964 #endif
965  nnterms1 = getlecloseterms(scip, vnoi, termdist1, ecost, vbase, neighbterms1, i, nnodes);
966 
967  if( nnterms1 == 0 )
968  continue;
969  }
970 
971  nnterms2 = 0;
972 
973  if( Is_term(g->term[i2]) )
974  {
975  nnterms2 = 1;
976  termdist2[0] = 0.0;
977  neighbterms2[0] = i2;
978  }
979  else
980  {
981  /* get closest terminals of distance smaller ecost */
982 #if 0
983  if( Is_term(g->term[i]) )
984  nnterms2 = getcloseterms(scip, vnoi, termdist2, ecost, vbase, neighbterms2, i2, nnodes);
985  else
986  nnterms2 = getlecloseterms(scip, vnoi, termdist2, ecost, vbase, neighbterms2, i2, nnodes);
987 #endif
988  nnterms2 = getlecloseterms(scip, vnoi, termdist2, ecost, vbase, neighbterms2, i2, nnodes);
989 
990  if( nnterms2 == 0 )
991  continue;
992  }
993 
994  for( j = 0; j < nnterms1; j++ )
995  {
996  /* has edge already been deleted? */
997  if( g->oeat[e] == EAT_FREE )
998  break;
999 
1000  tj = neighbterms1[j];
1001 
1002  assert(tj >= 0);
1003 
1004  for( k = 0; k < nnterms2; k++ )
1005  {
1006  tk = neighbterms2[k];
1007 
1008  assert(tk >= 0);
1009  assert(Is_term(g->term[tk]));
1010  assert(Is_term(g->term[tj]));
1011 
1012  if( tj == tk )
1013  {
1014  if( SCIPisGE(scip, termdist1[j], termdist2[k] ) )
1015  dist = termdist1[j];
1016  else
1017  dist = termdist2[k];
1018 
1019  assert(SCIPisGE(scip, ecost, dist));
1020 
1021  if( SCIPisEQ(scip, dist, ecost) )
1022  if( !sddeltable(scip, g, vnoi, vbase, forbidden, j, k, i, i2, e, nnodes ) )
1023  continue;
1024 
1025  graph_edge_del(scip, g, e, TRUE);
1026  (*nelims)++;
1027  break;
1028  }
1029  else
1030  {
1031  /* get sd between (terminals) tj and tk */
1032  nj = nodesid[tj];
1033  nk = nodesid[tk];
1034 
1035  assert(nj != nk);
1036 
1037  l = nj;
1038  dist = 0.0;
1039  mstsdist[l] = 0.0;
1040 
1041  /* go down to the root */
1042  while( l != 0 )
1043  {
1044  ne = mst[l].edge;
1045 
1046  assert(netgraph->head[ne] == l);
1047 
1048  l = netgraph->tail[ne];
1049 
1050  if( SCIPisGT(scip, netgraph->cost[ne], dist) )
1051  dist = netgraph->cost[ne];
1052 
1053  mstsdist[l] = dist;
1054 
1055  if( l == nk )
1056  break;
1057  }
1058 
1059  if( l == nk )
1060  {
1061  l = 0;
1062  }
1063  else
1064  {
1065  l = nk;
1066  dist = 0.0;
1067  }
1068 
1069  while( l != 0 )
1070  {
1071  ne = mst[l].edge;
1072  l = netgraph->tail[ne];
1073 
1074  if( SCIPisGT(scip, netgraph->cost[ne], dist) )
1075  dist = netgraph->cost[ne];
1076 
1077  if( mstsdist[l] >= 0 )
1078  {
1079  if( SCIPisGT(scip, mstsdist[l], dist) )
1080  dist = mstsdist[l];
1081  break;
1082  }
1083  if( l == 0 )
1084  assert(nj == 0);
1085  }
1086 
1087  /* restore */
1088  l = nj;
1089  mstsdist[l] = -1.0;
1090 
1091  while( l != 0 )
1092  {
1093  ne = mst[l].edge;
1094  l = netgraph->tail[ne];
1095  mstsdist[l] = -1.0;
1096  if( l == nk )
1097  break;
1098  }
1099 
1100  assert(SCIPisGT(scip, dist, 0.0));
1101 
1102  if( SCIPisLT(scip, dist, termdist1[j]) )
1103  dist = termdist1[j];
1104 
1105  if( SCIPisLT(scip, dist, termdist2[k]) )
1106  dist = termdist2[k];
1107 
1108  if( SCIPisGE(scip, ecost, dist) )
1109  {
1110  if( SCIPisEQ(scip, ecost, dist) )
1111  if( !(sddeltable(scip, g, vnoi, vbase, forbidden, j, k, i, i2, e, nnodes)) )
1112  continue;
1113 
1114  assert(SCIPisGE(scip, ecost, termdist1[j]));
1115  assert(SCIPisGE(scip, ecost, termdist2[k]));
1116 
1117  graph_edge_del(scip, g, e, TRUE);
1118  (*nelims)++;
1119  break;
1120  }
1121  } /* tj != tk (else) */
1122  } /* k < nnterms2 */
1123  } /* j < nnterms1 */
1124 
1125  } /* while( enext != EAT_LAST ) */
1126  }
1127 
1128  SCIP_CALL( bdr_reduction(scip, g, netgraph, mst, vnoi, mstsdist, termdist1, termdist2, vbase, nodesid, neighbterms1, neighbterms2, nelims) );
1129 
1130  /* free memory*/
1131  graph_path_exit(scip, netgraph);
1132  graph_free(scip, netgraph, TRUE);
1133  SCIPfreeBufferArray(scip, &mst);
1134  SCIPfreeBufferArray(scip, &neighbterms2);
1135  SCIPfreeBufferArray(scip, &neighbterms1);
1136  SCIPfreeBufferArray(scip, &termdist2);
1137  SCIPfreeBufferArray(scip, &termdist1);
1138 
1139  return SCIP_OKAY;
1140 }
1141 
1142 
1143 /** SD test for PC */
1144 SCIP_RETCODE sdpc_reduction(
1145  SCIP* scip, /**< SCIP data structure */
1146  GRAPH* g, /**< graph data structure */
1147  PATH* vnoi, /**< Voronoi data structure */
1148  SCIP_Real* boundedges, /**< array to store bound edges */
1149  int* heap, /**< heap array */
1150  int* state, /**< array to store state of a node during Voronoi computation*/
1151  int* vbase, /**< Voronoi base to each node */
1152  int* nodesid, /**< array */
1153  int* nodesorg, /**< array */
1154  int* nelims /**< pointer to store number of eliminated edges */
1155  )
1156 {
1157  GRAPH* netgraph;
1158  SCIP_Real* termdist1;
1159  SCIP_Real* termdist2;
1160  SCIP_Real ecost;
1161  SCIP_Real necost;
1162  int* neighbterms1;
1163  int* neighbterms2;
1164  int e;
1165  int e2;
1166  int i;
1167  int i2;
1168  int j;
1169  int k;
1170  int l;
1171  int tj;
1172  int tk;
1173  int ne;
1174  int pos;
1175  int root;
1176  int enext;
1177  int nnodes;
1178  int nterms;
1179  int nedges;
1180  int nnterms1;
1181  int nnterms2;
1182  int maxnedges;
1183 
1184  assert(g != NULL);
1185  assert(heap != NULL);
1186  assert(vnoi != NULL);
1187  assert(state != NULL);
1188  assert(vbase != NULL);
1189  assert(scip != NULL);
1190  assert(nelims != NULL);
1191  assert(nodesid != NULL);
1192  assert(nodesorg != NULL);
1193  assert(boundedges != NULL);
1194 
1195  root = g->source[0];
1196  nnodes = g->knots;
1197  nterms = g->terms;
1198  nedges = g->edges;
1199  *nelims = 0;
1200  maxnedges = MIN(nedges, (nterms - 1) * nterms);
1201 
1202  SCIP_CALL( SCIPallocBufferArray(scip, &termdist1, 4) );
1203  SCIP_CALL( SCIPallocBufferArray(scip, &termdist2, 4) );
1204  SCIP_CALL( SCIPallocBufferArray(scip, &neighbterms1, 4) );
1205  SCIP_CALL( SCIPallocBufferArray(scip, &neighbterms2, 4) );
1206 
1207  /* compute nearest four terminals to each non-terminal */
1208  getnext4terms(scip, g, g->cost, g->cost, vnoi, vbase, heap, state);
1209 
1210  /* construct auxiliary graph to compute paths between terminals */
1211 
1212  /* initialize new graph */
1213  SCIP_CALL( graph_init(scip, &netgraph, nterms, maxnedges, 1, 0) );
1214 
1215  for( k = 0; k < 4; k++ )
1216  {
1217  termdist1[k] = FARAWAY;
1218  termdist2[k] = FARAWAY;
1219  }
1220 
1221  j = 0;
1222  for( k = 0; k < nnodes; k++ )
1223  {
1224  if( Is_term(g->term[k]) && g->grad[k] > 0 )
1225  {
1226  graph_knot_add(netgraph, -1);
1227  nodesid[k] = j;
1228  nodesorg[j++] = k;
1229  }
1230  else
1231  {
1232  nodesid[k] = UNKNOWN;
1233  }
1234  }
1235 
1236  assert(netgraph->knots == j);
1237  assert(netgraph->knots == nterms);
1238 
1239  /* insert Voronoi boundary paths as edges into netgraph */
1240  for( k = 0; k < nnodes; k++ )
1241  {
1242  if( !g->mark[k] )
1243  continue;
1244  for( e = g->outbeg[k]; e != EAT_LAST; e = g->oeat[e] )
1245  {
1246  if( !g->mark[g->head[e]] )
1247  continue;
1248  i = vbase[k];
1249  assert(i != UNKNOWN);
1250  if( i != vbase[g->head[e]] )
1251  {
1252  i2 = vbase[g->head[e]];
1253  assert(i2 != UNKNOWN);
1254  assert(Is_term(g->term[i]));
1255  assert(Is_term(g->term[i2]));
1256  assert(nodesid[i] >= 0);
1257  assert(nodesid[i2] >= 0);
1258  for( ne = netgraph->outbeg[nodesid[i]]; ne != EAT_LAST; ne = netgraph->oeat[ne] )
1259  if( netgraph->head[ne] == nodesid[i2] )
1260  break;
1261 
1262  ecost = g->cost[e] + vnoi[g->head[e]].dist + vnoi[g->tail[e]].dist;
1263  /* edge exists? */
1264  if( ne != EAT_LAST )
1265  {
1266  assert(ne >= 0);
1267  assert(netgraph->head[ne] == nodesid[i2]);
1268  assert(netgraph->tail[ne] == nodesid[i]);
1269  if( SCIPisGT(scip, netgraph->cost[ne], ecost) )
1270  {
1271  netgraph->cost[ne] = ecost;
1272  netgraph->cost[Edge_anti(ne)] = ecost;
1273  assert(ne <= maxnedges);
1274  }
1275  }
1276  else
1277  {
1278  graph_edge_add(scip, netgraph, nodesid[i], nodesid[i2], ecost, ecost);
1279  assert(netgraph->edges <= maxnedges);
1280  }
1281  }
1282  }
1283  }
1284 
1285  /* compute four close terminals to each terminal */
1286  getnext4tterms(scip, g, g->cost, boundedges, vnoi, vbase, heap, state);
1287 
1288  /* traverse all edges */
1289  for( i = 0; i < nnodes; i++ )
1290  {
1291  if( !g->mark[i] )
1292  continue;
1293 
1294  enext = g->outbeg[i];
1295  while( enext != EAT_LAST )
1296  {
1297  e = enext;
1298  enext = g->oeat[e];
1299  i2 = g->head[e];
1300  if( i2 < i || Is_term(g->term[i2]) || !g->mark[i2] )
1301  continue;
1302  ecost = g->cost[e];
1303 
1304  /* @todo: fix */
1305 #if 0
1306  if( Is_term(g->term[i]) )
1307  {
1308  for( k = 0; k < 4; k++ )
1309  neighbterms1[k] = UNKNOWN;
1310  nnterms1 = 0;
1311  /* get three nearest terms */
1312  for( ne = netgraph->outbeg[nodesid[i]]; ne != EAT_LAST; ne = netgraph->oeat[ne] )
1313  {
1314  if( SCIPisLT(scip, netgraph->cost[ne], ecost) )
1315  {
1316  j = nodesorg[netgraph->head[ne]];
1317  necost = netgraph->cost[ne];
1318  assert(Is_term(g->term[j]));
1319  assert(j != i2);
1320  if( nnterms1 < 4 )
1321  nnterms1++;
1322  for( k = 0; k < 4; k++ )
1323  {
1324  if( neighbterms1[k] == UNKNOWN || SCIPisGT(scip, termdist1[k], necost) )
1325  {
1326  for( l = 3; l > k; l-- )
1327  {
1328  neighbterms1[l] = neighbterms1[l - 1];
1329  termdist1[l] = termdist1[l - 1];
1330  }
1331  neighbterms1[k] = j;
1332  termdist1[k] = necost;
1333  break;
1334  }
1335  }
1336  }
1337  }
1338  }
1339  else
1340  {
1341  nnterms1 = getcloseterms(scip, vnoi, termdist1, ecost, vbase, neighbterms1, i, nnodes);
1342  }
1343 #endif
1344  nnterms1 = getcloseterms(scip, vnoi, termdist1, ecost, vbase, neighbterms1, i, nnodes);
1345 
1346  if( nnterms1 == 0 )
1347  continue;
1348 
1349  /* @todo: fix */
1350 #if 0
1351  if( Is_term(g->term[i2]) )
1352  {
1353  for( k = 0; k < 4; k++ )
1354  neighbterms2[k] = UNKNOWN;
1355  nnterms2 = 0;
1356  /* get three nearest terms */
1357  for( ne = netgraph->outbeg[nodesid[i2]]; ne != EAT_LAST; ne = netgraph->oeat[ne] )
1358  {
1359  if( SCIPisLT(scip, netgraph->cost[ne], ecost) )
1360  {
1361  j = nodesorg[netgraph->head[ne]];
1362  necost = netgraph->cost[ne];
1363  assert(Is_term(g->term[j]));
1364  assert(j != i);
1365  if( nnterms2 < 4 )
1366  nnterms2++;
1367  for( k = 0; k < 4; k++ )
1368  {
1369  if( neighbterms2[k] == UNKNOWN || SCIPisGT(scip, termdist2[k], necost) )
1370  {
1371  for( l = 3; l > k; l-- )
1372  {
1373  neighbterms2[l] = neighbterms2[l - 1];
1374  termdist2[l] = termdist2[l - 1];
1375  }
1376  neighbterms2[k] = j;
1377  termdist2[k] = necost;
1378  break;
1379  }
1380  }
1381  }
1382  }
1383  }
1384  else
1385  {
1386  nnterms2 = getcloseterms(scip, vnoi, termdist2, ecost, vbase, neighbterms2, i2, nnodes);
1387  }
1388 #endif
1389  nnterms2 = getcloseterms(scip, vnoi, termdist2, ecost, vbase, neighbterms2, i2, nnodes);
1390 
1391  if( nnterms2 == 0 )
1392  continue;
1393 
1394  /* @todo: mark nearest terminals!!!! */
1395  for( j = 0; j < nnterms1; j++ )
1396  {
1397  /* has edge already been deleted? */
1398  if( g->oeat[e] == EAT_FREE )
1399  break;
1400  tj = neighbterms1[j];
1401  assert(tj >= 0);
1402  assert(Is_term(g->term[tj]));
1403  for( k = 0; k < nnterms2; k++ )
1404  {
1405  tk = neighbterms2[k];
1406  assert(tk >= 0);
1407  assert(Is_term(g->term[tk]));
1408  if( tj == tk )
1409  {
1410  if( SCIPisGT(scip, ecost, termdist1[j] + termdist2[k] - g->prize[tj]) || tj == root )
1411  {
1412  graph_edge_del(scip, g, e, TRUE);
1413  (*nelims)++;
1414  break;
1415  }
1416  }
1417  else
1418  {
1419  necost = FARAWAY;
1420 
1421  for( e2 = netgraph->outbeg[nodesid[tj]]; e2 != EAT_LAST; e2 = netgraph->oeat[e2] )
1422  {
1423  if( netgraph->head[e2] == nodesid[tk] )
1424  {
1425  necost = netgraph->cost[e2];
1426 
1427  break;
1428  }
1429  }
1430  pos = tj;
1431  for( l = 0; l < 4; l++ )
1432  {
1433  if( vbase[pos] == UNKNOWN )
1434  break;
1435  if( vbase[pos] == tk && SCIPisLT(scip, vnoi[pos].dist, necost) )
1436  {
1437  necost = vnoi[pos].dist;
1438  e2 = 0;
1439  break;
1440  }
1441  pos += nnodes;
1442  }
1443 
1444 #if 1
1445  if( e2 != EAT_LAST && SCIPisGT(scip, ecost, necost)
1446  && SCIPisGT(scip, ecost, necost + termdist1[j] - g->prize[tj])
1447  && SCIPisGT(scip, ecost, necost + termdist2[k] - g->prize[tk])
1448  && SCIPisGT(scip, ecost, necost + termdist1[j] + termdist2[k] - g->prize[tj] - g->prize[tk]) )
1449  {
1450  SCIPdebugMessage("SDSP delete: %d %d (%d)\n", g->tail[e], g->head[e], e);
1451  graph_edge_del(scip, g, e, TRUE);
1452  (*nelims)++;
1453  break;
1454  }
1455 #endif
1456  }
1457  }
1458  }
1459  }
1460  }
1461 
1462  graph_free(scip, netgraph, TRUE);
1463  SCIPfreeBufferArray(scip, &neighbterms2);
1464  SCIPfreeBufferArray(scip, &neighbterms1);
1465  SCIPfreeBufferArray(scip, &termdist2);
1466  SCIPfreeBufferArray(scip, &termdist1);
1467  return SCIP_OKAY;
1468 }
1469 
1470 /** get RSD to a single edge*/
1471 static
1472 SCIP_Real getRSD(
1473  SCIP* scip, /**< SCIP data structure */
1474  GRAPH* g, /**< graph structure */
1475  GRAPH* netgraph, /**< auxiliary graph structure */
1476  PATH* mst, /**< MST structure */
1477  PATH* vnoi, /**< path structure */
1478  SCIP_Real* mstsdist, /**< MST distance in aux-graph */
1479  SCIP_Real* termdist1, /**< dist array */
1480  SCIP_Real* termdist2, /**< second dist array */
1481  int* vbase, /**< bases for nearest terminals */
1482  int* nodesid, /**< nodes identification array */
1483  int* neighbterms1, /**< neighbour terminals array */
1484  int* neighbterms2, /**< second neighbour terminals array */
1485  int i, /**< first vertex */
1486  int i2, /**< second vertex */
1487  int limit /**< limit for incident edges to consider */
1488  )
1489 {
1490  SCIP_Real sd;
1491  SCIP_Real max;
1492  SCIP_Real dist;
1493  int l;
1494  int e;
1495  int j;
1496  int k;
1497  int ne;
1498  int tj;
1499  int tk;
1500  int nj;
1501  int nk;
1502  int nnodes;
1503  int nnterms1;
1504  int nnterms2;
1505 
1506  assert(scip != NULL);
1507  assert(g != NULL);
1508  assert(netgraph != NULL);
1509  assert(mst != NULL);
1510  assert(mstsdist != NULL);
1511  assert(termdist1 != NULL);
1512  assert(termdist2 != NULL);
1513  assert(neighbterms1 != NULL);
1514  assert(neighbterms2 != NULL);
1515 
1516  nnodes = g->knots;
1517  l = 0;
1518  sd = FARAWAY;
1519  /* compare restriced sd with edge cost (if existing) */
1520  for( e = g->outbeg[i]; (l++ <= limit) && (e != EAT_LAST); e = g->oeat[e] )
1521  {
1522  if( g->head[e] == i2 )
1523  {
1524  sd = g->cost[e];
1525  break;
1526  }
1527  }
1528 
1529  /* is i a terminal? If not, get three closest terminals of distance smaller sd */
1530  if( Is_term(g->term[i]) )
1531  {
1532  nnterms1 = 1;
1533  termdist1[0] = 0.0;
1534  neighbterms1[0] = i;
1535  }
1536  else
1537  {
1538  nnterms1 = getcloseterms(scip, vnoi, termdist1, sd, vbase, neighbterms1, i, nnodes);
1539 
1540  if( nnterms1 == 0 )
1541  return sd;
1542  }
1543 
1544  /* is i2 a terminal? If not, get three closest terminals of distance smaller sd */
1545  if( Is_term(g->term[i2]) )
1546  {
1547  nnterms2 = 1;
1548  termdist2[0] = 0.0;
1549  neighbterms2[0] = i2;
1550  }
1551  else
1552  {
1553  /* get closest terminals of distance smaller sd */
1554  nnterms2 = getcloseterms(scip, vnoi, termdist2, sd, vbase, neighbterms2, i2, nnodes);
1555 
1556  if( nnterms2 == 0 )
1557  return sd;
1558  }
1559 
1560  for( j = 0; j < nnterms1; j++ )
1561  {
1562  tj = neighbterms1[j];
1563  assert(tj >= 0);
1564  for( k = 0; k < nnterms2; k++ )
1565  {
1566  tk = neighbterms2[k];
1567  assert(Is_term(g->term[tk]));
1568  assert(Is_term(g->term[tj]));
1569  assert(tk >= 0);
1570 
1571  if( SCIPisGT(scip, termdist1[j], termdist2[k]) )
1572  max = termdist1[j];
1573  else
1574  max = termdist2[k];
1575 
1576  if( tj == tk )
1577  {
1578  if( SCIPisLT(scip, max, sd) )
1579  sd = max;
1580  }
1581  else
1582  {
1583  /* get sd between (terminals) tj and tk */
1584  nj = nodesid[tj];
1585  nk = nodesid[tk];
1586  assert(nj != nk);
1587 
1588  l = nj;
1589  dist = 0.0;
1590  mstsdist[l] = 0.0;
1591 
1592  while( l != 0 )
1593  {
1594  ne = mst[l].edge;
1595 
1596  assert(netgraph->head[ne] == l);
1597  l = netgraph->tail[ne];
1598  if( SCIPisGT(scip, netgraph->cost[ne], dist) )
1599  dist = netgraph->cost[ne];
1600 
1601  mstsdist[l] = dist;
1602  if( l == nk )
1603  break;
1604  }
1605 
1606  if( l == nk )
1607  {
1608  l = 0;
1609  }
1610  else
1611  {
1612  l = nk;
1613  dist = 0.0;
1614  }
1615  while( l != 0 )
1616  {
1617  ne = mst[l].edge;
1618  l = netgraph->tail[ne];
1619  if( SCIPisGT(scip, netgraph->cost[ne], dist) )
1620  dist = netgraph->cost[ne];
1621 
1622  if( mstsdist[l] >= 0 )
1623  {
1624  if( SCIPisGT(scip, mstsdist[l], dist) )
1625  dist = mstsdist[l];
1626  break;
1627  }
1628  if( l == 0 )
1629  assert( nj == 0);
1630  }
1631 
1632  /* restore */
1633  l = nj;
1634  mstsdist[l] = -1.0;
1635  while( l != 0 )
1636  {
1637  ne = mst[l].edge;
1638  l = netgraph->tail[ne];
1639  mstsdist[l] = -1.0;
1640  if( l == nk )
1641  break;
1642  }
1643 
1644  assert(SCIPisGT(scip, dist, 0.0));
1645  if( SCIPisGT(scip, dist, max) )
1646  max = dist;
1647  if( SCIPisLT(scip, max, sd) )
1648  sd = max;
1649  }
1650  } /* k < nnterms2 */
1651  } /* j < nnterms1 */
1652  return sd;
1653 }
1654 
1655 
1656 
1657 /** get SD to a single edge*/
1658 SCIP_RETCODE getSD(
1659  SCIP* scip,
1660  GRAPH* g,
1661  PATH* pathtail,
1662  PATH* pathhead,
1663  SCIP_Real* sdist,
1664  SCIP_Real distlimit,
1665  int* heap,
1666  int* statetail,
1667  int* statehead,
1668  int* memlbltail,
1669  int* memlblhead,
1670  int i,
1671  int i2,
1672  int limit,
1673  SCIP_Bool pc,
1674  SCIP_Bool mw
1675  )
1676 {
1677  SCIP_Real sd;
1678  SCIP_Real dist;
1679  int k;
1680  int l;
1681  int e;
1682  int nnodes;
1683  int nlbltail;
1684  int nlblhead;
1685  SCIP_Bool pcmw;
1686 
1687  assert(g != NULL);
1688  assert(scip != NULL);
1689  assert(pathtail != NULL);
1690  assert(pathhead != NULL);
1691  assert(heap != NULL);
1692  assert(statetail != NULL);
1693  assert(statehead != NULL);
1694  assert(memlbltail != NULL);
1695  assert(memlblhead != NULL);
1696  assert(sdist != NULL);
1697 
1698  pcmw = pc || mw;
1699  nnodes = g->knots;
1700 
1701  /* start from tail */
1702  sdpaths(scip, g, pathtail, g->cost, distlimit, heap, statetail, memlbltail, &nlbltail, i, i2, limit);
1703 
1704  /* test whether edge e can be eliminated */
1705  sdpaths(scip, g, pathhead, g->cost, distlimit, heap, statehead, memlblhead, &nlblhead, i2, i, limit);
1706 
1707  sd = FARAWAY;
1708 #if 0
1709  if( statetail[i2] != UNKNOWN )
1710  {
1711  sd = pathtail[i2].dist;
1712  assert(SCIPisGT(scip, FARAWAY, sd));
1713  }
1714  if( statehead[i] != UNKNOWN && SCIPisGT(scip, sd, pathhead[i].dist) )
1715  {
1716  sd = pathhead[i].dist;
1717  assert(SCIPisGT(scip, FARAWAY, sd));
1718  }
1719 #endif
1720  /* get restore state and path of tail and head */
1721  for( k = 0; k < nlbltail; k++ )
1722  {
1723  l = memlbltail[k];
1724  assert(statetail[l] != UNKNOWN);
1725  if( statehead[l] != UNKNOWN )
1726  {
1727  assert(SCIPisGT(scip, FARAWAY, pathtail[l].dist));
1728  assert(SCIPisGT(scip, FARAWAY, pathhead[l].dist));
1729  if( Is_term(g->term[l]) )
1730  {
1731  dist = 0.0;
1732  if( SCIPisLT(scip, dist, pathhead[l].dist) )
1733  dist = pathhead[l].dist;
1734  if( SCIPisLT(scip, dist, pathtail[l].dist) )
1735  dist = pathtail[l].dist;
1736  if( pcmw && SCIPisLT(scip, dist, pathhead[l].dist + pathtail[l].dist - g->prize[l]) )
1737  dist = pathhead[l].dist + pathtail[l].dist - g->prize[l];
1738  if( SCIPisGT(scip, sd, dist) )
1739  sd = dist;
1740  }
1741  else
1742  {
1743  if( mw && l != i && l != i2 )
1744  assert(SCIPisLE(scip, g->prize[l], 0.0));
1745  if( mw && SCIPisLT(scip, g->prize[l], 0.0) )
1746  dist = pathhead[l].dist + pathtail[l].dist + g->prize[l];
1747  else
1748  dist = pathhead[l].dist + pathtail[l].dist;
1749  if( SCIPisGT(scip, sd, dist) )
1750  sd = dist;
1751  }
1752  }
1753 
1754  statetail[l] = UNKNOWN;
1755  pathtail[l].dist = FARAWAY;
1756  pathtail[l].edge = UNKNOWN;
1757  }
1758  /* restore state and path of tail and head */
1759  for( k = 0; k < nlblhead; k++ )
1760  {
1761  l = memlblhead[k];
1762  statehead[l] = UNKNOWN;
1763  pathhead[l].dist = FARAWAY;
1764  pathhead[l].edge = UNKNOWN;
1765  }
1766 
1767 
1768  for( k = 0; k < nnodes; k++ )
1769  {
1770  assert(statetail[k] == UNKNOWN);
1771  assert(pathtail[k].dist == FARAWAY);
1772  assert(pathtail[k].edge == UNKNOWN);
1773  assert(statehead[k] == UNKNOWN);
1774  assert(pathhead[k].dist == FARAWAY);
1775  assert(pathhead[k].edge == UNKNOWN);
1776  }
1777 
1778 
1779  l = 0;
1780  /* compare restriced sd with edge cost (if existing) */
1781  for( e = g->outbeg[i]; (l++ <= limit) && (e != EAT_LAST); e = g->oeat[e] )
1782  {
1783  if( g->head[e] == i2 )
1784  {
1785  if( mw )
1786  sd = 0.0;
1787  else if( SCIPisGT(scip, sd, g->cost[e]) )
1788  sd = g->cost[e];
1789  break;
1790  }
1791  }
1792 
1793  *sdist = sd;
1794  return SCIP_OKAY;
1795 }
1796 
1797 
1798 /** SD test using only two edges */
1799 SCIP_RETCODE sd2_reduction(
1800  SCIP* scip,
1801  GRAPH* g,
1802  SCIP_Real* nodecost,
1803  int* nelims,
1804  int* adjacent
1805  )
1806 {
1807  SCIP_Real cost;
1808  int i;
1809  int e;
1810  int i2;
1811  int i3;
1812  int e2;
1813  int enext;
1814  int nnodes;
1815  SCIP_Bool pc;
1816 
1817  assert(g != NULL);
1818  assert(scip != NULL);
1819  assert(nelims != NULL);
1820  assert(adjacent != NULL);
1821  assert(nodecost != NULL);
1822 
1823  nnodes = g->knots;
1824  *nelims = 0;
1826 
1827  if( !pc )
1828  for( i = 0; i < nnodes; i++ )
1829  g->mark[i] = (g->grad[i] > 0);
1830  for( i = 0; i < nnodes; i++ )
1831  adjacent[i] = FALSE;
1832 
1833  for( i = 0; i < nnodes; i++ )
1834  {
1835  if( !g->mark[i] )
1836  continue;
1837 
1838  /* mark neighbours */
1839  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
1840  {
1841  i2 = g->head[e];
1842  if( g->mark[i2] )
1843  {
1844  adjacent[i2] = TRUE;
1845  nodecost[i2] = g->cost[e];
1846  }
1847  }
1848  assert(!adjacent[i]);
1849 
1850  /* traverse neighbours */
1851  e = g->outbeg[i];
1852  while( e != EAT_LAST )
1853  {
1854  enext = g->oeat[e];
1855  i2 = g->head[e];
1856  /* avoid double check */
1857  if( i2 < i || !g->mark[i2] )
1858  {
1859  e = enext;
1860  continue;
1861  }
1862 
1863  /* test whether edge e can be eliminated */
1864  cost = g->cost[e];
1865 
1866  for( e2 = g->outbeg[i2]; e2 != EAT_LAST; e2 = g->oeat[e2] )
1867  {
1868  i3 = g->head[e2];
1869  if( !adjacent[i3] )
1870  continue;
1871 
1872  assert(g->mark[i3]);
1873 
1874  if( (Is_term(g->term[i3]) && SCIPisGE(scip, cost, g->cost[e2]) && SCIPisGE(scip, cost, nodecost[i3])) ||
1875  (!Is_term(g->term[i3]) && SCIPisGE(scip, cost, g->cost[e2] + nodecost[i3])) )
1876  {
1877  if( pc && Is_term(g->term[i3]) && !SCIPisGE(scip, cost, g->cost[e2] + nodecost[i3] - g->prize[i3]) )
1878  continue;
1879 
1880  adjacent[i2] = FALSE;
1881  graph_edge_del(scip, g, e, TRUE);
1882  (*nelims)++;
1883  break;
1884  }
1885  }
1886  e = enext;
1887  }
1888 
1889  /* restore neigbour adjacency array */
1890  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
1891  adjacent[g->head[e]] = FALSE;
1892  }
1893 
1894  return SCIP_OKAY;
1895 }
1896 
1897 
1898 
1899 /** SDC test for the SAP using a limited version of Dijkstra's algorithm from both endpoints of an arc */
1900 SCIP_RETCODE sdsp_sap_reduction(
1901  SCIP* scip,
1902  GRAPH* g,
1903  PATH* pathtail,
1904  PATH* pathhead,
1905  int* heap,
1906  int* statetail,
1907  int* statehead,
1908  int* memlbltail,
1909  int* memlblhead,
1910  int* nelims,
1911  int limit
1912  )
1913 {
1914  SCIP_Real sdist;
1915  SCIP_Real* costrev;
1916  int i;
1917  int k;
1918  int l;
1919  int e;
1920  int i2;
1921  int enext;
1922  int nnodes;
1923  int nedges;
1924  int nlbltail;
1925  int nlblhead;
1926 
1927  assert(g != NULL);
1928  assert(scip != NULL);
1929  assert(pathtail != NULL);
1930  assert(pathhead != NULL);
1931  assert(heap != NULL);
1932  assert(statetail != NULL);
1933  assert(statehead != NULL);
1934  assert(memlbltail != NULL);
1935  assert(memlblhead != NULL);
1936  assert(nelims != NULL);
1937 
1938  nedges = g->edges;
1939  nnodes = g->knots;
1940  *nelims = 0;
1941 
1942  for( i = 0; i < nnodes; i++ )
1943  {
1944  g->mark[i] = (g->grad[i] > 0);
1945  statetail[i] = UNKNOWN;
1946  pathtail[i].dist = FARAWAY;
1947  pathtail[i].edge = UNKNOWN;
1948  statehead[i] = UNKNOWN;
1949  pathhead[i].dist = FARAWAY;
1950  pathhead[i].edge = UNKNOWN;
1951  }
1952 
1953  SCIP_CALL( SCIPallocBufferArray(scip, &costrev, nedges) );
1954 
1955  for( e = 0; e < nedges; e++ )
1956  costrev[e] = g->cost[flipedge(e)];
1957 
1958  /* iterate through all nodes */
1959  for( i = 0; i < nnodes; i++ )
1960  {
1961  if( !g->mark[i] )
1962  continue;
1963  /* traverse neighbours */
1964  e = g->outbeg[i];
1965  while( e != EAT_LAST )
1966  {
1967 
1968  enext = g->oeat[e];
1969  i2 = g->head[e];
1970 
1971  assert(g->mark[i2]);
1972 
1973  /* start limited dijkstra from i, marking all reached vertices */
1974  sdpaths(scip, g, pathtail, g->cost, g->cost[e], heap, statetail, memlbltail, &nlbltail, i, i2, limit);
1975 
1976  /* start limited dijkstra from i2, marking all reached vertices */
1977  sdpaths(scip, g, pathhead, costrev, g->cost[e], heap, statehead, memlblhead, &nlblhead, i2, i, limit);
1978 
1979  sdist = FARAWAY;
1980 #if 0
1981  if( statetail[i2] != UNKNOWN )
1982  {
1983  sdist = pathtail[i2].dist;
1984  assert(SCIPisGT(scip, FARAWAY, sdist));
1985  }
1986  if( statehead[i] != UNKNOWN && SCIPisGT(scip, sdist, pathhead[i].dist) )
1987  {
1988  sdist = pathhead[i].dist;
1989  assert(SCIPisGT(scip, FARAWAY, sdist));
1990  }
1991 #endif
1992  /* get restore state and path of tail and head */
1993  for( k = 0; k < nlbltail; k++ )
1994  {
1995  l = memlbltail[k];
1996  assert(g->mark[l]);
1997  assert(statetail[l] != UNKNOWN);
1998  if( statehead[l] != UNKNOWN )
1999  {
2000  assert(SCIPisGT(scip, FARAWAY, pathtail[l].dist));
2001  assert(SCIPisGT(scip, FARAWAY, pathhead[l].dist));
2002 
2003  if( SCIPisGT(scip, sdist, pathhead[l].dist + pathtail[l].dist) )
2004  sdist = pathhead[l].dist + pathtail[l].dist;
2005  }
2006 
2007  statetail[l] = UNKNOWN;
2008  pathtail[l].dist = FARAWAY;
2009  pathtail[l].edge = UNKNOWN;
2010  }
2011  /* restore state and path of tail and head */
2012  for( k = 0; k < nlblhead; k++ )
2013  {
2014  l = memlblhead[k];
2015  statehead[l] = UNKNOWN;
2016  pathhead[l].dist = FARAWAY;
2017  pathhead[l].edge = UNKNOWN;
2018  }
2019 
2020 #if 1
2021  for( k = 0; k < nnodes; k++ )
2022  {
2023  assert(statetail[k] == UNKNOWN);
2024  assert(pathtail[k].dist == FARAWAY);
2025  assert(pathtail[k].edge == UNKNOWN);
2026  assert(statehead[k] == UNKNOWN);
2027  assert(pathhead[k].dist == FARAWAY);
2028  assert(pathhead[k].edge == UNKNOWN);
2029  }
2030 #endif
2031  /* can edge be deleted? */
2032  if( SCIPisGE(scip, g->cost[e], sdist) )
2033  {
2034 
2035  if( SCIPisGE(scip, costrev[e], FARAWAY) )
2036  printf("ELIM edge \n");
2037  else
2038  printf("counteredge \n");
2039 
2040  if( SCIPisGE(scip, costrev[e], FARAWAY) )
2041  graph_edge_del(scip, g, e, TRUE);
2042  else
2043  g->cost[e] = FARAWAY;
2044  (*nelims)++;
2045  }
2046 
2047  e = enext;
2048  }
2049  }
2050 
2051  SCIPfreeBufferArray(scip, &costrev);
2052 
2053  return SCIP_OKAY;
2054 }
2055 
2056 
2057 /** SD test using only limited dijkstra from both endpoints of an edge */
2058 SCIP_RETCODE sdsp_reduction(
2059  SCIP* scip,
2060  GRAPH* g,
2061  PATH* pathtail,
2062  PATH* pathhead,
2063  int* heap,
2064  int* statetail,
2065  int* statehead,
2066  int* memlbltail,
2067  int* memlblhead,
2068  int* nelims,
2069  int limit
2070  )
2071 {
2072  SCIP_Real dist;
2073  SCIP_Real sdist;
2074  int i;
2075  int k;
2076  int l;
2077  int e;
2078  int i2;
2079  int enext;
2080  int nnodes;
2081  int nlbltail;
2082  int nlblhead;
2083  SCIP_Bool pc;
2084 
2085  assert(g != NULL);
2086  assert(scip != NULL);
2087  assert(pathtail != NULL);
2088  assert(pathhead != NULL);
2089  assert(heap != NULL);
2090  assert(statetail != NULL);
2091  assert(statehead != NULL);
2092  assert(memlbltail != NULL);
2093  assert(memlblhead != NULL);
2094  assert(nelims != NULL);
2095 
2096  nnodes = g->knots;
2097  *nelims = 0;
2099 
2100  if( !pc )
2101  for( i = 0; i < nnodes; i++ )
2102  g->mark[i] = (g->grad[i] > 0);
2103 
2104  for( i = 0; i < nnodes; i++ )
2105  {
2106  statetail[i] = UNKNOWN;
2107  pathtail[i].dist = FARAWAY;
2108  pathtail[i].edge = UNKNOWN;
2109  statehead[i] = UNKNOWN;
2110  pathhead[i].dist = FARAWAY;
2111  pathhead[i].edge = UNKNOWN;
2112  }
2113 
2114  /* iterate through all nodes */
2115  for( i = 0; i < nnodes; i++ )
2116  {
2117  if( !g->mark[i] )
2118  continue;
2119 
2120  /* traverse neighbours */
2121  e = g->outbeg[i];
2122  while( e != EAT_LAST )
2123  {
2124  enext = g->oeat[e];
2125  i2 = g->head[e];
2126 
2127  /* avoid double checking */
2128  if( i2 < i || !g->mark[i2] )
2129  {
2130  e = enext;
2131  continue;
2132  }
2133 
2134  /* start limited dijkstra from i, marking all reached vertices */
2135  sdpaths(scip, g, pathtail, g->cost, g->cost[e], heap, statetail, memlbltail, &nlbltail, i, i2, limit);
2136 
2137  /* start limited dijkstra from i2, marking all reached vertices */
2138  sdpaths(scip, g, pathhead, g->cost, g->cost[e], heap, statehead, memlblhead, &nlblhead, i2, i, limit);
2139 
2140  sdist = FARAWAY;
2141 #if 0
2142  if( statetail[i2] != UNKNOWN )
2143  {
2144  sdist = pathtail[i2].dist;
2145  assert(SCIPisGT(scip, FARAWAY, sdist));
2146  }
2147  if( statehead[i] != UNKNOWN && SCIPisGT(scip, sdist, pathhead[i].dist) )
2148  {
2149  sdist = pathhead[i].dist;
2150  assert(SCIPisGT(scip, FARAWAY, sdist));
2151  }
2152 #endif
2153  /* get restore state and path of tail and head */
2154  for( k = 0; k < nlbltail; k++ )
2155  {
2156  l = memlbltail[k];
2157  assert(g->mark[l]);
2158  assert(statetail[l] != UNKNOWN);
2159  if( statehead[l] != UNKNOWN )
2160  {
2161  assert(SCIPisGT(scip, FARAWAY, pathtail[l].dist));
2162  assert(SCIPisGT(scip, FARAWAY, pathhead[l].dist));
2163  if( Is_term(g->term[l]) )
2164  {
2165  dist = 0.0;
2166  if( SCIPisLT(scip, dist, pathhead[l].dist) )
2167  dist = pathhead[l].dist;
2168  if( SCIPisLT(scip, dist, pathtail[l].dist) )
2169  dist = pathtail[l].dist;
2170  if( pc && SCIPisLT(scip, dist, pathhead[l].dist + pathtail[l].dist - g->prize[l]) )
2171  dist = pathhead[l].dist + pathtail[l].dist - g->prize[l];
2172  if( SCIPisGT(scip, sdist, dist) )
2173  sdist = dist;
2174  }
2175  else
2176  {
2177  if( SCIPisGT(scip, sdist, pathhead[l].dist + pathtail[l].dist) )
2178  sdist = pathhead[l].dist + pathtail[l].dist;
2179  }
2180  }
2181 
2182  statetail[l] = UNKNOWN;
2183  pathtail[l].dist = FARAWAY;
2184  pathtail[l].edge = UNKNOWN;
2185  }
2186  /* restore state and path of tail and head */
2187  for( k = 0; k < nlblhead; k++ )
2188  {
2189  l = memlblhead[k];
2190  statehead[l] = UNKNOWN;
2191  pathhead[l].dist = FARAWAY;
2192  pathhead[l].edge = UNKNOWN;
2193  }
2194 
2195 #if 1
2196  for( k = 0; k < nnodes; k++ )
2197  {
2198  assert(statetail[k] == UNKNOWN);
2199  assert(pathtail[k].dist == FARAWAY);
2200  assert(pathtail[k].edge == UNKNOWN);
2201  assert(statehead[k] == UNKNOWN);
2202  assert(pathhead[k].dist == FARAWAY);
2203  assert(pathhead[k].edge == UNKNOWN);
2204  }
2205 #endif
2206  /* can edge be deleted? */
2207  if( SCIPisGE(scip, g->cost[e], sdist) )
2208  {
2209  graph_edge_del(scip, g, e, TRUE);
2210  (*nelims)++;
2211  }
2212 
2213  e = enext;
2214  }
2215  }
2216  return SCIP_OKAY;
2217 }
2218 
2219 /* C. W. Duin and A. Volganant
2220  *
2221  * "An Edge Elimination Test for the Steiner Problem in Graphs"
2222  *
2223  * Operations Research Letters 8, (1989), 79-83
2224  *
2225  * Special Distance Test
2226  */
2227 SCIP_RETCODE sd_reduction(
2228  SCIP* scip,
2229  GRAPH* g,
2230  SCIP_Real* sddist,
2231  SCIP_Real* sdtrans,
2232  SCIP_Real* sdrand,
2233  SCIP_Real* cost,
2234  SCIP_Real* randarr,
2235  int* heap,
2236  int* state,
2237  int* knotexamined,
2238  int* elimins,
2239  int runnum,
2240  unsigned int* seed
2241  )
2242 {
2243  SCIP_Real redstarttime;
2244  SCIP_Real timelimit;
2245  SCIP_Real stalltime;
2246  int count = 0;
2247  int i;
2248  int e;
2249  int j;
2250  int nnodes;
2251  int knotoffset = 0;
2252 
2253  SCIPdebugMessage("SD-Reduktion: ");
2254 
2255  assert(g != NULL);
2256  assert(scip != NULL);
2257  assert(heap != NULL);
2258  assert(state != NULL);
2259  assert(sddist != NULL);
2260  assert(sdtrans != NULL);
2261  assert(cost != NULL);
2262  assert(knotexamined != NULL);
2263 
2264  nnodes = g->knots;
2265  *elimins = 0;
2266  redstarttime = SCIPgetTotalTime(scip);
2267  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
2268  stalltime = timelimit * 0.1; /* @todo this should be set as a parameter */
2269 
2270  for( i = 0; i < nnodes; i++ )
2271  {
2272  g->mark[i] = (g->grad[i] > 0);
2273  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
2274  {
2275  randarr[e] = SCIPgetRandomReal(0.0, (g->cost[e]), seed);/* @todo: org (double)(rand() % 512); */
2276  cost[e] = g->cost[e] * 1.0 + randarr[e];
2277  }
2278  }
2279 
2280  /* this is the offset used to minimise the number of knots to examine in large graphs. */
2281  if( nnodes > KNOTLIMIT )
2282  {
2283  srand(((unsigned int)runnum * 100));
2284  i = 0;
2285  do
2286  {
2287  knotoffset = rand() % KNOTFREQ;
2288  i++;
2289  } while( nnodes > KNOTLIMIT && knotexamined[knotoffset] >= 0 && i < 50 );
2290  knotexamined[knotoffset]++;
2291  }
2292 
2293 
2294  for( i = 0; i < nnodes; i++ )
2295  {
2296  if( i % 100 == 0 && *elimins == 0 && SCIPgetTotalTime(scip) - redstarttime > stalltime)
2297  break;
2298 
2299  if( !g->mark[i] || g->grad[i] == 0 )
2300  continue;
2301 
2302  if( nnodes > KNOTLIMIT && i % KNOTFREQ != knotoffset )
2303  continue;
2304 
2305 #if 0
2306  /* For the prize collecting variants all edges from the "dummy" root node must be retained. */
2308  || g->stp_type == STP_MAX_NODE_WEIGHT) && i == g->source[0] )
2309  continue;
2310 #endif
2311 
2312  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
2313  {
2314  assert(g->mark[g->head[e]] == 1);
2315  g->mark[g->head[e]] = 2;
2316  }
2317 
2318  compute_sd(scip, g, i, cost, randarr, heap, state, &count, sddist, sdtrans, sdrand);
2319 
2320  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
2321  {
2322  assert(g->mark[g->head[e]] == 2);
2323  g->mark[g->head[e]] = 1;
2324  }
2325 
2326  for( e = g->outbeg[i]; e != EAT_LAST; e = j )
2327  {
2328  assert(g->tail[e] == i);
2329 
2330  j = g->oeat[e];
2331 
2332  if( SCIPisLT(scip, g->cost[e], FARAWAY) && SCIPisLT(scip, sddist[g->head[e]], cost[e])
2333  && SCIPisLT(scip, sddist[g->head[e]] - sdrand[g->head[e]], cost[e] - randarr[e]) )
2334  {
2335  graph_edge_del(scip, g, e, TRUE);
2336  (*elimins)++;
2337  }
2338  }
2339  }
2340 
2341  assert(graph_valid(g));
2342 
2343  SCIPdebugMessage("%d Edges deleted\n", *elimins * 2);
2344  return SCIP_OKAY;
2345 }
2346 
2347 #if 0
2348 /* C. W. Duin and A. Volganant
2349  *
2350  * "An Edge Elimination Test for the Steiner Problem in Graphs"
2351  *
2352  * Operations Research Letters 8, (1989), 79-83
2353  *
2354  * Special Distance Test for directed graphs
2355  */
2356 SCIP_RETCODE sd_reduction_dir(
2357  SCIP* scip,
2358  GRAPH* g,
2359  double** sd_indist,
2360  double** sd_intran,
2361  double** sd_outdist,
2362  double** sd_outtran,
2363  double* cost,
2364  int* heap,
2365  int* state,
2366  int* outterms,
2367  int* elimins
2368  )
2369 {
2370  int* sourceadj;
2371  int outtermcount = 0;
2372  int count = 0;
2373  int i;
2374  int e;
2375  int j;
2376  int k;
2377  int l;
2378  double tempsd;
2379  double specialdist;
2380 
2381  assert(sd_indist != NULL);
2382  assert(sd_intran != NULL);
2383  assert(sd_outdist != NULL);
2384  assert(sd_outtran != NULL);
2385  assert(cost != NULL);
2386  assert(heap != NULL);
2387  assert(state != NULL);
2388  assert(elimins != NULL);
2389 
2390 
2391  SCIPdebugMessage("SD-Reduktion: ");
2392  fflush(stdout);
2393 
2394  assert(outterms != NULL);
2395 
2396  sourceadj = malloc((size_t)g->knots * sizeof(int));
2397 
2398  for(i = 0; i < g->knots; i++)
2399  {
2400  assert(sd_indist[i] != NULL);
2401  assert(sd_intran[i] != NULL);
2402  assert(sd_outdist[i] != NULL);
2403  assert(sd_outtran[i] != NULL);
2404 
2405  if( Is_term(g->term[i]) )
2406  {
2407  for(e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e])
2408  {
2409  if( Is_term(g->term[i]) && LT(g->cost[e], FARAWAY) )
2410  {
2411  outterms[outtermcount] = i;
2412  outtermcount++;
2413 
2414  break;
2415  }
2416  }
2417  }
2418  g->mark[i] = (g->grad[i] > 0);
2419  sourceadj[i] = -1;
2420  }
2421 
2422  /* getting the knots that are adjacent to the source */
2423  for( e = g->outbeg[g->source[0]]; e != EAT_LAST; e = g->oeat[e] )
2424  {
2425  l = g->head[e];
2426  sourceadj[l] = l;
2427  }
2428 
2429  for(i = 0; i < g->edges; i++)
2430  cost[i] = g->cost[i] * 1000.0 + (double)(rand() % 512);
2431 
2432  for( i = 0; i < outtermcount; i++ )
2433  {
2434  compute_sd_dir(g, outterms[i], cost, heap, state, &count, sd_indist[i], sd_intran[i], TRUE);
2435  compute_sd_dir(g, outterms[i], cost, heap, state, &count, sd_outdist[i], sd_outtran[i], FALSE);
2436  }
2437 
2438  for(i = 0; i < g->knots; i++)
2439  {
2440  if (!(i % 100))
2441  {
2442  SCIPdebug(fputc('.', stdout));
2443  SCIPdebug(fflush(stdout));
2444  }
2445 
2446  if (g->grad[i] == 0)
2447  continue;
2448 
2449  /* For the prize collecting variants all edges from the "dummy" root node must be retained. */
2450  if ( (g->stp_type == STP_PRIZE_COLLECTING || g->stp_type == STP_MAX_NODE_WEIGHT) && i == g->source[0] )
2451  continue;
2452 
2453  /* for the hop constrained problems we only want to examine the nodes adjacent to the source. */
2454  if( g->stp_type == STP_HOP_CONS && sourceadj[i] < 0 )
2455  continue;
2456 
2457 
2458  for(e = g->outbeg[i]; e != EAT_LAST; e = j)
2459  {
2460  assert(g->tail[e] == i);
2461  l = g->head[e];
2462 
2463  j = g->oeat[e];
2464 
2465  if ( (g->stp_type == STP_PRIZE_COLLECTING || g->stp_type == STP_MAX_NODE_WEIGHT) && l == g->source[0] )
2466  continue;
2467 
2468  /* for the hop constrained problems we only want to examine the nodes adjacent to the source. */
2469  if( g->stp_type == STP_HOP_CONS && sourceadj[l] < 0 )
2470  continue;
2471 
2472  specialdist = FARAWAY;
2473  for( k = 0; k < outtermcount; k++ )
2474  {
2475  assert(l >= 0 && l < g->knots);
2476  tempsd = FARAWAY;
2477  if( outterms[k] == g->source[0] )
2478  {
2479  if( (LT(sd_indist[k][i], FARAWAY) || LT(sd_outdist[k][i], FARAWAY)) && LT(sd_outdist[k][l], FARAWAY) )
2480  {
2481  if( !LT(sd_indist[k][i], FARAWAY) )
2482  tempsd = sd_outdist[k][i];
2483  else if( !LT(sd_outdist[k][i], FARAWAY) )
2484  tempsd = sd_indist[k][i];
2485  else if( GT(sd_indist[k][i], sd_outdist[k][i]) )
2486  tempsd = sd_indist[k][i];
2487  else
2488  tempsd = sd_outdist[k][i];
2489 
2490 
2491  if( GT(sd_outdist[k][l], tempsd) )
2492  tempsd = sd_outdist[k][l];
2493  }
2494  }
2495  else
2496  {
2497  if( LT(sd_indist[k][i], FARAWAY) && LT(sd_outdist[k][l], FARAWAY) )
2498  {
2499  tempsd = sd_indist[k][i];
2500 
2501  if( GT(sd_outdist[k][l], tempsd) )
2502  tempsd = sd_outdist[k][l];
2503  }
2504  }
2505 
2506  if( LT(tempsd, specialdist) )
2507  specialdist = tempsd;
2508  }
2509 
2510  if (LT(cost[e], FARAWAY) && LT(specialdist, cost[e]))
2511  {
2512  if( LT(g->cost[Edge_anti(e)], FARAWAY) )
2513  {
2514  g->cost[e] = FARAWAY;
2515  cost[e] = FARAWAY;
2516  }
2517  else
2518  graph_edge_del(scip, g, e, TRUE);
2519 
2520  (*elimins)++;
2521 
2522  }
2523  }
2524  }
2525 
2526  assert(graph_valid(g));
2527 
2528  SCIPdebugMessage("%d Edges deleted\n", *elimins * 2);
2529 
2530  free(sourceadj);
2531 
2532  return SCIP_OKAY;
2533 }
2534 #endif
2535 
2536 
2537 
2538 SCIP_RETCODE bdr_reduction(
2539  SCIP* scip, /**< SCIP data structure */
2540  GRAPH* g, /**< graph structure */
2541  GRAPH* netgraph, /**< auxiliary graph structure */
2542  PATH* netmst, /**< MST structure */
2543  PATH* vnoi, /**< path structure */
2544  SCIP_Real* mstsdist, /**< MST distance in aux-graph */
2545  SCIP_Real* termdist1, /**< dist array */
2546  SCIP_Real* termdist2, /**< second dist array */
2547  int* vbase, /**< bases for nearest terminals */
2548  int* nodesid, /**< nodes identification array */
2549  int* neighbterms1, /**< neighbour terminals array */
2550  int* neighbterms2, /**< second neighbour terminals array */
2551  int* nelims /**< number of eliminations */
2552  )
2553 {
2554  GRAPH* auxg;
2555  PATH* mst;
2556  IDX** ancestors;
2557  IDX** revancestors;
2558  SCIP_Real csum;
2559  SCIP_Real mstcost;
2560  SCIP_Real* sd;
2561  SCIP_Real* ecost;
2562  int i;
2563  int k;
2564  int e;
2565  int l;
2566  int k2;
2567  int tail;
2568  int head;
2569  int nnodes;
2570  int* adjvert;
2571  int* incedge;
2572  int* reinsert;
2573  SCIP_Bool pc;
2574 
2575  assert(g != NULL);
2576  assert(netgraph != NULL);
2577  assert(netmst != NULL);
2578 
2579  /* initialize mst struct and new graph for bd4, bd5 tests */
2580  SCIP_CALL( SCIPallocBufferArray(scip, &mst, 5) );
2581  SCIP_CALL( graph_init(scip, &auxg, 5, 40, 1, 0) );
2582 
2583  for( k = 0; k < 4; k++ )
2584  graph_knot_add(auxg, -1);
2585  for( k = 0; k < 4; k++ )
2586  for( k2 = k + 1; k2 < 4; k2++ )
2587  graph_edge_add(scip, auxg, k, k2, 1.0, 1.0);
2588 
2589  /* init graph for mst computation */
2590  SCIP_CALL( graph_path_init(scip, auxg) );
2591 
2592  /* allocate buffer memory */
2593  SCIP_CALL( SCIPallocBufferArray(scip, &sd, 4) );
2594  SCIP_CALL( SCIPallocBufferArray(scip, &ancestors, 4) );
2595  SCIP_CALL( SCIPallocBufferArray(scip, &revancestors, 4) );
2596  SCIP_CALL( SCIPallocBufferArray(scip, &ecost, 4) );
2597  SCIP_CALL( SCIPallocBufferArray(scip, &adjvert, 4) );
2598  SCIP_CALL( SCIPallocBufferArray(scip, &reinsert, 4) );
2599  SCIP_CALL( SCIPallocBufferArray(scip, &incedge, 4) );
2600 
2601  SCIPdebugMessage("BD3-R Reduction: ");
2602 
2603  nnodes = g->knots;
2605 
2606  for( i = 0; i < 4; i++ )
2607  {
2608  sd[i] = 0.0;
2609  ancestors[i] = NULL;
2610  revancestors[i] = NULL;
2611  }
2612  if( !pc )
2613  for( i = 0; i < nnodes; i++ )
2614  g->mark[i] = (g->grad[i] > 0);
2615 
2616  for( i = 0; i < nnodes; i++ )
2617  {
2618  if( Is_term(g->term[i]) || (g->grad[i] != 3 && g->grad[i] != 4) )
2619  continue;
2620 
2621  k = 0;
2622  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
2623  {
2624  incedge[k] = e;
2625  ecost[k] = g->cost[e];
2626  adjvert[k++] = g->head[e];
2627  assert(k <= 4);
2628  }
2629 
2630  /* vertex of degree 3? */
2631  if( g->grad[i] == 3 )
2632  {
2633  assert(k == 3);
2634 
2635  csum = ecost[0] + ecost[1] + ecost[2];
2636 
2637  sd[0] = getRSD(scip, g, netgraph, netmst, vnoi, mstsdist, termdist1, termdist2, vbase, nodesid, neighbterms1, neighbterms2, adjvert[0], adjvert[1], 300);
2638  sd[1] = getRSD(scip, g, netgraph, netmst, vnoi, mstsdist, termdist1, termdist2, vbase, nodesid, neighbterms1, neighbterms2, adjvert[1], adjvert[2], 300);
2639  sd[2] = getRSD(scip, g, netgraph, netmst, vnoi, mstsdist, termdist1, termdist2, vbase, nodesid, neighbterms1, neighbterms2, adjvert[2], adjvert[0], 300);
2640 
2641  if( SCIPisLE(scip, sd[0] + sd[1], csum) || SCIPisLE(scip, sd[0] + sd[2], csum) || SCIPisLE(scip, sd[1] + sd[2], csum) )
2642  {
2643  SCIPdebugMessage("BD3-R Reduction: %f %f %f csum: %f\n ", sd[0], sd[1], sd[2], csum);
2644  (*nelims)++;
2645  /* save ancestors */
2646  for( k = 0; k < 3; k++ )
2647  {
2648  SCIPintListNodeFree(scip, &(ancestors[k]));
2649  SCIPintListNodeFree(scip, &(revancestors[k]));
2650  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(ancestors[k]), g->ancestors[incedge[k]]) );
2651  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(revancestors[k]), g->ancestors[Edge_anti(incedge[k])]) );
2652  }
2653 
2654  for( k = 0; k < 3; k++ )
2655  {
2656  k2 = (k + 1) % 3;
2657 
2658  if( SCIPisLT(scip, sd[k], ecost[k] + ecost[k2]) )
2659  {
2660  graph_edge_del(scip, g, incedge[k], TRUE);
2661  }
2662  else
2663  SCIP_CALL( graph_edge_reinsert(scip, g, incedge[k], adjvert[k], adjvert[k2], ecost[k] + ecost[k2], ancestors[k], ancestors[k2], revancestors[k], revancestors[k2]) );
2664  }
2665 
2666  assert(g->grad[i] == 0);
2667  }
2668  }
2669  /* vertex of degree 4? */
2670  else if( g->grad[i] == 4 )
2671  {
2672  assert(k == 4);
2673 
2674  for( k = 0; k < 4; k++ )
2675  {
2676  auxg->mark[k] = TRUE;
2677  for( e = auxg->outbeg[k]; e != EAT_LAST; e = auxg->oeat[e] )
2678  {
2679  k2 = auxg->head[e];
2680  if( k2 > k )
2681  {
2682  auxg->cost[e] = getRSD(scip, g, netgraph, netmst, vnoi, mstsdist, termdist1, termdist2, vbase, nodesid, neighbterms1, neighbterms2, adjvert[k], adjvert[k2], 200);
2683  auxg->cost[flipedge(e)] = auxg->cost[e];
2684  }
2685  }
2686  }
2687 
2688  for( l = 0; l < 4; l++ )
2689  mst[l].dist = UNKNOWN;
2690  /* compute mst on all neighbours */
2691  graph_path_exec(scip, auxg, MST_MODE, 0, auxg->cost, mst);
2692  mstcost = 0.0;
2693  for( l = 1; l < 4; l++ )
2694  assert(mst[l].dist != UNKNOWN);
2695  for( l = 1; l < 4; l++ )
2696  mstcost += mst[l].dist;
2697 
2698  k = UNKNOWN;
2699  csum = ecost[0] + ecost[1] + ecost[2] + ecost[3];
2700 
2701  if( SCIPisGE(scip, csum, mstcost) )
2702  {
2703  /* compute mst on all 3-subsets of all neigbours */
2704  for( k = 0; k < 4; k++ )
2705  {
2706  auxg->mark[k] = FALSE;
2707  mstcost = 0.0;
2708 
2709  if( k != 0 )
2710  {
2711  graph_path_exec(scip, auxg, MST_MODE, 0, auxg->cost, mst);
2712  for( l = 1; l < 4; l++ )
2713  if( auxg->mark[l] )
2714  mstcost += mst[l].dist;
2715  }
2716  else
2717  {
2718  graph_path_exec(scip, auxg, MST_MODE, 1, auxg->cost, mst);
2719  for( l = 2; l < 4; l++ )
2720  mstcost += mst[l].dist;
2721  }
2722 
2723  auxg->mark[k] = TRUE;
2724  csum -= ecost[k];
2725 
2726  if( SCIPisLT(scip, csum, mstcost) )
2727  break;
2728 
2729  csum += ecost[k];
2730  }
2731  }
2732 
2733  if( k == 4 )
2734  {
2735  l = 0;
2736  for( k = 0; k < 4; k++ )
2737  {
2738  for( e = auxg->outbeg[k]; e != EAT_LAST; e = auxg->oeat[e] )
2739  {
2740  k2 = auxg->head[e];
2741  if( k2 > k )
2742  {
2743  if( SCIPisGE(scip, auxg->cost[e], ecost[k] + ecost[k2]) )
2744  {
2745  if( l >= 4 )
2746  break;
2747  reinsert[l++] = e;
2748  }
2749  }
2750  }
2751  }
2752 
2753  if( k == 4 )
2754  {
2755  (*nelims) += g->grad[i] - l;
2756 
2757  /* save ancestors */
2758  for( k = 0; k < 4; k++ )
2759  {
2760  SCIPintListNodeFree(scip, &(ancestors[k]));
2761  SCIPintListNodeFree(scip, &(revancestors[k]));
2762  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(ancestors[k]), g->ancestors[incedge[k]]) );
2763  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(revancestors[k]), g->ancestors[Edge_anti(incedge[k])]) );
2764  }
2765 
2766  for( k = 0; k < l; k++ )
2767  {
2768  e = reinsert[k];
2769  tail = auxg->tail[e];
2770  head = auxg->head[e];
2771  SCIP_CALL( graph_edge_reinsert(scip, g, incedge[k], adjvert[tail], adjvert[head], ecost[tail] + ecost[head], ancestors[tail], ancestors[head], revancestors[tail], revancestors[head]) );
2772  }
2773 
2774  /* delete remaining edges */
2775  while( g->outbeg[i] >= 0 )
2776  graph_edge_del(scip, g, g->outbeg[i], TRUE);
2777  }
2778  assert(g->grad[i] == 0);
2779  }
2780 
2781  }
2782  }
2783 
2784  for( k = 0; k < 4; k++ )
2785  {
2786  SCIPintListNodeFree(scip, &(ancestors[k]));
2787  SCIPintListNodeFree(scip, &(revancestors[k]));
2788  }
2789 
2790  /* free memory */
2791  SCIPfreeBufferArray(scip, &incedge);
2792  SCIPfreeBufferArray(scip, &reinsert);
2793  SCIPfreeBufferArray(scip, &adjvert);
2794  SCIPfreeBufferArray(scip, &ecost);
2795  SCIPfreeBufferArray(scip, &revancestors);
2796  SCIPfreeBufferArray(scip, &ancestors);
2797  SCIPfreeBufferArray(scip, &sd);
2798 
2799  graph_path_exit(scip, auxg);
2800  graph_free(scip, auxg, TRUE);
2801  SCIPfreeBufferArray(scip, &mst);
2802 
2803  return SCIP_OKAY;
2804 }
2805 
2806 
2807 
2808 
2809 /* C. W. Duin and A. Volganant
2810  *
2811  * "Reduction Tests for the Steiner Problem in Graphs"
2812  *
2813  * Networks, Volume 19 (1989), 549-567
2814  *
2815  * Bottleneck Degree 3,4 Test
2816  */
2817 SCIP_RETCODE bd3_reduction(
2818  SCIP* scip,
2819  GRAPH* g,
2820  PATH* pathtail,
2821  PATH* pathhead,
2822  int* heap,
2823  int* statetail,
2824  int* statehead,
2825  int* memlbltail,
2826  int* memlblhead,
2827  int* nelims,
2828  int limit
2829  )
2830 {
2831  GRAPH* auxg;
2832  PATH* mst;
2833  IDX** ancestors;
2834  IDX** revancestors;
2835  SCIP_Real s1;
2836  SCIP_Real csum;
2837  SCIP_Real mstcost;
2838  SCIP_Real* sd;
2839  SCIP_Real* ecost;
2840  int i;
2841  int k;
2842  int e;
2843  int l;
2844  int k2;
2845  int tail;
2846  int head;
2847  int nnodes;
2848  int* adjvert;
2849  int* incedge;
2850  int* reinsert;
2851 
2852  SCIP_Bool pc;
2853 
2854  SCIPdebugMessage("BD3-Reduction: ");
2855 
2856  assert(g != NULL);
2857  assert(heap != NULL);
2858  assert(nelims != NULL);
2859 
2860  /* initialize mst struct and new graph for bd4, bd5 tests */
2861  SCIP_CALL( SCIPallocBufferArray(scip, &mst, 5) );
2862  SCIP_CALL( graph_init(scip, &auxg, 5, 40, 1, 0) );
2863 
2864  for( k = 0; k < 4; k++ )
2865  graph_knot_add(auxg, -1);
2866  for( k = 0; k < 4; k++ )
2867  for( k2 = k + 1; k2 < 4; k2++ )
2868  graph_edge_add(scip, auxg, k, k2, 1.0, 1.0);
2869 
2870  /* init graph for mst computation */
2871  SCIP_CALL( graph_path_init(scip, auxg) );
2872 
2873  /* allocate buffer memory */
2874  SCIP_CALL( SCIPallocBufferArray(scip, &sd, 4) );
2875  SCIP_CALL( SCIPallocBufferArray(scip, &ancestors, 4) );
2876  SCIP_CALL( SCIPallocBufferArray(scip, &revancestors, 4) );
2877  SCIP_CALL( SCIPallocBufferArray(scip, &ecost, 4) );
2878  SCIP_CALL( SCIPallocBufferArray(scip, &adjvert, 4) );
2879  SCIP_CALL( SCIPallocBufferArray(scip, &reinsert, 4) );
2880  SCIP_CALL( SCIPallocBufferArray(scip, &incedge, 4) );
2881 
2882  *nelims = 0;
2883  nnodes = g->knots;
2885 
2886  for( i = 0; i < 4; i++ )
2887  {
2888  sd[i] = 0.0;
2889  ancestors[i] = NULL;
2890  revancestors[i] = NULL;
2891  }
2892  if( !pc )
2893  for( i = 0; i < nnodes; i++ )
2894  g->mark[i] = (g->grad[i] > 0);
2895  for( i = 0; i < nnodes; i++ )
2896  {
2897  statetail[i] = UNKNOWN;
2898  pathtail[i].dist = FARAWAY;
2899  pathtail[i].edge = UNKNOWN;
2900  statehead[i] = UNKNOWN;
2901  pathhead[i].dist = FARAWAY;
2902  pathhead[i].edge = UNKNOWN;
2903  }
2904 
2905  for( i = 0; i < nnodes; i++ )
2906  {
2907  if( Is_term(g->term[i]) || (g->grad[i] != 3 && g->grad[i] != 4) )
2908  continue;
2909 
2910  k = 0;
2911  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
2912  {
2913  incedge[k] = e;
2914  ecost[k] = g->cost[e];
2915  adjvert[k++] = g->head[e];
2916  assert(k <= 4);
2917  }
2918 
2919  /* vertex of degree 3? */
2920  if( g->grad[i] == 3 )
2921  {
2922  assert(k == 3);
2923 
2924  csum = ecost[0] + ecost[1] + ecost[2];
2925 
2926  SCIP_CALL( getSD(scip, g, pathtail, pathhead, &(sd[0]), csum, heap, statetail, statehead, memlbltail, memlblhead, adjvert[0], adjvert[1], limit, pc, FALSE) );
2927  SCIP_CALL( getSD(scip, g, pathtail, pathhead, &(sd[1]), csum, heap, statetail, statehead, memlbltail, memlblhead, adjvert[1], adjvert[2], limit, pc, FALSE) );
2928  SCIP_CALL( getSD(scip, g, pathtail, pathhead, &(sd[2]), csum, heap, statetail, statehead, memlbltail, memlblhead, adjvert[2], adjvert[0], limit, pc, FALSE) );
2929 
2930  if( SCIPisLE(scip, sd[0] + sd[1], csum) || SCIPisLE(scip, sd[0] + sd[2], csum) || SCIPisLE(scip, sd[1] + sd[2], csum) )
2931  {
2932  (*nelims)++;
2933 
2934  /* save ancestors */
2935  for( k = 0; k < 3; k++ )
2936  {
2937  SCIPintListNodeFree(scip, &(ancestors[k]));
2938  SCIPintListNodeFree(scip, &(revancestors[k]));
2939  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(ancestors[k]), g->ancestors[incedge[k]]) );
2940  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(revancestors[k]), g->ancestors[Edge_anti(incedge[k])]) );
2941  }
2942 
2943  for( k = 0; k < 3; k++ )
2944  {
2945  k2 = (k + 1) % 3;
2946 
2947  if( SCIPisLT(scip, sd[k], ecost[k] + ecost[k2]) )
2948  {
2949  graph_edge_del(scip, g, incedge[k], TRUE);
2950  }
2951  else
2952  SCIP_CALL( graph_edge_reinsert(scip, g, incedge[k], adjvert[k], adjvert[k2], ecost[k] + ecost[k2], ancestors[k], ancestors[k2], revancestors[k], revancestors[k2]) );
2953  }
2954 #if 0
2955  if( SCIPisLE(scip, s1, ecost[0] + ecost[1]) )
2956  graph_edge_del(scip, g, incedge[0], TRUE);
2957  else
2958  SCIP_CALL( graph_edge_reinsert(scip, g, incedge[0], adjvert[0], adjvert[1], ecost[0] + ecost[1], ancestors[0], ancestors[1], revancestors[0], revancestors[1]) );
2959 
2960  if( SCIPisLE(scip, s2, ecost[1] + ecost[2]) )
2961  graph_edge_del(scip, g, incedge[1], TRUE);
2962  else
2963  SCIP_CALL( graph_edge_reinsert(scip, g, incedge[1], adjvert[1], adjvert[2], ecost[1] + ecost[2], ancestors[1], ancestors[2], revancestors[1], revancestors[2]) );
2964 
2965  if( SCIPisLE(scip, s3, ecost[0] + ecost[2]) )
2966  graph_edge_del(scip, g, incedge[2], TRUE);
2967  else
2968  SCIP_CALL( graph_edge_reinsert(scip, g, incedge[2], adjvert[2], adjvert[0], ecost[2] + ecost[0], ancestors[2], ancestors[0], revancestors[2], revancestors[0]) );
2969 #endif
2970 #if 0
2971  {
2972  n1 = graph_edge_redirect(g, incedge[2], adjvert[2], adjvert[0], ecost[2] + ecost[0]);
2973  if( n1 >= 0 )
2974  {
2975  SCIPintListNodeFree(scip, &(g->ancestors[n1]));
2976  SCIPintListNodeFree(scip, &(g->ancestors[Edge_anti(n1)]));
2977  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(g->ancestors[n1]), revancestors[2]) );
2978  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(g->ancestors[n1]), ancestors[0]) );
2979 
2980  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(g->ancestors[Edge_anti(n1)]), ancestors[2]) );
2981  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(g->ancestors[Edge_anti(n1)]), revancestors[0]) );
2982  }
2983  }
2984 #endif
2985  assert(g->grad[i] == 0);
2986  }
2987 
2988  }
2989  /* vertex of degree 4? */
2990  else if( g->grad[i] == 4 )
2991  {
2992  assert(k == 4);
2993  csum = ecost[0] + ecost[1] + ecost[2] + ecost[3];
2994 
2995  for( k = 0; k < 4; k++ )
2996  {
2997  auxg->mark[k] = TRUE;
2998  for( e = auxg->outbeg[k]; e != EAT_LAST; e = auxg->oeat[e] )
2999  {
3000  k2 = auxg->head[e];
3001  if( k2 > k )
3002  {
3003  SCIP_CALL( getSD(scip, g, pathtail, pathhead, &(s1), csum, heap, statetail, statehead, memlbltail, memlblhead, adjvert[k], adjvert[k2], limit, pc, FALSE) );
3004  auxg->cost[e] = s1;
3005  auxg->cost[flipedge(e)] = s1;
3006  }
3007  }
3008  }
3009 
3010  for( l = 0; l < 4; l++ )
3011  mst[l].dist = UNKNOWN;
3012  /* compute mst on all neighbours */
3013  graph_path_exec(scip, auxg, MST_MODE, 0, auxg->cost, mst);
3014  mstcost = 0.0;
3015  for( l = 1; l < 4; l++ )
3016  assert(mst[l].dist != UNKNOWN);
3017  for( l = 1; l < 4; l++ )
3018  mstcost += mst[l].dist;
3019 
3020  k = UNKNOWN;
3021  if( SCIPisGE(scip, csum, mstcost) )
3022  {
3023  /* compute mst on all 3-subsets of all neigbours */
3024  for( k = 0; k < 4; k++ )
3025  {
3026  auxg->mark[k] = FALSE;
3027  mstcost = 0.0;
3028 
3029  if( k != 0 )
3030  {
3031  graph_path_exec(scip, auxg, MST_MODE, 0, auxg->cost, mst);
3032  for( l = 1; l < 4; l++ )
3033  if( auxg->mark[l] )
3034  mstcost += mst[l].dist;
3035  }
3036  else
3037  {
3038  graph_path_exec(scip, auxg, MST_MODE, 1, auxg->cost, mst);
3039  for( l = 2; l < 4; l++ )
3040  mstcost += mst[l].dist;
3041  }
3042 
3043  auxg->mark[k] = TRUE;
3044  csum -= ecost[k];
3045 
3046  if( SCIPisLT(scip, csum, mstcost) )
3047  break;
3048 
3049  csum += ecost[k];
3050  }
3051  }
3052 
3053  if( k == 4 )
3054  {
3055  l = 0;
3056  for( k = 0; k < 4; k++ )
3057  {
3058  for( e = auxg->outbeg[k]; e != EAT_LAST; e = auxg->oeat[e] )
3059  {
3060  k2 = auxg->head[e];
3061  if( k2 > k )
3062  {
3063  if( SCIPisGE(scip, auxg->cost[e], ecost[k] + ecost[k2]) )
3064  {
3065  if( l >= 4 )
3066  break;
3067 
3068  reinsert[l++] = e;
3069  }
3070  }
3071  }
3072  }
3073 
3074  if( k == 4 )
3075  {
3076  SCIPdebugMessage("npv4Reduction delete: %d\n", i);
3077  (*nelims) += g->grad[i] - l;
3078 
3079  /* save ancestors */
3080  for( k = 0; k < 4; k++ )
3081  {
3082  SCIPintListNodeFree(scip, &(ancestors[k]));
3083  SCIPintListNodeFree(scip, &(revancestors[k]));
3084  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(ancestors[k]), g->ancestors[incedge[k]]) );
3085  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(revancestors[k]), g->ancestors[Edge_anti(incedge[k])]) );
3086  }
3087 
3088  for( k = 0; k < l; k++ )
3089  {
3090  e = reinsert[k];
3091  tail = auxg->tail[e];
3092  head = auxg->head[e];
3093  SCIP_CALL( graph_edge_reinsert(scip, g, incedge[k], adjvert[tail], adjvert[head], ecost[tail] + ecost[head], ancestors[tail], ancestors[head], revancestors[tail], revancestors[head]) );
3094  }
3095 
3096  /* delete remaining edges */
3097  while( g->outbeg[i] >= 0 )
3098  graph_edge_del(scip, g, g->outbeg[i], TRUE);
3099  }
3100  assert(g->grad[i] == 0);
3101  }
3102 
3103  }
3104  }
3105 
3106  for( k = 0; k < 4; k++ )
3107  {
3108  SCIPintListNodeFree(scip, &(ancestors[k]));
3109  SCIPintListNodeFree(scip, &(revancestors[k]));
3110  }
3111 
3112  /* free memory */
3113  SCIPfreeBufferArray(scip, &incedge);
3114  SCIPfreeBufferArray(scip, &reinsert);
3115  SCIPfreeBufferArray(scip, &adjvert);
3116  SCIPfreeBufferArray(scip, &ecost);
3117  SCIPfreeBufferArray(scip, &revancestors);
3118  SCIPfreeBufferArray(scip, &ancestors);
3119  SCIPfreeBufferArray(scip, &sd);
3120 
3121  graph_path_exit(scip, auxg);
3122  graph_free(scip, auxg, TRUE);
3123  SCIPfreeBufferArray(scip, &mst);
3124 
3125  SCIPdebugMessage("bd3: %d Knots deleted\n", *nelims);
3126 
3127  return SCIP_OKAY;
3128 }
3129 
3130 #if 0
3131 inline static double mst_cost(
3132  const GRAPH* g,
3133  const PATH* mst)
3134 {
3135  double cost = 0;
3136  int i;
3137  int e;
3138 
3139  for(i = 0; i < g->knots; i++)
3140  if ((e = mst[i].edge) >= 0)
3141  cost += g->cost[e];
3142 
3143  return(cost);
3144 }
3145 
3146 /* C. W. Duin and A. Volganant
3147  *
3148  * "Reduction Tests for the Steiner Problem in Graphs"
3149  *
3150  * Networks, Volume 19 (1989), 549-567
3151  *
3152  * Nearest Special Vertex 3 Test
3153  */
3154 SCIP_RETCODE nsv_reduction(
3155  SCIP* scip,
3156  GRAPH* g,
3157  double* cost,
3158  double* fixed,
3159  int* nelims
3160  )
3161 {
3162  SCIP_Real redstarttime;
3163  SCIP_Real timelimit;
3164  SCIP_Real stalltime;
3165  PATH** path;
3166  PATH* mst1;
3167  PATH* mst2;
3168  int i;
3169  int e;
3170  int k;
3171  int j;
3172  double min1;
3173  double min2;
3174  double cost1;
3175  double cost2;
3176 
3177  SCIPdebugMessage("NSV-Reduction: ");
3178  fflush(stdout);
3179  /*
3180  graph_show(g);
3181  */
3182  *nelims = 0;
3183 
3184  path = malloc((size_t)g->knots * sizeof(PATH*));
3185 
3186  assert(path != NULL);
3187 
3188  mst1 = malloc((size_t)g->knots * sizeof(PATH));
3189  mst2 = malloc((size_t)g->knots * sizeof(PATH));
3190 
3191  assert(mst1 != NULL);
3192  assert(mst2 != NULL);
3193  assert(cost != NULL);
3194 
3195  redstarttime = SCIPgetTotalTime(scip);
3196  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
3197  stalltime = timelimit*0.1; /* this should be set as a parameter */
3198 
3199  /* Check this cost setting. It may need to be changed for the directed case.
3200  */
3201  for(i = 0; i < g->edges; i++)
3202  cost[i] = g->cost[i];
3203 
3204  for(i = 0; i < g->knots; i++)
3205  {
3206  g->mark[i] = (g->grad[i] > 0);
3207  path[i] = NULL;
3208  }
3209 
3210  calculate_distances(scip, g, path, g->cost, FSP_MODE);
3211 
3212  for(i = 0; i < g->knots; i++)
3213  {
3214  if( i % 100 == 0 && SCIPgetTotalTime(scip) > timelimit )
3215  break;
3216 
3217  if( i % 100 == 0 && (*nelims) == 0 && SCIPgetTotalTime(scip) - redstarttime > stalltime)
3218  break;
3219 
3220  if (!(i % 100))
3221  {
3222  SCIPdebug(fputc('.', stdout));
3223  SCIPdebug(fflush(stdout));
3224  }
3225  if (g->grad[i] < 3)
3226  continue;
3227 
3228  graph_path_exec(scip, g, MST_MODE, i, g->cost, mst1);
3229 
3230  cost1 = mst_cost(g, mst1);
3231 
3232  for(e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e])
3233  {
3234  assert(g->tail[e] == i);
3235 
3236  if (mst1[g->head[e]].edge == e)
3237  break;
3238  }
3239  assert(e != EAT_LAST);
3240 
3241  cost[e] = FARAWAY - 1.0;
3242  cost[Edge_anti(e)] = FARAWAY - 1.0;
3243 
3244  graph_path_exec(scip, g, MST_MODE, i, cost, mst2);
3245 
3246  cost2 = mst_cost(g, mst2);
3247 
3248  cost[e] = g->cost[e];
3249  cost[Edge_anti(e)] = g->cost[Edge_anti(e)];
3250 
3251  assert(GE(cost2, cost1));
3252 
3253  if (LE(cost2 - cost1, 2.0))
3254  {
3255  /*
3256  SCIPdebugMessage("\t\te=%d i=%d k=%d cost1=%d cost2=%d\n",
3257  e, i, g->head[e], cost1, cost2);
3258  */
3259  continue;
3260  }
3261  k = g->head[e];
3262  min1 = FARAWAY;
3263  min2 = FARAWAY;
3264 
3265  for(j = 0; j < g->knots; j++)
3266  {
3267  if (!Is_term(g->term[j]) || (g->grad[j] == 0))
3268  continue;
3269 
3270  assert(path[j] != NULL);
3271 
3272  if (LT(path[j][i].dist, min1) && LT(path[j][i].dist, path[j][k].dist))
3273  min1 = path[j][i].dist;
3274 
3275  if (LT(path[j][k].dist, min2) && LT(path[j][k].dist, path[j][i].dist))
3276  min2 = path[j][k].dist;
3277  }
3278  if (EQ(min1, FARAWAY) || EQ(min2, FARAWAY))
3279  {
3280  /*
3281  SCIPdebugMessage("\te=%d i=%d k=%d min1=%d min2=%d cost1=%d cost2=%d\n",
3282  e, i, k, min1, min2, cost1, cost2);
3283  */
3284  continue;
3285  }
3286  if (LT(cost1 + min1 + min2, cost2))
3287  {
3288  /*
3289  SCIPdebugMessage("e=%d i=%d k=%d min1=%d min2=%d cost1=%d cost2=%d\n",
3290  e, i, k, min1, min2, cost1, cost2);
3291  */
3292  *fixed += g->cost[e];
3293  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(g->fixedges), g->ancestors[e]) );
3294  SCIP_CALL( graph_knot_contract(scip, g, i, k) );
3295 
3296  (*nelims)++;
3297 
3298  calculate_distances(scip, g, path, g->cost, FSP_MODE);
3299 
3300  for(j = 0; j < g->edges; j++)
3301  cost[j] = g->cost[j];
3302  }
3303  }
3304  for(i = 0; i < g->knots; i++)
3305  {
3306  if (path[i] != NULL)
3307  {
3308  assert(Is_term(g->term[i]));
3309 
3310  free(path[i]);
3311  }
3312  }
3313  free(mst1);
3314  free(mst2);
3315  free(path);
3316 
3317  assert(graph_valid(g));
3318 
3319  SCIPdebugMessage(" %d Knots deleted\n", *nelims);
3320  /*printf("nsv_reduction: %d Knots deleted\n", elimins);*/
3321 
3322  return SCIP_OKAY;
3323 }
3324 #endif
3325 
3326 
3327 #if 0
3328 /* C. W. Duin and A. Volganant
3329  *
3330  * "Reduction Tests for the Steiner Problem in Graphs"
3331  *
3332  * Networks, Volume 19 (1989), 549-567
3333  *
3334  * Nearest Special Vertex 3 Test
3335  *
3336  * Taken from:
3337  *
3338  * Maculan et. al.
3339  *
3340  * "An approach for the Steiner problem in directed graphs"
3341  *
3342  * Annals of Operations Research, Volume 33 (1991), 471-480
3343  *
3344  * Nearest Vertex Test (for optimal arcs)
3345  *
3346  * and
3347  *
3348  * T. Polzin
3349  *
3350  * "Algorithms for the Steiner problem in networks"
3351  *
3352  * Section 3.3.3 pp. 54-55
3353  *
3354  * This is only called for the directed Steiner tree problem
3355  */
3356 SCIP_RETCODE nv_reduction_optimal(
3357  SCIP* scip,
3358  GRAPH* g,
3359  double* fixed,
3360  int* elimins,
3361  int runnum)
3362 {
3363  PATH** path;
3364  PATH* pathfromterm;
3365  PATH* pathfromsource;
3366  PATH* pathhops;
3367  double* distance;
3368  double* radius;
3369  double* hopscost;
3370  int* vregion;
3371  int* heap;
3372  int* state;
3373  int* pred;
3374  int* minArc1;
3375  int* minArc2;
3376  int* terms;
3377  int termcount;
3378  int i;
3379  int j;
3380  int e;
3381  double min1;
3382  double min2;
3383  int minhops;
3384  int shortarc;
3385  int shortarctail;
3386  char antiedgeexists;
3387  int knotoffset;
3388 
3389  SCIPdebugMessage("NSV-Reduction: ");
3390  fflush(stdout);
3391  /*
3392  graph_show(g);
3393  */
3394  path = malloc((size_t)g->knots * sizeof(PATH*));
3395 
3396  assert(path != NULL);
3397 
3398  pathfromterm = malloc((size_t)g->knots * sizeof(PATH));
3399  pathfromsource = malloc((size_t)g->knots * sizeof(PATH));
3400 
3401  assert(pathfromterm != NULL);
3402  assert(pathfromsource != NULL);
3403 
3404  pathhops = malloc((size_t)g->knots * sizeof(PATH));
3405 
3406  assert(pathhops != NULL);
3407 
3408  distance = malloc((size_t)g->knots * sizeof(double));
3409  radius = malloc((size_t)g->knots * sizeof(double));
3410 
3411  assert(distance != NULL);
3412  assert(radius != NULL);
3413 
3414  hopscost = malloc((size_t)g->edges * sizeof(double));
3415 
3416  assert(hopscost != NULL);
3417 
3418  vregion = malloc((size_t)g->knots * sizeof(int));
3419 
3420  assert(vregion != NULL);
3421 
3422  heap = malloc((size_t)g->knots * sizeof(int));
3423  state = malloc((size_t)g->knots * sizeof(int));
3424 
3425  assert(heap != NULL);
3426  assert(state != NULL);
3427 
3428  *elimins = 0;
3429  pred = malloc((size_t)g->edges * sizeof(int));
3430  minArc1 = malloc((size_t)g->knots * sizeof(int));
3431  minArc2 = malloc((size_t)g->knots * sizeof(int));
3432  terms = malloc((size_t)g->terms * sizeof(int));
3433 
3434  termcount = 0;
3435  for(i = 0; i < g->knots; i++)
3436  {
3437  if( Is_term(g->term[i]) )
3438  {
3439  terms[termcount] = i;
3440  termcount++;
3441  }
3442  g->mark[i] = (g->grad[i] > 0);
3443  minArc1[i] = -1;
3444  minArc2[i] = -1;
3445  path[i] = NULL;
3446 
3447  for(e = g->inpbeg[i]; e != EAT_LAST; e = g->ieat[e])
3448  {
3449  if( LT(g->cost[e], FARAWAY) )
3450  hopscost[e] = 1;
3451  else
3452  hopscost[e] = FARAWAY;
3453 
3454  if( LT(g->cost[Edge_anti(e)], FARAWAY) )
3455  hopscost[Edge_anti(e)] = 1;
3456  else
3457  hopscost[Edge_anti(e)] = FARAWAY;
3458  }
3459  }
3460 
3461  assert(g->source[0] >= 0);
3462 
3463  /* computing the voronoi regions inward to a node */
3464  voronoi_term(g, g->cost, distance, radius, pathfromterm, vregion, heap, state, pred, 1);
3465 
3466  /* computing the shortest paths from the source node */
3467  graph_path_exec(scip, g, FSP_MODE, g->source[0], g->cost, pathfromsource);
3468 
3469  /* computing the shortest hops paths from the source node */
3470  graph_path_exec(scip, g, FSP_MODE, g->source[0], hopscost, pathhops);
3471 
3472  /* this is the offset used to minimise the number of knots to examine in large graphs. */
3473  srand(runnum*100);
3474  knotoffset = rand() % KNOTFREQ;
3475 
3476  for(i = 0; i < g->knots; i++)
3477  {
3478  /* For the prize collecting variants all edges from the "dummy" root node must be retained. */
3479  if ((g->stp_type == STP_PRIZE_COLLECTING || g->stp_type == STP_MAX_NODE_WEIGHT) && i == g->source[0] )
3480  continue;
3481 
3482  if( g->stp_type == STP_DIRECTED && i != g->source[0] )
3483  continue;
3484 
3485 
3486  if( g->knots > KNOTLIMIT && i % KNOTFREQ != knotoffset )
3487  continue;
3488 
3489  if (Is_term(g->term[i]) && g->grad[i] >= 3)
3490  {
3491 
3492  min1 = FARAWAY;
3493  min2 = FARAWAY;
3494  minhops = g->hoplimit;
3495  shortarctail = -1;
3496  shortarc = -1;
3497  antiedgeexists = FALSE;
3498  for(e = g->inpbeg[i]; e != EAT_LAST; e = g->ieat[e])
3499  {
3500  if( g->stp_type == STP_DIRECTED && i == g->source[0] )
3501  {
3502  if( LT(g->cost[e], FARAWAY) )
3503  {
3504  g->cost[e] = FARAWAY;
3505  (*elimins)++;
3506  }
3507 
3508  continue;
3509  }
3510 
3511  if (g->cost[e] < min1)
3512  {
3513  shortarc = e;
3514  shortarctail = g->tail[e];
3515 
3516  min2 = min1;
3517  min1 = g->cost[e];
3518  }
3519 
3520  if( LT(pathfromsource[g->tail[e]].hops, minhops) )
3521  minhops = pathfromsource[g->tail[e]].hops;
3522 
3523  if( LT(g->cost[Edge_anti(e)], FARAWAY) )
3524  antiedgeexists = TRUE;
3525 
3526  }
3527 
3528  if( g->stp_type == STP_DIRECTED )
3529  continue;
3530 
3531  if (LT(min1, FARAWAY) && LE(pathfromsource[shortarctail].dist + min1, min2))
3532  {
3533  assert(shortarc >= 0);
3534  assert(shortarctail >= 0);
3535 
3537  || g->stp_type == STP_DIRECTED) && shortarctail == g->source[0] )
3538  continue;
3539 
3540  if( g->stp_type == STP_HOP_CONS && GT(pathfromsource[shortarctail].hops, pathhops[i].dist - 1) )
3541  continue;
3542 
3543  if( antiedgeexists == TRUE )
3544  {
3545  if( LT(min2, FARAWAY) )
3546  {
3547  for(e = g->inpbeg[i]; e != EAT_LAST; e = j)
3548  {
3549  j = g->ieat[e];
3550 
3551  if( e != shortarc )
3552  {
3553  if( LT(g->cost[Edge_anti(e)], FARAWAY) )
3554  g->cost[e] = FARAWAY;
3555  else
3556  graph_edge_del(scip, g, e, TRUE);
3557  }
3558  }
3559  (*elimins)++;
3560  }
3561  }
3562  else
3563  {
3564  *fixed += min1;
3565  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(g->fixedges), g->ancestors[shortarc]) ); /* I think that this should be
3566  shortarc instead of shortarctail */
3567  SCIP_CALL( graph_knot_contract(scip, g, i, shortarctail) );
3568 
3569  if( g->stp_type == STP_HOP_CONS )
3570  {
3571  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
3572  g->cost[e] = FARAWAY;
3573  }
3574 
3575  (*elimins)++;
3576  }
3577 
3578  /* computing the shortest paths from the source node */
3579  graph_path_exec(scip, g, FSP_MODE, g->source[0], g->cost, pathfromsource);
3580  }
3581  }
3582  /* The knot is not a terminal so we can perform the short link test */
3583 #if 0
3584  else
3585  {
3586  for(e = g->inpbeg[i]; e != EAT_LAST; e = g->ieat[e])
3587  {
3588  j = g->tail[e];
3589  if( vregion[i] != vregion[j] )
3590  {
3591  if( minArc1[vregion[i]] < 0 )
3592  minArc1[vregion[i]] = e;
3593  else if( g->cost[e] < g->cost[minArc1[vregion[i]]] )
3594  {
3595  minArc2[vregion[i]] = minArc1[vregion[i]];
3596  minArc1[vregion[i]] = e;
3597  }
3598  }
3599  }
3600  }
3601 #endif
3602  }
3603 
3604 #if 0
3605  for( k = 0; k < termcount; k++ )
3606  {
3607  assert(terms[k] >= 0 && terms[k] < g->knots);
3608 
3609  if( minArc1[terms[k]] >= 0 && minArc2[terms[k]] >= 0 && pathfromsource[g->tail[minArc1[terms[k]]]].dist
3610  + g->cost[minArc1[terms[k]]] + pathfromterm[g->head[minArc1[terms[k]]]].dist < g->cost[minArc2[terms[k]]] )
3611  {
3612  e = minArc1[terms[k]];
3613  i = g->head[e];
3614  j = g->tail[e];
3615 
3616  if ((g->stp_type == STP_PRIZE_COLLECTING || g->stp_type == STP_MAX_NODE_WEIGHT) && (i == g->source[0] || j == g->source[0]) )
3617  continue;
3618 
3619 
3620  if( Is_term(g->term[i]) )
3621  {
3623  *fixed += g->cost[e];
3624  }
3625  graph_knot_contract(g, j, i);
3626 
3627 
3628  elimins++;
3629  }
3630  }
3631 #endif
3632 
3633  free(terms);
3634  free(minArc2);
3635  free(minArc1);
3636  free(pred);
3637  free(state);
3638  free(heap);
3639  free(hopscost);
3640  free(radius);
3641  free(distance);
3642  free(vregion);
3643  free(pathhops);
3644  free(pathfromsource);
3645  free(pathfromterm);
3646  free(path);
3647 
3648  assert(graph_valid(g));
3649  SCIPdebugMessage(" %d Knots deleted\n", *elimins);
3650 
3651  return SCIP_OKAY;
3652 }
3653 
3654 #endif
3655 /* shortest link reduction */
3656 SCIP_RETCODE sl_reduction(
3657  SCIP* scip,
3658  GRAPH* g,
3659  PATH* vnoi,
3660  double* fixed,
3661  int* heap,
3662  int* state,
3663  int* vbase,
3664  int* vrnodes,
3665  char* visited,
3666  int* nelims
3667  )
3668 {
3669  SCIP_QUEUE* queue;
3670  SCIP_Real cost;
3671  SCIP_Real mincost2;
3672  SCIP_Real mincost3;
3673  int i;
3674  int k;
3675  int e;
3676  int j;
3677  int t;
3678 #if 0
3679  int e2;
3680 #endif
3681  int old;
3682  int head;
3683  int tail;
3684  int root;
3685  int nnodes;
3686  int vrcount;
3687  int minedge;
3688 #if 0
3689  int minedge2;
3690 #endif
3691  int* qnode;
3692  char contract;
3693  char* forbidden;
3694  SCIP_Bool pc;
3695 
3696  assert(g != NULL);
3697  assert(vnoi != NULL);
3698  assert(heap != NULL);
3699  assert(state != NULL);
3700  assert(vbase != NULL);
3701  assert(vrnodes != NULL);
3702  assert(visited != NULL);
3703 
3704  *nelims = 0;
3705  nnodes = g->knots;
3706  root = g->source[0];
3708 
3709  SCIP_CALL( SCIPallocBufferArray(scip, &forbidden, nnodes) );
3710 
3711  if( !pc )
3712  for( i = 0; i < nnodes; i++ )
3713  g->mark[i] = (g->grad[i] > 0);
3714 
3715  voronoi_terms(scip, g, g->cost, vnoi, vbase, heap, state);
3716 
3717  SCIP_CALL( SCIPqueueCreate(&queue, nnodes, 2.0) );
3718  for( j = 0; j < nnodes; j++ )
3719  {
3720  forbidden[j] = FALSE;
3721  visited[j] = FALSE;
3722  }
3723  for( i = 0; i < nnodes; i++ )
3724  {
3725  /* is i terminal and not disabled? */
3726  if( Is_term(g->term[i]) && g->mark[i] && !forbidden[i] )
3727  {
3728  /* traverse voronoi-region of (terminal) i */
3729  assert(SCIPqueueIsEmpty(queue));
3730  t = i;
3731  SCIP_CALL( SCIPqueueInsert(queue, &t) );
3732  vrcount = 1;
3733  vrnodes[0] = i;
3734  visited[i] = TRUE;
3735  minedge = UNKNOWN;
3736 #if 0
3737  minedge2 = UNKNOWN;
3738 #endif
3739  mincost2 = FARAWAY;
3740  mincost3 = FARAWAY;
3741 
3742  while( !SCIPqueueIsEmpty(queue) )
3743  {
3744  qnode = (SCIPqueueRemove(queue));
3745  /* traverse all adjacent edges */
3746  for( e = g->outbeg[*qnode]; e != EAT_LAST; e = g->oeat[e] )
3747  {
3748  j = g->head[e];
3749 
3750  if( !g->mark[j] )
3751  continue;
3752 
3753  k = vbase[j];
3754  assert(k != UNKNOWN);
3755  if( !visited[j] && k == i )
3756  {
3757  visited[j] = TRUE;
3758  vrnodes[vrcount++] = j;
3759  SCIP_CALL( SCIPqueueInsert(queue, &(g->head[e])) );
3760  }
3761  else if( k != i )
3762  /* update shortest and second shortest edge (cost) leaving the voronoi region */
3763  {
3764  cost = g->cost[e];
3765  if( minedge == UNKNOWN )
3766  {
3767  minedge = e;
3768  }
3769  else if( SCIPisLE(scip, cost, g->cost[minedge]) )
3770  {
3771  mincost3 = mincost2;
3772  mincost2 = g->cost[minedge];
3773 #if 0
3774  minedge2 = minedge;
3775 #endif
3776  minedge = e;
3777  }
3778  else if( SCIPisLE(scip, cost, mincost2) )
3779  {
3780 #if 0
3781  minedge2 = e;
3782 #endif
3783  mincost3 = mincost2;
3784  mincost2 = g->cost[e];
3785  }
3786  else if( SCIPisLT(scip, cost, mincost3) )
3787  {
3788  mincost3 = g->cost[e];
3789  }
3790  }
3791  }
3792  }
3793  for( j = 0; j < vrcount; j++ )
3794  visited[vrnodes[j]] = FALSE;
3795  if( minedge == UNKNOWN )
3796  continue;
3797  e = minedge;
3798  tail = g->tail[e];
3799  head = g->head[e];
3800  assert(vbase[tail] == i);
3801 
3802  contract = FALSE;
3803  cost = vnoi[tail].dist + g->cost[e] + vnoi[head].dist;
3804  if( SCIPisGE(scip, mincost2, cost) )
3805  {
3806  contract = TRUE;
3807  }
3808  /* @todo fix */
3809 #if 0
3810  else if( minedge2 != UNKNOWN && !Is_term(g->term[g->head[minedge2]]) && SCIPisGE(scip, mincost3, cost) )
3811  {
3812  t = g->head[minedge2];
3813  for( e2 = g->outbeg[t]; e2 != EAT_LAST; e2 = g->oeat[e2] )
3814  if( e2 != flipedge(minedge2) && SCIPisLT(scip, g->cost[e2], cost) && vbase[g->head[e2]] != i )
3815  break;
3816 
3817  if( e2 == EAT_LAST )
3818  contract = TRUE;
3819  if( contract )
3820  printf("sladv \n");
3821 
3822  }
3823 #endif
3824 
3825  /* check whether minedge can be removed */
3826  if( contract )
3827  {
3828  if( pc )
3829  {
3830  if( root != vbase[head] && !SCIPisLE(scip, g->cost[e] + vnoi[tail].dist + vnoi[head].dist, g->prize[vbase[head]]) )
3831  continue;
3832  if( i == tail )
3833  {
3834  if( root != i && !SCIPisLE(scip, vnoi[tail].dist + g->cost[e], g->prize[i]) )
3835  continue;
3836  }
3837  else
3838  {
3839  if( root != i && !SCIPisLT(scip, vnoi[tail].dist + g->cost[e], g->prize[i]) )
3840  continue;
3841  }
3842  if( Is_term(g->term[head]) && Is_term(g->term[tail]) )
3843  continue;
3844  }
3845 
3846 
3847 
3848  *fixed += g->cost[e];
3849  assert(g->mark[tail] && g->mark[head]);
3850  assert(!Is_pterm(g->term[tail]) && !Is_pterm(g->term[head]));
3851 
3852  if( Is_term(g->term[head]) )
3853  {
3854  j = head;
3855  k = tail;
3856  }
3857  else
3858  {
3859  j = tail;
3860  k = head;
3861  }
3862 
3863  old = g->grad[j] + g->grad[k] - 1;
3864 
3865  if( pc )
3866  {
3867  SCIP_CALL( graph_knot_contractpc(scip, g, j, k, i) );
3868  }
3869  else
3870  {
3871  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(g->fixedges), g->ancestors[e]) );
3872  SCIP_CALL( graph_knot_contract(scip, g, j, k) );
3873  }
3874 
3875  assert(old - g->grad[j] - g->grad[k] > 0);
3876  (*nelims) += old - g->grad[j] - g->grad[k];
3877  forbidden[vbase[j]] = TRUE;
3878  forbidden[vbase[k]] = TRUE;
3879  }
3880  }
3881  }
3882 
3883  /* free memory */
3884  SCIPqueueFree(&queue);
3885  SCIPfreeBufferArray(scip, &forbidden);
3886 
3887  return SCIP_OKAY;
3888 }
3889 
3890 
3891 /* NV reduction from T. Polzin's "Algorithms for the Steiner problem in networks" */
3892 SCIP_RETCODE nv_reduction(
3893  SCIP* scip,
3894  GRAPH* g,
3895  PATH* vnoi,
3896  double* fixed,
3897  int* edgearrint,
3898  int* heap,
3899  int* state,
3900  int* vbase,
3901  int* nelims
3902  )
3903 {
3904  SCIP_Real* distance;
3905  SCIP_Real min1;
3906  SCIP_Real min2;
3907  SCIP_Real pi;
3908  SCIP_Real pt;
3909  SCIP_Real ttdist;
3910  int* term;
3911  int* minedge1;
3912  int* distnode;
3913  int i;
3914  int l;
3915  int k;
3916  int e;
3917  int t;
3918  int old;
3919  int edge1;
3920  int nnodes;
3921  int nterms;
3922  int mingrad;
3923  int termcount;
3924  SCIP_Bool pc;
3925  assert(g != NULL);
3926  assert(vnoi != NULL);
3927  assert(heap != NULL);
3928  assert(state != NULL);
3929  assert(vbase != NULL);
3930 
3931  t = 0;
3932  termcount = 0;
3933  *nelims = 0;
3934  pi = 0;
3935  pt = 0;
3936 
3937  nnodes = g->knots;
3938  nterms = g->terms;
3940  SCIP_CALL( SCIPallocBufferArray(scip, &term, nterms) );
3941  SCIP_CALL( SCIPallocBufferArray(scip, &minedge1, nterms) );
3942  SCIP_CALL( SCIPallocBufferArray(scip, &distance, nnodes) );
3943 
3944  /* minimal grad of a vertex to be scrutinized */
3945  if( pc )
3946  {
3948  mingrad = 3;
3949  else
3950  mingrad = 4;
3951 
3952  SCIP_CALL( SCIPallocBufferArray(scip, &distnode, nnodes) );
3953  }
3954  else
3955  {
3956  mingrad = 2;
3957  distnode = NULL;
3958  for( i = 0; i < nnodes; i++ )
3959  g->mark[i] = (g->grad[i] > 0);
3960  }
3961 
3962  for( i = 0; i < nnodes; i++ )
3963  {
3964  if( Is_term(g->term[i]) && g->mark[i] && g->grad[i] > 0 )
3965  {
3966  /* compute shortest incident edge */
3967  edge1 = UNKNOWN;
3968  if( g->grad[i] >= 1 )
3969  {
3970  min1 = FARAWAY;
3971 
3972  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
3973  {
3974  if( !g->mark[g->head[e]] )
3975  continue;
3976  if( SCIPisLE(scip, g->cost[e], min1) )
3977  {
3978  edge1 = e;
3979  min1 = g->cost[e];
3980  }
3981  }
3982  }
3983  minedge1[termcount] = edge1;
3984  term[termcount++] = i;
3985  }
3986  }
3987 
3988  /* compute Voronoi regions and distances */
3989  SCIP_CALL( voronoi_dist(scip, g, g->cost, distance, edgearrint, vbase, minedge1, heap, state, distnode, vnoi) );
3990 
3991  for( l = 0; l < termcount; l++ )
3992  {
3993  /* get l'th terminal */
3994  i = term[l];
3995 
3996  if( g->grad[i] < mingrad )
3997  continue;
3998 
3999  assert(minedge1[l] != UNKNOWN);
4000  /* get shortest two edges */
4001  edge1 = UNKNOWN;
4002  min2 = FARAWAY;
4003  min1 = FARAWAY;
4004  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
4005  {
4006  if( !g->mark[g->head[e]] )
4007  continue;
4008  if( SCIPisLE(scip, g->cost[e], min1) )
4009  {
4010  edge1 = e;
4011  min2 = min1;
4012  min1 = g->cost[e];
4013  }
4014  else if( SCIPisLE(scip, g->cost[e], min2) )
4015  {
4016  min2 = g->cost[e];
4017  }
4018  }
4019 
4020  assert(edge1 != UNKNOWN);
4021  assert(i == g->tail[edge1]);
4022  k = g->head[edge1];
4023 
4024  /* covered in degree test */
4025  if( Is_term(g->term[k]) )
4026  continue;
4027 
4028  if( vbase[k] != i )
4029  {
4030  if( pc )
4031  t = vbase[k];
4032  ttdist = g->cost[edge1] + vnoi[k].dist;
4033  }
4034  else
4035  {
4036  if( distnode != NULL )
4037  t = distnode[i];
4038  ttdist = distance[i];
4039  }
4040  if( pc )
4041  {
4042  if( i != g->source[0] )
4043  pi = g->prize[i];
4044  else
4045  pi = FARAWAY;
4046 
4047  if( t != g->source[0] )
4048  pt = g->prize[t];
4049  else
4050  pt = FARAWAY;
4051  }
4052 
4053  if( SCIPisGE(scip, min2, ttdist)
4054  && (!pc || (SCIPisLE(scip, g->cost[edge1], pi) && SCIPisLE(scip, ttdist, pt))) )
4055  {
4056  old = g->grad[i] + g->grad[k] - 1;
4057  *fixed += g->cost[edge1];
4058 
4059  if( pc )
4060  {
4061  SCIP_CALL( graph_knot_contractpc(scip, g, i, k, i) );
4062  }
4063  else
4064  {
4065  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(g->fixedges), g->ancestors[edge1]) );
4066  SCIP_CALL( graph_knot_contract(scip, g, i, k) );
4067  }
4068  assert(old - g->grad[i] - g->grad[k] > 0);
4069  (*nelims) += old - g->grad[i] - g->grad[k];
4070  }
4071  }
4072 
4073  SCIPfreeBufferArrayNull(scip, &distnode);
4074  SCIPfreeBufferArray(scip, &distance);
4075  SCIPfreeBufferArray(scip, &minedge1);
4076  SCIPfreeBufferArray(scip, &term);
4077 
4078  return SCIP_OKAY;
4079 }
4080 
4081 
4082 /* advanced NV reduction */
4083 SCIP_RETCODE nv_reductionAdv(
4084  SCIP* scip,
4085  GRAPH* g,
4086  PATH* vnoi,
4087  SCIP_Real* distance,
4088  double* fixed,
4089  int* edgearrint,
4090  int* heap,
4091  int* state,
4092  int* vbase,
4093  int* neighb,
4094  int* distnode,
4095  int* nelims
4096  )
4097 {
4098  SCIP_Real min1;
4099  SCIP_Real min2;
4100  SCIP_Real min3;
4101  SCIP_Real pi;
4102  SCIP_Real pt;
4103  SCIP_Real ttdist;
4104  int* term;
4105  int* minedge1;
4106  int i;
4107  int l;
4108  int k;
4109  int e;
4110  int t;
4111  int edge1;
4112  int edge2;
4113  int nnodes;
4114  int nterms;
4115  int mingrad;
4116  int termcount;
4117  SCIP_Bool pc;
4118  SCIP_Bool contract;
4119 
4120  assert(g != NULL);
4121  assert(neighb != NULL);
4122  assert(vnoi != NULL);
4123  assert(heap != NULL);
4124  assert(state != NULL);
4125  assert(vbase != NULL);
4126 
4127  t = 0;
4128  pi = 0;
4129  pt = 0;
4131  nnodes = g->knots;
4132  nterms = g->terms;
4133  *nelims = 0;
4134  termcount = 0;
4135 
4136  /* allocate memory */
4137  SCIP_CALL( SCIPallocBufferArray(scip, &term, nterms) );
4138  SCIP_CALL( SCIPallocBufferArray(scip, &minedge1, nterms) );
4139 
4140  /* set minimal grad of a vertex to be scrutinized */
4141  if( pc )
4142  {
4144  mingrad = 3;
4145  else
4146  mingrad = 4;
4147 
4148  assert(distnode != NULL);
4149  }
4150  else
4151  {
4152  mingrad = 2;
4153  for( i = 0; i < nnodes; i++ )
4154  g->mark[i] = (g->grad[i] > 0);
4155  }
4156 
4157  /* compute shortest incident edge to each terminal */
4158  for( i = 0; i < nnodes; i++ )
4159  {
4160  neighb[i] = FALSE;
4161  if( Is_term(g->term[i]) && g->mark[i] && g->grad[i] > 0 )
4162  {
4163  /* compute shortest incident edge */
4164  edge1 = UNKNOWN;
4165  if( g->grad[i] >= 1 )
4166  {
4167  min1 = FARAWAY;
4168 
4169  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
4170  {
4171  if( g->mark[g->head[e]] && SCIPisLE(scip, g->cost[e], min1) )
4172  {
4173  edge1 = e;
4174  min1 = g->cost[e];
4175  }
4176  }
4177  }
4178 
4179  minedge1[termcount] = edge1;
4180  term[termcount++] = i;
4181  }
4182  }
4183 
4184  /* compute Voronoi regions and distances */
4185  SCIP_CALL( voronoi_dist(scip, g, g->cost, distance, edgearrint, vbase, minedge1, heap, state, distnode, vnoi) );
4186 
4187 #if 0
4188  printf("rootmarkterm?: %d \n", Is_term(g->term[g->source[0]]));
4189  printf("rootmarked?: %d \n", g->mark[g->source[0]]);
4190  printf("vbase 187?: %d \n", vbase[187]);
4191 
4192  int a;
4193  int h;
4194  int* pnode;
4195  int v = 187;
4196  SCIP_QUEUE* queue;
4197 
4198  SCIP_CALL( SCIPqueueCreate(&queue, nnodes + 1, 2.0) );
4199  for( k = 0; k < nnodes; k++ )
4200  g->mark[k] = FALSE;
4201  g->mark[v] = TRUE;
4202  SCIP_CALL( SCIPqueueInsert(queue, &(g->tail[g->outbeg[v]])) );
4203 
4204  while( !SCIPqueueIsEmpty(queue) )
4205  {
4206  pnode = (SCIPqueueRemove(queue));
4207 
4208  /* traverse incoming arcs */
4209  for( a = g->outbeg[*pnode]; a != EAT_LAST; a = g->oeat[a] )
4210  {
4211  h = g->head[a];
4212 
4213  if( !g->mark[h] && h != 0 )
4214  {
4215  printf("goto: %d->%d \n", *pnode, h);
4216  /* if an active vertex has been hit, break */
4217  if( Is_term(g->term[h]) )
4218  {
4219  printf("hit: %d \n", h);
4220  assert(0);
4221  }
4222 
4223  g->mark[h] = TRUE;
4224 
4225  SCIP_CALL( SCIPqueueInsert(queue, &(g->head[a])) );
4226  }
4227 
4228  }
4229  }
4230 
4231  assert(0);
4232 #endif
4233  /* main loop: try to contract (shortest) edges into terminals */
4234  for( l = 0; l < termcount; l++ )
4235  {
4236  /* get l'th terminal */
4237  i = term[l];
4238 
4239  if( g->grad[i] < mingrad )
4240  continue;
4241 
4242  assert(minedge1[l] != UNKNOWN);
4243 
4244  /* get shortest two edges */
4245 
4246  min3 = FARAWAY;
4247  min2 = FARAWAY;
4248  min1 = FARAWAY;
4249  edge1 = UNKNOWN;
4250  edge2 = UNKNOWN;
4251 
4252  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
4253  {
4254  if( !g->mark[g->head[e]] )
4255  continue;
4256  neighb[g->head[e]] = TRUE;
4257 
4258  if( SCIPisLE(scip, g->cost[e], min1) )
4259  {
4260  edge2 = edge1;
4261  edge1 = e;
4262 
4263  min3 = min2;
4264  min2 = min1;
4265  min1 = g->cost[e];
4266  }
4267  else if( SCIPisLE(scip, g->cost[e], min2) )
4268  {
4269  edge2 = e;
4270 
4271  min3 = min2;
4272  min2 = g->cost[e];
4273  }
4274  else if( SCIPisLE(scip, g->cost[e], min3) )
4275  {
4276  min3 = g->cost[e];
4277  }
4278  }
4279 
4280  assert(edge1 != UNKNOWN);
4281  assert(i == g->tail[edge1]);
4282 
4283  k = g->head[edge1];
4284 #if 0
4285  printf("root: %d \n", g->source[0]);
4286  printf("edge: %d->%d\n", g->tail[edge1], g->head[edge1]);
4287  printf("i: %d distance: %f \n", i, distance[0]);
4288  assert(0);
4289 #endif
4290  /* covered in degree test */
4291  if( Is_term(g->term[k]) )
4292  continue;
4293 
4294  if( vbase[k] != i )
4295  {
4296  if( pc )
4297  t = vbase[k];
4298  ttdist = g->cost[edge1] + vnoi[k].dist;
4299  }
4300  else
4301  {
4302  if( pc )
4303  {
4304  assert(distnode != NULL);
4305  t = distnode[i];
4306  }
4307  ttdist = distance[i];
4308  }
4309  if( pc )
4310  {
4311  if( i != g->source[0] )
4312  pi = g->prize[i];
4313  else
4314  pi = FARAWAY;
4315 
4316  if( t == UNKNOWN )
4317  pt = -1.0;
4318  else if( t != g->source[0] )
4319  pt = g->prize[t];
4320  else
4321  pt = FARAWAY;
4322  }
4323 
4324  contract = FALSE;
4325 
4326  if( SCIPisGE(scip, min2, ttdist) )
4327  {
4328  contract = TRUE;
4329  }
4330  else if( edge2 != UNKNOWN && !Is_term(g->term[g->head[edge2]]) && SCIPisGE(scip, min3, ttdist) )
4331  {
4332  t = g->head[edge2];
4333  for( e = g->outbeg[t]; e != EAT_LAST; e = g->oeat[e] )
4334  if( e != flipedge(edge2) && SCIPisLT(scip, g->cost[e], ttdist) )/*&& !neighb[g->head[e]] ) */
4335  break;
4336 
4337  if( e == EAT_LAST )
4338  contract = TRUE;
4339 #if 0
4340  contract = FALSE;
4341 #endif
4342  }
4343 
4344  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
4345  neighb[g->head[e]] = FALSE;
4346 
4347  if( contract && (!pc || (SCIPisLE(scip, g->cost[edge1], pi) && SCIPisLE(scip, ttdist, pt))) )
4348  {
4349  (*nelims)++;
4350  *fixed += g->cost[edge1];
4351 
4352  if( pc )
4353  {
4354  SCIP_CALL( graph_knot_contractpc(scip, g, i, k, i) );
4355  }
4356  else
4357  {
4358  SCIP_CALL( SCIPintListNodeAppendCopy(scip, &(g->fixedges), g->ancestors[edge1]) );
4359  SCIP_CALL( graph_knot_contract(scip, g, i, k) );
4360  }
4361  }
4362  }
4363 
4364  SCIPfreeBufferArray(scip, &minedge1);
4365  SCIPfreeBufferArray(scip, &term);
4366 
4367  return SCIP_OKAY;
4368 }
4369 
4370 
4371 /* longest edge reduction test from T. Polzin's "Algorithms for the Steiner problem in networks" (Lemma 20) */
4372 SCIP_RETCODE ledge_reduction(
4373  SCIP* scip,
4374  GRAPH* g,
4375  PATH* vnoi,
4376  int* heap,
4377  int* state,
4378  int* vbase,
4379  int* nelims
4380  )
4381 {
4382  GRAPH* netgraph;
4383  PATH* mst;
4384  SCIP_Real cost;
4385  SCIP_Real maxcost;
4386  int v1;
4387  int v2;
4388  int k;
4389  int e;
4390  int ne;
4391  int nedges;
4392  int nnodes;
4393  int nterms;
4394  int maxnedges;
4395  int netnnodes;
4396  int* nodesid;
4397  int* edgeorg;
4398  char* blocked;
4399 
4400  assert(g != NULL);
4401  assert(vnoi != NULL);
4402  assert(heap != NULL);
4403  assert(state != NULL);
4404  assert(vbase != NULL);
4405 
4406  *nelims = 0;
4407  nedges = g->edges;
4408  nnodes = g->knots;
4409  assert(graph_valid(g));
4410 
4411  nterms = 0;
4412  for( k = 0; k < nnodes; k++ )
4413  {
4414  g->mark[k] = (g->grad[k] > 0);
4415  if( Is_term(g->term[k]) && g->mark[k] )
4416  nterms++;
4417  }
4418 
4419  if( nterms <= 1 )
4420  return SCIP_OKAY;
4421 
4422  SCIP_CALL( SCIPallocBufferArray(scip, &blocked, nedges / 2) );
4423  SCIP_CALL( SCIPallocBufferArray(scip, &edgeorg, nedges / 2) );
4424 
4425  voronoi_terms(scip, g, g->cost, vnoi, vbase, heap, state);
4426 
4427  if( nedges >= (nterms - 1) * nterms )
4428  maxnedges = (nterms - 1) * nterms;
4429  else
4430  maxnedges = nedges;
4431 
4432  SCIP_CALL( SCIPallocBufferArray(scip, &nodesid, nnodes) );
4433 
4434  /* initialize the new graph */
4435  SCIP_CALL( graph_init(scip, &netgraph, nterms, maxnedges, 1, 0) );
4436 
4437  e = 0;
4438  for( k = 0; k < nnodes; k++ )
4439  {
4440  if( Is_term(g->term[k]) && g->grad[k] > 0 )
4441  {
4442  if( e == 0 )
4443  graph_knot_add(netgraph, 0);
4444  else
4445  graph_knot_add(netgraph, -1);
4446  nodesid[k] = e++;
4447  }
4448  else
4449  {
4450  nodesid[k] = UNKNOWN;
4451  }
4452  }
4453 
4454  netnnodes = netgraph->knots;
4455  assert(netnnodes == e);
4456  assert(netnnodes == nterms);
4457 
4458  for( e = 0; e < nedges / 2; e++ )
4459  {
4460  blocked[e] = FALSE;
4461  edgeorg[e] = UNKNOWN;
4462  }
4463 
4464  for( k = 0; k < nnodes; k++ )
4465  {
4466  for( e = g->outbeg[k]; e != EAT_LAST; e = g->oeat[e] )
4467  {
4468  v1 = vbase[k];
4469  assert(k == g->tail[e]);
4470 
4471  if( v1 != vbase[g->head[e]] )
4472  {
4473  v2 = vbase[g->head[e]];
4474  assert(Is_term(g->term[v1]));
4475  assert(Is_term(g->term[v2]));
4476  assert(nodesid[v1] >= 0);
4477  assert(nodesid[v2] >= 0);
4478 
4479  for( ne = netgraph->outbeg[nodesid[v1]]; ne != EAT_LAST; ne = netgraph->oeat[ne] )
4480  if( netgraph->head[ne] == nodesid[v2] )
4481  break;
4482 
4483  cost = g->cost[e] + vnoi[g->head[e]].dist + vnoi[g->tail[e]].dist;
4484  /* edge exists? */
4485  if( ne != EAT_LAST )
4486  {
4487  assert(ne >= 0);
4488  assert(netgraph->head[ne] == nodesid[v2]);
4489  assert(netgraph->tail[ne] == nodesid[v1]);
4490  if( SCIPisGT(scip, netgraph->cost[ne], cost) )
4491  {
4492  netgraph->cost[ne] = cost;
4493  netgraph->cost[Edge_anti(ne)] = cost;
4494  edgeorg[ne / 2] = e;
4495  assert(ne <= maxnedges);
4496  }
4497  }
4498  else
4499  {
4500  edgeorg[netgraph->edges / 2] = e;
4501  graph_edge_add(scip, netgraph, nodesid[v1], nodesid[v2], cost, cost);
4502  assert(netgraph->edges <= maxnedges);
4503  }
4504  }
4505  }
4506  }
4507  netgraph->source[0] = 0;
4508 
4509  assert(graph_valid(netgraph));
4510 
4511  for( k = 0; k < netnnodes; k++ )
4512  netgraph->mark[k] = TRUE;
4513 
4514  /* compute a MST on netgraph */
4515  SCIP_CALL( SCIPallocBufferArray(scip, &mst, netnnodes) );
4516  SCIP_CALL( graph_path_init(scip, netgraph) );
4517  graph_path_exec(scip, netgraph, MST_MODE, 0, netgraph->cost, mst);
4518 
4519  maxcost = -1;
4520  assert(mst[0].edge == -1);
4521 
4522  for( k = 1; k < netnnodes; k++ )
4523  {
4524  assert(netgraph->path_state[k] == CONNECT);
4525  e = mst[k].edge;
4526  assert(e >= 0);
4527  cost = netgraph->cost[e];
4528  if( SCIPisGT(scip, cost, maxcost) )
4529  maxcost = cost;
4530 
4531  ne = edgeorg[e / 2];
4532  blocked[ne / 2] = TRUE;
4533  for( v1 = g->head[ne]; v1 != vbase[v1]; v1 = g->tail[vnoi[v1].edge] )
4534  blocked[vnoi[v1].edge / 2] = TRUE;
4535 
4536  for( v1 = g->tail[ne]; v1 != vbase[v1]; v1 = g->tail[vnoi[v1].edge] )
4537  blocked[vnoi[v1].edge / 2] = TRUE;
4538  assert(e != EAT_LAST);
4539  }
4540 
4541  for( k = 0; k < nnodes; k++ )
4542  {
4543  e = g->outbeg[k];
4544  while( e != EAT_LAST )
4545  {
4546  assert(e >= 0);
4547  if( SCIPisGE(scip, g->cost[e], maxcost) && !blocked[e / 2] )
4548  {
4549  (*nelims)++;
4550  v1 = g->oeat[e];
4551  graph_edge_del(scip, g, e, TRUE);
4552  e = v1;
4553  }
4554  else
4555  {
4556  e = g->oeat[e];
4557  }
4558  }
4559  }
4560 
4561  /* graph might have become disconnected */
4562  if( *nelims > 0 )
4563  level0(scip, g);
4564 
4565  /* free netgraph and MST data structure */
4566  graph_path_exit(scip, netgraph);
4567  graph_free(scip, netgraph, TRUE);
4568  SCIPfreeBufferArray(scip, &mst);
4569  SCIPfreeBufferArray(scip, &nodesid);
4570  SCIPfreeBufferArray(scip, &edgeorg);
4571  SCIPfreeBufferArray(scip, &blocked);
4572 
4573  assert(graph_valid(g));
4574  return SCIP_OKAY;
4575 }
4576 
4577 
4578 /** adjacent neighbourhood reduction for the MWCSP */
4579 SCIP_RETCODE ansReduction(
4580  SCIP* scip, /**< SCIP data structure */
4581  GRAPH* g, /**< graph data structure */
4582  SCIP_Real* fixed, /**< pointer to offfset value */
4583  int* marked, /**< nodes array */
4584  int* count /**< pointer to number of reductions */
4585  )
4586 {
4587  SCIP_Real min;
4588  int k;
4589  int j;
4590  int e;
4591  int e2;
4592  int nnodes;
4593  int maxgrad;
4594 
4595  assert(scip != NULL);
4596  assert(g != NULL);
4597  assert(fixed != NULL);
4598  assert(count != NULL);
4599  assert(marked != NULL);
4600  assert(g->stp_type == STP_MAX_NODE_WEIGHT);
4601 
4602  *count = 0;
4603  nnodes = g->knots;
4604 
4605  /* unmark all nodes */
4606  for( k = 0; k < nnodes; k++ )
4607  marked[k] = FALSE;
4608 
4609  /* check neighbourhood of all nodes */
4610  for( k = 0; k < nnodes; k++ )
4611  {
4612  if( !g->mark[k] )
4613  continue;
4614 
4615  /* mark adjacent vertices and k*/
4616  for( e = g->outbeg[k]; e != EAT_LAST; e = g->oeat[e] )
4617  marked[g->head[e]] = TRUE;
4618  marked[k] = TRUE;
4619 
4620  if( SCIPisLT(scip, g->prize[k], 0.0) )
4621  min = g->prize[k];
4622  else
4623  min = 0.0;
4624 
4625  maxgrad = g->grad[k];
4626 
4627  /* check all neighbours of k */
4628  e = g->outbeg[k];
4629  while( e != EAT_LAST )
4630  {
4631 #if 0
4632  if( !g->mark[k] || k == k2 )
4633  continue;
4634  j = k2;
4635 #else
4636  j = g->head[e];
4637  e = g->oeat[e];
4638 #endif
4639  /* valid candidate? */
4640  if( g->grad[j] <= maxgrad && g->mark[j] && SCIPisLE(scip, g->prize[j], min) )
4641  {
4642  for( e2 = g->outbeg[j]; e2 != EAT_LAST; e2 = g->oeat[e2] )
4643  if( !marked[g->head[e2]] )
4644  break;
4645 
4646  /* neighbours of j subset of those of k? */
4647  if( e2 == EAT_LAST )
4648  {
4649  while( g->outbeg[j] != EAT_LAST )
4650  {
4651  e2 = g->outbeg[j];
4652  (*count)++;
4653  graph_edge_del(scip, g, e2, TRUE);
4654  }
4655  g->mark[j] = FALSE;
4656  marked[j] = FALSE;
4657  }
4658  }
4659  }
4660 
4661  for( e = g->outbeg[k]; e != EAT_LAST; e = g->oeat[e] )
4662  marked[g->head[e]] = FALSE;
4663  marked[k] = FALSE;
4664 
4665  for( j = 0; j < nnodes; j++ )
4666  assert(marked[j] == FALSE);
4667  }
4668 
4669  return SCIP_OKAY;
4670 }
4671 
4672 #if 1
4673 
4674 /** advanced connected neighbourhood subset reduction test for the MWCSP */
4675 SCIP_RETCODE cnsAdvReduction(
4676  SCIP* scip, /**< SCIP data structure */
4677  GRAPH* g, /**< graph data structure */
4678  int* marked, /**< nodes array */
4679  int* count /**< pointer to number of reductions */
4680  )
4681 {
4682  SCIP_Real min;
4683  SCIP_Real kprize;
4684  int* neighbarr;
4685  int* neighbarr2;
4686  int k;
4687  int j;
4688  int e;
4689  int k2;
4690  int e2;
4691  int l;
4692  int run;
4693  int nn;
4694  int nn2;
4695  int k2grad;
4696  int nnodes;
4697  int maxgrad;
4698 
4699  assert(scip != NULL);
4700  assert(g != NULL);
4701  assert(count != NULL);
4702  assert(marked != NULL);
4703  assert(g->stp_type == STP_MAX_NODE_WEIGHT);
4704 
4705  k2grad = 0;
4706  *count = 0;
4707  kprize = 0.0;
4708  nnodes = g->knots;
4709 
4710  SCIP_CALL( SCIPallocBufferArray(scip, &neighbarr, CNSNN + 1) );
4711  SCIP_CALL( SCIPallocBufferArray(scip, &neighbarr2, CNSNN + 1) );
4712 
4713  /* unmark all nodes */
4714  for( k = 0; k < nnodes; k++ )
4715  marked[k] = 0;
4716 
4717  /* first run: consider node plus adjacent terminals; second run: consider the same plus an additional (non-positive) vertex */
4718  for( run = 0; run < 2; run++ )
4719  {
4720  /* check neighbourhood of all nodes */
4721  for( k = 0; k < nnodes; k++ )
4722  {
4723  if( (!(g->mark[k])) || (g->grad[k] < 2) )
4724  continue;
4725 
4726  if( run == 1 && Is_term(g->term[k]) )
4727  continue;
4728  nn = 0;
4729  k2 = UNKNOWN;
4730  nn2 = 0;
4731  kprize = g->prize[k];
4732  maxgrad = g->grad[k];
4733 
4734  /* mark adjacent vertices and k */
4735  for( e = g->outbeg[k]; e != EAT_LAST; e = g->oeat[e] )
4736  {
4737  j = g->head[e];
4738 
4739  if( !g->mark[j] )
4740  continue;
4741 
4742  if( SCIPisGE(scip, g->prize[j], 0.0) && nn < CNSNN - 1 )
4743  {
4744  neighbarr[nn++] = j;
4745  marked[j] = 3;
4746  }
4747  else if( (run == 1) &&
4748  ((SCIPisGT(scip, g->prize[j], kprize) && nn2 < CNSNN) || (SCIPisGE(scip, g->prize[j], kprize) && j > k && nn2 < 3)) )
4749  {
4750  neighbarr2[nn2++] = j;
4751  marked[j] = 3;
4752  }
4753  else
4754  {
4755  marked[j] = 2;
4756  }
4757  }
4758 
4759 
4760  for( l = 0; l < nn; l++ )
4761  {
4762  for( e = g->outbeg[neighbarr[l]]; e != EAT_LAST; e = g->oeat[e] )
4763  {
4764  j = g->head[e];
4765  if( !g->mark[j] )
4766  continue;
4767  if( run == 1 && SCIPisGT(scip, g->prize[j], kprize) && nn2 < CNSNN )
4768  {
4769  neighbarr2[nn2++] = j;
4770  marked[j] = 3;
4771  }
4772  else if( marked[j] == 0 )
4773  {
4774  marked[j] = 2;
4775  }
4776  }
4777  maxgrad += g->grad[neighbarr[l]];
4778  }
4779 
4780 
4781  marked[k] = 3;
4782 
4783  if( Is_term(g->term[k]) )
4784  min = 0.0;
4785  else
4786  min = g->prize[k];
4787 
4788  for( l = 0; l < nn2 + 1 - run; l++ )
4789  {
4790  if( run == 1 )
4791  {
4792  k2 = neighbarr2[l];
4793  for( e = g->outbeg[k2]; e != EAT_LAST; e = g->oeat[e] )
4794  if( marked[g->head[e]] < 2 && g->mark[g->head[e]] )
4795  marked[g->head[e]] = 1;
4796  min += g->prize[k2];
4797  k2grad = g->grad[k2];
4798  maxgrad += k2grad;
4799  assert(SCIPisLE(scip, g->prize[k2], 0.0));
4800 
4801  }
4802 
4803  /* traverse all vertices */
4804  for( j = 0; j < nnodes; j++ )
4805  {
4806  /* vertex part of the current connected subset? Or terminal? Or belonging to the extension of the graph? */
4807  if( marked[j] == 3 || Is_term(g->term[j]) || !(g->mark[j]) )
4808  continue;
4809 
4810  /* valid candidate? */
4811  if( g->grad[j] <= maxgrad && SCIPisLE(scip, g->prize[j], min) )
4812  {
4813  for( e2 = g->outbeg[j]; e2 != EAT_LAST; e2 = g->oeat[e2] )
4814  if( marked[g->head[e2]] == 0 )
4815  break;
4816 
4817  /* neighbours of j subset of those of k? */
4818  if( e2 == EAT_LAST )
4819  {
4820  while( g->outbeg[j] != EAT_LAST )
4821  {
4822  e2 = g->outbeg[j];
4823  (*count)++;
4824  graph_edge_del(scip, g, e2, TRUE);
4825  }
4826  g->mark[j] = FALSE;
4827  marked[j] = 0;
4828 
4829  }
4830  }
4831  }
4832  if( run == 1 )
4833  {
4834  for( e = g->outbeg[k2]; e != EAT_LAST; e = g->oeat[e] )
4835  if( marked[g->head[e]] == 1 && g->mark[g->head[e]] )
4836  marked[g->head[e]] = 0;
4837  min -= g->prize[k2];
4838  maxgrad -= k2grad;
4839  }
4840  }
4841  for( e = g->outbeg[k]; e != EAT_LAST; e = g->oeat[e] )
4842  {
4843  marked[g->head[e]] = 0;
4844 
4845  }
4846 
4847  for( l = 0; l < nn; l++ )
4848  for( e = g->outbeg[neighbarr[l]]; e != EAT_LAST; e = g->oeat[e] )
4849  marked[g->head[e]] = 0;
4850 
4851 
4852  marked[k] = 0;
4853 
4854  for( l = 0; l < nnodes; l++ )
4855  assert(marked[l] == 0);
4856 
4857  }
4858  }
4859 
4860  SCIPfreeBufferArray(scip, &neighbarr2);
4861  SCIPfreeBufferArray(scip, &neighbarr);
4862  return SCIP_OKAY;
4863 }
4864 #endif
4865 
4866 /** advanced adjacent neighbourhood reduction for the MWCSP */
4867 SCIP_RETCODE ansadvReduction(
4868  SCIP* scip, /**< SCIP data structure */
4869  GRAPH* g, /**< graph data structure */
4870  SCIP_Real* fixed, /**< pointer to offfset value */
4871  int* marked, /**< nodes array */
4872  int* count /**< pointer to number of reductions */
4873  )
4874 {
4875  SCIP_Real min;
4876  int* neighbarr;
4877  int k;
4878  int j;
4879  int e;
4880  int k2;
4881  int e2;
4882  int l;
4883  int nn;
4884  int nnodes;
4885  int maxgrad;
4886 
4887  assert(scip != NULL);
4888  assert(g != NULL);
4889  assert(fixed != NULL);
4890  assert(count != NULL);
4891  assert(marked != NULL);
4892  assert(g->stp_type == STP_MAX_NODE_WEIGHT);
4893 
4894  *count = 0;
4895  nnodes = g->knots;
4896 
4897  SCIP_CALL( SCIPallocBufferArray(scip, &neighbarr, CNSNN) );
4898 
4899  /* unmark all nodes */
4900  for( k = 0; k < nnodes; k++ )
4901  marked[k] = FALSE;
4902 
4903  /* check neighbourhood of all nodes */
4904  for( k = 0; k < nnodes; k++ )
4905  {
4906  if( (!(g->mark[k])) || (g->grad[k] < 2) || Is_term(g->term[k]) )
4907  continue;
4908 
4909  maxgrad = 0;
4910  nn = 0;
4911 
4912  /* mark adjacent vertices and k */
4913  for( e = g->outbeg[k]; e != EAT_LAST; e = g->oeat[e] )
4914  {
4915  j = g->head[e];
4916  marked[j] = TRUE;
4917  if( SCIPisGT(scip, g->prize[j], 0.0) && nn < CNSNN )
4918  neighbarr[nn++] = j;
4919  }
4920 
4921  marked[k] = TRUE;
4922 
4923  maxgrad = g->grad[k];
4924  for( l = 0; l < nn; l++ )
4925  {
4926  for( e = g->outbeg[neighbarr[l]]; e != EAT_LAST; e = g->oeat[e] )
4927  marked[g->head[e]] = TRUE;
4928  maxgrad += g->grad[neighbarr[l]];
4929  }
4930 
4931  assert(SCIPisLE(scip, g->prize[k], 0.0));
4932 
4933  min = g->prize[k];
4934 
4935  /* check all neighbours of k */
4936 #if 1
4937  e = g->outbeg[k];
4938  while( e != EAT_LAST )
4939 #else
4940  for( j = 0; j < nnodes; j++ )
4941 #endif
4942  {
4943 #if 0
4944  if( j == k )
4945  continue;
4946 #else
4947  j = g->head[e];
4948  e = g->oeat[e];
4949 #endif
4950  /* valid candidate? */
4951  if( g->grad[j] <= maxgrad && g->mark[j] && SCIPisLE(scip, g->prize[j], min) )
4952  {
4953  for( e2 = g->outbeg[j]; e2 != EAT_LAST; e2 = g->oeat[e2] )
4954  if( !marked[g->head[e2]] )
4955  break;
4956 
4957  /* neighbours of j subset of those of k? */
4958  if( e2 == EAT_LAST )
4959  {
4960  while( g->outbeg[j] != EAT_LAST )
4961  {
4962  e2 = g->outbeg[j];
4963  (*count)++;
4964  graph_edge_del(scip, g, e2, TRUE);
4965  }
4966  g->mark[j] = FALSE;
4967  marked[j] = FALSE;
4968  }
4969  }
4970  }
4971 
4972  for( e = g->outbeg[k]; e != EAT_LAST; e = g->oeat[e] )
4973  marked[g->head[e]] = FALSE;
4974 
4975  for( l = 0; l < nn; l++ )
4976  for( e = g->outbeg[neighbarr[l]]; e != EAT_LAST; e = g->oeat[e] )
4977  marked[g->head[e]] = FALSE;
4978 
4979  marked[k] = FALSE;
4980 
4981  for( k2 = 0; k2 < nnodes; k2++ )
4982  assert(marked[k2] == FALSE);
4983  }
4984 
4985  SCIPfreeBufferArray(scip, &neighbarr);
4986  return SCIP_OKAY;
4987 }
4988 
4989 
4990 /** alternative advanced adjacent neighbourhood reduction for the MWCSP */
4991 SCIP_RETCODE ansadv2Reduction(
4992  SCIP* scip, /**< SCIP data structure */
4993  GRAPH* g, /**< graph data structure */
4994  SCIP_Real* fixed, /**< pointer to offfset value */
4995  int* marked, /**< nodes array */
4996  int* count /**< pointer to number of reductions */
4997  )
4998 {
4999  SCIP_Real min;
5000  SCIP_Real maxprize;
5001  int* neighbarr;
5002  int k;
5003  int j;
5004  int e;
5005  int k2;
5006  int e2;
5007  int l;
5008  int run;
5009  int nn;
5010  int nnodes;
5011  int maxgrad;
5012 
5013  assert(scip != NULL);
5014  assert(g != NULL);
5015  assert(fixed != NULL);
5016  assert(count != NULL);
5017  assert(marked != NULL);
5018  assert(g->stp_type == STP_MAX_NODE_WEIGHT);
5019 
5020  *count = 0;
5021  nnodes = g->knots;
5022 
5023  SCIP_CALL( SCIPallocBufferArray(scip, &neighbarr, CNSNN + 1) );
5024 
5025  /* unmark all nodes */
5026  for( k = 0; k < nnodes; k++ )
5027  marked[k] = FALSE;
5028 
5029  for( run = 0; run < 2; run++ )
5030  {
5031  /* check neighbourhood of all nodes */
5032  for( k = 0; k < nnodes; k++ )
5033  {
5034  if( (!(g->mark[k])) || (g->grad[k] < 2) || Is_term(g->term[k]) )
5035  continue;
5036 
5037  nn = 0;
5038  k2 = UNKNOWN;
5039  maxgrad = g->grad[k];
5040  maxprize = g->prize[k];
5041 
5042  /* mark adjacent vertices and k */
5043  for( e = g->outbeg[k]; e != EAT_LAST; e = g->oeat[e] )
5044  {
5045  j = g->head[e];
5046  marked[j] = TRUE;
5047  if( SCIPisGT(scip, g->prize[j], 0.0) && nn < CNSNN - 1 )
5048  {
5049  neighbarr[nn++] = j;
5050  }
5051  else if( SCIPisGT(scip, g->prize[j], maxprize) && g->mark[j] )
5052  {
5053  maxprize = g->prize[j];
5054  k2 = j;
5055  }
5056  }
5057 
5058  marked[k] = TRUE;
5059 
5060  if( run == 0 && k2 != UNKNOWN )
5061  neighbarr[nn++] = k2;
5062 
5063  for( l = 0; l < nn; l++ )
5064  {
5065  for( e = g->outbeg[neighbarr[l]]; e != EAT_LAST; e = g->oeat[e] )
5066  {
5067  j = g->head[e];
5068  if( run == 1 && g->mark[j] && !Is_term(g->term[j]) && SCIPisGT(scip, g->prize[j], maxprize) )
5069  {
5070  maxprize = g->prize[j];
5071  k2 = j;
5072  }
5073  marked[j] = TRUE;
5074  }
5075  maxgrad += g->grad[neighbarr[l]];
5076  }
5077 
5078  if( run == 1 && k2 != UNKNOWN )
5079  {
5080  maxgrad += g->grad[k2];
5081  neighbarr[nn++] = k2;
5082 
5083  for( e = g->outbeg[k2]; e != EAT_LAST; e = g->oeat[e] )
5084  marked[g->head[e]] = TRUE;
5085  }
5086 
5087  assert(SCIPisLE(scip, g->prize[k], 0.0));
5088 
5089  min = g->prize[k];
5090  if( k2 != UNKNOWN )
5091  min += g->prize[k2];
5092 
5093  /* check all neighbours of k */
5094  e = g->outbeg[k];
5095  while( e != EAT_LAST )
5096  {
5097 #if 0
5098  if( j == k )
5099  continue;
5100 #else
5101  j = g->head[e];
5102  e = g->oeat[e];
5103 #endif
5104  /* valid candidate? */
5105  if( g->grad[j] <= maxgrad && g->mark[j] && SCIPisLE(scip, g->prize[j], min) && k2 != j )
5106  {
5107  for( e2 = g->outbeg[j]; e2 != EAT_LAST; e2 = g->oeat[e2] )
5108  if( !marked[g->head[e2]] )
5109  break;
5110 
5111  /* neighbours of j subset of those of k? */
5112  if( e2 == EAT_LAST )
5113  {
5114  while( g->outbeg[j] != EAT_LAST )
5115  {
5116  e2 = g->outbeg[j];
5117  (*count)++;
5118  graph_edge_del(scip, g, e2, TRUE);
5119  }
5120  g->mark[j] = FALSE;
5121  marked[j] = FALSE;
5122  }
5123  }
5124  }
5125 
5126  for( e = g->outbeg[k]; e != EAT_LAST; e = g->oeat[e] )
5127  marked[g->head[e]] = FALSE;
5128 
5129  for( l = 0; l < nn; l++ )
5130  for( e = g->outbeg[neighbarr[l]]; e != EAT_LAST; e = g->oeat[e] )
5131  marked[g->head[e]] = FALSE;
5132 
5133  marked[k] = FALSE;
5134 
5135  for( k2 = 0; k2 < nnodes; k2++ )
5136  assert(marked[k2] == FALSE);
5137  }
5138  }
5139 
5140  SCIPfreeBufferArray(scip, &neighbarr);
5141  return SCIP_OKAY;
5142 }
5143 
5144 
5145 /** non-positive vertex reduction for the MWCSP */
5146 SCIP_RETCODE npvReduction(
5147  SCIP* scip,
5148  GRAPH* g,
5149  PATH* pathtail,
5150  PATH* pathhead,
5151  int* heap,
5152  int* statetail,
5153  int* statehead,
5154  int* memlbltail,
5155  int* memlblhead,
5156  int* nelims,
5157  int limit
5158  )
5159 {
5160  GRAPH* auxg;
5161  PATH* mst;
5162  SCIP_Real prize;
5163  SCIP_Real sdist0;
5164  SCIP_Real sdist1;
5165  SCIP_Real sdist2;
5166  int* adjverts;
5167  int i;
5168  int k;
5169  int k2;
5170  int s;
5171  int l;
5172  int e;
5173  int nnodes;
5174 
5175  assert(g != NULL);
5176  assert(scip != NULL);
5177  assert(pathtail != NULL);
5178  assert(pathhead != NULL);
5179  assert(heap != NULL);
5180  assert(statetail != NULL);
5181  assert(statehead != NULL);
5182  assert(memlbltail != NULL);
5183  assert(memlblhead != NULL);
5184  assert(nelims != NULL);
5185 
5186  SCIP_CALL( SCIPallocBufferArray(scip, &adjverts, 5) );
5187 
5188  *nelims = 0;
5189  nnodes = g->knots;
5190 
5191  /* initialize arrays */
5192  for( i = 0; i < nnodes; i++ )
5193  {
5194  statetail[i] = UNKNOWN;
5195  pathtail[i].dist = FARAWAY;
5196  pathtail[i].edge = UNKNOWN;
5197  statehead[i] = UNKNOWN;
5198  pathhead[i].dist = FARAWAY;
5199  pathhead[i].edge = UNKNOWN;
5200  }
5201 
5202 
5203  /* --- NPV3 test --- */
5204 
5205  /* try to eliminate non-positive vertices of degree 3 */
5206  for( i = 0; i < nnodes; i++ )
5207  {
5208  assert(g->grad[i] >= 0);
5209  /* only non-positive vertices of degree 3 */
5210  if( !g->mark[i] || g->grad[i] != 3 || Is_term(g->term[i]) )
5211  continue;
5212 
5213  k = 0;
5214  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
5215  adjverts[k++] = g->head[e];
5216 
5217  assert(k == 3);
5218 
5219  g->mark[i] = FALSE;
5220  prize = g->prize[i];
5221  SCIP_CALL( getSD(scip, g, pathtail, pathhead, &sdist0, -prize, heap, statetail, statehead, memlbltail, memlblhead, adjverts[0], adjverts[1], limit, FALSE, TRUE) );
5222  SCIP_CALL( getSD(scip, g, pathtail, pathhead, &sdist1, -prize, heap, statetail, statehead, memlbltail, memlblhead, adjverts[1], adjverts[2], limit, FALSE, TRUE) );
5223  SCIP_CALL( getSD(scip, g, pathtail, pathhead, &sdist2, -prize, heap, statetail, statehead, memlbltail, memlblhead, adjverts[2], adjverts[0], limit, FALSE, TRUE) );
5224 
5225  /* can vertex be deleted? */
5226  if( (SCIPisGE(scip, -sdist0 - sdist1, prize) && SCIPisGE(scip, -sdist2, prize))
5227  || (SCIPisGE(scip, -sdist1 - sdist2, prize) && SCIPisGE(scip, -sdist0, prize))
5228  || (SCIPisGE(scip, -sdist2 - sdist0, prize) && SCIPisGE(scip, -sdist1, prize))
5229  )
5230  {
5231  SCIPdebugMessage("npv3Reduction delete: %d (prize: %f) \n", i, g->prize[i]);
5232  (*nelims) += g->grad[i];
5233  while( g->outbeg[i] != EAT_LAST )
5234  graph_edge_del(scip, g, g->outbeg[i], TRUE);
5235  }
5236  else
5237  {
5238  g->mark[i] = TRUE;
5239  }
5240  }
5241 
5242 
5243  /* --- NPV4 test --- */
5244 
5245  /* initialize mst struct and new graph for further tests */
5246  SCIP_CALL( SCIPallocBufferArray(scip, &mst, 5) );
5247  SCIP_CALL( graph_init(scip, &auxg, 5, 40, 1, 0) );
5248 
5249  for( k = 0; k < 4; k++ )
5250  graph_knot_add(auxg, -1);
5251  for( k = 0; k < 4; k++ )
5252  for( k2 = k + 1; k2 < 4; k2++ )
5253  graph_edge_add(scip, auxg, k, k2, 1.0, 1.0);
5254 
5255  SCIP_CALL( graph_path_init(scip, auxg) );
5256 
5257  /* try to eliminate non-positive vertices of degree 4 */
5258  for( i = 0; i < nnodes; i++ )
5259  {
5260  /* only non-positive vertices of degree 4 */
5261  if( !g->mark[i] || g->grad[i] != 4 || Is_term(g->term[i]) )
5262  continue;
5263  k = 0;
5264 
5265  /* store neighbours */
5266  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
5267  adjverts[k++] = g->head[e];
5268 
5269  assert(k == 4);
5270 
5271  g->mark[i] = FALSE;
5272  prize = g->prize[i];
5273 
5274  /* compute mw bottleneck distance to each pair of neighbours */
5275  for( k = 0; k < 4; k++ )
5276  {
5277  auxg->mark[k] = TRUE;
5278  for( e = auxg->outbeg[k]; e != EAT_LAST; e = auxg->oeat[e] )
5279  {
5280  k2 = auxg->head[e];
5281  if( k2 > k )
5282  {
5283  SCIP_CALL( getSD(scip, g, pathtail, pathhead, &(sdist0), -prize, heap, statetail, statehead, memlbltail, memlblhead, adjverts[k], adjverts[k2], limit, FALSE, TRUE) );
5284  auxg->cost[e] = sdist0;
5285  if( SCIPisGT(scip, prize, -auxg->cost[e]) )
5286  break;
5287 
5288  auxg->cost[flipedge(e)] = auxg->cost[e];
5289  }
5290  }
5291  if( e != EAT_LAST )
5292  break;
5293  }
5294 
5295  k = UNKNOWN;
5296  if( e == EAT_LAST )
5297  {
5298  /* compute mst on all neighbours */
5299  graph_path_exec(scip, auxg, MST_MODE, 0, auxg->cost, mst);
5300 
5301  /* calculate mst cost */
5302  sdist0 = 0.0;
5303  for( l = 1; l < 4; l++ )
5304  sdist0 += mst[l].dist;
5305 
5306  if( SCIPisLE(scip, prize, -sdist0) )
5307  {
5308  /* compute subset msts on all neighbours */
5309  for( k = 0; k < 4; k++ )
5310  {
5311  auxg->mark[k] = FALSE;
5312  sdist0 = 0.0;
5313  if( k != 0 )
5314  {
5315  graph_path_exec(scip, auxg, MST_MODE, 0, auxg->cost, mst);
5316  for( l = 1; l < 4; l++ )
5317  if( auxg->mark[l] )
5318  sdist0 += mst[l].dist;
5319  }
5320  else
5321  {
5322  graph_path_exec(scip, auxg, MST_MODE, 1, auxg->cost, mst);
5323  for( l = 2; l < 4; l++ )
5324  sdist0 += mst[l].dist;
5325  }
5326  auxg->mark[k] = TRUE;
5327  if( SCIPisGT(scip, prize, -sdist0) )
5328  break;
5329  }
5330  }
5331  }
5332 
5333  /* can node be eliminated? */
5334  if( k == 4 )
5335  {
5336  SCIPdebugMessage("npv4Reduction delete: %d (prize: %f) \n", i, g->prize[i]);
5337  (*nelims) += g->grad[i];
5338  while( g->outbeg[i] != EAT_LAST )
5339  graph_edge_del(scip, g, g->outbeg[i], TRUE);
5340  }
5341  else
5342  {
5343  g->mark[i] = TRUE;
5344  }
5345  }
5346 
5347  /* --- NPV5 test --- */
5348 
5349  /* enlarge graph for NPV5 test*/
5350  graph_knot_add(auxg, -1);
5351  for( k = 0; k < 4; k++ )
5352  graph_edge_add(scip, auxg, k, 4, 1.0, 1.0);
5353  graph_path_exit(scip, auxg);
5354  SCIP_CALL( graph_path_init(scip, auxg) );
5355 
5356  /* try to eliminate non-positive vertices of degree 5 */
5357  for( i = 0; i < nnodes; i++ )
5358  {
5359  /* only non-positive vertices of degree 5 */
5360  if( !g->mark[i] || g->grad[i] != 5 || Is_term(g->term[i]) )
5361  continue;
5362  k = 0;
5363 
5364  /* store neighbours */
5365  for( e = g->outbeg[i]; e != EAT_LAST; e = g->oeat[e] )
5366  adjverts[k++] = g->head[e];
5367 
5368  assert(k == 5);
5369 
5370  g->mark[i] = FALSE;
5371  prize = g->prize[i];
5372 
5373  for( k = 0; k < 5; k++ )
5374  {
5375  auxg->mark[k] = TRUE;
5376  for( e = auxg->outbeg[k]; e != EAT_LAST; e = auxg->oeat[e] )
5377  {
5378  k2 = auxg->head[e];
5379  if( k2 > k )
5380  {
5381  SCIP_CALL( getSD(scip, g, pathtail, pathhead, &(sdist0), -prize, heap, statetail, statehead, memlbltail, memlblhead, adjverts[k], adjverts[k2], limit, FALSE, TRUE) );
5382  auxg->cost[e] = sdist0;
5383  if( SCIPisGT(scip, prize, -auxg->cost[e]) )
5384  break;
5385 
5386  auxg->cost[flipedge(e)] = auxg->cost[e];
5387  }
5388  }
5389  if( e != EAT_LAST )
5390  break;
5391  }
5392  k = UNKNOWN;
5393  if( e == EAT_LAST )
5394  {
5395 
5396  graph_path_exec(scip, auxg, MST_MODE, 0, auxg->cost, mst);
5397  sdist0 = 0.0;
5398  for( l = 1; l < 5; l++ )
5399  sdist0 += mst[l].dist;
5400 
5401  if( SCIPisLE(scip, prize, -sdist0) )
5402  {
5403  for( k = 0; k < 5; k++ )
5404  {
5405  auxg->mark[k] = FALSE;
5406  sdist0 = 0.0;
5407  if( k != 0 )
5408  {
5409  graph_path_exec(scip, auxg, MST_MODE, 0, auxg->cost, mst);
5410  for( l = 1; l < 5; l++ )
5411  if( auxg->mark[l] )
5412  sdist0 += mst[l].dist;
5413  }
5414  else
5415  {
5416  graph_path_exec(scip, auxg, MST_MODE, 1, auxg->cost, mst);
5417  for( l = 2; l < 5; l++ )
5418  sdist0 += mst[l].dist;
5419  }
5420  k2 = UNKNOWN;
5421  if( SCIPisLE(scip, prize, -sdist0) )
5422  {
5423  for( k2 = k + 1; k2 < 5; k2++ )
5424  {
5425  if( k2 == k )
5426  continue;
5427  auxg->mark[k2] = FALSE;
5428  sdist0 = 0.0;
5429  if( k2 != 0 && k != 0)
5430  {
5431  graph_path_exec(scip, auxg, MST_MODE, 0, auxg->cost, mst);
5432  for( l = 1; l < 5; l++ )
5433  if( auxg->mark[l] )
5434  sdist0 += mst[l].dist;
5435  }
5436  else
5437  {
5438  if( k != 1 && k2 != 1 )
5439  s = 1;
5440  else
5441  s = 2;
5442  graph_path_exec(scip, auxg, MST_MODE, s, auxg->cost, mst);
5443  for( l = 0; l < 5; l++ )
5444  if( auxg->mark[l] && l != s )
5445  sdist0 += mst[l].dist;
5446  }
5447  auxg->mark[k2] = TRUE;
5448  if( SCIPisGT(scip, prize, -sdist0) )
5449  break;
5450  }
5451  }
5452  auxg->mark[k] = TRUE;
5453  if( k2 != 5 )
5454  break;
5455  }
5456  }
5457  }
5458 
5459  if( k == 5 )
5460  {
5461  SCIPdebugMessage(" \n npv5Reduction delete: %d (prize: %f) \n", i, g->prize[i]);
5462  (*nelims) += g->grad[i];
5463  while( g->outbeg[i] != EAT_LAST )
5464  graph_edge_del(scip, g, g->outbeg[i], TRUE);
5465 
5466  }
5467  else
5468  {
5469  g->mark[i] = TRUE;
5470  }
5471  }
5472 
5473  /* free memory*/
5474  graph_path_exit(scip, auxg);
5475  graph_free(scip, auxg, TRUE);
5476  SCIPfreeBufferArray(scip, &mst);
5477  SCIPfreeBufferArray(scip, &adjverts);
5478 
5479  return SCIP_OKAY;
5480 }
5481 
5482 
5483 /** chain reduction (NPV_2) for the MWCSP */
5484 SCIP_RETCODE chain2Reduction(
5485  SCIP* scip,
5486  GRAPH* g,
5487  PATH* pathtail,
5488  PATH* pathhead,
5489  int* heap,
5490  int* statetail,
5491  int* statehead,
5492  int* memlbltail,
5493  int* memlblhead,
5494  int* nelims,
5495  int limit
5496  )
5497 {
5498  SCIP_Real sdist;
5499  int i;
5500  int i1;
5501  int i2;
5502  int e1;
5503  int e2;
5504  int nnodes;
5505 
5506  assert(g != NULL);
5507  assert(scip != NULL);
5508  assert(pathtail != NULL);
5509  assert(pathhead != NULL);
5510  assert(heap != NULL);
5511  assert(statetail != NULL);
5512  assert(statehead != NULL);
5513  assert(memlbltail != NULL);
5514  assert(memlblhead != NULL);
5515  assert(nelims != NULL);
5516 
5517  *nelims = 0;
5518  nnodes = g->knots;
5519 
5520  /* initialize arrays */
5521  for( i = 0; i < nnodes; i++ )
5522  {
5523  statetail[i] = UNKNOWN;
5524  pathtail[i].dist = FARAWAY;
5525  pathtail[i].edge = UNKNOWN;
5526  statehead[i] = UNKNOWN;
5527  pathhead[i].dist = FARAWAY;
5528  pathhead[i].edge = UNKNOWN;
5529  }
5530 
5531  for( i = 0; i < nnodes; i++ )
5532  {
5533  assert(g->grad[i] >= 0);
5534  if( !g->mark[i] || g->grad[i] == 0 || Is_term(g->term[i]) || g->grad[i] != 2 )
5535  continue;
5536 
5537  /* non-positive chains */
5538  e1 = g->outbeg[i];
5539  e2 = g->oeat[e1];
5540  i1 = g->head[e1];
5541  i2 = g->head[e2];
5542 
5543  assert(e1 >= 0);
5544  assert(e2 >= 0);
5545  assert(g->mark[i1]);
5546  assert(g->mark[i2]);
5547  g->mark[i] = FALSE;
5548  SCIP_CALL( getSD(scip, g, pathtail, pathhead, &sdist, -(g->prize[i]), heap, statetail, statehead, memlbltail, memlblhead, i1, i2, limit, FALSE, TRUE) );
5549  if( SCIPisGE(scip, -sdist, g->prize[i]) )
5550  {
5551  SCIPdebugMessage("delete : %d prize: %f sd: %f \n", i, g->prize[i], -sdist );
5552  graph_edge_del(scip, g, e1, TRUE);
5553  graph_edge_del(scip, g, e2, TRUE);
5554  (*nelims) += 2;
5555  }
5556  else
5557  {
5558  g->mark[i] = TRUE;
5559  }
5560  }
5561  return SCIP_OKAY;
5562 }
5563 /** non-negative path reduction for the MWCSP */
5564 SCIP_RETCODE nnpReduction(
5565  SCIP* scip, /**< SCIP data structure */
5566  GRAPH* g, /**< graph data structure */
5567  SCIP_Real* fixed, /**< pointer to offfset value */
5568  int* mem, /**< nodes array */
5569  int* marked, /**< nodes array */
5570  int* visited, /**< nodes array */
5571  int* count, /**< pointer to number of reductions */
5572  int maxniter, /**< max number of edges to check */
5573  char* positive /**< nodes array */
5574  )
5575 {
5576  SCIP_QUEUE* queue;
5577  int* pnode;
5578  int i;
5579  int j;
5580  int k;
5581  int e;
5582  int e2;
5583  int erev;
5584  int enext;
5585  int nnodes;
5586  int nvisited1;
5587  int nvisited2;
5588  int iterations;
5589  SCIP_Bool success;
5590 
5591  assert(scip != NULL);
5592  assert(g != NULL);
5593  assert(fixed != NULL);
5594  assert(count != NULL);
5595  assert(mem != NULL);
5596  assert(positive != NULL);
5597  assert(visited != NULL);
5598  assert(marked != NULL);
5599  assert(g->stp_type == STP_MAX_NODE_WEIGHT);
5600 
5601  *count = 0;
5602  nnodes = g->knots;
5603 
5604  /* unmark all nodes */
5605  for( i = 0; i < nnodes; i++ )
5606  {
5607  if( g->mark[i] && SCIPisGE(scip, g->prize[i], 0.0) )
5608  positive[i] = TRUE;
5609  else
5610  positive[i] = FALSE;
5611  marked[i] = FALSE;
5612  visited[i] = FALSE;
5613  }
5614 
5615  SCIP_CALL( SCIPqueueCreate(&queue, nnodes, 2.0) );
5616 
5617  for( i = 0; i < nnodes; i++ )
5618  {
5619  if( !g->mark[i] )
5620  continue;
5621 
5622  /* mark adjacent vertices and i*/
5623  e = g->outbeg[i];
5624  while( e != EAT_LAST )
5625  {
5626  j = g->head[e];
5627  enext = g->oeat[e];
5628  if( g->mark[j] )
5629  {
5630  nvisited1 = 0;
5631  iterations = 0;
5632  success = FALSE;
5633 
5634  assert(SCIPqueueIsEmpty(queue));
5635 
5636  SCIP_CALL( SCIPqueueInsert(queue, &g->head[g->inpbeg[i]]) );
5637  marked[i] = TRUE;
5638  mem[nvisited1++] = i;
5639 
5640  /* BFS */
5641  while( !SCIPqueueIsEmpty(queue) )
5642  {
5643  pnode = SCIPqueueRemove(queue);
5644  for( e2 = g->outbeg[*pnode]; e2 != EAT_LAST; e2 = g->oeat[e2] )
5645  {
5646  if( e2 == e )
5647  continue;
5648  k = g->head[e2];
5649  if( iterations++ >= maxniter || k == j )
5650  {
5651  if( k == j )
5652  success = TRUE;
5653  SCIPqueueClear(queue);
5654  break;
5655  }
5656 
5657  if( positive[k] && !marked[k] )
5658  {
5659  marked[k] = TRUE;
5660  assert(nvisited1 < nnodes);
5661  mem[nvisited1++] = k;
5662  SCIP_CALL( SCIPqueueInsert(queue, &g->head[e2]) );
5663  }
5664  }
5665  }
5666 
5667  nvisited2 = 0;
5668  /* vertex j not reached yet? */
5669  if( !success )
5670  {
5671  assert(SCIPqueueIsEmpty(queue));
5672  SCIP_CALL( SCIPqueueInsert(queue, &j) );
5673  visited[j] = TRUE;
5674  assert(nvisited2 + nvisited1 < nnodes);
5675  mem[nvisited1 + nvisited2++] = j;
5676  erev = flipedge(e);
5677 
5678  iterations = 0;
5679  while( !SCIPqueueIsEmpty(queue) )
5680  {
5681  pnode = (SCIPqueueRemove(queue));
5682  for( e2 = g->outbeg[*pnode]; e2 != EAT_LAST; e2 = g->oeat[e2] )
5683  {
5684  if( e2 == erev )
5685  continue;
5686  k = g->head[e2];
5687 
5688  if( iterations++ >= maxniter || marked[k] )
5689  {
5690  if( marked[k] )
5691  success = TRUE;
5692  SCIPqueueClear(queue);
5693  break;
5694  }
5695 
5696  if( positive[k] && !visited[k] )
5697  {
5698  visited[k] = TRUE;
5699  assert(nvisited2 + nvisited1 < nnodes);
5700  mem[nvisited1 + nvisited2++] = k;
5701  SCIP_CALL( SCIPqueueInsert(queue, &g->head[e2]) );
5702  }
5703  }
5704  }
5705  }
5706 
5707  if( success )
5708  {
5709  (*count)++;
5710  graph_edge_del(scip, g, e, TRUE);
5711  }
5712  for( j = 0; j < nvisited1; j++ )
5713  marked[mem[j]] = FALSE;
5714 
5715  for( j = nvisited1; j < nvisited1 + nvisited2; j++ )
5716  visited[mem[j]] = FALSE;
5717 
5718  for( j = 0; j < nnodes; j++ )
5719  {
5720  assert(marked[j] == FALSE);
5721  assert(visited[j] == FALSE);
5722  }
5723  }
5724  e = enext;
5725  }
5726  }
5727  SCIPqueueFree(&queue);
5728 
5729  return SCIP_OKAY;
5730 }
SCIP_RETCODE graph_path_init(SCIP *, GRAPH *)
Definition: grphpath.c:407
SCIP_RETCODE sd_reduction(SCIP *scip, GRAPH *g, SCIP_Real *sddist, SCIP_Real *sdtrans, SCIP_Real *sdrand, SCIP_Real *cost, SCIP_Real *randarr, int *heap, int *state, int *knotexamined, int *elimins, int runnum, unsigned int *seed)
Definition: reduce_alt.c:2227
#define Is_term(a)
Definition: grph.h:158
static int getcloseterms(SCIP *scip, PATH *vnoi, SCIP_Real *termdist, SCIP_Real ecost, int *vbase, int *neighbterms, int i, int nnodes)
Definition: reduce_alt.c:272
#define LT(a, b)
Definition: portab.h:64
int graph_valid(const GRAPH *)
Definition: grphbase.c:2532
static int getlecloseterms(SCIP *scip, PATH *vnoi, SCIP_Real *termdist, SCIP_Real ecost, int *vbase, int *neighbterms, int i, int nnodes)
Definition: reduce_alt.c:311
static void compute_sd(SCIP *scip, const GRAPH *p, int start, const double *cost, const double *randarr, int *heap, int *state, int *count, double *pathdist, double *pathtran, double *pathrand)
Definition: reduce_alt.c:462
SCIP_RETCODE sdsp_reduction(SCIP *scip, GRAPH *g, PATH *pathtail, PATH *pathhead, int *heap, int *statetail, int *statehead, int *memlbltail, int *memlblhead, int *nelims, int limit)
Definition: reduce_alt.c:2058
#define LE(a, b)
Definition: portab.h:65
Definition: grph.h:55
#define TRUE
Definition: portab.h:34
SCIP_RETCODE bd3_reduction(SCIP *scip, GRAPH *g, PATH *pathtail, PATH *pathhead, int *heap, int *statetail, int *statehead, int *memlbltail, int *memlblhead, int *nelims, int limit)
Definition: reduce_alt.c:2817
signed int edge
Definition: grph.h:140
#define KNOTLIMIT
Definition: reduce_alt.c:41
void getnext4tterms(SCIP *, const GRAPH *, SCIP_Real *, SCIP_Real *, PATH *, int *, int *, int *)
Definition: grphpath.c:1603
#define MST_MODE
Definition: grph.h:152
int terms
Definition: grph.h:63
SCIP_RETCODE graph_edge_reinsert(SCIP *, GRAPH *, int, int, int, SCIP_Real, IDX *, IDX *, IDX *, IDX *)
Definition: grphbase.c:1846
#define GT(a, b)
Definition: portab.h:66
#define STP_HOP_CONS
Definition: grph.h:48
#define EAT_LAST
Definition: grph.h:31
#define Edge_anti(a)
Definition: grph.h:161
void sdpaths(SCIP *, const GRAPH *, PATH *, SCIP_Real *, SCIP_Real, int *, int *, int *, int *, int, int, int)
Definition: grphpath.c:542
SCIP_RETCODE ansadvReduction(SCIP *scip, GRAPH *g, SCIP_Real *fixed, int *marked, int *count)
Definition: reduce_alt.c:4867
int * path_state
Definition: grph.h:115
SCIP_RETCODE nv_reductionAdv(SCIP *scip, GRAPH *g, PATH *vnoi, SCIP_Real *distance, double *fixed, int *edgearrint, int *heap, int *state, int *vbase, int *neighb, int *distnode, int *nelims)
Definition: reduce_alt.c:4083
Problem data for stp problem.
SCIP_RETCODE graph_knot_contract(SCIP *, GRAPH *, int, int)
Definition: grphbase.c:1415
static SCIP_Bool sddeltable(SCIP *scip, GRAPH *g, PATH *path, int *vbase, int *forbidden, int tpos, int hpos, int tail, int head, int edge, int nnodes)
Definition: reduce_alt.c:129
void graph_path_exit(SCIP *, GRAPH *)
Definition: grphpath.c:429
SCIP_RETCODE sdsp_sap_reduction(SCIP *scip, GRAPH *g, PATH *pathtail, PATH *pathhead, int *heap, int *statetail, int *statehead, int *memlbltail, int *memlblhead, int *nelims, int limit)
Definition: reduce_alt.c:1900
static void correct(SCIP *scip, int *heap, int *state, int *count, double *pathdist, double *pathtran, int l)
Definition: reduce_alt.c:420
static SCIP_Bool maxprize(SCIP *scip, GRAPH *g, int i)
Definition: reduce_simple.c:40
SCIP_RETCODE sd_red(SCIP *scip, GRAPH *g, PATH *vnoi, SCIP_Real *edgepreds, SCIP_Real *mstsdist, int *heap, int *state, int *vbase, int *nodesid, int *nodesorg, int *forbidden, int *nelims)
Definition: reduce_alt.c:598
int * oeat
Definition: grph.h:100
void graph_free(SCIP *, GRAPH *, SCIP_Bool)
Definition: grphbase.c:1137
#define KNOTFREQ
Definition: reduce_alt.c:40
int graph_edge_redirect(SCIP *, GRAPH *, int, int, int, SCIP_Real)
Definition: grphbase.c:1783
void graph_knot_chg(GRAPH *, int, int)
Definition: grphbase.c:1386
int * head
Definition: grph.h:94
SCIP_RETCODE ledge_reduction(SCIP *scip, GRAPH *g, PATH *vnoi, int *heap, int *state, int *vbase, int *nelims)
Definition: reduce_alt.c:4372
IDX * fixedges
Definition: grph.h:82
SCIP_RETCODE nnpReduction(SCIP *scip, GRAPH *g, SCIP_Real *fixed, int *mem, int *marked, int *visited, int *count, int maxniter, char *positive)
Definition: reduce_alt.c:5564
static int nearest(SCIP *scip, int *heap, int *state, int *count, const double *pathdist, const double *pathtran)
Definition: reduce_alt.c:375
#define FALSE
Definition: portab.h:37
void SCIPintListNodeFree(SCIP *scip, IDX **node)
Definition: misc_stp.c:140
int * mark
Definition: grph.h:71
void graph_path_execX(SCIP *, const GRAPH *, int, SCIP_Real *, SCIP_Real *, int *)
Definition: grphpath.c:639
#define CONNECT
Definition: grph.h:147
SCIP_RETCODE ansReduction(SCIP *scip, GRAPH *g, SCIP_Real *fixed, int *marked, int *count)
Definition: reduce_alt.c:4579
#define EQ(a, b)
Definition: portab.h:62
int stp_type
Definition: grph.h:123
IDX ** ancestors
Definition: grph.h:83
SCIP_RETCODE npvReduction(SCIP *scip, GRAPH *g, PATH *pathtail, PATH *pathhead, int *heap, int *statetail, int *statehead, int *memlbltail, int *memlblhead, int *nelims, int limit)
Definition: reduce_alt.c:5146
int * outbeg
Definition: grph.h:77
#define Is_pterm(a)
Definition: grph.h:159
SCIP_Real * prize
Definition: grph.h:92
int * tail
Definition: grph.h:93
#define FSP_MODE
Definition: grph.h:153
#define GE(a, b)
Definition: portab.h:67
int * term
Definition: grph.h:69
int knots
Definition: grph.h:61
#define STP_MAX_NODE_WEIGHT
Definition: grph.h:47
SCIP_RETCODE SCIPprobdataPrintGraph2(const GRAPH *graph, const char *filename, SCIP_Bool *edgemark)
void voronoi_terms(SCIP *, const GRAPH *, SCIP_Real *, PATH *, int *, int *, int *)
Definition: grphpath.c:1679
SCIP_RETCODE nv_reduction(SCIP *scip, GRAPH *g, PATH *vnoi, double *fixed, int *edgearrint, int *heap, int *state, int *vbase, int *nelims)
Definition: reduce_alt.c:3892
void getnext4terms(SCIP *, const GRAPH *, SCIP_Real *, SCIP_Real *, PATH *, int *, int *, int *)
Definition: grphpath.c:1562
int * inpbeg
Definition: grph.h:75
static int islarger(SCIP *scip, const double *pathdist, const double *pathtran, int a, int b)
Definition: reduce_alt.c:359
SCIP_RETCODE bdr_reduction(SCIP *scip, GRAPH *g, GRAPH *netgraph, PATH *netmst, PATH *vnoi, SCIP_Real *mstsdist, SCIP_Real *termdist1, SCIP_Real *termdist2, int *vbase, int *nodesid, int *neighbterms1, int *neighbterms2, int *nelims)
Definition: reduce_alt.c:2538
#define FARAWAY
Definition: grph.h:149
void voronoi_term(const GRAPH *, double *, double *, double *, PATH *, int *, int *, int *, int *, int)
SCIP_RETCODE SCIPintListNodeAppendCopy(SCIP *scip, IDX **node1, IDX *node2)
Definition: misc_stp.c:76
#define UNKNOWN
Definition: grph.h:148
#define STP_PRIZE_COLLECTING
Definition: grph.h:40
SCIP_RETCODE graph_init(SCIP *, GRAPH **, int, int, int, int)
Definition: grphbase.c:44
void graph_edge_del(SCIP *, GRAPH *, int, SCIP_Bool)
Definition: grphbase.c:1965
void level0(SCIP *, GRAPH *)
Definition: reduce.c:791
SCIP_RETCODE sd2_reduction(SCIP *scip, GRAPH *g, SCIP_Real *nodecost, int *nelims, int *adjacent)
Definition: reduce_alt.c:1799
SCIP_RETCODE getSD(SCIP *scip, GRAPH *g, PATH *pathtail, PATH *pathhead, SCIP_Real *sdist, SCIP_Real distlimit, int *heap, int *statetail, int *statehead, int *memlbltail, int *memlblhead, int i, int i2, int limit, SCIP_Bool pc, SCIP_Bool mw)
Definition: reduce_alt.c:1658
includes various files containing graph methods used for Steiner problems
SCIP_RETCODE sl_reduction(SCIP *scip, GRAPH *g, PATH *vnoi, double *fixed, int *heap, int *state, int *vbase, int *vrnodes, char *visited, int *nelims)
Definition: reduce_alt.c:3656
#define EAT_FREE
Definition: grph.h:30
int * grad
Definition: grph.h:74
SCIP_RETCODE ansadv2Reduction(SCIP *scip, GRAPH *g, SCIP_Real *fixed, int *marked, int *count)
Definition: reduce_alt.c:4991
SCIP_Real * cost
Definition: grph.h:91
static int issmaller(SCIP *scip, const double *pathdist, const double *pathtran, int a, int b)
Definition: reduce_alt.c:350
#define STP_ROOTED_PRIZE_COLLECTING
Definition: grph.h:41
int * source
Definition: grph.h:67
SCIP_RETCODE cnsAdvReduction(SCIP *scip, GRAPH *g, int *marked, int *count)
Definition: reduce_alt.c:4675
SCIP_RETCODE graph_knot_contractpc(SCIP *, GRAPH *, int, int, int)
Definition: grphbase.c:1679
#define STP_DIRECTED
Definition: grph.h:39
#define CNSNN
Definition: reduce_alt.c:39
int edges
Definition: grph.h:89
#define flipedge(edge)
Definition: grph.h:143
void graph_knot_add(GRAPH *, int)
Definition: grphbase.c:1362
int * ieat
Definition: grph.h:99
static SCIP_Real getRSD(SCIP *scip, GRAPH *g, GRAPH *netgraph, PATH *mst, PATH *vnoi, SCIP_Real *mstsdist, SCIP_Real *termdist1, SCIP_Real *termdist2, int *vbase, int *nodesid, int *neighbterms1, int *neighbterms2, int i, int i2, int limit)
Definition: reduce_alt.c:1472
int hoplimit
Definition: grph.h:86
double dist
Definition: grph.h:139
void graph_edge_add(SCIP *, GRAPH *, int, int, double, double)
void graph_path_exec(SCIP *, const GRAPH *, int, int, SCIP_Real *, PATH *)
Definition: grphpath.c:453
SCIP_RETCODE sdpc_reduction(SCIP *scip, GRAPH *g, PATH *vnoi, SCIP_Real *boundedges, int *heap, int *state, int *vbase, int *nodesid, int *nodesorg, int *nelims)
Definition: reduce_alt.c:1144
SCIP_RETCODE voronoi_dist(SCIP *, const GRAPH *, SCIP_Real *, double *, int *, int *, int *, int *, int *, int *, PATH *)
SCIP_RETCODE chain2Reduction(SCIP *scip, GRAPH *g, PATH *pathtail, PATH *pathhead, int *heap, int *statetail, int *statehead, int *memlbltail, int *memlblhead, int *nelims, int limit)
Definition: reduce_alt.c:5484