Scippy

SCIP

Solving Constraint Integer Programs

extreduce_redcosts.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_redcosts.c
17  * @brief reduced cost routines for extended reduction techniques for Steiner tree problems
18  * @author Daniel Rehfeldt
19  *
20  * This file implements methods for using reduced costs in extended reduction techniques.
21  *
22  * A list of all interface methods can be found in extreduce.h.
23  *
24  */
25 
26 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
27 
28  //#define SCIP_DEBUG
29  // #define STP_DEBUG_EXT
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <assert.h>
34 #include "graph.h"
35 #include "portab.h"
36 #include "extreduce.h"
37 
38 #ifndef NDEBUG
39 /** recomputes simple reduced costs for current tree */
40 static
42  const GRAPH* graph, /**< graph data structure */
43  int redcostlevel, /**< the reduced costs level */
44  const EXTDATA* extdata, /**< extension data */
45  int root /**< the root for the orientation */
46 )
47 {
48  const REDCOST* const redcostdata = extdata->redcostdata;
49  const PATH* const nodeTo3TermsPaths = redcosts_getNodeToTermsPaths(redcostdata, redcostlevel);
50  const SCIP_Real* const rootToNodeDist = redcosts_getRootToNodeDist(redcostdata, redcostlevel);
51  const SCIP_Real* const redcost = redcosts_getEdgeCosts(redcostdata, redcostlevel);
52  const int* const tree_edges = extdata->tree_edges;
53  const int* const tree_leaves = extdata->tree_leaves;
54  const int tree_nedges = extdata->tree_nedges;
55  const int nleaves = extdata->tree_nleaves;
56  const int tree_root = extdata->tree_root;
57  SCIP_Real tree_redcost;
58 
59  tree_redcost = rootToNodeDist[root];
60 
61  for( int i = 0; i < nleaves; i++ )
62  {
63  const int leaf = tree_leaves[i];
64  if( leaf == root )
65  continue;
66 
67  tree_redcost += nodeTo3TermsPaths[leaf].dist;
68  }
69 
70  for( int i = 0; i < tree_nedges; i++ )
71  {
72  const int edge = tree_edges[i];
73  assert(edge >= 0 && edge < graph->edges);
74 
75  tree_redcost += redcost[edge];
76  assert(LT(tree_redcost, FARAWAY));
77  }
78 
79  for( int node = root; node != tree_root; node = extdata->tree_parentNode[node] )
80  {
81  int e;
82  const int parent = extdata->tree_parentNode[node];
83  assert(graph_knot_isInRange(graph, parent));
84 
85  for( e = graph->outbeg[node]; e != EAT_LAST; e = graph->oeat[e] )
86  {
87  if( graph->head[e] == parent )
88  break;
89  }
90 
91  assert(e != EAT_LAST);
92  tree_redcost += redcost[e];
93  tree_redcost -= redcost[flipedge(e)];
94  }
95 
96  return tree_redcost;
97 }
98 #endif
99 
100 
101 /** insertion sort; keyArr has sentinel value at position -1
102  * : do something special: maybe sort index array
103  * */
104 static inline
106  int* RESTRICT keyArr, /**< key array of size 'nentries' */
107  SCIP_Real* RESTRICT dataArr1, /**< array of size 'nentries' */
108  SCIP_Real* RESTRICT dataArr2, /**< array of size 'nentries' */
109  int nentries /**< number of entries */
110 )
111 {
112  assert(keyArr && dataArr1 && dataArr2);
113  assert(nentries >= 1);
114 
115 #if 1
116  for( int i = 1; i < nentries; i++ )
117  {
118  int j;
119  const int currKey = keyArr[i];
120  const SCIP_Real currData1 = dataArr1[i];
121  const SCIP_Real currData2 = dataArr2[i];
122 
123  for( j = i - 1; currKey > keyArr[j]; j-- )
124  {
125  assert(j >= 0);
126  keyArr[j + 1] = keyArr[j];
127  dataArr1[j + 1] = dataArr1[j];
128  dataArr2[j + 1] = dataArr2[j];
129  }
130 
131  keyArr[j + 1] = currKey;
132  dataArr1[j + 1] = currData1;
133  dataArr2[j + 1] = currData2;
134  }
135 #else
136  for( int i = 0; i < nentries - 1; i++ )
137  {
138  int max_pos = i;
139 
140  for( int j = i + 1; j < nentries; j++ )
141  {
142  if( keyArr[j] > keyArr[max_pos] )
143  max_pos = j;
144  }
145 
146  if( max_pos != i )
147  {
148  int temp_int;
149  SCIP_Real tmp_real;
150 
151  temp_int = keyArr[max_pos];
152  keyArr[max_pos] = keyArr[i];
153  keyArr[i] = temp_int;
154 
155  tmp_real = dataArr1[max_pos];
156  dataArr1[max_pos] = dataArr1[i];
157  dataArr1[i] = tmp_real;
158 
159  tmp_real = dataArr2[max_pos];
160  dataArr2[max_pos] = dataArr2[i];
161  dataArr2[i] = tmp_real;
162  }
163  }
164 #endif
165 
166 #ifndef NDEBUG
167  for( int i = 1; i < nentries; i++ )
168  assert(keyArr[i - 1] >= keyArr[i] );
169 #endif
170 }
171 
172 
173 /** helper for rooted tree reduced cost computation */
174 static inline
176  const SCIP_Real* firstTermDist, /**< array of size 'nentries' */
177  const SCIP_Real* secondTermDist, /**< array of size 'nentries' */
178  int nentries /**< number of entries to check */
179 )
180 {
181  SCIP_Real min;
182 
183  assert(firstTermDist && secondTermDist);
184  assert(nentries >= 1);
185 
186  if( nentries == 1 )
187  {
188  min = firstTermDist[0];
189  }
190  else
191  {
192  int i;
193  SCIP_Real secondSum = 0.0;
194  min = FARAWAY;
195 
196  for( i = 0; i < nentries; i++ )
197  {
198  assert(LE(firstTermDist[i], secondTermDist[i]));
199  assert(LE(secondTermDist[i], FARAWAY));
200 
201  if( EQ(secondTermDist[i], FARAWAY) )
202  break;
203 
204  secondSum += secondTermDist[i];
205  }
206 
207  assert(LT(secondSum, FARAWAY));
208 
209  /* is there an index i with secondTermDist[i] == FARAWAY? */
210  if( i < nentries )
211  {
212  assert(EQ(secondTermDist[i], FARAWAY));
213 
214  min = firstTermDist[i];
215  for( int j = 0; j < nentries; j++ )
216  {
217  if( j == i )
218  continue;
219 
220  min += secondTermDist[j];
221  }
222  }
223  else
224  {
225  for( i = 0; i < nentries; i++ )
226  {
227  const SCIP_Real distCombination = secondSum + firstTermDist[i] - secondTermDist[i];
228 
229  assert(LT(secondTermDist[i], FARAWAY));
230 
231  if( distCombination < min )
232  min = distCombination;
233  }
234 
235  assert(LE(min, secondSum));
236  }
237  }
238 
239  return min;
240 }
241 
242 
243 /** gets reduced cost of current tree rooted at leave 'root' */
244 static inline
246  const GRAPH* graph, /**< graph data structure */
247  int redcostlevel, /**< the reduced costs level */
248  const EXTDATA* extdata, /**< extension data */
249  int root /**< the root for the orientation */
250 )
251 {
252  int nearestTerms_x[STP_EXTTREE_MAXNLEAVES_GUARD + 1];
253  int* nearestTerms;
255  SCIP_Real secondTermDist[STP_EXTTREE_MAXNLEAVES_GUARD];
256  const int* const tree_leaves = extdata->tree_leaves;
257  const int nleaves = extdata->tree_nleaves;
258  const REDDATA* reddata = extdata->reddata;
259  const REDCOST* const redcostdata = extdata->redcostdata;
260  const PATH* const nodeTo3TermsPaths = redcosts_getNodeToTermsPaths(redcostdata, redcostlevel);
261  const SCIP_Real* const rootToNodeDist = redcosts_getRootToNodeDist(redcostdata, redcostlevel);
262  const int* const next3Terms = redcosts_getNodeToTermsBases(redcostdata, redcostlevel);
263  const SCIP_Bool* const isterm = extdata->node_isterm;
264  const int* tree_deg = extdata->tree_deg;
265  const int nnodes = graph->knots;
266  const SCIP_Real tree_redcost = reddata->redcost_treecosts[redcostlevel];
267  const SCIP_Real swapcost = reddata->redcost_treenodeswaps[redcostlevel * nnodes + root];
268  SCIP_Real redcost_directed = tree_redcost + rootToNodeDist[root] + swapcost;
269  int leavescount = 0;
270 #ifndef NDEBUG
271  SCIP_Real redcost_debug = redcost_directed;
272 #endif
273 
274  nearestTerms_x[0] = INT_MAX;
275  nearestTerms = &(nearestTerms_x[1]);
276 
277 #ifndef NDEBUG
278  for( int i = 0; i < STP_EXTTREE_MAXNLEAVES_GUARD; i++ )
279  {
280  nearestTerms[i] = -1;
281  firstTermDist[i] = -1.0;
282  secondTermDist[i] = -1.0;
283  }
284 
285  assert(LT(redcost_directed, FARAWAY));
286  assert(GE(tree_redcost, 0.0));
287  assert(graph_knot_isInRange(graph, root));
288 #endif
289 
290 
291 
292 #ifdef STP_DEBUG_EXT
293  SCIPdebugMessage("...reduced costs without leaves: %f (treecost=%f + rootdist=%f + swap=%f) \n",
294  redcost_directed, tree_redcost, rootToNodeDist[root], swapcost);
295 #endif
296 
297  for( int j = 0; j < nleaves; j++ )
298  {
299  int i;
300  int term;
301  const int leaf = tree_leaves[j];
302 
303 #ifdef STP_DEBUG_EXT
304  SCIPdebugMessage("...checking leaf: %d \n", leaf);
305 #endif
306 
307  if( leaf == root || isterm[leaf] )
308  {
309  assert(leaf == root || EQ(0.0, nodeTo3TermsPaths[leaf].dist));
310  continue;
311  }
312 
313  /* find closest valid terminal for extension */
314  for( i = 0; i < 3; i++ )
315  {
316  term = next3Terms[leaf + i * nnodes];
317 
318  if( term == UNKNOWN )
319  break;
320 
321  assert(graph_pc_isPcMw(graph) || Is_term(graph->term[term]));
322  assert(term >= 0 && term < graph->knots);
323  assert(term != leaf);
324 
325  /* terminal not in current tree?*/
326  if( tree_deg[term] == 0 )
327  break;
328 
329  if( tree_deg[term] < 0 )
330  {
331  assert(graph_pc_isPcMw(graph) && tree_deg[term] == -1);
332  assert(Is_pseudoTerm(graph->term[term]));
333  break;
334  }
335  }
336 
337  /* no terminal reachable? */
338  if( term == UNKNOWN )
339  {
340 #ifdef STP_DEBUG_EXT
341  SCIPdebugMessage("...no terminal reachable from leaf %d \n", leaf);
342 #endif
343  assert(i < 3 && GE(nodeTo3TermsPaths[leaf + i * nnodes].dist, FARAWAY));
344  return FARAWAY;
345  }
346 
347  /* all terminals in current tree? */
348  if( i == 3 )
349  i = 2;
350 
351  nearestTerms[leavescount] = term;
352  firstTermDist[leavescount] = nodeTo3TermsPaths[leaf + i * nnodes].dist;
353  secondTermDist[leavescount] = (i < 2) ? nodeTo3TermsPaths[leaf + (i + 1) * nnodes].dist : firstTermDist[leavescount];
354 
355  assert(LE(nodeTo3TermsPaths[leaf].dist, firstTermDist[leavescount]));
356  assert(LE(firstTermDist[leavescount], secondTermDist[leavescount]));
357 
358 #ifdef STP_DEBUG_EXT
359  SCIPdebugMessage("...closeterm=%d, dist1=%f dist2=%f distdef=%f \n", term,
360  firstTermDist[leavescount], secondTermDist[leavescount], nodeTo3TermsPaths[leaf].dist);
361 #endif
362 
363  leavescount++;
364 
365 #ifndef NDEBUG
366  redcost_debug += nodeTo3TermsPaths[leaf].dist;
367  assert(leavescount <= STP_EXTTREE_MAXNLEAVES_GUARD);
368 #endif
369  }
370 
371  if( leavescount > 0 )
372  {
373  int first = 0;
374 
375  sortDescendingIntRealReal(nearestTerms, firstTermDist, secondTermDist, leavescount);
376 
377  for( int i = 1; i < leavescount; i++ )
378  {
379  assert(nearestTerms[i] >= 0 && firstTermDist[i] >= 0.0 && secondTermDist[i] >= 0.0);
380  if( nearestTerms[i] != nearestTerms[i - 1] )
381  {
382  const int n = i - first;
383  redcost_directed += getMinDistCombination(firstTermDist + first, secondTermDist + first, n);
384  first = i;
385  }
386  }
387 
388  redcost_directed += getMinDistCombination(firstTermDist + first, secondTermDist + first, leavescount - first);
389  }
390 
391 
392 #ifdef STP_DEBUG_EXT
393  SCIPdebugMessage("...reduced costs with leaves: %f \n", redcost_directed);
394 #endif
395 
396  // printf("redcost_directed=%f redcost_debug=%f \n", redcost_directed, redcost_debug );
397 
398  assert(GE(redcost_directed, redcost_debug));
399 
400  return redcost_directed;
401 }
402 
403 
404 /** gets reduced cost of current tree rooted at leave 'root' */
405 static inline
407  const GRAPH* graph, /**< graph data structure */
408  int redcostlevel, /**< the reduced costs level */
409  const EXTDATA* extdata, /**< extension data */
410  const REDDATA* reddata, /**< reduction data */
411  int root /**< the root for the orientation */
412 )
413 {
414  const SCIP_Real* const redcost_treenodeswaps = reddata->redcost_treenodeswaps;
415 
416  assert(extdata->tree_nleaves > 1 && extdata->tree_nleaves < STP_EXTTREE_MAXNLEAVES_GUARD);
417  assert(extdata->tree_leaves[0] == extdata->tree_root);
418  assert(graph_knot_isInRange(graph, root));
419 
420 #ifdef STP_DEBUG_EXT
421  SCIPdebugMessage("Check directed tree rooted at %d \n", root);
422 #endif
423 
424  /* are there any deleted arcs in the directed tree? */
425  if( extdata->tree_nDelUpArcs > 0 && root == extdata->tree_root )
426  {
427  return FARAWAY;
428  }
429 
430  /* is the rooting possible? */
431  if( LT(redcost_treenodeswaps[redcostlevel * graph->knots + root], FARAWAY) )
432  {
433  return extTreeGetDirectedRedcostProper(graph, redcostlevel, extdata, root);
434  }
435 
436 #ifdef STP_DEBUG_EXT
437  SCIPdebugMessage("Directed tree directly ruled-out \n");
438 #endif
439 
440  return FARAWAY;
441 }
442 
443 
444 /** checks for reduced-cost cutoff of current tree */
445 static inline
447  const GRAPH* graph, /**< graph data structure */
448  int redcostlevel, /**< level */
449  const EXTDATA* extdata, /**< extension data */
450  const REDDATA* reddata /**< reduction data */
451 )
452 {
453  const int* const tree_leaves = extdata->tree_leaves;
454  const SCIP_Real cutoff = redcosts_getCutoff(extdata->redcostdata, redcostlevel);
455  const int nleaves = extdata->tree_nleaves;
456  const SCIP_Bool allowEquality = reddata->redcost_allowEquality;
457 
458 #ifdef SCIP_DEBUG
459  SCIP_Real tree_redcost = FARAWAY;
460 #endif
461 
462 #ifdef STP_DEBUG_EXT
463  SCIPdebugMessage("---Redcosts checking LEVEL %d--- \n", redcostlevel);
464 #endif
465 
466  /* take each leaf as root of the tree and check whether cutoff condition is violated */
467  for( int i = 0; i < nleaves; i++ )
468  {
469  const int leaf = tree_leaves[i];
470  const SCIP_Real tree_redcost_new = extTreeGetDirectedRedcost(graph, redcostlevel, extdata, reddata, leaf);
471 
472  // printf("%f >= %f \n", tree_redcost_new, getTreeRedcosts_dbg(graph, extdata, leaf));
473  assert(GE_FEAS_EPS(tree_redcost_new, getTreeRedcosts_dbg(graph, redcostlevel, extdata, leaf), EPS_ZERO_HARD));
474 
475  if( allowEquality ? LT(tree_redcost_new, cutoff) : LE(tree_redcost_new, cutoff) )
476  {
477  SCIPdebugMessage("NO rule-out periph (red.cost<=%f from root=%d and cutoff=%f) \n", tree_redcost_new, leaf, cutoff);
478  return FALSE;
479  }
480 
481 #ifdef SCIP_DEBUG
482  tree_redcost = MIN(tree_redcost, tree_redcost_new);
483 #endif
484  }
485 
486 #ifdef SCIP_DEBUG
487  SCIPdebugMessage("Rule-out periph (with red.cost=%f and cutoff=%f, level=%d) \n", tree_redcost, cutoff, redcostlevel);
488 #endif
489 
490  return TRUE;
491 }
492 
493 
494 /** recomputes reduced cost tree information */
496  SCIP* scip, /**< SCIP */
497  const GRAPH* graph, /**< graph data structure */
498  EXTDATA* extdata /**< extension data */
499 )
500 {
501 
502  REDDATA* const reddata = extdata->reddata;
503  const STP_Bool* const edgedeleted = reddata->edgedeleted;
504  SCIP_Real* lvl_redcostsbuffer;
505  const SCIP_Real* const lvl_redcosts = redcosts_getEdgeCosts(extdata->redcostdata, 0);
506  const int* const tree_edges = extdata->tree_edges;
507  SCIP_Real* const redcost_treecosts = extdata->reddata->redcost_treecosts;
508  const int tree_nedges = extdata->tree_nedges;
509  const int nlevels = reddata->redcost_nlevels;
510  const int nedges = graph->edges;
511 
512  assert(!extreduce_treeIsFlawed(scip, graph, extdata));
513  assert(nedges == redcosts_getNedges(extdata->redcostdata));
514 
515  SCIP_CALL_ABORT( SCIPallocBlockMemoryArray(scip, &lvl_redcostsbuffer, nlevels) );
516 
517  for( int i = 0; i < nlevels; i++ )
518  lvl_redcostsbuffer[i] = 0.0;
519 
520  for( int i = 0; i < tree_nedges; i++ )
521  {
522  const int edge = tree_edges[i];
523  const SCIP_Bool edgeIsDeleted = (edgedeleted && edgedeleted[edge]);
524  assert(graph_edge_isInRange(graph, edge));
525 
526  if( !edgeIsDeleted )
527  {
528  /* NOTE: not clean, but better for better performance */
529  for( int j = 0; j < nlevels; j++ )
530  {
531  lvl_redcostsbuffer[j] += lvl_redcosts[j * nedges + edge];
532  assert(LT(lvl_redcostsbuffer[j], FARAWAY));
533  }
534  }
535  }
536 
537  for( int i = 0; i < nlevels; i++ )
538  {
539  assert(SCIPisEQ(scip, redcost_treecosts[i], lvl_redcostsbuffer[i]));
540  redcost_treecosts[i] = lvl_redcostsbuffer[i];
541  }
542 
543  SCIPfreeBlockMemoryArray(scip, &lvl_redcostsbuffer, nlevels);
544 }
545 
546 
547 /** NOTE: call before adding edges for new expansion! */
549  const GRAPH* graph, /**< graph data structure */
550  EXTDATA* extdata /**< extension data */
551 )
552 {
553  REDDATA* const reddata = extdata->reddata;
554  const REDCOST* const redcostdata = extdata->redcostdata;
555  SCIP_Bool* const noReverses = reddata->redcost_noReversedTree;
556  const SCIP_Real* const treenodeswaps = reddata->redcost_treenodeswaps;
557  const int nlevels = reddata->redcost_nlevels;
558  const int comproot = extStackGetTopRoot(graph, extdata);
559  const int tree_root = extdata->tree_root;
560  const int nnodes = graph->knots;
561 
562  for( int i = 0; i < nlevels; i++ )
563  {
564  noReverses[i] = (redcosts_getRoot(redcostdata, i) == tree_root || GE(treenodeswaps[nnodes * i + comproot], FARAWAY));
565  }
566 }
567 
568 
569 /** Updates reduced cost for added edge.
570  * NOTE: call extreduce_redcostInitExpansion before each new expansion! */
572  const GRAPH* graph, /**< graph data structure */
573  int edge, /**< edge to be added */
574  REDDATA* reddata, /**< reduction data */
575  EXTDATA* extdata /**< extension data */
576 )
577 {
578  const SCIP_Real* const redcosts = redcosts_getEdgeCosts(extdata->redcostdata, 0);
579  SCIP_Real* const redcost_treenodeswaps = reddata->redcost_treenodeswaps;
580  SCIP_Real* const redcost_treecosts = reddata->redcost_treecosts;
581  SCIP_Bool* const redcost_noReverses = reddata->redcost_noReversedTree;
582  const STP_Bool* const edgedeleted = reddata->edgedeleted;
583  const SCIP_Bool edgeIsDeleted = (edgedeleted && edgedeleted[edge]);
584  const int tail = graph->tail[edge];
585  const int head = graph->head[edge];
586  const int nlevels = reddata->redcost_nlevels;
587  const int nnodes = graph->knots;
588  const int nedges = graph->edges;
589 
590  assert(!edgedeleted && "deprecated!");
591  assert(nedges == redcosts_getNedges(extdata->redcostdata));
592  assert(nnodes == redcosts_getNnodes(extdata->redcostdata));
593 
594  for( int i = 0; i < nlevels; i++ )
595  {
596  const int offset_node = i * nnodes;
597  const int offset_edge = i * nedges;
598 
599  if( redcost_noReverses[i] || (edgedeleted && edgedeleted[flipedge(edge)]) )
600  {
601  redcost_treenodeswaps[offset_node + head] = FARAWAY;
602 
603  if( head == extdata->tree_starcenter )
604  {
605  assert(extIsAtInitialStar(extdata) || extIsAtInitialGenStar(extdata));
606  redcost_noReverses[i] = TRUE;
607  }
608  }
609  else
610  {
611  redcost_treenodeswaps[offset_node + head] =
612  redcost_treenodeswaps[offset_node + tail] + redcosts[offset_edge + flipedge(edge)];
613 
614  if( !edgeIsDeleted )
615  redcost_treenodeswaps[offset_node + head] -= redcosts[offset_edge + edge];
616 
617  assert(LT(redcost_treenodeswaps[offset_node + head], FARAWAY));
618  }
619 
620  if( !edgeIsDeleted )
621  {
622  redcost_treecosts[i] += redcosts[offset_edge + edge];
623  assert(LT(redcost_treecosts[i], FARAWAY));
624  }
625  }
626 
627  if( edgeIsDeleted )
628  {
629  extdata->tree_nDelUpArcs++;
630  }
631 }
632 
633 
634 /** update reduced cost for removed edge */
636  int edge, /**< edge to be added */
637  const REDDATA* reddata, /**< reduction data */
638  EXTDATA* extdata /**< extension data */
639 )
640 {
641  const SCIP_Bool edgeIsDeleted = (reddata->edgedeleted && reddata->edgedeleted[edge]);
642 
643  if( !edgeIsDeleted )
644  {
645  const SCIP_Real* const redcosts = redcosts_getEdgeCosts(extdata->redcostdata, 0);
646  const int nlevels = reddata->redcost_nlevels;
647  const int nedges = redcosts_getNedges(extdata->redcostdata);
648  SCIP_Real* const redcost_treecosts = reddata->redcost_treecosts;
649 
650  for( int i = 0; i < nlevels; i++ )
651  {
652  redcost_treecosts[i] -= redcosts[i * nedges + edge];
653  assert(LT(redcost_treecosts[i], FARAWAY));
654  }
655  }
656  else
657  {
658  extdata->tree_nDelUpArcs--;
659  assert(extdata->tree_nDelUpArcs >= 0);
660  }
661 }
662 
663 
664 /** Can current tree be peripherally ruled out by using reduced costs arguments? */
666  const GRAPH* graph, /**< graph data structure */
667  EXTDATA* extdata /**< extension data */
668 )
669 {
670  const REDDATA* const reddata = extdata->reddata;
671  const int nlevels = reddata->redcost_nlevels;
672 
673  assert(graph);
674  assert(extdata->tree_nleaves > 1 && extdata->tree_leaves[0] == extdata->tree_root);
675  assert(nlevels >= 1);
676 
677  for( int i = 0; i < nlevels; i++ )
678  {
679  if( extTreeRedcostCutoff(graph, i, extdata, reddata) )
680  {
681  return TRUE;
682  }
683  }
684 
685  return FALSE;
686 }
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:101
const STP_Bool *const edgedeleted
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:84
int *RESTRICT head
Definition: graphdefs.h:224
SCIP_Bool extreduce_treeIsFlawed(SCIP *, const GRAPH *, const EXTDATA *)
#define Is_term(a)
Definition: graphdefs.h:102
static SCIP_Bool extIsAtInitialStar(const EXTDATA *extdata)
SCIP_Real * redcosts_getRootToNodeDist(const REDCOST *redcostdata, int level)
Definition: redcosts.c:213
static SCIP_Real extTreeGetDirectedRedcostProper(const GRAPH *graph, int redcostlevel, const EXTDATA *extdata, int root)
SCIP_Real *const redcost_treecosts
#define FALSE
Definition: def.h:87
int redcosts_getRoot(const REDCOST *redcostdata, int level)
Definition: redcosts.c:335
#define TRUE
Definition: def.h:86
includes various files containing graph methods used for Steiner tree problems
const SCIP_Bool redcost_allowEquality
int *const tree_edges
#define EAT_LAST
Definition: graphdefs.h:58
#define SCIPdebugMessage
Definition: pub_message.h:87
#define FARAWAY
Definition: graphdefs.h:89
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define EPS_ZERO_HARD
Definition: portab.h:59
REDDATA *const reddata
static SCIP_Real extTreeGetDirectedRedcost(const GRAPH *graph, int redcostlevel, const EXTDATA *extdata, const REDDATA *reddata, int root)
void extreduce_redcostRemoveEdge(int edge, const REDDATA *reddata, EXTDATA *extdata)
SCIP_Real * redcosts_getEdgeCosts(const REDCOST *redcostdata, int level)
Definition: redcosts.c:187
static void sortDescendingIntRealReal(int *RESTRICT keyArr, SCIP_Real *RESTRICT dataArr1, SCIP_Real *RESTRICT dataArr2, int nentries)
int * redcosts_getNodeToTermsBases(const REDCOST *redcostdata, int level)
Definition: redcosts.c:264
int *const tree_leaves
int *RESTRICT oeat
Definition: graphdefs.h:231
This file implements extended reduction techniques for several Steiner problems.
#define LE(a, b)
Definition: portab.h:83
#define GE(a, b)
Definition: portab.h:85
int *const tree_parentNode
int redcosts_getNnodes(const REDCOST *redcostdata)
Definition: redcosts.c:165
SCIP_Real dist
Definition: graphdefs.h:286
int redcosts_getNedges(const REDCOST *redcostdata)
Definition: redcosts.c:176
static SCIP_Real getTreeRedcosts_dbg(const GRAPH *graph, int redcostlevel, const EXTDATA *extdata, int root)
#define EQ(a, b)
Definition: portab.h:79
int knots
Definition: graphdefs.h:190
SCIP_Real redcosts_getCutoff(const REDCOST *redcostdata, int level)
Definition: redcosts.c:288
#define LT(a, b)
Definition: portab.h:81
const REDCOST *const redcostdata
unsigned char STP_Bool
Definition: portab.h:34
#define STP_EXTTREE_MAXNLEAVES_GUARD
Definition: extreducedefs.h:48
#define SCIP_Bool
Definition: def.h:84
void extreduce_redcostTreeRecompute(SCIP *scip, const GRAPH *graph, EXTDATA *extdata)
int *RESTRICT tail
Definition: graphdefs.h:223
#define flipedge(edge)
Definition: graphdefs.h:84
static SCIP_Bool extTreeRedcostCutoff(const GRAPH *graph, int redcostlevel, const EXTDATA *extdata, const REDDATA *reddata)
SCIP_Real *const redcost_treenodeswaps
void extreduce_redcostAddEdge(const GRAPH *graph, int edge, REDDATA *reddata, EXTDATA *extdata)
int *RESTRICT term
Definition: graphdefs.h:196
const SCIP_Bool *const node_isterm
Portable definitions.
SCIP_Bool *const redcost_noReversedTree
#define Is_pseudoTerm(a)
Definition: graphdefs.h:103
static SCIP_Real getMinDistCombination(const SCIP_Real *firstTermDist, const SCIP_Real *secondTermDist, int nentries)
SCIP_Bool graph_edge_isInRange(const GRAPH *, int)
Definition: graph_stats.c:110
const int redcost_nlevels
static SCIP_Bool extIsAtInitialGenStar(const EXTDATA *extdata)
SCIP_Bool graph_pc_isPcMw(const GRAPH *)
#define SCIP_Real
Definition: def.h:177
PATH * redcosts_getNodeToTermsPaths(const REDCOST *redcostdata, int level)
Definition: redcosts.c:240
int *RESTRICT outbeg
Definition: graphdefs.h:204
int edges
Definition: graphdefs.h:219
SCIP_Bool graph_knot_isInRange(const GRAPH *, int)
Definition: graph_node.c:52
SCIP_Bool extreduce_redcostRuleOutPeriph(const GRAPH *graph, EXTDATA *extdata)
#define UNKNOWN
Definition: sepa_mcf.c:4095
int *const tree_deg
#define nnodes
Definition: gastrans.c:65
static int extStackGetTopRoot(const GRAPH *graph, const EXTDATA *extdata)
#define SCIP_CALL_ABORT(x)
Definition: def.h:363
void extreduce_redcostInitExpansion(const GRAPH *graph, EXTDATA *extdata)
#define GE_FEAS_EPS(a, b, eps)
Definition: portab.h:77