Scippy

SCIP

Solving Constraint Integer Programs

extreduce_core.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 extreduce_core.c
17  * @brief extended reduction techniques for Steiner tree problems
18  * @author Daniel Rehfeldt
19  *
20  * This file implements the core algorithms for the extended reduction techniques, namely for the tree search.
21  * Starting from a given component (e.g. a single edge), a number of possible extensions are checked to be able
22  * to verify that this component is not part of at least one optimal solution.
23  *
24  * A list of all interface methods can be found in extreduce.h.
25  *
26  */
27 
28 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
29 // #define SCIP_DEBUG
30 // #define STP_DEBUG_EXT
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <assert.h>
35 #include "graph.h"
36 #include "portab.h"
37 #include "extreduce.h"
38 #include "extreducedefs.h"
39 
40 
41 #define EXT_COSTS_RECOMPBOUND 10
42 
43 /*
44  * Local methods
45  */
46 
47 
48 /** gets next subset of given size, returns FALSE if no further subset possible, otherwise TRUE */
49 static inline
51  int k, /**< size of subset */
52  int n, /**< size of underlying set */
53  SCIP_Bool isFirstSubset, /**< first call? */
54  int* ksubset /**< the k-subset IN/OUT */
55 )
56 {
57  assert(0 < k && k <= n);
58 
59  if( isFirstSubset )
60  {
61  for( int i = 0; i < k; i++ )
62  ksubset[i] = i;
63 
64  return TRUE;
65  }
66 
67  for( int i = k - 1; i >= 0; i-- )
68  {
69  /* can index be incremented? */
70  if( ksubset[i] < n - k + i )
71  {
72  ksubset[i]++;
73 
74  /* set right entries in incremental order */
75  while( ++i < k )
76  ksubset[i] = ksubset[i - 1] + 1;
77 
78  return TRUE;
79  }
80  }
81 
82  return FALSE;
83 }
84 
85 
86 /** are the given extension vertices in conflict with the extension conditions? */
87 static inline
89  const GRAPH* graph, /**< graph data structure */
90  const STP_Vectype(int) implications, /**< implications for extroot */
91  const int* tree_deg, /**< tree degree or NULL */
92  int tree_root, /**< tree root */
93  const int* extedges, /**< extension edges */
94  int nextedges /**< number of extension edges */
95 )
96 {
97  const int nimplications = StpVecGetSize(implications);
98 
99  assert(nextedges > 0);
100  assert(graph_knot_isInRange(graph, tree_root));
101 
102  for( int i = 0; i < nimplications; i++ )
103  {
104  int j;
105  const int impnode = implications[i];
106  assert(graph_knot_isInRange(graph, impnode));
107  assert(Is_term(graph->term[impnode]));
108 
109  if( tree_root == impnode )
110  continue;
111 
112  if( tree_deg && tree_deg[impnode] > 0 )
113  continue;
114 
115  for( j = 0; j < nextedges; j++ )
116  {
117  const int extnode = graph->head[extedges[j]];
118  assert(graph_knot_isInRange(graph, extnode));
119 
120  if( impnode == extnode )
121  break;
122  }
123 
124  /* implication node not contained in extension nodes? */
125  if( j == nextedges )
126  {
127  return TRUE;
128  }
129  }
130 
131  return FALSE;
132 }
133 
134 /** returns position of last marked component before the current one */
135 static inline
137  const EXTDATA* extdata /**< extension data */
138 )
139 {
140  const int* const extstack_state = extdata->extstack_state;
141  int stackpos = extStackGetPosition(extdata) - 1;
142 
143  assert(stackpos >= 0);
144 
145  while( extstack_state[stackpos] != EXT_STATE_MARKED )
146  {
147  stackpos--;
148  assert(stackpos >= 0);
149  }
150 
151  return stackpos;
152 }
153 
154 
155 /** can the extension stack hold new components? */
156 static inline
158  int nextedges, /**< number of edges for extension */
159  int nnewcomps, /**< number of new components */
160  int stack_datasize, /**< datasize of stack */
161  const EXTDATA* extdata /**< extension data */
162 )
163 {
164  const int newstacksize_upper = (stack_datasize + nnewcomps * (nextedges + 1) / 2);
165  const int newncomponents_upper = extdata->extstack_ncomponents + nnewcomps;
166 
167  if( newstacksize_upper > extdata->extstack_maxsize || newncomponents_upper >= extdata->extstack_maxncomponents )
168  {
169  assert(extdata->extstack_state[extStackGetPosition(extdata)] == EXT_STATE_NONE);
170 
171  SCIPdebugMessage("stack too full, cannot expand \n");
172 
173  return FALSE;
174  }
175 
176  return TRUE;
177 }
178 
179 
180 /** Adds non-expanded components (i.e. sets of edges extending at a certain leaf) to the stack.
181  * Components are ordered such that smallest component is added last. */
182 static inline
184  const GRAPH* graph, /**< graph data structure */
185  const int* extedgesstart, /**< starts of extension edges for one components */
186  const int* extedges, /**< extensions edges */
187  int nextendable_leaves, /**< number of leaves that can be extended */
188  EXTDATA* extdata /**< extension data */
189  )
190 {
191  int* const extstack_data = extdata->extstack_data;
192  int* const extstack_start = extdata->extstack_start;
193  int* const extstack_state = extdata->extstack_state;
194  int stackpos = extStackGetPosition(extdata);
195  int datasize = extstack_start[stackpos + 1];
196  int extsize[STP_EXT_MAXGRAD];
197  int extindex[STP_EXT_MAXGRAD];
198 
199  assert(nextendable_leaves > 0);
200  assert(extedgesstart[nextendable_leaves] - extedgesstart[0] > 0);
201  assert(datasize + (extedgesstart[nextendable_leaves] - extedgesstart[0]) <= extdata->extstack_maxsize);
202 
203  for( int i = 0; i < nextendable_leaves; i++ )
204  {
205  assert(extedgesstart[i + 1] >= 0);
206 
207  extsize[i] = extedgesstart[i + 1] - extedgesstart[i];
208  extindex[i] = i;
209  assert(extsize[i] >= 0);
210  }
211 
212  SCIPsortDownIntInt(extsize, extindex, nextendable_leaves);
213 
214  /* put the non-empty extensions on the stack, with smallest last */
215  for( int i = 0; i < nextendable_leaves; i++ )
216  {
217  const int index = extindex[i];
218 
219  if( extsize[i] == 0 )
220  {
221 #ifndef NDEBUG
222  assert(i > 0);
223  assert(extedgesstart[index + 1] - extedgesstart[index] == 0);
224 
225  for( int j = i; j < nextendable_leaves; j++ )
226  assert(extsize[j] == 0);
227 #endif
228 
229  break;
230  }
231 
232  for( int j = extedgesstart[index]; j < extedgesstart[index + 1]; j++ )
233  {
234  assert(extedges[j] >= 0);
235  extstack_data[datasize++] = extedges[j];
236  }
237 
238  assert(stackpos < extdata->extstack_maxsize - 2);
239 
240  extstack_state[++stackpos] = EXT_STATE_NONE;
241  extstack_start[stackpos + 1] = datasize;
242  }
243 
244 #ifdef SCIP_DEBUG
245  printf("added extending edges: \n");
246 
247  for( int i = extstack_start[extdata->extstack_ncomponents]; i < extstack_start[stackpos + 1]; i++ )
248  graph_edge_printInfo(graph, extstack_data[i]);
249 #endif
250 
251  extdata->extstack_ncomponents = stackpos + 1;
252 
253  assert(extdata->extstack_ncomponents <= extdata->extstack_maxncomponents);
254 }
255 
256 
257 /** adds a new leaf */
258 static inline
260  int leaf, /**< leaf to add */
261  EXTDATA* extdata /**< extension data */
262 )
263 {
264  assert(extdata && extdata->tree_leaves);
265  assert(leaf >= 0 && extdata->tree_deg[leaf] == 0);
266 
267  extdata->tree_leaves[(extdata->tree_nleaves)++] = leaf;
268 }
269 
270 
271 /** remove entry from leaves list */
272 static inline
274  int leaf, /**< leaf to remove */
275  EXTDATA* extdata /**< extension data */
276 )
277 {
278  int* const tree_leaves = extdata->tree_leaves;
279  int nleaves;
280  int position;
281 
282  assert(extdata->tree_deg[leaf] == 1);
283 
284  /* switch last leaf and leaf to be removed */
285  assert(extdata->tree_nleaves > 1);
286 
287  position = extLeafFindPos(extdata, leaf);
288  assert(position > 0);
289 
290  extdata->tree_nleaves--;
291 
292  nleaves = extdata->tree_nleaves;
293 
294  for( int p = position; p < nleaves; p++ )
295  {
296  tree_leaves[p] = tree_leaves[p + 1];
297  }
298 }
299 
300 
301 /** Remove top component from leaves, and restore the root of the component as a leaf
302  * NOTE: assumes that the tree_deg has already been adapted */
303 static inline
305  const GRAPH* graph, /**< graph data structure */
306  int topsize, /**< size of top to remove */
307  int toproot, /**< root of the top component */
308  EXTDATA* extdata /**< extension data */
309 )
310 {
311  const int* const extstack_data = extdata->extstack_data;
312  int* const tree_leaves = extdata->tree_leaves;
313  const int stackpos_prev = extStackGetPrevMarked(extdata);
314  const int prevedges_start = extStackGetOutEdgesStart(extdata, stackpos_prev);
315  const int prevedges_end = extStackGetOutEdgesEnd(extdata, stackpos_prev);
316  const int compsize = prevedges_end - prevedges_start;
317  int compleaves_start;
318 
319  assert(extdata);
320  assert(topsize >= 1 && topsize < extdata->tree_nleaves);
321  assert(toproot >= 0);
322  assert(extdata->tree_deg[toproot] == 1);
323  assert(compsize > 0);
324 
325 #ifndef NDEBUG
326  {
327  const int* const tree_deg = extdata->tree_deg;
328  const int nleaves = extdata->tree_nleaves;
329 
330  for( int i = 1; i <= topsize; i++ )
331  {
332  const int leaf = tree_leaves[nleaves - i];
333  assert(tree_deg[leaf] == 0);
334  }
335  }
336 #endif
337 
338  extdata->tree_nleaves -= (topsize - 1);
339 
340 #ifndef NDEBUG
341  tree_leaves[(extdata->tree_nleaves) - 1] = toproot;
342 
343  for( int i = prevedges_start; i != prevedges_end; i++ )
344  {
345  const int edge = extstack_data[i];
346  const int head = graph->head[edge];
347 
348  assert(extLeafFindPos(extdata, head) >= extdata->tree_nleaves - compsize);
349  }
350 #endif
351 
352  compleaves_start = extdata->tree_nleaves - compsize;
353 
354  for( int i = prevedges_start; i < prevedges_end; i++ )
355  {
356  const int edge = extstack_data[i];
357  const int head = graph->head[edge];
358 
359  tree_leaves[compleaves_start++] = head;
360  }
361 
362  assert(compleaves_start == extdata->tree_nleaves);
363  assert(extdata->tree_nleaves >= 1);
364 }
365 
366 
367 /** adds a new inner node */
368 static inline
370  const GRAPH* graph, /**< graph data structure */
371  int innernode, /**< node to add */
372  EXTDATA* extdata /**< extension data */
373 )
374 {
375  const SCIP_Bool isPc = (graph->prize != NULL);
376 
377  assert(extdata->tree_innerNodes);
378  assert(0 <= innernode && innernode < graph->knots);
379  assert(extdata->tree_deg[innernode] > 0);
380  assert(isPc == graph_pc_isPc(graph));
381 
382  if( isPc )
383  {
384  extdata->pcdata->tree_innerPrize += graph->prize[innernode];
385  }
386 
387  extdata->tree_innerNodes[(extdata->tree_ninnerNodes)++] = innernode;
388 }
389 
390 
391 /** removes a new inner node */
392 static inline
394  const GRAPH* graph, /**< graph data structure */
395  int innernode, /**< (top) node to remove */
396  EXTDATA* extdata /**< extension data */
397 )
398 {
399  assert(extdata && extdata->tree_innerNodes);
400  assert(innernode >= 0);
401 
402  /* update tree leaves array */
403  if( innernode != extdata->tree_root )
404  {
405  const SCIP_Bool isPc = (graph->prize != NULL);
406 
407  assert(extdata->tree_ninnerNodes >= 1);
408  assert(innernode == extdata->tree_innerNodes[extdata->tree_ninnerNodes - 1]);
409  assert(isPc == graph_pc_isPc(graph));
410 
411  extdata->tree_ninnerNodes--;
412 
413  if( isPc )
414  {
415  extdata->pcdata->tree_innerPrize -= graph->prize[innernode];
416 
417  assert(GE(extdata->pcdata->tree_innerPrize, 0.0));
418  }
419  }
420  else
421  {
422  assert(!extInitialCompIsEdge(extdata) || extdata->tree_ninnerNodes == 0);
423  assert(!extInitialCompIsStar(extdata) || extdata->tree_ninnerNodes == 1);
424  assert(!extInitialCompIsGenStar(extdata) || extdata->tree_ninnerNodes == 2);
425  }
426 }
427 
428 
429 /** adds edge to tree */
430 static inline
432  const GRAPH* graph, /**< graph data structure */
433  int edge, /**< edge to be added */
434  EXTDATA* extdata /**< extension data */
435 )
436 {
437  int* const tree_deg = extdata->tree_deg;
438  int* const tree_edges = extdata->tree_edges;
439  int* const tree_parentNode = extdata->tree_parentNode;
440  SCIP_Real* const tree_parentEdgeCost = extdata->tree_parentEdgeCost;
441  const SCIP_Real edgecost = graph->cost[edge];
442  const int head = graph->head[edge];
443  const int tail = graph->tail[edge];
444  const int genstar_centerhead = (extdata->genstar_centeredge == -1) ? -1 : graph->head[extdata->genstar_centeredge];
445 
446  assert(tree_deg[head] == 0);
447  assert(tree_deg[tail] > 0 || tail == extdata->tree_root);
448 
449  if( extdata->tree_starcenter != head && genstar_centerhead != head )
450  {
451  extLeafAdd(head, extdata);
452  }
453  else
454  {
455  assert(extInitialCompIsStar(extdata) || extInitialCompIsGenStar(extdata));
456  assert(extIsAtInitialComp(extdata));
457  }
458 
459  /* NOTE: a bit hacky, but also works for general stars, because of the order
460  * in which the initial edges are processed */
461  extdata->tree_cost += edgecost;
462  tree_deg[head] = 1;
463  tree_edges[(extdata->tree_nedges)++] = edge;
464  tree_parentNode[head] = tail;
465  tree_parentEdgeCost[head] = edgecost;
466  tree_deg[tail]++;
467 }
468 
469 
470 /** removes root of stack top component from tree */
471 static inline
473  const GRAPH* graph, /**< graph data structure */
474  EXTDATA* extdata /**< extension data */
475 )
476 {
477  const int comproot = extStackGetTopRoot(graph, extdata);
478 
479  /* update tree leaves array */
480  if( !extIsAtInitialComp(extdata) )
481  {
482  assert(comproot != extdata->tree_root);
483 
484  extLeafRemove(comproot, extdata);
485  extInnerNodeAdd(graph, comproot, extdata);
486  }
487  else
488  {
489  assert(extdata->tree_nleaves == 1);
490  assert(extdata->tree_deg[comproot] == 1);
491  assert(comproot == extdata->tree_root);
492 
493  /* will be reset afterwards! */
494  extdata->tree_deg[comproot] = 0;
495 
496  if( extInitialCompIsStar(extdata) )
497  {
498  const int starcenter = extdata->tree_starcenter;
499  assert(graph_knot_isInRange(graph, starcenter));
500 
501  extdata->tree_deg[starcenter] = 0;
502  }
503  else if( extInitialCompIsGenStar(extdata) )
504  {
505  const int centeredge = extdata->genstar_centeredge;
506  const int starcenter = extdata->tree_starcenter;
507 
508  assert(graph_edge_isInRange(graph, centeredge));
509  assert(graph_knot_isInRange(graph, starcenter));
510  assert(graph->tail[centeredge] == starcenter);
511 
512  extdata->tree_deg[starcenter] = 0;
513  extdata->tree_deg[graph->head[centeredge]] = 0;
514  }
515  }
516 }
517 
518 
519 /** adds top component of stack to tree */
520 static
522  SCIP* scip, /**< SCIP */
523  const GRAPH* graph, /**< graph data structure */
524  EXTDATA* extdata, /**< extension data */
525  SCIP_Bool* conflict /**< conflict found? */
526 )
527 {
528  const int* const extstack_data = extdata->extstack_data;
529  const int* const extstack_start = extdata->extstack_start;
530  REDDATA* const reddata = extdata->reddata;
531  int* const pseudoancestor_mark = reddata->pseudoancestor_mark;
532  const int stackpos = extStackGetPosition(extdata);
533  int conflictIteration = -1;
534 
535  assert(!(*conflict));
536  assert(stackpos >= 0);
537  assert(extstack_start[stackpos + 1] - extstack_start[stackpos] > 0);
538  assert(extdata->extstack_state[stackpos] == EXT_STATE_EXPANDED);
539 
540  extreduce_redcostInitExpansion(graph, extdata);
541  extTreeStackTopRootRemove(graph, extdata);
542 
543  /* add top expanded component to tree data */
544  for( int i = extstack_start[stackpos]; i < extstack_start[stackpos + 1]; i++ )
545  {
546  const int edge = extstack_data[i];
547 
548  assert(extdata->tree_nedges < extdata->extstack_maxsize);
549  assert(edge >= 0 && edge < graph->edges);
550 
551  extreduce_redcostAddEdge(graph, edge, reddata, extdata);
552  extTreeAddEdge(graph, edge, extdata);
553 
554  /* no conflict found yet? */
555  if( conflictIteration == -1 )
556  {
557  assert(*conflict == FALSE);
558 
559  graph_pseudoAncestors_hashEdgeDirty(graph->pseudoancestors, edge, TRUE, conflict, pseudoancestor_mark);
560 
561  if( *conflict )
562  {
563  SCIPdebugMessage("pseudoancestor conflict for edge %d \n", edge);
564  conflictIteration = i;
565  assert(conflictIteration >= 0);
566  }
567  }
568  }
569 
570  /* conflict found? */
571  if( conflictIteration != -1 )
572  {
573  assert(*conflict && conflictIteration >= 0);
574 
575  for( int i = extstack_start[stackpos]; i < conflictIteration; i++ )
576  {
577  const int edge = extstack_data[i];
578  graph_pseudoAncestors_unhashEdge(graph->pseudoancestors, edge, pseudoancestor_mark);
579  }
580  }
581 
582  extdata->tree_depth++;
583 
584  assert(!extreduce_treeIsFlawed(scip, graph, extdata));
585 }
586 
587 
588 /** removes top component of stack from tree */
589 static inline
591  const GRAPH* graph, /**< graph data structure */
592  SCIP_Bool ancestor_conflict, /**< with ancestor conflict? */
593  EXTDATA* extdata /**< extension data */
594 )
595 {
596  REDDATA* const reddata = extdata->reddata;
597  int* const pseudoancestor_mark = reddata->pseudoancestor_mark;
598  int* const extstack_data = extdata->extstack_data;
599  int* const extstack_start = extdata->extstack_start;
600  int* const tree_deg = extdata->tree_deg;
601  const int stackpos = extStackGetPosition(extdata);
602  const int stackstart = extstack_start[stackpos];
603  const int comproot = extStackGetTopRoot(graph, extdata);
604  const int compsize = extstack_start[stackpos + 1] - extstack_start[stackpos];
605 
606  assert(compsize > 0);
607  assert(stackstart > 0);
608  assert(tree_deg[comproot] > 1);
609  assert(extdata->extstack_state[stackpos] != EXT_STATE_NONE);
610 
611  /* remove top component */
612  for( int i = stackstart; i < extstack_start[stackpos + 1]; i++ )
613  {
614  const int edge = extstack_data[i];
615  const int head = graph->head[edge];
616 
617  assert(edge >= 0 && edge < graph->edges);
618  assert(comproot == graph->tail[edge]);
619  assert(tree_deg[head] == 1 && tree_deg[comproot] > 1);
620 
621  extreduce_redcostRemoveEdge(edge, reddata, extdata);
622 
623  extdata->tree_cost -= graph->cost[edge];
624  tree_deg[head] = 0;
625  tree_deg[comproot]--;
626 
627  if( !ancestor_conflict ) /* in case of a conflict, edge is unhashed already */
628  graph_pseudoAncestors_unhashEdge(graph->pseudoancestors, edge, pseudoancestor_mark);
629  }
630 
631  assert(tree_deg[comproot] == 1);
632 
633  (extdata->tree_nedges) -= compsize;
634  (extdata->tree_depth)--;
635 
636  /* finally, remove top component from leaves and MST storages and restore the component root */
637  extLeafRemoveTop(graph, compsize, comproot, extdata);
638  extInnerNodeRemoveTop(graph, comproot, extdata);
639  extreduce_mstCompRemove(graph, extdata);
640 
641  assert(extdata->tree_nedges >= 0 && extdata->tree_depth >= 0);
642 }
643 
644 
645 /** can any extension via edge be ruled out by using simple test?? */
646 static inline
648  const GRAPH* graph, /**< graph data structure */
649  EXTDATA* extdata, /**< extension data */
650  int edge /**< edge to be tested */
651 )
652 {
653  const REDDATA* const reddata = extdata->reddata;
654  const int extvert = graph->head[edge];
655  const int* const tree_deg = extdata->tree_deg;
656 
657  if( tree_deg[extvert] != 0 )
658  {
659 #ifdef SCIP_DEBUG
660  SCIPdebugMessage("simple rule-out (edge-to-tree) ");
661  graph_edge_printInfo(graph, edge);
662 #endif
663 
664  return TRUE;
665  }
666 
668  {
669 #ifdef SCIP_DEBUG
670 
671  SCIPdebugMessage("simple rule-out (ancestor) ");
672  graph_edge_printInfo(graph, edge);
673 #endif
674 
675  return TRUE;
676  }
677 
678  return FALSE;
679 }
680 
681 
682 #ifdef SCIP_DISABLED
683 /** can any extension via edge except for only the edge itself be ruled out? */
684 static
685 SCIP_Bool extRuleOutEdgeCombinations(
686  const GRAPH* graph, /**< graph data structure */
687  const EXTDATA* extdata, /**< extension data */
688  int extedge /**< edge to be tested */
689 )
690 {
691 }
692 #endif
693 
694 
695 
696 /** Can current singleton extension be ruled out?
697  * NOTE: Also stores vertical SDs for this singleton if not ruled out! */
698 static inline
700  SCIP* scip, /**< SCIP */
701  const GRAPH* graph, /**< graph data structure */
702  EXTDATA* extdata /**< extension data */
703 )
704 {
705  SCIP_Bool ruledOutFull = FALSE;
706  const int edge = extdata->extstack_data[extdata->extstack_start[extStackGetPosition(extdata)]];
707  const int base = graph->tail[edge];
708  const int leaf = graph->head[edge];
709 
710  SCIPdebugMessage("adding SDs for edge %d->%d \n", graph->tail[edge], graph->head[edge]);
711 
713 
714  assert(extdata->tree_deg[base] == 2);
715  assert(extdata->tree_deg[leaf] == 1);
716 
717  /* NOTE the following is needed to keep invariants */
718  extdata->tree_deg[base] = 1;
719  extdata->tree_deg[leaf] = 0;
720  extLeafRemoveTop(graph, 1, base, extdata);
721  extInnerNodeRemoveTop(graph, base, extdata);
722 
723  extreduce_mstLevelVerticalAddLeaf(scip, graph, edge, extdata, &ruledOutFull);
724 
725  extLeafRemove(base, extdata);
726  extLeafAdd(leaf, extdata);
727  extInnerNodeAdd(graph, base, extdata);
728  extdata->tree_deg[base] = 2;
729  extdata->tree_deg[leaf] = 1;
730 
732 
733  return ruledOutFull;
734 }
735 
736 
737 /** Can current singleton extension be ruled out by implication argument? */
738 static inline
740  SCIP* scip, /**< SCIP */
741  const GRAPH* graph, /**< graph data structure */
742  EXTDATA* extdata /**< extension data */
743 )
744 {
745  const int edge = extdata->extstack_data[extdata->extstack_start[extStackGetPosition(extdata)]];
746  const int base = graph->tail[edge];
747  const int *tree_deg = graph_pc_isPc(graph) ? extdata->tree_deg : NULL;
748  const STP_Vectype(int) implications = extdata->reddata->nodes_implications[base];
749 
750  if( extensionHasImplicationConflict(graph, implications, tree_deg,
751  extdata->tree_root, &edge, 1) )
752  {
753  SCIPdebugMessage("implication singleton rule-out \n");
754  return TRUE;
755  }
756 
757  return FALSE;
758 }
759 
760 
761 /** Can current tree be peripherally ruled out?
762  * NOTE: If tree cannot be ruled-out, the current component will be put into the MST storage 'reddata->msts' */
763 static inline
765  SCIP* scip, /**< SCIP */
766  const GRAPH* graph, /**< graph data structure */
767  EXTDATA* extdata /**< extension data */
768 )
769 {
770 //#define EXT_PRINT_STATS
771 #ifdef EXT_PRINT_STATS
772  static SCIP_Longint contracts = 0;
773  static SCIP_Longint mst = 0;
774  static SCIP_Longint red = 0;
775 #endif
776 
777  /* if we have a singleton edge, we first check whether the edge is redundant in all extension components
778  * and concomitantly compute the SDs to the current tree leafs */
779  if( extStackTopIsSingleton(extdata) && !extIsAtInitialComp(extdata) )
780  {
781  /* NOTE SDs will also be computed if not ruled out */
782  SCIP_Bool ruledOutFull = extTreeRuleOutSingletonFull(scip, graph, extdata);
783 
784 
785  if( ruledOutFull )
786  return TRUE;
787 
788  if( extTreeRuleOutSingletonImplied(scip, graph, extdata) )
789  return TRUE;
790  }
791 
792  if( extreduce_mstRuleOutPeriph(scip, graph, extdata) )
793  {
794 #ifdef EXT_PRINT_STATS
795  mst++;
796  if( mst % 10000 == 0 )
797  {
798  printf("rule-out-red=%lld \n", red);
799  printf("rule-out-mst=%lld \n", mst);
800  printf("rule-out-contracts=%lld \n", contracts);
801  }
802 #endif
803 
804  return TRUE;
805  }
806 
807  if( extreduce_redcostRuleOutPeriph(graph, extdata) )
808  {
809 #ifdef EXT_PRINT_STATS
810  red++;
811  if( red % 10000 == 0 )
812  {
813  printf("rule-out-red=%lld \n", red);
814  printf("rule-out-mst=%lld \n", mst);
815  printf("rule-out-contracts=%lld \n", contracts);
816  }
817 #endif
818 
819  return TRUE;
820  }
821 
822  if( extreduce_contractionRuleOutPeriph(scip, graph, extdata) )
823  {
824 #ifdef EXT_PRINT_STATS
825  contracts++;
826  if( contracts % 10000 == 0 )
827  {
828  printf("rule-out-red=%lld \n", red);
829  printf("rule-out-mst=%lld \n", mst);
830  printf("rule-out-contracts=%lld \n", contracts);
831  }
832 #endif
833 
834  return TRUE;
835  }
836 
837  return FALSE;
838 }
839 
840 
841 /** Stores extensions of tree from current (expanded and marked) stack top that cannot be ruled-out. */
842 static inline
844  SCIP* scip, /**< SCIP */
845  const GRAPH* graph, /**< graph data structure */
846  EXTDATA* extdata, /**< extension data */
847  int* extedgesstart, /**< starts of extension edges for one components */
848  int* extedges, /**< extensions edges */
849  int* nextensions, /**< number of all extensions */
850  int* nextendableleaves, /**< number of leaves that can be extended */
851  SCIP_Bool* with_ruledout_leaf /**< one leaf could already be ruled out? */
852 )
853 {
854  const int* const extstack_data = extdata->extstack_data;
855  const SCIP_Bool* const isterm = extdata->node_isterm;
856  const int stackpos = extStackGetPosition(extdata);
857  const int topedges_start = extStackGetTopOutEdgesStart(extdata, stackpos);
858  const int topedges_end = extStackGetTopOutEdgesEnd(extdata, stackpos);
859 
860 #ifndef NDEBUG
861  assert(graph && extdata && extedgesstart && extedges && nextensions && nextendableleaves && with_ruledout_leaf);
862  assert(stackpos >= 0);
863  assert(EXT_STATE_MARKED == extdata->extstack_state[stackpos]);
864  assert(!(*with_ruledout_leaf));
865  assert(*nextensions == 0 && *nextendableleaves == 0);
866  assert(topedges_start < topedges_end);
867 
868  extreduce_extendInitDebug(extedgesstart, extedges);
869 #endif
870 
871  extedgesstart[0] = 0;
872 
873  /* loop over all leaves of top component */
874  for( int i = topedges_start; i < topedges_end; i++ )
875  {
876  int nleafextensions = 0;
877  const int leaf = graph->head[extstack_data[i]];
878 
879  assert(extstack_data[i] >= 0 && extstack_data[i] < graph->edges);
880 
881  /* extensions from leaf not possible? */
882  if( !extLeafIsExtendable(graph, isterm, leaf) )
883  continue;
884 
885  // todo extra method...skipping all edges except for the reverted one
886  if( extIsAtInitialStar(extdata) && extdata->extcomp->nextleaves == 1 && extdata->extcomp->extleaves[0] != leaf )
887  continue;
888 
889  /* assemble feasible single edge extensions from leaf */
890  for( int e = graph->outbeg[leaf]; e != EAT_LAST; e = graph->oeat[e] )
891  {
892  if( extTreeRuleOutEdgeSimple(graph, extdata, e) )
893  {
894  continue;
895  }
896 
897  assert(*nextensions < STP_EXT_MAXGRAD * STP_EXT_MAXGRAD);
898  extedges[(*nextensions)++] = e;
899  nleafextensions++;
900  }
901 
902  if( nleafextensions == 0 )
903  {
904  *with_ruledout_leaf = TRUE;
905  return;
906  }
907 
908  extedgesstart[++(*nextendableleaves)] = *nextensions;
909  }
910 
911  assert(*nextensions >= *nextendableleaves);
912  assert(*nextendableleaves <= STP_EXT_MAXGRAD);
913 }
914 
915 
916 /** synchronize tree with the stack */
917 static inline
919  SCIP* scip, /**< SCIP */
920  const GRAPH* graph, /**< graph data structure */
921  EXTDATA* extdata, /**< extension data */
922  SCIP_Bool* conflict /**< conflict found? */
923 )
924 {
925  const int stackposition = extStackGetPosition(extdata);
926 
927  assert(scip && graph && extdata && conflict);
928  assert(!(*conflict));
929 
930 #ifdef SCIP_DEBUG
931  extreduce_printStack(graph, extdata);
932 #endif
933 
934  /* is current component expanded? */
935  if( extdata->extstack_state[stackposition] == EXT_STATE_EXPANDED && !extStackTopIsWrapped(extdata) )
936  {
937  /* add top component to tree */
938  extTreeStackTopAdd(scip, graph, extdata, conflict);
939  }
940 
941  /* recompute edge costs and reduced costs? */
942  if( ++(extdata->ncostupdatestalls) > EXT_COSTS_RECOMPBOUND )
943  {
944  extreduce_treeRecompCosts(scip, graph, extdata);
945  extdata->ncostupdatestalls = 0;
946  }
947 
948 #ifndef NDEBUG
949  if( !(*conflict) )
950  {
951  assert(extreduce_treeIsHashed(graph, extdata));
952  }
953 #endif
954 }
955 
956 
957 /** should we truncate from current component? */
958 static
960  const GRAPH* graph, /**< graph data structure */
961  const EXTDATA* extdata /**< extension data */
962 )
963 {
964  const int* const extstack_data = extdata->extstack_data;
965  const int* const extstack_start = extdata->extstack_start;
966  const SCIP_Bool* const isterm = extdata->node_isterm;
967  const int stackpos = extStackGetPosition(extdata);
968 
969  assert(extdata->extstack_state[stackpos] == EXT_STATE_MARKED);
970  assert(extstack_start[stackpos] < extdata->extstack_maxsize);
971 
972  if( extdata->tree_depth >= extdata->tree_maxdepth )
973  {
974  SCIPdebugMessage("truncate (depth too high) \n");
975  return TRUE;
976  }
977 
978  if( extdata->tree_nedges >= extdata->tree_maxnedges )
979  {
980  SCIPdebugMessage("truncate (too many tree edges) \n");
981  return TRUE;
982  }
983 
984  if( extdata->tree_nleaves >= extdata->tree_maxnleaves )
985  {
986  SCIPdebugMessage("truncate (too many leaves) \n");
987  return TRUE;
988  }
989 
990  if( extdata->extstack_ncomponents >= extdata->extstack_maxncomponents - 1 )
991  {
992  SCIPdebugMessage("truncate (too many stack components) \n");
993  return TRUE;
994  }
995 
996  /* check whether at least one leaf is extendable */
997  for( int i = extstack_start[stackpos]; i < extstack_start[stackpos + 1]; i++ )
998  {
999  const int edge = extstack_data[i];
1000  const int leaf = graph->head[edge];
1001 
1002  assert(edge >= 0 && edge < graph->edges);
1003  assert(extdata->tree_deg[leaf] > 0);
1004 
1005  if( extLeafIsExtendable(graph, isterm, leaf) )
1006  return FALSE;
1007  }
1008 
1009  SCIPdebugMessage("truncate (non-promising) \n");
1010  return TRUE;
1011 }
1012 
1013 
1014 /** top component is rebuilt, and
1015  * if success == TRUE: goes back to first marked component
1016  * if success == FALSE: goes back to first marked or non-expanded component
1017  * */
1018 static
1020  SCIP* scip, /**< SCIP data structure */
1021  const GRAPH* graph, /**< graph data structure */
1022  SCIP_Bool success, /**< backtrack from success? */
1023  SCIP_Bool ancestor_conflict, /**< backtrack triggered by ancestor conflict? */
1024  EXTDATA* extdata /**< extension data */
1025 )
1026 {
1027  int* const extstack_state = extdata->extstack_state;
1028  int stackpos = extStackGetPosition(extdata);
1029  const int extstate_top = extstack_state[stackpos];
1030 
1031  assert(graph && extdata);
1032  assert(extdata->extstack_start[stackpos + 1] - extdata->extstack_start[stackpos] > 0);
1033 
1034  /* top component already expanded (including marked)? */
1035  if( extstate_top != EXT_STATE_NONE )
1036  {
1037  extTreeStackTopRemove(graph, ancestor_conflict, extdata);
1038  }
1039 
1040  stackpos--;
1041 
1042  /* backtrack */
1043  if( success )
1044  {
1045  if( extstack_state[stackpos] != EXT_STATE_EXPANDED )
1046  {
1047  /* the MST level associated top component cannot be used anymore, because the next component is not a sibling */
1049  }
1050 
1051  while( extstack_state[stackpos] == EXT_STATE_NONE )
1052  {
1053  stackpos--;
1054  assert(stackpos >= 0);
1055  }
1056 
1057  SCIPdebugMessage("backtrack SUCCESS \n");
1058  assert(extstack_state[stackpos] == EXT_STATE_EXPANDED || extstack_state[stackpos] == EXT_STATE_MARKED);
1059  }
1060  else
1061  {
1062  /* the MST level associated with top component cannot be used anymore, because siblings will be removed */
1064 
1065  while( extstack_state[stackpos] == EXT_STATE_EXPANDED )
1066  {
1067  stackpos--;
1068  assert(stackpos >= 0);
1069  }
1070 
1071  SCIPdebugMessage("backtrack FAILURE \n");
1072  assert(extstack_state[stackpos] == EXT_STATE_NONE || extstack_state[stackpos] == EXT_STATE_MARKED);
1073  }
1074 
1075  extdata->extstack_ncomponents = stackpos + 1;
1076 
1077  assert(extdata->extstack_ncomponents <= extdata->extstack_maxncomponents);
1078  assert(!extreduce_treeIsFlawed(scip, graph, extdata));
1079 }
1080 
1081 /** Builds components from top edges and adds them.
1082  * Backtracks if stack is too full.
1083  * Helper method for 'extStackTopExpand' */
1084 static inline
1086  SCIP* scip, /**< SCIP data structure */
1087  const GRAPH* graph, /**< graph data structure */
1088  int nextedges, /**< number of edges for extension */
1089  const int* extedges, /**< array of edges for extension */
1090  EXTDATA* extdata, /**< extension data */
1091  SCIP_Bool* success, /**< success pointer */
1092  SCIP_Bool* ruledOut /**< all ruled out? */
1093 )
1094 {
1095  int ksubset[STP_EXT_MAXGRAD];
1096  int* const extstack_data = extdata->extstack_data;
1097  int* const extstack_start = extdata->extstack_start;
1098  int* const extstack_state = extdata->extstack_state;
1099  const int extroot = graph->tail[extedges[0]];
1100  const STP_Vectype(int) implications = extdata->reddata->nodes_implications[extroot];
1101  int stackpos = extStackGetPosition(extdata);
1102  int datasize = extstack_start[stackpos];
1103  const uint32_t powsize = (uint32_t) pow(2.0, nextedges);
1104  const int* tree_deg = graph_pc_isPc(graph) ? extdata->tree_deg : NULL;
1105 
1106  assert(0 < nextedges && nextedges < STP_EXT_MAXGRAD);
1107  assert(powsize >= 2);
1108  assert(extstack_data[datasize] == EXT_EDGE_WRAPPED);
1109 
1110  *ruledOut = FALSE;
1111 
1112  /* stack too full? */
1113  if( !extStackIsExtendable(nextedges, (int) powsize, datasize, extdata) )
1114  {
1115  *success = FALSE;
1116  extBacktrack(scip, graph, *success, FALSE, extdata);
1117 
1118  return;
1119  }
1120 
1121  /* remove the dummy level */
1123 
1124  extreduce_mstLevelHorizontalAdd(scip, graph, nextedges, extedges, extdata);
1125 
1126  /* compute and add components (overwrite previous, non-expanded component) */
1127  // todo since single extensions are used first, might make sense to also have a special bottleneck test for this case!
1128  // -also good if we have the method that excludes everything except for the singletons!
1129  for( int setsize = nextedges; setsize >= 2; setsize-- )
1130  {
1131  SCIP_Bool isFirst = TRUE;
1132 
1133  while( ksubsetGetNext(setsize, nextedges, isFirst, ksubset) )
1134  {
1135  const int datasize_prev = datasize;
1136  isFirst = FALSE;
1137 
1138  for( int j = 0; j < setsize; j++ )
1139  {
1140  const int pos = ksubset[j];
1141 
1142  assert(datasize < extdata->extstack_maxsize);
1143  assert(graph->tail[extedges[pos]] == extroot);
1144 
1145  extstack_data[datasize++] = extedges[pos];
1146  SCIPdebugMessage(" head %d \n", graph->head[extedges[pos]]);
1147  }
1148 
1149  SCIPdebugMessage("... added \n");
1150  assert(stackpos < extdata->extstack_maxsize - 1);
1151 
1152  if( extensionHasImplicationConflict(graph, implications, tree_deg, extdata->tree_root,
1153  &(extstack_data[datasize_prev]), datasize - datasize_prev) )
1154  {
1155  SCIPdebugMessage("implication conflict found for root %d \n", extroot);
1156  datasize = datasize_prev;
1157  }
1158  else
1159  {
1160  extstack_state[stackpos] = EXT_STATE_EXPANDED;
1161  extstack_start[++stackpos] = datasize;
1162  }
1163 
1164  assert(extstack_start[stackpos] - extstack_start[stackpos - 1] > 0);
1165  }
1166  }
1167 
1168  /* nothing added? */
1169  if( stackpos == extStackGetPosition(extdata) )
1170  {
1171  assert(datasize == extstack_start[stackpos]);
1172  *ruledOut = TRUE;
1173  extstack_data[datasize] = EXT_EDGE_WRAPPED;
1174  }
1175  else
1176  {
1177  assert(stackpos > extStackGetPosition(extdata));
1178  assert(stackpos >= extdata->extstack_ncomponents);
1179  assert(stackpos <= extdata->extstack_maxncomponents);
1180 
1181  extdata->extstack_ncomponents = stackpos;
1182  }
1183 }
1184 
1185 
1186 /** Builds singleton components from top edges and adds them.
1187  * Backtracks if stack is too full */
1188 static inline
1190  SCIP* scip, /**< SCIP data structure */
1191  const GRAPH* graph, /**< graph data structure */
1192  int nextedges, /**< number of edges for extension */
1193  const int* extedges, /**< array of edges for extension */
1194  EXTDATA* extdata, /**< extension data */
1195  SCIP_Bool* success, /**< success pointer */
1196  SCIP_Bool* ruledOut /**< all ruled out? */
1197 )
1198 {
1199  int* const extstack_data = extdata->extstack_data;
1200  int* const extstack_start = extdata->extstack_start;
1201  int* const extstack_state = extdata->extstack_state;
1202  const int extroot = graph->tail[extedges[0]];
1203  int stackpos = extStackGetPosition(extdata);
1204  int datasize = extstack_start[stackpos];
1205 
1206  assert(nextedges > 0 && nextedges < STP_EXT_MAXGRAD);
1207  *ruledOut = FALSE;
1208 
1209  /* stack too full? */
1210  if( !extStackIsExtendable(nextedges, nextedges + 1, datasize, extdata) )
1211  {
1212  *success = FALSE;
1213  extBacktrack(scip, graph, *success, FALSE, extdata);
1214  return;
1215  }
1216 
1217  extreduce_mstLevelHorizontalAddEmpty(graph, extdata);
1218  extreduce_mstLevelClose(scip, graph, extroot, extdata);
1219 
1220  /* first we add the wrapped component */
1221  extstack_data[datasize++] = EXT_EDGE_WRAPPED;
1222  extstack_state[stackpos] = EXT_STATE_EXPANDED;
1223  extstack_start[++stackpos] = datasize;
1224 
1225  /* compute and add singleton components (overwrite previous, non-expanded component) */
1226  for( int pos = 0; pos < nextedges; pos++ )
1227  {
1228  assert(datasize < extdata->extstack_maxsize && stackpos < extdata->extstack_maxsize - 1);
1229  assert(graph->tail[extedges[pos]] == extroot);
1230 
1231  extstack_data[datasize++] = extedges[pos];
1232  SCIPdebugMessage("add singleton head %d \n", graph->head[extedges[pos]]);
1233 
1234  extstack_state[stackpos] = EXT_STATE_EXPANDED;
1235  extstack_start[++stackpos] = datasize;
1236 
1237  assert(extstack_start[stackpos] - extstack_start[stackpos - 1] > 0);
1238  }
1239 
1240  assert(stackpos > extStackGetPosition(extdata));
1241 
1242  /* only wrapped component added? */
1243  if( stackpos == extStackGetPosition(extdata) + 1 )
1244  {
1245  *ruledOut = TRUE;
1246  }
1247  else
1248  {
1249  assert(stackpos > extStackGetPosition(extdata));
1250  assert(stackpos >= extdata->extstack_ncomponents);
1251  assert(stackpos <= extdata->extstack_maxncomponents);
1252 
1253  extdata->extstack_ncomponents = stackpos;
1254  }
1255 }
1256 
1257 
1258 /** adds initial component as 'expanded' to stack (including computation of horizontal SDs) */
1259 static inline
1261  SCIP* scip, /**< SCIP data structure */
1262  const GRAPH* graph, /**< graph data structure */
1263  EXTDATA* extdata /**< extension data */
1264 )
1265 {
1266  const int* const extstack_data = extdata->extstack_data;
1267  const int* const extstack_start = extdata->extstack_start;
1268  const int* extedges;
1269  int nextedges;
1270 
1271  /* NOTE: in case of star component we want to skip the root edge for the horizontal SD computation */
1272  if( extInitialCompIsStar(extdata) )
1273  {
1274  extedges = &(extstack_data[1]);
1275  nextedges = (extstack_start[1] - 1);
1276  }
1277  else if( extInitialCompIsGenStar(extdata) )
1278  {
1279  extedges = &(extstack_data[2]);
1280  nextedges = (extstack_start[1] - 2);
1281  }
1282  else
1283  {
1284  extedges = extstack_data;
1285  nextedges = extstack_start[1];
1286  }
1287 
1288  assert(nextedges > 0);
1289  assert(graph->tail[extstack_data[0]] == extdata->tree_root);
1290 
1291  extreduce_mstLevelHorizontalAdd(scip, graph, nextedges, extedges, extdata);
1292  extreduce_mstLevelClose(scip, graph, extdata->tree_root, extdata);
1293 
1294  extdata->extstack_state[0] = EXT_STATE_EXPANDED;
1295  extdata->extstack_ncomponents = 1;
1296 }
1297 
1298 
1299 /** Collects edges top component of stack that we need to consider for extension
1300  * (i.e. which cannot be ruled out).
1301  * Helper method for 'extStackTopExpand' */
1302 static inline
1304  SCIP* scip, /**< SCIP data structure */
1305  const GRAPH* graph, /**< graph data structure */
1306  EXTDATA* extdata, /**< extension data */
1307  int* extedges, /**< array of collected edges */
1308  int* nextedges /**< number of edges */
1309 )
1310 {
1311  const MLDISTS* const sds_vertical = extdata->reddata->sds_vertical;
1312  const int stackpos = extStackGetPosition(extdata);
1313  const int toplevel = extreduce_mldistsTopLevel(sds_vertical);
1314  const int comproot = graph->tail[extdata->extstack_data[extdata->extstack_start[stackpos] + 1]];
1315  // todo make that less hacky
1316 
1317  assert(*nextedges == 0);
1318  assert(extreduce_mstTopCompInSync(scip, graph, extdata));
1319 
1320  for( int e = graph->outbeg[comproot]; e != EAT_LAST; e = graph->oeat[e] )
1321  {
1322  if( extdata->tree_deg[graph->head[e]] != 0 )
1323  continue;
1324 
1325  if( extreduce_mldistsLevelContainsBase(sds_vertical, toplevel, graph->head[e]) )
1326  {
1327  SCIPdebugMessage("collecting edge %d->%d \n", graph->tail[e], graph->head[e]);
1328  extedges[(*nextedges)++] = e;
1329  }
1330  }
1331 }
1332 
1333 
1334 
1335 /** Collects edges top component of stack that we need to consider for singletons extension */
1336 static inline
1338  SCIP* scip, /**< SCIP data structure */
1339  const GRAPH* graph, /**< graph data structure */
1340  EXTDATA* extdata, /**< extension data */
1341  int* extedges, /**< array of collected edges */
1342  int* nextedges /**< number of edges */
1343 )
1344 {
1345  const int* const extstack_data = extdata->extstack_data;
1346  const int* const extstack_start = extdata->extstack_start;
1347  const int stackpos = extStackGetPosition(extdata);
1348 
1349  assert(*nextedges == 0);
1350  assert(extstack_start[stackpos + 1] - extstack_start[stackpos] >= 1);
1351  assert(extreduce_mstTopCompInSync(scip, graph, extdata));
1352 
1353  /* collect edges for components (and try to rule each of them out) */
1354  for( int i = extstack_start[stackpos]; i < extstack_start[stackpos + 1]; i++ )
1355  {
1356  const int edge = extstack_data[i];
1357 
1358  assert(*nextedges < STP_EXT_MAXGRAD);
1359  assert(edge >= 0 && edge < graph->edges);
1360  assert(extdata->tree_deg[graph->head[edge]] == 0);
1361  assert(!extTreeRuleOutEdgeSimple(graph, extdata, edge));
1362 
1363  extedges[(*nextedges)++] = edge;
1364  }
1365 }
1366 
1367 
1368 /** Gets start of data for initial component */
1369 static inline
1371  const EXTDATA* extdata /**< extension data */
1372 )
1373 {
1374  const int* const extstack_start = extdata->extstack_start;
1375  int start;
1376 
1377  assert(extStackGetPosition(extdata) == 0);
1378 
1379  if( extInitialCompIsEdge(extdata) )
1380  start = extstack_start[0];
1381  else if( extInitialCompIsGenStar(extdata) )
1382  start = extstack_start[0] + 2;
1383  else
1384  start = extstack_start[0] + 1;
1385 
1386  return start;
1387 }
1388 
1389 
1390 /** Computes ancestor SDs for leaves of initial component.
1391  * Also checks for possible rule-out. */
1392 static inline
1394  SCIP* scip, /**< SCIP data structure */
1395  const GRAPH* graph, /**< graph data structure */
1396  EXTDATA* extdata, /**< extension data */
1397  SCIP_Bool* initialRuleOut /**< pointer to mark early rule-out */
1398 )
1399 {
1400  const int* const extstack_data = extdata->extstack_data;
1401  const int* const extstack_start = extdata->extstack_start;
1402  const int stackpos = extStackGetPosition(extdata);
1403  const SCIP_Bool compIsEdge = extInitialCompIsEdge(extdata);
1404  const int data_start = extStackTopGetInitalDataStart(extdata);
1405  const int data_end = extstack_start[stackpos + 1];
1406 
1407  assert(*initialRuleOut == FALSE);
1408  assert(extstack_start[stackpos + 1] - extstack_start[stackpos] >= 1);
1409  assert(extreduce_mstTopCompInSync(scip, graph, extdata));
1410  assert(extstack_start[stackpos + 1] - extstack_start[stackpos] == extstack_start[1]);
1411  assert(data_start < data_end);
1412 
1413  /* compute SDs for all leaves (and try to rule each of them out) */
1414  for( int i = data_start; i < data_end; i++ )
1415  {
1416  const int edge = extstack_data[i];
1417 
1418  assert(edge >= 0 && edge < graph->edges);
1419  assert(extdata->tree_deg[graph->head[edge]] == 0);
1420  assert(!extTreeRuleOutEdgeSimple(graph, extdata, edge));
1421 
1422  /* computes the SDs from 'leaf' to all tree leaves in 'sds_vertical', unless the edge is ruled out */
1423  extreduce_mstLevelVerticalAddLeafInitial(scip, graph, edge, extdata, initialRuleOut);
1424 
1425  if( *initialRuleOut )
1426  {
1427  SCIPdebugMessage("initial component ruled-out! \n");
1428  return;
1429  }
1430 
1431 #if 0
1432  if( extRuleOutEdgeCombinations(graph, extdata, e) )
1433  {
1434  // todo: need some marker here to say that we have a single edge!
1435  continue;
1436  }
1437 #endif
1438  }
1439 
1440  if( !compIsEdge )
1441  {
1442  const STP_Vectype(int) implications = extdata->reddata->nodes_implications[extdata->tree_starcenter];
1443 
1444  assert(extdata->tree_deg[graph->tail[extstack_data[0]]] == 1);
1445  assert(graph_knot_isInRange(graph, extdata->tree_starcenter));
1446 
1447  /* NOTE: need to be careful here, because the fist edge is an in-edge! */
1448  if( extensionHasImplicationConflict(graph, implications, extdata->tree_deg, extdata->tree_root,
1449  &(extstack_data[data_start]), data_end - data_start) )
1450  {
1451  SCIPdebugMessage("implication conflict found for initial star component \n");
1452 
1453  *initialRuleOut = TRUE;
1454  }
1455  }
1456 }
1457 
1458 
1459 /** Expands top component of stack to singletons */
1460 static
1462  SCIP* scip, /**< SCIP data structure */
1463  const GRAPH* graph, /**< graph data structure */
1464  EXTDATA* extdata, /**< extension data */
1465  SCIP_Bool* success /**< success pointer */
1466 )
1467 {
1468  int extedges[STP_EXT_MAXGRAD];
1469  int nextedges = 0;
1471 
1472 #ifndef NDEBUG
1473  const int stackpos = extStackGetPosition(extdata);
1474  const int* const extstack_state = extdata->extstack_state;
1475  for( int i = 0; i < STP_EXT_MAXGRAD; i++ )
1476  extedges[i] = -1;
1477 
1478  assert(scip && graph && success);
1479  assert(EXT_STATE_NONE == extstack_state[stackpos]);
1480 #endif
1481  SCIPdebugMessage("expanding singletons \n");
1482 
1483  extStackTopCollectExtEdgesSing(scip, graph, extdata, extedges, &nextedges);
1484  assert(nextedges > 0);
1485 
1486  /* add a placeholder level to keep invariants */
1487  extreduce_mstLevelVerticalAddEmpty(graph, extdata);
1488 
1489  /* use the just collected edges 'extedges' to build singleton components and add them to the stack */
1490  extStackAddCompsExpandedSing(scip, graph, nextedges, extedges, extdata, success, &ruledOut);
1491 
1492 #ifndef NDEBUG
1493  {
1494  const int stackpos_new = extStackGetPosition(extdata);
1495  assert(extstack_state[stackpos_new] == EXT_STATE_EXPANDED || (stackpos_new < stackpos) );
1496  }
1497 #endif
1498 }
1499 
1500 
1501 /** Expands wrapped component of stack
1502  * by adding all possible subsets of the component that cannot be ruled-out.
1503  */
1504 static
1506  SCIP* scip, /**< SCIP data structure */
1507  const GRAPH* graph, /**< graph data structure */
1508  EXTDATA* extdata, /**< extension data */
1509  SCIP_Bool* success /**< success pointer */
1510 )
1511 {
1512  int extedges[STP_EXT_MAXGRAD];
1513  int* const extstack_state = extdata->extstack_state;
1514  const int stackpos = extStackGetPosition(extdata);
1515  int nextedges = 0;
1517 
1518 #ifndef NDEBUG
1519  for( int i = 0; i < STP_EXT_MAXGRAD; i++ )
1520  extedges[i] = -1;
1521 
1522  assert(scip && graph && success);
1523  assert(EXT_STATE_EXPANDED == extstack_state[stackpos]);
1524 #endif
1525  SCIPdebugMessage("expanding wrapped components \n");
1526 
1527  /* collect surviving singleton edges */
1528  extStackTopCollectExtEdges(scip, graph, extdata, extedges, &nextedges);
1529 
1530  //extreduce_mstLevelVerticalClose(reddata);
1531 
1532  /* everything ruled out already?
1533  * NOTE in the case of 1 extension edge, this edge has already been ruled out! */
1534  if( nextedges == 0 || nextedges == 1 )
1535  {
1536  ruledOut = TRUE;
1537  }
1538  else
1539  {
1540  /* use the just collected edges 'extedges' to build components and add them to the stack */
1541  extStackAddCompsExpanded(scip, graph, nextedges, extedges, extdata, success, &ruledOut);
1542 
1543 #ifndef NDEBUG
1544  if( !ruledOut )
1545  {
1546  const int stackpos_new = extStackGetPosition(extdata);
1547  assert(extstack_state[stackpos_new] == EXT_STATE_EXPANDED || (stackpos_new < stackpos) );
1548  }
1549 #endif
1550  }
1551 
1552  if( ruledOut )
1553  {
1554  *success = TRUE;
1555 
1556  if( extStackTopIsWrapped(extdata) )
1557  extstack_state[stackpos] = EXT_STATE_NONE;
1558 
1559  assert(extstack_state[stackpos] == EXT_STATE_NONE);
1560  assert(stackpos != 0); /* not the initial component! */
1561 
1562  extBacktrack(scip, graph, *success, FALSE, extdata);
1563  }
1564 }
1565 
1566 
1567 /** Expands top component of stack.
1568  * Note: This method can backtrack:
1569  * 1. If stack is full (with success set to FALSE),
1570  * 2. If all edges of the component can be ruled-out (with success set to TRUE).
1571  */
1572 static
1574  SCIP* scip, /**< SCIP data structure */
1575  const GRAPH* graph, /**< graph data structure */
1576  EXTDATA* extdata, /**< extension data */
1577  SCIP_Bool* success /**< success pointer */
1578 )
1579 {
1580  if( extStackTopIsWrapped(extdata) )
1581  extStackTopExpandWrapped(scip, graph, extdata, success);
1582  else
1583  extStackTopExpandSingletons(scip, graph, extdata, success);
1584 }
1585 
1586 
1587 /** same as 'extStackTopExpand', but for initial component only */
1588 static inline
1590  SCIP* scip, /**< SCIP data structure */
1591  const GRAPH* graph, /**< graph data structure */
1592  EXTDATA* extdata, /**< extension data */
1593  SCIP_Bool* initialRuleOut /**< pointer to mark early rule-out */
1594 )
1595 {
1596  REDDATA* const reddata = extdata->reddata;
1597 
1598 #ifndef NDEBUG
1599  const int nextedges = extdata->extstack_start[1];
1600  const int* const extstack_state = extdata->extstack_state;
1601 
1602  assert(EXT_STATE_NONE == extstack_state[0]);
1603  assert(extStackGetPosition(extdata) == 0);
1604  assert(extIsAtInitialComp(extdata));
1605  assert(nextedges == 1 || nextedges >= 3);
1606 #endif
1607 
1608  extreduce_mstLevelInitialInit(reddata, extdata);
1609  extStackTopProcessInitialEdges(scip, graph, extdata, initialRuleOut);
1611 
1612  assert(extstack_state[0] == EXT_STATE_NONE);
1613 
1614  /* initial component ruled out already? */
1615  if( *initialRuleOut )
1616  {
1618  }
1619  else
1620  {
1621  extStackAddCompInitialExpanded(scip, graph, extdata);
1622 
1623  assert(extstack_state[0] != EXT_STATE_NONE);
1624  }
1625 
1626  assert(*initialRuleOut || extdata->extstack_state[0] != EXT_STATE_NONE );
1627 }
1628 
1629 
1630 /** Extends top component of stack.
1631  * Backtracks if stack is full.
1632  * Will not add anything in case of rule-out of at least one extension node. */
1633 static
1635  SCIP* scip, /**< SCIP data structure */
1636  const GRAPH* graph, /**< graph data structure */
1637  EXTDATA* extdata, /**< extension data */
1638  SCIP_Bool* success /**< success pointer, FALSE iff no extension was possible */
1639 )
1640 {
1641  int* extedges = NULL;
1642  int* extedgesstart = NULL;
1643  int* const extstack_start = extdata->extstack_start;
1644  const int stackpos = extStackGetPosition(extdata);
1645  int nextendable_leaves = 0;
1646  int nextensions = 0;
1647  SCIP_Bool has_ruledout_leaf = FALSE;
1648 
1649  assert(stackpos >= 0);
1650  assert(EXT_STATE_MARKED == extdata->extstack_state[stackpos]);
1651  assert(extstack_start[stackpos + 1] - extstack_start[stackpos] <= STP_EXT_MAXGRAD);
1652 
1654  SCIP_CALL_ABORT( SCIPallocBufferArray(scip, &extedgesstart, STP_EXT_MAXGRAD + 1) );
1655 
1656  extTreeFindExtensions(scip, graph, extdata, extedgesstart, extedges, &nextensions,
1657  &nextendable_leaves, &has_ruledout_leaf);
1658 
1659  if( has_ruledout_leaf )
1660  {
1661  *success = TRUE;
1662 
1663  SCIPdebugMessage("ruled-out one leaf \n");
1664  }
1665  else if( nextendable_leaves == 0 ) /* found no valid extensions? */
1666  {
1667  *success = FALSE;
1668 
1669  assert(nextensions == 0);
1670  SCIPdebugMessage("no valid extensions found \n");
1671  }
1672  else /* found non-empty valid extensions */
1673  {
1674  const int stacksize_new = extstack_start[stackpos + 1] + (extedgesstart[nextendable_leaves] - extedgesstart[0]);
1675  assert(nextendable_leaves > 0 && nextensions > 0);
1676 
1677  /* stack too small? */
1678  if( stacksize_new > extdata->extstack_maxsize )
1679  {
1680  *success = FALSE;
1681  assert(EXT_STATE_MARKED == extdata->extstack_state[extStackGetPosition(extdata)]);
1682 
1683  SCIPdebugMessage("stack is full! need to backtrack \n");
1684 
1685  extBacktrack(scip, graph, *success, FALSE, extdata);
1686  }
1687  else
1688  {
1689  *success = TRUE;
1690 
1691  extStackAddCompsNonExpanded(graph, extedgesstart, extedges, nextendable_leaves, extdata);
1692 
1693  /* try to expand last (and smallest!) component, which currently is just a set of edges */
1694  extStackTopExpand(scip, graph, extdata, success);
1695  }
1696  }
1697 
1698  SCIPfreeBufferArray(scip, &extedgesstart);
1699  SCIPfreeBufferArray(scip, &extedges);
1700 }
1701 
1702 
1703 /** adds initial single edge to stack */
1704 static inline
1706  SCIP* scip, /**< SCIP data structure */
1707  const GRAPH* graph, /**< graph data structure */
1708  const EXTCOMP* extcomp, /**< component to be checked */
1709  EXTDATA* extdata /**< extension data */
1710 )
1711 {
1712  const int edge = extcomp->compedges[0];
1713 
1714  assert(0 <= edge && edge < graph->edges);
1715  assert(extcomp->ncompedges == 1);
1716  assert(graph->tail[edge] == extcomp->comproot);
1717 
1718 #ifdef SCIP_DEBUG
1719  printf("\n --- ADD initial EDGE component --- \n\n");
1720  SCIPdebugMessage("...initial edge %d: %d->%d \n\n", edge, graph->tail[edge], graph->head[edge]);
1721 #endif
1722 
1723  extdata->extstack_data[0] = edge;
1724 }
1725 
1726 
1727 /** adds initial star component edges to stack */
1728 /* NOTE: it is vital the the first edge of the star component comes from the root! */
1729 static inline
1731  SCIP* scip, /**< SCIP data structure */
1732  const GRAPH* graph, /**< graph data structure */
1733  const EXTCOMP* extcomp, /**< component to be checked */
1734  EXTDATA* extdata /**< extension data */
1735 )
1736 {
1737  const int* const compedges = extcomp->compedges;
1738  const int ncompedges = extcomp->ncompedges;
1739  const int rootedge = compedges[0];
1740  const int starcenter = graph->head[rootedge];
1741  const int comproot = extcomp->comproot;
1742 
1743  assert(ncompedges >= 3);
1744  assert(graph->tail[rootedge] == comproot);
1745 
1746 #ifdef SCIP_DEBUG
1747  printf("\n --- ADD initial STAR component --- \n\n");
1748  SCIPdebugMessage("...root star edge %d: %d->%d \n", rootedge, comproot, starcenter);
1749 #endif
1750 
1751  extdata->extstack_data[0] = rootedge;
1752  extdata->tree_deg[starcenter] = ncompedges;
1753  extdata->tree_parentNode[starcenter] = comproot;
1754  extdata->tree_parentEdgeCost[starcenter] = graph->cost[rootedge];
1755  extdata->tree_starcenter = starcenter;
1756 
1757  for( int i = 1; i < ncompedges; i++ )
1758  {
1759  const int e = compedges[i];
1760 
1761  SCIPdebugMessage("...star edge %d: %d->%d \n", e, graph->tail[e], graph->head[e]);
1762  assert(graph->tail[e] == starcenter);
1763  extdata->extstack_data[i] = e;
1764  }
1765 
1766  extInnerNodeAdd(graph, starcenter, extdata);
1767 
1768 #ifdef SCIP_DEBUG
1769  printf(" \n");
1770 #endif
1771 }
1772 
1773 
1774 
1775 /** adds initial general star component edges to stack */
1776 /* NOTE: it is vital the the first edge of the star component comes from the root! */
1777 static inline
1779  SCIP* scip, /**< SCIP data structure */
1780  const GRAPH* graph, /**< graph data structure */
1781  const EXTCOMP* extcomp, /**< component to be checked */
1782  EXTDATA* extdata /**< extension data */
1783 )
1784 {
1785  const int* const compedges = extcomp->compedges;
1786  const int ncompedges = extcomp->ncompedges;
1787  const int rootedge = compedges[0];
1788  const int starcenter = graph->head[rootedge];
1789  const int comproot = extcomp->comproot;
1790  const int centeredge = extdata->genstar_centeredge;
1791  const int centerhead = graph->head[centeredge];
1792 
1793  assert(extInitialCompIsGenStar(extdata));
1794  assert(ncompedges >= 3);
1795  assert(graph->tail[rootedge] == comproot);
1796  assert(graph_edge_isInRange(graph, extdata->genstar_centeredge));
1797  assert(graph->tail[centeredge] == starcenter);
1798 
1799 #ifdef SCIP_DEBUG
1800  printf("\n --- ADD initial GENERAL star component --- \n\n");
1801  SCIPdebugMessage("...root star edge %d: %d->%d \n", rootedge, comproot, starcenter);
1802  SCIPdebugMessage("...center star edge %d: %d->%d \n", centeredge, starcenter, centerhead);
1803 #endif
1804 
1805  extdata->extstack_data[0] = rootedge;
1806  /* NOTE: one time for root edge, one time for center edge */
1807  extdata->tree_deg[starcenter] = 2;
1808  extdata->tree_parentNode[starcenter] = comproot;
1809  extdata->tree_parentEdgeCost[starcenter] = graph->cost[rootedge];
1810  extdata->tree_starcenter = starcenter;
1811 
1812  extdata->extstack_data[1] = centeredge;
1813  extdata->tree_deg[centerhead] = 1;
1814  extdata->tree_parentNode[centerhead] = starcenter;
1815  extdata->tree_parentEdgeCost[centerhead] = graph->cost[centeredge];
1816 
1817  for( int i = 1; i < ncompedges; i++ )
1818  {
1819  const int e = compedges[i];
1820 
1821  SCIPdebugMessage("...star edge %d: %d->%d \n", e, graph->tail[e], graph->head[e]);
1822 
1823  extdata->tree_deg[graph->tail[e]]++;
1824  extdata->extstack_data[i + 1] = e;
1825  }
1826 
1827  assert(extdata->tree_deg[starcenter] >= 2);
1828  assert(extdata->tree_deg[centerhead] >= 2);
1829 
1830  extInnerNodeAdd(graph, starcenter, extdata);
1831  extInnerNodeAdd(graph, centerhead, extdata);
1832 
1833 #ifdef SCIP_DEBUG
1834  printf(" \n");
1835 #endif
1836 }
1837 
1838 
1839 /** Initial component preprocessing:
1840  * The component root is added to the tree and the stack,
1841  * and the remainder is added to the stack to allow for further expansion. */
1842 static inline
1844  SCIP* scip, /**< SCIP data structure */
1845  const GRAPH* graph, /**< graph data structure */
1846  const EXTCOMP* extcomp, /**< component to be checked */
1847  EXTDATA* extdata /**< extension data */
1848 )
1849 {
1850  SCIP_Real* redcost_treenodeswap = extdata->reddata->redcost_treenodeswaps;
1851  const int ncompedges = extcomp->ncompedges;
1852  const int comproot = extcomp->comproot;
1853  const SCIP_Bool compIsEdge = (ncompedges == 1);
1854  const SCIP_Bool compIsGenStar = extInitialCompIsGenStar(extdata);
1855  const int redcost_nlevels = extdata->reddata->redcost_nlevels;
1856  const int nnodes = graph->knots;
1857 
1858  assert(ncompedges >= 1 && ncompedges < STP_EXT_MAXGRAD);
1859  assert(comproot >= 0 && comproot < graph->knots);
1860  assert(redcost_nlevels >= 1);
1861 
1862  if( compIsEdge )
1863  extPreprocessInitialEdge(scip, graph, extcomp, extdata);
1864  else if( compIsGenStar )
1865  extPreprocessInitialGenStar(scip, graph, extcomp, extdata);
1866  else
1867  extPreprocessInitialStar(scip, graph, extcomp, extdata);
1868 
1869  /* for now, only the component root is marked as a leaf */
1870  extreduce_mstAddRootLevel(scip, comproot, extdata);
1871  extLeafAdd(comproot, extdata);
1872 
1873  extdata->tree_root = comproot;
1874  extdata->extstack_ncomponents = 1;
1875  extdata->extstack_state[0] = EXT_STATE_NONE;
1876  extdata->extstack_start[0] = 0;
1877  extdata->extstack_start[1] = ncompedges;
1878  extdata->tree_parentNode[comproot] = -1;
1879  extdata->tree_parentEdgeCost[comproot] = -1.0;
1880 
1881  for( int i = 0; i < redcost_nlevels; i++ )
1882  redcost_treenodeswap[comproot + i * nnodes] = 0.0;
1883 
1884  if( compIsGenStar )
1885  {
1886  /* center edge is also included... */
1887  extdata->extstack_start[1]++;
1888  }
1889 
1890  assert(extdata->tree_leaves[0] == comproot);
1891  assert(extdata->tree_deg[comproot] == 0);
1892  assert(extdata->tree_nleaves == 1);
1893 
1894  extdata->tree_deg[comproot] = 1;
1895 }
1896 
1897 
1898 /** helper for rule-out during initial component processing */
1899 static inline
1901  const GRAPH* graph, /**< graph data structure */
1902  const EXTCOMP* extcomp, /**< component to be checked */
1903  EXTDATA* extdata /**< extension data */
1904 )
1905 {
1906  const PSEUDOANS* const pseudoancestors = graph->pseudoancestors;
1907  const int* const compedges = extcomp->compedges;
1908  int* const pseudoancestor_mark = extdata->reddata->pseudoancestor_mark;
1909  const int ncompedges = extcomp->ncompedges;
1910 
1911  /* necessary because these edges will be deleted in clean-up otherwise */
1912  for( int i = 0; i < ncompedges; i++ )
1913  {
1914  graph_pseudoAncestors_unhashEdge(pseudoancestors, compedges[i], pseudoancestor_mark);
1915  }
1916 
1917  if( extInitialCompIsGenStar(extdata) )
1918  {
1919  const int centeredge = extcomp->genstar_centeredge;
1920  assert(graph_edge_isInRange(graph, centeredge));
1921 
1922  graph_pseudoAncestors_unhashEdge(pseudoancestors, centeredge, pseudoancestor_mark);
1923  }
1924 }
1925 
1926 
1927 /** Adds extensions initial component to stack (needs to be star component rooted in root).
1928  * If no extensions are added, then the component has been ruled-out. */
1929 static inline
1931  SCIP* scip, /**< SCIP data structure */
1932  const GRAPH* graph, /**< graph data structure */
1933  const EXTCOMP* extcomp, /**< component to be checked */
1934  EXTDATA* extdata, /**< extension data */
1935  SCIP_Bool* ruledOut, /**< initial component ruled out? */
1936  SCIP_Bool* isExtendable /**< extension possible? */
1937 )
1938 {
1939  SCIP_Bool conflict = FALSE;
1940 
1941  assert(FALSE == (*ruledOut) && TRUE == (*isExtendable));
1942 
1943  extPreprocessInitialComponent(scip, graph, extcomp, extdata);
1944  extStackTopExpandInitial(scip, graph, extdata, ruledOut);
1945 
1946  assert(extStackGetPosition(extdata) == 0);
1947 
1948  /* early rule-out? */
1949  if( *ruledOut )
1950  {
1951  return;
1952  }
1953 
1954  assert(extdata->extstack_state[0] == EXT_STATE_EXPANDED);
1955 
1956  extTreeStackTopAdd(scip, graph, extdata, &conflict);
1957 
1958  if( conflict )
1959  {
1960  assert(extInitialCompIsStar(extdata) || extInitialCompIsGenStar(extdata));
1961  *ruledOut = TRUE;
1962  return;
1963  }
1964 
1965  assert(extdata->tree_deg[extdata->tree_root] == 1);
1966  assert(extdata->tree_deg[graph->head[extdata->extstack_data[0]]] == extcomp->ncompedges
1967  || extInitialCompIsGenStar(extdata));
1968 
1969  /* NOTE: anyway necessary to keep the MST graph up-to-date! */
1970  if( extTreeRuleOutPeriph(scip, graph, extdata) )
1971  {
1972  *ruledOut = TRUE;
1973  extUnhashInitialComponent(graph, extcomp, extdata);
1974  return;
1975  }
1976 
1977  /* the initial component could not be ruled-out, so set its stage to 'marked' */
1978  extdata->extstack_state[0] = EXT_STATE_MARKED;
1979  assert(extStackGetPosition(extdata) == 0);
1980  extExtend(scip, graph, extdata, isExtendable);
1981 
1982  if( !(*isExtendable) )
1983  {
1984  extUnhashInitialComponent(graph, extcomp, extdata);
1985  }
1986 
1987  assert(*isExtendable || extcomp->ncompedges >= 3);
1988 }
1989 
1990 
1991 /** Checks whether component 'extcomp' (star or single edge) can be ruled out. */
1992 static
1994  SCIP* scip, /**< SCIP data structure */
1995  const GRAPH* graph, /**< graph data structure */
1996  const EXTCOMP* extcomp, /**< initial component to be checked */
1997  EXTDATA* extdata, /**< extension data */
1998  SCIP_Bool* deletable /**< is component deletable? */
1999 )
2000 {
2001  int* const extstack_state = extdata->extstack_state;
2002  SCIP_Bool success = TRUE;
2003  SCIP_Bool conflict = FALSE;
2004 
2005  assert(extreduce_extdataIsClean(graph, extdata));
2006  assert(extreduce_reddataIsClean(graph, extdata->reddata));
2007  assert(extreduce_pcdataIsClean(graph, extdata->pcdata));
2008  assert(FALSE == (*deletable));
2009 
2010  /* put initial component on the stack */
2011  extProcessInitialComponent(scip, graph, extcomp, extdata, deletable, &success);
2012 
2013  /* early rule-out? or no extension possible? */
2014  if( *deletable || !success )
2015  {
2016  extreduce_extCompClean(scip, graph, extcomp, FALSE, extdata);
2017  return;
2018  }
2019 
2020  assert(extstack_state[0] == EXT_STATE_MARKED);
2021 
2022  /* limited DFS backtracking; stops once back at initial component */
2023  while( extdata->extstack_ncomponents > 1 )
2024  {
2025  const int stackposition = extStackGetPosition(extdata);
2026  conflict = FALSE;
2027 
2028  extTreeSyncWithStack(scip, graph, extdata, &conflict);
2029 
2030  /* has current component already been extended? */
2031  if( extstack_state[stackposition] == EXT_STATE_MARKED )
2032  {
2033  extBacktrack(scip, graph, success, FALSE, extdata);
2034  continue;
2035  }
2036 
2037  /* component not expanded yet or is wrapped? */
2038  if( extstack_state[stackposition] != EXT_STATE_EXPANDED || extStackTopIsWrapped(extdata) )
2039  {
2040  assert(extstack_state[stackposition] == EXT_STATE_NONE || extStackTopIsWrapped(extdata));
2041 
2042  extStackTopExpand(scip, graph, extdata, &success);
2043  continue;
2044  }
2045 
2046  assert(extstack_state[stackposition] == EXT_STATE_EXPANDED);
2047 
2048  if( conflict || extTreeRuleOutPeriph(scip, graph, extdata) )
2049  {
2050  success = TRUE;
2051  extBacktrack(scip, graph, success, conflict, extdata);
2052  continue;
2053  }
2054 
2055  /* the component could not be ruled-out, so set its stage to 'marked' */
2056  extstack_state[stackposition] = EXT_STATE_MARKED;
2057 
2058  if( extTruncate(graph, extdata) )
2059  {
2060  success = FALSE;
2061  extBacktrack(scip, graph, success, FALSE, extdata);
2062  continue;
2063  }
2064 
2065  /* neither ruled out nor truncated, so extend */
2066  extExtend(scip, graph, extdata, &success);
2067 
2068  } /* DFS loop */
2069 
2070  *deletable = success;
2071 
2072  extreduce_extCompClean(scip, graph, extcomp, TRUE, extdata);
2073 }
2074 
2075 /*
2076  * Interface methods
2077  */
2078 
2079 
2080 /** check component for possible elimination */
2082  SCIP* scip, /**< SCIP data structure */
2083  const GRAPH* graph, /**< graph data structure */
2084  const REDCOST* redcostdata, /**< reduced cost data structures */
2085  EXTCOMP* extcomp, /**< component to be checked (might be reverted) */
2086  EXTPERMA* extpermanent, /**< extension data */
2087  SCIP_Bool* compIsDeletable /**< is component deletable? */
2088 )
2089 {
2090  int* extstack_data;
2091  int* extstack_start;
2092  int* extstack_state;
2093  int* tree_edges;
2094  int* tree_leaves;
2095  int* tree_innerNodes;
2096  int* tree_parentNode;
2097  int* pcSdCands = NULL;
2098  SCIP_Real* tree_parentEdgeCost;
2099  SCIP_Real* redcost_treenodeswaps;
2100  SCIP_Real* redcost_treecosts;
2101  int* pseudoancestor_mark = NULL;
2102  SCIP_Bool* redcost_noReversedTree;
2103  SCIP_Bool* sdeq_edgesIsForbidden;
2104  const int nnodes = graph->knots;
2105  const int redcosts_nlevels = redcosts_getNlevels(redcostdata);
2106  const int maxstacksize = extreduce_getMaxStackSize();
2107  const int maxncomponents = extreduce_getMaxStackNcomponents(graph);
2108 
2109  assert(!(*compIsDeletable));
2110  assert(extreduce_extCompFullIsPromising(graph, extpermanent, extcomp) || (extcomp->ncompedges > 1));
2111  assert(redcosts_nlevels > 0 && maxstacksize > 0 && maxncomponents > 0 && nnodes > 0);
2112 
2113  SCIP_CALL( SCIPallocBufferArray(scip, &extstack_data, maxstacksize) );
2114  SCIP_CALL( SCIPallocBufferArray(scip, &extstack_start, maxncomponents + 1) );
2115  SCIP_CALL( SCIPallocBufferArray(scip, &extstack_state, maxncomponents + 1) );
2116  SCIP_CALL( SCIPallocBufferArray(scip, &tree_edges, nnodes) );
2117  SCIP_CALL( SCIPallocBufferArray(scip, &tree_leaves, nnodes) );
2118  SCIP_CALL( SCIPallocBufferArray(scip, &tree_innerNodes, nnodes) );
2119  SCIP_CALL( SCIPallocBufferArray(scip, &tree_parentNode, nnodes) );
2120  SCIP_CALL( SCIPallocBufferArray(scip, &tree_parentEdgeCost, nnodes) );
2121  SCIP_CALL( SCIPallocBufferArray(scip, &redcost_treenodeswaps, nnodes * redcosts_nlevels) );
2122  SCIP_CALL( SCIPallocBufferArray(scip, &redcost_treecosts, redcosts_nlevels) );
2123  SCIP_CALL( SCIPallocBufferArray(scip, &redcost_noReversedTree, redcosts_nlevels) );
2124 
2125  if( graph_pc_isPc(graph) )
2126  {
2127  SCIP_CALL( SCIPallocBufferArray(scip, &pcSdCands, nnodes) );
2128  }
2129 
2131  {
2133  }
2134  SCIP_CALL( SCIPallocCleanBufferArray(scip, &sdeq_edgesIsForbidden, graph->edges / 2) );
2135 
2136  {
2137  const SCIP_Bool* isterm = extpermanent->isterm;
2138 
2139  PCDATA pcdata = { .pcSdToNode = extpermanent->pcSdToNode, .pcSdCands = pcSdCands, .nPcSdCands = -1,
2140  .pcSdStart = -1, .tree_innerPrize = 0.0 };
2141  REDDATA reddata = { .contration = extpermanent->contration,
2142  .dcmst = extpermanent->dcmst, .msts_comp = extpermanent->msts_comp,
2143  .msts_levelbase = extpermanent->msts_levelbase,
2144  .sds_horizontal = extpermanent->sds_horizontal, .sds_vertical = extpermanent->sds_vertical,
2145  .sdsbias_horizontal = extpermanent->sdsbias_horizontal, .sdsbias_vertical = extpermanent->sdsbias_vertical,
2146  .edgedeleted = extpermanent->edgedeleted, .pseudoancestor_mark = pseudoancestor_mark,
2147  .nodes_implications = extpermanent->nodes_implications,
2148  .redcost_treenodeswaps = redcost_treenodeswaps, .redcost_treecosts = redcost_treecosts,
2149  .redcost_noReversedTree = redcost_noReversedTree,
2150  .redcost_nlevels = redcosts_nlevels, .redcost_allowEquality = extpermanent->redcostEqualAllow,
2151  .sdsbias_use = extpermanent->useSdBias };
2152  EXTDATA extdata = { .extstack_data = extstack_data, .extstack_start = extstack_start,
2153  .extstack_state = extstack_state, .extstack_ncomponents = 0, .tree_leaves = tree_leaves,
2154  .tree_edges = tree_edges, .tree_deg = extpermanent->tree_deg, .tree_nleaves = 0,
2155  .tree_bottleneckDistNode = extpermanent->bottleneckDistNode, .tree_parentNode = tree_parentNode,
2156  .tree_parentEdgeCost = tree_parentEdgeCost, .tree_cost = 0.0, .ncostupdatestalls = 0,
2157  .tree_nDelUpArcs = 0, .tree_root = -1, .tree_starcenter = -1, .tree_nedges = 0, .tree_depth = 0,
2158  .extstack_maxsize = maxstacksize, .extstack_maxncomponents = maxncomponents,
2159  .pcdata = &pcdata, .redcostdata = redcostdata,
2160  .sdeq_resetStack = NULL, .sdeq_edgesIsForbidden = sdeq_edgesIsForbidden, .sdeq_hasForbiddenEdges = FALSE,
2161  .genstar_centeredge = extcomp->genstar_centeredge,
2162  .tree_innerNodes = tree_innerNodes, .tree_ninnerNodes = 0,
2163  .tree_maxdepth = extpermanent->tree_maxdepth,
2164  .tree_maxnleaves = extpermanent->tree_maxnleaves,
2165  .tree_maxnedges = extpermanent->tree_maxnedges, .node_isterm = isterm, .reddata = &reddata,
2166  .distdata = extpermanent->distdata_default, .distdata_biased = extpermanent->distdata_biased,
2167  .mode = extpermanent->mode, .extcomp = extcomp };
2168 
2169 #ifdef STP_DEBUG_EXT
2170  extreduce_extdataCleanArraysDbg(graph, &extdata);
2171 #endif
2172 
2173  extreduce_reddataClean(&reddata);
2174 
2175  if( extreduce_extCompIsPromising(graph, extpermanent, extcomp) )
2176  extProcessComponent(scip, graph, extcomp, &extdata, compIsDeletable);
2177 
2178  /* also try the other way? */
2179  if( !(*compIsDeletable) && extcomp->allowReversion )
2180  {
2181  extreduce_extCompRevert(graph, extpermanent, extcomp);
2182 
2183  if( extreduce_extCompIsPromising(graph, extpermanent, extcomp) )
2184  {
2185  extProcessComponent(scip, graph, extcomp, &extdata, compIsDeletable);
2186  }
2187  }
2188  }
2189 
2190  assert(extreduce_extPermaIsClean(graph, extpermanent));
2191 
2192  SCIPfreeCleanBufferArray(scip, &sdeq_edgesIsForbidden);
2193  if( pseudoancestor_mark )
2194  SCIPfreeCleanBufferArray(scip, &pseudoancestor_mark);
2195 
2196  SCIPfreeBufferArrayNull(scip, &pcSdCands);
2197 
2198  SCIPfreeBufferArray(scip, &redcost_noReversedTree);
2199  SCIPfreeBufferArray(scip, &redcost_treecosts);
2200  SCIPfreeBufferArray(scip, &redcost_treenodeswaps);
2201  SCIPfreeBufferArray(scip, &tree_parentEdgeCost);
2202  SCIPfreeBufferArray(scip, &tree_parentNode);
2203  SCIPfreeBufferArray(scip, &tree_innerNodes);
2204  SCIPfreeBufferArray(scip, &tree_leaves);
2205  SCIPfreeBufferArray(scip, &tree_edges);
2206  SCIPfreeBufferArray(scip, &extstack_state);
2207  SCIPfreeBufferArray(scip, &extstack_start);
2208  SCIPfreeBufferArray(scip, &extstack_data);
2209 
2210  return SCIP_OKAY;
2211 }
#define STP_Vectype(type)
Definition: stpvector.h:44
static void extStackTopProcessInitialEdges(SCIP *scip, const GRAPH *graph, EXTDATA *extdata, SCIP_Bool *initialRuleOut)
void extreduce_mstLevelClose(SCIP *, const GRAPH *, int, EXTDATA *)
void graph_pseudoAncestors_unhashEdge(const PSEUDOANS *, int, int *)
void extreduce_extendInitDebug(int *, int *)
static SCIP_Bool ksubsetGetNext(int k, int n, SCIP_Bool isFirstSubset, int *ksubset)
static void extPreprocessInitialEdge(SCIP *scip, const GRAPH *graph, const EXTCOMP *extcomp, EXTDATA *extdata)
#define StpVecGetSize(vec)
Definition: stpvector.h:139
static void extStackTopExpandInitial(SCIP *scip, const GRAPH *graph, EXTDATA *extdata, SCIP_Bool *initialRuleOut)
static SCIP_Bool extInitialCompIsGenStar(const EXTDATA *extdata)
void extreduce_mstLevelVerticalRemove(REDDATA *)
int *RESTRICT head
Definition: graphdefs.h:224
enum EXTRED_MODE mode
static SCIP_Bool extTreeRuleOutEdgeSimple(const GRAPH *graph, EXTDATA *extdata, int edge)
#define EXT_EDGE_WRAPPED
Definition: extreducedefs.h:49
static void extPreprocessInitialComponent(SCIP *scip, const GRAPH *graph, const EXTCOMP *extcomp, EXTDATA *extdata)
static void extStackTopExpand(SCIP *scip, const GRAPH *graph, EXTDATA *extdata, SCIP_Bool *success)
static int extLeafFindPos(const EXTDATA *extdata, int leaf)
SCIP_Bool extreduce_treeIsFlawed(SCIP *, const GRAPH *, const EXTDATA *)
#define Is_term(a)
Definition: graphdefs.h:102
static void extBacktrack(SCIP *scip, const GRAPH *graph, SCIP_Bool success, SCIP_Bool ancestor_conflict, EXTDATA *extdata)
SCIP_Bool extreduce_extCompIsPromising(const GRAPH *, const EXTPERMA *, const EXTCOMP *)
const int extstack_maxsize
static void extStackAddCompInitialExpanded(SCIP *scip, const GRAPH *graph, EXTDATA *extdata)
int redcosts_getNlevels(const REDCOST *redcostdata)
Definition: redcosts.c:369
static SCIP_Bool extTreeRuleOutPeriph(SCIP *scip, const GRAPH *graph, EXTDATA *extdata)
static SCIP_Bool extIsAtInitialStar(const EXTDATA *extdata)
static SCIP_Bool extTreeRuleOutSingletonImplied(SCIP *scip, const GRAPH *graph, EXTDATA *extdata)
const int extstack_maxncomponents
static SCIP_Bool extStackTopIsWrapped(const EXTDATA *extdata)
SCIP_Real tree_innerPrize
static void extTreeStackTopRemove(const GRAPH *graph, SCIP_Bool ancestor_conflict, EXTDATA *extdata)
int graph_pseudoAncestorsGetHashArraySize(const PSEUDOANS *)
int extreduce_getMaxStackNcomponents(const GRAPH *)
SCIP_Bool extreduce_contractionRuleOutPeriph(SCIP *, const GRAPH *, EXTDATA *)
static void extInnerNodeRemoveTop(const GRAPH *graph, int innernode, EXTDATA *extdata)
#define FALSE
Definition: def.h:87
int *const pseudoancestor_mark
void extreduce_mstLevelVerticalReopen(EXTDATA *)
SCIP_Bool extreduce_extCompFullIsPromising(const GRAPH *, const EXTPERMA *, const EXTCOMP *)
#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
static SCIP_Bool extInitialCompIsEdge(const EXTDATA *extdata)
int *const extstack_data
SCIP_Bool extreduce_treeIsHashed(const GRAPH *, const EXTDATA *)
int *const tree_edges
void extreduce_mstLevelVerticalAddEmpty(const GRAPH *, EXTDATA *)
static void extStackAddCompsExpandedSing(SCIP *scip, const GRAPH *graph, int nextedges, const int *extedges, EXTDATA *extdata, SCIP_Bool *success, SCIP_Bool *ruledOut)
static int extStackGetTopOutEdgesStart(const EXTDATA *extdata, int stackpos)
void SCIPsortDownIntInt(int *intarray1, int *intarray2, int len)
static void extLeafRemove(int leaf, EXTDATA *extdata)
#define EXT_STATE_EXPANDED
Definition: extreducedefs.h:53
static SCIP_Bool extStackTopIsSingleton(const EXTDATA *extdata)
SCIP_Bool extreduce_redcostRuleOutPeriph(const GRAPH *, EXTDATA *)
#define EAT_LAST
Definition: graphdefs.h:58
static SCIP_Bool extInitialCompIsStar(const EXTDATA *extdata)
#define SCIPdebugMessage
Definition: pub_message.h:87
static int extStackGetTopOutEdgesEnd(const EXTDATA *extdata, int stackpos)
static int extStackGetPosition(const EXTDATA *extdata)
static void extStackTopCollectExtEdges(SCIP *scip, const GRAPH *graph, EXTDATA *extdata, int *extedges, int *nextedges)
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:127
void extreduce_reddataClean(REDDATA *)
REDDATA *const reddata
void extreduce_mstLevelHorizontalAdd(SCIP *, const GRAPH *, int, const int *, EXTDATA *)
void extreduce_mstLevelRemove(REDDATA *)
const EXTCOMP *const extcomp
#define SCIPallocCleanBufferArray(scip, ptr, num)
Definition: scip_mem.h:133
SCIP_RETCODE extreduce_checkComponent(SCIP *scip, const GRAPH *graph, const REDCOST *redcostdata, EXTCOMP *extcomp, EXTPERMA *extpermanent, SCIP_Bool *compIsDeletable)
int *const tree_leaves
int *RESTRICT oeat
Definition: graphdefs.h:231
static void extTreeFindExtensions(SCIP *scip, const GRAPH *graph, EXTDATA *extdata, int *extedgesstart, int *extedges, int *nextensions, int *nextendableleaves, SCIP_Bool *with_ruledout_leaf)
This file implements extended reduction techniques for several Steiner problems.
void extreduce_redcostAddEdge(const GRAPH *, int, REDDATA *, EXTDATA *)
static void extInnerNodeAdd(const GRAPH *graph, int innernode, EXTDATA *extdata)
static int extStackGetPrevMarked(const EXTDATA *extdata)
#define GE(a, b)
Definition: portab.h:85
void extreduce_mstLevelVerticalAddLeaf(SCIP *, const GRAPH *, int, EXTDATA *, SCIP_Bool *)
void extreduce_printStack(const GRAPH *, const EXTDATA *)
#define EXT_STATE_MARKED
Definition: extreducedefs.h:54
SCIP_Real *const pcSdToNode
static SCIP_Bool extStackIsExtendable(int nextedges, int nnewcomps, int stack_datasize, const EXTDATA *extdata)
void extreduce_mstLevelHorizontalAddEmpty(const GRAPH *, EXTDATA *)
int *const tree_parentNode
void extreduce_mstAddRootLevel(SCIP *, int, EXTDATA *)
PSEUDOANS * pseudoancestors
Definition: graphdefs.h:236
static void extUnhashInitialComponent(const GRAPH *graph, const EXTCOMP *extcomp, EXTDATA *extdata)
int *const tree_innerNodes
static SCIP_Bool extIsAtInitialComp(const EXTDATA *extdata)
static SCIP_Bool extTruncate(const GRAPH *graph, const EXTDATA *extdata)
SCIP_Real * bottleneckDistNode
static SCIP_Bool extensionHasImplicationConflict(const GRAPH *graph, const STP_Vectype(int) implications, const int *tree_deg, int tree_root, const int *extedges, int nextedges)
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip_mem.h:128
SCIP_Real * prize
Definition: graphdefs.h:210
void extreduce_treeRecompCosts(SCIP *, const GRAPH *, EXTDATA *)
void extreduce_mstCompRemove(const GRAPH *, EXTDATA *)
void extreduce_redcostInitExpansion(const GRAPH *, EXTDATA *)
const int tree_maxnedges
#define NULL
Definition: lpi_spx1.cpp:155
int *const extstack_state
static void extTreeStackTopAdd(SCIP *scip, const GRAPH *graph, EXTDATA *extdata, SCIP_Bool *conflict)
int knots
Definition: graphdefs.h:190
CONTRACT * contration
#define SCIP_CALL(x)
Definition: def.h:384
const int tree_maxdepth
static int extStackGetOutEdgesEnd(const EXTDATA *extdata, int stackpos)
static void extProcessInitialComponent(SCIP *scip, const GRAPH *graph, const EXTCOMP *extcomp, EXTDATA *extdata, SCIP_Bool *ruledOut, SCIP_Bool *isExtendable)
void extreduce_mstLevelHorizontalRemove(REDDATA *)
static int extStackTopGetInitalDataStart(const EXTDATA *extdata)
SCIP_Bool extreduce_extdataIsClean(const GRAPH *, const EXTDATA *)
static void extLeafAdd(int leaf, EXTDATA *extdata)
static int extStackGetOutEdgesStart(const EXTDATA *extdata, int stackpos)
const int tree_maxnleaves
static SCIP_Bool extTreeRuleOutSingletonFull(SCIP *scip, const GRAPH *graph, EXTDATA *extdata)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:115
#define SCIP_Bool
Definition: def.h:84
void extreduce_mstLevelInitialInit(REDDATA *, EXTDATA *)
includes extended reductions definitions and inline methods used for Steiner tree problems ...
int *RESTRICT tail
Definition: graphdefs.h:223
int *const extstack_start
#define EXT_COSTS_RECOMPBOUND
static void extStackAddCompsNonExpanded(const GRAPH *graph, const int *extedgesstart, const int *extedges, int nextendable_leaves, EXTDATA *extdata)
void extreduce_mstLevelVerticalClose(REDDATA *)
SCIP_Real *const redcost_treenodeswaps
SCIP_Bool extreduce_pcdataIsClean(const GRAPH *, const PCDATA *)
static void extStackAddCompsExpanded(SCIP *scip, const GRAPH *graph, int nextedges, const int *extedges, EXTDATA *extdata, SCIP_Bool *success, SCIP_Bool *ruledOut)
int *RESTRICT term
Definition: graphdefs.h:196
PCDATA *const pcdata
SCIP_Bool extreduce_extPermaIsClean(const GRAPH *, const EXTPERMA *)
void graph_edge_printInfo(const GRAPH *, int)
Definition: graph_stats.c:133
static void extTreeSyncWithStack(SCIP *scip, const GRAPH *graph, EXTDATA *extdata, SCIP_Bool *conflict)
SCIP_Bool graph_pc_isPc(const GRAPH *)
const SCIP_Bool *const node_isterm
static void extExtend(SCIP *scip, const GRAPH *graph, EXTDATA *extdata, SCIP_Bool *success)
Portable definitions.
#define EXT_STATE_NONE
Definition: extreducedefs.h:52
static void extPreprocessInitialStar(SCIP *scip, const GRAPH *graph, const EXTCOMP *extcomp, EXTDATA *extdata)
int extreduce_mldistsTopLevel(const MLDISTS *)
SCIP_Bool extreduce_reddataIsClean(const GRAPH *, const REDDATA *)
SCIP_Real * cost
Definition: graphdefs.h:221
void extreduce_redcostRemoveEdge(int, const REDDATA *, EXTDATA *)
SCIP_Bool graph_edge_isInRange(const GRAPH *, int)
Definition: graph_stats.c:110
const int redcost_nlevels
int extreduce_getMaxStackSize(void)
static SCIP_Bool ruledOut(SCIP *scip, const GRAPH *graph, EXTDATA *extdata)
#define STP_EXT_MAXGRAD
Definition: extreducedefs.h:42
static void extStackTopExpandSingletons(SCIP *scip, const GRAPH *graph, EXTDATA *extdata, SCIP_Bool *success)
SCIP_Bool extreduce_mldistsLevelContainsBase(const MLDISTS *, int, int)
#define SCIP_Real
Definition: def.h:177
#define SCIPfreeCleanBufferArray(scip, ptr)
Definition: scip_mem.h:137
void graph_pseudoAncestors_hashEdgeDirty(const PSEUDOANS *, int, SCIP_Bool, SCIP_Bool *, int *)
MLDISTS *const sds_vertical
int *RESTRICT outbeg
Definition: graphdefs.h:204
#define SCIP_Longint
Definition: def.h:162
int edges
Definition: graphdefs.h:219
SCIP_Bool graph_knot_isInRange(const GRAPH *, int)
Definition: graph_node.c:52
static void extTreeAddEdge(const GRAPH *graph, int edge, EXTDATA *extdata)
int *const tree_deg
#define nnodes
Definition: gastrans.c:65
SCIP_Bool extreduce_mstRuleOutPeriph(SCIP *, const GRAPH *, EXTDATA *)
static void extStackTopCollectExtEdgesSing(SCIP *scip, const GRAPH *graph, EXTDATA *extdata, int *extedges, int *nextedges)
SCIP_Bool extreduce_mstTopCompInSync(SCIP *, const GRAPH *, EXTDATA *)
static int extStackGetTopRoot(const GRAPH *graph, const EXTDATA *extdata)
#define SCIP_CALL_ABORT(x)
Definition: def.h:363
static void extPreprocessInitialGenStar(SCIP *scip, const GRAPH *graph, const EXTCOMP *extcomp, EXTDATA *extdata)
SCIP_Bool graph_pseudoAncestors_edgeIsHashed(const PSEUDOANS *, int, const int *)
void extreduce_mstLevelVerticalAddLeafInitial(SCIP *, const GRAPH *, int, EXTDATA *, SCIP_Bool *)
SCIP_Real tree_cost
static void extStackTopExpandWrapped(SCIP *scip, const GRAPH *graph, EXTDATA *extdata, SCIP_Bool *success)
void extreduce_extdataCleanArraysDbg(const GRAPH *, EXTDATA *)
void extreduce_extCompRevert(const GRAPH *, const EXTPERMA *, EXTCOMP *)
void extreduce_extCompClean(SCIP *, const GRAPH *, const EXTCOMP *, SCIP_Bool, EXTDATA *)
static void extProcessComponent(SCIP *scip, const GRAPH *graph, const EXTCOMP *extcomp, EXTDATA *extdata, SCIP_Bool *deletable)
static void extTreeStackTopRootRemove(const GRAPH *graph, EXTDATA *extdata)
static void extLeafRemoveTop(const GRAPH *graph, int topsize, int toproot, EXTDATA *extdata)
static SCIP_Bool extLeafIsExtendable(const GRAPH *graph, const SCIP_Bool *isterm, int leaf)
SCIP_Real *const tree_parentEdgeCost