Scippy

SCIP

Solving Constraint Integer Programs

reduce_ext.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-2022 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 visit scip.zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file reduce_ext.c
17  * @brief extended reductions for Steiner tree problems
18  * @author Daniel Rehfeldt
19  *
20  * This file implements extended reduction techniques for several Steiner problems.
21  * Note: Deprecated and is only used for test purposes. Use extreduce.h methods instead.
22  *
23  * A list of all interface methods can be found in reduce.h.
24  *
25  */
26 
27 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
28 
29 //#define SCIP_DEBUG
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <assert.h>
33 #include "graph.h"
34 #include "reduce.h"
35 
36 #define EXT_ANCESTORS_MAX 16
37 
38 #define RED_EXT_MAXDFSDEPTH 6
39 #define RED_EXT_MINDFSDEPTH 4
40 #define RED_EXT_MAXGRAD 8
41 #define RED_EXT_MINGRAD 6
42 #define RED_EXT_EDGELIMIT 50000
43 
44 
45 /** deletes an edge and makes corresponding adaptations */
46 static
48  SCIP* scip, /**< SCIP */
49  int edge, /**< edge to delete */
50  GRAPH* graph /**< graph data structure */
51 )
52 {
53  const int tail = graph->tail[edge];
54  const int head = graph->head[edge];
55  graph_edge_del(scip, graph, edge, TRUE);
56 
57  if( graph->grad[tail] == 0 )
58  {
59  if( Is_term(graph->term[tail]) )
60  {
61  assert(graph_pc_isPcMw(graph) || tail == graph->source);
62  }
63  else
64  {
65  graph->mark[tail] = FALSE;
66  }
67  }
68 
69  if( graph->grad[head] == 0 )
70  {
71  if( Is_term(graph->term[head]) || head == graph->source )
72  {
73  assert(graph_pc_isPcMw(graph));
74  }
75  else
76  {
77  graph->mark[head] = FALSE;
78  }
79  }
80 }
81 
82 /** mark ancestors of given edge */
83 static
85  const GRAPH* graph, /**< graph data structure */
86  int edge, /**< edge to use */
87  int* ancestormark /**< ancestor mark array */
88  )
89 {
90  int count = 0;
91  assert(edge >= 0);
92 
93  for( IDX* curr = graph_edge_getAncestors(graph, edge); curr != NULL && count <= EXT_ANCESTORS_MAX; curr = curr->parent, count++ )
94  {
95  const unsigned idx = ((unsigned) curr->index) / 2;
96 
97  assert(curr->index >= 0 && idx < (unsigned) (MAX(graph->edges, graph->orgedges) / 2));
98 
99  if( ancestormark[idx] )
100  return TRUE;
101 
102  ancestormark[idx] = 1;
103  }
104 
105  return FALSE;
106 }
107 
108 /** mark ancestors of given edge */
109 static
111  const GRAPH* graph, /**< graph data structure */
112  int edge, /**< edge to use */
113  int* ancestormark /**< ancestor mark array */
114  )
115 {
116  int count = 0;
117  assert(edge >= 0);
118 
119  for( IDX* curr = graph_edge_getAncestors(graph, edge); curr != NULL && count <= EXT_ANCESTORS_MAX; curr = curr->parent, count++ )
120  {
121  assert(curr->index >= 0 && curr->index / 2 < (MAX(graph->edges, graph->orgedges) / 2));
122  assert((ancestormark[((unsigned) curr->index) / 2]) == 0);
123 
124  ancestormark[((unsigned) curr->index) / 2] = 1;
125  }
126 }
127 
128 /** unmark ancestors of given edge */
129 static
131  const GRAPH* graph, /**< graph data structure */
132  int edge, /**< edge to use */
133  int* ancestormark /**< ancestor mark array */
134  )
135 {
136  int count = 0;
137  assert(edge >= 0);
138 
139  for( IDX* curr = graph_edge_getAncestors(graph, edge); curr != NULL && count <= EXT_ANCESTORS_MAX; curr = curr->parent, count++ )
140  {
141  assert(curr->index >= 0 && curr->index / 2 < (MAX(graph->edges, graph->orgedges) / 2));
142  ancestormark[((unsigned) curr->index) / 2] = 0;
143  }
144 }
145 
146 /** unmark ancestors of given edge */
147 static
149  const GRAPH* graph, /**< graph data structure */
150  int edge, /**< edge to use */
151  int* ancestormark /**< ancestor mark array */
152  )
153 {
154  int count = 0;
155  assert(edge >= 0);
156 
157  for( IDX* curr = graph_edge_getAncestors(graph, edge); curr != NULL && count <= EXT_ANCESTORS_MAX; curr = curr->parent, count++ )
158  {
159  const unsigned idx = ((unsigned) curr->index) / 2;
160 
161  assert(curr->index >= 0 && curr->index / 2 < (MAX(graph->edges, graph->orgedges) / 2));
162  assert(ancestormark[idx] == 1);
163 
164  ancestormark[idx] = 0;
165  }
166 }
167 
168 /** finalize subtree computations (clean up, update global bound) */
169 static
171  const GRAPH* graph, /**< graph data structure */
172  const int* edgeends, /**< heads or tail of edge */
173  const int* treeedges, /**< tree edges */
174  int dfsdepth, /**< dfs depth */
175  SCIP_Bool stopped, /**< has extension been stopped? */
176  SCIP_Real localbound, /**< local bound */
177  SCIP_Real* globalbound, /**< points to global bound */
178  SCIP_Bool* ruleout, /**< rule out? */
179  int* nodepos, /**< node position in tree */
180  int* ancestormark /**< ancestor mark array */
181 )
182 {
183 
184  if( localbound > *globalbound )
185  *globalbound = localbound;
186 
187  if( !stopped )
188  *ruleout = TRUE;
189 
190  if( !(*ruleout) )
191  {
192  for( int etree = 0; etree < dfsdepth; etree++ )
193  {
194  const int node = edgeends[treeedges[etree]];
195  assert(nodepos[node]);
196  nodepos[node] = 0;
197  unmarkAncestors(graph, treeedges[etree], ancestormark);
198  }
199  }
200  else
201  {
202  assert(dfsdepth == 0);
203  }
204 }
205 
206 /** should we truncate subtree? */
207 static
209  const GRAPH* graph, /**< graph data structure */
210  SCIP_Real extendedcost, /**< cost of subtree */
211  int root, /**< DA root */
212  int currhead, /**< latest node */
213  int maxgrad, /**< maximum allowed degree */
214  int dfsdepth, /**< dfs depth */
215  int maxdfsdepth, /**< max dfs depth */
216  SCIP_Real* minbound, /**< bound */
217  SCIP_Bool* stopped /**< real truncation? */
218 )
219 {
220  assert(graph->mark[currhead]);
221 
222  if( Is_term(graph->term[currhead]) || graph->grad[currhead] > maxgrad || dfsdepth >= maxdfsdepth )
223  {
224  /* real truncation? */
225  if( root != currhead )
226  {
227  *stopped = TRUE;
228  if( extendedcost < *minbound )
229  *minbound = extendedcost;
230  }
231  return TRUE;
232  }
233  return FALSE;
234 }
235 
236 /** remove latest edge from subtree and returns new tree cost */
237 static
239  SCIP* scip, /**< SCIP */
240  const GRAPH* graph, /**< graph data structure */
241  const SCIP_Real* redcost, /**< reduced costs */
242  const int* treeedges, /**< edges of tree */
243  SCIP_Real treecostold, /**< old tree cost */
244  SCIP_Real treecostoffset, /**< tree cost offset */
245  int dfsdepth, /**< DFS depth */
246  int lastnode, /**< last node */
247  int* nodepos, /**< array to mark node position*/
248  int* ancestormark, /**< ancestor mark array */
249  unsigned int* nstallrounds /**< rounds since latest update */
250 )
251 {
252  const int lastedge = treeedges[dfsdepth - 1];
253 
254  assert(dfsdepth >= 1 && lastnode >= 0);
255  assert(SCIPisGE(scip, treecostold, 0.0) && treecostoffset >= 0.0);
256 
257  nodepos[lastnode] = 0;
258  unmarkAncestors(graph, lastedge, ancestormark);
259 
260  /* recompute tree cost? */
261  if( (*nstallrounds)++ >= 9 )
262  {
263  SCIP_Real treecost = treecostoffset;
264 
265  *nstallrounds = 0;
266 
267  for( int i = 0; i < dfsdepth - 1; i++ )
268  treecost += redcost[treeedges[i]];
269 
270  assert(SCIPisEQ(scip, treecost, treecostold - redcost[lastedge]));
271  }
272 
273  return (treecostold - redcost[lastedge]);
274 }
275 
276 /** extend subtree and return new nadded_edges */
277 static
279  SCIP* scip, /**< SCIP */
280  const GRAPH* graph, /**< graph data structure */
281  const SCIP_Real* redcost, /**< reduced costs */
282  int curredge, /**< added edges */
283  int currhead, /**< latest node */
284  int dfsdepth, /**< DFS depth*/
285  int nadded_edges, /**< added edges */
286  SCIP_Real* treecost, /**< pointer to treecost */
287  SCIP_Real* treecosts, /**< edge costs of tree */
288  int* nodepos, /**< node position in tree */
289  int* treeedges, /**< edges of tree */
290  int* edgestack, /**< stack */
291  int* ancestormark /**< ancestor mark array */
292 )
293 {
294  int n = nadded_edges + 1;
295  nodepos[currhead] = dfsdepth + 1;
296  *treecost += redcost[curredge];
297  treeedges[dfsdepth] = curredge;
298  treecosts[dfsdepth] = graph->cost[curredge];
299 
300  markAncestors(graph, curredge, ancestormark);
301  assert(graph->mark[currhead]);
302 
303  for( int e = graph->outbeg[currhead]; e != EAT_LAST; e = graph->oeat[e] )
304  {
305  const int head = graph->head[e];
306  if( !nodepos[head] && graph->mark[head] )
307  edgestack[n++] = e;
308  }
309 
310  return n;
311 }
312 
313 /** extend subtree and return new nadded_edges */
314 static
316  const GRAPH* graph, /**< graph data structure */
317  const SCIP_Real* redcost, /**< reduced costs */
318  int curredge, /**< added edges */
319  int currtail, /**< latest node */
320  int dfsdepth, /**< DFS depth*/
321  int nadded_edges, /**< added edges */
322  SCIP_Real* treecost, /**< pointer to treecost */
323  SCIP_Real* treecosts, /**< edge costs of tree */
324  int* nodepos, /**< node position in tree */
325  int* treeedges, /**< edges of tree */
326  int* edgestack, /**< stack */
327  int* ancestormark /**< ancestor mark array */
328 )
329 {
330  int n = nadded_edges + 1;
331  nodepos[currtail] = dfsdepth + 1;
332  *treecost += redcost[curredge];
333  treeedges[dfsdepth] = curredge;
334  treecosts[dfsdepth] = graph->cost[curredge];
335 
336  markAncestors(graph, curredge, ancestormark);
337  assert(graph->mark[currtail]);
338 
339  for( int e = graph->inpbeg[currtail]; e != EAT_LAST; e = graph->ieat[e] )
340  {
341  const int tail = graph->tail[e];
342  if( !nodepos[tail] && graph->mark[tail] )
343  edgestack[n++] = e;
344  }
345 
346  return n;
347 }
348 
349 
350 /** small helper */
351 static
353  int edge, /**< the edge */
354  unsigned int* eqstack, /**< stores edges that were used for equality comparison */
355  int* eqstack_size, /**< pointer to size of eqstack */
356  SCIP_Bool* eqmark /**< marks edges that were used for equality comparison */
357 )
358 {
359  const unsigned int halfedge = ((unsigned int) edge) / 2;
360 
361  assert(edge >= 0);
362 
363  if( !eqmark[halfedge] )
364  {
365  eqmark[halfedge] = TRUE;
366  eqstack[*eqstack_size] = halfedge;
367 
368  *eqstack_size = *eqstack_size + 1;
369  }
370 }
371 
372 
373 /** compare with tree bottleneck */
374 static
376  SCIP* scip, /**< SCIP */
377  const GRAPH* graph, /**< graph data structure */
378  const SCIP_Real* treecosts, /**< costs of edges of the tree */
379  const SCIP_Real* basebottlenecks, /**< bottleneck costs for innode and basenode */
380  const int* nodepos, /**< node position in tree */
381  const int* treeedges, /**< edges in tree (corresponding to treecosts) */
382  SCIP_Real orgedgecost, /**< cost of original edge */
383  SCIP_Real extedgecost, /**< cost of short-cut edge */
384  int orgedge, /**< original edge */
385  int extedge, /**< short-cut edge */
386  int dfsdepth, /**< dfs depth */
387  SCIP_Bool allow_eq, /**< test for equality? */
388  unsigned int* eqstack, /**< stores edges that were used for equality comparison */
389  int* eqstack_size, /**< pointer to size of eqstack */
390  SCIP_Bool* eqmark /**< marks edges that were used for equality comparison */
391 )
392 {
393  int start;
394 
395  assert(!allow_eq ||(eqstack != NULL && eqstack_size != NULL && eqmark != NULL));
396 
397  if( allow_eq )
398  {
399  if( SCIPisLE(scip, extedgecost, orgedgecost) )
400  {
401  if( SCIPisEQ(scip, extedgecost, orgedgecost) )
402  updateEqArrays(orgedge, eqstack, eqstack_size, eqmark);
403 
404  return TRUE;
405  }
406  }
407  else if( SCIPisLT(scip, extedgecost, orgedgecost) )
408  return TRUE;
409 
410  if( nodepos[graph->tail[extedge]] > graph->knots )
411  {
412  start = nodepos[graph->tail[extedge]] - 1 - graph->knots;
413  assert(start >= 0 && start <= 3);
414 
415  if( start <= 2 )
416  {
417  assert(basebottlenecks[start] > 0);
418 
419  if( SCIPisLT(scip, extedgecost, basebottlenecks[start]) )
420  return TRUE;
421  }
422  start = 0;
423  }
424  else
425  {
426  start = nodepos[graph->tail[extedge]]; /* not -1! We save the incoming bottlenecks */
427  assert(start >= 1 && start <= dfsdepth);
428  assert(start < dfsdepth || graph->tail[orgedge] == graph->tail[extedge]);
429 
430  }
431 
432  for( int i = start; i < dfsdepth; i++ )
433  {
434  assert(treecosts[i] >= 0.0);
435 
436  if( allow_eq )
437  {
438  if( SCIPisLE(scip, extedgecost, treecosts[i]) )
439  {
440  if( SCIPisEQ(scip, extedgecost, treecosts[i]) )
441  updateEqArrays(treeedges[i], eqstack, eqstack_size, eqmark);
442 
443  return TRUE;
444  }
445  }
446  else if( SCIPisLT(scip, extedgecost, treecosts[i]) )
447  return TRUE;
448  }
449 
450  return FALSE;
451 }
452 
453 /** can subtree be ruled out? */
454 static
456  SCIP* scip, /**< SCIP */
457  const GRAPH* graph, /**< graph data structure */
458  const SCIP_Real* treecosts, /**< costs of edges of the tree */
459  const SCIP_Real* basebottlenecks, /**< bottleneck costs for innode and basenode */
460  const int* nodepos, /**< node position in tree */
461  const int* treeedges, /**< edges in tree (corresponding to treecosts) */
462  SCIP_Real cutoff, /**< cut-off bound */
463  SCIP_Real extendedcost, /**< cost of subtree */
464  int dfsdepth, /**< dfs depth */
465  int curredge, /**< latest edge */
466  SCIP_Bool allowequality, /**< rule out also in case of equality */
467  const int* ancestormark, /**< ancestor mark array */
468  unsigned int* eqstack, /**< stores edges that were used for equality comparison */
469  int* eqstack_size, /**< pointer to size of eqstack */
470  SCIP_Bool* eqmark /**< marks edges that were used for equality comparison */
471 )
472 {
473 
474  if( allowequality ? (extendedcost >= cutoff) : SCIPisGT(scip, extendedcost, cutoff) )
475  {
476  return TRUE;
477  }
478  else
479  {
480  const SCIP_Bool pcmw = graph_pc_isPcMw(graph);
481  SCIP_Real currcost;
482  int currhead;
483 
484  if( ancestormark != NULL )
485  {
486  int count = 0;
487  for( IDX* curr = graph_edge_getAncestors(graph, curredge); curr != NULL && count <= EXT_ANCESTORS_MAX; curr = curr->parent, count++ )
488  {
489  assert(curr->index >= 0 && curr->index / 2 < (MAX(graph->edges, graph->orgedges) / 2));
490  if( ancestormark[((unsigned) curr->index) / 2] )
491  return TRUE;
492  }
493  }
494 
495  currcost = graph->cost[curredge];
496  currhead = graph->head[curredge];
497 
498  for( int e = graph->inpbeg[currhead]; e != EAT_LAST; e = graph->ieat[e] )
499  {
500  int tail;
501  SCIP_Real ecost;
502 
503  if( e == curredge )
504  continue;
505 
506  assert(flipedge(e) != curredge);
507 
508  tail = graph->tail[e];
509  ecost = graph->cost[e];
510 
511  if( nodepos[tail] )
512  {
513  const SCIP_Bool allow_eq = (eqmark != NULL && eqmark[((unsigned) e) / 2] == FALSE);
514  assert(graph->mark[tail]);
515 
516  if( bottleneckRuleOut(scip, graph, treecosts, basebottlenecks, nodepos, treeedges, currcost,
517  ecost, curredge, e, dfsdepth, allow_eq, eqstack, eqstack_size, eqmark) )
518  return TRUE;
519  }
520  else
521  {
522  const SCIP_Bool is_term = Is_term(graph->term[tail]);
523 
524  for( int e2 = graph->outbeg[tail], count = 0; e2 != EAT_LAST && count < RED_EXT_MAXGRAD;
525  e2 = graph->oeat[e2], count++ )
526  {
527  int head2;
528 
529  if( e2 == e )
530  continue;
531 
532  assert(flipedge(e2) != e && e2 != curredge && e2 != flipedge(curredge) );
533 
534  head2 = graph->head[e2];
535  assert(head2 != tail);
536 
537  if( nodepos[head2] )
538  {
539  SCIP_Real extcost = is_term ? MAX(ecost, graph->cost[e2]) : (ecost + graph->cost[e2]);
540  const SCIP_Bool allow_eq = (eqmark != NULL && eqmark[((unsigned) e) / 2] == FALSE && eqmark[((unsigned) e2) / 2] == FALSE);
541  assert(graph->mark[head2]);
542 
543  if( pcmw && is_term )
544  extcost = MAX(ecost + graph->cost[e2] - graph->prize[tail], extcost);
545 
546  assert(head2 != currhead);
547 
548  if( bottleneckRuleOut(scip, graph, treecosts, basebottlenecks,
549  nodepos, treeedges, currcost, extcost, curredge, flipedge(e2), dfsdepth, allow_eq, eqstack, eqstack_size, eqmark) )
550  {
551  return TRUE;
552  }
553  }
554  }
555  }
556  }
557  }
558 
559  return FALSE;
560 }
561 
562 /** check (directed) edge */
563 static
565  SCIP* scip, /**< SCIP data structure */
566  const GRAPH* graph, /**< graph data structure */
567  int root, /**< graph root from dual ascent */
568  const SCIP_Real* redcost, /**< reduced costs */
569  const SCIP_Real* pathdist, /**< shortest path distances */
570  const PATH* vnoi, /**< Voronoi paths */
571  SCIP_Real cutoff, /**< cutoff value */
572  int edge, /**< (directed) edge to be checked */
573  SCIP_Bool equality, /**< allow equality? */
574  int* edgestack, /**< array of size nodes for internal computations */
575  SCIP_Bool* deletable, /**< is edge deletable? */
576  unsigned int* eqstack, /**< stores edges that were used for equality comparison */
577  int* eqstack_size, /**< pointer to size of eqstack */
578  SCIP_Bool* eqmark /**< marks edges that were used for equality comparison */
579 )
580 {
581  const int head = graph->head[edge];
582  const int tail = graph->tail[edge];
583  const int maxgrad = (graph->edges > RED_EXT_EDGELIMIT) ? RED_EXT_MINGRAD : RED_EXT_MAXGRAD;
584  SCIP_Real edgebound = redcost[edge] + pathdist[tail] + vnoi[head].dist;
585 
586  assert(scip != NULL);
587  assert(graph != NULL);
588  assert(redcost != NULL);
589  assert(pathdist != NULL);
590  assert(vnoi != NULL);
591  assert(edge >= 0 && edge < graph->edges);
592 
593 #ifndef NDEBUG
594  if( !graph_pc_isPcMw(graph) )
595  for( int k = 0; k < graph->knots; k++ )
596  assert(graph->mark[k] == (graph->grad[k] > 0));
597 
598  assert(!graph_pc_isPcMw(graph) || !graph->extended);
599  assert(graph->mark[tail] && graph->mark[head]);
600 #endif
601 
602  *deletable = FALSE;
603 
604  /* trivial rule-out? */
605  if( SCIPisGT(scip, edgebound, cutoff) || (equality && SCIPisEQ(scip, edgebound, cutoff)) || head == root )
606  {
607  *deletable = TRUE;
608  }
609  else if( (graph->grad[tail] <= maxgrad && !Is_term(graph->term[tail]))
610  || (graph->grad[head] <= maxgrad && !Is_term(graph->term[head])) )
611  {
612  SCIP_Real treecosts[RED_EXT_MAXDFSDEPTH + 1];
613  int treeedges[RED_EXT_MAXDFSDEPTH + 1];
614  SCIP_Real basebottlenecks[3];
615  int* nodepos;
616  int* ancestormark;
617  const int nnodes = graph->knots;
618  const int maxdfsdepth = (graph->edges > RED_EXT_EDGELIMIT) ? RED_EXT_MINDFSDEPTH : RED_EXT_MAXDFSDEPTH;
619 
620  /* allocate clean arrays */
621  SCIP_CALL( SCIPallocCleanBufferArray(scip, &nodepos, nnodes) );
622  SCIP_CALL( SCIPallocCleanBufferArray(scip, &ancestormark, (MAX(graph->edges, graph->orgedges) / 2)) );
623 
624  basebottlenecks[0] = graph->cost[edge];
625 #ifndef NEBUG
626  basebottlenecks[1] = -1.0;
627  basebottlenecks[2] = -1.0;
628 
629  for( int i = 0; i < RED_EXT_MAXDFSDEPTH + 1; i++ )
630  {
631  treecosts[i] = -1.0;
632  treeedges[i] = -1;
633  }
634 #endif
635 
636  markAncestors(graph, edge, ancestormark);
637 
638  /* check whether to extend from head */
639  if( !Is_term(graph->term[head]) && graph->grad[head] <= maxgrad )
640  {
641  const SCIP_Real treecostoffset = redcost[edge] + pathdist[tail];
642  SCIP_Real minbound = FARAWAY;
643  SCIP_Real treecost = treecostoffset;
644  unsigned int rounds = 0;
645  int dfsdepth = 0;
646  int nadded_edges = 0;
647  SCIP_Bool stopped = FALSE;
648 
649  nodepos[tail] = nnodes + 1;
650  nodepos[head] = nnodes + 4;
651 
652  for( int e = graph->outbeg[head]; e != EAT_LAST; e = graph->oeat[e] )
653  {
654  const int head2 = graph->head[e];
655  if( head2 != tail && graph->mark[head2] )
656  edgestack[nadded_edges++] = e;
657  }
658 
659  /* limited DFS */
660  while( nadded_edges > 0 )
661  {
662  const int curredge = edgestack[--nadded_edges];
663  const int currhead = graph->head[curredge];
664 
665  assert(graph->mark[currhead]);
666 
667  /* subtree already processed? */
668  if( nodepos[currhead] )
669  {
670  assert(dfsdepth >= 1 && treeedges[dfsdepth - 1] == curredge);
671 
672  treecost = shortenSubtree(scip, graph, redcost, treeedges, treecost, treecostoffset, dfsdepth,
673  currhead, nodepos, ancestormark, &rounds);
674 
675  dfsdepth--;
676  }
677  else
678  {
679  const SCIP_Real extendedcost = treecost + redcost[curredge] + vnoi[currhead].dist;
680 
681  if( ruleOutSubtree(scip, graph, treecosts, basebottlenecks, nodepos, treeedges, cutoff, extendedcost, dfsdepth, curredge, equality,
682  ancestormark, eqstack, eqstack_size, eqmark) )
683  continue;
684 
685  if( truncateSubtree(graph, extendedcost, root, currhead, maxgrad, dfsdepth, maxdfsdepth, &minbound, &stopped) )
686  {
687  /* stopped and no further improvement of bound possible? */
688  if( stopped && minbound <= edgebound )
689  break;
690 
691  continue;
692  }
693 
694  nadded_edges = extendSubtreeHead(scip, graph, redcost, curredge, currhead, dfsdepth, nadded_edges, &treecost, treecosts, nodepos,
695  treeedges, edgestack, ancestormark);
696  dfsdepth++;
697  }
698  } /* DFS loop */
699 
700  assert(stopped || minbound == FARAWAY);
701  assert(SCIPisGE(scip, minbound, redcost[edge] + pathdist[tail] + vnoi[head].dist));
702 
703  finalizeSubtree(graph, graph->head, treeedges, dfsdepth, stopped, minbound, &edgebound, deletable, nodepos, ancestormark);
704  } /* extend from head */
705 
706  /* check whether to extend from tail */
707  if( !(*deletable) && !Is_term(graph->term[tail]) && graph->grad[tail] <= maxgrad )
708  {
709  const SCIP_Real treecostoffset = edgebound - pathdist[tail];
710  SCIP_Real minbound = FARAWAY;
711  SCIP_Real treecost = treecostoffset;
712  int dfsdepth = 0;
713  int nadded_edges = 0;
714  unsigned int rounds = 0;
715  SCIP_Bool stopped = FALSE;
716 
717  nodepos[head] = nnodes + 1;
718  nodepos[tail] = nnodes + 4;
719 
720  for( int e = graph->inpbeg[tail]; e != EAT_LAST; e = graph->ieat[e] )
721  {
722  const int tail2 = graph->tail[e];
723  if( tail2 != head && graph->mark[tail2] )
724  edgestack[nadded_edges++] = e;
725  }
726 
727  /* limited DFS */
728  while( nadded_edges > 0 )
729  {
730  const int curredge = edgestack[--nadded_edges];
731  const int currtail = graph->tail[curredge];
732  assert(graph->mark[currtail]);
733 
734  /* subtree already processed? */
735  if( nodepos[currtail] )
736  {
737  assert(dfsdepth >= 1 && treeedges[dfsdepth - 1] == curredge);
738 
739  treecost = shortenSubtree(scip, graph, redcost, treeedges, treecost, treecostoffset, dfsdepth,
740  currtail, nodepos, ancestormark, &rounds);
741 
742  dfsdepth--;
743  }
744  else
745  {
746  const SCIP_Real extendedcost = treecost + redcost[curredge] + pathdist[currtail];
747 
748  if( ruleOutSubtree(scip, graph, treecosts, basebottlenecks, nodepos, treeedges, cutoff, extendedcost, dfsdepth, flipedge(curredge), equality,
749  ancestormark, eqstack, eqstack_size, eqmark) )
750  continue;
751 
752  if( truncateSubtree(graph, extendedcost, -1, currtail, maxgrad, dfsdepth, maxdfsdepth, &minbound, &stopped) )
753  {
754  if( stopped )
755  break;
756  continue;
757  }
758 
759  nadded_edges = extendSubtreeTail(graph, redcost, curredge, currtail, dfsdepth, nadded_edges, &treecost, treecosts, nodepos, treeedges,
760  edgestack, ancestormark);
761  dfsdepth++;
762  }
763  } /* DFS loop */
764 
765  assert(stopped || minbound == FARAWAY);
766  assert(SCIPisGE(scip, minbound, redcost[edge] + pathdist[tail] + vnoi[head].dist));
767 
768  finalizeSubtree(graph, graph->tail, treeedges, dfsdepth, stopped, minbound, &edgebound, deletable, nodepos, ancestormark);
769  } /* extend from tail */
770 
771  /* clean arrays */
772  nodepos[head] = 0;
773  nodepos[tail] = 0;
774  unmarkAncestors(graph, edge, ancestormark);
775 
776  /* free memory */
777  for( int i = 0; i < nnodes; i++ )
778  assert(nodepos[i] == 0);
779  for( int i = 0; i < MAX(graph->edges, graph->orgedges) / 2; i++ )
780  assert(ancestormark[i] == 0);
781 
782  SCIPfreeCleanBufferArray(scip, &ancestormark);
783  SCIPfreeCleanBufferArray(scip, &nodepos);
784  }
785 
786  return SCIP_OKAY;
787 }
788 
789 
790 /** todo don't use this function, but check for conflicts in misc_stp.c and handle them */
792  SCIP* scip, /**< SCIP data structure */
793  GRAPH* g /**< the graph */
794 )
795 {
796  int* edgemark;
797  const int nedges = g->edges;
798  const int nancestors = MAX(g->edges, g->orgedges) / 2;
799  const SCIP_Bool pcmw = graph_pc_isPcMw(g);
800 
801  assert(scip != NULL && g != NULL);
802  assert(g->ancestors != NULL);
803  assert(!graph_pc_isPcMw(g) || !g->extended);
804 
805  SCIP_CALL( SCIPallocBufferArray(scip, &edgemark, nancestors) );
806 
807  for( int e = 0; e < nancestors; e++ )
808  edgemark[e] = FALSE;
809 
810  for( int e = 0; e < nedges; e += 2 )
811  {
812  SCIP_Bool conflict;
813 
814  if( g->oeat[e] == EAT_FREE )
815  continue;
816 
817  if( pcmw && g->cost[e] != g->cost[e + 1] )
818  continue;
819 
820  conflict = markAncestorsConflict(g, e, edgemark);
821 
822  unmarkAncestorsConflict(g, e, edgemark);
823  if( conflict )
824  {
825  conflict = markAncestorsConflict(g, e + 1, edgemark);
826  unmarkAncestorsConflict(g, e + 1, edgemark);
827 
828  if( conflict )
829  {
830  assert(!graph_pc_isPcMw(g) || (!Is_pseudoTerm(g->term[g->head[e]]) && !Is_pseudoTerm(g->term[g->tail[e]])));
831  graph_edge_del(scip, g, e, TRUE);
832  }
833  }
834  }
835 
836  SCIPfreeBufferArray(scip, &edgemark);
837 
838  return SCIP_OKAY;
839 }
840 
841 /** check 3-tree */
843  SCIP* scip, /**< SCIP data structure */
844  const GRAPH* graph, /**< graph data structure */
845  int root, /**< graph root from dual ascent */
846  const SCIP_Real* redcost, /**< reduced costs */
847  const SCIP_Real* pathdist, /**< shortest path distances */
848  const PATH* vnoi, /**< Voronoi paths */
849  const int* vbase, /**< bases to Voronoi paths */
850  SCIP_Real cutoff, /**< cutoff value */
851  const int* outedges, /**< two outgoing edge */
852  int inedge, /**< incoming edge */
853  SCIP_Real* treebound, /**< to store a lower bound for the tree */
854  SCIP_Bool* ruleout, /**< could tree be ruled out? */
855  unsigned int* eqstack, /**< stores edges that were used for equality comparison */
856  int* eqstack_size, /**< pointer to size of eqstack */
857  SCIP_Bool* eqmark /**< marks edges that were used for equality comparison */
858 )
859 {
860  int* edgestack;
861 #ifndef NDEBUG
862  const SCIP_Real orgtreebound = *treebound;
863 #endif
864  assert(scip != NULL);
865  assert(graph != NULL);
866  assert(redcost != NULL);
867  assert(ruleout != NULL);
868  assert(pathdist != NULL);
869  assert(vnoi != NULL);
870  assert(vbase != NULL);
871  assert(outedges != NULL);
872  assert(inedge >= 0 && outedges[0] >= 0 && outedges[1] >= 0);
873  assert(inedge < graph->edges && outedges[0] < graph->edges && outedges[1] < graph->edges);
874 
875  SCIP_CALL( SCIPallocBufferArray(scip, &edgestack, graph->knots) );
876 
877  /* trivial rule-out? */
878  if( SCIPisGT(scip, *treebound, cutoff) )
879  {
880  *ruleout = TRUE;
881  }
882  else
883  {
884  SCIP_Real treecosts[RED_EXT_MAXDFSDEPTH + 1];
885  int treeedges[RED_EXT_MAXDFSDEPTH + 1];
886  SCIP_Real basebottlenecks[3];
887  const SCIP_Real basecost = redcost[inedge] + redcost[outedges[0]] + redcost[outedges[1]] + pathdist[graph->tail[inedge]];
888  int* nodepos;
889  int* ancestormark;
890  const int nnodes = graph->knots;
891  const int innode = graph->tail[inedge];
892  const int basenode = graph->head[inedge];
893  const int maxdfsdepth = (graph->edges > RED_EXT_EDGELIMIT) ? RED_EXT_MINDFSDEPTH : RED_EXT_MAXDFSDEPTH;
894  const int maxgrad = (graph->edges > RED_EXT_EDGELIMIT) ? RED_EXT_MINGRAD : RED_EXT_MAXGRAD;
895 
896  assert(basenode == graph->tail[outedges[0]] && basenode == graph->tail[outedges[1]]);
897 
898  /* allocate clean array */
899  SCIP_CALL(SCIPallocCleanBufferArray(scip, &nodepos, nnodes));
900  SCIP_CALL( SCIPallocCleanBufferArray(scip, &ancestormark, (MAX(graph->edges, graph->orgedges) / 2)) );
901 
902  nodepos[basenode] = nnodes + 1; /* basenode */
903  nodepos[innode] = nnodes + 2; /* innode */
904 
905 #ifndef NDEBUG
906  for( int i = 0; i < RED_EXT_MAXDFSDEPTH + 1; i++ )
907  {
908  treecosts[i] = -1.0;
909  treeedges[i] = -1;
910  }
911 #endif
912 
913  *ruleout = FALSE;
914 
915  /* can we rule out subgraph beforehand? */
916  if( markAncestorsConflict(graph, inedge, ancestormark)
917  || markAncestorsConflict(graph, outedges[0], ancestormark)
918  || markAncestorsConflict(graph, outedges[1], ancestormark) )
919  {
920  *ruleout = TRUE;
921  }
922 
923  /* main loop: extend tree and try to rule it out */
924  for( int i = 0; i < 2 && !(*ruleout); i++ )
925  {
926  SCIP_Real minbound = FARAWAY;
927  SCIP_Real treecost = basecost;
928  const int startedge = outedges[i];
929  const int costartedge = outedges[(i + 1) % 2];
930  const int startnode = graph->head[startedge];
931  const int costartnode = graph->head[costartedge];
932  int dfsdepth = 0;
933  int nadded_edges = 0;
934  SCIP_Bool stopped = FALSE;
935  unsigned int rounds = 0;
936 
937  /* try to extend the tree from startnode */
938 
939  assert(startnode != root && costartnode != root);
940 
941  /* for basenode */
942  basebottlenecks[0] = graph->cost[startedge];
943 
944  /* for innode */
945  basebottlenecks[1] = MAX(graph->cost[startedge], graph->cost[inedge]);
946 
947  /* for costartnode */
948  basebottlenecks[2] = MAX(graph->cost[startedge], graph->cost[costartedge]);
949 
950  nodepos[costartnode] = nnodes + 3;
951  nodepos[startnode] = nnodes + 4;
952 
953  /* can we rule out entire subtree already? */
954  if( ruleOutSubtree(scip, graph, treecosts, basebottlenecks, nodepos, treeedges, FARAWAY, 0.0, 0, startedge, FALSE,
955  NULL, NULL, NULL, NULL) )
956  {
957  *ruleout = TRUE;
958  break;
959  }
960 
961  /* cannot extend over terminals or vertices of high degree */
962  if( Is_term(graph->term[startnode]) || graph->grad[startnode] > maxgrad )
963  continue;
964 
965  assert(nodepos[startnode]);
966 
967  for( int e = graph->outbeg[startnode]; e != EAT_LAST; e = graph->oeat[e] )
968  if( !nodepos[graph->head[e]] )
969  edgestack[nadded_edges++] = e;
970 
971  /* limited DFS starting from startnode */
972  while ( nadded_edges > 0 )
973  {
974  const int curredge = edgestack[--nadded_edges];
975  const int currhead = graph->head[curredge];
976 
977  /* subtree already processed? */
978  if( nodepos[currhead] )
979  {
980  assert(dfsdepth >= 1 && treeedges[dfsdepth - 1] == curredge);
981 
982  treecost = shortenSubtree(scip, graph, redcost, treeedges, treecost, basecost, dfsdepth,
983  currhead, nodepos, ancestormark, &rounds);
984 
985  dfsdepth--;
986  }
987  else
988  {
989  SCIP_Real extendedcost = treecost + redcost[curredge];
990 
991  if( vbase[costartnode] == vbase[currhead] )
992  {
993  /* also covers the case that leaf is a terminal */
994  const SCIP_Real costartfar = vnoi[costartnode + nnodes].dist;
995  const SCIP_Real currentfar = vnoi[currhead + nnodes].dist;
996 
997  assert(vbase[costartnode + nnodes] >= 0 || costartfar == FARAWAY);
998  assert(vbase[currhead + nnodes] >= 0 || currentfar == FARAWAY);
999  extendedcost += MIN(costartfar + vnoi[currhead].dist, vnoi[costartnode].dist + currentfar);
1000  }
1001  else
1002  extendedcost += vnoi[costartnode].dist + vnoi[currhead].dist;
1003 
1004  /* can we rule out subtree? */
1005  if( ruleOutSubtree(scip, graph, treecosts, basebottlenecks, nodepos, treeedges, cutoff, extendedcost, dfsdepth, curredge, FALSE,
1006  ancestormark, eqstack, eqstack_size, eqmark) )
1007  continue;
1008 
1009  /* do we need to stop extension? */
1010  if( truncateSubtree(graph, extendedcost, root, currhead, maxgrad, dfsdepth, maxdfsdepth, &minbound, &stopped) )
1011  {
1012  if( stopped && minbound <= (*treebound) )
1013  break;
1014 
1015  continue;
1016  }
1017 
1018  nadded_edges = extendSubtreeHead(scip, graph, redcost, curredge, currhead, dfsdepth, nadded_edges, &treecost, treecosts, nodepos,
1019  treeedges, edgestack, ancestormark);
1020  dfsdepth++;
1021  }
1022  } /* DFS loop */
1023 
1024  assert(stopped || minbound == FARAWAY);
1025 #ifndef NDEBUG
1026  assert(SCIPisGE(scip, minbound, orgtreebound));
1027 #endif
1028 
1029  finalizeSubtree(graph, graph->head, treeedges, dfsdepth, stopped, minbound, treebound, ruleout, nodepos, ancestormark);
1030  } /* main loop for outgoing edges */
1031 
1032 #ifndef NDEBUG
1033  assert(*treebound >= orgtreebound);
1034 #endif
1035 
1036  if( !(*ruleout) && !Is_term(graph->term[innode]) && graph->grad[innode] <= maxgrad )
1037  {
1038  /* move down the incoming edge */
1039  const SCIP_Real treecostoffset = *treebound - pathdist[innode];
1040  SCIP_Real minbound = FARAWAY;
1041  SCIP_Real treecost = treecostoffset;
1042  int dfsdepth = 0;
1043  int nadded_edges = 0;
1044  SCIP_Bool stopped = FALSE;
1045  unsigned int rounds = 0;
1046 
1047  assert(treecost >= 0.0);
1048  assert(nodepos[innode] == nnodes + 2);
1049  assert(nodepos[basenode] == nnodes + 1);
1050 
1051  nodepos[graph->head[outedges[0]]] = nnodes + 2;
1052  nodepos[graph->head[outedges[1]]] = nnodes + 3;
1053  nodepos[innode] = nnodes + 4;
1054 
1055  /* for basenode */
1056  basebottlenecks[0] = graph->cost[inedge];
1057 
1058  /* for outedges[0] */
1059  basebottlenecks[1] = MAX(graph->cost[outedges[0]], graph->cost[inedge]);
1060 
1061  /* for outedges[1] */
1062  basebottlenecks[2] = MAX(graph->cost[outedges[1]], graph->cost[inedge]);
1063 
1064  /* can we rule out entire subtree already? */
1065  if( ruleOutSubtree(scip, graph, treecosts, basebottlenecks, nodepos, treeedges, FARAWAY, 0.0, 0, flipedge(inedge), FALSE,
1066  NULL, NULL, NULL, NULL) )
1067  {
1068  *ruleout = TRUE;
1069  }
1070  else
1071  {
1072  for( int e = graph->inpbeg[innode]; e != EAT_LAST; e = graph->ieat[e] )
1073  if( !nodepos[graph->tail[e]] )
1074  edgestack[nadded_edges++] = e;
1075  }
1076 
1077  /* limited DFS starting from inedge */
1078  while( nadded_edges > 0 )
1079  {
1080  const int curredge = edgestack[--nadded_edges];
1081  const int currtail = graph->tail[curredge];
1082 
1083  /* subtree already processed? */
1084  if( nodepos[currtail] )
1085  {
1086  assert(dfsdepth >= 1 && treeedges[dfsdepth - 1] == curredge);
1087 
1088  treecost = shortenSubtree(scip, graph, redcost, treeedges, treecost, treecostoffset, dfsdepth,
1089  currtail, nodepos, ancestormark, &rounds);
1090 
1091  dfsdepth--;
1092  }
1093  else
1094  {
1095  const SCIP_Real extendedcost = treecost + redcost[curredge] + pathdist[currtail];
1096 
1097  if( ruleOutSubtree(scip, graph, treecosts, basebottlenecks, nodepos, treeedges, cutoff, extendedcost, dfsdepth, flipedge((unsigned)curredge), FALSE,
1098  ancestormark, eqstack, eqstack_size, eqmark) )
1099  continue;
1100 
1101  if( truncateSubtree(graph, extendedcost, -1, currtail, maxgrad, dfsdepth, maxdfsdepth, &minbound, &stopped) )
1102  {
1103  if( stopped && minbound <= (*treebound) )
1104  break;
1105 
1106  continue;
1107  }
1108 
1109  nadded_edges = extendSubtreeTail(graph, redcost, curredge, currtail, dfsdepth, nadded_edges, &treecost, treecosts, nodepos,
1110  treeedges, edgestack, ancestormark);
1111  dfsdepth++;
1112  }
1113  } /* DFS loop */
1114 
1115 #ifndef NDEBUG
1116  assert(stopped || minbound == FARAWAY);
1117  assert(SCIPisGE(scip, minbound, orgtreebound));
1118 #endif
1119 
1120  finalizeSubtree(graph, graph->tail, treeedges, dfsdepth, stopped, minbound, treebound, ruleout, nodepos, ancestormark);
1121  } /* inedge */
1122 
1123  /* clean nodepos array */
1124  nodepos[basenode] = 0;
1125  nodepos[innode] = 0;
1126 
1127  unmarkAncestorsConflict(graph, inedge, ancestormark);
1128 
1129  for( int i = 0; i < 2; i++ )
1130  {
1131  nodepos[graph->head[outedges[i]]] = 0;
1132  unmarkAncestorsConflict(graph, outedges[i], ancestormark);
1133  }
1134 
1135 #ifndef NDEBUG
1136  assert(*treebound >= orgtreebound);
1137 
1138  for( int i = 0; i < nnodes; i++ )
1139  assert(nodepos[i] == 0);
1140 
1141  for( int i = 0; i < MAX(graph->edges, graph->orgedges) / 2; i++ )
1142  assert(ancestormark[i] == 0);
1143 #endif
1144 
1145  SCIPfreeCleanBufferArray(scip, &ancestormark);
1146  SCIPfreeCleanBufferArray(scip, &nodepos);
1147  }
1148 
1149  SCIPfreeBufferArray(scip, &edgestack);
1150 
1151  return SCIP_OKAY;
1152 }
1153 
1154 /** reduce SPG graph based on reduced cost information and given upper bound todo to be deleted and replaced by reduce_extendedEdge2 */
1156  SCIP* scip, /**< SCIP data structure */
1157  GRAPH* graph, /**< graph data structure */
1158  const PATH* vnoi, /**< Voronoi data structure */
1159  const SCIP_Real* cost, /**< dual ascent costs */
1160  const SCIP_Real* pathdist, /**< distance array from shortest path calculations */
1161  const int* result, /**< sol int array */
1162  SCIP_Real minpathcost, /**< the required reduced path cost to be surpassed */
1163  int root, /**< the root */
1164  STP_Bool* marked, /**< edge array to mark which (directed) edge can be removed */
1165  SCIP_Bool markdirected /**< try to also mark edge if anti-parallel is not marked */
1166 )
1167 {
1168  int* nodearr;
1169  unsigned int* eqstack;
1170  SCIP_Bool* eqmark;
1171  int nfixed = 0;
1172  const int nedges = graph->edges;
1173  const int nnodes = graph->knots;
1174  const int halfnedges = graph->edges / 2;
1175  const SCIP_Bool pcmw = graph_pc_isPcMw(graph);
1176 
1177  assert(marked != NULL);
1178  assert(!pcmw || !graph->extended);
1179 
1180  if( SCIPisZero(scip, minpathcost) )
1181  return 0;
1182 
1183  SCIP_CALL( SCIPallocCleanBufferArray(scip, &eqmark, halfnedges) );
1184  SCIP_CALL( SCIPallocBufferArray(scip, &eqstack, halfnedges) );
1185  SCIP_CALL( SCIPallocBufferArray(scip, &nodearr, nnodes) );
1186 
1187  if( !pcmw )
1188  for( int k = 0; k < nnodes; k++ )
1189  graph->mark[k] = (graph->grad[k] > 0);
1190 
1191  /* main loop */
1192  for( int e = 0; e < nedges; e += 2 )
1193  {
1194  const int erev = e + 1;
1195 
1196  if( pcmw && !SCIPisEQ(scip, graph->cost[e], graph->cost[erev]) )
1197  continue;
1198 
1199  if( graph->oeat[e] != EAT_FREE )
1200  {
1201  int eqstack_size = 0;
1202  SCIP_Bool deletable = TRUE;
1203  const SCIP_Bool allowequality = (result != NULL && result[e] != CONNECT && result[erev] != CONNECT);
1204 
1205  assert(graph->oeat[erev] != EAT_FREE);
1206 
1207  if( SCIPisZero(scip, cost[e]) || SCIPisZero(scip, cost[erev]) )
1208  continue;
1209 
1210  if( !marked[e] )
1211  {
1212  SCIP_CALL_ABORT(reduceCheckEdge(scip, graph, root, cost, pathdist, vnoi, minpathcost, e, allowequality, nodearr,
1213  &deletable, eqstack, &eqstack_size, eqmark));
1214 
1215  if( deletable )
1216  marked[e] = TRUE;
1217  }
1218 
1219  if( !marked[erev] && (deletable || markdirected) )
1220  {
1221  SCIP_Bool erevdeletable = TRUE;
1222  SCIP_CALL_ABORT(reduceCheckEdge(scip, graph, root, cost, pathdist, vnoi, minpathcost, erev, allowequality,
1223  nodearr, &erevdeletable, eqstack, &eqstack_size, eqmark));
1224 
1225  if( erevdeletable )
1226  marked[erev] = TRUE;
1227 
1228  deletable = (deletable && erevdeletable);
1229  }
1230 
1231  for( int i = 0; i < eqstack_size; i++ )
1232  eqmark[eqstack[i]] = FALSE;
1233 
1234  for( int i = 0; i < halfnedges; i++ )
1235  assert(eqmark[i] == FALSE);
1236 
1237  if( deletable )
1238  {
1239  removeEdge(scip, e, graph);
1240 
1241  nfixed++;
1242  }
1243  }
1244  }
1245 
1246  SCIPfreeBufferArray(scip, &nodearr);
1247  SCIPfreeBufferArray(scip, &eqstack);
1248  SCIPfreeCleanBufferArray(scip, &eqmark);
1249 
1250 #ifndef NDEBUG
1251  for( int k = 0; k < nnodes; k++ )
1252  if( graph->grad[k] == 0 && k != root )
1253  assert(!graph->mark[k]|| (Is_term(graph->term[k]) && graph_pc_isPcMw(graph)));
1254 #endif
1255 
1256  return nfixed;
1257 }
static SCIP_Bool ruleOutSubtree(SCIP *scip, const GRAPH *graph, const SCIP_Real *treecosts, const SCIP_Real *basebottlenecks, const int *nodepos, const int *treeedges, SCIP_Real cutoff, SCIP_Real extendedcost, int dfsdepth, int curredge, SCIP_Bool allowequality, const int *ancestormark, unsigned int *eqstack, int *eqstack_size, SCIP_Bool *eqmark)
Definition: reduce_ext.c:455
static SCIP_Bool markAncestorsConflict(const GRAPH *graph, int edge, int *ancestormark)
Definition: reduce_ext.c:84
SCIP_RETCODE reduce_extendedCheck3Tree(SCIP *scip, const GRAPH *graph, int root, const SCIP_Real *redcost, const SCIP_Real *pathdist, const PATH *vnoi, const int *vbase, SCIP_Real cutoff, const int *outedges, int inedge, SCIP_Real *treebound, SCIP_Bool *ruleout, unsigned int *eqstack, int *eqstack_size, SCIP_Bool *eqmark)
Definition: reduce_ext.c:842
int *RESTRICT head
Definition: graphdefs.h:224
void graph_edge_del(SCIP *, GRAPH *, int, SCIP_Bool)
Definition: graph_edge.c:368
int source
Definition: graphdefs.h:195
#define Is_term(a)
Definition: graphdefs.h:102
static SCIP_Bool bottleneckRuleOut(SCIP *scip, const GRAPH *graph, const SCIP_Real *treecosts, const SCIP_Real *basebottlenecks, const int *nodepos, const int *treeedges, SCIP_Real orgedgecost, SCIP_Real extedgecost, int orgedge, int extedge, int dfsdepth, SCIP_Bool allow_eq, unsigned int *eqstack, int *eqstack_size, SCIP_Bool *eqmark)
Definition: reduce_ext.c:375
static void removeEdge(SCIP *scip, int edge, GRAPH *graph)
Definition: reduce_ext.c:47
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define EAT_FREE
Definition: graphdefs.h:57
#define FALSE
Definition: def.h:87
int *RESTRICT inpbeg
Definition: graphdefs.h:202
static int extendSubtreeTail(const GRAPH *graph, const SCIP_Real *redcost, int curredge, int currtail, int dfsdepth, int nadded_edges, SCIP_Real *treecost, SCIP_Real *treecosts, int *nodepos, int *treeedges, int *edgestack, int *ancestormark)
Definition: reduce_ext.c:315
#define EXT_ANCESTORS_MAX
Definition: reduce_ext.c:36
#define TRUE
Definition: def.h:86
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
includes various files containing graph methods used for Steiner tree problems
#define EAT_LAST
Definition: graphdefs.h:58
#define FARAWAY
Definition: graphdefs.h:89
static void unmarkAncestorsConflict(const GRAPH *graph, int edge, int *ancestormark)
Definition: reduce_ext.c:130
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:127
static SCIP_RETCODE reduceCheckEdge(SCIP *scip, const GRAPH *graph, int root, const SCIP_Real *redcost, const SCIP_Real *pathdist, const PATH *vnoi, SCIP_Real cutoff, int edge, SCIP_Bool equality, int *edgestack, SCIP_Bool *deletable, unsigned int *eqstack, int *eqstack_size, SCIP_Bool *eqmark)
Definition: reduce_ext.c:564
#define RED_EXT_MINGRAD
Definition: reduce_ext.c:41
int *RESTRICT mark
Definition: graphdefs.h:198
#define SCIPallocCleanBufferArray(scip, ptr, num)
Definition: scip_mem.h:133
int *RESTRICT oeat
Definition: graphdefs.h:231
SCIP_RETCODE reduce_deleteConflictEdges(SCIP *scip, GRAPH *g)
Definition: reduce_ext.c:791
SCIP_Bool extended
Definition: graphdefs.h:267
IDX ** ancestors
Definition: graphdefs.h:234
int orgedges
Definition: graphdefs.h:220
static void markAncestors(const GRAPH *graph, int edge, int *ancestormark)
Definition: reduce_ext.c:110
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define RED_EXT_EDGELIMIT
Definition: reduce_ext.c:42
SCIP_Real * prize
Definition: graphdefs.h:210
SCIP_Real dist
Definition: graphdefs.h:286
int *RESTRICT grad
Definition: graphdefs.h:201
#define NULL
Definition: lpi_spx1.cpp:155
int reduce_extendedEdge(SCIP *scip, GRAPH *graph, const PATH *vnoi, const SCIP_Real *cost, const SCIP_Real *pathdist, const int *result, SCIP_Real minpathcost, int root, STP_Bool *marked, SCIP_Bool markdirected)
Definition: reduce_ext.c:1155
int knots
Definition: graphdefs.h:190
#define SCIP_CALL(x)
Definition: def.h:384
unsigned char STP_Bool
Definition: portab.h:34
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:115
#define SCIP_Bool
Definition: def.h:84
int *RESTRICT ieat
Definition: graphdefs.h:230
static int extendSubtreeHead(SCIP *scip, const GRAPH *graph, const SCIP_Real *redcost, int curredge, int currhead, int dfsdepth, int nadded_edges, SCIP_Real *treecost, SCIP_Real *treecosts, int *nodepos, int *treeedges, int *edgestack, int *ancestormark)
Definition: reduce_ext.c:278
int *RESTRICT tail
Definition: graphdefs.h:223
#define flipedge(edge)
Definition: graphdefs.h:84
#define MAX(x, y)
Definition: tclique_def.h:83
static SCIP_Bool truncateSubtree(const GRAPH *graph, SCIP_Real extendedcost, int root, int currhead, int maxgrad, int dfsdepth, int maxdfsdepth, SCIP_Real *minbound, SCIP_Bool *stopped)
Definition: reduce_ext.c:208
#define RED_EXT_MAXDFSDEPTH
Definition: reduce_ext.c:38
static SCIP_Real shortenSubtree(SCIP *scip, const GRAPH *graph, const SCIP_Real *redcost, const int *treeedges, SCIP_Real treecostold, SCIP_Real treecostoffset, int dfsdepth, int lastnode, int *nodepos, int *ancestormark, unsigned int *nstallrounds)
Definition: reduce_ext.c:238
int *RESTRICT term
Definition: graphdefs.h:196
#define CONNECT
Definition: graphdefs.h:87
#define Is_pseudoTerm(a)
Definition: graphdefs.h:103
#define RED_EXT_MAXGRAD
Definition: reduce_ext.c:40
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
static void updateEqArrays(int edge, unsigned int *eqstack, int *eqstack_size, SCIP_Bool *eqmark)
Definition: reduce_ext.c:352
SCIP_Real * cost
Definition: graphdefs.h:221
#define RED_EXT_MINDFSDEPTH
Definition: reduce_ext.c:39
SCIP_Bool graph_pc_isPcMw(const GRAPH *)
static void finalizeSubtree(const GRAPH *graph, const int *edgeends, const int *treeedges, int dfsdepth, SCIP_Bool stopped, SCIP_Real localbound, SCIP_Real *globalbound, SCIP_Bool *ruleout, int *nodepos, int *ancestormark)
Definition: reduce_ext.c:170
#define SCIP_Real
Definition: def.h:177
#define SCIPfreeCleanBufferArray(scip, ptr)
Definition: scip_mem.h:137
int *RESTRICT outbeg
Definition: graphdefs.h:204
int edges
Definition: graphdefs.h:219
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define nnodes
Definition: gastrans.c:65
#define SCIP_CALL_ABORT(x)
Definition: def.h:363
static void unmarkAncestors(const GRAPH *graph, int edge, int *ancestormark)
Definition: reduce_ext.c:148
includes various reduction methods for Steiner tree problems
IDX * graph_edge_getAncestors(const GRAPH *, int)