Scippy

SCIP

Solving Constraint Integer Programs

extreduce_extmst.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_extmst.c
17  * @brief extended-reduction specific MST algorithms for Steiner tree problems
18  * @author Daniel Rehfeldt
19  *
20  * This file implements MST algorithms for extended reduction techniques for Steiner problems.
21  * Allows to efficiently compute and store special distance (SD) MSTs between the leaves of extension tree.
22  * Furthermore, one can check for tree bottlenecks.
23  *
24  * A 'level' of the extension tree consists of all possible extension edges from the leaf used for extension.
25  * For each level there are a number of 'components': all the subsets that were not already ruled-out.
26  * Once a level is initiated, all SDs to the other leaves of the tree are computed ('vertical'),
27  * as well as the SDs among the level ('horizontal').
28  * These SDs are kept until the level has been removed again.
29  * Furthermore, for each level of the tree we store two SD MSTs, namely:
30  * 1. the MST corresponding to the extension tree without the level and without the tree node at which the level
31  * is rooted: 'msts_levelbase'
32  * 2. the MST corresponding to the component of this level in the current tree: "msts_comp'
33  *
34  * A list of all interface methods can be found in extreduce.h.
35  *
36  */
37 
38 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
39 // #define SCIP_DEBUG
40 //#define STP_DEBUG_EXT
41 
42 #include <string.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <assert.h>
46 #include "graph.h"
47 #include "portab.h"
48 #include "extreduce.h"
49 #include "extreducedefs.h"
50 
51 
52 #define EXT_PC_SDMAXVISITS 20 /**< maximum visits for PC specific SD computation */
53 #define EXT_DOUBLESD_ALWAYS
54 
56 {
57  const CSR* mst_parent; /**< parent MST (for which to use vertical SDs) */
58  CSR* mst_new; /**< new MST (out) */
59  const int* comp_nodes; /**< nodes of component */
60  int comp_vert; /**< current vertex */
61  int comp_extnode; /**< component node from which we extended; or -1 */
62  int comp_level; /**< level of component */
63  int comp_size; /**< size of component */
64  SCIP_Bool isExtended; /**< mst_new already extended? */
65 } MSTXCOMP;
66 
67 
68 /** returns special distance computed only for PC and for current leaf */
69 static inline
71  const GRAPH* g, /**< graph data structure */
72  const PCDATA* pcdata, /**< PC data */
73  int vertex1, /**< second vertex */
74  int vertex2, /**< second vertex */
75  SCIP_Real* sd /**< special distance */
76 )
77 {
78  const SCIP_Real sdpc = pcdata->pcSdToNode[vertex2];
79 
80  assert(graph_pc_isPcMw(g));
81  assert(pcdata->pcSdStart == vertex1);
82  assert(EQ(sdpc, -1.0) || GE(sdpc, 0.0));
83 
84  if( sdpc > -0.5 && (sdpc < *sd || *sd < -0.5) )
85  {
86  SCIPdebugMessage("special distance update for pc: %f to %f \n", *sd, sdpc);
87  *sd = sdpc;
88  }
89 }
90 
91 
92 /** Returns special distance.
93  * Checks normal distance from vertex2 to vertex1 if no opposite distance is known. */
94 static inline
96  SCIP* scip, /**< SCIP */
97  const GRAPH* g, /**< graph data structure */
98  int vertex1, /**< first vertex */
99  int vertex2, /**< second vertex */
100  EXTDATA* extdata /**< extension data */
101 )
102 {
103  SCIP_Real sd = extreduce_distDataGetSdDouble(scip, g, vertex1, vertex2, extdata->distdata);
104 
105  if( extProbIsPc(g, extdata) )
106  extGetSdPcUpdate(g, extdata->pcdata, vertex1, vertex2, &sd);
107 
108  assert(SCIPisEQ(scip, sd, -1.0) || SCIPisGE(scip, sd, 0.0));
109 
110  return sd;
111 }
112 
113 
114 
115 /** As above, but with given distance data */
116 static inline
118  SCIP* scip, /**< SCIP */
119  const GRAPH* g, /**< graph data structure */
120  int vertex1, /**< first vertex */
121  int vertex2, /**< second vertex */
122  DISTDATA* distdata, /**< distance data */
123  EXTDATA* extdata /**< extension data */
124 )
125 {
126  SCIP_Real sd = extreduce_distDataGetSdDouble(scip, g, vertex1, vertex2, distdata);
127 
128  if( extProbIsPc(g, extdata) )
129  extGetSdPcUpdate(g, extdata->pcdata, vertex1, vertex2, &sd);
130 
131  assert(SCIPisEQ(scip, sd, -1.0) || SCIPisGE(scip, sd, 0.0));
132 
133  return sd;
134 }
135 
136 
137 /** Returns special distance.
138  * Only checks normal distance from vertex1 to vertex2. */
139 static inline
141  SCIP* scip, /**< SCIP */
142  const GRAPH* g, /**< graph data structure */
143  int vertex1, /**< first vertex */
144  int vertex2, /**< second vertex */
145  EXTDATA* extdata /**< extension data */
146 )
147 {
148 #ifdef EXT_DOUBLESD_ALWAYS
149  return extGetSdDouble(scip, g, vertex1, vertex2, extdata);
150 #else
151  SCIP_Real sd = extreduce_distDataGetSd(scip, g, vertex1, vertex2, extdata->distdata);
152  const PCDATA* const pcdata = extdata->pcdata;
153 
154  assert((pcdata->pcSdToNode != NULL) == graph_pc_isPcMw(g));
155 
156  if( pcdata->pcSdToNode )
157  {
158  extGetSdPcUpdate(g, pcdata, vertex1, vertex2, &sd);
159  }
160 
161  assert(SCIPisEQ(scip, sd, -1.0) || SCIPisGE(scip, sd, 0.0));
162 
163  return sd;
164 #endif
165 }
166 
167 
168 /** returns position of last marked component */
169 static inline
171  const EXTDATA* extdata /**< extension data */
172 )
173 {
174  const int* const extstack_state = extdata->extstack_state;
175  int stackpos = extStackGetPosition(extdata);
176 
177  while( extstack_state[stackpos] != EXT_STATE_MARKED )
178  {
179  stackpos--;
180  assert(stackpos >= 0);
181  }
182 
183  return stackpos;
184 }
185 
186 
187 /** returns size of top component on the stack */
188 static inline
190  const EXTDATA* extdata /**< extension data */
191 )
192 {
193  const int stackpos = extStackGetPosition(extdata);
194  const int* const stack_start = extdata->extstack_start;
195  const int size = stack_start[stackpos + 1] - stack_start[stackpos];
196 
197  assert(extdata->extstack_state[stackpos] != EXT_STATE_NONE);
198  assert(size > 0 && size < STP_EXT_MAXGRAD);
199 
200  return size;
201 }
202 
203 
204 /** returns number of ancestor leaves (i.e. number of leaves below current level) */
205 static inline
207  const EXTDATA* extdata /**< extension data */
208 )
209 {
210  int nleaves_ancestors;
211 
212  if( extIsAtInitialComp(extdata) )
213  {
214  nleaves_ancestors = 1;
215  }
216  else
217  {
218  const int compsize = extStackGetTopSize(extdata);
219  const int nleaves = extdata->tree_nleaves;
220  nleaves_ancestors = nleaves - compsize;
221  }
222 
223  assert(nleaves_ancestors > 0 && nleaves_ancestors < extdata->tree_nleaves);
224 
225  return nleaves_ancestors;
226 }
227 
228 
229 /** Repeatedly extends MST 'new', starting from MST 'parent' (in 'mstextcomp').
230  * In first call 'new' is extended from 'parent', afterwards from itself */
231 static inline
233  SCIP* scip, /**< SCIP */
234  const SCIP_Real adjcosts[], /**< adjacency costs */
235  DCMST* dcmst, /**< DCMST */
236  MSTXCOMP* mstextcomp /**< extension component (in/out) */
237 )
238 {
239  const CSR* mst_parent = mstextcomp->mst_parent;
240  CSR* mst_new = mstextcomp->mst_new;
241 
242  /* first time we want to extend the MST? */
243  if( !mstextcomp->isExtended )
244  {
245  mst_new->nnodes = mst_parent->nnodes + 1;
246  mst_new->nedges_max = mst_parent->nedges_max + 2;
247  reduce_dcmstAddNode(scip, mst_parent, adjcosts, dcmst, mst_new);
248 
249  mstextcomp->isExtended = TRUE;
250  }
251  else
252  {
253  reduce_dcmstAddNodeInplace(scip, adjcosts, dcmst, mst_new);
254  }
255 
256  assert(mst_new->nnodes >= mst_parent->nnodes + 1);
257 }
258 
259 
260 /** fills MST adjacency costs for new vertex in */
261 static inline
263  const REDDATA* reddata, /**< reduction data */
264  MSTXCOMP* mstextcomp, /**< extension component (in/out) */
265  SCIP_Real adjcosts[] /**< adjacency costs (out) */
266 )
267 {
268  const MLDISTS* const sds_vertical = reddata->sds_vertical;
269  const MLDISTS* const sds_horizontal = reddata->sds_horizontal;
270  const CSR* const mst_parent = mstextcomp->mst_parent;
271  const int comp_vert = mstextcomp->comp_vert;
272  const int comp_extnode = mstextcomp->comp_extnode;
273  const int comp_level = mstextcomp->comp_level;
274  const int comp_size = mstextcomp->comp_size;
275  const int* const comp_nodes = mstextcomp->comp_nodes;
276  const int nnodes_parent = mst_parent->nnodes;
277  int adjpos = nnodes_parent;
278 
279  const SCIP_Real* const adjcosts_ancestors = extreduce_mldistsTargetDists(sds_vertical, comp_level, comp_vert);
280 
281  memcpy(adjcosts, adjcosts_ancestors, nnodes_parent * sizeof(adjcosts[0]));
282 
283  /* compute adjacent costs to left siblings of 'compvert' */
284  for( int j = 0; j < comp_size; j++ )
285  {
286  const int sibling = comp_nodes[j];
287 
288  if( sibling == comp_vert )
289  {
290  adjcosts[adjpos] = FARAWAY;
291  break;
292  }
293 
294  if( sibling == comp_extnode )
295  {
296  continue;
297  }
298 
299  adjcosts[adjpos++] = extreduce_mldistsTargetDist(sds_horizontal, comp_level, comp_vert, sibling);
300  }
301 }
302 
303 
304 /** Gets nodes of parent component ordered according to their position in the
305  * tree leaves array. */
306 static inline
308  const GRAPH* graph, /**< graph */
309  const EXTDATA* extdata, /**< extension data */
310  int* parentcomp_size, /**< size (number of nodes) of parent component */
311  int parentcomp_nodes[] /**< ordered nodes of parent component */
312 )
313 {
314  int leavespos[STP_EXT_MAXGRAD];
315  const int* const extstack_data = extdata->extstack_data;
316  const int stackpos_parent = extStackGetLastMarked(extdata);
317  const int parentedges_start = extStackGetOutEdgesStart(extdata, stackpos_parent);
318  const int parentedges_end = extStackGetOutEdgesEnd(extdata, stackpos_parent);
319  int compsize = 0;
320 
321  assert(parentedges_start < parentedges_end);
322 
323  for( int i = parentedges_start; i != parentedges_end; i++ )
324  {
325  const int edge = extstack_data[i];
326  const int compvert = graph->head[edge];
327 
328  assert(compsize < STP_EXT_MAXGRAD);
329  assert(edge >= 0 && edge < graph->edges);
330 
331  parentcomp_nodes[compsize] = compvert;
332  leavespos[compsize] = extLeafFindPos(extdata, compvert);
333 
334  assert(leavespos[compsize] > 0);
335 
336  compsize++;
337  }
338 
339  assert(compsize > 0);
340  assert(compsize == extreduce_extStackCompNOutedges(extdata, stackpos_parent));
341 
342  *parentcomp_size = compsize;
343 
344  SCIPsortIntInt(leavespos, parentcomp_nodes, compsize);
345 
346 }
347 
348 
349 /** initializes base MST data for old and new MSTs */
350 static inline
352  const EXTDATA* extdata, /**< extension data */
353  REDDATA* reddata, /**< reduction data (in/out) */
354  CSR* mst_parent, /**< parent MST (out) */
355  CSR* mst_new /**< new MST (out) */
356 )
357 {
358  CSRDEPO* const msts_levelbase = reddata->msts_levelbase;
359  const int nleaves = extdata->tree_nleaves;
360  const int nnodes_new = nleaves - 1;
361 
362 #ifndef NDEBUG
363  const MLDISTS* const sds_vertical = reddata->sds_vertical;
364  const int level_parent = extreduce_mldistsTopLevel(sds_vertical) - 1;
365  const int stackpos_parent = extStackGetLastMarked(extdata);
366 #endif
367 
368  /* get the previous levelbase MST */
369  graph_csrdepo_getTopCSR(msts_levelbase, mst_parent);
370 
371  assert(nnodes_new >= 1 && stackpos_parent >= 0);
372  assert(mst_parent->nnodes == extreduce_mldistsLevelNTargets(sds_vertical, level_parent));
373  assert(mst_parent->nnodes == nleaves - extreduce_extStackCompNOutedges(extdata, stackpos_parent));
374 
375  SCIPdebugMessage("got MST level parent with n=%d, m=%d \n", mst_parent->nnodes, mst_parent->nedges_max);
376 
377  /* get space for the new MST */
378  graph_csrdepo_addEmptyTopTree(msts_levelbase, nnodes_new);
379  graph_csrdepo_getEmptyTop(msts_levelbase, mst_new);
380 }
381 
382 
383 /** (partially) initializes base MST data */
384 static inline
386  const REDDATA* reddata, /**< reduction data */
387  int extnode, /**< node from which we extended */
388  const CSR* mst_parent, /**< parent MST */
389  CSR* mst_new, /**< new MST (in) */
390  MSTXCOMP* mstextcomp /**< extension component (out) */
391 )
392 {
393  const MLDISTS* const sds_vertical = reddata->sds_vertical;
394  const int parentcomp_level = extreduce_mldistsTopLevel(sds_vertical) - 1;
395 
396  assert(!extReddataHasBiasedSds(reddata) ||
398 
399  mstextcomp->mst_parent = mst_parent;
400  mstextcomp->mst_new = mst_new;
401  mstextcomp->comp_nodes = NULL;
402  mstextcomp->comp_vert = -1;
403  mstextcomp->comp_extnode = extnode;
404  mstextcomp->comp_level = parentcomp_level;
405  mstextcomp->comp_size = -1;
406  mstextcomp->isExtended = FALSE;
407 }
408 
409 
410 /** extends parent base MST to obtain current one */
411 static inline
413  SCIP* scip, /**< SCIP */
414  const GRAPH* graph, /**< graph */
415  REDDATA* reddata, /**< reduction data */
416  EXTDATA* extdata, /**< extension data */
417  MSTXCOMP* mstextcomp /**< extension component (in/out) */
418 )
419 {
420  int parentcomp_nodes[STP_EXT_MAXGRAD];
421  DCMST* const dcmst = reddata->dcmst;
422  SCIP_Real* const adjcosts = reduce_dcmstGetAdjcostBuffer(dcmst);
423  const int extnode = mstextcomp->comp_extnode;
424  int parentcomp_size = -1;
425 
426 #ifndef NDEBUG
427  const int nnodes_new = extdata->tree_nleaves - 1;
428  int nextnode_hits = 0;
429 #endif
430 
431  assert(!mstextcomp->isExtended);
432  assert(mstextcomp->comp_vert == -1);
433  assert(mstextcomp->comp_size == -1);
434  assert(mstextcomp->comp_nodes == NULL);
435 
436  /* It is necessary to have the parent nodes ordered, because the internal leaves ordering might
437  * have changed since the creation of the parent component. The internal order will not change
438  * anymore, though, for the extension trees build from here */
439  baseMstGetOrderedParentNodes(graph, extdata, &parentcomp_size, parentcomp_nodes);
440 
441  assert(parentcomp_size >= 0 && parentcomp_size < STP_EXT_MAXGRAD);
442 
443  mstextcomp->comp_size = parentcomp_size;
444  mstextcomp->comp_nodes = parentcomp_nodes;
445 
446  /* build 'mst_new' from 'mst_parent' by adding all siblings of 'extnode' */
447  for( int i = 0; i < parentcomp_size; i++ )
448  {
449  const int parentcomp_vert = parentcomp_nodes[i];
450 
451  if( parentcomp_vert != extnode )
452  {
453  mstextcomp->comp_vert = parentcomp_vert;
454 
455  baseMstGetAdjcosts(reddata, mstextcomp, adjcosts);
456 
457  mstExtend(scip, adjcosts, dcmst, mstextcomp);
458  }
459 #ifndef NDEBUG
460  else
461  nextnode_hits++;
462 #endif
463  }
464 
465  if( !mstextcomp->isExtended )
466  {
467  CSR* mst_new = mstextcomp->mst_new;
468  const CSR* mst_parent = mstextcomp->mst_parent;
469 
470  assert(nnodes_new == mstextcomp->mst_parent->nnodes);
471  graph_csr_copy(mst_parent, mst_new);
472  }
473 
474  assert(nnodes_new == mstextcomp->mst_new->nnodes);
475  assert(nextnode_hits == 1);
476 }
477 
478 
479 /** finalizes base MST built */
480 static inline
482  SCIP* scip, /**< SCIP */
483  const GRAPH* graph, /**< graph */
484  const MSTXCOMP* mstextcomp, /**< extension component */
485  REDDATA* reddata, /**< reduction data */
486  EXTDATA* extdata /**< extension data */
487 )
488 {
489  CSRDEPO* const msts_levelbase = reddata->msts_levelbase;
490 
491  graph_csrdepo_emptyTopSetMarked(msts_levelbase);
492 
493 
494 #if defined(STP_DEBUG_EXT) && defined(SCIP_DEBUG)
495  graph_csrdepo_print(msts_levelbase);
496 
497  printf("---parent: \n");
498  graph_csr_print(mstextcomp->mst_parent);
499  printf("---new: \n");
500  graph_csr_print(mstextcomp->mst_new);
501 #endif
502 
503  assert(extreduce_mstTopLevelBaseObjValid(scip, graph, mstextcomp->comp_extnode, extdata));
504 
505 #ifdef SCIP_DEBUG
506  SCIPdebugMessage("add MST level with n=%d, m=%d \n", mstextcomp->mst_new->nnodes, mstextcomp->mst_new->nedges_max);
507  SCIPdebugMessage("weight of levelbase new MST: %f \n", reduce_dcmstGetWeight(scip, mstextcomp->mst_new));
508 #endif
509 }
510 
511 
512 /** (partially) initializes component extension MST data */
513 static inline
515  const GRAPH* graph, /**< the graph */
516  const EXTDATA* extdata, /**< extension data */
517  const CSR* mst_base, /**< levelbase MST */
518  CSR* mst_new, /**< new MST (in) */
519  MSTXCOMP* mstextcomp /**< extension component (out) */
520 )
521 {
522  const int topcompsize = extStackGetTopSize(extdata);
523 
524  assert(extreduce_mldistsTopLevel(extdata->reddata->sds_vertical) == extdata->tree_depth);
525 
526  mstextcomp->mst_parent = mst_base;
527  mstextcomp->mst_new = mst_new;
528  mstextcomp->comp_nodes = NULL;
529  mstextcomp->comp_vert = -1;
530  mstextcomp->comp_extnode = -1;
531  mstextcomp->comp_level = extdata->tree_depth;
532  mstextcomp->comp_size = topcompsize;
533  mstextcomp->isExtended = FALSE;
534 }
535 
536 
537 /** initializes component MSTs (current component MST and previous levelbase) */
538 static inline
540  EXTDATA* extdata, /**< extension data */
541  CSR* mst_base, /**< the base (out) */
542  CSR* mst_new /**< new MST (out) */
543 )
544 {
545  REDDATA* const reddata = extdata->reddata;
546  CSRDEPO* const msts_comp = reddata->msts_comp;
547  const CSRDEPO* const msts_levelbase = reddata->msts_levelbase;
548  const int nleaves = extdata->tree_nleaves;
549  const int nnodes_new = nleaves;
550 
551  assert(graph_csrdepo_getNcsrs(msts_comp) == (graph_csrdepo_getNcsrs(msts_levelbase) - 1));
552 
553  graph_csrdepo_getTopCSR(msts_levelbase, mst_base);
554 
555 #ifndef NDEBUG
556  if( !extIsAtInitialComp(extdata) || extInitialCompIsEdge(extdata) )
557  {
558  const MLDISTS* const sds_vertical = reddata->sds_vertical;
559  const int nnodes_base = mst_base->nnodes;
560 
561  assert(nnodes_base == nleaves - extStackGetTopSize(extdata));
562  assert(nnodes_base == extreduce_mldistsLevelNTopTargets(sds_vertical));
563  }
564 #endif
565 
566  /* get space for the new MST */
567  graph_csrdepo_addEmptyTopTree(msts_comp, nnodes_new);
568  graph_csrdepo_getEmptyTop(msts_comp, mst_new);
569 }
570 
571 
572 /** finalizes component MST */
573 static inline
575  const MSTXCOMP* mstextcomp, /**< extension component */
576  SCIP_Bool deletemst, /**< delete the MST? */
577  EXTDATA* extdata /**< extension data */
578 )
579 {
580  REDDATA* const reddata = extdata->reddata;
581  CSRDEPO* const msts_comp = reddata->msts_comp;
582 
583 #ifdef SCIP_DEBUG
584  CSR* mst_new = mstextcomp->mst_new;
585 #endif
586 
587  if( deletemst )
588  {
589  graph_csrdepo_removeTop(msts_comp);
590 
591  return;
592  }
593 
595 
596 #if defined(STP_DEBUG_EXT) && defined(SCIP_DEBUG)
597  graph_csrdepo_print(reddata->msts_comp);
598 
599  printf("---parent: \n");
600  graph_csr_print(mstextcomp->mst_parent);
601  printf("---new: \n");
602  graph_csr_print(mstextcomp->mst_new);
603 #endif
604 
605 #ifdef SCIP_DEBUG
606  SCIPdebugMessage("added MST component with n=%d, m=%d \n", mst_new->nnodes, mst_new->nedges_max);
607 #endif
608 }
609 
610 
611 /** marks single PcSd array entry */
612 static inline
614  const GRAPH* graph, /**< graph data structure */
615  int entry, /**< entry to mark */
616  SCIP_Real value, /**< value to mark with */
617  SCIP_Real* pcSdToNode, /**< node mark array */
618  int* pcSdCands, /**< marked candidates list */
619  int* nPcSdCands /**< pointer to store number of candidates */
620 )
621 {
622  /* entry not marked yet? */
623  if( pcSdToNode[entry] < -0.5 )
624  {
625  assert(EQ(pcSdToNode[entry], -1.0));
626  assert(*nPcSdCands < graph->knots);
627 
628  pcSdCands[(*nPcSdCands)++] = entry;
629  pcSdToNode[entry] = value;
630  }
631  else if( value < pcSdToNode[entry] )
632  {
633  pcSdToNode[entry] = value;
634  }
635 
636  assert(GE(pcSdToNode[entry], 0.0));
637 }
638 
639 
640 /** marks PcSd array */
641 static
643  const GRAPH* graph, /**< graph data structure */
644  int startvertex, /**< vertex to start from */
645  EXTDATA* extdata /**< extension data */
646  )
647 {
648  PCDATA* const pcdata = extdata->pcdata;
649  SCIP_Real* const pcSdToNode = pcdata->pcSdToNode;
650  int* const pcSdCands = pcdata->pcSdCands;
651  const DCSR* const dcsr = graph->dcsr_storage;
652  const RANGE* const range_csr = dcsr->range;
653  const int* const head_csr = dcsr->head;
654  const SCIP_Real* const cost_csr = dcsr->cost;
655  const SCIP_Real* const prize = graph->prize;
656  const int* const tree_deg = extdata->tree_deg;
657  const int start = range_csr[startvertex].start;
658  const int end = range_csr[startvertex].end;
659  int count1 = 0;
660  int count2 = 0;
661 
662  assert(graph_pc_isPcMw(graph));
663  assert(pcSdCands && pcSdToNode && prize);
664  assert(startvertex >= 0 && startvertex < graph->knots);
665  assert(pcdata->nPcSdCands == -1);
666  assert(pcdata->pcSdStart == -1);
667 
668 #ifndef NDEBUG
669  pcdata->pcSdStart = startvertex;
670 #endif
671 
672  pcdata->nPcSdCands = 0;
673 
674  for( int i = start; i != end; i++ )
675  {
676  const SCIP_Real edgecost = cost_csr[i];
677  const int head = head_csr[i];
678  assert(tree_deg[head] >= 0);
679 
680  if( tree_deg[head] == 0 )
681  {
682  const int start2 = range_csr[head].start;
683  const int end2 = range_csr[head].end;
684 
685  for( int i2 = start2; i2 != end2; i2++ )
686  {
687  const int head2 = head_csr[i2];
688  assert(tree_deg[head2] >= 0);
689 
690  /* tree reached? */
691  if( tree_deg[head2] > 0 && head2 != startvertex )
692  {
693  const SCIP_Real edgecost2 = cost_csr[i2];
694  const SCIP_Real maxedgecost = MAX(edgecost, edgecost2);
695  SCIP_Real dist2 = MAX(maxedgecost, edgecost + edgecost2 - prize[head]);
696 
697  assert(0.0 == prize[head] || Is_term(graph->term[head]));
698 
699  pcSdMarkSingle(graph, head2, dist2, pcSdToNode, pcSdCands, &(pcdata->nPcSdCands));
700  }
701 
702  if( count2++ > EXT_PC_SDMAXVISITS )
703  break;
704  }
705  }
706  else
707  {
708  assert(head != startvertex);
709  pcSdMarkSingle(graph, head, edgecost, pcSdToNode, pcSdCands, &(pcdata->nPcSdCands));
710  }
711 
712  if( count1++ > EXT_PC_SDMAXVISITS )
713  break;
714  }
715 }
716 
717 
718 /** unmarks PcSd array */
719 static inline
721  const GRAPH* graph, /**< graph data structure */
722  int startvertex, /**< vertex to start from */
723  EXTDATA* extdata /**< extension data */
724  )
725 {
726  PCDATA* const pcdata = extdata->pcdata;
727  SCIP_Real* const pcSdToNode = pcdata->pcSdToNode;
728  const int* const pcSdCands = pcdata->pcSdCands;
729  const int nPcSdCands = pcdata->nPcSdCands;
730 
731  assert(graph_pc_isPcMw(graph));
732  assert(pcSdCands && pcSdToNode);
733  assert(nPcSdCands >= 0);
734  assert(pcdata->pcSdStart >= 0 && pcdata->pcSdStart < graph->knots);
735  assert(startvertex == pcdata->pcSdStart);
736 
737  for( int i = 0; i < nPcSdCands; i++ )
738  {
739  const int cand = pcSdCands[i];
740 
741  assert(pcSdToNode[cand] >= 0.0);
742 
743  pcSdToNode[cand] = -1.0;
744  }
745 
746 #ifndef NDEBUG
747  pcdata->pcSdStart = -1;
748  pcdata->nPcSdCands = -1;
749 #endif
750 }
751 
752 #ifndef NDEBUG
753 /** has the leaf a dominated bottleneck with other leaves? */
754 static
756  SCIP* scip, /**< SCIP */
757  const GRAPH* graph, /**< graph data structure */
758  int topleaf, /**< component leaf to check for */
759  SCIP_Bool with_sd_double, /**< use SD double method? */
760  int edge_forbidden, /**< forbidden edge */
761  EXTDATA* extdata /**< extension data */
762  )
763 {
764  const int* const leaves = extdata->tree_leaves;
765  const int nleaves = extdata->tree_nleaves;
766  SCIP_Bool ruleOut = FALSE;
767  const SCIP_Bool isPc = graph_pc_isPc(graph);
768 
769  extreduce_bottleneckMarkRootPath(graph, topleaf, extdata);
770 
771  if( isPc )
772  pcSdToNodeMark(graph, topleaf, extdata);
773 
774  for( int j = 0; j < nleaves; j++ )
775  {
776  const int leaf = leaves[j];
777 
778  if( leaf != topleaf )
779  {
780  const SCIP_Real specialDist = with_sd_double ?
781  extGetSdDouble(scip, graph, topleaf, leaf, extdata)
782  : extGetSd(scip, graph, topleaf, leaf, extdata);
783 
784  if( extreduce_bottleneckIsDominated(scip, graph, topleaf, leaf, specialDist, edge_forbidden, extdata) )
785  {
786  SCIPdebugMessage("...debug check ruled out! \n");
787  ruleOut = TRUE;
788  break;
789  }
790  }
791  }
792 
793  if( isPc )
794  pcSdToNodeUnmark(graph, topleaf, extdata);
795 
796  extreduce_bottleneckUnmarkRootPath(graph, topleaf, extdata);
797 
798  return ruleOut;
799 }
800 
801 #endif
802 
803 
804 /** helper; adds single node MST */
805 static inline
807  SCIP* scip, /**< SCIP */
808  CSRDEPO* msts /**< MSTs */
809 )
810 {
811  CSR mst1;
812 
813  assert(msts);
814 
815  graph_csrdepo_addEmptyTop(msts, 1, 0);
816  graph_csrdepo_getEmptyTop(msts, &mst1);
817 
818  reduce_dcmstGet1NodeMst(scip, &mst1);
819 
821 }
822 
823 
824 /** helper; adds MSTs */
825 static
827  SCIP* scip, /**< SCIP */
828  EXTDATA* extdata /**< extension data */
829 )
830 {
831  REDDATA* const reddata = extdata->reddata;
832  CSRDEPO* const msts_comp = reddata->msts_comp;
833  CSRDEPO* const msts_levelbase = reddata->msts_levelbase;
834 
835  assert(graph_csrdepo_isEmpty(msts_comp));
836  assert(graph_csrdepo_isEmpty(msts_levelbase));
837  assert(0 == extdata->tree_depth);
838 
839  /* initialize 1-node MSTs corresponding to the root of the extension tree */
840  add1NodeMst(scip, msts_comp);
841  add1NodeMst(scip, msts_levelbase);
842 }
843 
844 
845 /** helper; adds SDs */
846 static
848  int root, /**< the root of the extension tree */
849  EXTDATA* extdata /**< extension data */
850 )
851 {
852  REDDATA* const reddata = extdata->reddata;
853  MLDISTS* const sds_vertical = reddata->sds_vertical;
854  MLDISTS* const sds_horizontal = reddata->sds_horizontal;
855 
856  extreduce_mldistsLevelAddAndCloseRoot(root, sds_vertical);
857  extreduce_mldistsLevelAddAndCloseRoot(root, sds_horizontal);
858 
859  if( extReddataHasBiasedSds(reddata) )
860  {
863  }
864 
865  SCIPdebugMessage("initialized first MST level (%d) \n", extreduce_mldistsTopLevel(sds_vertical));
866 }
867 
868 
869 /** can current 3-leaf tree be rule-out in case of equality? */
870 static inline
872  SCIP* scip, /**< SCIP */
873  const GRAPH* graph, /**< graph data structure */
874  SCIP_Real tree_cost, /**< tree cost */
875  EXTDATA* extdata /**< extension data */
876 )
877 {
878  SCIP_Real sds[3];
879  const int* leaves = extdata->tree_leaves;
880 
881  assert(3 == extdata->tree_nleaves);
882 
883  /* NOTE: initial component star should be ok, because in this case we don't
884  * use simple paths for equality rule-outs */
885  if( extInitialCompIsStar(extdata) || !extdata->sdeq_hasForbiddenEdges )
886  return TRUE;
887 
888  sds[0] = extreduce_distDataGetSdDoubleForbidden(scip, graph,
889  leaves[0], leaves[1], extdata);
890 
891  sds[1] = extreduce_distDataGetSdDoubleForbidden(scip, graph,
892  leaves[0], leaves[2], extdata);
893 
894  if( LE(sds[0] + sds[1], tree_cost) )
895  {
896  return TRUE;
897  }
898 
899  sds[2] = extreduce_distDataGetSdDoubleForbidden(scip, graph,
900  leaves[1], leaves[2], extdata);
901 
902  if( LE(sds[0] + sds[2], tree_cost) || LE(sds[1] + sds[2], tree_cost) )
903  {
904  return TRUE;
905  }
906 
907  return FALSE;
908 }
909 
910 
911 
912 /** Is bottleneck rule out with biased SDs from leaf of top tree component to siblings possible?
913  * NOTE: Only restricted bottleneck tests are performed! */
914 static inline
916  SCIP* scip, /**< SCIP */
917  const GRAPH* graph, /**< graph data structure */
918  int edge2top, /**< edge to the top component leaf */
919  EXTDATA* extdata /**< extension data */
920  )
921 {
922  const MLDISTS* const sdsbias_horizontal = extdata->reddata->sdsbias_horizontal;
923  const int* const extstack_data = extdata->extstack_data;
924  const int* const ghead = graph->head;
925  const int stackpos = extStackGetPosition(extdata);
926  const int topedges_start = extStackGetTopOutEdgesStart(extdata, stackpos);
927  const int topedges_end = extStackGetTopOutEdgesEnd(extdata, stackpos);
928  const int topleaf = ghead[edge2top];
929  SCIP_Bool hitTopLeaf = FALSE;
930 
931  assert(extreduce_sdshorizontalInSync(scip, graph, topleaf, extdata));
932  assert(topedges_start <= topedges_end);
933  assert(!extIsAtInitialGenStar(extdata));
934  assert(extReddataHasBiasedSds(extdata->reddata));
935 
936  for( int i = topedges_start, j = 0; i != topedges_end; i++, j++ )
937  {
938  SCIP_Real sdbiased;
939  const int edge2sibling = extstack_data[i];
940  const int sibling = ghead[edge2sibling];
941 
942  assert(extreduce_nodeIsInStackTop(graph, extdata, sibling));
943  assert(extdata->tree_deg[sibling] == 1);
944  assert(graph->tail[edge2top] == graph->tail[edge2sibling]);
945 
946  if( sibling == topleaf )
947  {
948  assert(!hitTopLeaf);
949  hitTopLeaf = TRUE;
950  continue;
951  }
952 
953  /* only make bottleneck test for 'right' siblings to avoid double checks */
954  if( !hitTopLeaf )
955  {
956  continue;
957  }
958 
959  sdbiased = extreduce_mldistsTopTargetDist(sdsbias_horizontal, topleaf, sibling);
960 
961  if( extreduce_bottleneckToSiblingIsDominatedBiased(scip, graph, edge2top, edge2sibling, sdbiased, extdata) )
962  {
963  SCIPdebugMessage("---biased bottleneck rule-out component (siblings test)---\n");
964  return TRUE;
965  }
966  }
967 
968  assert(hitTopLeaf);
969 
970  return FALSE;
971 }
972 
973 
974 /** Is bottleneck rule out with biased SDs from leaf of top tree component to ancestors possible?
975  * NOTE: Only restricted bottleneck tests are performed! */
976 static inline
978  SCIP* scip, /**< SCIP */
979  const GRAPH* graph, /**< graph data structure */
980  int edge2leaf, /**< edge to the top component leaf */
981  int nleaves_ancestors, /**< number of leaves to ancestors */
982  EXTDATA* extdata /**< extension data */
983  )
984 {
985  const MLDISTS* const sdsbias_vertical = extdata->reddata->sdsbias_vertical;
986  const int topleaf = graph->head[edge2leaf];
987  const SCIP_Real* const adjedgecosts = extreduce_mldistsTopTargetDists(sdsbias_vertical, topleaf);
988  const SCIP_Bool hasSiblings = (extStackGetTopSize(extdata) > 1);
989  SCIP_Bool leafRuledOut = FALSE;
990 
991 #ifndef NDEBUG
992  assert(!graph_pc_isPc(graph));
993  assert(nleaves_ancestors >= 1);
994  assert(extreduce_mldistsLevelNTopTargets(sdsbias_vertical) == nleaves_ancestors);
995  assert(!extIsAtInitialGenStar(extdata));
996 #endif
997 
998  /* if there are no siblings, then there is a chance to find a non-trivial bottleneck rule-out */
999  if( !hasSiblings )
1000  {
1001  const int* const leaves = extdata->tree_leaves;
1002 
1003  extreduce_bottleneckMarkRootPath(graph, topleaf, extdata);
1004 
1005  /* get the SDs to the ancestor (lower) leafs and try bottleneck rule out */
1006  for( int j = 0; j < nleaves_ancestors; j++ )
1007  {
1008  const int leaf = leaves[j];
1009  const SCIP_Real sd = adjedgecosts[j];
1010  const SCIP_Real specialDistBiased = EQ(sd, FARAWAY) ? -1.0 : sd;
1011 
1012  assert(EQ(specialDistBiased,
1013  extGetSdDoubleFromDistdata(scip, graph, topleaf, leaf, extdata->distdata_biased, extdata)));
1014 
1015  if( extreduce_bottleneckIsDominatedBiased(scip, graph, topleaf, leaf, specialDistBiased, extdata) )
1016  {
1017  SCIPdebugMessage("---biased bottleneck rule-out component (standard test)---\n");
1018  leafRuledOut = TRUE;
1019  break;
1020  }
1021  }
1022 
1023  extreduce_bottleneckUnmarkRootPath(graph, topleaf, extdata);
1024  }
1025 
1026  return leafRuledOut;
1027 }
1028 
1029 /** Gets SDs from leaf of top tree component to siblings for MST calculation.
1030  * Returns early (with leafRuledOut == TRUE) if extension via 'edge2leaf' can be ruled out already.
1031  * NOTE: Only restricted bottleneck tests are performed! */
1032 static inline
1034  SCIP* scip, /**< SCIP */
1035  const GRAPH* graph, /**< graph data structure */
1036  int edge2top, /**< edge to the top component leaf */
1037  EXTDATA* extdata, /**< extension data */
1038  SCIP_Real sds[], /**< array to store the SDs */
1039  SCIP_Bool* leafRuledOut /**< could the extension already by ruled out */
1040  )
1041 {
1042  const MLDISTS* const sds_horizontal = extdata->reddata->sds_horizontal;
1043  const int* const extstack_data = extdata->extstack_data;
1044  const int* const ghead = graph->head;
1045  const int stackpos = extStackGetPosition(extdata);
1046  const int topedges_start = extStackGetTopOutEdgesStart(extdata, stackpos);
1047  const int topedges_end = extStackGetTopOutEdgesEnd(extdata, stackpos);
1048  const int topleaf = ghead[edge2top];
1049  SCIP_Bool hitTopLeaf = FALSE;
1050  const SCIP_Bool isAtInitialGenStar = extIsAtInitialGenStar(extdata);
1051 
1052 #ifndef NDEBUG
1053  {
1054  const SCIP_Bool atInitialAnyStar = extIsAtInitialStar(extdata) || extIsAtInitialGenStar(extdata);
1055 
1056  assert(leafRuledOut && sds);
1057  assert((*leafRuledOut) == FALSE);
1058  assert(atInitialAnyStar || extreduce_mldistsLevelNTopTargets(sds_horizontal) >= extStackGetTopSize(extdata) - 1);
1059  assert(extreduce_sdshorizontalInSync(scip, graph, topleaf, extdata));
1060  assert(topedges_start <= topedges_end);
1061  }
1062 #endif
1063 
1064  if( isAtInitialGenStar )
1065  {
1066  extreduce_bottleneckMarkRootPath(graph, topleaf, extdata);
1067  }
1068 
1069  for( int i = topedges_start, j = 0; i != topedges_end; i++, j++ )
1070  {
1071  const int edge2sibling = extstack_data[i];
1072  const int sibling = ghead[edge2sibling];
1073 
1074  assert(extreduce_nodeIsInStackTop(graph, extdata, sibling));
1075  assert(extdata->tree_deg[sibling] == 1);
1076  assert(EQ(sds[j], -1.0));
1077 
1078  if( sibling == topleaf )
1079  {
1080  assert(!hitTopLeaf);
1081 
1082  hitTopLeaf = TRUE;
1083  sds[j] = FARAWAY;
1084 
1085  continue;
1086  }
1087 
1088  sds[j] = extreduce_mldistsTopTargetDist(sds_horizontal, topleaf, sibling);
1089 
1090  if( graph->tail[edge2top] != graph->tail[edge2sibling] )
1091  {
1092  assert(isAtInitialGenStar);
1093  if( extreduce_bottleneckIsDominated(scip, graph, topleaf, sibling, sds[j], edge2sibling, extdata) )
1094  {
1095  SCIPdebugMessage("---bottleneck rule-out component (GENSTAR siblings test)---\n");
1096  *leafRuledOut = TRUE;
1097  break;
1098  }
1099 
1100  continue;
1101  }
1102 
1103  /* only make bottleneck test for 'right' siblings to avoid double checks */
1104  if( !hitTopLeaf )
1105  {
1106  assert(!extreduce_bottleneckToSiblingIsDominated(scip, graph, edge2top, edge2sibling, sds[j], extdata));
1107  }
1108  else if( extreduce_bottleneckToSiblingIsDominated(scip, graph, edge2top, edge2sibling, sds[j], extdata) )
1109  {
1110  SCIPdebugMessage("---bottleneck rule-out component (siblings test)---\n");
1111  *leafRuledOut = TRUE;
1112  break;
1113  }
1114  }
1115 
1116  if( isAtInitialGenStar )
1117  {
1118  extreduce_bottleneckUnmarkRootPath(graph, topleaf, extdata);
1119  }
1120 
1121  assert(hitTopLeaf || *leafRuledOut);
1122 }
1123 
1124 
1125 /** Gets SDs from leaf of top tree component to ancestors for MST calculation.
1126  * Returns early (with leafRuledOut == TRUE) if extension via 'edge2leaf' can be ruled out already.
1127  * NOTE: Only restricted bottleneck tests are performed, UNLESS the leaf has no siblings! */
1128 static inline
1130  SCIP* scip, /**< SCIP */
1131  const GRAPH* graph, /**< graph data structure */
1132  int edge2leaf, /**< edge to the top component leaf */
1133  int nleaves_ancestors, /**< number of leaves to ancestors */
1134  EXTDATA* extdata, /**< extension data */
1135  SCIP_Real sds[], /**< array to store the SDs */
1136  SCIP_Bool* leafRuledOut /**< could the extension already by ruled out */
1137  )
1138 {
1139  const MLDISTS* const sds_vertical = extdata->reddata->sds_vertical;
1140  const int topleaf = graph->head[edge2leaf];
1141  const SCIP_Real* const adjedgecosts = extreduce_mldistsTopTargetDists(sds_vertical, topleaf);
1142  const SCIP_Bool hasSiblings = (extStackGetTopSize(extdata) > 1);
1143 
1144 #ifndef NDEBUG
1145  const SCIP_Bool isPc = graph_pc_isPc(graph);
1146 
1147  assert(adjedgecosts && leafRuledOut && sds);
1148  assert(!(*leafRuledOut));
1149  assert(nleaves_ancestors >= 1);
1150  assert(extreduce_mldistsLevelNTopTargets(sds_vertical) == nleaves_ancestors);
1151  /* expensive check, maybe only do if STP_DEBUG_EXT is set? */
1152  assert(extreduce_sdsverticalInSync(scip, graph, extStackGetTopSize(extdata), nleaves_ancestors, topleaf, extdata));
1153 
1154  for( int j = 0; j < nleaves_ancestors; j++ )
1155  assert(EQ(sds[j], -1.0));
1156 #endif
1157 
1158  memcpy(sds, adjedgecosts, nleaves_ancestors * sizeof(sds[0]));
1159 
1160  /* if there are no siblings, then there is a chance to find a non-trivial bottleneck rule-out
1161  * ...if the initial component is a general star, rule-out is also possible otherwise */
1162  if( !hasSiblings || extIsAtInitialGenStar(extdata) )
1163  {
1164  const int* const leaves = extdata->tree_leaves;
1165 
1166  extreduce_bottleneckMarkRootPath(graph, topleaf, extdata);
1167 
1168  /* WARNING: might lead to bugs in OPT, but not in DEBUG mode! */
1169 #ifndef NDEBUG
1170  if( isPc )
1171  pcSdToNodeMark(graph, topleaf, extdata);
1172 #endif
1173 
1174  /* get the SDs to the ancestor (lower) leafs and try bottleneck rule out */
1175  for( int j = 0; j < nleaves_ancestors; j++ )
1176  {
1177  const int leaf = leaves[j];
1178  const SCIP_Real sd = adjedgecosts[j];
1179  const SCIP_Real specialDist = EQ(sd, FARAWAY) ? -1.0 : sd;
1180 
1181  assert(EQ(specialDist, extGetSd(scip, graph, topleaf, leaf, extdata)));
1182 
1183  if( extreduce_bottleneckIsDominated(scip, graph, topleaf, leaf, specialDist, edge2leaf, extdata) )
1184  {
1185  SCIPdebugMessage("---bottleneck rule-out component (standard test)---\n");
1186  *leafRuledOut = TRUE;
1187  break;
1188  }
1189  }
1190 
1191  extreduce_bottleneckUnmarkRootPath(graph, topleaf, extdata);
1192 
1193  /* WARNING: might lead to bugs in OPT, but not in DEBUG mode! */
1194 #ifndef NDEBUG
1195  if( isPc )
1196  pcSdToNodeUnmark(graph, topleaf, extdata);
1197 #endif
1198  }
1199 }
1200 
1201 
1202 /** Gets SDs from leaf (head of 'edge2leaf') to all other leaves of the tree.
1203  * Returns early (with leafRuledOut == TRUE) if extension via 'edge2leaf' can be ruled out already.
1204  * NOTE: Only restricted bottleneck tests are performed! */
1205 static inline
1207  SCIP* scip, /**< SCIP */
1208  const GRAPH* graph, /**< graph data structure */
1209  int edge2leaf, /**< edge to the top component leaf */
1210  EXTDATA* extdata, /**< extension data */
1211  SCIP_Real sds[], /**< array to store the SDs */
1212  SCIP_Bool* leafRuledOut /**< could the extension already by ruled out */
1213  )
1214 {
1215  const SCIP_Bool hasSdsBiased = extReddataHasBiasedSds(extdata->reddata);
1216  const int nleaves_ancestors = extGetNancestorLeaves(extdata);
1217 #ifndef NDEBUG
1218  const int compleaf = graph->head[edge2leaf];
1219 #endif
1220 
1221  assert(compleaf != extdata->tree_starcenter);
1222  assert(leafRuledOut && !(*leafRuledOut));
1223 
1224  /* fill in the second part of the sds array */
1225  mstCompLeafGetSDsToSiblings(scip, graph, edge2leaf, extdata, &(sds[nleaves_ancestors]), leafRuledOut);
1226 
1227  if( *leafRuledOut )
1228  {
1229  /* NOTE: does not need to hold in case of equality rule out! */
1230  assert(!extInitialCompIsStar(extdata) || dbgBottleneckFromLeafIsDominated(scip, graph, compleaf, TRUE, edge2leaf, extdata));
1231  return;
1232  }
1233 
1234  if( hasSdsBiased && mstCompLeafToSiblingsBiasedRuleOut(scip, graph, edge2leaf, extdata) )
1235  {
1236  *leafRuledOut = TRUE;
1237  return;
1238  }
1239 
1240  /* fill in the first part of the sds array */
1241  mstCompLeafGetSDsToAncestors(scip, graph, edge2leaf, nleaves_ancestors, extdata, sds, leafRuledOut);
1242 
1243  if( *leafRuledOut )
1244  {
1245  /* NOTE: does the following not need to hold in case of equality rule out! */
1246  assert(!extInitialCompIsStar(extdata) || dbgBottleneckFromLeafIsDominated(scip, graph, compleaf, FALSE, edge2leaf, extdata));
1247  return;
1248  }
1249 
1250  if( hasSdsBiased && mstCompLeafToAncestorsBiasedRuleOut(scip, graph, edge2leaf, nleaves_ancestors, extdata) )
1251  {
1252  *leafRuledOut = TRUE;
1253  return;
1254  }
1255 
1256  assert(!dbgBottleneckFromLeafIsDominated(scip, graph, compleaf, FALSE, edge2leaf, extdata) || graph_pc_isPc(graph));
1257  assert(extreduce_sdsTopInSync(scip, graph, sds, compleaf, extdata));
1258 }
1259 
1260 
1261 /** Adds leaf from top component of current tree to MST. I.e., adds SD adjacency costs updates MST.
1262  * 'edge2leaf' must be in top component of the stack.
1263  * Returns early (with leafRuledOut == TRUE) if extension via 'edge2leaf' can be ruled out already.
1264  * NOTE: SDs are not computed but taken from storage! */
1265 static inline
1267  SCIP* scip, /**< SCIP */
1268  const GRAPH* graph, /**< graph data structure */
1269  int edge2leaf, /**< edge to the top component leaf */
1270  MSTXCOMP* mstextcomp, /**< MST extension component */
1271  EXTDATA* extdata, /**< extension data */
1272  SCIP_Bool* leafRuledOut /**< could the extension already by ruled out */
1273 )
1274 {
1275  REDDATA* const reddata = extdata->reddata;
1276  DCMST* const dcmst = reddata->dcmst;
1277  SCIP_Real* const adjcosts = reduce_dcmstGetAdjcostBuffer(dcmst);
1278 
1279  assert(leafRuledOut);
1280  assert(FALSE == *leafRuledOut);
1281  assert(reduce_dcmstGetMaxnnodes(dcmst) >= extdata->tree_nleaves);
1282 
1283  mstCompLeafGetSDs(scip, graph, edge2leaf, extdata, adjcosts, leafRuledOut);
1284 
1285  if( (*leafRuledOut) )
1286  {
1287  return;
1288  }
1289  else
1290  {
1291  assert(mstextcomp->comp_vert == -1);
1292  assert(mstextcomp->comp_extnode == -1);
1293 
1294  mstExtend(scip, adjcosts, dcmst, mstextcomp);
1295  }
1296 }
1297 
1298 
1299 /** is a rule-out by using the top component possible? */
1300 static inline
1302  SCIP* scip, /**< SCIP */
1303  const GRAPH* graph, /**< graph data structure */
1304  EXTDATA* extdata /**< extension data */
1305 )
1306 {
1307  CSR topmst;
1308  REDDATA* const reddata = extdata->reddata;
1309  const CSRDEPO* const msts_comp = reddata->msts_comp;
1310  SCIP_Real mstweight;
1311  SCIP_Real tree_cost = extdata->tree_cost;
1312  const SCIP_Bool isPc = (graph->prize != NULL);
1314 
1315  assert(isPc == graph_pc_isPc(graph));
1316 
1317  if( isPc )
1318  {
1319  tree_cost -= extdata->pcdata->tree_innerPrize;
1320  assert(GE(tree_cost, 0.0));
1321  }
1322 
1323  graph_csrdepo_getTopCSR(msts_comp, &topmst);
1324 
1325  mstweight = reduce_dcmstGetWeight(scip, &topmst);
1326 
1327  assert(extreduce_mstTopCompObjValid(scip, graph, mstweight, extdata));
1328  assert(topmst.nedges_max % 2 == 0);
1329 
1330  ruledOut = (topmst.nedges_max > 2)? LE(mstweight, tree_cost) : LT(mstweight, tree_cost);
1331 
1332  if( ruledOut )
1333  {
1334  // todo: probably also need to check for > 3! */
1335  if( extdata->tree_nleaves == 3 && EQ(mstweight, tree_cost) && !mstEqComp3RuleOut(scip, graph, tree_cost, extdata) )
1336  {
1337  ruledOut = FALSE;
1338  }
1339  }
1340 
1341  if( !ruledOut )
1342  {
1343  if( extdata->tree_nleaves == 3 && extInitialCompIsEdge(extdata) )
1344  {
1345  assert(!extReddataHasBiasedSds(reddata));
1346  ruledOut = extreduce_spg3LeafTreeRuleOut(scip, graph, tree_cost, extdata);
1347  }
1348  else if( extdata->tree_nleaves == 3 && extReddataHasBiasedSds(reddata) )
1349  {
1350  assert(!extInitialCompIsEdge(extdata));
1351  ruledOut = extreduce_mstbiased3LeafTreeRuleOut(scip, graph, tree_cost, extdata);
1352  }
1353  }
1354  else
1355  {
1356  SCIPdebugMessage("SD MST alternative found %f < %f \n", mstweight, tree_cost);
1357  }
1358 
1359  return ruledOut;
1360 }
1361 
1362 
1363 /** builds (top) component MST */
1364 static inline
1366  SCIP* scip, /**< SCIP */
1367  const GRAPH* graph, /**< graph data structure */
1368  EXTDATA* extdata, /**< extension data */
1369  SCIP_Bool* ruledOut /**< already ruled out? */
1370 )
1371 {
1372  CSR mst_base;
1373  CSR mst_new;
1374  MSTXCOMP mstextcomp;
1375  const int* const extstack_data = extdata->extstack_data;
1376  const int stackpos = extStackGetPosition(extdata);
1377  const int topedges_start = extStackGetTopOutEdgesStart(extdata, stackpos);
1378  const int topedges_end = extStackGetTopOutEdgesEnd(extdata, stackpos);
1379 
1380  assert(*ruledOut == FALSE);
1381  assert(EXT_STATE_EXPANDED == extdata->extstack_state[stackpos]);
1382  assert(0 <= topedges_start && topedges_start < topedges_end);
1383 
1384  compMstInitMsts(extdata, &mst_base, &mst_new);
1385 
1386  compMstInitExtComp(graph, extdata, &mst_base, &mst_new, &mstextcomp);
1387 
1388  /* add nodes (with special distances) to MST,
1389  * and compare with tree bottleneck distances for early rule-out */
1390  for( int i = topedges_start; i != topedges_end; i++ )
1391  {
1392  const int edge2leaf = extstack_data[i];
1393 
1394  /* add vertex to MST graph and check for bottleneck shortcut */
1395  mstCompAddLeaf(scip, graph, edge2leaf, &mstextcomp, extdata, ruledOut);
1396 
1397  /* early rule-out? */
1398  if( *ruledOut )
1399  {
1400  break;
1401  }
1402  }
1403 
1404  compMstFinalizeNew(&mstextcomp, *ruledOut, extdata);
1405 
1406  assert(*ruledOut || extreduce_mstTopCompInSync(scip, graph, extdata));
1407 }
1408 
1409 
1410 /** Computes and stores SDs from head of extension edge to all leaves of the tree.
1411  * Also computes biased special distances if existing
1412  * NOTE: ugly, but should be more efficient, because bottleneck distances can be reused! */
1413 static inline
1415  SCIP* scip, /**< SCIP */
1416  const GRAPH* graph, /**< graph data structure */
1417  int edge2neighbor, /**< the edge from the tree to the neighbor */
1418  EXTDATA* extdata, /**< extension data */
1419  SCIP_Bool* ruledOut /**< early rule out? */
1420 )
1421 {
1422  REDDATA* const reddata = extdata->reddata;
1423  MLDISTS* const sds_vertical = reddata->sds_vertical;
1424  MLDISTS* const sdsbias_vertical = reddata->sdsbias_vertical;
1425  SCIP_Real* const adjedgecosts = extreduce_mldistsEmptySlotTargetDists(sds_vertical);
1426  const int* const leaves = extdata->tree_leaves;
1427  const SCIP_Bool hasBiasedSds = extReddataHasBiasedSds(reddata);
1428  SCIP_Real* const adjedgecostsBiased = hasBiasedSds ? extreduce_mldistsEmptySlotTargetDists(sdsbias_vertical) : NULL;
1429  const int nleaves = extdata->tree_nleaves;
1430  const int neighbor = graph->head[edge2neighbor];
1431  const int neighbor_base = graph->tail[edge2neighbor];
1432 
1433 #ifndef NDEBUG
1434  int* const adjids = extreduce_mldistsEmptySlotTargetIds(sds_vertical);
1435  int* const adjidsBiased = hasBiasedSds ? extreduce_mldistsEmptySlotTargetIds(sdsbias_vertical) : NULL;
1436 #endif
1437 
1438  assert(adjedgecosts && leaves && ruledOut);
1439  assert(*ruledOut == FALSE);
1440 
1441  for( int j = 0; j < nleaves; j++ )
1442  {
1443  SCIP_Real specialDist;
1444  const int leaf = leaves[j];
1445 
1446  assert(leaf >= 0 && leaf < graph->knots);
1447  assert(extdata->tree_deg[leaf] == 1 && leaf != neighbor);
1448 
1449  specialDist = extGetSd(scip, graph, neighbor, leaf, extdata);
1450 
1451  adjedgecosts[j] = extSdGetProper(specialDist);
1452 #ifndef NDEBUG
1453  adjids[j] = leaf;
1454 #endif
1455 
1456  if( extreduce_bottleneckWithExtedgeIsDominated(scip, graph, edge2neighbor, neighbor_base, leaf, specialDist, extdata) )
1457  {
1458  SCIPdebugMessage("---bottleneck rule-out (%d->%d)---\n", neighbor, leaf);
1459  assert(*ruledOut == FALSE);
1460  *ruledOut = TRUE;
1461  break;
1462  }
1463 
1464  if( hasBiasedSds )
1465  {
1466  assert(adjedgecostsBiased);
1467 
1468  specialDist = extGetSdDoubleFromDistdata(scip, graph, neighbor, leaf, extdata->distdata_biased, extdata);
1469  adjedgecostsBiased[j] = extSdGetProper(specialDist);
1470 #ifndef NDEBUG
1471  adjidsBiased[j] = leaf;
1472 #endif
1473 
1474  if( extreduce_bottleneckWithExtedgeIsDominatedBiased(scip, graph, edge2neighbor, neighbor_base, leaf, specialDist, extdata) )
1475  {
1476  SCIPdebugMessage("---bottleneck implied SD rule-out (%d->%d)---\n", neighbor, leaf);
1477  assert(*ruledOut == FALSE);
1478  *ruledOut = TRUE;
1479  break;
1480  }
1481  }
1482  }
1483 }
1484 
1485 
1486 /** adjusts vertical SDs by removing the neighbor base entry */
1487 static inline
1489  int neighbor_base, /**< the edge from the tree to the neighbor */
1490  MLDISTS* sds_vertical, /**< SD storage, possibly biased! */
1491  EXTDATA* extdata /**< extension data */
1492 )
1493 {
1494  const int nleaves = extdata->tree_nleaves;
1495 
1496  /* if the base is the root and the only leaf, we want to keep the SD */
1497  if( extIsAtInitialComp(extdata) )
1498  {
1499  assert(nleaves == 1);
1500  assert(!extInitialCompIsEdge(extdata) || neighbor_base == extdata->tree_root);
1501  assert(!extInitialCompIsStar(extdata) || neighbor_base == extdata->tree_starcenter);
1502  }
1503  else
1504  {
1505  /* shift the adjacent cost to remove the neighbor base */
1506 
1507  SCIP_Real* const dists = extreduce_mldistsEmptySlotTargetDistsDirty(sds_vertical);
1508  const int leaves_pos = extLeafFindPos(extdata, neighbor_base);
1509 
1510 #ifndef NDEBUG
1511  int* const ids = extreduce_mldistsEmptySlotTargetIdsDirty(sds_vertical);
1512 #endif
1513 
1514  assert(nleaves >= 2);
1515  assert(leaves_pos > 0 && leaves_pos < nleaves);
1516  assert(ids[leaves_pos] == neighbor_base);
1517  assert(neighbor_base != extdata->tree_root);
1518 
1519  for( int i = leaves_pos + 1; i < nleaves; i++ )
1520  {
1521  dists[i - 1] = dists[i];
1522  }
1523 
1524 #ifndef NDEBUG
1525  for( int i = leaves_pos + 1; i < nleaves; i++ )
1526  {
1527  ids[i - 1] = ids[i];
1528  }
1529 
1530  dists[nleaves - 1] = STP_MLDISTS_DIST_UNSET;
1531  ids[nleaves - 1] = STP_MLDISTS_ID_UNSET;
1532 #endif
1533  }
1534 }
1535 
1536 
1537 /** initialization for adding a leaf to a level */
1538 static inline
1540  const GRAPH* graph, /**< graph data structure */
1541  int neighbor_base, /**< neighbor base */
1542  int neighbor, /**< neighbor */
1543  EXTDATA* extdata /**< extension data */
1544 )
1545 {
1546  REDDATA* const reddata = extdata->reddata;
1547  MLDISTS* const sds_vertical = reddata->sds_vertical;
1548  const SCIP_Bool isPc = (extdata->pcdata->pcSdToNode != NULL);
1549 
1550  assert(graph_pc_isPc(graph) == isPc);
1551 
1552  extreduce_mldistsEmptySlotSetBase(neighbor, sds_vertical);
1553 
1554  if( extReddataHasBiasedSds(reddata) )
1556 
1557  /* Initialization for bottleneck. We start from the base of the neighbor! */
1558  extreduce_bottleneckMarkRootPath(graph, neighbor_base, extdata);
1559 
1560  if( isPc )
1561  {
1562  pcSdToNodeMark(graph, neighbor, extdata);
1563  }
1564 }
1565 
1566 
1567 /** finalization for adding a neighbor leaf to a level */
1568 static inline
1570  const GRAPH* graph, /**< graph data structure */
1571  int neighbor_base, /**< neighbor base */
1572  int neighbor, /**< neighbor */
1573  SCIP_Bool ruledOut, /**< extension along neighbor already ruled out? */
1574  EXTDATA* extdata /**< extension data */
1575 )
1576 {
1577  REDDATA* const reddata = extdata->reddata;
1578  MLDISTS* const sds_vertical = reddata->sds_vertical;
1579  MLDISTS* const sdsbias_vertical = reddata->sdsbias_vertical;
1580 
1581  const SCIP_Bool isPc = graph_pc_isPc(graph);
1582 
1583  if( ruledOut )
1584  {
1585  extreduce_mldistsEmptySlotReset(sds_vertical);
1586 
1587  if( extReddataHasBiasedSds(reddata) )
1588  extreduce_mldistsEmptySlotReset(sdsbias_vertical);
1589  }
1590  else
1591  {
1592  /* remove the neighbor base SD entry (which we don't need for further extensions from the neighbor base) */
1593  mstLevelLeafAdjustVerticalSDs(neighbor_base, sds_vertical, extdata);
1595 
1596  if( extReddataHasBiasedSds(reddata) )
1597  {
1598  mstLevelLeafAdjustVerticalSDs(neighbor_base, sdsbias_vertical, extdata);
1599  extreduce_mldistsEmptySlotSetFilled(sdsbias_vertical);
1600  }
1601  }
1602 
1603  extreduce_bottleneckUnmarkRootPath(graph, neighbor_base, extdata);
1604 
1605  if( isPc )
1606  pcSdToNodeUnmark(graph, neighbor, extdata);
1607 }
1608 
1609 
1610 /** checks whether the MST extended at the given neighbor allows to rule-out any extension along this neighbor */
1611 static inline
1613  SCIP* scip, /**< SCIP */
1614  const GRAPH* graph, /**< graph data structure */
1615  int extneighbor, /**< neighbor leaf to extend to */
1616  EXTDATA* extdata, /**< extension data */
1617  SCIP_Bool* leafRuledOut /**< rule out possible? */
1618 )
1619 {
1620  CSR topmst;
1621  SCIP_Real extweight;
1622  REDDATA* const reddata = extdata->reddata;
1623  MLDISTS* const sds_vertical = reddata->sds_vertical;
1624  CSRDEPO* const msts_comp = reddata->msts_comp;
1625  DCMST* const dcmst = reddata->dcmst;
1626  const SCIP_Real* const adjcosts = extreduce_mldistsEmptySlotTargetDistsDirty(sds_vertical);
1627  const SCIP_Bool isPc = (graph->prize != NULL);
1628  SCIP_Real tree_cost = extdata->tree_cost;
1629 
1630  assert(isPc == graph_pc_isPc(graph));
1631  assert(FALSE == *leafRuledOut);
1632 
1633  if( isPc )
1634  {
1635  tree_cost -= extdata->pcdata->tree_innerPrize;
1636  assert(GE(tree_cost, 0.0));
1637  }
1638 
1639  graph_csrdepo_getTopCSR(msts_comp, &topmst);
1640 
1641  assert(topmst.nnodes == extdata->tree_nleaves);
1642 
1643  extweight = reduce_dcmstGetExtWeight(scip, &topmst, adjcosts, dcmst);
1644 
1645 /*
1646  SCIP_Real mstweight = reduce_dcmstGetWeight(scip, &topmst);
1647  assert(extreduce_mstTopCompObjValid(scip, graph, mstweight, extdata));
1648 */
1649 
1650  /* make sure that the objective of the MST is ok! */
1651  assert(extreduce_mstTopCompExtObjValid(scip, graph, extneighbor, extweight, extdata));
1652 
1653  if( LT(extweight, tree_cost) )
1654  {
1655  SCIPdebugMessage("extension along vertex %d ruled out by extension MST! (%f < %f) \n",
1656  extneighbor, extweight, extdata->tree_cost);
1657 
1658  *leafRuledOut = TRUE;
1659  }
1660 }
1661 
1662 
1663 /** builds base MST */
1664 static inline
1666  SCIP* scip, /**< SCIP */
1667  const GRAPH* graph, /**< graph */
1668  int extnode, /**< node from which to extend */
1669  REDDATA* reddata, /**< reduction data */
1670  EXTDATA* extdata /**< extension data */
1671 )
1672 {
1673  CSR mst_new;
1674  CSR mst_parent;
1675  MSTXCOMP mstextcomp;
1676 
1677  assert(extnode >= 0 && extnode < graph->knots);
1678  assert(extnode != extdata->tree_root);
1679 
1680  baseMstInitMsts(extdata, reddata, &mst_parent, &mst_new);
1681 
1682  /* partially initialize 'mstextcomp' */
1683  baseMstInitExtComp(reddata, extnode, &mst_parent, &mst_new, &mstextcomp);
1684 
1685  /* now build the new MST */
1686  baseMstBuildNew(scip, graph, reddata, extdata, &mstextcomp);
1687 
1688  baseMstFinalizeNew(scip, graph, &mstextcomp, reddata, extdata);
1689 }
1690 
1691 
1692 /** Builds base MST if the previous level is the root.
1693  * I.e., just a 1-node MST. */
1694 static inline
1696  SCIP* scip, /**< SCIP */
1697  REDDATA* reddata /**< reduction data */
1698 )
1699 {
1700  CSRDEPO* const msts_levelbase = reddata->msts_levelbase;
1701 
1702  assert(!graph_csrdepo_isEmpty(msts_levelbase));
1703  assert(graph_csrdepo_getNcsrs(msts_levelbase) == 1);
1704 
1705  add1NodeMst(scip, msts_levelbase);
1706 }
1707 
1708 
1709 /** Compute and store horizontal SDs in given ML storage */
1710 static
1712  SCIP* scip, /**< SCIP */
1713  const GRAPH* graph, /**< graph data structure */
1714  int nextedges, /**< number of edges for extension */
1715  const int* extedges, /**< array of edges for extension */
1716  EXTDATA* extdata, /**< extension data */
1717  DISTDATA* distdata, /**< distance data (possibly biased!) */
1718  MLDISTS* sds_horizontal /**< horizontal multi-level distances (possibly biased!) */
1719 )
1720 {
1721  const int* const ghead = graph->head;
1722  const SCIP_Bool isPc = extProbIsPc(graph, extdata);
1723 
1724  assert(nextedges > 0);
1725 
1726  extreduce_mldistsLevelAddTop(nextedges, nextedges - 1, sds_horizontal);
1727 
1728  /* tree has not yet been extended, so sds_horizontal is ahead */
1729  assert(extdata->tree_depth == extreduce_mldistsTopLevel(sds_horizontal) - 1);
1730  assert(extreduce_mldistsEmptySlotExists(sds_horizontal));
1731 
1732  for( int i = 0; i < nextedges; ++i )
1733  {
1734  int* const adjids = extreduce_mldistsEmptySlotTargetIds(sds_horizontal);
1735  SCIP_Real* const adjedgecosts = extreduce_mldistsEmptySlotTargetDists(sds_horizontal);
1736  const int ext_edge = extedges[i];
1737  const int ext_head = ghead[ext_edge];
1738 
1739  extreduce_mldistsEmptySlotSetBase(ext_head, sds_horizontal);
1740 
1741  if( isPc )
1742  pcSdToNodeMark(graph, ext_head, extdata);
1743 
1744  /* for left siblings: use SDs that have already been computed*/
1745  for( int j = 0; j < i; ++j )
1746  {
1747  const int sibling_left = ghead[extedges[j]];
1748  const SCIP_Real specialDist = extreduce_mldistsTopTargetDist(sds_horizontal, sibling_left, ext_head);
1749 
1750 #ifndef NDEBUG
1751  if( !graph_pc_isPc(graph) )
1752  {
1753  const SCIP_Real sd_new = extGetSdDoubleFromDistdata(scip, graph, ext_head, sibling_left, distdata, extdata);
1754  assert(EQ(specialDist, sd_new) || (EQ(specialDist, FARAWAY) && EQ(sd_new, -1.0)));
1755  }
1756 #endif
1757 
1758  adjedgecosts[j] = specialDist;
1759  adjids[j] = sibling_left;
1760  }
1761 
1762  /* for right siblings: compute new SDs */
1763  for( int j = i + 1; j < nextedges; ++j )
1764  {
1765  const int sibling_right = ghead[extedges[j]];
1766  const SCIP_Real specialDist = extGetSdDoubleFromDistdata(scip, graph, ext_head, sibling_right, distdata, extdata);
1767 
1768  adjedgecosts[j - 1] = (specialDist >= -0.5) ? specialDist : FARAWAY;
1769  adjids[j - 1] = sibling_right;
1770  }
1771 
1772  if( isPc )
1773  pcSdToNodeUnmark(graph, ext_head, extdata);
1774 
1775  extreduce_mldistsEmptySlotSetFilled(sds_horizontal);
1776  }
1777 
1778  assert(!extreduce_mldistsEmptySlotExists(sds_horizontal));
1779 }
1780 
1781 
1782 /** Can current tree be peripherally ruled out by using MST based arguments? */
1784  SCIP* scip, /**< SCIP */
1785  const GRAPH* graph, /**< graph data structure */
1786  EXTDATA* extdata /**< extension data */
1787 )
1788 {
1790 
1791  /* build the SD MST and check for early rule-out via bottleneck distances */
1792  mstCompBuildMst(scip, graph, extdata, &ruledOut);
1793 
1794  if( ruledOut)
1795  {
1796  SCIPdebugMessage("Rule-out periph (via bottleneck) \n");
1797 
1798  ruledOut = TRUE;
1799  }
1800  else if( mstCompRuleOut(scip, graph, extdata) )
1801  {
1802  SCIPdebugMessage("Rule-out periph (via MST) \n");
1803 
1804  ruledOut = TRUE;
1805  }
1806 
1807  assert(extreduce_stackTopIsHashed(graph, extdata));
1808 
1809  return ruledOut;
1810 }
1811 
1812 
1813 /** adds the initial level corresponding to the root of the extension tree */
1815  SCIP* scip, /**< SCIP */
1816  int root, /**< the root of the extension tree */
1817  EXTDATA* extdata /**< extension data */
1818 )
1819 {
1820  assert(scip && extdata);
1821  assert(root >= 0);
1822 
1823  mstAddRootLevelMsts(scip, extdata);
1824  mstAddRootLevelSDs(root, extdata);
1825 }
1826 
1827 
1828 /** Removes current component (subset of the top level) from MST storages */
1830  const GRAPH* graph, /**< graph data structure */
1831  EXTDATA* extdata /**< extension data */
1832  )
1833 {
1834  REDDATA* const reddata = extdata->reddata;
1835  CSRDEPO* const msts_comp = reddata->msts_comp;
1836  const int msts_comp_level = graph_csrdepo_getNcsrs(msts_comp) - 1;
1837 
1838  if( msts_comp_level > extdata->tree_depth )
1839  {
1840  graph_csrdepo_removeTop(msts_comp);
1841  }
1842 
1843  assert(graph_csrdepo_getNcsrs(msts_comp) - 1 == extdata->tree_depth);
1844 }
1845 
1846 
1847 /** Adds a full initial new level at the top.
1848  * NOTE: for now only the horizontal distances are initialized */
1850  REDDATA* reddata, /**< reduction data */
1851  EXTDATA* extdata /**< extension data */
1852 )
1853 {
1854  MLDISTS* const sds_vertical = reddata->sds_vertical;
1855  MLDISTS* const sdsbias_vertical = reddata->sdsbias_vertical;
1856  const SCIP_Bool hasBiasedSd = extReddataHasBiasedSds(reddata);
1857 
1858  assert(extIsAtInitialComp(extdata));
1859  assert(extdata->tree_nleaves == 1);
1860 
1861  /* Reserve space for the SDs from each potential vertex of the new level to all leaves
1862  * of the tree except for the extending vertex.
1863  * But for the initial component we need to keep the root! */
1865 
1866  if( hasBiasedSd )
1867  extreduce_mldistsLevelAddTop(STP_EXT_MAXGRAD, extdata->tree_nleaves, sdsbias_vertical);
1868 
1869  SCIPdebugMessage("init MST level %d \n", extreduce_mldistsTopLevel(sds_vertical));
1870 
1871  /* tree has not yet been extended, so sds_vertical is ahead */
1872  assert(extdata->tree_depth == extreduce_mldistsTopLevel(sds_vertical) - 1);
1873  assert(!hasBiasedSd || extreduce_mldistsTopLevel(sdsbias_vertical) == extreduce_mldistsTopLevel(sds_vertical));
1874 }
1875 
1876 
1877 /** Adds neighbor of tree for MST calculation.
1878  * Basically, SDs to all leafs are computed and stored in 'reddata->sds_vertical'.
1879  * Neighbor is given by head of edge 'edge2neighbor'.
1880  * Returns early (with leafRuledOut == TRUE, and without adding the neighbor)
1881  * if extension via this edge can be ruled out already by using a bottleneck argument or MST. */
1883  SCIP* scip, /**< SCIP */
1884  const GRAPH* graph, /**< graph data structure */
1885  int edge2neighbor, /**< the edge from the tree to the neighbor */
1886  EXTDATA* extdata, /**< extension data */
1887  SCIP_Bool* leafRuledOut /**< could the extension already by ruled out */
1888 )
1889 {
1890  const int neighbor = graph->head[edge2neighbor];
1891  const int neighbor_base = graph->tail[edge2neighbor];
1892  const SCIP_Bool isPc = graph_pc_isPc(graph);
1893 
1894  assert(leafRuledOut);
1895  assert(extdata->tree_deg[neighbor_base] == 1);
1896  assert(extdata->tree_deg[neighbor] == 0);
1897  assert(*leafRuledOut == FALSE);
1898  assert(!extIsAtInitialComp(extdata));
1899 
1900  mstLevelLeafInit(graph, neighbor_base, neighbor, extdata);
1901 
1902  /* compute and store SDs to all leaves;
1903  * also check for bottleneck rule-out! */
1904  mstLevelLeafSetVerticalSDsBoth(scip, graph, edge2neighbor, extdata, leafRuledOut);
1905 
1906  /* if not yet ruled out, check whether extending the SD MST helps */
1907  if( !(*leafRuledOut) )
1908  {
1909  mstLevelLeafTryExtMst(scip, graph, neighbor, extdata, leafRuledOut);
1910  }
1911 
1912  /* if not yet ruled out and in PC mode, try bottleneck distances to tree vertices marked before */
1913  if( isPc && !(*leafRuledOut) )
1914  {
1915  extreduce_bottleneckCheckNonLeaves_pc(scip, graph, edge2neighbor, extdata, leafRuledOut);
1916  }
1917 
1918  /* if not yet ruled out, try bottleneck distances to non-leaves of the tree */
1919  if( (extdata->mode == extred_full) && !(*leafRuledOut) && !extInitialCompIsGenStar(extdata) )
1920  {
1921  extreduce_bottleneckCheckNonLeaves(scip, graph, edge2neighbor, extdata, leafRuledOut);
1922  }
1923 
1924  mstLevelLeafExit(graph, neighbor_base, neighbor, *leafRuledOut, extdata);
1925 }
1926 
1927 
1928 /** similar to above, but only for initial component! */
1930  SCIP* scip, /**< SCIP */
1931  const GRAPH* graph, /**< graph data structure */
1932  int edge2neighbor, /**< edge to the neighbor */
1933  EXTDATA* extdata, /**< extension data */
1934  SCIP_Bool* leafRuledOut /**< could the extension already by ruled out? */
1935 )
1936 {
1937  const int neighbor_base = graph->tail[edge2neighbor];
1938  const int neighbor = graph->head[edge2neighbor];
1939 
1940  assert(*leafRuledOut == FALSE);
1941  assert(extIsAtInitialComp(extdata));
1942  assert(!extInitialCompIsEdge(extdata) || neighbor_base == extdata->tree_root);
1943  assert(!extInitialCompIsStar(extdata) || neighbor_base == graph->head[extdata->extstack_data[0]]);
1944  assert(extdata->tree_deg[neighbor_base] >= 1);
1945  assert(extdata->tree_deg[neighbor] == 0);
1946 
1947  /* NOTE: also initializes bottlenecks from neighbor_base */
1948  mstLevelLeafInit(graph, neighbor_base, neighbor, extdata);
1949 
1950  /* compute and store SDs to all leaves;
1951  * also check for bottleneck rule-out! */
1952  mstLevelLeafSetVerticalSDsBoth(scip, graph, edge2neighbor, extdata, leafRuledOut);
1953 
1954  mstLevelLeafExit(graph, neighbor_base, neighbor, *leafRuledOut, extdata);
1955 }
1956 
1957 
1958 /** Adds empty level for vertical SDs */
1960  const GRAPH* graph, /**< graph data structure */
1961  EXTDATA* extdata /**< extension data */
1962 )
1963 {
1964  REDDATA* const reddata = extdata->reddata;
1965  MLDISTS* const sds_vertical = reddata->sds_vertical;
1966 
1967  assert(!(extReddataHasBiasedSds(reddata) && graph_pc_isPc(graph)));
1968 
1969  SCIPdebugMessage("add EMPTY vertical level %d \n", extreduce_mldistsTopLevel(sds_vertical) + 1);
1970 
1971  extreduce_mldistsLevelAddAndCloseEmpty(extdata->tree_nleaves - 1, sds_vertical);
1972 
1973  if( extReddataHasBiasedSds(reddata) )
1974  {
1975  MLDISTS* const sdsbias_vertical = reddata->sdsbias_vertical;
1976 
1977  extreduce_mldistsLevelAddAndCloseEmpty(extdata->tree_nleaves - 1, sdsbias_vertical);
1978 
1979  assert(extreduce_mldistsTopLevel(sdsbias_vertical) == extreduce_mldistsTopLevel(sds_vertical));
1980  }
1981 }
1982 
1983 
1984 /** reopens top level and allows one more slot */
1986  EXTDATA* extdata /**< extension data */
1987 )
1988 {
1989  REDDATA* const reddata = extdata->reddata;
1990  MLDISTS* const sds_vertical = reddata->sds_vertical;
1991  assert(extdata->tree_nleaves - 1 == extreduce_mldistsLevelNTopTargets(sds_vertical));
1992 
1993  extreduce_mldistsLevelReopenTop(sds_vertical);
1994 
1995  if( extReddataHasBiasedSds(reddata) )
1996  {
1997  MLDISTS* const sdsbias_vertical = reddata->sdsbias_vertical;
1998  assert(extdata->tree_nleaves - 1 == extreduce_mldistsLevelNTopTargets(sdsbias_vertical));
1999 
2000  extreduce_mldistsLevelReopenTop(sdsbias_vertical);
2001 
2002  assert(extreduce_mldistsTopLevel(sdsbias_vertical) == extreduce_mldistsTopLevel(sds_vertical));
2003  }
2004 }
2005 
2006 
2007 /** closes vertical part of top MST level for further additions */
2009  REDDATA* reddata /**< reduction data */
2010 )
2011 {
2012  MLDISTS* const sds_vertical = reddata->sds_vertical;
2013 
2014  extreduce_mldistsLevelCloseTop(sds_vertical);
2015 
2016  if( extReddataHasBiasedSds(reddata) )
2017  {
2018  MLDISTS* const sdsbias_vertical = reddata->sdsbias_vertical;
2019 
2020  extreduce_mldistsLevelCloseTop(sdsbias_vertical);
2021  assert(extreduce_mldistsTopLevel(sdsbias_vertical) == extreduce_mldistsTopLevel(sds_vertical));
2022  }
2023 
2024 #ifdef SCIP_DEBUG
2025  {
2026  const int toplevel = extreduce_mldistsTopLevel(sds_vertical);
2027 
2028  SCIPdebugMessage("closing vertical MST level %d, nslots=%d\n",
2029  toplevel,
2030  extreduce_mldistsLevelNSlots(sds_vertical, toplevel) );
2031  }
2032 #endif
2033 }
2034 
2035 
2036 /** Compute and store horizontal SDs */
2038  SCIP* scip, /**< SCIP */
2039  const GRAPH* graph, /**< graph data structure */
2040  int nextedges, /**< number of edges for extension */
2041  const int* extedges, /**< array of edges for extension */
2042  EXTDATA* extdata /**< extension data */
2043 )
2044 {
2045  REDDATA* const reddata = extdata->reddata;
2046  MLDISTS* const sds_horizontal = reddata->sds_horizontal;
2047 
2048  assert(!(extReddataHasBiasedSds(reddata) && graph_pc_isPc(graph)));
2049 
2050  SCIPdebugMessage("add horizontal level %d \n", extreduce_mldistsTopLevel(sds_horizontal) + 1);
2051  mstLevelHorizontalAddSds(scip, graph, nextedges, extedges, extdata, extdata->distdata, sds_horizontal);
2052 
2053  if( extReddataHasBiasedSds(reddata) )
2054  {
2055  MLDISTS* const sdsbias_horizontal = reddata->sdsbias_horizontal;
2056 
2057  mstLevelHorizontalAddSds(scip, graph, nextedges, extedges, extdata, extdata->distdata_biased, sdsbias_horizontal);
2058 
2059  assert(extreduce_mldistsTopLevel(sds_horizontal) == extreduce_mldistsTopLevel(sdsbias_horizontal));
2060  }
2061 }
2062 
2063 
2064 /** Reserve space for horizontal SDs */
2066  const GRAPH* graph, /**< graph data structure */
2067  EXTDATA* extdata /**< extension data */
2068 )
2069 {
2070  REDDATA* const reddata = extdata->reddata;
2071  MLDISTS* const sds_horizontal = reddata->sds_horizontal;
2072 
2073  assert(!(extReddataHasBiasedSds(reddata) && graph_pc_isPc(graph)));
2074  SCIPdebugMessage("add EMPTY horizontal level %d \n", extreduce_mldistsTopLevel(sds_horizontal) + 1);
2075 
2076  extreduce_mldistsLevelAddAndCloseEmpty(0, sds_horizontal);
2077 
2078  if( extReddataHasBiasedSds(reddata) )
2079  {
2080  MLDISTS* const sdsbias_horizontal = reddata->sdsbias_horizontal;
2081  extreduce_mldistsLevelAddAndCloseEmpty(0, sdsbias_horizontal);
2082 
2083  assert(extreduce_mldistsTopLevel(sds_horizontal) == extreduce_mldistsTopLevel(sdsbias_horizontal));
2084  }
2085 }
2086 
2087 
2088 /** Removes top horizontal MST level.
2089  * NOTE: SDs from level vertices to all leafs will be discarded! */
2091  REDDATA* reddata /**< reduction data */
2092 )
2093 {
2094  assert(reddata);
2095  SCIPdebugMessage("remove horizontal MST level %d \n", extreduce_mldistsNlevels(reddata->sds_horizontal));
2096 
2098  if( extReddataHasBiasedSds(reddata) )
2100 }
2101 
2102 
2103 /** Removes top vertical MST level.
2104  * NOTE: SDs from level vertices to all leafs will be discarded! */
2106  REDDATA* reddata /**< reduction data */
2107 )
2108 {
2109  MLDISTS* const sds_vertical = reddata->sds_vertical;
2110 
2111  SCIPdebugMessage("remove vertical MST level %d \n", extreduce_mldistsNlevels(sds_vertical));
2112 
2113  extreduce_mldistsLevelRemoveTop(sds_vertical);
2114 
2115  if( extReddataHasBiasedSds(reddata) )
2116  {
2117  MLDISTS* const sdsbias_vertical = reddata->sdsbias_vertical;
2118  extreduce_mldistsLevelRemoveTop(sdsbias_vertical);
2119  assert(extreduce_mldistsNlevels(sds_vertical) == extreduce_mldistsNlevels(sdsbias_vertical));
2120  }
2121 }
2122 
2123 
2124 /** Closes top MST level for further additions.
2125  * Will initialize the 'mst_levelbase' MST. */
2127  SCIP* scip, /**< SCIP */
2128  const GRAPH* graph, /**< graph */
2129  int extnode, /**< node from which to extend */
2130  EXTDATA* extdata /**< extension data */
2131 )
2132 {
2133  REDDATA* const reddata = extdata->reddata;
2134 
2135  assert(extreduce_mstInternalsInSync(extdata));
2136 
2137 #ifdef SCIP_DEBUG
2138  SCIPdebugMessage("close MST level %d, horizontal nslots=%d\n", extreduce_mldistsTopLevel(reddata->sds_horizontal),
2140 
2141  extreduce_printTopLevel(extdata);
2142 #endif
2143 
2144  /* build a new 'mst_levelbase' MST */
2145  if( extIsAtInitialComp(extdata) )
2146  {
2147  assert(extnode == extdata->tree_root);
2148  mstLevelBuildBaseMstRoot(scip, reddata);
2149  }
2150  else
2151  {
2152  assert(extnode != extdata->tree_root);
2153  mstLevelBuildBaseMst(scip, graph, extnode, reddata, extdata);
2154  }
2155 }
2156 
2157 
2158 /** Removes top MST level (both vertical and horizontal).
2159  * NOTE: SDs from level vertices to all leafs will be discarded! */
2161  REDDATA* reddata /**< reduction data */
2162 )
2163 {
2164  CSRDEPO* const msts_levelbase = reddata->msts_levelbase;
2165  MLDISTS* const sds_vertical = reddata->sds_vertical;
2166  MLDISTS* const sds_horizontal = reddata->sds_horizontal;
2167  const int horizontal_nlevels = extreduce_mldistsNlevels(sds_horizontal);
2168  const int vertical_nlevels = extreduce_mldistsNlevels(sds_vertical);
2169 
2170  assert(horizontal_nlevels == vertical_nlevels || (horizontal_nlevels + 1) == vertical_nlevels);
2171 
2172  SCIPdebugMessage("remove MST level %d \n", vertical_nlevels - 1);
2173 
2174  /* it might happen that the horizontal part has not yet been added */
2175  if( horizontal_nlevels == vertical_nlevels )
2176  {
2177  SCIPdebugMessage("remove horizontal level %d \n", horizontal_nlevels - 1);
2178 
2179  extreduce_mldistsLevelRemoveTop(sds_horizontal);
2180 
2181  if( extReddataHasBiasedSds(reddata) )
2183 
2184  graph_csrdepo_removeTop(msts_levelbase);
2185  }
2186 
2187  assert(graph_csrdepo_getNcsrs(msts_levelbase) == extreduce_mldistsNlevels(sds_horizontal));
2188 
2189  extreduce_mldistsLevelRemoveTop(sds_vertical);
2190 
2191  if( extReddataHasBiasedSds(reddata) )
2193 }
2194 
2195 
2196 /** Returns special distance.
2197  * NOTE: Only checks normal distance from vertex1 to vertex2.
2198  * I.e., might lead different result if 'vertex1' and 'vertex2' are swapped.
2199  * SHOULD MOSTLY BE USED FOR DEBUG CHECKS! */
2201  SCIP* scip, /**< SCIP */
2202  const GRAPH* g, /**< graph data structure */
2203  int vertex1, /**< first vertex */
2204  int vertex2, /**< second vertex */
2205  EXTDATA* extdata /**< extension data */
2206 )
2207 {
2208  return extGetSd(scip, g, vertex1, vertex2, extdata);
2209 }
2210 
2211 /** Returns special distance.
2212  * NOTE: Checks normal distance from vertex2 to vertex1 if no opposite distance is known.
2213  * SHOULD MOSTLY BE USED FOR DEBUG CHECKS! */
2215  SCIP* scip, /**< SCIP */
2216  const GRAPH* g, /**< graph data structure */
2217  int vertex1, /**< first vertex */
2218  int vertex2, /**< second vertex */
2219  EXTDATA* extdata /**< extension data */
2220 )
2221 {
2222  return extGetSdDouble(scip, g, vertex1, vertex2, extdata);
2223 }
2224 
2225 
2226 /** Proper SD version of above method. I.e. SD is non-negative, but possibly FARAWAY
2227  * FOR DEBUG CHECKS ONLY! */
2229  SCIP* scip, /**< SCIP */
2230  const GRAPH* g, /**< graph data structure */
2231  int vertex1, /**< first vertex */
2232  int vertex2, /**< second vertex */
2233  EXTDATA* extdata /**< extension data */
2234 )
2235 {
2236  return extSdGetProper(extGetSd(scip, g, vertex1, vertex2, extdata));
2237 }
2238 
2239 
2240 /** Proper SD version of above method. I.e. SD is non-negative, but possibly FARAWAY
2241  * FOR DEBUG CHECKS ONLY! */
2243  SCIP* scip, /**< SCIP */
2244  const GRAPH* g, /**< graph data structure */
2245  int vertex1, /**< first vertex */
2246  int vertex2, /**< second vertex */
2247  EXTDATA* extdata /**< extension data */
2248 )
2249 {
2250  return extSdGetProper(extGetSdDouble(scip, g, vertex1, vertex2, extdata));
2251 }
void graph_csr_copy(const CSR *, CSR *)
Definition: graph_util.c:1483
void graph_csrdepo_addEmptyTopTree(CSRDEPO *, int)
Definition: graph_util.c:836
void extreduce_mstLevelVerticalReopen(EXTDATA *extdata)
static void mstLevelBuildBaseMst(SCIP *scip, const GRAPH *graph, int extnode, REDDATA *reddata, EXTDATA *extdata)
SCIP_Bool extreduce_bottleneckIsDominatedBiased(SCIP *, const GRAPH *, int, int, SCIP_Real, EXTDATA *)
void extreduce_mstLevelVerticalClose(REDDATA *reddata)
SCIP_Bool extreduce_mstTopCompObjValid(SCIP *, const GRAPH *, SCIP_Real, EXTDATA *)
void graph_csr_print(const CSR *)
Definition: graph_util.c:1514
static SCIP_Bool extInitialCompIsGenStar(const EXTDATA *extdata)
static void mstLevelBuildBaseMstRoot(SCIP *scip, REDDATA *reddata)
int *RESTRICT head
Definition: graphdefs.h:224
static void mstLevelLeafSetVerticalSDsBoth(SCIP *scip, const GRAPH *graph, int edge2neighbor, EXTDATA *extdata, SCIP_Bool *ruledOut)
static int extLeafFindPos(const EXTDATA *extdata, int leaf)
#define Is_term(a)
Definition: graphdefs.h:102
int extreduce_mldistsLevelNSlots(const MLDISTS *, int)
SCIP_Real extreduce_distDataGetSdDouble(SCIP *, const GRAPH *, int, int, DISTDATA *)
static void pcSdToNodeMark(const GRAPH *graph, int startvertex, EXTDATA *extdata)
int *const pcSdCands
int start
Definition: graphdefs.h:152
void extreduce_bottleneckCheckNonLeaves(SCIP *, const GRAPH *, int, EXTDATA *, SCIP_Bool *)
SCIP_Bool extreduce_mstTopLevelBaseObjValid(SCIP *, const GRAPH *, int, EXTDATA *)
static void mstCompBuildMst(SCIP *scip, const GRAPH *graph, EXTDATA *extdata, SCIP_Bool *ruledOut)
SCIP_Bool extreduce_mstInternalsInSync(const EXTDATA *)
static SCIP_Bool extIsAtInitialStar(const EXTDATA *extdata)
void extreduce_mstLevelVerticalAddLeafInitial(SCIP *scip, const GRAPH *graph, int edge2neighbor, EXTDATA *extdata, SCIP_Bool *leafRuledOut)
SCIP_Bool extreduce_mldistsEmptySlotExists(const MLDISTS *)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
static SCIP_Bool dbgBottleneckFromLeafIsDominated(SCIP *scip, const GRAPH *graph, int topleaf, SCIP_Bool with_sd_double, int edge_forbidden, EXTDATA *extdata)
SCIP_Real tree_innerPrize
int * extreduce_mldistsEmptySlotTargetIdsDirty(const MLDISTS *)
static void extGetSdPcUpdate(const GRAPH *g, const PCDATA *pcdata, int vertex1, int vertex2, SCIP_Real *sd)
SCIP_Bool extreduce_bottleneckIsDominated(SCIP *, const GRAPH *, int, int, SCIP_Real, int, EXTDATA *)
#define EXT_PC_SDMAXVISITS
SCIP_Real * extreduce_mldistsEmptySlotTargetDistsDirty(const MLDISTS *)
static SCIP_Bool mstCompLeafToAncestorsBiasedRuleOut(SCIP *scip, const GRAPH *graph, int edge2leaf, int nleaves_ancestors, EXTDATA *extdata)
void extreduce_mldistsEmptySlotSetBase(int, MLDISTS *)
static SCIP_Real extGetSdDoubleFromDistdata(SCIP *scip, const GRAPH *g, int vertex1, int vertex2, DISTDATA *distdata, EXTDATA *extdata)
#define FALSE
Definition: def.h:87
static SCIP_Bool mstCompLeafToSiblingsBiasedRuleOut(SCIP *scip, const GRAPH *graph, int edge2top, EXTDATA *extdata)
void extreduce_mstLevelHorizontalAddEmpty(const GRAPH *graph, EXTDATA *extdata)
static void mstLevelLeafAdjustVerticalSDs(int neighbor_base, MLDISTS *sds_vertical, EXTDATA *extdata)
#define TRUE
Definition: def.h:86
int extreduce_mldistsNlevels(const MLDISTS *)
includes various files containing graph methods used for Steiner tree problems
static SCIP_Bool extInitialCompIsEdge(const EXTDATA *extdata)
int *const extstack_data
void extreduce_mstLevelVerticalRemove(REDDATA *reddata)
SCIP_Real * cost
Definition: graphdefs.h:164
static int extStackGetTopOutEdgesStart(const EXTDATA *extdata, int stackpos)
void graph_csrdepo_getTopCSR(const CSRDEPO *, CSR *)
Definition: graph_util.c:684
#define EXT_STATE_EXPANDED
Definition: extreducedefs.h:53
SCIP_Bool extreduce_sdsverticalInSync(SCIP *, const GRAPH *, int, int, int, EXTDATA *)
static void baseMstBuildNew(SCIP *scip, const GRAPH *graph, REDDATA *reddata, EXTDATA *extdata, MSTXCOMP *mstextcomp)
static SCIP_Bool extInitialCompIsStar(const EXTDATA *extdata)
static SCIP_Real extGetSdDouble(SCIP *scip, const GRAPH *g, int vertex1, int vertex2, EXTDATA *extdata)
#define SCIPdebugMessage
Definition: pub_message.h:87
#define FARAWAY
Definition: graphdefs.h:89
static int extStackGetTopOutEdgesEnd(const EXTDATA *extdata, int stackpos)
static int extStackGetPosition(const EXTDATA *extdata)
SCIP_Real extreduce_distDataGetSdDoubleForbidden(SCIP *, const GRAPH *, int, int, EXTDATA *)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
static void mstLevelHorizontalAddSds(SCIP *scip, const GRAPH *graph, int nextedges, const int *extedges, EXTDATA *extdata, DISTDATA *distdata, MLDISTS *sds_horizontal)
int extreduce_extStackCompNOutedges(const EXTDATA *, int)
REDDATA *const reddata
void extreduce_mldistsLevelCloseTop(MLDISTS *)
static void add1NodeMst(SCIP *scip, CSRDEPO *msts)
SCIP_Bool graph_csrdepo_isEmpty(const CSRDEPO *)
Definition: graph_util.c:851
static void mstLevelLeafTryExtMst(SCIP *scip, const GRAPH *graph, int extneighbor, EXTDATA *extdata, SCIP_Bool *leafRuledOut)
static int extStackGetTopSize(const EXTDATA *extdata)
static SCIP_Bool mstCompRuleOut(SCIP *scip, const GRAPH *graph, EXTDATA *extdata)
static void baseMstGetAdjcosts(const REDDATA *reddata, MSTXCOMP *mstextcomp, SCIP_Real adjcosts[])
static void mstAddRootLevelMsts(SCIP *scip, EXTDATA *extdata)
static void pcSdToNodeUnmark(const GRAPH *graph, int startvertex, EXTDATA *extdata)
SCIP_Real extreduce_extGetSdProperDouble(SCIP *scip, const GRAPH *g, int vertex1, int vertex2, EXTDATA *extdata)
int extreduce_mldistsTopLevelNSlots(const MLDISTS *)
SCIP_Real reduce_dcmstGetExtWeight(SCIP *, const CSR *, const SCIP_Real *, DCMST *)
Definition: reduce_util.c:1541
int *const tree_leaves
void reduce_dcmstAddNode(SCIP *, const CSR *, const SCIP_Real *, DCMST *, CSR *)
Definition: reduce_util.c:1411
This file implements extended reduction techniques for several Steiner problems.
void extreduce_mldistsLevelAddAndCloseEmpty(int, MLDISTS *)
#define LE(a, b)
Definition: portab.h:83
static SCIP_Real extSdGetProper(SCIP_Real sd_in)
#define GE(a, b)
Definition: portab.h:85
static void mstCompAddLeaf(SCIP *scip, const GRAPH *graph, int edge2leaf, MSTXCOMP *mstextcomp, EXTDATA *extdata, SCIP_Bool *leafRuledOut)
#define EXT_STATE_MARKED
Definition: extreducedefs.h:54
void extreduce_bottleneckUnmarkRootPath(const GRAPH *, int, EXTDATA *)
SCIP_Real *const pcSdToNode
static void baseMstInitMsts(const EXTDATA *extdata, REDDATA *reddata, CSR *mst_parent, CSR *mst_new)
int * extreduce_mldistsEmptySlotTargetIds(const MLDISTS *)
SCIP_Bool extreduce_bottleneckWithExtedgeIsDominated(SCIP *, const GRAPH *, int, int, int, SCIP_Real, EXTDATA *)
SCIP_Bool extreduce_mstTopCompExtObjValid(SCIP *, const GRAPH *, int, SCIP_Real, EXTDATA *)
void SCIPsortIntInt(int *intarray1, int *intarray2, int len)
void reduce_dcmstGet1NodeMst(SCIP *, CSR *)
Definition: reduce_util.c:1479
void extreduce_mldistsEmptySlotSetFilled(MLDISTS *)
static SCIP_Bool extIsAtInitialComp(const EXTDATA *extdata)
static void baseMstGetOrderedParentNodes(const GRAPH *graph, const EXTDATA *extdata, int *parentcomp_size, int parentcomp_nodes[])
SCIP_Real * prize
Definition: graphdefs.h:210
void extreduce_mstCompRemove(const GRAPH *graph, EXTDATA *extdata)
int nedges_max
Definition: graphdefs.h:144
SCIP_Real reduce_dcmstGetWeight(SCIP *, const CSR *)
Definition: reduce_util.c:1573
static SCIP_Bool extReddataHasBiasedSds(const REDDATA *reddata)
void reduce_dcmstAddNodeInplace(SCIP *, const SCIP_Real *, DCMST *, CSR *)
Definition: reduce_util.c:1438
void extreduce_mldistsLevelReopenTop(MLDISTS *)
void graph_csrdepo_getEmptyTop(const CSRDEPO *, CSR *)
Definition: graph_util.c:874
void extreduce_printTopLevel(const EXTDATA *)
static void compMstFinalizeNew(const MSTXCOMP *mstextcomp, SCIP_Bool deletemst, EXTDATA *extdata)
int extreduce_mldistsLevelNTargets(const MLDISTS *, int)
void extreduce_mldistsLevelAddAndCloseRoot(int, MLDISTS *)
SCIP_Bool extreduce_spg3LeafTreeRuleOut(SCIP *, const GRAPH *, SCIP_Real, EXTDATA *)
#define NULL
Definition: lpi_spx1.cpp:155
int *const extstack_state
void extreduce_mldistsLevelRemoveTop(MLDISTS *)
static SCIP_Bool extProbIsPc(const GRAPH *graph, const EXTDATA *extdata)
#define EQ(a, b)
Definition: portab.h:79
static void baseMstInitExtComp(const REDDATA *reddata, int extnode, const CSR *mst_parent, CSR *mst_new, MSTXCOMP *mstextcomp)
int knots
Definition: graphdefs.h:190
SCIP_Bool extreduce_sdshorizontalInSync(SCIP *, const GRAPH *, int, EXTDATA *)
static SCIP_Real extGetSd(SCIP *scip, const GRAPH *g, int vertex1, int vertex2, EXTDATA *extdata)
static void compMstInitExtComp(const GRAPH *graph, const EXTDATA *extdata, const CSR *mst_base, CSR *mst_new, MSTXCOMP *mstextcomp)
SCIP_Bool extreduce_stackTopIsHashed(const GRAPH *, const EXTDATA *)
static int extStackGetOutEdgesEnd(const EXTDATA *extdata, int stackpos)
void extreduce_mstLevelRemove(REDDATA *reddata)
DISTDATA *const distdata_biased
void graph_csrdepo_addEmptyTop(CSRDEPO *, int, int)
Definition: graph_util.c:800
static void mstCompLeafGetSDs(SCIP *scip, const GRAPH *graph, int edge2leaf, EXTDATA *extdata, SCIP_Real sds[], SCIP_Bool *leafRuledOut)
SCIP_Real extreduce_extGetSd(SCIP *scip, const GRAPH *g, int vertex1, int vertex2, EXTDATA *extdata)
#define LT(a, b)
Definition: portab.h:81
SCIP_Real extreduce_mldistsTopTargetDist(const MLDISTS *, int, int)
#define STP_MLDISTS_ID_UNSET
Definition: extreducedefs.h:57
static int extStackGetOutEdgesStart(const EXTDATA *extdata, int stackpos)
static void mstLevelLeafExit(const GRAPH *graph, int neighbor_base, int neighbor, SCIP_Bool ruledOut, EXTDATA *extdata)
SCIP_Real * reduce_dcmstGetAdjcostBuffer(const DCMST *)
Definition: reduce_util.c:1617
SCIP_Bool extreduce_bottleneckToSiblingIsDominated(SCIP *, const GRAPH *, int, int, SCIP_Real, EXTDATA *)
CSRDEPO *const msts_comp
struct mst_extension_tree_component MSTXCOMP
#define SCIP_Bool
Definition: def.h:84
const SCIP_Real * extreduce_mldistsTopTargetDists(const MLDISTS *, int)
void extreduce_bottleneckCheckNonLeaves_pc(SCIP *, const GRAPH *, int, EXTDATA *, SCIP_Bool *)
static int extStackGetLastMarked(const EXTDATA *extdata)
static void pcSdMarkSingle(const GRAPH *graph, int entry, SCIP_Real value, SCIP_Real *pcSdToNode, int *pcSdCands, int *nPcSdCands)
SCIP_Bool extreduce_mstbiased3LeafTreeRuleOut(SCIP *, const GRAPH *, SCIP_Real, EXTDATA *)
void graph_csrdepo_removeTop(CSRDEPO *)
Definition: graph_util.c:753
int reduce_dcmstGetMaxnnodes(const DCMST *)
Definition: reduce_util.c:1604
static void mstCompLeafGetSDsToAncestors(SCIP *scip, const GRAPH *graph, int edge2leaf, int nleaves_ancestors, EXTDATA *extdata, SCIP_Real sds[], SCIP_Bool *leafRuledOut)
includes extended reductions definitions and inline methods used for Steiner tree problems ...
SCIP_Real extreduce_distDataGetSd(SCIP *, const GRAPH *, int, int, DISTDATA *)
void extreduce_mstAddRootLevel(SCIP *scip, int root, EXTDATA *extdata)
#define STP_MLDISTS_DIST_UNSET
Definition: extreducedefs.h:58
int *RESTRICT tail
Definition: graphdefs.h:223
CSRDEPO *const msts_levelbase
void graph_csrdepo_print(const CSRDEPO *)
Definition: graph_util.c:908
int *const extstack_start
#define MAX(x, y)
Definition: tclique_def.h:83
SCIP_Real extreduce_extGetSdProper(SCIP *scip, const GRAPH *g, int vertex1, int vertex2, EXTDATA *extdata)
SCIP_Real * extreduce_mldistsEmptySlotTargetDists(const MLDISTS *)
void extreduce_mstLevelVerticalAddEmpty(const GRAPH *graph, EXTDATA *extdata)
int *RESTRICT term
Definition: graphdefs.h:196
PCDATA *const pcdata
SCIP_Bool graph_pc_isPc(const GRAPH *)
void extreduce_mstLevelVerticalAddLeaf(SCIP *scip, const GRAPH *graph, int edge2neighbor, EXTDATA *extdata, SCIP_Bool *leafRuledOut)
int extreduce_mldistsLevelNTopTargets(const MLDISTS *)
Portable definitions.
SCIP_Bool sdeq_hasForbiddenEdges
#define EXT_STATE_NONE
Definition: extreducedefs.h:52
DCMST *const dcmst
void extreduce_bottleneckMarkRootPath(const GRAPH *, int, EXTDATA *)
enum EXTRED_MODE mode
void extreduce_mldistsLevelAddTop(int, int, MLDISTS *)
void graph_csrdepo_emptyTopSetMarked(CSRDEPO *)
Definition: graph_util.c:890
DISTDATA *const distdata
int extreduce_mldistsTopLevel(const MLDISTS *)
static void mstCompLeafGetSDsToSiblings(SCIP *scip, const GRAPH *graph, int edge2top, EXTDATA *extdata, SCIP_Real sds[], SCIP_Bool *leafRuledOut)
static SCIP_Bool ruledOut(SCIP *scip, const GRAPH *graph, EXTDATA *extdata)
static void compMstInitMsts(EXTDATA *extdata, CSR *mst_base, CSR *mst_new)
#define STP_EXT_MAXGRAD
Definition: extreducedefs.h:42
SCIP_Bool extreduce_nodeIsInStackTop(const GRAPH *, const EXTDATA *, int)
SCIP_Bool extreduce_bottleneckToSiblingIsDominatedBiased(SCIP *, const GRAPH *, int, int, SCIP_Real, EXTDATA *)
static SCIP_Bool extIsAtInitialGenStar(const EXTDATA *extdata)
SCIP_Bool graph_pc_isPcMw(const GRAPH *)
void extreduce_mstLevelHorizontalRemove(REDDATA *reddata)
SCIP_Bool extreduce_bottleneckWithExtedgeIsDominatedBiased(SCIP *, const GRAPH *, int, int, int, SCIP_Real, EXTDATA *)
SCIP_Bool extreduce_sdsTopInSync(SCIP *, const GRAPH *, const SCIP_Real[], int, EXTDATA *)
#define SCIP_Real
Definition: def.h:177
void extreduce_mldistsEmptySlotReset(MLDISTS *)
static void mstLevelLeafInit(const GRAPH *graph, int neighbor_base, int neighbor, EXTDATA *extdata)
const SCIP_Real * extreduce_mldistsTargetDists(const MLDISTS *, int, int)
MLDISTS *const sds_vertical
MLDISTS *const sdsbias_vertical
SCIP_Real extreduce_mldistsTargetDist(const MLDISTS *, int, int, int)
MLDISTS *const sds_horizontal
int *const tree_deg
static void mstAddRootLevelSDs(int root, EXTDATA *extdata)
static void baseMstFinalizeNew(SCIP *scip, const GRAPH *graph, const MSTXCOMP *mstextcomp, REDDATA *reddata, EXTDATA *extdata)
void extreduce_mstLevelClose(SCIP *scip, const GRAPH *graph, int extnode, EXTDATA *extdata)
DCSR * dcsr_storage
Definition: graphdefs.h:271
SCIP_Bool extreduce_mstTopCompInSync(SCIP *, const GRAPH *, EXTDATA *)
SCIP_Real extreduce_extGetSdDouble(SCIP *scip, const GRAPH *g, int vertex1, int vertex2, EXTDATA *extdata)
MLDISTS *const sdsbias_horizontal
void extreduce_mstLevelInitialInit(REDDATA *reddata, EXTDATA *extdata)
SCIP_Real tree_cost
static int extGetNancestorLeaves(const EXTDATA *extdata)
static SCIP_Bool mstEqComp3RuleOut(SCIP *scip, const GRAPH *graph, SCIP_Real tree_cost, EXTDATA *extdata)
static void mstExtend(SCIP *scip, const SCIP_Real adjcosts[], DCMST *dcmst, MSTXCOMP *mstextcomp)
SCIP_Bool extreduce_mstRuleOutPeriph(SCIP *scip, const GRAPH *graph, EXTDATA *extdata)
int graph_csrdepo_getNcsrs(const CSRDEPO *)
Definition: graph_util.c:741
void extreduce_mstLevelHorizontalAdd(SCIP *scip, const GRAPH *graph, int nextedges, const int *extedges, EXTDATA *extdata)