Scippy

SCIP

Solving Constraint Integer Programs

tree.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-2017 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file tree.c
17  * @brief methods for branch and bound tree
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Gerald Gamrath
21  */
22 
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24 
25 #include <assert.h>
26 
27 #include "scip/def.h"
28 #include "scip/set.h"
29 #include "scip/stat.h"
30 #include "scip/clock.h"
31 #include "scip/visual.h"
32 #include "scip/event.h"
33 #include "scip/lp.h"
34 #include "scip/relax.h"
35 #include "scip/var.h"
36 #include "scip/implics.h"
37 #include "scip/primal.h"
38 #include "scip/tree.h"
39 #include "scip/reopt.h"
40 #include "scip/conflictstore.h"
41 #include "scip/solve.h"
42 #include "scip/cons.h"
43 #include "scip/nodesel.h"
44 #include "scip/prop.h"
45 #include "scip/debug.h"
46 #include "scip/prob.h"
47 #include "scip/scip.h"
48 #include "scip/pub_message.h"
49 #include "lpi/lpi.h"
50 
51 
52 #define MAXREPROPMARK 511 /**< maximal subtree repropagation marker; must correspond to node data structure */
53 
54 
55 /*
56  * dynamic memory arrays
57  */
58 
59 /** resizes children arrays to be able to store at least num nodes */
60 static
62  SCIP_TREE* tree, /**< branch and bound tree */
63  SCIP_SET* set, /**< global SCIP settings */
64  int num /**< minimal number of node slots in array */
65  )
66 {
67  assert(tree != NULL);
68  assert(set != NULL);
69 
70  if( num > tree->childrensize )
71  {
72  int newsize;
73 
74  newsize = SCIPsetCalcMemGrowSize(set, num);
75  SCIP_ALLOC( BMSreallocMemoryArray(&tree->children, newsize) );
76  SCIP_ALLOC( BMSreallocMemoryArray(&tree->childrenprio, newsize) );
77  tree->childrensize = newsize;
78  }
79  assert(num <= tree->childrensize);
80 
81  return SCIP_OKAY;
82 }
83 
84 /** resizes path array to be able to store at least num nodes */
85 static
87  SCIP_TREE* tree, /**< branch and bound tree */
88  SCIP_SET* set, /**< global SCIP settings */
89  int num /**< minimal number of node slots in path */
90  )
91 {
92  assert(tree != NULL);
93  assert(set != NULL);
94 
95  if( num > tree->pathsize )
96  {
97  int newsize;
98 
99  newsize = SCIPsetCalcPathGrowSize(set, num);
100  SCIP_ALLOC( BMSreallocMemoryArray(&tree->path, newsize) );
101  SCIP_ALLOC( BMSreallocMemoryArray(&tree->pathnlpcols, newsize) );
102  SCIP_ALLOC( BMSreallocMemoryArray(&tree->pathnlprows, newsize) );
103  tree->pathsize = newsize;
104  }
105  assert(num <= tree->pathsize);
106 
107  return SCIP_OKAY;
108 }
109 
110 /** resizes pendingbdchgs array to be able to store at least num nodes */
111 static
113  SCIP_TREE* tree, /**< branch and bound tree */
114  SCIP_SET* set, /**< global SCIP settings */
115  int num /**< minimal number of node slots in path */
116  )
117 {
118  assert(tree != NULL);
119  assert(set != NULL);
120 
121  if( num > tree->pendingbdchgssize )
122  {
123  int newsize;
124 
125  newsize = SCIPsetCalcMemGrowSize(set, num);
126  SCIP_ALLOC( BMSreallocMemoryArray(&tree->pendingbdchgs, newsize) );
127  tree->pendingbdchgssize = newsize;
128  }
129  assert(num <= tree->pendingbdchgssize);
130 
131  return SCIP_OKAY;
132 }
133 
134 
135 
136 
137 /*
138  * Node methods
139  */
140 
141 /** node comparator for best lower bound */
142 SCIP_DECL_SORTPTRCOMP(SCIPnodeCompLowerbound)
143 { /*lint --e{715}*/
144  assert(elem1 != NULL);
145  assert(elem2 != NULL);
146 
147  if( ((SCIP_NODE*)elem1)->lowerbound < ((SCIP_NODE*)elem2)->lowerbound )
148  return -1;
149  else if( ((SCIP_NODE*)elem1)->lowerbound > ((SCIP_NODE*)elem2)->lowerbound )
150  return +1;
151  else
152  return 0;
153 }
154 
155 /** increases the reference counter of the LP state in the fork */
156 static
158  SCIP_FORK* fork, /**< fork data */
159  int nuses /**< number to add to the usage counter */
160  )
161 {
162  assert(fork != NULL);
163  assert(fork->nlpistateref >= 0);
164  assert(nuses > 0);
165 
166  fork->nlpistateref += nuses;
167  SCIPdebugMessage("captured LPI state of fork %p %d times -> new nlpistateref=%d\n", (void*)fork, nuses, fork->nlpistateref);
168 }
169 
170 /** decreases the reference counter of the LP state in the fork */
171 static
173  SCIP_FORK* fork, /**< fork data */
174  BMS_BLKMEM* blkmem, /**< block memory buffers */
175  SCIP_LP* lp /**< current LP data */
176  )
177 {
178  assert(fork != NULL);
179  assert(fork->nlpistateref > 0);
180  assert(blkmem != NULL);
181  assert(lp != NULL);
182 
183  fork->nlpistateref--;
184  if( fork->nlpistateref == 0 )
185  {
186  SCIP_CALL( SCIPlpFreeState(lp, blkmem, &(fork->lpistate)) );
187  }
188 
189  SCIPdebugMessage("released LPI state of fork %p -> new nlpistateref=%d\n", (void*)fork, fork->nlpistateref);
190 
191  return SCIP_OKAY;
192 }
193 
194 /** increases the reference counter of the LP state in the subroot */
195 static
197  SCIP_SUBROOT* subroot, /**< subroot data */
198  int nuses /**< number to add to the usage counter */
199  )
200 {
201  assert(subroot != NULL);
202  assert(subroot->nlpistateref >= 0);
203  assert(nuses > 0);
204 
205  subroot->nlpistateref += nuses;
206  SCIPdebugMessage("captured LPI state of subroot %p %d times -> new nlpistateref=%d\n",
207  (void*)subroot, nuses, subroot->nlpistateref);
208 }
209 
210 /** decreases the reference counter of the LP state in the subroot */
211 static
213  SCIP_SUBROOT* subroot, /**< subroot data */
214  BMS_BLKMEM* blkmem, /**< block memory buffers */
215  SCIP_LP* lp /**< current LP data */
216  )
217 {
218  assert(subroot != NULL);
219  assert(subroot->nlpistateref > 0);
220  assert(blkmem != NULL);
221  assert(lp != NULL);
222 
223  subroot->nlpistateref--;
224  if( subroot->nlpistateref == 0 )
225  {
226  SCIP_CALL( SCIPlpFreeState(lp, blkmem, &(subroot->lpistate)) );
227  }
228 
229  SCIPdebugMessage("released LPI state of subroot %p -> new nlpistateref=%d\n", (void*)subroot, subroot->nlpistateref);
230 
231  return SCIP_OKAY;
232 }
233 
234 /** increases the reference counter of the LP state in the fork or subroot node */
236  SCIP_NODE* node, /**< fork/subroot node */
237  int nuses /**< number to add to the usage counter */
238  )
239 {
240  assert(node != NULL);
241 
242  SCIPdebugMessage("capture %d times LPI state of node #%" SCIP_LONGINT_FORMAT " at depth %d (current: %d)\n",
243  nuses, SCIPnodeGetNumber(node), SCIPnodeGetDepth(node),
245 
246  switch( SCIPnodeGetType(node) )
247  {
248  case SCIP_NODETYPE_FORK:
249  forkCaptureLPIState(node->data.fork, nuses);
250  break;
252  subrootCaptureLPIState(node->data.subroot, nuses);
253  break;
254  default:
255  SCIPerrorMessage("node for capturing the LPI state is neither fork nor subroot\n");
256  SCIPABORT();
257  return SCIP_INVALIDDATA; /*lint !e527*/
258  } /*lint !e788*/
259  return SCIP_OKAY;
260 }
261 
262 /** decreases the reference counter of the LP state in the fork or subroot node */
264  SCIP_NODE* node, /**< fork/subroot node */
265  BMS_BLKMEM* blkmem, /**< block memory buffers */
266  SCIP_LP* lp /**< current LP data */
267  )
268 {
269  assert(node != NULL);
270 
271  SCIPdebugMessage("release LPI state of node #%" SCIP_LONGINT_FORMAT " at depth %d (current: %d)\n",
272  SCIPnodeGetNumber(node), SCIPnodeGetDepth(node),
274  switch( SCIPnodeGetType(node) )
275  {
276  case SCIP_NODETYPE_FORK:
277  return forkReleaseLPIState(node->data.fork, blkmem, lp);
279  return subrootReleaseLPIState(node->data.subroot, blkmem, lp);
280  default:
281  SCIPerrorMessage("node for releasing the LPI state is neither fork nor subroot\n");
282  return SCIP_INVALIDDATA;
283  } /*lint !e788*/
284 }
285 
286 /** creates probingnode data without LP information */
287 static
289  SCIP_PROBINGNODE** probingnode, /**< pointer to probingnode data */
290  BMS_BLKMEM* blkmem, /**< block memory */
291  SCIP_LP* lp /**< current LP data */
292  )
293 {
294  assert(probingnode != NULL);
295 
296  SCIP_ALLOC( BMSallocBlockMemory(blkmem, probingnode) );
297 
298  (*probingnode)->lpistate = NULL;
299  (*probingnode)->ninitialcols = SCIPlpGetNCols(lp);
300  (*probingnode)->ninitialrows = SCIPlpGetNRows(lp);
301  (*probingnode)->ncols = (*probingnode)->ninitialcols;
302  (*probingnode)->nrows = (*probingnode)->ninitialrows;
303  (*probingnode)->origobjvars = NULL;
304  (*probingnode)->origobjvals = NULL;
305  (*probingnode)->nchgdobjs = 0;
306 
307  SCIPdebugMessage("created probingnode information (%d cols, %d rows)\n", (*probingnode)->ncols, (*probingnode)->nrows);
308 
309  return SCIP_OKAY;
310 }
311 
312 /** updates LP information in probingnode data */
313 static
315  SCIP_PROBINGNODE* probingnode, /**< probingnode data */
316  BMS_BLKMEM* blkmem, /**< block memory */
317  SCIP_TREE* tree, /**< branch and bound tree */
318  SCIP_LP* lp /**< current LP data */
319  )
320 {
321  assert(probingnode != NULL);
322  assert(SCIPtreeIsPathComplete(tree));
323  assert(lp != NULL);
324 
325  /* free old LP state */
326  if( probingnode->lpistate != NULL )
327  {
328  SCIP_CALL( SCIPlpFreeState(lp, blkmem, &probingnode->lpistate) );
329  }
330 
331  /* get current LP state */
332  if( lp->flushed && lp->solved )
333  {
334  SCIP_CALL( SCIPlpGetState(lp, blkmem, &probingnode->lpistate) );
335  probingnode->lpwasprimfeas = lp->primalfeasible;
336  probingnode->lpwasprimchecked = lp->primalchecked;
337  probingnode->lpwasdualfeas = lp->dualfeasible;
338  probingnode->lpwasdualchecked = lp->dualchecked;
339  }
340  else
341  probingnode->lpistate = NULL;
342 
343  probingnode->ncols = SCIPlpGetNCols(lp);
344  probingnode->nrows = SCIPlpGetNRows(lp);
345 
346  SCIPdebugMessage("updated probingnode information (%d cols, %d rows)\n", probingnode->ncols, probingnode->nrows);
347 
348  return SCIP_OKAY;
349 }
350 
351 /** frees probingnode data */
352 static
354  SCIP_PROBINGNODE** probingnode, /**< probingnode data */
355  BMS_BLKMEM* blkmem, /**< block memory */
356  SCIP_LP* lp /**< current LP data */
357  )
358 {
359  assert(probingnode != NULL);
360  assert(*probingnode != NULL);
361 
362  /* free the associated LP state */
363  if( (*probingnode)->lpistate != NULL )
364  {
365  SCIP_CALL( SCIPlpFreeState(lp, blkmem, &(*probingnode)->lpistate) );
366  }
367 
368  /* free objective information */
369  if( (*probingnode)->nchgdobjs > 0 )
370  {
371  assert((*probingnode)->origobjvars != NULL);
372  assert((*probingnode)->origobjvals != NULL);
373 
374  BMSfreeMemoryArray(&(*probingnode)->origobjvars);
375  BMSfreeMemoryArray(&(*probingnode)->origobjvals);
376  }
377 
378  BMSfreeBlockMemory(blkmem, probingnode);
379 
380  return SCIP_OKAY;
381 }
382 
383 /** initializes junction data */
384 static
386  SCIP_JUNCTION* junction, /**< pointer to junction data */
387  SCIP_TREE* tree /**< branch and bound tree */
388  )
389 {
390  assert(junction != NULL);
391  assert(tree != NULL);
392  assert(tree->nchildren > 0);
393  assert(SCIPtreeIsPathComplete(tree));
394  assert(tree->focusnode != NULL);
395 
396  junction->nchildren = tree->nchildren;
397 
398  /* increase the LPI state usage counter of the current LP fork */
399  if( tree->focuslpstatefork != NULL )
400  {
402  }
403 
404  return SCIP_OKAY;
405 }
406 
407 /** creates pseudofork data */
408 static
410  SCIP_PSEUDOFORK** pseudofork, /**< pointer to pseudofork data */
411  BMS_BLKMEM* blkmem, /**< block memory */
412  SCIP_TREE* tree, /**< branch and bound tree */
413  SCIP_LP* lp /**< current LP data */
414  )
415 {
416  assert(pseudofork != NULL);
417  assert(blkmem != NULL);
418  assert(tree != NULL);
419  assert(tree->nchildren > 0);
420  assert(SCIPtreeIsPathComplete(tree));
421  assert(tree->focusnode != NULL);
422 
423  SCIP_ALLOC( BMSallocBlockMemory(blkmem, pseudofork) );
424 
425  (*pseudofork)->addedcols = NULL;
426  (*pseudofork)->addedrows = NULL;
427  (*pseudofork)->naddedcols = SCIPlpGetNNewcols(lp);
428  (*pseudofork)->naddedrows = SCIPlpGetNNewrows(lp);
429  (*pseudofork)->nchildren = tree->nchildren;
430 
431  SCIPdebugMessage("creating pseudofork information with %d children (%d new cols, %d new rows)\n",
432  (*pseudofork)->nchildren, (*pseudofork)->naddedcols, (*pseudofork)->naddedrows);
433 
434  if( (*pseudofork)->naddedcols > 0 )
435  {
436  /* copy the newly created columns to the pseudofork's col array */
437  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*pseudofork)->addedcols, SCIPlpGetNewcols(lp), \
438  (*pseudofork)->naddedcols) );
439  }
440  if( (*pseudofork)->naddedrows > 0 )
441  {
442  int i;
443 
444  /* copy the newly created rows to the pseudofork's row array */
445  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*pseudofork)->addedrows, SCIPlpGetNewrows(lp), \
446  (*pseudofork)->naddedrows) );
447 
448  /* capture the added rows */
449  for( i = 0; i < (*pseudofork)->naddedrows; ++i )
450  SCIProwCapture((*pseudofork)->addedrows[i]);
451  }
452 
453  /* increase the LPI state usage counter of the current LP fork */
454  if( tree->focuslpstatefork != NULL )
455  {
457  }
458 
459  return SCIP_OKAY;
460 }
461 
462 /** frees pseudofork data */
463 static
465  SCIP_PSEUDOFORK** pseudofork, /**< pseudofork data */
466  BMS_BLKMEM* blkmem, /**< block memory */
467  SCIP_SET* set, /**< global SCIP settings */
468  SCIP_LP* lp /**< current LP data */
469  )
470 {
471  int i;
472 
473  assert(pseudofork != NULL);
474  assert(*pseudofork != NULL);
475  assert((*pseudofork)->nchildren == 0);
476  assert(blkmem != NULL);
477  assert(set != NULL);
478 
479  /* release the added rows */
480  for( i = 0; i < (*pseudofork)->naddedrows; ++i )
481  {
482  SCIP_CALL( SCIProwRelease(&(*pseudofork)->addedrows[i], blkmem, set, lp) );
483  }
484 
485  BMSfreeBlockMemoryArrayNull(blkmem, &(*pseudofork)->addedcols, (*pseudofork)->naddedcols);
486  BMSfreeBlockMemoryArrayNull(blkmem, &(*pseudofork)->addedrows, (*pseudofork)->naddedrows);
487  BMSfreeBlockMemory(blkmem, pseudofork);
488 
489  return SCIP_OKAY;
490 }
491 
492 /** creates fork data */
493 static
495  SCIP_FORK** fork, /**< pointer to fork data */
496  BMS_BLKMEM* blkmem, /**< block memory */
497  SCIP_SET* set, /**< global SCIP settings */
498  SCIP_PROB* prob, /**< transformed problem after presolve */
499  SCIP_TREE* tree, /**< branch and bound tree */
500  SCIP_LP* lp /**< current LP data */
501  )
502 {
503  assert(fork != NULL);
504  assert(blkmem != NULL);
505  assert(tree != NULL);
506  assert(tree->nchildren > 0);
507  assert(tree->nchildren < (1 << 30));
508  assert(SCIPtreeIsPathComplete(tree));
509  assert(tree->focusnode != NULL);
510  assert(lp != NULL);
511  assert(lp->flushed);
512  assert(lp->solved);
514 
515  SCIP_ALLOC( BMSallocBlockMemory(blkmem, fork) );
516 
517  SCIP_CALL( SCIPlpGetState(lp, blkmem, &((*fork)->lpistate)) );
518  (*fork)->lpwasprimfeas = lp->primalfeasible;
519  (*fork)->lpwasprimchecked = lp->primalchecked;
520  (*fork)->lpwasdualfeas = lp->dualfeasible;
521  (*fork)->lpwasdualchecked = lp->dualchecked;
522  (*fork)->lpobjval = SCIPlpGetObjval(lp, set, prob);
523  (*fork)->nlpistateref = 0;
524  (*fork)->addedcols = NULL;
525  (*fork)->addedrows = NULL;
526  (*fork)->naddedcols = SCIPlpGetNNewcols(lp);
527  (*fork)->naddedrows = SCIPlpGetNNewrows(lp);
528  (*fork)->nchildren = (unsigned int) tree->nchildren;
529 
530  SCIPsetDebugMsg(set, "creating fork information with %u children (%d new cols, %d new rows)\n", (*fork)->nchildren, (*fork)->naddedcols, (*fork)->naddedrows);
531 
532  if( (*fork)->naddedcols > 0 )
533  {
534  /* copy the newly created columns to the fork's col array */
535  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*fork)->addedcols, SCIPlpGetNewcols(lp), (*fork)->naddedcols) );
536  }
537  if( (*fork)->naddedrows > 0 )
538  {
539  int i;
540 
541  /* copy the newly created rows to the fork's row array */
542  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*fork)->addedrows, SCIPlpGetNewrows(lp), (*fork)->naddedrows) );
543 
544  /* capture the added rows */
545  for( i = 0; i < (*fork)->naddedrows; ++i )
546  SCIProwCapture((*fork)->addedrows[i]);
547  }
548 
549  /* capture the LPI state for the children */
550  forkCaptureLPIState(*fork, tree->nchildren);
551 
552  return SCIP_OKAY;
553 }
554 
555 /** frees fork data */
556 static
558  SCIP_FORK** fork, /**< fork data */
559  BMS_BLKMEM* blkmem, /**< block memory */
560  SCIP_SET* set, /**< global SCIP settings */
561  SCIP_LP* lp /**< current LP data */
562  )
563 {
564  int i;
565 
566  assert(fork != NULL);
567  assert(*fork != NULL);
568  assert((*fork)->nchildren == 0);
569  assert((*fork)->nlpistateref == 0);
570  assert((*fork)->lpistate == NULL);
571  assert(blkmem != NULL);
572  assert(set != NULL);
573  assert(lp != NULL);
574 
575  /* release the added rows */
576  for( i = (*fork)->naddedrows - 1; i >= 0; --i )
577  {
578  SCIP_CALL( SCIProwRelease(&(*fork)->addedrows[i], blkmem, set, lp) );
579  }
580 
581  BMSfreeBlockMemoryArrayNull(blkmem, &(*fork)->addedcols, (*fork)->naddedcols);
582  BMSfreeBlockMemoryArrayNull(blkmem, &(*fork)->addedrows, (*fork)->naddedrows);
583  BMSfreeBlockMemory(blkmem, fork);
584 
585  return SCIP_OKAY;
586 }
587 
588 #ifdef WITHSUBROOTS /** @todo test whether subroots should be created */
589 /** creates subroot data */
590 static
591 SCIP_RETCODE subrootCreate(
592  SCIP_SUBROOT** subroot, /**< pointer to subroot data */
593  BMS_BLKMEM* blkmem, /**< block memory */
594  SCIP_SET* set, /**< global SCIP settings */
595  SCIP_PROB* prob, /**< transformed problem after presolve */
596  SCIP_TREE* tree, /**< branch and bound tree */
597  SCIP_LP* lp /**< current LP data */
598  )
599 {
600  int i;
601 
602  assert(subroot != NULL);
603  assert(blkmem != NULL);
604  assert(tree != NULL);
605  assert(tree->nchildren > 0);
606  assert(SCIPtreeIsPathComplete(tree));
607  assert(tree->focusnode != NULL);
608  assert(lp != NULL);
609  assert(lp->flushed);
610  assert(lp->solved);
612 
613  SCIP_ALLOC( BMSallocBlockMemory(blkmem, subroot) );
614  (*subroot)->lpobjval = SCIPlpGetObjval(lp, set, prob);
615  (*subroot)->nlpistateref = 0;
616  (*subroot)->ncols = SCIPlpGetNCols(lp);
617  (*subroot)->nrows = SCIPlpGetNRows(lp);
618  (*subroot)->nchildren = (unsigned int) tree->nchildren;
619  SCIP_CALL( SCIPlpGetState(lp, blkmem, &((*subroot)->lpistate)) );
620  (*subroot)->lpwasprimfeas = lp->primalfeasible;
621  (*subroot)->lpwasprimchecked = lp->primalchecked;
622  (*subroot)->lpwasdualfeas = lp->dualfeasible;
623  (*subroot)->lpwasdualchecked = lp->dualchecked;
624 
625  if( (*subroot)->ncols != 0 )
626  {
627  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*subroot)->cols, SCIPlpGetCols(lp), (*subroot)->ncols) );
628  }
629  else
630  (*subroot)->cols = NULL;
631  if( (*subroot)->nrows != 0 )
632  {
633  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*subroot)->rows, SCIPlpGetRows(lp), (*subroot)->nrows) );
634  }
635  else
636  (*subroot)->rows = NULL;
637 
638  /* capture the rows of the subroot */
639  for( i = 0; i < (*subroot)->nrows; ++i )
640  SCIProwCapture((*subroot)->rows[i]);
641 
642  /* capture the LPI state for the children */
643  subrootCaptureLPIState(*subroot, tree->nchildren);
644 
645  return SCIP_OKAY;
646 }
647 #endif
648 
649 /** frees subroot */
650 static
652  SCIP_SUBROOT** subroot, /**< subroot data */
653  BMS_BLKMEM* blkmem, /**< block memory */
654  SCIP_SET* set, /**< global SCIP settings */
655  SCIP_LP* lp /**< current LP data */
656  )
657 {
658  int i;
659 
660  assert(subroot != NULL);
661  assert(*subroot != NULL);
662  assert((*subroot)->nchildren == 0);
663  assert((*subroot)->nlpistateref == 0);
664  assert((*subroot)->lpistate == NULL);
665  assert(blkmem != NULL);
666  assert(set != NULL);
667  assert(lp != NULL);
668 
669  /* release the rows of the subroot */
670  for( i = 0; i < (*subroot)->nrows; ++i )
671  {
672  SCIP_CALL( SCIProwRelease(&(*subroot)->rows[i], blkmem, set, lp) );
673  }
674 
675  BMSfreeBlockMemoryArrayNull(blkmem, &(*subroot)->cols, (*subroot)->ncols);
676  BMSfreeBlockMemoryArrayNull(blkmem, &(*subroot)->rows, (*subroot)->nrows);
677  BMSfreeBlockMemory(blkmem, subroot);
678 
679  return SCIP_OKAY;
680 }
681 
682 /** removes given sibling node from the siblings array */
683 static
685  SCIP_TREE* tree, /**< branch and bound tree */
686  SCIP_NODE* sibling /**< sibling node to remove */
687  )
688 {
689  int delpos;
690 
691  assert(tree != NULL);
692  assert(sibling != NULL);
693  assert(SCIPnodeGetType(sibling) == SCIP_NODETYPE_SIBLING);
694  assert(sibling->data.sibling.arraypos >= 0 && sibling->data.sibling.arraypos < tree->nsiblings);
695  assert(tree->siblings[sibling->data.sibling.arraypos] == sibling);
696  assert(SCIPnodeGetType(tree->siblings[tree->nsiblings-1]) == SCIP_NODETYPE_SIBLING);
697 
698  delpos = sibling->data.sibling.arraypos;
699 
700  /* move last sibling in array to position of removed sibling */
701  tree->siblings[delpos] = tree->siblings[tree->nsiblings-1];
702  tree->siblingsprio[delpos] = tree->siblingsprio[tree->nsiblings-1];
703  tree->siblings[delpos]->data.sibling.arraypos = delpos;
704  sibling->data.sibling.arraypos = -1;
705  tree->nsiblings--;
706 }
707 
708 /** adds given child node to children array of focus node */
709 static
711  SCIP_TREE* tree, /**< branch and bound tree */
712  SCIP_SET* set, /**< global SCIP settings */
713  SCIP_NODE* child, /**< child node to add */
714  SCIP_Real nodeselprio /**< node selection priority of child node */
715  )
716 {
717  assert(tree != NULL);
718  assert(child != NULL);
719  assert(SCIPnodeGetType(child) == SCIP_NODETYPE_CHILD);
720  assert(child->data.child.arraypos == -1);
721 
722  SCIP_CALL( treeEnsureChildrenMem(tree, set, tree->nchildren+1) );
723  tree->children[tree->nchildren] = child;
724  tree->childrenprio[tree->nchildren] = nodeselprio;
725  child->data.child.arraypos = tree->nchildren;
726  tree->nchildren++;
727 
728  return SCIP_OKAY;
729 }
730 
731 /** removes given child node from the children array */
732 static
734  SCIP_TREE* tree, /**< branch and bound tree */
735  SCIP_NODE* child /**< child node to remove */
736  )
737 {
738  int delpos;
739 
740  assert(tree != NULL);
741  assert(child != NULL);
742  assert(SCIPnodeGetType(child) == SCIP_NODETYPE_CHILD);
743  assert(child->data.child.arraypos >= 0 && child->data.child.arraypos < tree->nchildren);
744  assert(tree->children[child->data.child.arraypos] == child);
745  assert(SCIPnodeGetType(tree->children[tree->nchildren-1]) == SCIP_NODETYPE_CHILD);
746 
747  delpos = child->data.child.arraypos;
748 
749  /* move last child in array to position of removed child */
750  tree->children[delpos] = tree->children[tree->nchildren-1];
751  tree->childrenprio[delpos] = tree->childrenprio[tree->nchildren-1];
752  tree->children[delpos]->data.child.arraypos = delpos;
753  child->data.child.arraypos = -1;
754  tree->nchildren--;
755 }
756 
757 /** makes node a child of the given parent node, which must be the focus node; if the child is a probing node,
758  * the parent node can also be a refocused node or a probing node
759  */
760 static
762  SCIP_NODE* node, /**< child node */
763  BMS_BLKMEM* blkmem, /**< block memory buffers */
764  SCIP_SET* set, /**< global SCIP settings */
765  SCIP_TREE* tree, /**< branch and bound tree */
766  SCIP_NODE* parent, /**< parent (= focus) node (or NULL, if node is root) */
767  SCIP_Real nodeselprio /**< node selection priority of child node */
768  )
769 {
770  assert(node != NULL);
771  assert(node->parent == NULL);
773  assert(node->conssetchg == NULL);
774  assert(node->domchg == NULL);
775  assert(SCIPsetIsInfinity(set, -node->lowerbound)); /* node was just created */
776  assert(blkmem != NULL);
777  assert(set != NULL);
778  assert(tree != NULL);
779  assert(SCIPtreeIsPathComplete(tree));
780  assert(tree->pathlen == 0 || tree->path[tree->pathlen-1] == parent);
781  assert(parent == tree->focusnode || SCIPnodeGetType(parent) == SCIP_NODETYPE_PROBINGNODE);
782  assert(parent == NULL || SCIPnodeGetType(parent) == SCIP_NODETYPE_FOCUSNODE
786 
787  /* link node to parent */
788  node->parent = parent;
789  if( parent != NULL )
790  {
791  assert(parent->lowerbound <= parent->estimate);
792  node->lowerbound = parent->lowerbound;
793  node->estimate = parent->estimate;
794  node->depth = parent->depth+1; /*lint !e732*/
795  if( parent->depth >= SCIP_MAXTREEDEPTH )
796  {
797  SCIPerrorMessage("maximal depth level exceeded\n");
798  return SCIP_MAXDEPTHLEVEL;
799  }
800  }
801  SCIPsetDebugMsg(set, "assigning parent #%" SCIP_LONGINT_FORMAT " to node #%" SCIP_LONGINT_FORMAT " at depth %d\n",
802  parent != NULL ? SCIPnodeGetNumber(parent) : -1, SCIPnodeGetNumber(node), SCIPnodeGetDepth(node));
803 
804  /* register node in the childlist of the focus (the parent) node */
805  if( SCIPnodeGetType(node) == SCIP_NODETYPE_CHILD )
806  {
807  assert(parent == NULL || SCIPnodeGetType(parent) == SCIP_NODETYPE_FOCUSNODE);
808  SCIP_CALL( treeAddChild(tree, set, node, nodeselprio) );
809  }
810 
811  return SCIP_OKAY;
812 }
813 
814 /** decreases number of children of the parent, frees it if no children are left */
815 static
817  SCIP_NODE* node, /**< child node */
818  BMS_BLKMEM* blkmem, /**< block memory buffer */
819  SCIP_SET* set, /**< global SCIP settings */
820  SCIP_STAT* stat, /**< problem statistics */
821  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
822  SCIP_TREE* tree, /**< branch and bound tree */
823  SCIP_LP* lp /**< current LP data */
824  )
825 {
826  SCIP_NODE* parent;
827 
828  assert(node != NULL);
829  assert(blkmem != NULL);
830  assert(tree != NULL);
831 
832  SCIPsetDebugMsg(set, "releasing parent-child relationship of node #%" SCIP_LONGINT_FORMAT " at depth %d of type %d with parent #%" SCIP_LONGINT_FORMAT " of type %d\n",
834  node->parent != NULL ? SCIPnodeGetNumber(node->parent) : -1,
835  node->parent != NULL ? (int)SCIPnodeGetType(node->parent) : -1);
836  parent = node->parent;
837  if( parent != NULL )
838  {
839  SCIP_Bool freeParent;
840  SCIP_Bool singleChild;
841 
842  freeParent = FALSE;
843  singleChild = FALSE;
844  switch( SCIPnodeGetType(parent) )
845  {
847  assert(parent->active);
849  || SCIPnodeGetType(node) == SCIP_NODETYPE_LEAF);
850  if( SCIPnodeGetType(node) == SCIP_NODETYPE_CHILD )
851  treeRemoveChild(tree, node);
852  /* don't kill the focus node at this point => freeParent = FALSE */
853  break;
855  assert(SCIPtreeProbing(tree));
856  /* probing nodes have to be freed individually => freeParent = FALSE */
857  break;
859  SCIPerrorMessage("sibling cannot be a parent node\n");
860  return SCIP_INVALIDDATA;
861  case SCIP_NODETYPE_CHILD:
862  SCIPerrorMessage("child cannot be a parent node\n");
863  return SCIP_INVALIDDATA;
864  case SCIP_NODETYPE_LEAF:
865  SCIPerrorMessage("leaf cannot be a parent node\n");
866  return SCIP_INVALIDDATA;
868  SCIPerrorMessage("dead-end cannot be a parent node\n");
869  return SCIP_INVALIDDATA;
871  assert(parent->data.junction.nchildren > 0);
872  parent->data.junction.nchildren--;
873  freeParent = (parent->data.junction.nchildren == 0); /* free parent if it has no more children */
874  singleChild = (parent->data.junction.nchildren == 1);
875  break;
877  assert(parent->data.pseudofork != NULL);
878  assert(parent->data.pseudofork->nchildren > 0);
879  parent->data.pseudofork->nchildren--;
880  freeParent = (parent->data.pseudofork->nchildren == 0); /* free parent if it has no more children */
881  singleChild = (parent->data.pseudofork->nchildren == 1);
882  break;
883  case SCIP_NODETYPE_FORK:
884  assert(parent->data.fork != NULL);
885  assert(parent->data.fork->nchildren > 0);
886  parent->data.fork->nchildren--;
887  freeParent = (parent->data.fork->nchildren == 0); /* free parent if it has no more children */
888  singleChild = (parent->data.fork->nchildren == 1);
889  break;
891  assert(parent->data.subroot != NULL);
892  assert(parent->data.subroot->nchildren > 0);
893  parent->data.subroot->nchildren--;
894  freeParent = (parent->data.subroot->nchildren == 0); /* free parent if it has no more children */
895  singleChild = (parent->data.subroot->nchildren == 1);
896  break;
898  /* the only possible child a refocused node can have in its refocus state is the probing root node;
899  * we don't want to free the refocused node, because we first have to convert it back to its original
900  * type (where it possibly has children) => freeParent = FALSE
901  */
903  assert(!SCIPtreeProbing(tree));
904  break;
905  default:
906  SCIPerrorMessage("unknown node type %d\n", SCIPnodeGetType(parent));
907  return SCIP_INVALIDDATA;
908  }
909 
910  /* free parent, if it is not on the current active path */
911  if( freeParent && !parent->active )
912  {
913  SCIP_CALL( SCIPnodeFree(&node->parent, blkmem, set, stat, eventqueue, tree, lp) );
914  }
915 
916  /* update the effective root depth
917  * in reoptimization we must not increase the effective root depth
918  */
919  assert(tree->effectiverootdepth >= 0);
920  if( singleChild && SCIPnodeGetDepth(parent) == tree->effectiverootdepth && !set->reopt_enable )
921  {
922  tree->effectiverootdepth++;
923  SCIPsetDebugMsg(set, "unlinked node #%" SCIP_LONGINT_FORMAT " in depth %d -> new effective root depth: %d\n",
925  }
926  }
927 
928  return SCIP_OKAY;
929 }
930 
931 /** creates a node data structure */
932 static
934  SCIP_NODE** node, /**< pointer to node data structure */
935  BMS_BLKMEM* blkmem, /**< block memory */
936  SCIP_SET* set /**< global SCIP settings */
937  )
938 {
939  assert(node != NULL);
940 
941  SCIP_ALLOC( BMSallocBlockMemory(blkmem, node) );
942  (*node)->parent = NULL;
943  (*node)->conssetchg = NULL;
944  (*node)->domchg = NULL;
945  (*node)->number = 0;
946  (*node)->lowerbound = -SCIPsetInfinity(set);
947  (*node)->estimate = -SCIPsetInfinity(set);
948  (*node)->reoptid = 0;
949  (*node)->reopttype = (unsigned int) SCIP_REOPTTYPE_NONE;
950  (*node)->depth = 0;
951  (*node)->active = FALSE;
952  (*node)->cutoff = FALSE;
953  (*node)->reprop = FALSE;
954  (*node)->repropsubtreemark = 0;
955 
956  return SCIP_OKAY;
957 }
958 
959 /** creates a child node of the focus node */
961  SCIP_NODE** node, /**< pointer to node data structure */
962  BMS_BLKMEM* blkmem, /**< block memory */
963  SCIP_SET* set, /**< global SCIP settings */
964  SCIP_STAT* stat, /**< problem statistics */
965  SCIP_TREE* tree, /**< branch and bound tree */
966  SCIP_Real nodeselprio, /**< node selection priority of new node */
967  SCIP_Real estimate /**< estimate for (transformed) objective value of best feasible solution in subtree */
968  )
969 {
970  assert(node != NULL);
971  assert(blkmem != NULL);
972  assert(set != NULL);
973  assert(stat != NULL);
974  assert(tree != NULL);
975  assert(SCIPtreeIsPathComplete(tree));
976  assert(tree->pathlen == 0 || tree->path != NULL);
977  assert((tree->pathlen == 0) == (tree->focusnode == NULL));
978  assert(tree->focusnode == NULL || tree->focusnode == tree->path[tree->pathlen-1]);
979  assert(tree->focusnode == NULL || SCIPnodeGetType(tree->focusnode) == SCIP_NODETYPE_FOCUSNODE);
980 
981  stat->ncreatednodes++;
982  stat->ncreatednodesrun++;
983 
984  /* create the node data structure */
985  SCIP_CALL( nodeCreate(node, blkmem, set) );
986  (*node)->number = stat->ncreatednodesrun;
987 
988  /* mark node to be a child node */
989  (*node)->nodetype = SCIP_NODETYPE_CHILD; /*lint !e641*/
990  (*node)->data.child.arraypos = -1;
991 
992  /* make focus node the parent of the new child */
993  SCIP_CALL( nodeAssignParent(*node, blkmem, set, tree, tree->focusnode, nodeselprio) );
994 
995  /* update the estimate of the child */
996  SCIPnodeSetEstimate(*node, set, estimate);
997 
998  /* output node creation to visualization file */
999  SCIP_CALL( SCIPvisualNewChild(stat->visual, set, stat, *node) );
1000 
1001  SCIPsetDebugMsg(set, "created child node #%" SCIP_LONGINT_FORMAT " at depth %u (prio: %g)\n", SCIPnodeGetNumber(*node), (*node)->depth, nodeselprio);
1002 
1003  return SCIP_OKAY;
1004 }
1005 
1006 /** frees node */
1008  SCIP_NODE** node, /**< node data */
1009  BMS_BLKMEM* blkmem, /**< block memory buffer */
1010  SCIP_SET* set, /**< global SCIP settings */
1011  SCIP_STAT* stat, /**< problem statistics */
1012  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1013  SCIP_TREE* tree, /**< branch and bound tree */
1014  SCIP_LP* lp /**< current LP data */
1015  )
1016 {
1017  SCIP_Bool isroot;
1018 
1019  assert(node != NULL);
1020  assert(*node != NULL);
1021  assert(!(*node)->active);
1022  assert(blkmem != NULL);
1023  assert(tree != NULL);
1024 
1025  SCIPsetDebugMsg(set, "free node #%" SCIP_LONGINT_FORMAT " at depth %d of type %d\n", SCIPnodeGetNumber(*node), SCIPnodeGetDepth(*node), SCIPnodeGetType(*node));
1026 
1027  /* inform solution debugger, that the node has been freed */
1028  assert( stat->inrestart || SCIPdebugRemoveNode(blkmem, set, *node) ); /*lint !e506 !e774*/
1029 
1030  /* check, if the node to be freed is the root node */
1031  isroot = (SCIPnodeGetDepth(*node) == 0);
1032 
1033  /* free nodetype specific data, and release no longer needed LPI states */
1034  switch( SCIPnodeGetType(*node) )
1035  {
1037  assert(tree->focusnode == *node);
1038  assert(!SCIPtreeProbing(tree));
1039  SCIPerrorMessage("cannot free focus node - has to be converted into a dead end first\n");
1040  return SCIP_INVALIDDATA;
1042  assert(SCIPtreeProbing(tree));
1043  assert(SCIPnodeGetDepth(tree->probingroot) <= SCIPnodeGetDepth(*node));
1044  assert(SCIPnodeGetDepth(*node) > 0);
1045  SCIP_CALL( probingnodeFree(&((*node)->data.probingnode), blkmem, lp) );
1046  break;
1047  case SCIP_NODETYPE_SIBLING:
1048  assert((*node)->data.sibling.arraypos >= 0);
1049  assert((*node)->data.sibling.arraypos < tree->nsiblings);
1050  assert(tree->siblings[(*node)->data.sibling.arraypos] == *node);
1051  if( tree->focuslpstatefork != NULL )
1052  {
1055  SCIP_CALL( SCIPnodeReleaseLPIState(tree->focuslpstatefork, blkmem, lp) );
1056  }
1057  treeRemoveSibling(tree, *node);
1058  break;
1059  case SCIP_NODETYPE_CHILD:
1060  assert((*node)->data.child.arraypos >= 0);
1061  assert((*node)->data.child.arraypos < tree->nchildren);
1062  assert(tree->children[(*node)->data.child.arraypos] == *node);
1063  /* The children capture the LPI state at the moment, where the focus node is
1064  * converted into a junction, pseudofork, fork, or subroot, and a new node is focused.
1065  * At the same time, they become siblings or leaves, such that freeing a child
1066  * of the focus node doesn't require to release the LPI state;
1067  * we don't need to call treeRemoveChild(), because this is done in nodeReleaseParent()
1068  */
1069  break;
1070  case SCIP_NODETYPE_LEAF:
1071  if( (*node)->data.leaf.lpstatefork != NULL )
1072  {
1073  SCIP_CALL( SCIPnodeReleaseLPIState((*node)->data.leaf.lpstatefork, blkmem, lp) );
1074  }
1075  break;
1076  case SCIP_NODETYPE_DEADEND:
1078  break;
1080  SCIP_CALL( pseudoforkFree(&((*node)->data.pseudofork), blkmem, set, lp) );
1081  break;
1082  case SCIP_NODETYPE_FORK:
1083 
1084  /* release special root LPI state capture which is used to keep the root LPI state over the whole solving
1085  * process
1086  */
1087  if( isroot )
1088  {
1089  SCIP_CALL( SCIPnodeReleaseLPIState(*node, blkmem, lp) );
1090  }
1091  SCIP_CALL( forkFree(&((*node)->data.fork), blkmem, set, lp) );
1092  break;
1093  case SCIP_NODETYPE_SUBROOT:
1094  SCIP_CALL( subrootFree(&((*node)->data.subroot), blkmem, set, lp) );
1095  break;
1097  SCIPerrorMessage("cannot free node as long it is refocused\n");
1098  return SCIP_INVALIDDATA;
1099  default:
1100  SCIPerrorMessage("unknown node type %d\n", SCIPnodeGetType(*node));
1101  return SCIP_INVALIDDATA;
1102  }
1103 
1104  /* free common data */
1105  SCIP_CALL( SCIPconssetchgFree(&(*node)->conssetchg, blkmem, set) );
1106  SCIP_CALL( SCIPdomchgFree(&(*node)->domchg, blkmem, set, eventqueue, lp) );
1107  SCIP_CALL( nodeReleaseParent(*node, blkmem, set, stat, eventqueue, tree, lp) );
1108 
1109  /* check, if the node is the current probing root */
1110  if( *node == tree->probingroot )
1111  {
1112  assert(SCIPnodeGetType(*node) == SCIP_NODETYPE_PROBINGNODE);
1113  tree->probingroot = NULL;
1114  }
1115 
1116  BMSfreeBlockMemory(blkmem, node);
1117 
1118  /* delete the tree's root node pointer, if the freed node was the root */
1119  if( isroot )
1120  tree->root = NULL;
1121 
1122  return SCIP_OKAY;
1123 }
1124 
1125 /** cuts off node and whole sub tree from branch and bound tree */
1127  SCIP_NODE* node, /**< node that should be cut off */
1128  SCIP_SET* set, /**< global SCIP settings */
1129  SCIP_STAT* stat, /**< problem statistics */
1130  SCIP_TREE* tree, /**< branch and bound tree */
1131  SCIP_PROB* transprob, /**< transformed problem after presolve */
1132  SCIP_PROB* origprob, /**< original problem */
1133  SCIP_REOPT* reopt, /**< reoptimization data structure */
1134  SCIP_LP* lp, /**< current LP */
1135  BMS_BLKMEM* blkmem /**< block memory */
1136  )
1137 {
1138  SCIP_Real oldbound;
1139 
1140  assert(node != NULL);
1141  assert(set != NULL);
1142  assert(stat != NULL);
1143  assert(tree != NULL);
1144 
1145  if( set->reopt_enable )
1146  {
1147  assert(reopt != NULL);
1148  /* check if the node should be stored for reoptimization */
1150  tree->root == node, tree->focusnode == node, node->lowerbound, tree->effectiverootdepth) );
1151  }
1152 
1153  oldbound = node->lowerbound;
1154  node->cutoff = TRUE;
1155  node->lowerbound = SCIPsetInfinity(set);
1156  node->estimate = SCIPsetInfinity(set);
1157  if( node->active )
1158  tree->cutoffdepth = MIN(tree->cutoffdepth, (int)node->depth);
1159 
1160  /* update primal integral */
1161  if( node->depth == 0 )
1162  {
1163  stat->rootlowerbound = SCIPsetInfinity(set);
1164  if( set->misc_calcintegral )
1165  SCIPstatUpdatePrimalDualIntegral(stat, set, transprob, origprob, SCIPsetInfinity(set), SCIPsetInfinity(set));
1166  }
1167  else if( set->misc_calcintegral && SCIPsetIsEQ(set, oldbound, stat->lastlowerbound) )
1168  {
1169  SCIP_Real lowerbound;
1170  lowerbound = SCIPtreeGetLowerbound(tree, set);
1171 
1172  /* updating the primal integral is only necessary if dual bound has increased since last evaluation */
1173  if( lowerbound > stat->lastlowerbound )
1174  SCIPstatUpdatePrimalDualIntegral(stat, set, transprob, origprob, SCIPsetInfinity(set), SCIPsetInfinity(set));
1175  }
1176 
1177  SCIPvisualCutoffNode(stat->visual, set, stat, node, TRUE);
1178 
1179  SCIPsetDebugMsg(set, "cutting off %s node #%" SCIP_LONGINT_FORMAT " at depth %d (cutoffdepth: %d)\n",
1180  node->active ? "active" : "inactive", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), tree->cutoffdepth);
1181 
1182  return SCIP_OKAY;
1183 }
1184 
1185 /** marks node, that propagation should be applied again the next time, a node of its subtree is focused */
1187  SCIP_NODE* node, /**< node that should be propagated again */
1188  SCIP_SET* set, /**< global SCIP settings */
1189  SCIP_STAT* stat, /**< problem statistics */
1190  SCIP_TREE* tree /**< branch and bound tree */
1191  )
1192 {
1193  assert(node != NULL);
1194  assert(set != NULL);
1195  assert(stat != NULL);
1196  assert(tree != NULL);
1197 
1198  if( !node->reprop )
1199  {
1200  node->reprop = TRUE;
1201  if( node->active )
1202  tree->repropdepth = MIN(tree->repropdepth, (int)node->depth);
1203 
1204  SCIPvisualMarkedRepropagateNode(stat->visual, stat, node);
1205 
1206  SCIPsetDebugMsg(set, "marked %s node #%" SCIP_LONGINT_FORMAT " at depth %d to be propagated again (repropdepth: %d)\n",
1207  node->active ? "active" : "inactive", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), tree->repropdepth);
1208  }
1209 }
1210 
1211 /** marks node, that it is completely propagated in the current repropagation subtree level */
1213  SCIP_NODE* node, /**< node that should be marked to be propagated */
1214  SCIP_TREE* tree /**< branch and bound tree */
1215  )
1216 {
1217  assert(node != NULL);
1218  assert(tree != NULL);
1219 
1220  if( node->parent != NULL )
1221  node->repropsubtreemark = node->parent->repropsubtreemark; /*lint !e732*/
1222  node->reprop = FALSE;
1223 
1224  /* if the node was the highest repropagation node in the path, update the repropdepth in the tree data */
1225  if( node->active && node->depth == tree->repropdepth )
1226  {
1227  do
1228  {
1229  assert(tree->repropdepth < tree->pathlen);
1230  assert(tree->path[tree->repropdepth]->active);
1231  assert(!tree->path[tree->repropdepth]->reprop);
1232  tree->repropdepth++;
1233  }
1234  while( tree->repropdepth < tree->pathlen && !tree->path[tree->repropdepth]->reprop );
1235  if( tree->repropdepth == tree->pathlen )
1236  tree->repropdepth = INT_MAX;
1237  }
1238 }
1239 
1240 /** moves the subtree repropagation counter to the next value */
1241 static
1243  SCIP_TREE* tree /**< branch and bound tree */
1244  )
1245 {
1246  assert(tree != NULL);
1247 
1248  tree->repropsubtreecount++;
1249  tree->repropsubtreecount %= (MAXREPROPMARK+1);
1250 }
1251 
1252 /** applies propagation on the node, that was marked to be propagated again */
1253 static
1255  SCIP_NODE* node, /**< node to apply propagation on */
1256  BMS_BLKMEM* blkmem, /**< block memory buffers */
1257  SCIP_SET* set, /**< global SCIP settings */
1258  SCIP_STAT* stat, /**< dynamic problem statistics */
1259  SCIP_PROB* transprob, /**< transformed problem */
1260  SCIP_PROB* origprob, /**< original problem */
1261  SCIP_PRIMAL* primal, /**< primal data */
1262  SCIP_TREE* tree, /**< branch and bound tree */
1263  SCIP_REOPT* reopt, /**< reoptimization data structure */
1264  SCIP_LP* lp, /**< current LP data */
1265  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1266  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1267  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1268  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1269  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1270  SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
1271  )
1272 {
1273  SCIP_NODETYPE oldtype;
1274  SCIP_NODE* oldfocusnode;
1275  SCIP_NODE* oldfocuslpfork;
1276  SCIP_NODE* oldfocuslpstatefork;
1277  SCIP_NODE* oldfocussubroot;
1278  SCIP_Longint oldfocuslpstateforklpcount;
1279  int oldnchildren;
1280  int oldnsiblings;
1281  SCIP_Bool oldfocusnodehaslp;
1282  SCIP_Longint oldnboundchgs;
1283  SCIP_Bool initialreprop;
1284  SCIP_Bool clockisrunning;
1285 
1286  assert(node != NULL);
1292  assert(node->active);
1293  assert(node->reprop || node->repropsubtreemark != node->parent->repropsubtreemark);
1294  assert(stat != NULL);
1295  assert(tree != NULL);
1296  assert(SCIPeventqueueIsDelayed(eventqueue));
1297  assert(cutoff != NULL);
1298 
1299  SCIPsetDebugMsg(set, "propagating again node #%" SCIP_LONGINT_FORMAT " at depth %d\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node));
1300  initialreprop = node->reprop;
1301 
1302  SCIPvisualRepropagatedNode(stat->visual, stat, node);
1303 
1304  /* process the delayed events in order to flush the problem changes */
1305  SCIP_CALL( SCIPeventqueueProcess(eventqueue, blkmem, set, primal, lp, branchcand, eventfilter) );
1306 
1307  /* stop node activation timer */
1308  clockisrunning = SCIPclockIsRunning(stat->nodeactivationtime);
1309  if( clockisrunning )
1310  SCIPclockStop(stat->nodeactivationtime, set);
1311 
1312  /* mark the node refocused and temporarily install it as focus node */
1313  oldtype = (SCIP_NODETYPE)node->nodetype;
1314  oldfocusnode = tree->focusnode;
1315  oldfocuslpfork = tree->focuslpfork;
1316  oldfocuslpstatefork = tree->focuslpstatefork;
1317  oldfocussubroot = tree->focussubroot;
1318  oldfocuslpstateforklpcount = tree->focuslpstateforklpcount;
1319  oldnchildren = tree->nchildren;
1320  oldnsiblings = tree->nsiblings;
1321  oldfocusnodehaslp = tree->focusnodehaslp;
1322  node->nodetype = SCIP_NODETYPE_REFOCUSNODE; /*lint !e641*/
1323  tree->focusnode = node;
1324  tree->focuslpfork = NULL;
1325  tree->focuslpstatefork = NULL;
1326  tree->focussubroot = NULL;
1327  tree->focuslpstateforklpcount = -1;
1328  tree->nchildren = 0;
1329  tree->nsiblings = 0;
1330  tree->focusnodehaslp = FALSE;
1331 
1332  /* propagate the domains again */
1333  oldnboundchgs = stat->nboundchgs;
1334  SCIP_CALL( SCIPpropagateDomains(blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
1335  eventqueue, conflict, cliquetable, SCIPnodeGetDepth(node), 0, SCIP_PROPTIMING_ALWAYS, cutoff) );
1336  assert(!node->reprop || *cutoff);
1337  assert(node->parent == NULL || node->repropsubtreemark == node->parent->repropsubtreemark);
1339  assert(tree->focusnode == node);
1340  assert(tree->focuslpfork == NULL);
1341  assert(tree->focuslpstatefork == NULL);
1342  assert(tree->focussubroot == NULL);
1343  assert(tree->focuslpstateforklpcount == -1);
1344  assert(tree->nchildren == 0);
1345  assert(tree->nsiblings == 0);
1346  assert(tree->focusnodehaslp == FALSE);
1347  assert(stat->nboundchgs >= oldnboundchgs);
1348  stat->nreprops++;
1349  stat->nrepropboundchgs += stat->nboundchgs - oldnboundchgs;
1350  if( *cutoff )
1351  stat->nrepropcutoffs++;
1352 
1353  SCIPsetDebugMsg(set, "repropagation %" SCIP_LONGINT_FORMAT " at depth %u changed %" SCIP_LONGINT_FORMAT " bounds (total reprop bound changes: %" SCIP_LONGINT_FORMAT "), cutoff: %u\n",
1354  stat->nreprops, node->depth, stat->nboundchgs - oldnboundchgs, stat->nrepropboundchgs, *cutoff);
1355 
1356  /* if a propagation marked with the reprop flag was successful, we want to repropagate the whole subtree */
1357  /**@todo because repropsubtree is only a bit flag, we cannot mark a whole subtree a second time for
1358  * repropagation; use a (small) part of the node's bits to be able to store larger numbers,
1359  * and update tree->repropsubtreelevel with this number
1360  */
1361  if( initialreprop && !(*cutoff) && stat->nboundchgs > oldnboundchgs )
1362  {
1364  node->repropsubtreemark = tree->repropsubtreecount; /*lint !e732*/
1365  SCIPsetDebugMsg(set, "initial repropagation at depth %u changed %" SCIP_LONGINT_FORMAT " bounds -> repropagating subtree (new mark: %d)\n",
1366  node->depth, stat->nboundchgs - oldnboundchgs, tree->repropsubtreecount);
1367  assert((int)(node->repropsubtreemark) == tree->repropsubtreecount); /* bitfield must be large enough */
1368  }
1369 
1370  /* reset the node's type and reinstall the old focus node */
1371  node->nodetype = oldtype; /*lint !e641*/
1372  tree->focusnode = oldfocusnode;
1373  tree->focuslpfork = oldfocuslpfork;
1374  tree->focuslpstatefork = oldfocuslpstatefork;
1375  tree->focussubroot = oldfocussubroot;
1376  tree->focuslpstateforklpcount = oldfocuslpstateforklpcount;
1377  tree->nchildren = oldnchildren;
1378  tree->nsiblings = oldnsiblings;
1379  tree->focusnodehaslp = oldfocusnodehaslp;
1380 
1381  /* make the domain change data static again to save memory */
1383  {
1384  SCIP_CALL( SCIPdomchgMakeStatic(&node->domchg, blkmem, set, eventqueue, lp) );
1385  }
1386 
1387  /* start node activation timer again */
1388  if( clockisrunning )
1389  SCIPclockStart(stat->nodeactivationtime, set);
1390 
1391  /* delay events in path switching */
1392  SCIP_CALL( SCIPeventqueueDelay(eventqueue) );
1393 
1394  /* mark the node to be cut off if a cutoff was detected */
1395  if( *cutoff )
1396  {
1397  SCIP_CALL( SCIPnodeCutoff(node, set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
1398  }
1399 
1400  return SCIP_OKAY;
1401 }
1402 
1403 /** informs node, that it is now on the active path and applies any domain and constraint set changes */
1404 static
1406  SCIP_NODE* node, /**< node to activate */
1407  BMS_BLKMEM* blkmem, /**< block memory buffers */
1408  SCIP_SET* set, /**< global SCIP settings */
1409  SCIP_STAT* stat, /**< problem statistics */
1410  SCIP_PROB* transprob, /**< transformed problem */
1411  SCIP_PROB* origprob, /**< original problem */
1412  SCIP_PRIMAL* primal, /**< primal data */
1413  SCIP_TREE* tree, /**< branch and bound tree */
1414  SCIP_REOPT* reopt, /**< reotimization data structure */
1415  SCIP_LP* lp, /**< current LP data */
1416  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1417  SCIP_CONFLICT* conflict, /**< conflict analysis data */
1418  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1419  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1420  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1421  SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
1422  )
1423 {
1424  assert(node != NULL);
1425  assert(!node->active);
1426  assert(stat != NULL);
1427  assert(tree != NULL);
1428  assert(!SCIPtreeProbing(tree));
1429  assert(cutoff != NULL);
1430 
1431  SCIPsetDebugMsg(set, "activate node #%" SCIP_LONGINT_FORMAT " at depth %d of type %d (reprop subtree mark: %u)\n",
1433 
1434  /* apply domain and constraint set changes */
1435  SCIP_CALL( SCIPconssetchgApply(node->conssetchg, blkmem, set, stat, node->depth,
1437  SCIP_CALL( SCIPdomchgApply(node->domchg, blkmem, set, stat, lp, branchcand, eventqueue, node->depth, cutoff) );
1438 
1439  /* mark node active */
1440  node->active = TRUE;
1441  stat->nactivatednodes++;
1442 
1443  /* check if the domain change produced a cutoff */
1444  if( *cutoff )
1445  {
1446  /* try to repropagate the node to see, if the propagation also leads to a conflict and a conflict constraint
1447  * could be generated; if propagation conflict analysis is turned off, repropagating the node makes no
1448  * sense, since it is already cut off
1449  */
1450  node->reprop = set->conf_enable && set->conf_useprop;
1451 
1452  /* mark the node to be cut off */
1453  SCIP_CALL( SCIPnodeCutoff(node, set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
1454  }
1455 
1456  /* propagate node again, if the reprop flag is set; in the new focus node, no repropagation is necessary, because
1457  * the focus node is propagated anyways
1458  */
1460  && (node->reprop || (node->parent != NULL && node->repropsubtreemark != node->parent->repropsubtreemark)) )
1461  {
1462  SCIP_Bool propcutoff;
1463 
1464  SCIP_CALL( nodeRepropagate(node, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, conflict,
1465  eventfilter, eventqueue, cliquetable, &propcutoff) );
1466  *cutoff = *cutoff || propcutoff;
1467  }
1468 
1469  return SCIP_OKAY;
1470 }
1471 
1472 /** informs node, that it is no longer on the active path and undoes any domain and constraint set changes */
1473 static
1475  SCIP_NODE* node, /**< node to deactivate */
1476  BMS_BLKMEM* blkmem, /**< block memory buffers */
1477  SCIP_SET* set, /**< global SCIP settings */
1478  SCIP_STAT* stat, /**< problem statistics */
1479  SCIP_TREE* tree, /**< branch and bound tree */
1480  SCIP_LP* lp, /**< current LP data */
1481  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1482  SCIP_EVENTQUEUE* eventqueue /**< event queue */
1483  )
1484 {
1485  SCIP_Bool freeNode;
1486 
1487  assert(node != NULL);
1488  assert(node->active);
1489  assert(tree != NULL);
1490  assert(SCIPnodeGetType(node) != SCIP_NODETYPE_FOCUSNODE);
1491 
1492  SCIPsetDebugMsg(set, "deactivate node #%" SCIP_LONGINT_FORMAT " at depth %d of type %d (reprop subtree mark: %u)\n",
1494 
1495  /* undo domain and constraint set changes */
1496  SCIP_CALL( SCIPdomchgUndo(node->domchg, blkmem, set, stat, lp, branchcand, eventqueue) );
1497  SCIP_CALL( SCIPconssetchgUndo(node->conssetchg, blkmem, set, stat) );
1498 
1499  /* mark node inactive */
1500  node->active = FALSE;
1501 
1502  /* count number of deactivated nodes (ignoring probing switches) */
1503  if( !SCIPtreeProbing(tree) )
1504  stat->ndeactivatednodes++;
1505 
1506  /* free node if it is a dead-end node, i.e., has no children */
1507  switch( SCIPnodeGetType(node) )
1508  {
1511  case SCIP_NODETYPE_SIBLING:
1512  case SCIP_NODETYPE_CHILD:
1513  case SCIP_NODETYPE_LEAF:
1514  case SCIP_NODETYPE_DEADEND:
1516  freeNode = FALSE;
1517  break;
1519  freeNode = (node->data.junction.nchildren == 0);
1520  break;
1522  freeNode = (node->data.pseudofork->nchildren == 0);
1523  break;
1524  case SCIP_NODETYPE_FORK:
1525  freeNode = (node->data.fork->nchildren == 0);
1526  break;
1527  case SCIP_NODETYPE_SUBROOT:
1528  freeNode = (node->data.subroot->nchildren == 0);
1529  break;
1530  default:
1531  SCIPerrorMessage("unknown node type %d\n", SCIPnodeGetType(node));
1532  return SCIP_INVALIDDATA;
1533  }
1534  if( freeNode )
1535  {
1536  SCIP_CALL( SCIPnodeFree(&node, blkmem, set, stat, eventqueue, tree, lp) );
1537  }
1538 
1539  return SCIP_OKAY;
1540 }
1541 
1542 /** adds constraint locally to the node and captures it; activates constraint, if node is active;
1543  * if a local constraint is added to the root node, it is automatically upgraded into a global constraint
1544  */
1546  SCIP_NODE* node, /**< node to add constraint to */
1547  BMS_BLKMEM* blkmem, /**< block memory */
1548  SCIP_SET* set, /**< global SCIP settings */
1549  SCIP_STAT* stat, /**< problem statistics */
1550  SCIP_TREE* tree, /**< branch and bound tree */
1551  SCIP_CONS* cons /**< constraint to add */
1552  )
1553 {
1554  assert(node != NULL);
1555  assert(cons != NULL);
1556  assert(cons->validdepth <= SCIPnodeGetDepth(node));
1557  assert(tree != NULL);
1558  assert(tree->effectiverootdepth >= 0);
1559  assert(tree->root != NULL);
1560  assert(SCIPconsIsGlobal(cons) || SCIPnodeGetDepth(node) > tree->effectiverootdepth);
1561 
1562 #ifndef NDEBUG
1563  /* check if we add this constraint to the same scip, where we create the constraint */
1564  if( cons->scip != set->scip )
1565  {
1566  SCIPerrorMessage("try to add a constraint of another scip instance\n");
1567  return SCIP_INVALIDDATA;
1568  }
1569 #endif
1570 
1571  /* add constraint addition to the node's constraint set change data, and activate constraint if node is active */
1572  SCIP_CALL( SCIPconssetchgAddAddedCons(&node->conssetchg, blkmem, set, stat, cons, node->depth,
1573  (SCIPnodeGetType(node) == SCIP_NODETYPE_FOCUSNODE), node->active) );
1574  assert(node->conssetchg != NULL);
1575  assert(node->conssetchg->addedconss != NULL);
1576  assert(!node->active || SCIPconsIsActive(cons));
1577 
1578  /* if the constraint is added to an active node which is not a probing node, increment the corresponding counter */
1579  if( node->active && SCIPnodeGetType(node) != SCIP_NODETYPE_PROBINGNODE )
1580  stat->nactiveconssadded++;
1581 
1582  return SCIP_OKAY;
1583 }
1584 
1585 /** locally deletes constraint at the given node by disabling its separation, enforcing, and propagation capabilities
1586  * at the node; captures constraint; disables constraint, if node is active
1587  */
1589  SCIP_NODE* node, /**< node to add constraint to */
1590  BMS_BLKMEM* blkmem, /**< block memory */
1591  SCIP_SET* set, /**< global SCIP settings */
1592  SCIP_STAT* stat, /**< problem statistics */
1593  SCIP_TREE* tree, /**< branch and bound tree */
1594  SCIP_CONS* cons /**< constraint to locally delete */
1595  )
1596 {
1597  assert(node != NULL);
1598  assert(tree != NULL);
1599  assert(cons != NULL);
1600 
1601  SCIPsetDebugMsg(set, "disabling constraint <%s> at node at depth %u\n", cons->name, node->depth);
1602 
1603  /* add constraint disabling to the node's constraint set change data */
1604  SCIP_CALL( SCIPconssetchgAddDisabledCons(&node->conssetchg, blkmem, set, cons) );
1605  assert(node->conssetchg != NULL);
1606  assert(node->conssetchg->disabledconss != NULL);
1607 
1608  /* disable constraint, if node is active */
1609  if( node->active && cons->enabled && !cons->updatedisable )
1610  {
1611  SCIP_CALL( SCIPconsDisable(cons, set, stat) );
1612  }
1613 
1614  return SCIP_OKAY;
1615 }
1616 
1617 /** returns all constraints added to a given node */
1619  SCIP_NODE* node, /**< node */
1620  SCIP_CONS** addedconss, /**< array to store the constraints */
1621  int* naddedconss, /**< number of added constraints */
1622  int addedconsssize /**< size of the constraint array */
1623  )
1624 {
1625  int cons;
1626 
1627  assert(node != NULL );
1628  assert(node->conssetchg != NULL);
1629  assert(node->conssetchg->addedconss != NULL);
1630  assert(node->conssetchg->naddedconss >= 1);
1631 
1632  *naddedconss = node->conssetchg->naddedconss;
1633 
1634  /* check the size and return if the array is not large enough */
1635  if( addedconsssize < *naddedconss )
1636  return;
1637 
1638  /* fill the array */
1639  for( cons = 0; cons < *naddedconss; cons++ )
1640  {
1641  addedconss[cons] = node->conssetchg->addedconss[cons];
1642  }
1643 
1644  return;
1645 }
1646 
1647 /** returns the number of added constraints to the given node */
1649  SCIP_NODE* node /**< node */
1650  )
1651 {
1652  assert(node != NULL);
1653 
1654  if( node->conssetchg == NULL )
1655  return 0;
1656  else
1657  return node->conssetchg->naddedconss;
1658 }
1659 
1660 /** adds the given bound change to the list of pending bound changes */
1661 static
1663  SCIP_TREE* tree, /**< branch and bound tree */
1664  SCIP_SET* set, /**< global SCIP settings */
1665  SCIP_NODE* node, /**< node to add bound change to */
1666  SCIP_VAR* var, /**< variable to change the bounds for */
1667  SCIP_Real newbound, /**< new value for bound */
1668  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
1669  SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1670  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1671  int inferinfo, /**< user information for inference to help resolving the conflict */
1672  SCIP_Bool probingchange /**< is the bound change a temporary setting due to probing? */
1673  )
1674 {
1675  assert(tree != NULL);
1676 
1677  /* make sure that enough memory is allocated for the pendingbdchgs array */
1678  SCIP_CALL( treeEnsurePendingbdchgsMem(tree, set, tree->npendingbdchgs+1) );
1679 
1680  /* capture the variable */
1681  SCIPvarCapture(var);
1682 
1683  /* add the bound change to the pending list */
1684  tree->pendingbdchgs[tree->npendingbdchgs].node = node;
1685  tree->pendingbdchgs[tree->npendingbdchgs].var = var;
1686  tree->pendingbdchgs[tree->npendingbdchgs].newbound = newbound;
1687  tree->pendingbdchgs[tree->npendingbdchgs].boundtype = boundtype;
1688  tree->pendingbdchgs[tree->npendingbdchgs].infercons = infercons;
1689  tree->pendingbdchgs[tree->npendingbdchgs].inferprop = inferprop;
1690  tree->pendingbdchgs[tree->npendingbdchgs].inferinfo = inferinfo;
1691  tree->pendingbdchgs[tree->npendingbdchgs].probingchange = probingchange;
1692  tree->npendingbdchgs++;
1693 
1694  /* check global pending boundchanges against debug solution */
1695  if( node->depth == 0 )
1696  {
1697 #ifndef NDEBUG
1698  SCIP_Real bound = newbound;
1699 
1700  /* get bound adjusted for integrality(, this should already be done) */
1701  SCIPvarAdjustBd(var, set, boundtype, &bound);
1702 
1703  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1704  {
1705  /* check that the bound is feasible */
1706  if( bound > SCIPvarGetUbGlobal(var) )
1707  {
1708  /* due to numerics we only want to be feasible in feasibility tolerance */
1709  assert(SCIPsetIsFeasLE(set, bound, SCIPvarGetUbGlobal(var)));
1710  bound = SCIPvarGetUbGlobal(var);
1711  }
1712  }
1713  else
1714  {
1715  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
1716 
1717  /* check that the bound is feasible */
1718  if( bound < SCIPvarGetLbGlobal(var) )
1719  {
1720  /* due to numerics we only want to be feasible in feasibility tolerance */
1721  assert(SCIPsetIsFeasGE(set, bound, SCIPvarGetLbGlobal(var)));
1722  bound = SCIPvarGetLbGlobal(var);
1723  }
1724  }
1725  /* check that the given bound was already adjusted for integrality */
1726  assert(SCIPsetIsEQ(set, newbound, bound));
1727 #endif
1728  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1729  {
1730  /* check bound on debugging solution */
1731  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
1732  }
1733  else
1734  {
1735  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
1736 
1737  /* check bound on debugging solution */
1738  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
1739  }
1740  }
1741 
1742  return SCIP_OKAY;
1743 }
1744 
1745 /** adds bound change with inference information to focus node, child of focus node, or probing node;
1746  * if possible, adjusts bound to integral value;
1747  * at most one of infercons and inferprop may be non-NULL
1748  */
1750  SCIP_NODE* node, /**< node to add bound change to */
1751  BMS_BLKMEM* blkmem, /**< block memory */
1752  SCIP_SET* set, /**< global SCIP settings */
1753  SCIP_STAT* stat, /**< problem statistics */
1754  SCIP_PROB* transprob, /**< transformed problem after presolve */
1755  SCIP_PROB* origprob, /**< original problem */
1756  SCIP_TREE* tree, /**< branch and bound tree */
1757  SCIP_REOPT* reopt, /**< reoptimization data structure */
1758  SCIP_LP* lp, /**< current LP data */
1759  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1760  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1761  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1762  SCIP_VAR* var, /**< variable to change the bounds for */
1763  SCIP_Real newbound, /**< new value for bound */
1764  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
1765  SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1766  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1767  int inferinfo, /**< user information for inference to help resolving the conflict */
1768  SCIP_Bool probingchange /**< is the bound change a temporary setting due to probing? */
1769  )
1770 {
1771  SCIP_VAR* infervar;
1772  SCIP_BOUNDTYPE inferboundtype;
1773  SCIP_Real oldlb;
1774  SCIP_Real oldub;
1775  SCIP_Real oldbound;
1776 
1777  assert(node != NULL);
1782  || node->depth == 0);
1783  assert(set != NULL);
1784  assert(tree != NULL);
1785  assert(tree->effectiverootdepth >= 0);
1786  assert(tree->root != NULL);
1787  assert(var != NULL);
1788  assert(node->active || (infercons == NULL && inferprop == NULL));
1789  assert((SCIP_NODETYPE)node->nodetype == SCIP_NODETYPE_PROBINGNODE || !probingchange);
1790 
1791  SCIPsetDebugMsg(set, "adding boundchange at node %llu at depth %u to variable <%s>: old bounds=[%g,%g], new %s bound: %g (infer%s=<%s>, inferinfo=%d)\n",
1792  node->number, node->depth, SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
1793  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", newbound, infercons != NULL ? "cons" : "prop",
1794  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo);
1795 
1796  /* remember variable as inference variable, and get corresponding active variable, bound and bound type */
1797  infervar = var;
1798  inferboundtype = boundtype;
1799 
1800  SCIP_CALL( SCIPvarGetProbvarBound(&var, &newbound, &boundtype) );
1801 
1803  {
1804  SCIPerrorMessage("cannot change bounds of multi-aggregated variable <%s>\n", SCIPvarGetName(var));
1805  SCIPABORT();
1806  return SCIP_INVALIDDATA; /*lint !e527*/
1807  }
1809 
1810  if( (int) node->depth <= tree->effectiverootdepth )
1811  {
1812  oldlb = SCIPvarGetLbGlobal(var);
1813  oldub = SCIPvarGetUbGlobal(var);
1814  }
1815  else
1816  {
1817  oldlb = SCIPvarGetLbLocal(var);
1818  oldub = SCIPvarGetUbLocal(var);
1819  }
1820  assert(SCIPsetIsLE(set, oldlb, oldub));
1821 
1822  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1823  {
1824  /* adjust lower bound w.r.t. to integrality */
1825  SCIPvarAdjustLb(var, set, &newbound);
1826  assert(SCIPsetIsGT(set, newbound, oldlb));
1827  assert(SCIPsetIsFeasLE(set, newbound, oldub));
1828  oldbound = oldlb;
1829  newbound = MIN(newbound, oldub);
1830 
1831  if ( set->stage == SCIP_STAGE_SOLVING && SCIPsetIsInfinity(set, newbound) )
1832  {
1833  SCIPerrorMessage("cannot change lower bound of variable <%s> to infinity.\n", SCIPvarGetName(var));
1834  SCIPABORT();
1835  return SCIP_INVALIDDATA; /*lint !e527*/
1836  }
1837  }
1838  else
1839  {
1840  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
1841 
1842  /* adjust the new upper bound */
1843  SCIPvarAdjustUb(var, set, &newbound);
1844  assert(SCIPsetIsLT(set, newbound, oldub));
1845  assert(SCIPsetIsFeasGE(set, newbound, oldlb));
1846  oldbound = oldub;
1847  newbound = MAX(newbound, oldlb);
1848 
1849  if ( set->stage == SCIP_STAGE_SOLVING && SCIPsetIsInfinity(set, -newbound) )
1850  {
1851  SCIPerrorMessage("cannot change upper bound of variable <%s> to minus infinity.\n", SCIPvarGetName(var));
1852  SCIPABORT();
1853  return SCIP_INVALIDDATA; /*lint !e527*/
1854  }
1855  }
1856 
1857  SCIPsetDebugMsg(set, " -> transformed to active variable <%s>: old bounds=[%g,%g], new %s bound: %g, obj: %g\n",
1858  SCIPvarGetName(var), oldlb, oldub, boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", newbound,
1859  SCIPvarGetObj(var));
1860 
1861  /* if the bound change takes place at an active node but is conflicting with the current local bounds,
1862  * we cannot apply it immediately because this would introduce inconsistencies to the bound change data structures
1863  * in the tree and to the bound change information data in the variable;
1864  * instead we have to remember the bound change as a pending bound change and mark the affected nodes on the active
1865  * path to be infeasible
1866  */
1867  if( node->active )
1868  {
1869  int conflictingdepth;
1870 
1871  conflictingdepth = SCIPvarGetConflictingBdchgDepth(var, set, boundtype, newbound);
1872 
1873  if( conflictingdepth >= 0 )
1874  {
1875  /* 0 would mean the bound change conflicts with a global bound */
1876  assert(conflictingdepth > 0);
1877  assert(conflictingdepth < tree->pathlen);
1878 
1879  SCIPsetDebugMsg(set, " -> bound change <%s> %s %g violates current local bounds [%g,%g] since depth %d: remember for later application\n",
1880  SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound,
1881  SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), conflictingdepth);
1882 
1883  /* remember the pending bound change */
1884  SCIP_CALL( treeAddPendingBdchg(tree, set, node, var, newbound, boundtype, infercons, inferprop, inferinfo,
1885  probingchange) );
1886 
1887  /* mark the node with the conflicting bound change to be cut off */
1888  SCIP_CALL( SCIPnodeCutoff(tree->path[conflictingdepth], set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
1889 
1890  return SCIP_OKAY;
1891  }
1892  }
1893 
1894  SCIPstatIncrement(stat, set, nboundchgs);
1895 
1896  /* if we are in probing mode we have to additionally count the bound changes for the probing statistic */
1897  if( tree->probingroot != NULL )
1898  SCIPstatIncrement(stat, set, nprobboundchgs);
1899 
1900  /* if the node is the root node: change local and global bound immediately */
1901  if( SCIPnodeGetDepth(node) <= tree->effectiverootdepth )
1902  {
1903  assert(node->active || tree->focusnode == NULL );
1904  assert(SCIPnodeGetType(node) != SCIP_NODETYPE_PROBINGNODE);
1905  assert(!probingchange);
1906 
1907  SCIPsetDebugMsg(set, " -> bound change in root node: perform global bound change\n");
1908  SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
1909 
1910  if( set->stage == SCIP_STAGE_SOLVING )
1911  {
1912  /* the root should be repropagated due to the bound change */
1913  SCIPnodePropagateAgain(tree->root, set, stat, tree);
1914  SCIPsetDebugMsg(set, "marked root node to be repropagated due to global bound change <%s>:[%g,%g] -> [%g,%g] found in depth %u\n",
1915  SCIPvarGetName(var), oldlb, oldub, boundtype == SCIP_BOUNDTYPE_LOWER ? newbound : oldlb,
1916  boundtype == SCIP_BOUNDTYPE_LOWER ? oldub : newbound, node->depth);
1917  }
1918 
1919  return SCIP_OKAY;
1920  }
1921 
1922  /* if the node is a child, or the bound is a temporary probing bound
1923  * - the bound change is a branching decision
1924  * - the child's lower bound can be updated due to the changed pseudo solution
1925  * otherwise:
1926  * - the bound change is an inference
1927  */
1928  if( SCIPnodeGetType(node) == SCIP_NODETYPE_CHILD || probingchange )
1929  {
1930  SCIP_Real newpseudoobjval;
1931  SCIP_Real lpsolval;
1932 
1933  assert(!node->active || SCIPnodeGetType(node) == SCIP_NODETYPE_PROBINGNODE);
1934 
1935  /* get the solution value of variable in last solved LP on the active path:
1936  * - if the LP was solved at the current node, the LP values of the columns are valid
1937  * - if the last solved LP was the one in the current lpstatefork, the LP value in the columns are still valid
1938  * - otherwise, the LP values are invalid
1939  */
1940  if( SCIPtreeHasCurrentNodeLP(tree)
1942  {
1943  lpsolval = SCIPvarGetLPSol(var);
1944  }
1945  else
1946  lpsolval = SCIP_INVALID;
1947 
1948  /* remember the bound change as branching decision (infervar/infercons/inferprop are not important: use NULL) */
1949  SCIP_CALL( SCIPdomchgAddBoundchg(&node->domchg, blkmem, set, var, newbound, boundtype, SCIP_BOUNDCHGTYPE_BRANCHING,
1950  lpsolval, NULL, NULL, NULL, 0, inferboundtype) );
1951 
1952  /* update the child's lower bound */
1953  if( set->misc_exactsolve )
1954  newpseudoobjval = SCIPlpGetModifiedProvedPseudoObjval(lp, set, var, oldbound, newbound, boundtype);
1955  else
1956  newpseudoobjval = SCIPlpGetModifiedPseudoObjval(lp, set, transprob, var, oldbound, newbound, boundtype);
1957  SCIPnodeUpdateLowerbound(node, stat, set, tree, transprob, origprob, newpseudoobjval);
1958  }
1959  else
1960  {
1961  /* check the infered bound change on the debugging solution */
1962  SCIP_CALL( SCIPdebugCheckInference(blkmem, set, node, var, newbound, boundtype) ); /*lint !e506 !e774*/
1963 
1964  /* remember the bound change as inference (lpsolval is not important: use 0.0) */
1965  SCIP_CALL( SCIPdomchgAddBoundchg(&node->domchg, blkmem, set, var, newbound, boundtype,
1967  0.0, infervar, infercons, inferprop, inferinfo, inferboundtype) );
1968  }
1969 
1970  assert(node->domchg != NULL);
1971  assert(node->domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1972  assert(node->domchg->domchgdyn.boundchgs != NULL);
1973  assert(node->domchg->domchgdyn.nboundchgs > 0);
1974  assert(node->domchg->domchgdyn.boundchgs[node->domchg->domchgdyn.nboundchgs-1].var == var);
1975  assert(node->domchg->domchgdyn.boundchgs[node->domchg->domchgdyn.nboundchgs-1].newbound == newbound); /*lint !e777*/
1976 
1977  /* if node is active, apply the bound change immediately */
1978  if( node->active )
1979  {
1980  SCIP_Bool cutoff;
1981 
1982  /**@todo if the node is active, it currently must either be the effective root (see above) or the current node;
1983  * if a bound change to an intermediate active node should be added, we must make sure, the bound change
1984  * information array of the variable stays sorted (new info must be sorted in instead of putting it to
1985  * the end of the array), and we should identify now redundant bound changes that are applied at a
1986  * later node on the active path
1987  */
1988  assert(SCIPtreeGetCurrentNode(tree) == node);
1990  blkmem, set, stat, lp, branchcand, eventqueue, node->depth, node->domchg->domchgdyn.nboundchgs-1, &cutoff) );
1991  assert(node->domchg->domchgdyn.boundchgs[node->domchg->domchgdyn.nboundchgs-1].var == var);
1992  assert(!cutoff);
1993  }
1994 
1995  return SCIP_OKAY;
1996 }
1997 
1998 /** adds bound change to focus node, or child of focus node, or probing node;
1999  * if possible, adjusts bound to integral value
2000  */
2002  SCIP_NODE* node, /**< node to add bound change to */
2003  BMS_BLKMEM* blkmem, /**< block memory */
2004  SCIP_SET* set, /**< global SCIP settings */
2005  SCIP_STAT* stat, /**< problem statistics */
2006  SCIP_PROB* transprob, /**< transformed problem after presolve */
2007  SCIP_PROB* origprob, /**< original problem */
2008  SCIP_TREE* tree, /**< branch and bound tree */
2009  SCIP_REOPT* reopt, /**< reoptimization data structure */
2010  SCIP_LP* lp, /**< current LP data */
2011  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2012  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2013  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2014  SCIP_VAR* var, /**< variable to change the bounds for */
2015  SCIP_Real newbound, /**< new value for bound */
2016  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
2017  SCIP_Bool probingchange /**< is the bound change a temporary setting due to probing? */
2018  )
2019 {
2020  SCIP_CALL( SCIPnodeAddBoundinfer(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
2021  cliquetable, var, newbound, boundtype, NULL, NULL, 0, probingchange) );
2022 
2023  return SCIP_OKAY;
2024 }
2025 
2026 /** adds hole with inference information to focus node, child of focus node, or probing node;
2027  * if possible, adjusts bound to integral value;
2028  * at most one of infercons and inferprop may be non-NULL
2029  */
2031  SCIP_NODE* node, /**< node to add bound change to */
2032  BMS_BLKMEM* blkmem, /**< block memory */
2033  SCIP_SET* set, /**< global SCIP settings */
2034  SCIP_STAT* stat, /**< problem statistics */
2035  SCIP_TREE* tree, /**< branch and bound tree */
2036  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2037  SCIP_VAR* var, /**< variable to change the bounds for */
2038  SCIP_Real left, /**< left bound of open interval defining the hole (left,right) */
2039  SCIP_Real right, /**< right bound of open interval defining the hole (left,right) */
2040  SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
2041  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
2042  int inferinfo, /**< user information for inference to help resolving the conflict */
2043  SCIP_Bool probingchange, /**< is the bound change a temporary setting due to probing? */
2044  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
2045  )
2046 {
2047 #if 0
2048  SCIP_VAR* infervar;
2049 #endif
2050 
2051  assert(node != NULL);
2056  || node->depth == 0);
2057  assert(blkmem != NULL);
2058  assert(set != NULL);
2059  assert(tree != NULL);
2060  assert(tree->effectiverootdepth >= 0);
2061  assert(tree->root != NULL);
2062  assert(var != NULL);
2063  assert(node->active || (infercons == NULL && inferprop == NULL));
2064  assert((SCIP_NODETYPE)node->nodetype == SCIP_NODETYPE_PROBINGNODE || !probingchange);
2065 
2066  /* the interval should not be empty */
2067  assert(SCIPsetIsLT(set, left, right));
2068 
2069 #ifndef NDEBUG
2070  {
2071  SCIP_Real adjustedleft;
2072  SCIP_Real adjustedright;
2073 
2074  adjustedleft = left;
2075  adjustedright = right;
2076 
2077  SCIPvarAdjustUb(var, set, &adjustedleft);
2078  SCIPvarAdjustLb(var, set, &adjustedright);
2079 
2080  assert(SCIPsetIsEQ(set, left, adjustedleft));
2081  assert(SCIPsetIsEQ(set, right, adjustedright));
2082  }
2083 #endif
2084 
2085  /* the hole should lay within the lower and upper bounds */
2086  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
2087  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
2088 
2089  SCIPsetDebugMsg(set, "adding hole (%g,%g) at node at depth %u to variable <%s>: bounds=[%g,%g], (infer%s=<%s>, inferinfo=%d)\n",
2090  left, right, node->depth, SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), infercons != NULL ? "cons" : "prop",
2091  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo);
2092 
2093 #if 0
2094  /* remember variable as inference variable, and get corresponding active variable, bound and bound type */
2095  infervar = var;
2096 #endif
2097  SCIP_CALL( SCIPvarGetProbvarHole(&var, &left, &right) );
2098 
2100  {
2101  SCIPerrorMessage("cannot change bounds of multi-aggregated variable <%s>\n", SCIPvarGetName(var));
2102  SCIPABORT();
2103  return SCIP_INVALIDDATA; /*lint !e527*/
2104  }
2106 
2107  SCIPsetDebugMsg(set, " -> transformed to active variable <%s>: hole (%g,%g), obj: %g\n", SCIPvarGetName(var), left, right, SCIPvarGetObj(var));
2108 
2109  stat->nholechgs++;
2110 
2111  /* if we are in probing mode we have to additionally count the bound changes for the probing statistic */
2112  if( tree->probingroot != NULL )
2113  stat->nprobholechgs++;
2114 
2115  /* if the node is the root node: change local and global bound immediately */
2116  if( SCIPnodeGetDepth(node) <= tree->effectiverootdepth )
2117  {
2118  assert(node->active || tree->focusnode == NULL );
2119  assert(SCIPnodeGetType(node) != SCIP_NODETYPE_PROBINGNODE);
2120  assert(!probingchange);
2121 
2122  SCIPsetDebugMsg(set, " -> hole added in root node: perform global domain change\n");
2123  SCIP_CALL( SCIPvarAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
2124 
2125  if( set->stage == SCIP_STAGE_SOLVING && (*added) )
2126  {
2127  /* the root should be repropagated due to the bound change */
2128  SCIPnodePropagateAgain(tree->root, set, stat, tree);
2129  SCIPsetDebugMsg(set, "marked root node to be repropagated due to global added hole <%s>: (%g,%g) found in depth %u\n",
2130  SCIPvarGetName(var), left, right, node->depth);
2131  }
2132 
2133  return SCIP_OKAY;
2134  }
2135 
2136  /**@todo add adding of local domain holes */
2137 
2138  (*added) = FALSE;
2139  SCIPerrorMessage("WARNING: currently domain holes can only be handled globally!\n");
2140 
2141  stat->nholechgs--;
2142 
2143  /* if we are in probing mode we have to additionally count the bound changes for the probing statistic */
2144  if( tree->probingroot != NULL )
2145  stat->nprobholechgs--;
2146 
2147  return SCIP_OKAY;
2148 }
2149 
2150 /** adds hole change to focus node, or child of focus node */
2152  SCIP_NODE* node, /**< node to add bound change to */
2153  BMS_BLKMEM* blkmem, /**< block memory */
2154  SCIP_SET* set, /**< global SCIP settings */
2155  SCIP_STAT* stat, /**< problem statistics */
2156  SCIP_TREE* tree, /**< branch and bound tree */
2157  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2158  SCIP_VAR* var, /**< variable to change the bounds for */
2159  SCIP_Real left, /**< left bound of open interval defining the hole (left,right) */
2160  SCIP_Real right, /**< right bound of open interval defining the hole (left,right) */
2161  SCIP_Bool probingchange, /**< is the bound change a temporary setting due to probing? */
2162  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
2163  )
2164 {
2165  assert(node != NULL);
2169  assert(blkmem != NULL);
2170 
2171  SCIPsetDebugMsg(set, "adding hole (%g,%g) at node at depth %u of variable <%s>\n",
2172  left, right, node->depth, SCIPvarGetName(var));
2173 
2174  SCIP_CALL( SCIPnodeAddHoleinfer(node, blkmem, set, stat, tree, eventqueue, var, left, right,
2175  NULL, NULL, 0, probingchange, added) );
2176 
2177  /**@todo apply hole change on active nodes and issue event */
2178 
2179  return SCIP_OKAY;
2180 }
2181 
2182 /** applies the pending bound changes */
2183 static
2185  SCIP_TREE* tree, /**< branch and bound tree */
2186  SCIP_REOPT* reopt, /**< reoptimization data structure */
2187  BMS_BLKMEM* blkmem, /**< block memory */
2188  SCIP_SET* set, /**< global SCIP settings */
2189  SCIP_STAT* stat, /**< problem statistics */
2190  SCIP_PROB* transprob, /**< transformed problem after presolve */
2191  SCIP_PROB* origprob, /**< original problem */
2192  SCIP_LP* lp, /**< current LP data */
2193  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2194  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2195  SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
2196  )
2197 {
2198  SCIP_VAR* var;
2199  int npendingbdchgs;
2200  int conflictdepth;
2201  int i;
2202 
2203  assert(tree != NULL);
2204 
2205  npendingbdchgs = tree->npendingbdchgs;
2206  for( i = 0; i < npendingbdchgs; ++i )
2207  {
2208  var = tree->pendingbdchgs[i].var;
2209  assert(SCIPnodeGetDepth(tree->pendingbdchgs[i].node) < tree->cutoffdepth);
2210 
2211  conflictdepth = SCIPvarGetConflictingBdchgDepth(var, set, tree->pendingbdchgs[i].boundtype,
2212  tree->pendingbdchgs[i].newbound);
2213 
2214  /* It can happen, that a pending bound change conflicts with the global bounds, because when it was collected, it
2215  * just conflicted with the local bounds, but a conflicting global bound change was applied afterwards. In this
2216  * case, we can cut off the node where the pending bound change should be applied.
2217  */
2218  if( conflictdepth == 0 )
2219  {
2220  SCIP_CALL( SCIPnodeCutoff(tree->pendingbdchgs[i].node, set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
2221 
2222  if( ((int) tree->pendingbdchgs[i].node->depth) <= tree->effectiverootdepth )
2223  return SCIP_OKAY;
2224  else
2225  continue;
2226  }
2227 
2228  assert(conflictdepth == -1);
2229 
2230  SCIPsetDebugMsg(set, "applying pending bound change <%s>[%g,%g] %s %g\n", SCIPvarGetName(var),
2232  tree->pendingbdchgs[i].boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
2233  tree->pendingbdchgs[i].newbound);
2234 
2235  /* ignore bounds that are now redundant (for example, multiple entries in the pendingbdchgs for the same
2236  * variable)
2237  */
2238  if( tree->pendingbdchgs[i].boundtype == SCIP_BOUNDTYPE_LOWER )
2239  {
2240  SCIP_Real lb;
2241 
2242  lb = SCIPvarGetLbLocal(var);
2243  if( !SCIPsetIsGT(set, tree->pendingbdchgs[i].newbound, lb) )
2244  {
2245  /* release the variable */
2246  SCIP_CALL( SCIPvarRelease(&var, blkmem, set, eventqueue, lp) );
2247  continue;
2248  }
2249  }
2250  else
2251  {
2252  SCIP_Real ub;
2253 
2254  assert(tree->pendingbdchgs[i].boundtype == SCIP_BOUNDTYPE_UPPER);
2255  ub = SCIPvarGetUbLocal(var);
2256  if( !SCIPsetIsLT(set, tree->pendingbdchgs[i].newbound, ub) )
2257  {
2258  /* release the variable */
2259  SCIP_CALL( SCIPvarRelease(&var, blkmem, set, eventqueue, lp) );
2260  continue;
2261  }
2262  }
2263 
2264  SCIP_CALL( SCIPnodeAddBoundinfer(tree->pendingbdchgs[i].node, blkmem, set, stat, transprob, origprob, tree, reopt,
2265  lp, branchcand, eventqueue, cliquetable, var, tree->pendingbdchgs[i].newbound, tree->pendingbdchgs[i].boundtype,
2267  tree->pendingbdchgs[i].probingchange) );
2268  assert(tree->npendingbdchgs == npendingbdchgs); /* this time, the bound change can be applied! */
2269 
2270  /* release the variable */
2271  SCIP_CALL( SCIPvarRelease(&var, blkmem, set, eventqueue, lp) );
2272  }
2273  tree->npendingbdchgs = 0;
2274 
2275  return SCIP_OKAY;
2276 }
2277 
2278 /** if given value is larger than the node's lower bound, sets the node's lower bound to the new value */
2280  SCIP_NODE* node, /**< node to update lower bound for */
2281  SCIP_STAT* stat, /**< problem statistics */
2282  SCIP_SET* set, /**< global SCIP settings */
2283  SCIP_TREE* tree, /**< branch and bound tree */
2284  SCIP_PROB* transprob, /**< transformed problem after presolve */
2285  SCIP_PROB* origprob, /**< original problem */
2286  SCIP_Real newbound /**< new lower bound for the node (if it's larger than the old one) */
2287  )
2288 {
2289  assert(node != NULL);
2290  assert(stat != NULL);
2291 
2292  if( newbound > node->lowerbound )
2293  {
2294  SCIP_Real oldbound;
2295 
2296  oldbound = node->lowerbound;
2297  node->lowerbound = newbound;
2298  node->estimate = MAX(node->estimate, newbound);
2299  if( node->depth == 0 )
2300  {
2301  stat->rootlowerbound = newbound;
2302  if( set->misc_calcintegral )
2303  SCIPstatUpdatePrimalDualIntegral(stat, set, transprob, origprob, SCIPsetInfinity(set), newbound);
2304  }
2305  else if( set->misc_calcintegral && SCIPsetIsEQ(set, oldbound, stat->lastlowerbound) )
2306  {
2307  SCIP_Real lowerbound;
2308  lowerbound = SCIPtreeGetLowerbound(tree, set);
2309  assert(newbound >= lowerbound);
2310 
2311  /* updating the primal integral is only necessary if dual bound has increased since last evaluation */
2312  if( lowerbound > stat->lastlowerbound )
2313  SCIPstatUpdatePrimalDualIntegral(stat, set, transprob, origprob, SCIPsetInfinity(set), lowerbound);
2314  }
2315  }
2316 }
2317 
2318 /** updates lower bound of node using lower bound of LP */
2320  SCIP_NODE* node, /**< node to set lower bound for */
2321  SCIP_SET* set, /**< global SCIP settings */
2322  SCIP_STAT* stat, /**< problem statistics */
2323  SCIP_TREE* tree, /**< branch and bound tree */
2324  SCIP_PROB* transprob, /**< transformed problem after presolve */
2325  SCIP_PROB* origprob, /**< original problem */
2326  SCIP_LP* lp /**< LP data */
2327  )
2328 {
2329  SCIP_Real lpobjval;
2330 
2331  assert(set != NULL);
2332  assert(lp->flushed);
2333 
2334  /* in case of iteration or time limit, the LP value may not be a valid dual bound */
2335  /* @todo check for dual feasibility of LP solution and use sub-optimal solution if they are dual feasible */
2337  return SCIP_OKAY;
2338 
2339  if( set->misc_exactsolve )
2340  {
2341  SCIP_CALL( SCIPlpGetProvedLowerbound(lp, set, &lpobjval) );
2342  }
2343  else
2344  lpobjval = SCIPlpGetObjval(lp, set, transprob);
2345 
2346  SCIPnodeUpdateLowerbound(node, stat, set, tree, transprob, origprob, lpobjval);
2347 
2348  return SCIP_OKAY;
2349 }
2350 
2351 
2352 /** change the node selection priority of the given child */
2354  SCIP_TREE* tree, /**< branch and bound tree */
2355  SCIP_NODE* child, /**< child to update the node selection priority */
2356  SCIP_Real priority /**< node selection priority value */
2357  )
2358 {
2359  int pos;
2360 
2361  assert( SCIPnodeGetType(child) == SCIP_NODETYPE_CHILD );
2362 
2363  pos = child->data.child.arraypos;
2364  assert( pos >= 0 );
2365 
2366  tree->childrenprio[pos] = priority;
2367 }
2368 
2369 
2370 /** sets the node's estimated bound to the new value */
2372  SCIP_NODE* node, /**< node to update lower bound for */
2373  SCIP_SET* set, /**< global SCIP settings */
2374  SCIP_Real newestimate /**< new estimated bound for the node */
2375  )
2376 {
2377  assert(node != NULL);
2378  assert(set != NULL);
2379  assert(SCIPsetIsRelGE(set, newestimate, node->lowerbound));
2380 
2381  node->estimate = newestimate;
2382 }
2383 
2384 /** propagates implications of binary fixings at the given node triggered by the implication graph and the clique table */
2386  SCIP_NODE* node, /**< node to propagate implications on */
2387  BMS_BLKMEM* blkmem, /**< block memory */
2388  SCIP_SET* set, /**< global SCIP settings */
2389  SCIP_STAT* stat, /**< problem statistics */
2390  SCIP_PROB* transprob, /**< transformed problem after presolve */
2391  SCIP_PROB* origprob, /**< original problem */
2392  SCIP_TREE* tree, /**< branch and bound tree */
2393  SCIP_REOPT* reopt, /**< reoptimization data structure */
2394  SCIP_LP* lp, /**< current LP data */
2395  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2396  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2397  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2398  SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
2399  )
2400 {
2401  int nboundchgs;
2402  int i;
2403 
2404  assert(node != NULL);
2405  assert(SCIPnodeIsActive(node));
2409  assert(cutoff != NULL);
2410 
2411  SCIPsetDebugMsg(set, "implication graph propagation of node #%" SCIP_LONGINT_FORMAT " in depth %d\n",
2412  SCIPnodeGetNumber(node), SCIPnodeGetDepth(node));
2413 
2414  *cutoff = FALSE;
2415 
2416  /* propagate all fixings of binary variables performed at this node */
2417  nboundchgs = SCIPdomchgGetNBoundchgs(node->domchg);
2418  for( i = 0; i < nboundchgs && !(*cutoff); ++i )
2419  {
2420  SCIP_BOUNDCHG* boundchg;
2421  SCIP_VAR* var;
2422 
2423  boundchg = SCIPdomchgGetBoundchg(node->domchg, i);
2424 
2425  /* ignore redundant bound changes */
2426  if( SCIPboundchgIsRedundant(boundchg) )
2427  continue;
2428 
2429  var = SCIPboundchgGetVar(boundchg);
2430  if( SCIPvarIsBinary(var) )
2431  {
2432  SCIP_Bool varfixing;
2433  int nimpls;
2434  SCIP_VAR** implvars;
2435  SCIP_BOUNDTYPE* impltypes;
2436  SCIP_Real* implbounds;
2437  SCIP_CLIQUE** cliques;
2438  int ncliques;
2439  int j;
2440 
2441  varfixing = (SCIPboundchgGetBoundtype(boundchg) == SCIP_BOUNDTYPE_LOWER);
2442  nimpls = SCIPvarGetNImpls(var, varfixing);
2443  implvars = SCIPvarGetImplVars(var, varfixing);
2444  impltypes = SCIPvarGetImplTypes(var, varfixing);
2445  implbounds = SCIPvarGetImplBounds(var, varfixing);
2446 
2447  /* apply implications */
2448  for( j = 0; j < nimpls; ++j )
2449  {
2450  SCIP_Real lb;
2451  SCIP_Real ub;
2452 
2453  /* @note should this be checked here (because SCIPnodeAddBoundinfer fails for multi-aggregated variables)
2454  * or should SCIPnodeAddBoundinfer() just return for multi-aggregated variables?
2455  */
2457  continue;
2458 
2459  /* check for infeasibility */
2460  lb = SCIPvarGetLbLocal(implvars[j]);
2461  ub = SCIPvarGetUbLocal(implvars[j]);
2462  if( impltypes[j] == SCIP_BOUNDTYPE_LOWER )
2463  {
2464  if( SCIPsetIsFeasGT(set, implbounds[j], ub) )
2465  {
2466  *cutoff = TRUE;
2467  return SCIP_OKAY;
2468  }
2469  if( SCIPsetIsFeasLE(set, implbounds[j], lb) )
2470  continue;
2471  }
2472  else
2473  {
2474  if( SCIPsetIsFeasLT(set, implbounds[j], lb) )
2475  {
2476  *cutoff = TRUE;
2477  return SCIP_OKAY;
2478  }
2479  if( SCIPsetIsFeasGE(set, implbounds[j], ub) )
2480  continue;
2481  }
2482 
2483  /* @note the implication might affect a fixed variable (after resolving (multi-)aggregations);
2484  * normally, the implication should have been deleted in that case, but this is only possible
2485  * if the implied variable has the reverse implication stored as a variable bound;
2486  * due to numerics, the variable bound may not be present and so the implication is not deleted
2487  */
2489  continue;
2490 
2491  /* apply the implication */
2492  SCIP_CALL( SCIPnodeAddBoundinfer(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
2493  eventqueue, cliquetable, implvars[j], implbounds[j], impltypes[j], NULL, NULL, 0, FALSE) );
2494  }
2495 
2496  /* apply cliques */
2497  ncliques = SCIPvarGetNCliques(var, varfixing);
2498  cliques = SCIPvarGetCliques(var, varfixing);
2499  for( j = 0; j < ncliques; ++j )
2500  {
2501  SCIP_VAR** vars;
2502  SCIP_Bool* values;
2503  int nvars;
2504  int k;
2505 
2506  nvars = SCIPcliqueGetNVars(cliques[j]);
2507  vars = SCIPcliqueGetVars(cliques[j]);
2508  values = SCIPcliqueGetValues(cliques[j]);
2509  for( k = 0; k < nvars; ++k )
2510  {
2511  SCIP_Real lb;
2512  SCIP_Real ub;
2513 
2514  assert(SCIPvarIsBinary(vars[k]));
2515 
2516  if( SCIPvarGetStatus(vars[k]) == SCIP_VARSTATUS_MULTAGGR )
2517  continue;
2518 
2519  if( vars[k] == var && values[k] == varfixing )
2520  continue;
2521 
2522  /* check for infeasibility */
2523  lb = SCIPvarGetLbLocal(vars[k]);
2524  ub = SCIPvarGetUbLocal(vars[k]);
2525  if( values[k] == FALSE )
2526  {
2527  if( ub < 0.5 )
2528  {
2529  *cutoff = TRUE;
2530  return SCIP_OKAY;
2531  }
2532  if( lb > 0.5 )
2533  continue;
2534  }
2535  else
2536  {
2537  if( lb > 0.5 )
2538  {
2539  *cutoff = TRUE;
2540  return SCIP_OKAY;
2541  }
2542  if( ub < 0.5 )
2543  continue;
2544  }
2545 
2547  continue;
2548 
2549  /* apply the clique implication */
2550  SCIP_CALL( SCIPnodeAddBoundinfer(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
2551  eventqueue, cliquetable, vars[k], (SCIP_Real)(!values[k]), values[k] ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER,
2552  NULL, NULL, 0, FALSE) );
2553  }
2554  }
2555  }
2556  }
2557 
2558  return SCIP_OKAY;
2559 }
2560 
2561 
2562 
2563 
2564 /*
2565  * Path Switching
2566  */
2567 
2568 /** updates the LP sizes of the active path starting at the given depth */
2569 static
2571  SCIP_TREE* tree, /**< branch and bound tree */
2572  int startdepth /**< depth to start counting */
2573  )
2574 {
2575  SCIP_NODE* node;
2576  int ncols;
2577  int nrows;
2578  int i;
2579 
2580  assert(tree != NULL);
2581  assert(startdepth >= 0);
2582  assert(startdepth <= tree->pathlen);
2583 
2584  if( startdepth == 0 )
2585  {
2586  ncols = 0;
2587  nrows = 0;
2588  }
2589  else
2590  {
2591  ncols = tree->pathnlpcols[startdepth-1];
2592  nrows = tree->pathnlprows[startdepth-1];
2593  }
2594 
2595  for( i = startdepth; i < tree->pathlen; ++i )
2596  {
2597  node = tree->path[i];
2598  assert(node != NULL);
2599  assert(node->active);
2600  assert((int)(node->depth) == i);
2601 
2602  switch( SCIPnodeGetType(node) )
2603  {
2605  assert(i == tree->pathlen-1 || SCIPtreeProbing(tree));
2606  break;
2608  assert(SCIPtreeProbing(tree));
2609  assert(i >= 1);
2610  assert(SCIPnodeGetType(tree->path[i-1]) == SCIP_NODETYPE_FOCUSNODE
2611  || (ncols == node->data.probingnode->ninitialcols && nrows == node->data.probingnode->ninitialrows));
2612  assert(ncols <= node->data.probingnode->ncols || !tree->focuslpconstructed);
2613  assert(nrows <= node->data.probingnode->nrows || !tree->focuslpconstructed);
2614  if( i < tree->pathlen-1 )
2615  {
2616  ncols = node->data.probingnode->ncols;
2617  nrows = node->data.probingnode->nrows;
2618  }
2619  else
2620  {
2621  /* for the current probing node, the initial LP size is stored in the path */
2622  ncols = node->data.probingnode->ninitialcols;
2623  nrows = node->data.probingnode->ninitialrows;
2624  }
2625  break;
2626  case SCIP_NODETYPE_SIBLING:
2627  SCIPerrorMessage("sibling cannot be in the active path\n");
2628  SCIPABORT();
2629  return SCIP_INVALIDDATA; /*lint !e527*/
2630  case SCIP_NODETYPE_CHILD:
2631  SCIPerrorMessage("child cannot be in the active path\n");
2632  SCIPABORT();
2633  return SCIP_INVALIDDATA; /*lint !e527*/
2634  case SCIP_NODETYPE_LEAF:
2635  SCIPerrorMessage("leaf cannot be in the active path\n");
2636  SCIPABORT();
2637  return SCIP_INVALIDDATA; /*lint !e527*/
2638  case SCIP_NODETYPE_DEADEND:
2639  SCIPerrorMessage("dead-end cannot be in the active path\n");
2640  SCIPABORT();
2641  return SCIP_INVALIDDATA; /*lint !e527*/
2643  break;
2645  assert(node->data.pseudofork != NULL);
2646  ncols += node->data.pseudofork->naddedcols;
2647  nrows += node->data.pseudofork->naddedrows;
2648  break;
2649  case SCIP_NODETYPE_FORK:
2650  assert(node->data.fork != NULL);
2651  ncols += node->data.fork->naddedcols;
2652  nrows += node->data.fork->naddedrows;
2653  break;
2654  case SCIP_NODETYPE_SUBROOT:
2655  assert(node->data.subroot != NULL);
2656  ncols = node->data.subroot->ncols;
2657  nrows = node->data.subroot->nrows;
2658  break;
2660  SCIPerrorMessage("node cannot be of type REFOCUSNODE at this point\n");
2661  SCIPABORT();
2662  return SCIP_INVALIDDATA; /*lint !e527*/
2663  default:
2664  SCIPerrorMessage("unknown node type %d\n", SCIPnodeGetType(node));
2665  SCIPABORT();
2666  return SCIP_INVALIDDATA; /*lint !e527*/
2667  }
2668  tree->pathnlpcols[i] = ncols;
2669  tree->pathnlprows[i] = nrows;
2670  }
2671  return SCIP_OKAY;
2672 }
2673 
2674 /** finds the common fork node, the new LP state defining fork, and the new focus subroot, if the path is switched to
2675  * the given node
2676  */
2677 static
2679  SCIP_TREE* tree, /**< branch and bound tree */
2680  SCIP_NODE* node, /**< new focus node, or NULL */
2681  SCIP_NODE** commonfork, /**< pointer to store common fork node of old and new focus node */
2682  SCIP_NODE** newlpfork, /**< pointer to store the new LP defining fork node */
2683  SCIP_NODE** newlpstatefork, /**< pointer to store the new LP state defining fork node */
2684  SCIP_NODE** newsubroot, /**< pointer to store the new subroot node */
2685  SCIP_Bool* cutoff /**< pointer to store whether the given node can be cut off and no path switching
2686  * should be performed */
2687  )
2688 {
2689  SCIP_NODE* fork;
2690  SCIP_NODE* lpfork;
2691  SCIP_NODE* lpstatefork;
2692  SCIP_NODE* subroot;
2693 
2694  assert(tree != NULL);
2695  assert(tree->root != NULL);
2696  assert((tree->focusnode == NULL) == !tree->root->active);
2697  assert(tree->focuslpfork == NULL || tree->focusnode != NULL);
2698  assert(tree->focuslpfork == NULL || tree->focuslpfork->depth < tree->focusnode->depth);
2699  assert(tree->focuslpstatefork == NULL || tree->focuslpfork != NULL);
2700  assert(tree->focuslpstatefork == NULL || tree->focuslpstatefork->depth <= tree->focuslpfork->depth);
2701  assert(tree->focussubroot == NULL || tree->focuslpstatefork != NULL);
2702  assert(tree->focussubroot == NULL || tree->focussubroot->depth <= tree->focuslpstatefork->depth);
2703  assert(tree->cutoffdepth >= 0);
2704  assert(tree->cutoffdepth == INT_MAX || tree->cutoffdepth < tree->pathlen);
2705  assert(tree->cutoffdepth == INT_MAX || tree->path[tree->cutoffdepth]->cutoff);
2706  assert(tree->repropdepth >= 0);
2707  assert(tree->repropdepth == INT_MAX || tree->repropdepth < tree->pathlen);
2708  assert(tree->repropdepth == INT_MAX || tree->path[tree->repropdepth]->reprop);
2709  assert(commonfork != NULL);
2710  assert(newlpfork != NULL);
2711  assert(newlpstatefork != NULL);
2712  assert(newsubroot != NULL);
2713  assert(cutoff != NULL);
2714 
2715  *commonfork = NULL;
2716  *newlpfork = NULL;
2717  *newlpstatefork = NULL;
2718  *newsubroot = NULL;
2719  *cutoff = FALSE;
2720 
2721  /* if the new focus node is NULL, there is no common fork node, and the new LP fork, LP state fork, and subroot
2722  * are NULL
2723  */
2724  if( node == NULL )
2725  {
2726  tree->cutoffdepth = INT_MAX;
2727  tree->repropdepth = INT_MAX;
2728  return;
2729  }
2730 
2731  /* check if the new node is marked to be cut off */
2732  if( node->cutoff )
2733  {
2734  *cutoff = TRUE;
2735  return;
2736  }
2737 
2738  /* if the old focus node is NULL, there is no common fork node, and we have to search the new LP fork, LP state fork
2739  * and subroot
2740  */
2741  if( tree->focusnode == NULL )
2742  {
2743  assert(!tree->root->active);
2744  assert(tree->pathlen == 0);
2745  assert(tree->cutoffdepth == INT_MAX);
2746  assert(tree->repropdepth == INT_MAX);
2747 
2748  lpfork = node;
2749  while( SCIPnodeGetType(lpfork) != SCIP_NODETYPE_PSEUDOFORK
2751  {
2752  lpfork = lpfork->parent;
2753  if( lpfork == NULL )
2754  return;
2755  if( lpfork->cutoff )
2756  {
2757  *cutoff = TRUE;
2758  return;
2759  }
2760  }
2761  *newlpfork = lpfork;
2762 
2763  lpstatefork = lpfork;
2764  while( SCIPnodeGetType(lpstatefork) != SCIP_NODETYPE_FORK && SCIPnodeGetType(lpstatefork) != SCIP_NODETYPE_SUBROOT )
2765  {
2766  lpstatefork = lpstatefork->parent;
2767  if( lpstatefork == NULL )
2768  return;
2769  if( lpstatefork->cutoff )
2770  {
2771  *cutoff = TRUE;
2772  return;
2773  }
2774  }
2775  *newlpstatefork = lpstatefork;
2776 
2777  subroot = lpstatefork;
2778  while( SCIPnodeGetType(subroot) != SCIP_NODETYPE_SUBROOT )
2779  {
2780  subroot = subroot->parent;
2781  if( subroot == NULL )
2782  return;
2783  if( subroot->cutoff )
2784  {
2785  *cutoff = TRUE;
2786  return;
2787  }
2788  }
2789  *newsubroot = subroot;
2790 
2791  fork = subroot;
2792  while( fork->parent != NULL )
2793  {
2794  fork = fork->parent;
2795  if( fork->cutoff )
2796  {
2797  *cutoff = TRUE;
2798  return;
2799  }
2800  }
2801  return;
2802  }
2803 
2804  /* find the common fork node, the new LP defining fork, the new LP state defining fork, and the new focus subroot */
2805  fork = node;
2806  lpfork = NULL;
2807  lpstatefork = NULL;
2808  subroot = NULL;
2809  assert(fork != NULL);
2810 
2811  while( !fork->active )
2812  {
2813  fork = fork->parent;
2814  assert(fork != NULL); /* because the root is active, there must be a common fork node */
2815 
2816  if( fork->cutoff )
2817  {
2818  *cutoff = TRUE;
2819  return;
2820  }
2821  if( lpfork == NULL
2824  lpfork = fork;
2825  if( lpstatefork == NULL
2827  lpstatefork = fork;
2828  if( subroot == NULL && SCIPnodeGetType(fork) == SCIP_NODETYPE_SUBROOT )
2829  subroot = fork;
2830  }
2831  assert(lpfork == NULL || !lpfork->active || lpfork == fork);
2832  assert(lpstatefork == NULL || !lpstatefork->active || lpstatefork == fork);
2833  assert(subroot == NULL || !subroot->active || subroot == fork);
2834  SCIPdebugMessage("find switch forks: forkdepth=%u\n", fork->depth);
2835 
2836  /* if the common fork node is below the current cutoff depth, the cutoff node is an ancestor of the common fork
2837  * and thus an ancestor of the new focus node, s.t. the new node can also be cut off
2838  */
2839  assert((int)fork->depth != tree->cutoffdepth);
2840  if( (int)fork->depth > tree->cutoffdepth )
2841  {
2842 #ifndef NDEBUG
2843  while( !fork->cutoff )
2844  {
2845  fork = fork->parent;
2846  assert(fork != NULL);
2847  }
2848  assert((int)fork->depth >= tree->cutoffdepth);
2849 #endif
2850  *cutoff = TRUE;
2851  return;
2852  }
2853  tree->cutoffdepth = INT_MAX;
2854 
2855  /* if not already found, continue searching the LP defining fork; it cannot be deeper than the common fork */
2856  if( lpfork == NULL )
2857  {
2858  if( tree->focuslpfork != NULL && (int)(tree->focuslpfork->depth) > fork->depth )
2859  {
2860  /* focuslpfork is not on the same active path as the new node: we have to continue searching */
2861  lpfork = fork;
2862  while( lpfork != NULL
2864  && SCIPnodeGetType(lpfork) != SCIP_NODETYPE_FORK
2865  && SCIPnodeGetType(lpfork) != SCIP_NODETYPE_SUBROOT )
2866  {
2867  assert(lpfork->active);
2868  lpfork = lpfork->parent;
2869  }
2870  }
2871  else
2872  {
2873  /* focuslpfork is on the same active path as the new node: old and new node have the same lpfork */
2874  lpfork = tree->focuslpfork;
2875  }
2876  assert(lpfork == NULL || (int)(lpfork->depth) <= fork->depth);
2877  assert(lpfork == NULL || lpfork->active);
2878  }
2879  assert(lpfork == NULL
2881  || SCIPnodeGetType(lpfork) == SCIP_NODETYPE_FORK
2882  || SCIPnodeGetType(lpfork) == SCIP_NODETYPE_SUBROOT);
2883  SCIPdebugMessage("find switch forks: lpforkdepth=%d\n", lpfork == NULL ? -1 : (int)(lpfork->depth));
2884 
2885  /* if not already found, continue searching the LP state defining fork; it cannot be deeper than the
2886  * LP defining fork and the common fork
2887  */
2888  if( lpstatefork == NULL )
2889  {
2890  if( tree->focuslpstatefork != NULL && (int)(tree->focuslpstatefork->depth) > fork->depth )
2891  {
2892  /* focuslpstatefork is not on the same active path as the new node: we have to continue searching */
2893  if( lpfork != NULL && lpfork->depth < fork->depth )
2894  lpstatefork = lpfork;
2895  else
2896  lpstatefork = fork;
2897  while( lpstatefork != NULL
2898  && SCIPnodeGetType(lpstatefork) != SCIP_NODETYPE_FORK
2899  && SCIPnodeGetType(lpstatefork) != SCIP_NODETYPE_SUBROOT )
2900  {
2901  assert(lpstatefork->active);
2902  lpstatefork = lpstatefork->parent;
2903  }
2904  }
2905  else
2906  {
2907  /* focuslpstatefork is on the same active path as the new node: old and new node have the same lpstatefork */
2908  lpstatefork = tree->focuslpstatefork;
2909  }
2910  assert(lpstatefork == NULL || (int)(lpstatefork->depth) <= fork->depth);
2911  assert(lpstatefork == NULL || lpstatefork->active);
2912  }
2913  assert(lpstatefork == NULL
2914  || SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_FORK
2915  || SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_SUBROOT);
2916  assert(lpstatefork == NULL || (lpfork != NULL && lpstatefork->depth <= lpfork->depth));
2917  SCIPdebugMessage("find switch forks: lpstateforkdepth=%d\n", lpstatefork == NULL ? -1 : (int)(lpstatefork->depth));
2918 
2919  /* if not already found, continue searching the subroot; it cannot be deeper than the LP defining fork, the
2920  * LP state fork and the common fork
2921  */
2922  if( subroot == NULL )
2923  {
2924  if( tree->focussubroot != NULL && (int)(tree->focussubroot->depth) > fork->depth )
2925  {
2926  /* focussubroot is not on the same active path as the new node: we have to continue searching */
2927  if( lpstatefork != NULL && lpstatefork->depth < fork->depth )
2928  subroot = lpstatefork;
2929  else if( lpfork != NULL && lpfork->depth < fork->depth )
2930  subroot = lpfork;
2931  else
2932  subroot = fork;
2933  while( subroot != NULL && SCIPnodeGetType(subroot) != SCIP_NODETYPE_SUBROOT )
2934  {
2935  assert(subroot->active);
2936  subroot = subroot->parent;
2937  }
2938  }
2939  else
2940  subroot = tree->focussubroot;
2941  assert(subroot == NULL || subroot->depth <= fork->depth);
2942  assert(subroot == NULL || subroot->active);
2943  }
2944  assert(subroot == NULL || SCIPnodeGetType(subroot) == SCIP_NODETYPE_SUBROOT);
2945  assert(subroot == NULL || (lpstatefork != NULL && subroot->depth <= lpstatefork->depth));
2946  SCIPdebugMessage("find switch forks: subrootdepth=%d\n", subroot == NULL ? -1 : (int)(subroot->depth));
2947 
2948  /* if a node prior to the common fork should be repropagated, we select the node to be repropagated as common
2949  * fork in order to undo all bound changes up to this node, repropagate the node, and redo the bound changes
2950  * afterwards
2951  */
2952  if( (int)fork->depth > tree->repropdepth )
2953  {
2954  fork = tree->path[tree->repropdepth];
2955  assert(fork->active);
2956  assert(fork->reprop);
2957  }
2958 
2959  *commonfork = fork;
2960  *newlpfork = lpfork;
2961  *newlpstatefork = lpstatefork;
2962  *newsubroot = subroot;
2963 
2964 #ifndef NDEBUG
2965  while( fork != NULL )
2966  {
2967  assert(fork->active);
2968  assert(!fork->cutoff);
2969  assert(fork->parent == NULL || !fork->parent->reprop);
2970  fork = fork->parent;
2971  }
2972 #endif
2973  tree->repropdepth = INT_MAX;
2974 }
2975 
2976 /** switches the active path to the new focus node, applies domain and constraint set changes */
2977 static
2979  SCIP_TREE* tree, /**< branch and bound tree */
2980  SCIP_REOPT* reopt, /**< reoptimization data structure */
2981  BMS_BLKMEM* blkmem, /**< block memory buffers */
2982  SCIP_SET* set, /**< global SCIP settings */
2983  SCIP_STAT* stat, /**< problem statistics */
2984  SCIP_PROB* transprob, /**< transformed problem after presolve */
2985  SCIP_PROB* origprob, /**< original problem */
2986  SCIP_PRIMAL* primal, /**< primal data */
2987  SCIP_LP* lp, /**< current LP data */
2988  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2989  SCIP_CONFLICT* conflict, /**< conflict analysis data */
2990  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
2991  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2992  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2993  SCIP_NODE* fork, /**< common fork node of old and new focus node, or NULL */
2994  SCIP_NODE* focusnode, /**< new focus node, or NULL */
2995  SCIP_Bool* cutoff /**< pointer to store whether the new focus node can be cut off */
2996  )
2997 {
2998  int focusnodedepth; /* depth of the new focus node, or -1 if focusnode == NULL */
2999  int forkdepth; /* depth of the common subroot/fork/pseudofork/junction node, or -1 if no common fork exists */
3000  int i;
3001 
3002  assert(tree != NULL);
3003  assert(fork == NULL || (fork->active && !fork->cutoff));
3004  assert(fork == NULL || focusnode != NULL);
3005  assert(focusnode == NULL || (!focusnode->active && !focusnode->cutoff));
3006  assert(focusnode == NULL || SCIPnodeGetType(focusnode) == SCIP_NODETYPE_FOCUSNODE);
3007  assert(cutoff != NULL);
3008 
3009  *cutoff = FALSE;
3010 
3011  SCIPsetDebugMsg(set, "switch path: old pathlen=%d\n", tree->pathlen);
3012 
3013  /* get the nodes' depths */
3014  focusnodedepth = (focusnode != NULL ? (int)focusnode->depth : -1);
3015  forkdepth = (fork != NULL ? (int)fork->depth : -1);
3016  assert(forkdepth <= focusnodedepth);
3017  assert(forkdepth < tree->pathlen);
3018 
3019  /* delay events in path switching */
3020  SCIP_CALL( SCIPeventqueueDelay(eventqueue) );
3021 
3022  /* undo the domain and constraint set changes of the old active path by deactivating the path's nodes */
3023  for( i = tree->pathlen-1; i > forkdepth; --i )
3024  {
3025  SCIP_CALL( nodeDeactivate(tree->path[i], blkmem, set, stat, tree, lp, branchcand, eventqueue) );
3026  }
3027  tree->pathlen = forkdepth+1;
3028 
3029  /* apply the pending bound changes */
3030  SCIP_CALL( treeApplyPendingBdchgs(tree, reopt, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue, cliquetable) );
3031 
3032  /* create the new active path */
3033  SCIP_CALL( treeEnsurePathMem(tree, set, focusnodedepth+1) );
3034  while( focusnode != fork )
3035  {
3036  assert(focusnode != NULL);
3037  assert(!focusnode->active);
3038  assert(!focusnode->cutoff);
3039  tree->path[focusnode->depth] = focusnode;
3040  focusnode = focusnode->parent;
3041  }
3042 
3043  /* fork might be cut off when applying the pending bound changes */
3044  if( fork != NULL && fork->cutoff )
3045  *cutoff = TRUE;
3046  else if( fork != NULL && fork->reprop )
3047  {
3048  /* propagate common fork again, if the reprop flag is set */
3049  assert(tree->path[forkdepth] == fork);
3050  assert(fork->active);
3051  assert(!fork->cutoff);
3052 
3053  SCIP_CALL( nodeRepropagate(fork, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, conflict,
3054  eventfilter, eventqueue, cliquetable, cutoff) );
3055  }
3056  assert(fork != NULL || !(*cutoff));
3057 
3058  /* Apply domain and constraint set changes of the new path by activating the path's nodes;
3059  * on the way, domain propagation might be applied again to the path's nodes, which can result in the cutoff of
3060  * the node (and its subtree).
3061  * We only activate all nodes down to the parent of the new focus node, because the events in this process are
3062  * delayed, which means that multiple changes of a bound of a variable are merged (and might even be cancelled out,
3063  * if the bound is first relaxed when deactivating a node on the old path and then tightened to the same value
3064  * when activating a node on the new path).
3065  * This is valid for all nodes down to the parent of the new focus node, since they have already been propagated.
3066  * Bound change events on the new focus node, however, must not be cancelled out, since they need to be propagated
3067  * and thus, the event must be thrown and catched by the constraint handlers to mark constraints for propagation.
3068  */
3069  for( i = forkdepth+1; i < focusnodedepth && !(*cutoff); ++i )
3070  {
3071  assert(!tree->path[i]->cutoff);
3072  assert(tree->pathlen == i);
3073 
3074  /* activate the node, and apply domain propagation if the reprop flag is set */
3075  tree->pathlen++;
3076  SCIP_CALL( nodeActivate(tree->path[i], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
3077  conflict, eventfilter, eventqueue, cliquetable, cutoff) );
3078  }
3079 
3080  /* process the delayed events */
3081  SCIP_CALL( SCIPeventqueueProcess(eventqueue, blkmem, set, primal, lp, branchcand, eventfilter) );
3082 
3083  /* activate the new focus node; there is no need to delay these events */
3084  if( !(*cutoff) && (i == focusnodedepth) )
3085  {
3086  assert(!tree->path[focusnodedepth]->cutoff);
3087  assert(tree->pathlen == focusnodedepth);
3088 
3089  /* activate the node, and apply domain propagation if the reprop flag is set */
3090  tree->pathlen++;
3091  SCIP_CALL( nodeActivate(tree->path[focusnodedepth], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
3092  conflict, eventfilter, eventqueue, cliquetable, cutoff) );
3093  }
3094 
3095  /* mark last node of path to be cut off, if a cutoff was found */
3096  if( *cutoff )
3097  {
3098  assert(tree->pathlen > 0);
3099  assert(tree->path[tree->pathlen-1]->active);
3100  SCIP_CALL( SCIPnodeCutoff(tree->path[tree->pathlen-1], set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
3101  }
3102 
3103  /* count the new LP sizes of the path */
3104  SCIP_CALL( treeUpdatePathLPSize(tree, forkdepth+1) );
3105 
3106  SCIPsetDebugMsg(set, "switch path: new pathlen=%d\n", tree->pathlen);
3107 
3108  return SCIP_OKAY;
3109 }
3110 
3111 /** loads the subroot's LP data */
3112 static
3114  SCIP_NODE* subroot, /**< subroot node to construct LP for */
3115  BMS_BLKMEM* blkmem, /**< block memory buffers */
3116  SCIP_SET* set, /**< global SCIP settings */
3117  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3118  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
3119  SCIP_LP* lp /**< current LP data */
3120  )
3121 {
3122  SCIP_COL** cols;
3123  SCIP_ROW** rows;
3124  int ncols;
3125  int nrows;
3126  int c;
3127  int r;
3128 
3129  assert(subroot != NULL);
3130  assert(SCIPnodeGetType(subroot) == SCIP_NODETYPE_SUBROOT);
3131  assert(subroot->data.subroot != NULL);
3132  assert(blkmem != NULL);
3133  assert(set != NULL);
3134  assert(lp != NULL);
3135 
3136  cols = subroot->data.subroot->cols;
3137  rows = subroot->data.subroot->rows;
3138  ncols = subroot->data.subroot->ncols;
3139  nrows = subroot->data.subroot->nrows;
3140 
3141  assert(ncols == 0 || cols != NULL);
3142  assert(nrows == 0 || rows != NULL);
3143 
3144  for( c = 0; c < ncols; ++c )
3145  {
3146  SCIP_CALL( SCIPlpAddCol(lp, set, cols[c], subroot->depth) );
3147  }
3148  for( r = 0; r < nrows; ++r )
3149  {
3150  SCIP_CALL( SCIPlpAddRow(lp, blkmem, set, eventqueue, eventfilter, rows[r], subroot->depth) );
3151  }
3152 
3153  return SCIP_OKAY;
3154 }
3155 
3156 /** loads the fork's additional LP data */
3157 static
3159  SCIP_NODE* fork, /**< fork node to construct additional LP for */
3160  BMS_BLKMEM* blkmem, /**< block memory buffers */
3161  SCIP_SET* set, /**< global SCIP settings */
3162  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3163  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
3164  SCIP_LP* lp /**< current LP data */
3165  )
3166 {
3167  SCIP_COL** cols;
3168  SCIP_ROW** rows;
3169  int ncols;
3170  int nrows;
3171  int c;
3172  int r;
3173 
3174  assert(fork != NULL);
3175  assert(SCIPnodeGetType(fork) == SCIP_NODETYPE_FORK);
3176  assert(fork->data.fork != NULL);
3177  assert(blkmem != NULL);
3178  assert(set != NULL);
3179  assert(lp != NULL);
3180 
3181  cols = fork->data.fork->addedcols;
3182  rows = fork->data.fork->addedrows;
3183  ncols = fork->data.fork->naddedcols;
3184  nrows = fork->data.fork->naddedrows;
3185 
3186  assert(ncols == 0 || cols != NULL);
3187  assert(nrows == 0 || rows != NULL);
3188 
3189  for( c = 0; c < ncols; ++c )
3190  {
3191  SCIP_CALL( SCIPlpAddCol(lp, set, cols[c], fork->depth) );
3192  }
3193  for( r = 0; r < nrows; ++r )
3194  {
3195  SCIP_CALL( SCIPlpAddRow(lp, blkmem, set, eventqueue, eventfilter, rows[r], fork->depth) );
3196  }
3197 
3198  return SCIP_OKAY;
3199 }
3200 
3201 /** loads the pseudofork's additional LP data */
3202 static
3204  SCIP_NODE* pseudofork, /**< pseudofork node to construct additional LP for */
3205  BMS_BLKMEM* blkmem, /**< block memory buffers */
3206  SCIP_SET* set, /**< global SCIP settings */
3207  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3208  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
3209  SCIP_LP* lp /**< current LP data */
3210  )
3211 {
3212  SCIP_COL** cols;
3213  SCIP_ROW** rows;
3214  int ncols;
3215  int nrows;
3216  int c;
3217  int r;
3218 
3219  assert(pseudofork != NULL);
3220  assert(SCIPnodeGetType(pseudofork) == SCIP_NODETYPE_PSEUDOFORK);
3221  assert(pseudofork->data.pseudofork != NULL);
3222  assert(blkmem != NULL);
3223  assert(set != NULL);
3224  assert(lp != NULL);
3225 
3226  cols = pseudofork->data.pseudofork->addedcols;
3227  rows = pseudofork->data.pseudofork->addedrows;
3228  ncols = pseudofork->data.pseudofork->naddedcols;
3229  nrows = pseudofork->data.pseudofork->naddedrows;
3230 
3231  assert(ncols == 0 || cols != NULL);
3232  assert(nrows == 0 || rows != NULL);
3233 
3234  for( c = 0; c < ncols; ++c )
3235  {
3236  SCIP_CALL( SCIPlpAddCol(lp, set, cols[c], pseudofork->depth) );
3237  }
3238  for( r = 0; r < nrows; ++r )
3239  {
3240  SCIP_CALL( SCIPlpAddRow(lp, blkmem, set, eventqueue, eventfilter, rows[r], pseudofork->depth) );
3241  }
3242 
3243  return SCIP_OKAY;
3244 }
3245 
3246 #ifndef NDEBUG
3247 /** checks validity of active path */
3248 static
3250  SCIP_TREE* tree /**< branch and bound tree */
3251  )
3252 {
3253  SCIP_NODE* node;
3254  int ncols;
3255  int nrows;
3256  int d;
3257 
3258  assert(tree != NULL);
3259  assert(tree->path != NULL);
3260 
3261  ncols = 0;
3262  nrows = 0;
3263  for( d = 0; d < tree->pathlen; ++d )
3264  {
3265  node = tree->path[d];
3266  assert(node != NULL);
3267  assert((int)(node->depth) == d);
3268  switch( SCIPnodeGetType(node) )
3269  {
3271  assert(SCIPtreeProbing(tree));
3272  assert(d >= 1);
3273  assert(SCIPnodeGetType(tree->path[d-1]) == SCIP_NODETYPE_FOCUSNODE
3274  || (ncols == node->data.probingnode->ninitialcols && nrows == node->data.probingnode->ninitialrows));
3275  assert(ncols <= node->data.probingnode->ncols || !tree->focuslpconstructed);
3276  assert(nrows <= node->data.probingnode->nrows || !tree->focuslpconstructed);
3277  if( d < tree->pathlen-1 )
3278  {
3279  ncols = node->data.probingnode->ncols;
3280  nrows = node->data.probingnode->nrows;
3281  }
3282  else
3283  {
3284  /* for the current probing node, the initial LP size is stored in the path */
3285  ncols = node->data.probingnode->ninitialcols;
3286  nrows = node->data.probingnode->ninitialrows;
3287  }
3288  break;
3290  break;
3292  ncols += node->data.pseudofork->naddedcols;
3293  nrows += node->data.pseudofork->naddedrows;
3294  break;
3295  case SCIP_NODETYPE_FORK:
3296  ncols += node->data.fork->naddedcols;
3297  nrows += node->data.fork->naddedrows;
3298  break;
3299  case SCIP_NODETYPE_SUBROOT:
3300  ncols = node->data.subroot->ncols;
3301  nrows = node->data.subroot->nrows;
3302  break;
3305  assert(d == tree->pathlen-1 || SCIPtreeProbing(tree));
3306  break;
3307  default:
3308  SCIPerrorMessage("node at depth %d on active path has to be of type JUNCTION, PSEUDOFORK, FORK, SUBROOT, FOCUSNODE, REFOCUSNODE, or PROBINGNODE, but is %d\n",
3309  d, SCIPnodeGetType(node));
3310  SCIPABORT();
3311  } /*lint !e788*/
3312  assert(tree->pathnlpcols[d] == ncols);
3313  assert(tree->pathnlprows[d] == nrows);
3314  }
3315 }
3316 #else
3317 #define treeCheckPath(tree) /**/
3318 #endif
3319 
3320 /** constructs the LP relaxation of the focus node */
3322  SCIP_TREE* tree, /**< branch and bound tree */
3323  BMS_BLKMEM* blkmem, /**< block memory buffers */
3324  SCIP_SET* set, /**< global SCIP settings */
3325  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3326  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
3327  SCIP_LP* lp, /**< current LP data */
3328  SCIP_Bool* initroot /**< pointer to store whether the root LP relaxation has to be initialized */
3329  )
3330 {
3331  SCIP_NODE* lpfork;
3332  int lpforkdepth;
3333  int d;
3334 
3335  assert(tree != NULL);
3336  assert(!tree->focuslpconstructed);
3337  assert(tree->path != NULL);
3338  assert(tree->pathlen > 0);
3339  assert(tree->focusnode != NULL);
3341  assert(SCIPnodeGetDepth(tree->focusnode) == tree->pathlen-1);
3342  assert(!SCIPtreeProbing(tree));
3343  assert(tree->focusnode == tree->path[tree->pathlen-1]);
3344  assert(blkmem != NULL);
3345  assert(set != NULL);
3346  assert(lp != NULL);
3347  assert(initroot != NULL);
3348 
3349  SCIPsetDebugMsg(set, "load LP for current fork node #%" SCIP_LONGINT_FORMAT " at depth %d\n",
3350  tree->focuslpfork == NULL ? -1 : SCIPnodeGetNumber(tree->focuslpfork),
3351  tree->focuslpfork == NULL ? -1 : SCIPnodeGetDepth(tree->focuslpfork));
3352  SCIPsetDebugMsg(set, "-> old LP has %d cols and %d rows\n", SCIPlpGetNCols(lp), SCIPlpGetNRows(lp));
3353  SCIPsetDebugMsg(set, "-> correct LP has %d cols and %d rows\n",
3354  tree->correctlpdepth >= 0 ? tree->pathnlpcols[tree->correctlpdepth] : 0,
3355  tree->correctlpdepth >= 0 ? tree->pathnlprows[tree->correctlpdepth] : 0);
3356  SCIPsetDebugMsg(set, "-> old correctlpdepth: %d\n", tree->correctlpdepth);
3357 
3358  treeCheckPath(tree);
3359 
3360  lpfork = tree->focuslpfork;
3361 
3362  /* find out the lpfork's depth (or -1, if lpfork is NULL) */
3363  if( lpfork == NULL )
3364  {
3365  assert(tree->correctlpdepth == -1 || tree->pathnlpcols[tree->correctlpdepth] == 0);
3366  assert(tree->correctlpdepth == -1 || tree->pathnlprows[tree->correctlpdepth] == 0);
3367  assert(tree->focuslpstatefork == NULL);
3368  assert(tree->focussubroot == NULL);
3369  lpforkdepth = -1;
3370  }
3371  else
3372  {
3373  assert(SCIPnodeGetType(lpfork) == SCIP_NODETYPE_PSEUDOFORK
3375  assert(lpfork->active);
3376  assert(tree->path[lpfork->depth] == lpfork);
3377  lpforkdepth = lpfork->depth;
3378  }
3379  assert(lpforkdepth < tree->pathlen-1); /* lpfork must not be the last (the focus) node of the active path */
3380 
3381  /* find out, if we are in the same subtree */
3382  if( tree->correctlpdepth >= 0 )
3383  {
3384  /* same subtree: shrink LP to the deepest node with correct LP */
3385  assert(lpforkdepth == -1 || tree->pathnlpcols[tree->correctlpdepth] <= tree->pathnlpcols[lpforkdepth]);
3386  assert(lpforkdepth == -1 || tree->pathnlprows[tree->correctlpdepth] <= tree->pathnlprows[lpforkdepth]);
3387  assert(lpforkdepth >= 0 || tree->pathnlpcols[tree->correctlpdepth] == 0);
3388  assert(lpforkdepth >= 0 || tree->pathnlprows[tree->correctlpdepth] == 0);
3389  SCIP_CALL( SCIPlpShrinkCols(lp, set, tree->pathnlpcols[tree->correctlpdepth]) );
3390  SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, tree->pathnlprows[tree->correctlpdepth]) );
3391  }
3392  else
3393  {
3394  /* other subtree: fill LP with the subroot LP data */
3395  SCIP_CALL( SCIPlpClear(lp, blkmem, set, eventqueue, eventfilter) );
3396  if( tree->focussubroot != NULL )
3397  {
3398  SCIP_CALL( subrootConstructLP(tree->focussubroot, blkmem, set, eventqueue, eventfilter, lp) );
3399  tree->correctlpdepth = tree->focussubroot->depth;
3400  }
3401  }
3402 
3403  assert(lpforkdepth < tree->pathlen);
3404 
3405  /* add the missing columns and rows */
3406  for( d = tree->correctlpdepth+1; d <= lpforkdepth; ++d )
3407  {
3408  SCIP_NODE* pathnode;
3409 
3410  pathnode = tree->path[d];
3411  assert(pathnode != NULL);
3412  assert((int)(pathnode->depth) == d);
3413  assert(SCIPnodeGetType(pathnode) == SCIP_NODETYPE_JUNCTION
3415  || SCIPnodeGetType(pathnode) == SCIP_NODETYPE_FORK);
3416  if( SCIPnodeGetType(pathnode) == SCIP_NODETYPE_FORK )
3417  {
3418  SCIP_CALL( forkAddLP(pathnode, blkmem, set, eventqueue, eventfilter, lp) );
3419  }
3420  else if( SCIPnodeGetType(pathnode) == SCIP_NODETYPE_PSEUDOFORK )
3421  {
3422  SCIP_CALL( pseudoforkAddLP(pathnode, blkmem, set, eventqueue, eventfilter, lp) );
3423  }
3424  }
3425  tree->correctlpdepth = MAX(tree->correctlpdepth, lpforkdepth);
3426  assert(lpforkdepth == -1 || tree->pathnlpcols[tree->correctlpdepth] == tree->pathnlpcols[lpforkdepth]);
3427  assert(lpforkdepth == -1 || tree->pathnlprows[tree->correctlpdepth] == tree->pathnlprows[lpforkdepth]);
3428  assert(lpforkdepth == -1 || SCIPlpGetNCols(lp) == tree->pathnlpcols[lpforkdepth]);
3429  assert(lpforkdepth == -1 || SCIPlpGetNRows(lp) == tree->pathnlprows[lpforkdepth]);
3430  assert(lpforkdepth >= 0 || SCIPlpGetNCols(lp) == 0);
3431  assert(lpforkdepth >= 0 || SCIPlpGetNRows(lp) == 0);
3432 
3433  /* mark the LP's size, such that we know which rows and columns were added in the new node */
3434  SCIPlpMarkSize(lp);
3435 
3436  SCIPsetDebugMsg(set, "-> new correctlpdepth: %d\n", tree->correctlpdepth);
3437  SCIPsetDebugMsg(set, "-> new LP has %d cols and %d rows\n", SCIPlpGetNCols(lp), SCIPlpGetNRows(lp));
3438 
3439  /* if the correct LP depth is still -1, the root LP relaxation has to be initialized */
3440  *initroot = (tree->correctlpdepth == -1);
3441 
3442  /* mark the LP of the focus node constructed */
3443  tree->focuslpconstructed = TRUE;
3444 
3445  return SCIP_OKAY;
3446 }
3447 
3448 /** loads LP state for fork/subroot of the focus node */
3450  SCIP_TREE* tree, /**< branch and bound tree */
3451  BMS_BLKMEM* blkmem, /**< block memory buffers */
3452  SCIP_SET* set, /**< global SCIP settings */
3453  SCIP_STAT* stat, /**< dynamic problem statistics */
3454  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3455  SCIP_LP* lp /**< current LP data */
3456  )
3457 {
3458  SCIP_NODE* lpstatefork;
3459  SCIP_Bool updatefeas;
3460  SCIP_Bool checkbdchgs;
3461  int lpstateforkdepth;
3462  int d;
3463 
3464  assert(tree != NULL);
3465  assert(tree->focuslpconstructed);
3466  assert(tree->path != NULL);
3467  assert(tree->pathlen > 0);
3468  assert(tree->focusnode != NULL);
3469  assert(tree->correctlpdepth < tree->pathlen);
3471  assert(SCIPnodeGetDepth(tree->focusnode) == tree->pathlen-1);
3472  assert(!SCIPtreeProbing(tree));
3473  assert(tree->focusnode == tree->path[tree->pathlen-1]);
3474  assert(blkmem != NULL);
3475  assert(set != NULL);
3476  assert(lp != NULL);
3477 
3478  SCIPsetDebugMsg(set, "load LP state for current fork node #%" SCIP_LONGINT_FORMAT " at depth %d\n",
3480  tree->focuslpstatefork == NULL ? -1 : SCIPnodeGetDepth(tree->focuslpstatefork));
3481 
3482  lpstatefork = tree->focuslpstatefork;
3483 
3484  /* if there is no LP state defining fork, nothing can be done */
3485  if( lpstatefork == NULL )
3486  return SCIP_OKAY;
3487 
3488  /* get the lpstatefork's depth */
3489  assert(SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_FORK || SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_SUBROOT);
3490  assert(lpstatefork->active);
3491  assert(tree->path[lpstatefork->depth] == lpstatefork);
3492  lpstateforkdepth = lpstatefork->depth;
3493  assert(lpstateforkdepth < tree->pathlen-1); /* lpstatefork must not be the last (the focus) node of the active path */
3494  assert(lpstateforkdepth <= tree->correctlpdepth); /* LP must have been constructed at least up to the fork depth */
3495  assert(tree->pathnlpcols[tree->correctlpdepth] >= tree->pathnlpcols[lpstateforkdepth]); /* LP can only grow */
3496  assert(tree->pathnlprows[tree->correctlpdepth] >= tree->pathnlprows[lpstateforkdepth]); /* LP can only grow */
3497 
3498  /* load LP state */
3499  if( tree->focuslpstateforklpcount != stat->lpcount )
3500  {
3501  if( SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_FORK )
3502  {
3503  assert(lpstatefork->data.fork != NULL);
3504  SCIP_CALL( SCIPlpSetState(lp, blkmem, set, eventqueue, lpstatefork->data.fork->lpistate,
3505  lpstatefork->data.fork->lpwasprimfeas, lpstatefork->data.fork->lpwasprimchecked,
3506  lpstatefork->data.fork->lpwasdualfeas, lpstatefork->data.fork->lpwasdualchecked) );
3507  }
3508  else
3509  {
3510  assert(SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_SUBROOT);
3511  assert(lpstatefork->data.subroot != NULL);
3512  SCIP_CALL( SCIPlpSetState(lp, blkmem, set, eventqueue, lpstatefork->data.subroot->lpistate,
3513  lpstatefork->data.subroot->lpwasprimfeas, lpstatefork->data.subroot->lpwasprimchecked,
3514  lpstatefork->data.subroot->lpwasdualfeas, lpstatefork->data.subroot->lpwasdualchecked) );
3515  }
3516  updatefeas = !lp->solved || !lp->solisbasic;
3517  checkbdchgs = TRUE;
3518  }
3519  else
3520  {
3521  updatefeas = TRUE;
3522 
3523  /* we do not need to check the bounds, since primalfeasible is updated anyway when flushing the LP */
3524  checkbdchgs = FALSE;
3525  }
3526 
3527  if( updatefeas )
3528  {
3529  /* check whether the size of the LP increased (destroying primal/dual feasibility) */
3530  lp->primalfeasible = lp->primalfeasible
3531  && (tree->pathnlprows[tree->correctlpdepth] == tree->pathnlprows[lpstateforkdepth]);
3532  lp->primalchecked = lp->primalchecked
3533  && (tree->pathnlprows[tree->correctlpdepth] == tree->pathnlprows[lpstateforkdepth]);
3534  lp->dualfeasible = lp->dualfeasible
3535  && (tree->pathnlpcols[tree->correctlpdepth] == tree->pathnlpcols[lpstateforkdepth]);
3536  lp->dualchecked = lp->dualchecked
3537  && (tree->pathnlpcols[tree->correctlpdepth] == tree->pathnlpcols[lpstateforkdepth]);
3538 
3539  /* check the path from LP fork to focus node for domain changes (destroying primal feasibility of LP basis) */
3540  if( checkbdchgs )
3541  {
3542  for( d = lpstateforkdepth; d < (int)(tree->focusnode->depth) && lp->primalfeasible; ++d )
3543  {
3544  assert(d < tree->pathlen);
3545  lp->primalfeasible = (tree->path[d]->domchg == NULL || tree->path[d]->domchg->domchgbound.nboundchgs == 0);
3546  lp->primalchecked = lp->primalfeasible;
3547  }
3548  }
3549  }
3550 
3551  SCIPsetDebugMsg(set, "-> primalfeasible=%u, dualfeasible=%u\n", lp->primalfeasible, lp->dualfeasible);
3552 
3553  return SCIP_OKAY;
3554 }
3555 
3556 
3557 
3558 
3559 /*
3560  * Node Conversion
3561  */
3562 
3563 /** converts node into LEAF and moves it into the array of the node queue
3564  * if node's lower bound is greater or equal than the given upper bound, the node is deleted;
3565  * otherwise, it is moved to the node queue; anyways, the given pointer is NULL after the call
3566  */
3567 static
3569  SCIP_NODE** node, /**< pointer to child or sibling node to convert */
3570  BMS_BLKMEM* blkmem, /**< block memory buffers */
3571  SCIP_SET* set, /**< global SCIP settings */
3572  SCIP_STAT* stat, /**< dynamic problem statistics */
3573  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3574  SCIP_TREE* tree, /**< branch and bound tree */
3575  SCIP_REOPT* reopt, /**< reoptimization data structure */
3576  SCIP_LP* lp, /**< current LP data */
3577  SCIP_NODE* lpstatefork, /**< LP state defining fork of the node */
3578  SCIP_Real cutoffbound /**< cutoff bound: all nodes with lowerbound >= cutoffbound are cut off */
3579  )
3580 {
3583  assert(stat != NULL);
3584  assert(lpstatefork == NULL || lpstatefork->depth < (*node)->depth);
3585  assert(lpstatefork == NULL || lpstatefork->active || SCIPsetIsGE(set, (*node)->lowerbound, cutoffbound));
3586  assert(lpstatefork == NULL
3587  || SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_FORK
3588  || SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_SUBROOT);
3589 
3590  /* convert node into leaf */
3591  SCIPsetDebugMsg(set, "convert node #%" SCIP_LONGINT_FORMAT " at depth %d to leaf with lpstatefork #%" SCIP_LONGINT_FORMAT " at depth %d\n",
3592  SCIPnodeGetNumber(*node), SCIPnodeGetDepth(*node),
3593  lpstatefork == NULL ? -1 : SCIPnodeGetNumber(lpstatefork),
3594  lpstatefork == NULL ? -1 : SCIPnodeGetDepth(lpstatefork));
3595  (*node)->nodetype = SCIP_NODETYPE_LEAF; /*lint !e641*/
3596  (*node)->data.leaf.lpstatefork = lpstatefork;
3597 
3598 #ifndef NDEBUG
3599  /* check, if the LP state fork is the first node with LP state information on the path back to the root */
3600  if( !SCIPsetIsInfinity(set, -cutoffbound) ) /* if the node was cut off in SCIPnodeFocus(), the lpstatefork is invalid */
3601  {
3602  SCIP_NODE* pathnode;
3603  pathnode = (*node)->parent;
3604  while( pathnode != NULL && pathnode != lpstatefork )
3605  {
3606  assert(SCIPnodeGetType(pathnode) == SCIP_NODETYPE_JUNCTION
3607  || SCIPnodeGetType(pathnode) == SCIP_NODETYPE_PSEUDOFORK);
3608  pathnode = pathnode->parent;
3609  }
3610  assert(pathnode == lpstatefork);
3611  }
3612 #endif
3613 
3614  /* if node is good enough to keep, put it on the node queue */
3615  if( SCIPsetIsLT(set, (*node)->lowerbound, cutoffbound) )
3616  {
3617  /* insert leaf in node queue */
3618  SCIP_CALL( SCIPnodepqInsert(tree->leaves, set, *node) );
3619 
3620  /* make the domain change data static to save memory */
3621  SCIP_CALL( SCIPdomchgMakeStatic(&(*node)->domchg, blkmem, set, eventqueue, lp) );
3622 
3623  /* node is now member of the node queue: delete the pointer to forbid further access */
3624  *node = NULL;
3625  }
3626  else
3627  {
3628  if( set->reopt_enable )
3629  {
3630  assert(reopt != NULL);
3631  /* check if the node should be stored for reoptimization */
3633  tree->root == *node, tree->focusnode == *node, (*node)->lowerbound, tree->effectiverootdepth) );
3634  }
3635 
3636  /* delete node due to bound cut off */
3637  SCIPvisualCutoffNode(stat->visual, set, stat, *node, FALSE);
3638  SCIP_CALL( SCIPnodeFree(node, blkmem, set, stat, eventqueue, tree, lp) );
3639  }
3640  assert(*node == NULL);
3641 
3642  return SCIP_OKAY;
3643 }
3644 
3645 /** removes variables from the problem, that are marked to be deletable, and were created at the focusnode;
3646  * only removes variables that were created at the focusnode, unless inlp is TRUE (e.g., when the node is cut off, anyway)
3647  */
3648 static
3650  BMS_BLKMEM* blkmem, /**< block memory buffers */
3651  SCIP_SET* set, /**< global SCIP settings */
3652  SCIP_STAT* stat, /**< dynamic problem statistics */
3653  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3654  SCIP_PROB* transprob, /**< transformed problem after presolve */
3655  SCIP_PROB* origprob, /**< original problem */
3656  SCIP_TREE* tree, /**< branch and bound tree */
3657  SCIP_REOPT* reopt, /**< reoptimization data structure */
3658  SCIP_LP* lp, /**< current LP data */
3659  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3660  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3661  SCIP_Bool inlp /**< should variables in the LP be deleted, too?*/
3662  )
3663 {
3664  SCIP_VAR* var;
3665  int i;
3666  int ndelvars;
3667  SCIP_Bool needdel;
3668  SCIP_Bool deleted;
3669 
3670  assert(blkmem != NULL);
3671  assert(set != NULL);
3672  assert(stat != NULL);
3673  assert(tree != NULL);
3674  assert(!SCIPtreeProbing(tree));
3675  assert(tree->focusnode != NULL);
3677  assert(lp != NULL);
3678 
3679  /* check the settings, whether variables should be deleted */
3680  needdel = (tree->focusnode == tree->root ? set->price_delvarsroot : set->price_delvars);
3681 
3682  if( !needdel )
3683  return SCIP_OKAY;
3684 
3685  ndelvars = 0;
3686 
3687  /* also delete variables currently in the LP, thus remove all new variables from the LP, first */
3688  if( inlp )
3689  {
3690  /* remove all additions to the LP at this node */
3692 
3693  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
3694  }
3695 
3696  /* mark variables as deleted */
3697  for( i = 0; i < transprob->nvars; i++ )
3698  {
3699  var = transprob->vars[i];
3700  assert(var != NULL);
3701 
3702  /* check whether variable is deletable */
3703  if( SCIPvarIsDeletable(var) )
3704  {
3705  if( !SCIPvarIsInLP(var) )
3706  {
3707  /* fix the variable to 0, first */
3708  assert(!SCIPsetIsFeasPositive(set, SCIPvarGetLbGlobal(var)));
3709  assert(!SCIPsetIsFeasNegative(set, SCIPvarGetUbGlobal(var)));
3710 
3711  if( !SCIPsetIsFeasZero(set, SCIPvarGetLbGlobal(var)) )
3712  {
3713  SCIP_CALL( SCIPnodeAddBoundchg(tree->root, blkmem, set, stat, transprob, origprob,
3714  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
3715  }
3716  if( !SCIPsetIsFeasZero(set, SCIPvarGetUbGlobal(var)) )
3717  {
3718  SCIP_CALL( SCIPnodeAddBoundchg(tree->root, blkmem, set, stat, transprob, origprob,
3719  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
3720  }
3721 
3722  SCIP_CALL( SCIPprobDelVar(transprob, blkmem, set, eventqueue, var, &deleted) );
3723 
3724  if( deleted )
3725  ndelvars++;
3726  }
3727  else
3728  {
3729  /* mark variable to be non-deletable, because it will be contained in the basis information
3730  * at this node and must not be deleted from now on
3731  */
3733  }
3734  }
3735  }
3736 
3737  SCIPsetDebugMsg(set, "delvars at node %" SCIP_LONGINT_FORMAT ", deleted %d vars\n", stat->nnodes, ndelvars);
3738 
3739  if( ndelvars > 0 )
3740  {
3741  /* perform the variable deletions from the problem */
3742  SCIP_CALL( SCIPprobPerformVarDeletions(transprob, blkmem, set, stat, eventqueue, cliquetable, lp, branchcand) );
3743  }
3744 
3745  return SCIP_OKAY;
3746 }
3747 
3748 /** converts the focus node into a dead-end node */
3749 static
3751  BMS_BLKMEM* blkmem, /**< block memory buffers */
3752  SCIP_SET* set, /**< global SCIP settings */
3753  SCIP_STAT* stat, /**< dynamic problem statistics */
3754  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3755  SCIP_PROB* transprob, /**< transformed problem after presolve */
3756  SCIP_PROB* origprob, /**< original problem */
3757  SCIP_TREE* tree, /**< branch and bound tree */
3758  SCIP_REOPT* reopt, /**< reoptimization data structure */
3759  SCIP_LP* lp, /**< current LP data */
3760  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3761  SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
3762  )
3763 {
3764  assert(blkmem != NULL);
3765  assert(tree != NULL);
3766  assert(!SCIPtreeProbing(tree));
3767  assert(tree->focusnode != NULL);
3769  assert(tree->nchildren == 0);
3770 
3771  SCIPsetDebugMsg(set, "focusnode #%" SCIP_LONGINT_FORMAT " to dead-end at depth %d\n",
3773 
3774  /* remove variables from the problem that are marked as deletable and were created at this node */
3775  SCIP_CALL( focusnodeCleanupVars(blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp, branchcand, cliquetable, TRUE) );
3776 
3777  tree->focusnode->nodetype = SCIP_NODETYPE_DEADEND; /*lint !e641*/
3778 
3779  /* release LPI state */
3780  if( tree->focuslpstatefork != NULL )
3781  {
3782  SCIP_CALL( SCIPnodeReleaseLPIState(tree->focuslpstatefork, blkmem, lp) );
3783  }
3784 
3785  return SCIP_OKAY;
3786 }
3787 
3788 /** converts the focus node into a leaf node (if it was postponed) */
3789 static
3791  BMS_BLKMEM* blkmem, /**< block memory buffers */
3792  SCIP_SET* set, /**< global SCIP settings */
3793  SCIP_STAT* stat, /**< dynamic problem statistics */
3794  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3795  SCIP_TREE* tree, /**< branch and bound tree */
3796  SCIP_REOPT* reopt, /**< reoptimization data structure */
3797  SCIP_LP* lp, /**< current LP data */
3798  SCIP_NODE* lpstatefork, /**< LP state defining fork of the node */
3799  SCIP_Real cutoffbound /**< cutoff bound: all nodes with lowerbound >= cutoffbound are cut off */
3800 
3801  )
3802 {
3803  assert(tree != NULL);
3804  assert(!SCIPtreeProbing(tree));
3805  assert(tree->focusnode != NULL);
3806  assert(tree->focusnode->active);
3808 
3809  SCIPsetDebugMsg(set, "focusnode #%" SCIP_LONGINT_FORMAT " to leaf at depth %d\n",
3811 
3812  SCIP_CALL( nodeToLeaf(&tree->focusnode, blkmem, set, stat, eventqueue, tree, reopt, lp, lpstatefork, cutoffbound));
3813 
3814  return SCIP_OKAY;
3815 }
3816 
3817 /** converts the focus node into a junction node */
3818 static
3820  BMS_BLKMEM* blkmem, /**< block memory buffers */
3821  SCIP_SET* set, /**< global SCIP settings */
3822  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3823  SCIP_TREE* tree, /**< branch and bound tree */
3824  SCIP_LP* lp /**< current LP data */
3825  )
3826 {
3827  assert(tree != NULL);
3828  assert(!SCIPtreeProbing(tree));
3829  assert(tree->focusnode != NULL);
3830  assert(tree->focusnode->active); /* otherwise, no children could be created at the focus node */
3832  assert(SCIPlpGetNNewcols(lp) == 0);
3833 
3834  SCIPsetDebugMsg(set, "focusnode #%" SCIP_LONGINT_FORMAT " to junction at depth %d\n",
3836 
3837  /* convert node into junction */
3838  tree->focusnode->nodetype = SCIP_NODETYPE_JUNCTION; /*lint !e641*/
3839 
3840  SCIP_CALL( junctionInit(&tree->focusnode->data.junction, tree) );
3841 
3842  /* release LPI state */
3843  if( tree->focuslpstatefork != NULL )
3844  {
3845  SCIP_CALL( SCIPnodeReleaseLPIState(tree->focuslpstatefork, blkmem, lp) );
3846  }
3847 
3848  /* make the domain change data static to save memory */
3849  SCIP_CALL( SCIPdomchgMakeStatic(&tree->focusnode->domchg, blkmem, set, eventqueue, lp) );
3850 
3851  return SCIP_OKAY;
3852 }
3853 
3854 /** converts the focus node into a pseudofork node */
3855 static
3857  BMS_BLKMEM* blkmem, /**< block memory buffers */
3858  SCIP_SET* set, /**< global SCIP settings */
3859  SCIP_STAT* stat, /**< dynamic problem statistics */
3860  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3861  SCIP_PROB* transprob, /**< transformed problem after presolve */
3862  SCIP_PROB* origprob, /**< original problem */
3863  SCIP_TREE* tree, /**< branch and bound tree */
3864  SCIP_REOPT* reopt, /**< reoptimization data structure */
3865  SCIP_LP* lp, /**< current LP data */
3866  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3867  SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
3868  )
3869 {
3870  SCIP_PSEUDOFORK* pseudofork;
3871 
3872  assert(blkmem != NULL);
3873  assert(tree != NULL);
3874  assert(!SCIPtreeProbing(tree));
3875  assert(tree->focusnode != NULL);
3876  assert(tree->focusnode->active); /* otherwise, no children could be created at the focus node */
3878  assert(tree->nchildren > 0);
3879  assert(lp != NULL);
3880 
3881  SCIPsetDebugMsg(set, "focusnode #%" SCIP_LONGINT_FORMAT " to pseudofork at depth %d\n",
3883 
3884  /* remove variables from the problem that are marked as deletable and were created at this node */
3885  SCIP_CALL( focusnodeCleanupVars(blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp, branchcand, cliquetable, FALSE) );
3886 
3887  /* create pseudofork data */
3888  SCIP_CALL( pseudoforkCreate(&pseudofork, blkmem, tree, lp) );
3889 
3890  tree->focusnode->nodetype = SCIP_NODETYPE_PSEUDOFORK; /*lint !e641*/
3891  tree->focusnode->data.pseudofork = pseudofork;
3892 
3893  /* release LPI state */
3894  if( tree->focuslpstatefork != NULL )
3895  {
3896  SCIP_CALL( SCIPnodeReleaseLPIState(tree->focuslpstatefork, blkmem, lp) );
3897  }
3898 
3899  /* make the domain change data static to save memory */
3900  SCIP_CALL( SCIPdomchgMakeStatic(&tree->focusnode->domchg, blkmem, set, eventqueue, lp) );
3901 
3902  return SCIP_OKAY;
3903 }
3904 
3905 /** converts the focus node into a fork node */
3906 static
3908  BMS_BLKMEM* blkmem, /**< block memory buffers */
3909  SCIP_SET* set, /**< global SCIP settings */
3910  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3911  SCIP_STAT* stat, /**< dynamic problem statistics */
3912  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3913  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
3914  SCIP_PROB* transprob, /**< transformed problem after presolve */
3915  SCIP_PROB* origprob, /**< original problem */
3916  SCIP_TREE* tree, /**< branch and bound tree */
3917  SCIP_REOPT* reopt, /**< reoptimization data structure */
3918  SCIP_LP* lp, /**< current LP data */
3919  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3920  SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
3921  )
3922 {
3923  SCIP_FORK* fork;
3924  SCIP_Bool lperror;
3925 
3926  assert(blkmem != NULL);
3927  assert(tree != NULL);
3928  assert(!SCIPtreeProbing(tree));
3929  assert(tree->focusnode != NULL);
3930  assert(tree->focusnode->active); /* otherwise, no children could be created at the focus node */
3932  assert(tree->nchildren > 0);
3933  assert(lp != NULL);
3934  assert(lp->flushed);
3935  assert(lp->solved || lp->resolvelperror);
3936 
3937  SCIPsetDebugMsg(set, "focusnode #%" SCIP_LONGINT_FORMAT " to fork at depth %d\n",
3939 
3940  /* usually, the LP should be solved to optimality; otherwise, numerical troubles occured,
3941  * and we have to forget about the LP and transform the node into a junction (see below)
3942  */
3943  lperror = FALSE;
3945  {
3946  /* clean up newly created part of LP to keep only necessary columns and rows */
3947  SCIP_CALL( SCIPlpCleanupNew(lp, blkmem, set, stat, eventqueue, eventfilter, (tree->focusnode->depth == 0)) );
3948 
3949  /* resolve LP after cleaning up */
3950  if( !lp->solved || !lp->flushed )
3951  {
3952  SCIPsetDebugMsg(set, "resolving LP after cleanup\n");
3953  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, TRUE, &lperror) );
3954  }
3955  }
3956  assert(lp->flushed);
3957  assert(lp->solved || lperror || lp->resolvelperror);
3958 
3959  /* There are two reasons, that the (reduced) LP is not solved to optimality:
3960  * - The primal heuristics (called after the current node's LP was solved) found a new
3961  * solution, that is better than the current node's lower bound.
3962  * (But in this case, all children should be cut off and the node should be converted
3963  * into a dead-end instead of a fork.)
3964  * - Something numerically weird happened after cleaning up or after resolving a diving or probing LP.
3965  * The only thing we can do, is to completely forget about the LP and treat the node as
3966  * if it was only a pseudo-solution node. Therefore we have to remove all additional
3967  * columns and rows from the LP and convert the node into a junction.
3968  * However, the node's lower bound is kept, thus automatically throwing away nodes that
3969  * were cut off due to a primal solution.
3970  */
3971  if( lperror || lp->resolvelperror || SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_OPTIMAL )
3972  {
3973  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
3974  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles: LP %" SCIP_LONGINT_FORMAT " not optimal -- convert node into junction instead of fork\n",
3975  stat->nnodes, stat->nlps);
3976 
3977  /* remove all additions to the LP at this node */
3979  SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, SCIPlpGetNRows(lp) - SCIPlpGetNNewrows(lp)) );
3980 
3981  /* convert node into a junction */
3982  SCIP_CALL( focusnodeToJunction(blkmem, set, eventqueue, tree, lp) );
3983 
3984  return SCIP_OKAY;
3985  }
3986  assert(lp->flushed);
3987  assert(lp->solved);
3989 
3990  /* remove variables from the problem that are marked as deletable, were created at this node and are not contained in the LP */
3991  SCIP_CALL( focusnodeCleanupVars(blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp, branchcand, cliquetable, FALSE) );
3992 
3993  assert(lp->flushed);
3994  assert(lp->solved);
3995 
3996  /* create fork data */
3997  SCIP_CALL( forkCreate(&fork, blkmem, set, transprob, tree, lp) );
3998 
3999  tree->focusnode->nodetype = SCIP_NODETYPE_FORK; /*lint !e641*/
4000  tree->focusnode->data.fork = fork;
4001 
4002  /* capture the LPI state of the root node to ensure that the LPI state of the root stays for the whole solving
4003  * process
4004  */
4005  if( tree->focusnode == tree->root )
4006  forkCaptureLPIState(fork, 1);
4007 
4008  /* release LPI state */
4009  if( tree->focuslpstatefork != NULL )
4010  {
4011  SCIP_CALL( SCIPnodeReleaseLPIState(tree->focuslpstatefork, blkmem, lp) );
4012  }
4013 
4014  /* make the domain change data static to save memory */
4015  SCIP_CALL( SCIPdomchgMakeStatic(&tree->focusnode->domchg, blkmem, set, eventqueue, lp) );
4016 
4017  return SCIP_OKAY;
4018 }
4019 
4020 #ifdef WITHSUBROOTS /** @todo test whether subroots should be created */
4021 /** converts the focus node into a subroot node */
4022 static
4023 SCIP_RETCODE focusnodeToSubroot(
4024  BMS_BLKMEM* blkmem, /**< block memory buffers */
4025  SCIP_SET* set, /**< global SCIP settings */
4026  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4027  SCIP_STAT* stat, /**< dynamic problem statistics */
4028  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4029  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
4030  SCIP_PROB* transprob, /**< transformed problem after presolve */
4031  SCIP_PROB* origprob, /**< original problem */
4032  SCIP_TREE* tree, /**< branch and bound tree */
4033  SCIP_LP* lp, /**< current LP data */
4034  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4035  SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
4036  )
4037 {
4038  SCIP_SUBROOT* subroot;
4039  SCIP_Bool lperror;
4040 
4041  assert(blkmem != NULL);
4042  assert(tree != NULL);
4043  assert(!SCIPtreeProbing(tree));
4044  assert(tree->focusnode != NULL);
4046  assert(tree->focusnode->active); /* otherwise, no children could be created at the focus node */
4047  assert(tree->nchildren > 0);
4048  assert(lp != NULL);
4049  assert(lp->flushed);
4050  assert(lp->solved);
4051 
4052  SCIPsetDebugMsg(set, "focusnode #%" SCIP_LONGINT_FORMAT " to subroot at depth %d\n",
4054 
4055  /* usually, the LP should be solved to optimality; otherwise, numerical troubles occured,
4056  * and we have to forget about the LP and transform the node into a junction (see below)
4057  */
4058  lperror = FALSE;
4060  {
4061  /* clean up whole LP to keep only necessary columns and rows */
4062 #ifdef SCIP_DISABLED_CODE
4063  if( tree->focusnode->depth == 0 )
4064  {
4065  SCIP_CALL( SCIPlpCleanupAll(lp, blkmem, set, stat, eventqueue, eventfilter, (tree->focusnode->depth == 0)) );
4066  }
4067  else
4068 #endif
4069  {
4070  SCIP_CALL( SCIPlpRemoveAllObsoletes(lp, blkmem, set, stat, eventqueue, eventfilter) );
4071  }
4072 
4073  /* resolve LP after cleaning up */
4074  if( !lp->solved || !lp->flushed )
4075  {
4076  SCIPsetDebugMsg(set, "resolving LP after cleanup\n");
4077  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, TRUE, &lperror) );
4078  }
4079  }
4080  assert(lp->flushed);
4081  assert(lp->solved || lperror);
4082 
4083  /* There are two reasons, that the (reduced) LP is not solved to optimality:
4084  * - The primal heuristics (called after the current node's LP was solved) found a new
4085  * solution, that is better than the current node's lower bound.
4086  * (But in this case, all children should be cut off and the node should be converted
4087  * into a dead-end instead of a subroot.)
4088  * - Something numerically weird happened after cleaning up.
4089  * The only thing we can do, is to completely forget about the LP and treat the node as
4090  * if it was only a pseudo-solution node. Therefore we have to remove all additional
4091  * columns and rows from the LP and convert the node into a junction.
4092  * However, the node's lower bound is kept, thus automatically throwing away nodes that
4093  * were cut off due to a primal solution.
4094  */
4095  if( lperror || SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_OPTIMAL )
4096  {
4097  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
4098  "(node %" SCIP_LONGINT_FORMAT ") numerical troubles: LP %" SCIP_LONGINT_FORMAT " not optimal -- convert node into junction instead of subroot\n",
4099  stat->nnodes, stat->nlps);
4100 
4101  /* remove all additions to the LP at this node */
4103  SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, SCIPlpGetNRows(lp) - SCIPlpGetNNewrows(lp)) );
4104 
4105  /* convert node into a junction */
4106  SCIP_CALL( focusnodeToJunction(blkmem, set, eventqueue, tree, lp) );
4107 
4108  return SCIP_OKAY;
4109  }
4110  assert(lp->flushed);
4111  assert(lp->solved);
4113 
4114  /* remove variables from the problem that are marked as deletable, were created at this node and are not contained in the LP */
4115  SCIP_CALL( focusnodeCleanupVars(blkmem, set, stat, eventqueue, transprob, origprob, tree, lp, branchcand, cliquetable, FALSE) );
4116 
4117  assert(lp->flushed);
4118  assert(lp->solved);
4119 
4120 
4121  /* create subroot data */
4122  SCIP_CALL( subrootCreate(&subroot, blkmem, set, transprob, tree, lp) );
4123 
4124  tree->focusnode->nodetype = SCIP_NODETYPE_SUBROOT; /*lint !e641*/
4125  tree->focusnode->data.subroot = subroot;
4126 
4127  /* update the LP column and row counter for the converted node */
4128  SCIP_CALL( treeUpdatePathLPSize(tree, tree->focusnode->depth) );
4129 
4130  /* release LPI state */
4131  if( tree->focuslpstatefork != NULL )
4132  {
4133  SCIP_CALL( SCIPnodeReleaseLPIState(tree->focuslpstatefork, blkmem, lp) );
4134  }
4135 
4136  /* make the domain change data static to save memory */
4137  SCIP_CALL( SCIPdomchgMakeStatic(&tree->focusnode->domchg, blkmem, set, eventqueue, lp) );
4138 
4139  return SCIP_OKAY;
4140 }
4141 #endif
4142 
4143 /** puts all nodes in the array on the node queue and makes them LEAFs */
4144 static
4146  SCIP_TREE* tree, /**< branch and bound tree */
4147  SCIP_REOPT* reopt, /**< reoptimization data structure */
4148  BMS_BLKMEM* blkmem, /**< block memory buffers */
4149  SCIP_SET* set, /**< global SCIP settings */
4150  SCIP_STAT* stat, /**< dynamic problem statistics */
4151  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4152  SCIP_LP* lp, /**< current LP data */
4153  SCIP_NODE** nodes, /**< array of nodes to put on the queue */
4154  int* nnodes, /**< pointer to number of nodes in the array */
4155  SCIP_NODE* lpstatefork, /**< LP state defining fork of the nodes */
4156  SCIP_Real cutoffbound /**< cutoff bound: all nodes with lowerbound >= cutoffbound are cut off */
4157  )
4158 {
4159  int i;
4160 
4161  assert(tree != NULL);
4162  assert(set != NULL);
4163  assert(nnodes != NULL);
4164  assert(*nnodes == 0 || nodes != NULL);
4165 
4166  for( i = 0; i < *nnodes; ++i )
4167  {
4168  /* convert node to LEAF and put it into leaves queue, or delete it if it's lower bound exceeds the cutoff bound */
4169  SCIP_CALL( nodeToLeaf(&nodes[i], blkmem, set, stat, eventqueue, tree, reopt, lp, lpstatefork, cutoffbound) );
4170  assert(nodes[i] == NULL);
4171  }
4172  *nnodes = 0;
4173 
4174  return SCIP_OKAY;
4175 }
4176 
4177 /** converts children into siblings, clears children array */
4178 static
4180  SCIP_TREE* tree /**< branch and bound tree */
4181  )
4182 {
4183  SCIP_NODE** tmpnodes;
4184  SCIP_Real* tmpprios;
4185  int tmpnodessize;
4186  int i;
4187 
4188  assert(tree != NULL);
4189  assert(tree->nsiblings == 0);
4190 
4191  tmpnodes = tree->siblings;
4192  tmpprios = tree->siblingsprio;
4193  tmpnodessize = tree->siblingssize;
4194 
4195  tree->siblings = tree->children;
4196  tree->siblingsprio = tree->childrenprio;
4197  tree->nsiblings = tree->nchildren;
4198  tree->siblingssize = tree->childrensize;
4199 
4200  tree->children = tmpnodes;
4201  tree->childrenprio = tmpprios;
4202  tree->nchildren = 0;
4203  tree->childrensize = tmpnodessize;
4204 
4205  for( i = 0; i < tree->nsiblings; ++i )
4206  {
4207  assert(SCIPnodeGetType(tree->siblings[i]) == SCIP_NODETYPE_CHILD);
4208  tree->siblings[i]->nodetype = SCIP_NODETYPE_SIBLING; /*lint !e641*/
4209 
4210  /* because CHILD and SIBLING structs contain the same data in the same order, we do not have to copy it */
4211  assert(&(tree->siblings[i]->data.sibling.arraypos) == &(tree->siblings[i]->data.child.arraypos));
4212  }
4213 }
4214 
4215 /** installs a child, a sibling, or a leaf node as the new focus node */
4217  SCIP_NODE** node, /**< pointer to node to focus (or NULL to remove focus); the node
4218  * is freed, if it was cut off due to a cut off subtree */
4219  BMS_BLKMEM* blkmem, /**< block memory buffers */
4220  SCIP_SET* set, /**< global SCIP settings */
4221  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4222  SCIP_STAT* stat, /**< problem statistics */
4223  SCIP_PROB* transprob, /**< transformed problem */
4224  SCIP_PROB* origprob, /**< original problem */
4225  SCIP_PRIMAL* primal, /**< primal data */
4226  SCIP_TREE* tree, /**< branch and bound tree */
4227  SCIP_REOPT* reopt, /**< reoptimization data structure */
4228  SCIP_LP* lp, /**< current LP data */
4229  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4230  SCIP_CONFLICT* conflict, /**< conflict analysis data */
4231  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
4232  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4233  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4234  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4235  SCIP_Bool* cutoff, /**< pointer to store whether the given node can be cut off */
4236  SCIP_Bool postponed, /**< was the current focus node postponed? */
4237  SCIP_Bool exitsolve /**< are we in exitsolve stage, so we only need to loose the children */
4238  )
4239 { /*lint --e{715}*/
4240  SCIP_NODE* oldfocusnode;
4241  SCIP_NODE* fork;
4242  SCIP_NODE* lpfork;
4243  SCIP_NODE* lpstatefork;
4244  SCIP_NODE* subroot;
4245  SCIP_NODE* childrenlpstatefork;
4246  int oldcutoffdepth;
4247 
4248  assert(node != NULL);
4249  assert(*node == NULL
4252  || SCIPnodeGetType(*node) == SCIP_NODETYPE_LEAF);
4253  assert(*node == NULL || !(*node)->active);
4254  assert(stat != NULL);
4255  assert(tree != NULL);
4256  assert(!postponed || *node == NULL);
4257  assert(!postponed || tree->focusnode != NULL);
4258  assert(!SCIPtreeProbing(tree));
4259  assert(lp != NULL);
4260  assert(cutoff != NULL);
4261 
4262  SCIPsetDebugMsg(set, "focusing node #%" SCIP_LONGINT_FORMAT " of type %d in depth %d\n",
4263  *node != NULL ? SCIPnodeGetNumber(*node) : -1, *node != NULL ? (int)SCIPnodeGetType(*node) : 0,
4264  *node != NULL ? SCIPnodeGetDepth(*node) : -1);
4265 
4266  /* remember old cutoff depth in order to know, whether the children and siblings can be deleted */
4267  oldcutoffdepth = tree->cutoffdepth;
4268 
4269  /* find the common fork node, the new LP defining fork, and the new focus subroot,
4270  * thereby checking, if the new node can be cut off
4271  */
4272  treeFindSwitchForks(tree, *node, &fork, &lpfork, &lpstatefork, &subroot, cutoff);
4273  SCIPsetDebugMsg(set, "focus node: focusnodedepth=%d, forkdepth=%d, lpforkdepth=%d, lpstateforkdepth=%d, subrootdepth=%d, cutoff=%u\n",
4274  *node != NULL ? (*node)->depth : -1, fork != NULL ? fork->depth : -1, /*lint !e705 */
4275  lpfork != NULL ? lpfork->depth : -1, lpstatefork != NULL ? lpstatefork->depth : -1, /*lint !e705 */
4276  subroot != NULL ? subroot->depth : -1, *cutoff); /*lint !e705 */
4277 
4278  /* free the new node, if it is located in a cut off subtree */
4279  if( *cutoff )
4280  {
4281  assert(*node != NULL);
4282  assert(tree->cutoffdepth == oldcutoffdepth);
4283  if( SCIPnodeGetType(*node) == SCIP_NODETYPE_LEAF )
4284  {
4285  SCIP_CALL( SCIPnodepqRemove(tree->leaves, set, *node) );
4286  }
4287  SCIPvisualCutoffNode(stat->visual, set, stat, *node, FALSE);
4288 
4289  if( set->reopt_enable )
4290  {
4291  assert(reopt != NULL);
4292  /* check if the node should be stored for reoptimization */
4294  tree->root == (*node), tree->focusnode == (*node), (*node)->lowerbound, tree->effectiverootdepth) );
4295  }
4296 
4297  SCIP_CALL( SCIPnodeFree(node, blkmem, set, stat, eventqueue, tree, lp) );
4298 
4299  return SCIP_OKAY;
4300  }
4301 
4302  assert(tree->cutoffdepth == INT_MAX);
4303  assert(fork == NULL || fork->active);
4304  assert(lpstatefork == NULL || lpfork != NULL);
4305  assert(subroot == NULL || lpstatefork != NULL);
4306 
4307  /* remember the depth of the common fork node for LP updates */
4308  SCIPsetDebugMsg(set, "focus node: old correctlpdepth=%d\n", tree->correctlpdepth);
4309  if( subroot == tree->focussubroot && fork != NULL && lpfork != NULL )
4310  {
4311  /* we are in the same subtree with valid LP fork: the LP is correct at most upto the common fork depth */
4312  assert(subroot == NULL || subroot->active);
4313  tree->correctlpdepth = MIN(tree->correctlpdepth, (int)fork->depth);
4314  }
4315  else
4316  {
4317  /* we are in a different subtree, or no valid LP fork exists: the LP is completely incorrect */
4318  assert(subroot == NULL || !subroot->active
4319  || (tree->focussubroot != NULL && (int)(tree->focussubroot->depth) > subroot->depth));
4320  tree->correctlpdepth = -1;
4321  }
4322 
4323  /* if the LP state fork changed, the lpcount information for the new LP state fork is unknown */
4324  if( lpstatefork != tree->focuslpstatefork )
4325  tree->focuslpstateforklpcount = -1;
4326 
4327  /* in exitsolve we only need to take care of open children
4328  *
4329  * @note because we might do a 'newstart' and converted cuts to constraints might have rendered the LP in the current
4330  * focusnode unsolved the latter code would have resolved the LP unnecessarily
4331  */
4332  if( exitsolve && tree->nchildren > 0 )
4333  {
4334  SCIPsetDebugMsg(set, " -> deleting the %d children (in exitsolve) of the old focus node\n", tree->nchildren);
4335  SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, lp, tree->children, &tree->nchildren, NULL, -SCIPsetInfinity(set)) );
4336  assert(tree->nchildren == 0);
4337  }
4338 
4339  /* if the old focus node was cut off, we can delete its children;
4340  * if the old focus node's parent was cut off, we can also delete the focus node's siblings
4341  */
4342  if( tree->focusnode != NULL && oldcutoffdepth <= (int)tree->focusnode->depth )
4343  {
4344  SCIPsetDebugMsg(set, "path to old focus node of depth %u was cut off at depth %d\n", tree->focusnode->depth, oldcutoffdepth);
4345 
4346  /* delete the focus node's children by converting them to leaves with a cutoffbound of -SCIPsetInfinity(set);
4347  * we cannot delete them directly, because in SCIPnodeFree(), the children array is changed, which is the
4348  * same array we would have to iterate over here;
4349  * the children don't have an LP fork, because the old focus node is not yet converted into a fork or subroot
4350  */
4351  SCIPsetDebugMsg(set, " -> deleting the %d children of the old focus node\n", tree->nchildren);
4352  SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, lp, tree->children, &tree->nchildren, NULL, -SCIPsetInfinity(set)) );
4353  assert(tree->nchildren == 0);
4354 
4355  if( oldcutoffdepth < (int)tree->focusnode->depth )
4356  {
4357  /* delete the focus node's siblings by converting them to leaves with a cutoffbound of -SCIPsetInfinity(set);
4358  * we cannot delete them directly, because in SCIPnodeFree(), the siblings array is changed, which is the
4359  * same array we would have to iterate over here;
4360  * the siblings have the same LP state fork as the old focus node
4361  */
4362  SCIPsetDebugMsg(set, " -> deleting the %d siblings of the old focus node\n", tree->nsiblings);
4363  SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, lp, tree->siblings, &tree->nsiblings, tree->focuslpstatefork,
4364  -SCIPsetInfinity(set)) );
4365  assert(tree->nsiblings == 0);
4366  }
4367  }
4368 
4369  /* convert the old focus node into a fork or subroot node, if it has children;
4370  * otherwise, convert it into a dead-end, which will be freed later in treeSwitchPath();
4371  * if the node was postponed, make it a leaf.
4372  */
4373  childrenlpstatefork = tree->focuslpstatefork;
4374  if( postponed )
4375  {
4376  assert(tree->nchildren == 0);
4377  assert(*node == NULL);
4378 
4379  /* if the node is infeasible, convert it into a deadend; otherwise, put it into the LEAF queue */
4380  if( SCIPsetIsGE(set, tree->focusnode->lowerbound, primal->cutoffbound) )
4381  {
4382  /* in case the LP was not constructed (due to the parameter settings for example) we have the finally remember the
4383  * old size of the LP (if it was constructed in an earlier node) before we change the current node into a deadend
4384  */
4385  if( !tree->focuslpconstructed )
4386  SCIPlpMarkSize(lp);
4387 
4388  /* convert old focus node into deadend */
4389  SCIP_CALL( focusnodeToDeadend(blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp, branchcand,
4390  cliquetable) );
4391  }
4392  else
4393  {
4394  SCIP_CALL( focusnodeToLeaf(blkmem, set, stat, eventqueue, tree, reopt, lp, tree->focuslpstatefork,
4395  SCIPsetInfinity(set)) );
4396  }
4397  }
4398  else if( tree->nchildren > 0 )
4399  {
4400  SCIP_Bool selectedchild;
4401 
4402  assert(tree->focusnode != NULL);
4404  assert(oldcutoffdepth == INT_MAX);
4405 
4406  /* check whether the next focus node is a child of the old focus node */
4407  selectedchild = (*node != NULL && SCIPnodeGetType(*node) == SCIP_NODETYPE_CHILD);
4408 
4409  if( tree->focusnodehaslp && lp->isrelax )
4410  {
4411  assert(tree->focuslpconstructed);
4412 
4413 #ifdef WITHSUBROOTS /** @todo test whether subroots should be created, decide: old focus node becomes fork or subroot */
4414  if( tree->focusnode->depth > 0 && tree->focusnode->depth % 25 == 0 )
4415  {
4416  /* convert old focus node into a subroot node */
4417  SCIP_CALL( focusnodeToSubroot(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, origprob, tree, lp, branchcand) );
4418  if( *node != NULL && SCIPnodeGetType(*node) == SCIP_NODETYPE_CHILD
4420  subroot = tree->focusnode;
4421  }
4422  else
4423 #endif
4424  {
4425  /* convert old focus node into a fork node */
4426  SCIP_CALL( focusnodeToFork(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, origprob, tree,
4427  reopt, lp, branchcand, cliquetable) );
4428  }
4429 
4430  /* check, if the conversion into a subroot or fork was successful */
4433  {
4434  childrenlpstatefork = tree->focusnode;
4435 
4436  /* if a child of the old focus node was selected as new focus node, the old node becomes the new focus
4437  * LP fork and LP state fork
4438  */
4439  if( selectedchild )
4440  {
4441  lpfork = tree->focusnode;
4442  tree->correctlpdepth = tree->focusnode->depth;
4443  lpstatefork = tree->focusnode;
4444  tree->focuslpstateforklpcount = stat->lpcount;
4445  }
4446  }
4447 
4448  /* update the path's LP size */
4449  tree->pathnlpcols[tree->focusnode->depth] = SCIPlpGetNCols(lp);
4450  tree->pathnlprows[tree->focusnode->depth] = SCIPlpGetNRows(lp);
4451  }
4452  else if( tree->focuslpconstructed && (SCIPlpGetNNewcols(lp) > 0 || SCIPlpGetNNewrows(lp) > 0) )
4453  {
4454  /* convert old focus node into pseudofork */
4455  SCIP_CALL( focusnodeToPseudofork(blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp,
4456  branchcand, cliquetable) );
4458 
4459  /* update the path's LP size */
4460  tree->pathnlpcols[tree->focusnode->depth] = SCIPlpGetNCols(lp);
4461  tree->pathnlprows[tree->focusnode->depth] = SCIPlpGetNRows(lp);
4462 
4463  /* if a child of the old focus node was selected as new focus node, the old node becomes the new focus LP fork */
4464  if( selectedchild )
4465  {
4466  lpfork = tree->focusnode;
4467  tree->correctlpdepth = tree->focusnode->depth;
4468  }
4469  }
4470  else
4471  {
4472  /* in case the LP was not constructed (due to the parameter settings for example) we have the finally remember the
4473  * old size of the LP (if it was constructed in an earlier node) before we change the current node into a junction
4474  */
4475  SCIPlpMarkSize(lp);
4476 
4477  /* convert old focus node into junction */
4478  SCIP_CALL( focusnodeToJunction(blkmem, set, eventqueue, tree, lp) );
4479  }
4480  }
4481  else if( tree->focusnode != NULL )
4482  {
4483  /* in case the LP was not constructed (due to the parameter settings for example) we have the finally remember the
4484  * old size of the LP (if it was constructed in an earlier node) before we change the current node into a deadend
4485  */
4486  if( !tree->focuslpconstructed )
4487  SCIPlpMarkSize(lp);
4488 
4489  /* convert old focus node into deadend */
4490  SCIP_CALL( focusnodeToDeadend(blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp, branchcand, cliquetable) );
4491  }
4492  assert(subroot == NULL || SCIPnodeGetType(subroot) == SCIP_NODETYPE_SUBROOT);
4493  assert(lpstatefork == NULL
4494  || SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_SUBROOT
4495  || SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_FORK);
4496  assert(childrenlpstatefork == NULL
4497  || SCIPnodeGetType(childrenlpstatefork) == SCIP_NODETYPE_SUBROOT
4498  || SCIPnodeGetType(childrenlpstatefork) == SCIP_NODETYPE_FORK);
4499  assert(lpfork == NULL
4501  || SCIPnodeGetType(lpfork) == SCIP_NODETYPE_FORK
4503  SCIPsetDebugMsg(set, "focus node: new correctlpdepth=%d\n", tree->correctlpdepth);
4504 
4505  /* set up the new lists of siblings and children */
4506  oldfocusnode = tree->focusnode;
4507  if( *node == NULL )
4508  {
4509  /* move siblings to the queue, make them LEAFs */
4510  SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, lp, tree->siblings, &tree->nsiblings, tree->focuslpstatefork,
4511  primal->cutoffbound) );
4512 
4513  /* move children to the queue, make them LEAFs */
4514  SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, lp, tree->children, &tree->nchildren, childrenlpstatefork,
4515  primal->cutoffbound) );
4516  }
4517  else
4518  {
4519  SCIP_NODE* bestleaf;
4520 
4521  switch( SCIPnodeGetType(*node) )
4522  {
4523  case SCIP_NODETYPE_SIBLING:
4524  /* reset plunging depth, if the selected node is better than all leaves */
4525  bestleaf = SCIPtreeGetBestLeaf(tree);
4526  if( bestleaf == NULL || SCIPnodepqCompare(tree->leaves, set, *node, bestleaf) <= 0 )
4527  stat->plungedepth = 0;
4528 
4529  /* move children to the queue, make them LEAFs */
4530  SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, lp, tree->children, &tree->nchildren, childrenlpstatefork,
4531  primal->cutoffbound) );
4532 
4533  /* remove selected sibling from the siblings array */
4534  treeRemoveSibling(tree, *node);
4535 
4536  SCIPsetDebugMsg(set, "selected sibling node, lowerbound=%g, plungedepth=%d\n", (*node)->lowerbound, stat->plungedepth);
4537  break;
4538 
4539  case SCIP_NODETYPE_CHILD:
4540  /* reset plunging depth, if the selected node is better than all leaves; otherwise, increase plunging depth */
4541  bestleaf = SCIPtreeGetBestLeaf(tree);
4542  if( bestleaf == NULL || SCIPnodepqCompare(tree->leaves, set, *node, bestleaf) <= 0 )
4543  stat->plungedepth = 0;
4544  else
4545  stat->plungedepth++;
4546 
4547  /* move siblings to the queue, make them LEAFs */
4548  SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, lp, tree->siblings, &tree->nsiblings, tree->focuslpstatefork,
4549  primal->cutoffbound) );
4550 
4551  /* remove selected child from the children array */
4552  treeRemoveChild(tree, *node);
4553 
4554  /* move remaining children to the siblings array, make them SIBLINGs */
4555  treeChildrenToSiblings(tree);
4556 
4557  SCIPsetDebugMsg(set, "selected child node, lowerbound=%g, plungedepth=%d\n", (*node)->lowerbound, stat->plungedepth);
4558  break;
4559 
4560  case SCIP_NODETYPE_LEAF:
4561  /* move siblings to the queue, make them LEAFs */
4562  SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, lp, tree->siblings, &tree->nsiblings, tree->focuslpstatefork,
4563  primal->cutoffbound) );
4564 
4565  /* encounter an early backtrack if there is a child which does not exceed given reference bound */
4566  if( !SCIPsetIsInfinity(set, stat->referencebound) )
4567  {
4568  int c;
4569 
4570  /* loop over children and stop if we find a child with a lower bound below given reference bound */
4571  for( c = 0; c < tree->nchildren; ++c )
4572  {
4573  if( SCIPsetIsLT(set, SCIPnodeGetLowerbound(tree->children[c]), stat->referencebound) )
4574  {
4575  ++stat->nearlybacktracks;
4576  break;
4577  }
4578  }
4579  }
4580  /* move children to the queue, make them LEAFs */
4581  SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, lp, tree->children, &tree->nchildren, childrenlpstatefork,
4582  primal->cutoffbound) );
4583 
4584  /* remove node from the queue */
4585  SCIP_CALL( SCIPnodepqRemove(tree->leaves, set, *node) );
4586 
4587  stat->plungedepth = 0;
4588  if( SCIPnodeGetDepth(*node) > 0 )
4589  stat->nbacktracks++;
4590  SCIPsetDebugMsg(set, "selected leaf node, lowerbound=%g, plungedepth=%d\n", (*node)->lowerbound, stat->plungedepth);
4591  break;
4592 
4593  default:
4594  SCIPerrorMessage("selected node is neither sibling, child, nor leaf (nodetype=%d)\n", SCIPnodeGetType(*node));
4595  return SCIP_INVALIDDATA;
4596  } /*lint !e788*/
4597 
4598  /* convert node into the focus node */
4599  (*node)->nodetype = SCIP_NODETYPE_FOCUSNODE; /*lint !e641*/
4600  }
4601  assert(tree->nchildren == 0);
4602 
4603  /* set new focus node, LP fork, LP state fork, and subroot */
4604  assert(subroot == NULL || (lpstatefork != NULL && subroot->depth <= lpstatefork->depth));
4605  assert(lpstatefork == NULL || (lpfork != NULL && lpstatefork->depth <= lpfork->depth));
4606  assert(lpfork == NULL || (*node != NULL && lpfork->depth < (*node)->depth));
4607  tree->focusnode = *node;
4608  tree->focuslpfork = lpfork;
4609  tree->focuslpstatefork = lpstatefork;
4610  tree->focussubroot = subroot;
4611  tree->focuslpconstructed = FALSE;
4612  lp->resolvelperror = FALSE;
4613 
4614  /* track the path from the old focus node to the new node, and perform domain and constraint set changes */
4615  SCIP_CALL( treeSwitchPath(tree, reopt, blkmem, set, stat, transprob, origprob, primal, lp, branchcand, conflict,
4616  eventfilter, eventqueue, cliquetable, fork, *node, cutoff) );
4617  assert(tree->pathlen >= 0);
4618  assert(*node != NULL || tree->pathlen == 0);
4619  assert(*node == NULL || tree->pathlen-1 <= (int)(*node)->depth);
4620 
4621  /* if the old focus node is a dead end (has no children), delete it */
4622  if( oldfocusnode != NULL && SCIPnodeGetType(oldfocusnode) == SCIP_NODETYPE_DEADEND )
4623  {
4624  int appliedeffectiverootdepth;
4625 
4626  appliedeffectiverootdepth = tree->appliedeffectiverootdepth;
4627  assert(appliedeffectiverootdepth <= tree->effectiverootdepth);
4628 
4629  SCIP_CALL( SCIPnodeFree(&oldfocusnode, blkmem, set, stat, eventqueue, tree, lp) );
4630  assert(tree->effectiverootdepth < tree->pathlen || *node == NULL || *cutoff);
4631 
4632  if( tree->effectiverootdepth > appliedeffectiverootdepth && *node != NULL && !(*cutoff) )
4633  {
4634  int d;
4635 
4636  /* promote the constraint set and bound changes up to the new effective root to be global changes */
4637  SCIPsetDebugMsg(set, "effective root is now at depth %d: applying constraint set and bound changes to global problem\n",
4638  tree->effectiverootdepth);
4639 
4640  for( d = appliedeffectiverootdepth + 1; d <= tree->effectiverootdepth; ++d )
4641  {
4642  SCIP_Bool nodecutoff;
4643 
4644  SCIPsetDebugMsg(set, " -> applying constraint set changes of depth %d\n", d);
4645  SCIP_CALL( SCIPconssetchgMakeGlobal(&tree->path[d]->conssetchg, blkmem, set, stat, transprob, reopt) );
4646  SCIPsetDebugMsg(set, " -> applying bound changes of depth %d\n", d);
4647  SCIP_CALL( SCIPdomchgApplyGlobal(tree->path[d]->domchg, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
4648  &nodecutoff) );
4649 
4650  if( nodecutoff )
4651  {
4652  SCIP_CALL( SCIPnodeCutoff(tree->path[d], set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
4653  *cutoff = TRUE;
4654  }
4655  }
4656 
4658  }
4659  }
4660  assert(*cutoff || SCIPtreeIsPathComplete(tree));
4661 
4662  return SCIP_OKAY;
4663 }
4664 
4665 
4666 
4667 
4668 /*
4669  * Tree methods
4670  */
4671 
4672 /** creates an initialized tree data structure */
4674  SCIP_TREE** tree, /**< pointer to tree data structure */
4675  BMS_BLKMEM* blkmem, /**< block memory buffers */
4676  SCIP_SET* set, /**< global SCIP settings */
4677  SCIP_NODESEL* nodesel /**< node selector to use for sorting leaves in the priority queue */
4678  )
4679 {
4680  int p;
4681 
4682  assert(tree != NULL);
4683  assert(blkmem != NULL);
4684 
4685  SCIP_ALLOC( BMSallocMemory(tree) );
4686 
4687  (*tree)->root = NULL;
4688 
4689  SCIP_CALL( SCIPnodepqCreate(&(*tree)->leaves, set, nodesel) );
4690 
4691  /* allocate one slot for the prioritized and the unprioritized bound change */
4692  for( p = 0; p <= 1; ++p )
4693  {
4694  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*tree)->divebdchgdirs[p], 1) ); /*lint !e866*/
4695  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*tree)->divebdchgvars[p], 1) ); /*lint !e866*/
4696  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*tree)->divebdchgvals[p], 1) ); /*lint !e866*/
4697  (*tree)->ndivebdchanges[p] = 0;
4698  (*tree)->divebdchgsize[p] = 1;
4699  }
4700 
4701  (*tree)->path = NULL;
4702  (*tree)->focusnode = NULL;
4703  (*tree)->focuslpfork = NULL;
4704  (*tree)->focuslpstatefork = NULL;
4705  (*tree)->focussubroot = NULL;
4706  (*tree)->children = NULL;
4707  (*tree)->siblings = NULL;
4708  (*tree)->probingroot = NULL;
4709  (*tree)->childrenprio = NULL;
4710  (*tree)->siblingsprio = NULL;
4711  (*tree)->pathnlpcols = NULL;
4712  (*tree)->pathnlprows = NULL;
4713  (*tree)->probinglpistate = NULL;
4714  (*tree)->probinglpinorms = NULL;
4715  (*tree)->pendingbdchgs = NULL;
4716  (*tree)->pendingbdchgssize = 0;
4717  (*tree)->npendingbdchgs = 0;
4718  (*tree)->focuslpstateforklpcount = -1;
4719  (*tree)->childrensize = 0;
4720  (*tree)->nchildren = 0;
4721  (*tree)->siblingssize = 0;
4722  (*tree)->nsiblings = 0;
4723  (*tree)->pathlen = 0;
4724  (*tree)->pathsize = 0;
4725  (*tree)->effectiverootdepth = 0;
4726  (*tree)->appliedeffectiverootdepth = 0;
4727  (*tree)->correctlpdepth = -1;
4728  (*tree)->cutoffdepth = INT_MAX;
4729  (*tree)->repropdepth = INT_MAX;
4730  (*tree)->repropsubtreecount = 0;
4731  (*tree)->focusnodehaslp = FALSE;
4732  (*tree)->probingnodehaslp = FALSE;
4733  (*tree)->focuslpconstructed = FALSE;
4734  (*tree)->cutoffdelayed = FALSE;
4735  (*tree)->probinglpwasflushed = FALSE;
4736  (*tree)->probinglpwassolved = FALSE;
4737  (*tree)->probingloadlpistate = FALSE;
4738  (*tree)->probinglpwasrelax = FALSE;
4739  (*tree)->probingsolvedlp = FALSE;
4740  (*tree)->forcinglpmessage = FALSE;
4741  (*tree)->sbprobing = FALSE;
4742  (*tree)->probinglpwasprimfeas = TRUE;
4743  (*tree)->probinglpwasdualfeas = TRUE;
4744 
4745  return SCIP_OKAY;
4746 }
4747 
4748 /** frees tree data structure */
4750  SCIP_TREE** tree, /**< pointer to tree data structure */
4751  BMS_BLKMEM* blkmem, /**< block memory buffers */
4752  SCIP_SET* set, /**< global SCIP settings */
4753  SCIP_STAT* stat, /**< problem statistics */
4754  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4755  SCIP_LP* lp /**< current LP data */
4756  )
4757 {
4758  int p;
4759 
4760  assert(tree != NULL);
4761  assert(*tree != NULL);
4762  assert((*tree)->nchildren == 0);
4763  assert((*tree)->nsiblings == 0);
4764  assert((*tree)->focusnode == NULL);
4765  assert(!SCIPtreeProbing(*tree));
4766 
4767  SCIPsetDebugMsg(set, "free tree\n");
4768 
4769  /* free node queue */
4770  SCIP_CALL( SCIPnodepqFree(&(*tree)->leaves, blkmem, set, stat, eventqueue, *tree, lp) );
4771 
4772  /* free diving bound change storage */
4773  for( p = 0; p <= 1; ++p )
4774  {
4775  BMSfreeBlockMemoryArray(blkmem, &(*tree)->divebdchgdirs[p], (*tree)->divebdchgsize[p]); /*lint !e866*/
4776  BMSfreeBlockMemoryArray(blkmem, &(*tree)->divebdchgvals[p], (*tree)->divebdchgsize[p]); /*lint !e866*/
4777  BMSfreeBlockMemoryArray(blkmem, &(*tree)->divebdchgvars[p], (*tree)->divebdchgsize[p]); /*lint !e866*/
4778  }
4779 
4780  /* free pointer arrays */
4781  BMSfreeMemoryArrayNull(&(*tree)->path);
4782  BMSfreeMemoryArrayNull(&(*tree)->children);
4783  BMSfreeMemoryArrayNull(&(*tree)->siblings);
4784  BMSfreeMemoryArrayNull(&(*tree)->childrenprio);
4785  BMSfreeMemoryArrayNull(&(*tree)->siblingsprio);
4786  BMSfreeMemoryArrayNull(&(*tree)->pathnlpcols);
4787  BMSfreeMemoryArrayNull(&(*tree)->pathnlprows);
4788  BMSfreeMemoryArrayNull(&(*tree)->pendingbdchgs);
4789 
4790  BMSfreeMemory(tree);
4791 
4792  return SCIP_OKAY;
4793 }
4794 
4795 /** clears and resets tree data structure and deletes all nodes */
4797  SCIP_TREE* tree, /**< tree data structure */
4798  BMS_BLKMEM* blkmem, /**< block memory buffers */
4799  SCIP_SET* set, /**< global SCIP settings */
4800  SCIP_STAT* stat, /**< problem statistics */
4801  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4802  SCIP_LP* lp /**< current LP data */
4803  )
4804 {
4805  int v;
4806 
4807  assert(tree != NULL);
4808  assert(tree->nchildren == 0);
4809  assert(tree->nsiblings == 0);
4810  assert(tree->focusnode == NULL);
4811  assert(!SCIPtreeProbing(tree));
4812 
4813  SCIPsetDebugMsg(set, "clearing tree\n");
4814 
4815  /* clear node queue */
4816  SCIP_CALL( SCIPnodepqClear(tree->leaves, blkmem, set, stat, eventqueue, tree, lp) );
4817  assert(tree->root == NULL);
4818 
4819  /* we have to remove the captures of the variables within the pending bound change data structure */
4820  for( v = tree->npendingbdchgs-1; v >= 0; --v )
4821  {
4822  SCIP_VAR* var;
4823 
4824  var = tree->pendingbdchgs[v].var;
4825  assert(var != NULL);
4826 
4827  /* release the variable */
4828  SCIP_CALL( SCIPvarRelease(&var, blkmem, set, eventqueue, lp) );
4829  }
4830 
4831  /* mark working arrays to be empty and reset data */
4832  tree->focuslpstateforklpcount = -1;
4833  tree->nchildren = 0;
4834  tree->nsiblings = 0;
4835  tree->pathlen = 0;
4836  tree->effectiverootdepth = 0;
4837  tree->appliedeffectiverootdepth = 0;
4838  tree->correctlpdepth = -1;
4839  tree->cutoffdepth = INT_MAX;
4840  tree->repropdepth = INT_MAX;
4841  tree->repropsubtreecount = 0;
4842  tree->npendingbdchgs = 0;
4843  tree->focusnodehaslp = FALSE;
4844  tree->probingnodehaslp = FALSE;
4845  tree->cutoffdelayed = FALSE;
4846  tree->probinglpwasflushed = FALSE;
4847  tree->probinglpwassolved = FALSE;
4848  tree->probingloadlpistate = FALSE;
4849  tree->probinglpwasrelax = FALSE;
4850  tree->probingsolvedlp = FALSE;
4851 
4852  return SCIP_OKAY;
4853 }
4854 
4855 /** creates the root node of the tree and puts it into the leaves queue */
4857  SCIP_TREE* tree, /**< tree data structure */
4858  SCIP_REOPT* reopt, /**< reoptimization data structure */
4859  BMS_BLKMEM* blkmem, /**< block memory buffers */
4860  SCIP_SET* set, /**< global SCIP settings */
4861  SCIP_STAT* stat, /**< problem statistics */
4862  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4863  SCIP_LP* lp /**< current LP data */
4864  )
4865 {
4866  assert(tree != NULL);
4867  assert(tree->nchildren == 0);
4868  assert(tree->nsiblings == 0);
4869  assert(tree->root == NULL);
4870  assert(tree->focusnode == NULL);
4871  assert(!SCIPtreeProbing(tree));
4872 
4873  /* create root node */
4874  SCIP_CALL( SCIPnodeCreateChild(&tree->root, blkmem, set, stat, tree, 0.0, -SCIPsetInfinity(set)) );
4875  assert(tree->nchildren == 1);
4876 
4877 #ifndef NDEBUG
4878  /* check, if the sizes in the data structures match the maximal numbers defined here */
4879  tree->root->depth = SCIP_MAXTREEDEPTH + 1;
4881  assert(tree->root->depth - 1 == SCIP_MAXTREEDEPTH); /*lint !e650*/
4882  assert(tree->root->repropsubtreemark == MAXREPROPMARK);
4883  tree->root->depth++; /* this should produce an overflow and reset the value to 0 */
4884  tree->root->repropsubtreemark++; /* this should produce an overflow and reset the value to 0 */
4885  assert(tree->root->depth == 0);
4886  assert((SCIP_NODETYPE)tree->root->nodetype == SCIP_NODETYPE_CHILD);
4887  assert(!tree->root->active);
4888  assert(!tree->root->cutoff);
4889  assert(!tree->root->reprop);
4890  assert(tree->root->repropsubtreemark == 0);
4891 #endif
4892 
4893  /* move root to the queue, convert it to LEAF */
4894  SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, lp, tree->children, &tree->nchildren, NULL,
4895  SCIPsetInfinity(set)) );
4896 
4897  return SCIP_OKAY;
4898 }
4899 
4900 /** creates a temporary presolving root node of the tree and installs it as focus node */
4902  SCIP_TREE* tree, /**< tree data structure */
4903  SCIP_REOPT* reopt, /**< reoptimization data structure */
4904  BMS_BLKMEM* blkmem, /**< block memory buffers */
4905  SCIP_SET* set, /**< global SCIP settings */
4906  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4907  SCIP_STAT* stat, /**< problem statistics */
4908  SCIP_PROB* transprob, /**< transformed problem */
4909  SCIP_PROB* origprob, /**< original problem */
4910  SCIP_PRIMAL* primal, /**< primal data */
4911  SCIP_LP* lp, /**< current LP data */
4912  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4913  SCIP_CONFLICT* conflict, /**< conflict analysis data */
4914  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
4915  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4916  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4917  SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
4918  )
4919 {
4920  SCIP_Bool cutoff;
4921 
4922  assert(tree != NULL);
4923  assert(tree->nchildren == 0);
4924  assert(tree->nsiblings == 0);
4925  assert(tree->root == NULL);
4926  assert(tree->focusnode == NULL);
4927  assert(!SCIPtreeProbing(tree));
4928 
4929  /* create temporary presolving root node */
4930  SCIP_CALL( SCIPtreeCreateRoot(tree, reopt, blkmem, set, stat, eventqueue, lp) );
4931  assert(tree->root != NULL);
4932 
4933  /* install the temporary root node as focus node */
4934  SCIP_CALL( SCIPnodeFocus(&tree->root, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4935  conflict, conflictstore, eventfilter, eventqueue, cliquetable, &cutoff, FALSE, FALSE) );
4936  assert(!cutoff);
4937 
4938  return SCIP_OKAY;
4939 }
4940 
4941 /** frees the temporary presolving root and resets tree data structure */
4943  SCIP_TREE* tree, /**< tree data structure */
4944  SCIP_REOPT* reopt, /**< reoptimization data structure */
4945  BMS_BLKMEM* blkmem, /**< block memory buffers */
4946  SCIP_SET* set, /**< global SCIP settings */
4947  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4948  SCIP_STAT* stat, /**< problem statistics */
4949  SCIP_PROB* transprob, /**< transformed problem */
4950  SCIP_PROB* origprob, /**< original problem */
4951  SCIP_PRIMAL* primal, /**< primal data */
4952  SCIP_LP* lp, /**< current LP data */
4953  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4954  SCIP_CONFLICT* conflict, /**< conflict analysis data */
4955  SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
4956  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4957  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4958  SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
4959  )
4960 {
4961  SCIP_NODE* node;
4962  SCIP_Bool cutoff;
4963 
4964  assert(tree != NULL);
4965  assert(tree->root != NULL);
4966  assert(tree->focusnode == tree->root);
4967  assert(tree->pathlen == 1);
4968 
4969  /* unfocus the temporary root node */
4970  node = NULL;
4971  SCIP_CALL( SCIPnodeFocus(&node, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4972  conflict, conflictstore, eventfilter, eventqueue, cliquetable, &cutoff, FALSE, FALSE) );
4973  assert(!cutoff);
4974  assert(tree->root == NULL);
4975  assert(tree->focusnode == NULL);
4976  assert(tree->pathlen == 0);
4977 
4978  /* reset tree data structure */
4979  SCIP_CALL( SCIPtreeClear(tree, blkmem, set, stat, eventqueue, lp) );
4980 
4981  return SCIP_OKAY;
4982 }
4983 
4984 /** returns the node selector associated with the given node priority queue */
4986  SCIP_TREE* tree /**< branch and bound tree */
4987  )
4988 {
4989  assert(tree != NULL);
4990 
4991  return SCIPnodepqGetNodesel(tree->leaves);
4992 }
4993 
4994 /** sets the node selector used for sorting the nodes in the priority queue, and resorts the queue if necessary */
4996  SCIP_TREE* tree, /**< branch and bound tree */
4997  SCIP_SET* set, /**< global SCIP settings */
4998  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
4999  SCIP_STAT* stat, /**< problem statistics */
5000  SCIP_NODESEL* nodesel /**< node selector to use for sorting the nodes in the queue */
5001  )
5002 {
5003  assert(tree != NULL);
5004  assert(stat != NULL);
5005 
5006  if( SCIPnodepqGetNodesel(tree->leaves) != nodesel )
5007  {
5008  /* change the node selector used in the priority queue and resort the queue */
5009  SCIP_CALL( SCIPnodepqSetNodesel(&tree->leaves, set, nodesel) );
5010 
5011  /* issue message */
5012  if( stat->nnodes > 0 )
5013  {
5014  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
5015  "(node %" SCIP_LONGINT_FORMAT ") switching to node selector <%s>\n", stat->nnodes, SCIPnodeselGetName(nodesel));
5016  }
5017  }
5018 
5019  return SCIP_OKAY;
5020 }
5021 
5022 /** cuts off nodes with lower bound not better than given cutoff bound */
5024  SCIP_TREE* tree, /**< branch and bound tree */
5025  SCIP_REOPT* reopt, /**< reoptimization data structure */
5026  BMS_BLKMEM* blkmem, /**< block memory */
5027  SCIP_SET* set, /**< global SCIP settings */
5028  SCIP_STAT* stat, /**< dynamic problem statistics */
5029  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5030  SCIP_LP* lp, /**< current LP data */
5031  SCIP_Real cutoffbound /**< cutoff bound: all nodes with lowerbound >= cutoffbound are cut off */
5032  )
5033 {
5034  SCIP_NODE* node;
5035  int i;
5036 
5037  assert(tree != NULL);
5038  assert(stat != NULL);
5039  assert(lp != NULL);
5040 
5041  /* if we are in diving mode, it is not allowed to cut off nodes, because this can lead to deleting LP rows which
5042  * would modify the currently unavailable (due to diving modifications) SCIP_LP
5043  * -> the cutoff must be delayed and executed after the diving ends
5044  */
5045  if( SCIPlpDiving(lp) )
5046  {
5047  tree->cutoffdelayed = TRUE;
5048  return SCIP_OKAY;
5049  }
5050 
5051  tree->cutoffdelayed = FALSE;
5052 
5053  /* cut off leaf nodes in the queue */
5054  SCIP_CALL( SCIPnodepqBound(tree->leaves, blkmem, set, stat, eventqueue, tree, reopt, lp, cutoffbound) );
5055 
5056  /* cut off siblings: we have to loop backwards, because a removal leads to moving the last node in empty slot */
5057  for( i = tree->nsiblings-1; i >= 0; --i )
5058  {
5059  node = tree->siblings[i];
5060  if( SCIPsetIsGE(set, node->lowerbound, cutoffbound) )
5061  {
5062  SCIPsetDebugMsg(set, "cut off sibling #%" SCIP_LONGINT_FORMAT " at depth %d with lowerbound=%g at position %d\n",
5063  SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), node->lowerbound, i);
5064 
5065  if( set->reopt_enable )
5066  {
5067  assert(reopt != NULL);
5068  /* check if the node should be stored for reoptimization */
5070  tree->root == node, tree->focusnode == node, node->lowerbound, tree->effectiverootdepth) );
5071  }
5072 
5073  SCIPvisualCutoffNode(stat->visual, set, stat, node, FALSE);
5074 
5075  SCIP_CALL( SCIPnodeFree(&node, blkmem, set, stat, eventqueue, tree, lp) );
5076  }
5077  }
5078 
5079  /* cut off children: we have to loop backwards, because a removal leads to moving the last node in empty slot */
5080  for( i = tree->nchildren-1; i >= 0; --i )
5081  {
5082  node = tree->children[i];
5083  if( SCIPsetIsGE(set, node->lowerbound, cutoffbound) )
5084  {
5085  SCIPsetDebugMsg(set, "cut off child #%" SCIP_LONGINT_FORMAT " at depth %d with lowerbound=%g at position %d\n",
5086  SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), node->lowerbound, i);
5087 
5088  if( set->reopt_enable )
5089  {
5090  assert(reopt != NULL);
5091  /* check if the node should be stored for reoptimization */
5093  tree->root == node, tree->focusnode == node, node->lowerbound, tree->effectiverootdepth) );
5094  }
5095 
5096  SCIPvisualCutoffNode(stat->visual, set, stat, node, FALSE);
5097 
5098  SCIP_CALL( SCIPnodeFree(&node, blkmem, set, stat, eventqueue, tree, lp) );
5099  }
5100  }
5101 
5102  return SCIP_OKAY;
5103 }
5104 
5105 /** calculates the node selection priority for moving the given variable's LP value to the given target value;
5106  * this node selection priority can be given to the SCIPcreateChild() call
5107  */
5109  SCIP_TREE* tree, /**< branch and bound tree */
5110  SCIP_SET* set, /**< global SCIP settings */
5111  SCIP_STAT* stat, /**< dynamic problem statistics */
5112  SCIP_VAR* var, /**< variable, of which the branching factor should be applied, or NULL */
5113  SCIP_BRANCHDIR branchdir, /**< type of branching that was performed: upwards, downwards, or fixed
5114  * fixed should only be used, when both bounds changed
5115  */
5116  SCIP_Real targetvalue /**< new value of the variable in the child node */
5117  )
5118 {
5119  SCIP_Real prio;
5120  SCIP_Real varsol;
5121  SCIP_Real varrootsol;
5122  SCIP_Real downinfs;
5123  SCIP_Real upinfs;
5124  SCIP_Bool isroot;
5125  SCIP_Bool haslp;
5126 
5127  assert(set != NULL);
5128 
5129  /* extract necessary information */
5130  isroot = (SCIPtreeGetCurrentDepth(tree) == 0);
5131  haslp = SCIPtreeHasFocusNodeLP(tree);
5132  varsol = SCIPvarGetSol(var, haslp);
5133  varrootsol = SCIPvarGetRootSol(var);
5134  downinfs = SCIPvarGetAvgInferences(var, stat, SCIP_BRANCHDIR_DOWNWARDS);
5135  upinfs = SCIPvarGetAvgInferences(var, stat, SCIP_BRANCHDIR_UPWARDS);
5136 
5137  switch( branchdir )
5138  {
5140  switch( SCIPvarGetBranchDirection(var) )
5141  {
5143  prio = +1.0;
5144  break;
5146  prio = -1.0;
5147  break;
5148  case SCIP_BRANCHDIR_AUTO:
5149  switch( set->nodesel_childsel )
5150  {
5151  case 'd':
5152  prio = +1.0;
5153  break;
5154  case 'u':
5155  prio = -1.0;
5156  break;
5157  case 'p':
5158  prio = -SCIPvarGetPseudocost(var, stat, targetvalue - varsol);
5159  break;
5160  case 'i':
5161  prio = downinfs;
5162  break;
5163  case 'l':
5164  prio = targetvalue - varsol;
5165  break;
5166  case 'r':
5167  prio = varrootsol - varsol;
5168  break;
5169  case 'h':
5170  prio = downinfs + SCIPsetEpsilon(set);
5171  if( !isroot && haslp )
5172  prio *= (varrootsol - varsol + 1.0);
5173  break;
5174  default:
5175  SCIPerrorMessage("invalid child selection rule <%c>\n", set->nodesel_childsel);
5176  prio = 0.0;
5177  break;
5178  }
5179  break;
5180  default:
5181  SCIPerrorMessage("invalid preferred branching direction <%d> of variable <%s>\n",
5183  prio = 0.0;
5184  break;
5185  }
5186  break;
5188  /* the branch is directed upwards */
5189  switch( SCIPvarGetBranchDirection(var) )
5190  {
5192  prio = -1.0;
5193  break;
5195  prio = +1.0;
5196  break;
5197  case SCIP_BRANCHDIR_AUTO:
5198  switch( set->nodesel_childsel )
5199  {
5200  case 'd':
5201  prio = -1.0;
5202  break;
5203  case 'u':
5204  prio = +1.0;
5205  break;
5206  case 'p':
5207  prio = -SCIPvarGetPseudocost(var, stat, targetvalue - varsol);
5208  break;
5209  case 'i':
5210  prio = upinfs;
5211  break;
5212  case 'l':
5213  prio = varsol - targetvalue;
5214  break;
5215  case 'r':
5216  prio = varsol - varrootsol;
5217  break;
5218  case 'h':
5219  prio = upinfs + SCIPsetEpsilon(set);
5220  if( !isroot && haslp )
5221  prio *= (varsol - varrootsol + 1.0);
5222  break;
5223  default:
5224  SCIPerrorMessage("invalid child selection rule <%c>\n", set->nodesel_childsel);
5225  prio = 0.0;
5226  break;
5227  }
5228  /* since choosing the upwards direction is usually superior than the downwards direction (see results of
5229  * Achterberg's thesis (2007)), we break ties towards upwards branching
5230  */
5231  prio += SCIPsetEpsilon(set);
5232  break;
5233 
5234  default:
5235  SCIPerrorMessage("invalid preferred branching direction <%d> of variable <%s>\n",
5237  prio = 0.0;
5238  break;
5239  }
5240  break;
5241  case SCIP_BRANCHDIR_FIXED:
5242  prio = SCIPsetInfinity(set);
5243  break;
5244  case SCIP_BRANCHDIR_AUTO:
5245  default:
5246  SCIPerrorMessage("invalid branching direction <%d> of variable <%s>\n",
5248  prio = 0.0;
5249  break;
5250  }
5251 
5252  return prio;
5253 }
5254 
5255 /** calculates an estimate for the objective of the best feasible solution contained in the subtree after applying the given
5256  * branching; this estimate can be given to the SCIPcreateChild() call
5257  */
5259  SCIP_TREE* tree, /**< branch and bound tree */
5260  SCIP_SET* set, /**< global SCIP settings */
5261  SCIP_STAT* stat, /**< dynamic problem statistics */
5262  SCIP_VAR* var, /**< variable, of which the branching factor should be applied, or NULL */
5263  SCIP_Real targetvalue /**< new value of the variable in the child node */
5264  )
5265 {
5266  SCIP_Real estimateinc;
5267  SCIP_Real estimate;
5268  SCIP_Real varsol;
5269 
5270  assert(tree != NULL);
5271  assert(var != NULL);
5272 
5273  estimate = SCIPnodeGetEstimate(tree->focusnode);
5274  varsol = SCIPvarGetSol(var, SCIPtreeHasFocusNodeLP(tree));
5275 
5276  /* compute increase above parent node's (i.e., focus node's) estimate value */
5278  estimateinc = SCIPvarGetPseudocost(var, stat, targetvalue - varsol);
5279  else
5280  {
5281  SCIP_Real pscdown;
5282  SCIP_Real pscup;
5283 
5284  /* calculate estimate based on pseudo costs:
5285  * estimate = lowerbound + sum(min{f_j * pscdown_j, (1-f_j) * pscup_j})
5286  * = parentestimate - min{f_b * pscdown_b, (1-f_b) * pscup_b} + (targetvalue-oldvalue)*{pscdown_b or pscup_b}
5287  */
5288  pscdown = SCIPvarGetPseudocost(var, stat, SCIPsetFeasFloor(set, varsol) - varsol);
5289  pscup = SCIPvarGetPseudocost(var, stat, SCIPsetFeasCeil(set, varsol) - varsol);
5290  estimateinc = SCIPvarGetPseudocost(var, stat, targetvalue - varsol) - MIN(pscdown, pscup);
5291  }
5292 
5293  /* due to rounding errors estimateinc might be slightly negative; in this case return the parent node's estimate */
5294  if( estimateinc > 0.0 )
5295  estimate += estimateinc;
5296 
5297  return estimate;
5298 }
5299 
5300 /** branches on a variable x
5301  * if x is a continuous variable, then two child nodes will be created
5302  * (x <= x', x >= x')
5303  * but if the bounds of x are such that their relative difference is smaller than epsilon,
5304  * the variable is fixed to val (if not SCIP_INVALID) or a well chosen alternative in the current node,
5305  * i.e., no children are created
5306  * if x is not a continuous variable, then:
5307  * if solution value x' is fractional, two child nodes will be created
5308  * (x <= floor(x'), x >= ceil(x')),
5309  * if solution value is integral, the x' is equal to lower or upper bound of the branching
5310  * variable and the bounds of x are finite, then two child nodes will be created
5311  * (x <= x", x >= x"+1 with x" = floor((lb + ub)/2)),
5312  * otherwise (up to) three child nodes will be created
5313  * (x <= x'-1, x == x', x >= x'+1)
5314  * if solution value is equal to one of the bounds and the other bound is infinite, only two child nodes
5315  * will be created (the third one would be infeasible anyway)
5316  */
5318  SCIP_TREE* tree, /**< branch and bound tree */
5319  SCIP_REOPT* reopt, /**< reoptimization data structure */
5320  BMS_BLKMEM* blkmem, /**< block memory */
5321  SCIP_SET* set, /**< global SCIP settings */
5322  SCIP_STAT* stat, /**< problem statistics data */
5323  SCIP_PROB* transprob, /**< transformed problem after presolve */
5324  SCIP_PROB* origprob, /**< original problem */
5325  SCIP_LP* lp, /**< current LP data */
5326  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5327  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5328  SCIP_VAR* var, /**< variable to branch on */
5329  SCIP_Real val, /**< value to branch on or SCIP_INVALID for branching on current LP/pseudo solution.
5330  * A branching value is required for branching on continuous variables */
5331  SCIP_NODE** downchild, /**< pointer to return the left child with variable rounded down, or NULL */
5332  SCIP_NODE** eqchild, /**< pointer to return the middle child with variable fixed, or NULL */
5333  SCIP_NODE** upchild /**< pointer to return the right child with variable rounded up, or NULL */
5334  )
5335 {
5336  SCIP_NODE* node;
5337  SCIP_Real priority;
5338  SCIP_Real estimate;
5339 
5340  SCIP_Real downub;
5341  SCIP_Real fixval;
5342  SCIP_Real uplb;
5343  SCIP_Real lpval;
5344 
5345  SCIP_Bool validval;
5346 
5347  assert(tree != NULL);
5348  assert(set != NULL);
5349  assert(var != NULL);
5350 
5351  /* initialize children pointer */
5352  if( downchild != NULL )
5353  *downchild = NULL;
5354  if( eqchild != NULL )
5355  *eqchild = NULL;
5356  if( upchild != NULL )
5357  *upchild = NULL;
5358 
5359  /* store whether a valid value was given for branching */
5360  validval = (val != SCIP_INVALID); /*lint !e777 */
5361 
5362  /* get the corresponding active problem variable
5363  * if branching value is given, then transform it to the value of the active variable */
5364  if( validval )
5365  {
5366  SCIP_Real scalar;
5367  SCIP_Real constant;
5368 
5369  scalar = 1.0;
5370  constant = 0.0;
5371 
5372  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &constant) );
5373 
5374  if( scalar == 0.0 )
5375  {
5376  SCIPerrorMessage("cannot branch on fixed variable <%s>\n", SCIPvarGetName(var));
5377  return SCIP_INVALIDDATA;
5378  }
5379 
5380  /* we should have givenvariable = scalar * activevariable + constant */
5381  val = (val - constant) / scalar;
5382  }
5383  else
5384  var = SCIPvarGetProbvar(var);
5385 
5387  {
5388  SCIPerrorMessage("cannot branch on fixed or multi-aggregated variable <%s>\n", SCIPvarGetName(var));
5389  SCIPABORT();
5390  return SCIP_INVALIDDATA; /*lint !e527*/
5391  }
5392 
5393  /* ensure, that branching on continuous variables will only be performed when a branching point is given. */
5394  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS && !validval )
5395  {
5396  SCIPerrorMessage("Cannot branch on continuous variables without a given branching value.\n", SCIPvarGetName(var));
5397  SCIPABORT();
5398  return SCIP_INVALIDDATA; /*lint !e527*/
5399  }
5400 
5401  assert(SCIPvarIsActive(var));
5402  assert(SCIPvarGetProbindex(var) >= 0);
5406  assert(SCIPsetIsLT(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)));
5407 
5408  /* update the information for the focus node before creating children */
5409  SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, tree->focusnode) );
5410 
5411  /* get value of variable in current LP or pseudo solution */
5412  lpval = SCIPvarGetSol(var, tree->focusnodehaslp);
5413 
5414  /* if there was no explicit value given for branching, branch on current LP or pseudo solution value */
5415  if( !validval )
5416  {
5417  val = lpval;
5418 
5419  /* avoid branching on infinite values in pseudo solution */
5420  if( SCIPsetIsInfinity(set, -val) || SCIPsetIsInfinity(set, val) )
5421  {
5422  val = SCIPvarGetWorstBoundLocal(var);
5423 
5424  /* if both bounds are infinite, choose zero as branching point */
5425  if( SCIPsetIsInfinity(set, -val) || SCIPsetIsInfinity(set, val) )
5426  {
5427  assert(SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(var)));
5428  assert(SCIPsetIsInfinity(set, SCIPvarGetUbLocal(var)));
5429  val = 0.0;
5430  }
5431  }
5432  }
5433 
5434  assert(SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)));
5435  assert(SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)));
5436  /* see comment in SCIPbranchVarVal */
5437  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS ||
5438  SCIPrelDiff(SCIPvarGetUbLocal(var), SCIPvarGetLbLocal(var)) <= 2.02 * SCIPsetEpsilon(set) ||
5439  SCIPsetIsInfinity(set, -2.1*SCIPvarGetLbLocal(var)) || SCIPsetIsInfinity(set, 2.1*SCIPvarGetUbLocal(var)) ||
5440  (SCIPsetIsLT(set, 2.1*SCIPvarGetLbLocal(var), 2.1*val) && SCIPsetIsLT(set, 2.1*val, 2.1*SCIPvarGetUbLocal(var))) );
5441 
5442  downub = SCIP_INVALID;
5443  fixval = SCIP_INVALID;
5444  uplb = SCIP_INVALID;
5445 
5447  {
5448  if( SCIPsetIsRelEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) )
5449  {
5450  SCIPsetDebugMsg(set, "fixing continuous variable <%s> with value %g and bounds [%.15g, %.15g], priority %d (current lower bound: %g)\n",
5452 
5453  /* if val is at least epsilon away from both bounds, then we change both bounds to this value
5454  * otherwise, we fix the variable to its worst bound
5455  */
5456  if( SCIPsetIsGT(set, val, SCIPvarGetLbLocal(var)) && SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var)) )
5457  {
5458  SCIP_CALL( SCIPnodeAddBoundchg(tree->focusnode, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
5459  branchcand, eventqueue, NULL, var, val, SCIP_BOUNDTYPE_LOWER, FALSE) );
5460  SCIP_CALL( SCIPnodeAddBoundchg(tree->focusnode, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
5461  branchcand, eventqueue, NULL, var, val, SCIP_BOUNDTYPE_UPPER, FALSE) );
5462  }
5463  else if( SCIPvarGetObj(var) >= 0.0 )
5464  {
5465  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob,
5466  tree, reopt, lp, branchcand, eventqueue, NULL, var, SCIPvarGetUbLocal(var), SCIP_BOUNDTYPE_LOWER, FALSE) );
5467  }
5468  else
5469  {
5470  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob,
5471  tree, reopt, lp, branchcand, eventqueue, NULL, var, SCIPvarGetLbLocal(var), SCIP_BOUNDTYPE_UPPER, FALSE) );
5472  }
5473  }
5474  else if( SCIPrelDiff(SCIPvarGetUbLocal(var), SCIPvarGetLbLocal(var)) <= 2.02 * SCIPsetEpsilon(set) )
5475  {
5476  /* if the only way to branch is such that in both sides the relative domain width becomes smaller epsilon,
5477  * then fix the variable in both branches right away
5478  *
5479  * however, if one of the bounds is at infinity (and thus the other bound is at most 2eps away from the same infinity (in relative sense),
5480  * then fix the variable to the non-infinite value, as we cannot fix a variable to infinity
5481  */
5482  SCIPsetDebugMsg(set, "continuous branch on variable <%s> with bounds [%.15g, %.15g], priority %d (current lower bound: %g), node %p\n",
5484  if( SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(var)) )
5485  {
5486  assert(!SCIPsetIsInfinity(set, -SCIPvarGetUbLocal(var)));
5487  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob,
5488  tree, reopt, lp, branchcand, eventqueue, NULL, var, SCIPvarGetUbLocal(var), SCIP_BOUNDTYPE_LOWER, FALSE) );
5489  }
5490  else if( SCIPsetIsInfinity(set, SCIPvarGetUbLocal(var)) )
5491  {
5492  assert(!SCIPsetIsInfinity(set, SCIPvarGetLbLocal(var)));
5493  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob,
5494  tree, reopt, lp, branchcand, eventqueue, NULL, var, SCIPvarGetLbLocal(var), SCIP_BOUNDTYPE_UPPER, FALSE) );
5495  }
5496  else
5497  {
5498  downub = SCIPvarGetLbLocal(var);
5499  uplb = SCIPvarGetUbLocal(var);
5500  }
5501  }
5502  else
5503  {
5504  /* in the general case, there is enough space for two branches
5505  * a sophisticated user should have also chosen the branching value such that it is not very close to the bounds
5506  * so here we only ensure that it is at least epsilon away from both bounds
5507  */
5508  SCIPsetDebugMsg(set, "continuous branch on variable <%s> with value %g, priority %d (current lower bound: %g)\n",
5510  downub = MIN(val, SCIPvarGetUbLocal(var) - SCIPsetEpsilon(set)); /*lint !e666*/
5511  uplb = MAX(val, SCIPvarGetLbLocal(var) + SCIPsetEpsilon(set)); /*lint !e666*/
5512  }
5513  }
5514  else if( SCIPsetIsFeasIntegral(set, val) )
5515  {
5516  SCIP_Real lb;
5517  SCIP_Real ub;
5518 
5519  lb = SCIPvarGetLbLocal(var);
5520  ub = SCIPvarGetUbLocal(var);
5521 
5522  /* if there was no explicit value given for branching, the variable has a finite domain and the current LP/pseudo
5523  * solution is one of the bounds, we branch in the center of the domain */
5524  if( !validval && !SCIPsetIsInfinity(set, -lb) && !SCIPsetIsInfinity(set, ub)
5525  && (SCIPsetIsFeasEQ(set, val, lb) || SCIPsetIsFeasEQ(set, val, ub)) )
5526  {
5527  SCIP_Real center;
5528 
5529  /* create child nodes with x <= x", and x >= x"+1 with x" = floor((lb + ub)/2);
5530  * if x" is integral, make the interval smaller in the child in which the current solution x'
5531  * is still feasible
5532  */
5533  center = (ub + lb) / 2.0;
5534  if( val <= center )
5535  {
5536  downub = SCIPsetFeasFloor(set, center);
5537  uplb = downub + 1.0;
5538  }
5539  else
5540  {
5541  uplb = SCIPsetFeasCeil(set, center);
5542  downub = uplb - 1.0;
5543  }
5544  }
5545  else
5546  {
5547  /* create child nodes with x <= x'-1, x = x', and x >= x'+1 */
5548  assert(SCIPsetIsEQ(set, SCIPsetFeasCeil(set, val), SCIPsetFeasFloor(set, val)));
5549 
5550  fixval = SCIPsetFeasCeil(set, val); /* get rid of numerical issues */
5551 
5552  /* create child node with x <= x'-1, if this would be feasible */
5553  if( SCIPsetIsFeasGE(set, fixval-1.0, lb) )
5554  downub = fixval - 1.0;
5555 
5556  /* create child node with x >= x'+1, if this would be feasible */
5557  if( SCIPsetIsFeasLE(set, fixval+1.0, ub) )
5558  uplb = fixval + 1.0;
5559  }
5560  SCIPsetDebugMsg(set, "integral branch on variable <%s> with value %g, priority %d (current lower bound: %g)\n",
5562  }
5563  else
5564  {
5565  /* create child nodes with x <= floor(x'), and x >= ceil(x') */
5566  downub = SCIPsetFeasFloor(set, val);
5567  uplb = downub + 1.0;
5568  assert( SCIPsetIsRelEQ(set, SCIPsetFeasCeil(set, val), uplb) );
5569  SCIPsetDebugMsg(set, "fractional branch on variable <%s> with value %g, root value %g, priority %d (current lower bound: %g)\n",
5571  }
5572 
5573  /* perform the branching;
5574  * set the node selection priority in a way, s.t. a node is preferred whose branching goes in the same direction
5575  * as the deviation from the variable's root solution
5576  */
5577  if( downub != SCIP_INVALID ) /*lint !e777*/
5578  {
5579  /* create child node x <= downub */
5580  priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_DOWNWARDS, downub);
5581  /* if LP solution is cutoff in child, compute a new estimate
5582  * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node */
5583  if( SCIPsetIsGT(set, lpval, downub) )
5584  estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, downub);
5585  else
5586  estimate = SCIPnodeGetEstimate(tree->focusnode);
5587  SCIPsetDebugMsg(set, " -> creating child: <%s> <= %g (priority: %g, estimate: %g)\n",
5588  SCIPvarGetName(var), downub, priority, estimate);
5589  SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
5590  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
5591  NULL, var, downub, SCIP_BOUNDTYPE_UPPER, FALSE) );
5592  /* output branching bound change to visualization file */
5593  SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
5594 
5595  if( downchild != NULL )
5596  *downchild = node;
5597  }
5598 
5599  if( fixval != SCIP_INVALID ) /*lint !e777*/
5600  {
5601  /* create child node with x = fixval */
5602  priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_FIXED, fixval);
5603  estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, fixval);
5604  SCIPsetDebugMsg(set, " -> creating child: <%s> == %g (priority: %g, estimate: %g)\n",
5605  SCIPvarGetName(var), fixval, priority, estimate);
5606  SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
5607  if( !SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), fixval) )
5608  {
5609  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
5610  NULL, var, fixval, SCIP_BOUNDTYPE_LOWER, FALSE) );
5611  }
5612  if( !SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), fixval) )
5613  {
5614  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
5615  NULL, var, fixval, SCIP_BOUNDTYPE_UPPER, FALSE) );
5616  }
5617  /* output branching bound change to visualization file */
5618  SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
5619 
5620  if( eqchild != NULL )
5621  *eqchild = node;
5622  }
5623 
5624  if( uplb != SCIP_INVALID ) /*lint !e777*/
5625  {
5626  /* create child node with x >= uplb */
5627  priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_UPWARDS, uplb);
5628  if( SCIPsetIsLT(set, lpval, uplb) )
5629  estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, uplb);
5630  else
5631  estimate = SCIPnodeGetEstimate(tree->focusnode);
5632  SCIPsetDebugMsg(set, " -> creating child: <%s> >= %g (priority: %g, estimate: %g)\n",
5633  SCIPvarGetName(var), uplb, priority, estimate);
5634  SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
5635  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
5636  NULL, var, uplb, SCIP_BOUNDTYPE_LOWER, FALSE) );
5637  /* output branching bound change to visualization file */
5638  SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
5639 
5640  if( upchild != NULL )
5641  *upchild = node;
5642  }
5643 
5644 
5645  return SCIP_OKAY;
5646 }
5647 
5648 /** branches a variable x using the given domain hole; two child nodes will be created (x <= left, x >= right) */
5650  SCIP_TREE* tree, /**< branch and bound tree */
5651  SCIP_REOPT* reopt, /**< reoptimization data structure */
5652  BMS_BLKMEM* blkmem, /**< block memory */
5653  SCIP_SET* set, /**< global SCIP settings */
5654  SCIP_STAT* stat, /**< problem statistics data */
5655  SCIP_PROB* transprob, /**< transformed problem after presolve */
5656  SCIP_PROB* origprob, /**< original problem */
5657  SCIP_LP* lp, /**< current LP data */
5658  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5659  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5660  SCIP_VAR* var, /**< variable to branch on */
5661  SCIP_Real left, /**< left side of the domain hole */
5662  SCIP_Real right, /**< right side of the domain hole */
5663  SCIP_NODE** downchild, /**< pointer to return the left child with variable rounded down, or NULL */
5664  SCIP_NODE** upchild /**< pointer to return the right child with variable rounded up, or NULL */
5665  )
5666 {
5667  SCIP_NODE* node;
5668  SCIP_Real priority;
5669  SCIP_Real estimate;
5670  SCIP_Real lpval;
5671 
5672  assert(tree != NULL);
5673  assert(set != NULL);
5674  assert(var != NULL);
5675  assert(SCIPsetIsLT(set, left, SCIPvarGetUbLocal(var)));
5676  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
5677  assert(SCIPsetIsGT(set, right, SCIPvarGetLbLocal(var)));
5678  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
5679  assert(SCIPsetIsLE(set, left, right));
5680 
5681  /* initialize children pointer */
5682  if( downchild != NULL )
5683  *downchild = NULL;
5684  if( upchild != NULL )
5685  *upchild = NULL;
5686 
5687  /* get the corresponding active problem variable */
5688  SCIP_CALL( SCIPvarGetProbvarHole(&var, &left, &right) );
5689 
5691  {
5692  SCIPerrorMessage("cannot branch on fixed or multi-aggregated variable <%s>\n", SCIPvarGetName(var));
5693  SCIPABORT();
5694  return SCIP_INVALIDDATA; /*lint !e527*/
5695  }
5696 
5697  assert(SCIPvarIsActive(var));
5698  assert(SCIPvarGetProbindex(var) >= 0);
5702  assert(SCIPsetIsLT(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)));
5703 
5704  assert(SCIPsetIsFeasGE(set, left, SCIPvarGetLbLocal(var)));
5705  assert(SCIPsetIsFeasLE(set, right, SCIPvarGetUbLocal(var)));
5706 
5707  /* adjust left and right side of the domain hole if the variable is integral */
5708  if( SCIPvarIsIntegral(var) )
5709  {
5710  left = SCIPsetFeasFloor(set, left);
5711  right = SCIPsetFeasCeil(set, right);
5712  }
5713 
5714  assert(SCIPsetIsLT(set, left, SCIPvarGetUbLocal(var)));
5715  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
5716  assert(SCIPsetIsGT(set, right, SCIPvarGetLbLocal(var)));
5717  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
5718  assert(SCIPsetIsLE(set, left, right));
5719 
5720  /* get value of variable in current LP or pseudo solution */
5721  lpval = SCIPvarGetSol(var, tree->focusnodehaslp);
5722 
5723  /* perform the branching;
5724  * set the node selection priority in a way, s.t. a node is preferred whose branching goes in the same direction
5725  * as the deviation from the variable's root solution
5726  */
5727 
5728  /* create child node x <= left */
5729  priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_DOWNWARDS, left);
5730 
5731  /* if LP solution is cutoff in child, compute a new estimate
5732  * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node
5733  */
5734  if( SCIPsetIsGT(set, lpval, left) )
5735  estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, left);
5736  else
5737  estimate = SCIPnodeGetEstimate(tree->focusnode);
5738 
5739  SCIPsetDebugMsg(set, " -> creating child: <%s> <= %g (priority: %g, estimate: %g)\n",
5740  SCIPvarGetName(var), left, priority, estimate);
5741 
5742  SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
5743  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue, NULL,
5744  var, left, SCIP_BOUNDTYPE_UPPER, FALSE) );
5745  /* output branching bound change to visualization file */
5746  SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
5747 
5748  if( downchild != NULL )
5749  *downchild = node;
5750 
5751  /* create child node with x >= right */
5752  priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_UPWARDS, right);
5753 
5754  if( SCIPsetIsLT(set, lpval, right) )
5755  estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, right);
5756  else
5757  estimate = SCIPnodeGetEstimate(tree->focusnode);
5758 
5759  SCIPsetDebugMsg(set, " -> creating child: <%s> >= %g (priority: %g, estimate: %g)\n",
5760  SCIPvarGetName(var), right, priority, estimate);
5761 
5762  SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
5763  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
5764  NULL, var, right, SCIP_BOUNDTYPE_LOWER, FALSE) );
5765  /* output branching bound change to visualization file */
5766  SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
5767 
5768  if( upchild != NULL )
5769  *upchild = node;
5770 
5771  return SCIP_OKAY;
5772 }
5773 
5774 /** n-ary branching on a variable x
5775  * Branches on variable x such that up to n/2 children are created on each side of the usual branching value.
5776  * The branching value is selected as in SCIPtreeBranchVar().
5777  * If n is 2 or the variables local domain is too small for a branching into n pieces, SCIPtreeBranchVar() is called.
5778  * The parameters minwidth and widthfactor determine the domain width of the branching variable in the child nodes.
5779  * If n is odd, one child with domain width 'width' and having the branching value in the middle is created.
5780  * Otherwise, two children with domain width 'width' and being left and right of the branching value are created.
5781  * Next further nodes to the left and right are created, where width is multiplied by widthfactor with increasing distance from the first nodes.
5782  * The initial width is calculated such that n/2 nodes are created to the left and to the right of the branching value.
5783  * If this value is below minwidth, the initial width is set to minwidth, which may result in creating less than n nodes.
5784  *
5785  * Giving a large value for widthfactor results in creating children with small domain when close to the branching value
5786  * and large domain when closer to the current variable bounds. That is, setting widthfactor to a very large value and n to 3
5787  * results in a ternary branching where the branching variable is mostly fixed in the middle child.
5788  * Setting widthfactor to 1.0 results in children where the branching variable always has the same domain width
5789  * (except for one child if the branching value is not in the middle).
5790  */
5792  SCIP_TREE* tree, /**< branch and bound tree */
5793  SCIP_REOPT* reopt, /**< reoptimization data structure */
5794  BMS_BLKMEM* blkmem, /**< block memory */
5795  SCIP_SET* set, /**< global SCIP settings */
5796  SCIP_STAT* stat, /**< problem statistics data */
5797  SCIP_PROB* transprob, /**< transformed problem after presolve */
5798  SCIP_PROB* origprob, /**< original problem */
5799  SCIP_LP* lp, /**< current LP data */
5800  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5801  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5802  SCIP_VAR* var, /**< variable to branch on */
5803  SCIP_Real val, /**< value to branch on or SCIP_INVALID for branching on current LP/pseudo solution.
5804  * A branching value is required for branching on continuous variables */
5805  int n, /**< attempted number of children to be created, must be >= 2 */
5806  SCIP_Real minwidth, /**< minimal domain width in children */
5807  SCIP_Real widthfactor, /**< multiplier for children domain width with increasing distance from val, must be >= 1.0 */
5808  int* nchildren /**< buffer to store number of created children, or NULL */
5809  )
5810 {
5811  SCIP_NODE* node;
5812  SCIP_Real priority;
5813  SCIP_Real estimate;
5814  SCIP_Real lpval;
5815  SCIP_Real width;
5816  SCIP_Bool validval;
5817  SCIP_Real left;
5818  SCIP_Real right;
5819  SCIP_Real bnd;
5820  int i;
5821 
5822  assert(tree != NULL);
5823  assert(set != NULL);
5824  assert(var != NULL);
5825  assert(n >= 2);
5826  assert(minwidth >= 0.0);
5827 
5828  /* if binary branching is requested or we have not enough space for n children, delegate to SCIPtreeBranchVar */
5829  if( n == 2 ||
5830  2.0 * minwidth >= SCIPvarGetUbLocal(var) - SCIPvarGetLbLocal(var) ||
5832  {
5833  SCIP_NODE* downchild;
5834  SCIP_NODE* fixchild;
5835  SCIP_NODE* upchild;
5836 
5837  SCIP_CALL( SCIPtreeBranchVar(tree, reopt, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue, var, val,
5838  &downchild, &fixchild, &upchild) );
5839 
5840  if( nchildren != NULL )
5841  *nchildren = (downchild != NULL ? 1 : 0) + (fixchild != NULL ? 1 : 0) + (upchild != NULL ? 1 : 0);
5842 
5843  return SCIP_OKAY;
5844  }
5845 
5846  /* store whether a valid value was given for branching */
5847  validval = (val != SCIP_INVALID); /*lint !e777 */
5848 
5849  /* get the corresponding active problem variable
5850  * if branching value is given, then transform it to the value of the active variable */
5851  if( validval )
5852  {
5853  SCIP_Real scalar;
5854  SCIP_Real constant;
5855 
5856  scalar = 1.0;
5857  constant = 0.0;
5858 
5859  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &constant) );
5860 
5861  if( scalar == 0.0 )
5862  {
5863  SCIPerrorMessage("cannot branch on fixed variable <%s>\n", SCIPvarGetName(var));
5864  return SCIP_INVALIDDATA;
5865  }
5866 
5867  /* we should have givenvariable = scalar * activevariable + constant */
5868  val = (val - constant) / scalar;
5869  }
5870  else
5871  var = SCIPvarGetProbvar(var);
5872 
5874  {
5875  SCIPerrorMessage("cannot branch on fixed or multi-aggregated variable <%s>\n", SCIPvarGetName(var));
5876  SCIPABORT();
5877  return SCIP_INVALIDDATA; /*lint !e527*/
5878  }
5879 
5880  /* ensure, that branching on continuous variables will only be performed when a branching point is given. */
5881  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS && !validval )
5882  {
5883  SCIPerrorMessage("Cannot branch on continuous variables without a given branching value.\n", SCIPvarGetName(var));
5884  SCIPABORT();
5885  return SCIP_INVALIDDATA; /*lint !e527*/
5886  }
5887 
5888  assert(SCIPvarIsActive(var));
5889  assert(SCIPvarGetProbindex(var) >= 0);
5893  assert(SCIPsetIsLT(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)));
5894 
5895  /* get value of variable in current LP or pseudo solution */
5896  lpval = SCIPvarGetSol(var, tree->focusnodehaslp);
5897 
5898  /* if there was no explicit value given for branching, branch on current LP or pseudo solution value */
5899  if( !validval )
5900  {
5901  val = lpval;
5902 
5903  /* avoid branching on infinite values in pseudo solution */
5904  if( SCIPsetIsInfinity(set, -val) || SCIPsetIsInfinity(set, val) )
5905  {
5906  val = SCIPvarGetWorstBoundLocal(var);
5907 
5908  /* if both bounds are infinite, choose zero as branching point */
5909  if( SCIPsetIsInfinity(set, -val) || SCIPsetIsInfinity(set, val) )
5910  {
5911  assert(SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(var)));
5912  assert(SCIPsetIsInfinity(set, SCIPvarGetUbLocal(var)));
5913  val = 0.0;
5914  }
5915  }
5916  }
5917 
5918  assert(SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)));
5919  assert(SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)));
5920  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS ||
5922  (SCIPsetIsLT(set, 2.1*SCIPvarGetLbLocal(var), 2.1*val) && SCIPsetIsLT(set, 2.1*val, 2.1*SCIPvarGetUbLocal(var))) ); /* see comment in SCIPbranchVarVal */
5923 
5924  /* calculate minimal distance of val from bounds */
5925  width = SCIP_REAL_MAX;
5926  if( !SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(var)) )
5927  {
5928  width = val - SCIPvarGetLbLocal(var);
5929  }
5930  if( !SCIPsetIsInfinity(set, SCIPvarGetUbLocal(var)) )
5931  {
5932  width = MIN(width, SCIPvarGetUbLocal(var) - val); /*lint !e666*/
5933  }
5934  /* calculate initial domain width of child nodes
5935  * if we have at least one finite bound, choose width such that we have roughly the same number of nodes left and right of val
5936  */
5937  if( width == SCIP_REAL_MAX ) /*lint !e777*/
5938  {
5939  /* unbounded variable, let's create a child with a small domain */
5940  width = 1.0;
5941  }
5942  else if( widthfactor == 1.0 )
5943  {
5944  /* most domains get same size */
5945  width /= n/2; /*lint !e653*/ /* rounding is ok at this point */
5946  }
5947  else
5948  {
5949  /* width is increased by widthfactor for each child
5950  * if n is even, compute width such that we can create n/2 nodes with width
5951  * width, widthfactor*width, ..., widthfactor^(n/2)*width on each side, i.e.,
5952  * sum(width * widthfactor^(i-1), i = 1..n/2) = min(ub-val, val-lb)
5953  * <-> width * (widthfactor^(n/2) - 1) / (widthfactor - 1) = min(ub-val, val-lb)
5954  *
5955  * if n is odd, compute width such that we can create one middle node with width width
5956  * and n/2 nodes with width widthfactor*width, ..., widthfactor^(n/2)*width on each side, i.e.,
5957  * width/2 + sum(width * widthfactor^i, i = 1..n/2) = min(ub-val, val-lb)
5958  * <-> width * (1/2 + widthfactor * (widthfactor^(n/2) - 1) / (widthfactor - 1) = min(ub-val, val-lb)
5959  */
5960  assert(widthfactor > 1.0);
5961  if( n % 2 == 0 )
5962  width *= (widthfactor - 1.0) / (pow(widthfactor, (SCIP_Real)(n/2)) - 1.0); /*lint !e653*/
5963  else
5964  width /= 0.5 + widthfactor * (pow(widthfactor, (SCIP_Real)(n/2)) - 1.0) / (widthfactor - 1.0); /*lint !e653*/
5965  }
5967  minwidth = MAX(1.0, minwidth);
5968  if( width < minwidth )
5969  width = minwidth;
5970  assert(SCIPsetIsPositive(set, width));
5971 
5972  SCIPsetDebugMsg(set, "%d-ary branching on variable <%s> [%g, %g] around %g, initial width = %g\n",
5973  n, SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), val, width);
5974 
5975  if( nchildren != NULL )
5976  *nchildren = 0;
5977 
5978  /* initialize upper bound on children left of val and children right of val
5979  * if we are supposed to create an odd number of children, then create a child that has val in the middle of its domain */
5980  if( n % 2 == 1 )
5981  {
5982  left = val - width/2.0;
5983  right = val + width/2.0;
5984  SCIPvarAdjustLb(var, set, &left);
5985  SCIPvarAdjustUb(var, set, &right);
5986 
5987  /* create child node left <= x <= right, if left <= right */
5988  if( left <= right )
5989  {
5990  priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_FIXED, val); /* ????????????? how to compute priority for such a child? */
5991  /* if LP solution is cutoff in child, compute a new estimate
5992  * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node */
5993  if( SCIPsetIsLT(set, lpval, left) )
5994  estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, left);
5995  else if( SCIPsetIsGT(set, lpval, right) )
5996  estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, right);
5997  else
5998  estimate = SCIPnodeGetEstimate(tree->focusnode);
5999 
6000  SCIPsetDebugMsg(set, " -> creating middle child: %g <= <%s> <= %g (priority: %g, estimate: %g, width: %g)\n",
6001  left, SCIPvarGetName(var), right, priority, estimate, right - left);
6002 
6003  SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
6004  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
6005  eventqueue, NULL, var, left , SCIP_BOUNDTYPE_LOWER, FALSE) );
6006  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
6007  NULL, var, right, SCIP_BOUNDTYPE_UPPER, FALSE) );
6008  /* output branching bound change to visualization file */
6009  SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
6010 
6011  if( nchildren != NULL )
6012  ++*nchildren;
6013  }
6014  --n;
6015 
6017  {
6018  /* if it's a discrete variable, we can use left-1 and right+1 as upper and lower bounds for following nodes on the left and right, resp. */
6019  left -= 1.0;
6020  right += 1.0;
6021  }
6022 
6023  width *= widthfactor;
6024  }
6025  else
6026  {
6028  {
6029  left = SCIPsetFloor(set, val);
6030  right = SCIPsetCeil(set, val);
6031  if( right - left < 0.5 )
6032  left -= 1.0;
6033  }
6034  else if( SCIPsetIsZero(set, val) )
6035  {
6036  left = 0.0;
6037  right = 0.0;
6038  }
6039  else
6040  {
6041  left = val;
6042  right = val;
6043  }
6044  }
6045 
6046  assert(n % 2 == 0);
6047  n /= 2;
6048  for( i = 0; i < n; ++i )
6049  {
6050  /* create child node left - width <= x <= left, if left > lb(x) or x is discrete */
6052  {
6053  /* new lower bound should be variables lower bound, if we are in the last round or left - width is very close to lower bound
6054  * otherwise we take left - width
6055  */
6056  if( i == n-1 || SCIPsetIsRelEQ(set, SCIPvarGetLbLocal(var), left - width))
6057  {
6058  bnd = SCIPvarGetLbLocal(var);
6059  }
6060  else
6061  {
6062  bnd = left - width;
6063  SCIPvarAdjustLb(var, set, &bnd);
6064  bnd = MAX(SCIPvarGetLbLocal(var), bnd); /*lint !e666*/
6065  }
6066  assert(SCIPsetIsRelLT(set, bnd, left));
6067 
6068  /* the nodeselection priority of nodes is decreased as more as they are away from val */
6069  priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_DOWNWARDS, bnd) / (i+1);
6070  /* if LP solution is cutoff in child, compute a new estimate
6071  * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node */
6072  if( SCIPsetIsLT(set, lpval, bnd) )
6073  estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, bnd);
6074  else if( SCIPsetIsGT(set, lpval, left) )
6075  estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, left);
6076  else
6077  estimate = SCIPnodeGetEstimate(tree->focusnode);
6078 
6079  SCIPsetDebugMsg(set, " -> creating left child: %g <= <%s> <= %g (priority: %g, estimate: %g, width: %g)\n",
6080  bnd, SCIPvarGetName(var), left, priority, estimate, left - bnd);
6081 
6082  SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
6083  if( SCIPsetIsGT(set, bnd, SCIPvarGetLbLocal(var)) )
6084  {
6085  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
6086  NULL, var, bnd, SCIP_BOUNDTYPE_LOWER, FALSE) );
6087  }
6088  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
6089  NULL, var, left, SCIP_BOUNDTYPE_UPPER, FALSE) );
6090  /* output branching bound change to visualization file */
6091  SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
6092 
6093  if( nchildren != NULL )
6094  ++*nchildren;
6095 
6096  left = bnd;
6098  left -= 1.0;
6099  }
6100 
6101  /* create child node right <= x <= right + width, if right < ub(x) */
6102  if( SCIPsetIsRelGT(set, SCIPvarGetUbLocal(var), right) || SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS )
6103  {
6104  /* new upper bound should be variables upper bound, if we are in the last round or right + width is very close to upper bound
6105  * otherwise we take right + width
6106  */
6107  if( i == n-1 || SCIPsetIsRelEQ(set, SCIPvarGetUbLocal(var), right + width))
6108  {
6109  bnd = SCIPvarGetUbLocal(var);
6110  }
6111  else
6112  {
6113  bnd = right + width;
6114  SCIPvarAdjustUb(var, set, &bnd);
6115  bnd = MIN(SCIPvarGetUbLocal(var), bnd); /*lint !e666*/
6116  }
6117  assert(SCIPsetIsRelGT(set, bnd, right));
6118 
6119  /* the nodeselection priority of nodes is decreased as more as they are away from val */
6120  priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_UPWARDS, bnd) / (i+1);
6121  /* if LP solution is cutoff in child, compute a new estimate
6122  * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node */
6123  if( SCIPsetIsLT(set, lpval, right) )
6124  estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, right);
6125  else if( SCIPsetIsGT(set, lpval, bnd) )
6126  estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, bnd);
6127  else
6128  estimate = SCIPnodeGetEstimate(tree->focusnode);
6129 
6130  SCIPsetDebugMsg(set, " -> creating right child: %g <= <%s> <= %g (priority: %g, estimate: %g, width: %g)\n",
6131  right, SCIPvarGetName(var), bnd, priority, estimate, bnd - right);
6132 
6133  SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
6134  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
6135  NULL, var, right, SCIP_BOUNDTYPE_LOWER, FALSE) );
6136  if( SCIPsetIsLT(set, bnd, SCIPvarGetUbLocal(var)) )
6137  {
6138  SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
6139  NULL, var, bnd, SCIP_BOUNDTYPE_UPPER, FALSE) );
6140  }
6141  /* output branching bound change to visualization file */
6142  SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
6143 
6144  if( nchildren != NULL )
6145  ++*nchildren;
6146 
6147  right = bnd;
6149  right += 1.0;
6150  }
6151 
6152  width *= widthfactor;
6153  }
6154 
6155  return SCIP_OKAY;
6156 }
6157 
6158 /** adds a diving bound change to the tree together with the information if this is a bound change
6159  * for the preferred direction or not
6160  */
6161 #define ARRAYGROWTH 5
6163  SCIP_TREE* tree, /**< branch and bound tree */
6164  BMS_BLKMEM* blkmem, /**< block memory buffers */
6165  SCIP_VAR* var, /**< variable to apply the bound change to */
6166  SCIP_BRANCHDIR dir, /**< direction of the bound change */
6167  SCIP_Real value, /**< value to adjust this variable bound to */
6168  SCIP_Bool preferred /**< is this a bound change for the preferred child? */
6169  )
6170 {
6171  int idx = preferred ? 0 : 1;
6172  int pos = tree->ndivebdchanges[idx];
6173 
6174  assert(pos < tree->divebdchgsize[idx]);
6175 
6176  if( pos == tree->divebdchgsize[idx] - 1 )
6177  {
6178  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tree->divebdchgdirs[idx], tree->divebdchgsize[idx], tree->divebdchgsize[idx] + ARRAYGROWTH) ); /*lint !e866*/
6179  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tree->divebdchgvars[idx], tree->divebdchgsize[idx], tree->divebdchgsize[idx] + ARRAYGROWTH) ); /*lint !e866*/
6180  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tree->divebdchgvals[idx], tree->divebdchgsize[idx], tree->divebdchgsize[idx] + ARRAYGROWTH) ); /*lint !e866*/
6181  tree->divebdchgsize[idx] += ARRAYGROWTH;
6182  }
6183 
6184  tree->divebdchgvars[idx][pos] = var;
6185  tree->divebdchgdirs[idx][pos] = dir;
6186  tree->divebdchgvals[idx][pos] = value;
6187 
6188  ++tree->ndivebdchanges[idx];
6189 
6190  return SCIP_OKAY;
6191 }
6192 
6193 /** get the dive bound change data for the preferred or the alternative direction */
6195  SCIP_TREE* tree, /**< branch and bound tree */
6196  SCIP_VAR*** variables, /**< pointer to store variables for the specified direction */
6197  SCIP_BRANCHDIR** directions, /**< pointer to store the branching directions */
6198  SCIP_Real** values, /**< pointer to store bound change values */
6199  int* ndivebdchgs, /**< pointer to store the number of dive bound changes */
6200  SCIP_Bool preferred /**< should the dive bound changes for the preferred child be output? */
6201  )
6202 {
6203  int idx = preferred ? 0 : 1;
6204 
6205  assert(variables != NULL);
6206  assert(directions != NULL);
6207  assert(values != NULL);
6208  assert(ndivebdchgs != NULL);
6209 
6210  *variables = tree->divebdchgvars[idx];
6211  *directions = tree->divebdchgdirs[idx];
6212  *values = tree->divebdchgvals[idx];
6213  *ndivebdchgs = tree->ndivebdchanges[idx];
6214 }
6215 
6216 /** clear the tree bound change data structure */
6218  SCIP_TREE* tree /**< branch and bound tree */
6219  )
6220 {
6221  int p;
6222 
6223  for( p = 0; p < 2; ++p )
6224  tree->ndivebdchanges[p] = 0;
6225 }
6226 
6227 /** creates a probing child node of the current node, which must be the focus node, the current refocused node,
6228  * or another probing node; if the current node is the focus or a refocused node, the created probing node is
6229  * installed as probing root node
6230  */
6231 static
6233  SCIP_TREE* tree, /**< branch and bound tree */
6234  BMS_BLKMEM* blkmem, /**< block memory */
6235  SCIP_SET* set, /**< global SCIP settings */
6236  SCIP_LP* lp /**< current LP data */
6237  )
6238 {
6239  SCIP_NODE* currentnode;
6240  SCIP_NODE* node;
6241  SCIP_RETCODE retcode;
6242 
6243  assert(tree != NULL);
6244  assert(SCIPtreeIsPathComplete(tree));
6245  assert(tree->pathlen > 0);
6246  assert(blkmem != NULL);
6247  assert(set != NULL);
6248 
6249  /* get the current node */
6250  currentnode = SCIPtreeGetCurrentNode(tree);
6251  assert(SCIPnodeGetType(currentnode) == SCIP_NODETYPE_FOCUSNODE
6252  || SCIPnodeGetType(currentnode) == SCIP_NODETYPE_REFOCUSNODE
6253  || SCIPnodeGetType(currentnode) == SCIP_NODETYPE_PROBINGNODE);
6254  assert((SCIPnodeGetType(currentnode) == SCIP_NODETYPE_PROBINGNODE) == SCIPtreeProbing(tree));
6255 
6256  /* create the node data structure */
6257  SCIP_CALL( nodeCreate(&node, blkmem, set) );
6258  assert(node != NULL);
6259 
6260  /* mark node to be a probing node */
6261  node->nodetype = SCIP_NODETYPE_PROBINGNODE; /*lint !e641*/
6262 
6263  /* create the probingnode data */
6264  SCIP_CALL( probingnodeCreate(&node->data.probingnode, blkmem, lp) );
6265 
6266  /* make the current node the parent of the new probing node */
6267  retcode = nodeAssignParent(node, blkmem, set, tree, currentnode, 0.0);
6268 
6269  /* if we reached the maximal depth level we clean up the allocated memory and stop */
6270  if( retcode == SCIP_MAXDEPTHLEVEL )
6271  {
6272  SCIP_CALL( probingnodeFree(&(node->data.probingnode), blkmem, lp) );
6273  BMSfreeBlockMemory(blkmem, &node);
6274  }
6275  SCIP_CALL( retcode );
6276  assert(SCIPnodeGetDepth(node) == tree->pathlen);
6277 
6278  /* check, if the node is the probing root node */
6279  if( tree->probingroot == NULL )
6280  {
6281  tree->probingroot = node;
6282  SCIPsetDebugMsg(set, "created probing root node #%" SCIP_LONGINT_FORMAT " at depth %d\n",
6283  SCIPnodeGetNumber(node), SCIPnodeGetDepth(node));
6284  }
6285  else
6286  {
6288  assert(SCIPnodeGetDepth(tree->probingroot) < SCIPnodeGetDepth(node));
6289 
6290  SCIPsetDebugMsg(set, "created probing child node #%" SCIP_LONGINT_FORMAT " at depth %d, probing depth %d\n",
6292  }
6293 
6294  /* create the new active path */
6295  SCIP_CALL( treeEnsurePathMem(tree, set, tree->pathlen+1) );
6296  node->active = TRUE;
6297  tree->path[tree->pathlen] = node;
6298  tree->pathlen++;
6299 
6300  /* update the path LP size for the previous node and set the (initial) path LP size for the newly created node */
6301  SCIP_CALL( treeUpdatePathLPSize(tree, tree->pathlen-2) );
6302 
6303  /* mark the LP's size */
6304  SCIPlpMarkSize(lp);
6305  assert(tree->pathlen >= 2);
6306  assert(lp->firstnewrow == tree->pathnlprows[tree->pathlen-1]); /* marked LP size should be initial size of new node */
6307  assert(lp->firstnewcol == tree->pathnlpcols[tree->pathlen-1]);
6308 
6309  /* the current probing node does not yet have a solved LP */
6310  tree->probingnodehaslp = FALSE;
6311 
6312  return SCIP_OKAY;
6313 }
6314 
6315 /** switches to probing mode and creates a probing root */
6317  SCIP_TREE* tree, /**< branch and bound tree */
6318  BMS_BLKMEM* blkmem, /**< block memory */
6319  SCIP_SET* set, /**< global SCIP settings */
6320  SCIP_LP* lp, /**< current LP data */
6321  SCIP_Bool strongbranching /**< is the probing mode used for strongbranching? */
6322  )
6323 {
6324  assert(tree != NULL);
6325  assert(tree->probinglpistate == NULL);
6326  assert(tree->probinglpinorms == NULL);
6327  assert(!SCIPtreeProbing(tree));
6328  assert(lp != NULL);
6329 
6330  SCIPsetDebugMsg(set, "probing started in depth %d (LP flushed: %u, LP solved: %u, solstat: %d), probing root in depth %d\n",
6331  tree->pathlen-1, lp->flushed, lp->solved, SCIPlpGetSolstat(lp), tree->pathlen);
6332 
6333  /* store all marked constraints for propagation */
6334  SCIP_CALL( SCIPconshdlrsStorePropagationStatus(set, set->conshdlrs, set->nconshdlrs) );
6335 
6336  /* inform LP about probing mode */
6338 
6339  assert(!lp->divingobjchg);
6340 
6341  /* remember, whether the LP was flushed and solved */
6342  tree->probinglpwasflushed = lp->flushed;
6343  tree->probinglpwassolved = lp->solved;
6344  tree->probingloadlpistate = FALSE;
6345  tree->probinglpwasrelax = lp->isrelax;
6346  lp->isrelax = TRUE;
6347  tree->probingsolvedlp = FALSE;
6348  tree->probingobjchanged = FALSE;
6349  lp->divingobjchg = FALSE;
6350  tree->probingsumchgdobjs = 0;
6351  tree->sbprobing = strongbranching;
6352 
6353  /* remember the LP state in order to restore the LP solution quickly after probing */
6354  /**@todo could the lp state be worth storing if the LP is not flushed (and hence not solved)? */
6355  if( lp->flushed && lp->solved )
6356  {
6357  SCIP_CALL( SCIPlpGetState(lp, blkmem, &tree->probinglpistate) );
6358  SCIP_CALL( SCIPlpGetNorms(lp, blkmem, &tree->probinglpinorms) );
6361  tree->probinglpwasdualfeas = lp->dualfeasible;
6363  }
6364 
6365  /* create temporary probing root node */
6366  SCIP_CALL( treeCreateProbingNode(tree, blkmem, set, lp) );
6367  assert(SCIPtreeProbing(tree));
6368 
6369  return SCIP_OKAY;
6370 }
6371 
6372 /** creates a new probing child node in the probing path */
6374  SCIP_TREE* tree, /**< branch and bound tree */
6375  BMS_BLKMEM* blkmem, /**< block memory */
6376  SCIP_SET* set, /**< global SCIP settings */
6377  SCIP_LP* lp /**< current LP data */
6378  )
6379 {
6380  assert(SCIPtreeProbing(tree));
6381 
6382  SCIPsetDebugMsg(set, "new probing child in depth %d (probing depth: %d)\n", tree->pathlen, tree->pathlen-1 - SCIPnodeGetDepth(tree->probingroot));
6383 
6384  /* create temporary probing root node */
6385  SCIP_CALL( treeCreateProbingNode(tree, blkmem, set, lp) );
6386 
6387  return SCIP_OKAY;
6388 }
6389 
6390 /** loads the LP state for the current probing node */
6392  SCIP_TREE* tree, /**< branch and bound tree */
6393  BMS_BLKMEM* blkmem, /**< block memory buffers */
6394  SCIP_SET* set, /**< global SCIP settings */
6395  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6396  SCIP_LP* lp /**< current LP data */
6397  )
6398 {
6399  assert(tree != NULL);
6400  assert(SCIPtreeProbing(tree));
6401 
6402  /* loading the LP state is only necessary if we backtracked */
6403  if( tree->probingloadlpistate )
6404  {
6405  SCIP_NODE* node;
6406  SCIP_LPISTATE* lpistate;
6407  SCIP_LPINORMS* lpinorms;
6408  SCIP_Bool lpwasprimfeas = FALSE;
6409  SCIP_Bool lpwasprimchecked = FALSE;
6410  SCIP_Bool lpwasdualfeas = FALSE;
6411  SCIP_Bool lpwasdualchecked = FALSE;
6412 
6413  /* get the current probing node */
6414  node = SCIPtreeGetCurrentNode(tree);
6415  assert(SCIPnodeGetType(node) == SCIP_NODETYPE_PROBINGNODE);
6416 
6417  /* search the last node where an LP state information was attached */
6418  lpistate = NULL;
6419  lpinorms = NULL;
6420  do
6421  {
6422  assert(SCIPnodeGetType(node) == SCIP_NODETYPE_PROBINGNODE);
6423  assert(node->data.probingnode != NULL);
6424  if( node->data.probingnode->lpistate != NULL )
6425  {
6426  lpistate = node->data.probingnode->lpistate;
6427  lpwasprimfeas = node->data.probingnode->lpwasprimfeas;
6428  lpwasprimchecked = node->data.probingnode->lpwasprimchecked;
6429  lpwasdualfeas = node->data.probingnode->lpwasdualfeas;
6430  lpwasdualchecked = node->data.probingnode->lpwasdualchecked;
6431  break;
6432  }
6433  node = node->parent;
6434  assert(node != NULL); /* the root node cannot be a probing node! */
6435  }
6436  while( SCIPnodeGetType(node) == SCIP_NODETYPE_PROBINGNODE );
6437 
6438  /* if there was no LP information stored in the probing nodes, use the one stored before probing started */
6439  if( lpistate == NULL )
6440  {
6441  lpistate = tree->probinglpistate;
6442  lpinorms = tree->probinglpinorms;
6443  lpwasprimfeas = tree->probinglpwasprimfeas;
6444  lpwasprimchecked = tree->probinglpwasprimchecked;
6445  lpwasdualfeas = tree->probinglpwasdualfeas;
6446  lpwasdualchecked = tree->probinglpwasdualchecked;
6447  }
6448 
6449  /* set the LP state */
6450  if( lpistate != NULL )
6451  {
6452  SCIP_CALL( SCIPlpSetState(lp, blkmem, set, eventqueue, lpistate,
6453  lpwasprimfeas, lpwasprimchecked, lpwasdualfeas, lpwasdualchecked) );
6454  }
6455 
6456  /* set the LP pricing norms */
6457  if( lpinorms != NULL )
6458  {
6459  SCIP_CALL( SCIPlpSetNorms(lp, blkmem, lpinorms) );
6460  }
6461 
6462  /* now we don't need to load the LP state again until the next backtracking */
6463  tree->probingloadlpistate = FALSE;
6464  }
6465 
6466  return SCIP_OKAY;
6467 }
6468 
6469 /** marks the probing node to have a solved LP relaxation */
6471  SCIP_TREE* tree, /**< branch and bound tree */
6472  BMS_BLKMEM* blkmem, /**< block memory */
6473  SCIP_LP* lp /**< current LP data */
6474  )
6475 {
6476  SCIP_NODE* node;
6477 
6478  assert(tree != NULL);
6479  assert(SCIPtreeProbing(tree));
6480 
6481  /* mark the probing node to have an LP */
6482  tree->probingnodehaslp = TRUE;
6483 
6484  /* get current probing node */
6485  node = SCIPtreeGetCurrentNode(tree);
6486  assert(SCIPnodeGetType(node) == SCIP_NODETYPE_PROBINGNODE);
6487  assert(node != NULL && node->data.probingnode != NULL);
6488 
6489  /* update LP information in probingnode data */
6490  /* cppcheck-suppress nullPointer */
6491  SCIP_CALL( probingnodeUpdate(node->data.probingnode, blkmem, tree, lp) );
6492 
6493  return SCIP_OKAY;
6494 }
6495 
6496 /** undoes all changes to the problem applied in probing up to the given probing depth */
6497 static
6499  SCIP_TREE* tree, /**< branch and bound tree */
6500  SCIP_REOPT* reopt, /**< reoptimization data structure */
6501  BMS_BLKMEM* blkmem, /**< block memory buffers */
6502  SCIP_SET* set, /**< global SCIP settings */
6503  SCIP_STAT* stat, /**< problem statistics */
6504  SCIP_PROB* transprob, /**< transformed problem after presolve */
6505  SCIP_PROB* origprob, /**< original problem */
6506  SCIP_LP* lp, /**< current LP data */
6507  SCIP_RELAXATION* relaxation, /**< global relaxation data */
6508  SCIP_PRIMAL* primal, /**< primal data structure */
6509  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6510  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6511  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
6512  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6513  int probingdepth /**< probing depth of the node in the probing path that should be reactivated,
6514  * -1 to even deactivate the probing root, thus exiting probing mode */
6515  )
6516 {
6517  int newpathlen;
6518  int i;
6519 
6520  assert(tree != NULL);
6521  assert(SCIPtreeProbing(tree));
6522  assert(tree->probingroot != NULL);
6523  assert(tree->focusnode != NULL);
6527  assert(tree->probingroot->parent == tree->focusnode);
6528  assert(SCIPnodeGetDepth(tree->probingroot) == SCIPnodeGetDepth(tree->focusnode)+1);
6529  assert(tree->pathlen >= 2);
6530  assert(SCIPnodeGetType(tree->path[tree->pathlen-1]) == SCIP_NODETYPE_PROBINGNODE);
6531  assert(-1 <= probingdepth && probingdepth <= SCIPtreeGetProbingDepth(tree));
6532 
6533  treeCheckPath(tree);
6534 
6535  newpathlen = SCIPnodeGetDepth(tree->probingroot) + probingdepth + 1;
6536  assert(newpathlen >= 1); /* at least root node of the tree remains active */
6537 
6538  /* check if we have to do any backtracking */
6539  if( newpathlen < tree->pathlen )
6540  {
6541  int ncols;
6542  int nrows;
6543 
6544  /* the correct LP size of the node to which we backtracked is stored as initial LP size for its child */
6545  assert(SCIPnodeGetType(tree->path[newpathlen]) == SCIP_NODETYPE_PROBINGNODE);
6546  ncols = tree->path[newpathlen]->data.probingnode->ninitialcols;
6547  nrows = tree->path[newpathlen]->data.probingnode->ninitialrows;
6548  assert(ncols >= tree->pathnlpcols[newpathlen-1] || !tree->focuslpconstructed);
6549  assert(nrows >= tree->pathnlprows[newpathlen-1] || !tree->focuslpconstructed);
6550 
6551  while( tree->pathlen > newpathlen )
6552  {
6553  SCIP_NODE* node;
6554 
6555  node = tree->path[tree->pathlen-1];
6556 
6557  assert(SCIPnodeGetType(node) == SCIP_NODETYPE_PROBINGNODE);
6558  assert(tree->pathlen-1 == SCIPnodeGetDepth(node));
6559  assert(tree->pathlen-1 >= SCIPnodeGetDepth(tree->probingroot));
6560 
6561  if( node->data.probingnode->nchgdobjs > 0 )
6562  {
6563  /* @todo only do this if we don't backtrack to the root node - in that case, we can just restore the unchanged
6564  * objective values
6565  */
6566  for( i = node->data.probingnode->nchgdobjs - 1; i >= 0; --i )
6567  {
6568  assert(tree->probingobjchanged);
6569 
6570  /* inform relaxation and update objective value of relaxation solution */
6571  SCIPrelaxationUpdateVarObj(relaxation, set, node->data.probingnode->origobjvars[i],
6573 
6574  SCIP_CALL( SCIPvarChgObj(node->data.probingnode->origobjvars[i], blkmem, set, transprob, primal, lp,
6575  eventqueue, node->data.probingnode->origobjvals[i]) );
6576  }
6577  tree->probingsumchgdobjs -= node->data.probingnode->nchgdobjs;
6578  assert(tree->probingsumchgdobjs >= 0);
6579 
6580  /* reset probingobjchanged flag and cutoff bound */
6581  if( tree->probingsumchgdobjs == 0 )
6582  {
6584  tree->probingobjchanged = FALSE;
6585 
6586  SCIP_CALL( SCIPlpSetCutoffbound(lp, set, transprob, primal->cutoffbound) );
6587  }
6588 
6589  /* recompute global and local pseudo objective values */
6590  SCIPlpRecomputeLocalAndGlobalPseudoObjval(lp, set, transprob);
6591  }
6592 
6593  /* undo bound changes by deactivating the probing node */
6594  SCIP_CALL( nodeDeactivate(node, blkmem, set, stat, tree, lp, branchcand, eventqueue) );
6595 
6596  /* free the probing node */
6597  SCIP_CALL( SCIPnodeFree(&tree->path[tree->pathlen-1], blkmem, set, stat, eventqueue, tree, lp) );
6598  tree->pathlen--;
6599  }
6600  assert(tree->pathlen == newpathlen);
6601 
6602  /* reset the path LP size to the initial size of the probing node */
6603  if( SCIPnodeGetType(tree->path[tree->pathlen-1]) == SCIP_NODETYPE_PROBINGNODE )
6604  {
6605  tree->pathnlpcols[tree->pathlen-1] = tree->path[tree->pathlen-1]->data.probingnode->ninitialcols;
6606  tree->pathnlprows[tree->pathlen-1] = tree->path[tree->pathlen-1]->data.probingnode->ninitialrows;
6607  }
6608  else
6609  assert(SCIPnodeGetType(tree->path[tree->pathlen-1]) == SCIP_NODETYPE_FOCUSNODE);
6610  treeCheckPath(tree);
6611 
6612  /* undo LP extensions */
6613  SCIP_CALL( SCIPlpShrinkCols(lp, set, ncols) );
6614  SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, nrows) );
6615  tree->probingloadlpistate = TRUE; /* LP state must be reloaded if the next LP is solved */
6616 
6617  /* reset the LP's marked size to the initial size of the LP at the node stored in the path */
6618  assert(lp->nrows >= tree->pathnlprows[tree->pathlen-1] || !tree->focuslpconstructed);
6619  assert(lp->ncols >= tree->pathnlpcols[tree->pathlen-1] || !tree->focuslpconstructed);
6620  SCIPlpSetSizeMark(lp, tree->pathnlprows[tree->pathlen-1], tree->pathnlpcols[tree->pathlen-1]);
6621 
6622  /* if the highest cutoff or repropagation depth is inside the deleted part of the probing path,
6623  * reset them to infinity
6624  */
6625  if( tree->cutoffdepth >= tree->pathlen )
6626  {
6627  /* apply the pending bound changes */
6628  SCIP_CALL( treeApplyPendingBdchgs(tree, reopt, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue, cliquetable) );
6629 
6630  tree->cutoffdepth = INT_MAX;
6631  }
6632  if( tree->repropdepth >= tree->pathlen )
6633  tree->repropdepth = INT_MAX;
6634  }
6635 
6636  SCIPsetDebugMsg(set, "probing backtracked to depth %d (%d cols, %d rows)\n", tree->pathlen-1, SCIPlpGetNCols(lp), SCIPlpGetNRows(lp));
6637 
6638  return SCIP_OKAY;
6639 }
6640 
6641 /** undoes all changes to the problem applied in probing up to the given probing depth;
6642  * the changes of the probing node of the given probing depth are the last ones that remain active;
6643  * changes that were applied before calling SCIPtreeCreateProbingNode() cannot be undone
6644  */
6646  SCIP_TREE* tree, /**< branch and bound tree */
6647  SCIP_REOPT* reopt, /**< reoptimization data structure */
6648  BMS_BLKMEM* blkmem, /**< block memory buffers */
6649  SCIP_SET* set, /**< global SCIP settings */
6650  SCIP_STAT* stat, /**< problem statistics */
6651  SCIP_PROB* transprob, /**< transformed problem */
6652  SCIP_PROB* origprob, /**< original problem */
6653  SCIP_LP* lp, /**< current LP data */
6654  SCIP_RELAXATION* relaxation, /**< global relaxation data */
6655  SCIP_PRIMAL* primal, /**< primal data structure */
6656  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6657  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6658  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
6659  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6660  int probingdepth /**< probing depth of the node in the probing path that should be reactivated */
6661  )
6662 {
6663  assert(tree != NULL);
6664  assert(SCIPtreeProbing(tree));
6665  assert(0 <= probingdepth && probingdepth <= SCIPtreeGetProbingDepth(tree));
6666 
6667  /* undo the domain and constraint set changes and free the temporary probing nodes below the given probing depth */
6668  SCIP_CALL( treeBacktrackProbing(tree, reopt, blkmem, set, stat, transprob, origprob, lp, relaxation, primal, branchcand,
6669  eventqueue, eventfilter, cliquetable, probingdepth) );
6670 
6671  assert(SCIPtreeProbing(tree));
6673 
6674  return SCIP_OKAY;
6675 }
6676 
6677 /** switches back from probing to normal operation mode, frees all nodes on the probing path, restores bounds of all
6678  * variables and restores active constraints arrays of focus node
6679  */
6681  SCIP_TREE* tree, /**< branch and bound tree */
6682  SCIP_REOPT* reopt, /**< reoptimization data structure */
6683  BMS_BLKMEM* blkmem, /**< block memory buffers */
6684  SCIP_SET* set, /**< global SCIP settings */
6685  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
6686  SCIP_STAT* stat, /**< problem statistics */
6687  SCIP_PROB* transprob, /**< transformed problem after presolve */
6688  SCIP_PROB* origprob, /**< original problem */
6689  SCIP_LP* lp, /**< current LP data */
6690  SCIP_RELAXATION* relaxation, /**< global relaxation data */
6691  SCIP_PRIMAL* primal, /**< Primal LP data */
6692  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6693  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6694  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
6695  SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
6696  )
6697 {
6698  assert(tree != NULL);
6699  assert(SCIPtreeProbing(tree));
6700  assert(tree->probingroot != NULL);
6701  assert(tree->focusnode != NULL);
6705  assert(tree->probingroot->parent == tree->focusnode);
6706  assert(SCIPnodeGetDepth(tree->probingroot) == SCIPnodeGetDepth(tree->focusnode)+1);
6707  assert(tree->pathlen >= 2);
6708  assert(SCIPnodeGetType(tree->path[tree->pathlen-1]) == SCIP_NODETYPE_PROBINGNODE);
6709  assert(set != NULL);
6710 
6711  /* undo the domain and constraint set changes of the temporary probing nodes and free the probing nodes */
6712  SCIP_CALL( treeBacktrackProbing(tree, reopt, blkmem, set, stat, transprob, origprob, lp, relaxation, primal, branchcand,
6713  eventqueue, eventfilter, cliquetable, -1) );
6714  assert(tree->probingsumchgdobjs == 0);
6715  assert(!tree->probingobjchanged);
6716  assert(!lp->divingobjchg);
6717  assert(lp->cutoffbound == primal->cutoffbound); /*lint !e777*/
6718  assert(SCIPtreeGetCurrentNode(tree) == tree->focusnode);
6719  assert(!SCIPtreeProbing(tree));
6720 
6721  /* if the LP was flushed before probing starts, flush it again */
6722  if( tree->probinglpwasflushed )
6723  {
6724  SCIP_CALL( SCIPlpFlush(lp, blkmem, set, eventqueue) );
6725 
6726  /* if the LP was solved before probing starts, solve it again to restore the LP solution */
6727  if( tree->probinglpwassolved )
6728  {
6729  SCIP_Bool lperror;
6730 
6731  /* reset the LP state before probing started */
6732  if( tree->probinglpistate == NULL )
6733  {
6734  assert(tree->probinglpinorms == NULL);
6736  lp->primalfeasible = (lp->nlpicols == 0 && lp->nlpirows == 0);
6737  lp->primalchecked = (lp->nlpicols == 0 && lp->nlpirows == 0);
6738  lp->dualfeasible = (lp->nlpicols == 0 && lp->nlpirows == 0);
6739  lp->dualchecked = (lp->nlpicols == 0 && lp->nlpirows == 0);
6740  lp->solisbasic = FALSE;
6741  }
6742  else
6743  {
6744  SCIP_CALL( SCIPlpSetState(lp, blkmem, set, eventqueue, tree->probinglpistate,
6746  tree->probinglpwasdualchecked) );
6747  SCIP_CALL( SCIPlpFreeState(lp, blkmem, &tree->probinglpistate) );
6748 
6749  if( tree->probinglpinorms != NULL )
6750  {
6751  SCIP_CALL( SCIPlpSetNorms(lp, blkmem, tree->probinglpinorms) );
6752  SCIP_CALL( SCIPlpFreeNorms(lp, blkmem, &tree->probinglpinorms) );
6753  tree->probinglpinorms = NULL;
6754  }
6755  }
6757 
6758  /* resolve LP to reset solution */
6759  SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, FALSE, &lperror) );
6760  if( lperror )
6761  {
6762  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
6763  "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles while resolving LP %" SCIP_LONGINT_FORMAT " after probing\n",
6764  stat->nnodes, stat->nlps);
6765  lp->resolvelperror = TRUE;
6766  tree->focusnodehaslp = FALSE;
6767  }
6768  else if( SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_OPTIMAL
6772  {
6773  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
6774  "LP was not resolved to a sufficient status after probing\n");
6775  lp->resolvelperror = TRUE;
6776  tree->focusnodehaslp = FALSE;
6777  }
6778  else if( tree->focuslpconstructed && SCIPlpIsRelax(lp) && SCIPprobAllColsInLP(transprob, set, lp))
6779  {
6780  SCIP_CALL( SCIPnodeUpdateLowerboundLP(tree->focusnode, set, stat, tree, transprob, origprob, lp) );
6781  }
6782  }
6783  }
6784  else
6785  lp->flushed = FALSE;
6786 
6787  assert(tree->probinglpistate == NULL);
6788 
6789  /* if no LP was solved during probing and the LP before probing was not solved, then it should not be solved now */
6790  assert(tree->probingsolvedlp || tree->probinglpwassolved || !lp->solved);
6791 
6792  /* if the LP was solved (and hence flushed) before probing, then lp->solved should be TRUE unless we occured an error
6793  * during resolving right above
6794  */
6795  assert(!tree->probinglpwassolved || lp->solved || lp->resolvelperror);
6796 
6797  /* if the LP was not solved before probing it should be marked unsolved now; this can occur if a probing LP was
6798  * solved in between
6799  */
6800  if( !tree->probinglpwassolved )
6801  {
6802  lp->solved = FALSE;
6804  }
6805 
6806  /* if the LP was solved during probing, but had been unsolved before probing started, we discard the LP state */
6807  if( set->lp_clearinitialprobinglp && tree->probingsolvedlp && !tree->probinglpwassolved )
6808  {
6809  SCIPsetDebugMsg(set, "clearing lp state at end of probing mode because LP was initially unsolved\n");
6811  }
6812 
6813  assert(tree->probingobjchanged == SCIPlpDivingObjChanged(lp));
6814 
6815  /* reset flags */
6816  tree->probinglpwasflushed = FALSE;
6817  tree->probinglpwassolved = FALSE;
6818  tree->probingloadlpistate = FALSE;
6819  tree->probinglpwasrelax = FALSE;
6820  tree->probingsolvedlp = FALSE;
6821  tree->sbprobing = FALSE;
6822 
6823  /* inform LP about end of probing mode */
6824  SCIP_CALL( SCIPlpEndProbing(lp) );
6825 
6826  /* reset all marked constraints for propagation */
6827  SCIP_CALL( SCIPconshdlrsResetPropagationStatus(set, blkmem, set->conshdlrs, set->nconshdlrs) );
6828 
6829  SCIPsetDebugMsg(set, "probing ended in depth %d (LP flushed: %u, solstat: %d)\n", tree->pathlen-1, lp->flushed, SCIPlpGetSolstat(lp));
6830 
6831  return SCIP_OKAY;
6832 }
6833 
6834 /** gets the best child of the focus node w.r.t. the node selection priority assigned by the branching rule */
6836  SCIP_TREE* tree /**< branch and bound tree */
6837  )
6838 {
6839  SCIP_NODE* bestnode;
6840  SCIP_Real bestprio;
6841  int i;
6842 
6843  assert(tree != NULL);
6844 
6845  bestnode = NULL;
6846  bestprio = SCIP_REAL_MIN;
6847  for( i = 0; i < tree->nchildren; ++i )
6848  {
6849  if( tree->childrenprio[i] > bestprio )
6850  {
6851  bestnode = tree->children[i];
6852  bestprio = tree->childrenprio[i];
6853  }
6854  }
6855  assert((tree->nchildren == 0) == (bestnode == NULL));
6856 
6857  return bestnode;
6858 }
6859 
6860 /** gets the best sibling of the focus node w.r.t. the node selection priority assigned by the branching rule */
6862  SCIP_TREE* tree /**< branch and bound tree */
6863  )
6864 {
6865  SCIP_NODE* bestnode;
6866  SCIP_Real bestprio;
6867  int i;
6868 
6869  assert(tree != NULL);
6870 
6871  bestnode = NULL;
6872  bestprio = SCIP_REAL_MIN;
6873  for( i = 0; i < tree->nsiblings; ++i )
6874  {
6875  if( tree->siblingsprio[i] > bestprio )
6876  {
6877  bestnode = tree->siblings[i];
6878  bestprio = tree->siblingsprio[i];
6879  }
6880  }
6881  assert((tree->nsiblings == 0) == (bestnode == NULL));
6882 
6883  return bestnode;
6884 }
6885 
6886 /** gets the best child of the focus node w.r.t. the node selection strategy */
6888  SCIP_TREE* tree, /**< branch and bound tree */
6889  SCIP_SET* set /**< global SCIP settings */
6890  )
6891 {
6892  SCIP_NODESEL* nodesel;
6893  SCIP_NODE* bestnode;
6894  int i;
6895 
6896  assert(tree != NULL);
6897 
6898  nodesel = SCIPnodepqGetNodesel(tree->leaves);
6899  assert(nodesel != NULL);
6900 
6901  bestnode = NULL;
6902  for( i = 0; i < tree->nchildren; ++i )
6903  {
6904  if( bestnode == NULL || SCIPnodeselCompare(nodesel, set, tree->children[i], bestnode) < 0 )
6905  {
6906  bestnode = tree->children[i];
6907  }
6908  }
6909 
6910  return bestnode;
6911 }
6912 
6913 /** gets the best sibling of the focus node w.r.t. the node selection strategy */
6915  SCIP_TREE* tree, /**< branch and bound tree */
6916  SCIP_SET* set /**< global SCIP settings */
6917  )
6918 {
6919  SCIP_NODESEL* nodesel;
6920  SCIP_NODE* bestnode;
6921  int i;
6922 
6923  assert(tree != NULL);
6924 
6925  nodesel = SCIPnodepqGetNodesel(tree->leaves);
6926  assert(nodesel != NULL);
6927 
6928  bestnode = NULL;
6929  for( i = 0; i < tree->nsiblings; ++i )
6930  {
6931  if( bestnode == NULL || SCIPnodeselCompare(nodesel, set, tree->siblings[i], bestnode) < 0 )
6932  {
6933  bestnode = tree->siblings[i];
6934  }
6935  }
6936 
6937  return bestnode;
6938 }
6939 
6940 /** gets the best leaf from the node queue w.r.t. the node selection strategy */
6942  SCIP_TREE* tree /**< branch and bound tree */
6943  )
6944 {
6945  assert(tree != NULL);
6946 
6947  return SCIPnodepqFirst(tree->leaves);
6948 }
6949 
6950 /** gets the best node from the tree (child, sibling, or leaf) w.r.t. the node selection strategy */
6952  SCIP_TREE* tree, /**< branch and bound tree */
6953  SCIP_SET* set /**< global SCIP settings */
6954  )
6955 {
6956  SCIP_NODESEL* nodesel;
6957  SCIP_NODE* bestchild;
6958  SCIP_NODE* bestsibling;
6959  SCIP_NODE* bestleaf;
6960  SCIP_NODE* bestnode;
6961 
6962  assert(tree != NULL);
6963 
6964  nodesel = SCIPnodepqGetNodesel(tree->leaves);
6965  assert(nodesel != NULL);
6966 
6967  /* get the best child, sibling, and leaf */
6968  bestchild = SCIPtreeGetBestChild(tree, set);
6969  bestsibling = SCIPtreeGetBestSibling(tree, set);
6970  bestleaf = SCIPtreeGetBestLeaf(tree);
6971 
6972  /* return the best of the three */
6973  bestnode = bestchild;
6974  if( bestsibling != NULL && (bestnode == NULL || SCIPnodeselCompare(nodesel, set, bestsibling, bestnode) < 0) )
6975  bestnode = bestsibling;
6976  if( bestleaf != NULL && (bestnode == NULL || SCIPnodeselCompare(nodesel, set, bestleaf, bestnode) < 0) )
6977  bestnode = bestleaf;
6978 
6979  assert(SCIPtreeGetNLeaves(tree) == 0 || bestnode != NULL);
6980 
6981  return bestnode;
6982 }
6983 
6984 /** gets the minimal lower bound of all nodes in the tree */
6986  SCIP_TREE* tree, /**< branch and bound tree */
6987  SCIP_SET* set /**< global SCIP settings */
6988  )
6989 {
6990  SCIP_Real lowerbound;
6991  int i;
6992 
6993  assert(tree != NULL);
6994  assert(set != NULL);
6995 
6996  /* get the lower bound from the queue */
6997  lowerbound = SCIPnodepqGetLowerbound(tree->leaves, set);
6998 
6999  /* compare lower bound with children */
7000  for( i = 0; i < tree->nchildren; ++i )
7001  {
7002  assert(tree->children[i] != NULL);
7003  lowerbound = MIN(lowerbound, tree->children[i]->lowerbound);
7004  }
7005 
7006  /* compare lower bound with siblings */
7007  for( i = 0; i < tree->nsiblings; ++i )
7008  {
7009  assert(tree->siblings[i] != NULL);
7010  lowerbound = MIN(lowerbound, tree->siblings[i]->lowerbound);
7011  }
7012 
7013  /* compare lower bound with focus node */
7014  if( tree->focusnode != NULL )
7015  {
7016  lowerbound = MIN(lowerbound, tree->focusnode->lowerbound);
7017  }
7018 
7019  return lowerbound;
7020 }
7021 
7022 /** gets the node with minimal lower bound of all nodes in the tree (child, sibling, or leaf) */
7024  SCIP_TREE* tree, /**< branch and bound tree */
7025  SCIP_SET* set /**< global SCIP settings */
7026  )
7027 {
7028  SCIP_NODE* lowerboundnode;
7029  SCIP_Real lowerbound;
7030  SCIP_Real bestprio;
7031  int i;
7032 
7033  assert(tree != NULL);
7034  assert(set != NULL);
7035 
7036  /* get the lower bound from the queue */
7037  lowerboundnode = SCIPnodepqGetLowerboundNode(tree->leaves, set);
7038  lowerbound = lowerboundnode != NULL ? lowerboundnode->lowerbound : SCIPsetInfinity(set);
7039  bestprio = -SCIPsetInfinity(set);
7040 
7041  /* compare lower bound with children */
7042  for( i = 0; i < tree->nchildren; ++i )
7043  {
7044  assert(tree->children[i] != NULL);
7045  if( SCIPsetIsLE(set, tree->children[i]->lowerbound, lowerbound) )
7046  {
7047  if( SCIPsetIsLT(set, tree->children[i]->lowerbound, lowerbound) || tree->childrenprio[i] > bestprio )
7048  {
7049  lowerboundnode = tree->children[i];
7050  lowerbound = lowerboundnode->lowerbound;
7051  bestprio = tree->childrenprio[i];
7052  }
7053  }
7054  }
7055 
7056  /* compare lower bound with siblings */
7057  for( i = 0; i < tree->nsiblings; ++i )
7058  {
7059  assert(tree->siblings[i] != NULL);
7060  if( SCIPsetIsLE(set, tree->siblings[i]->lowerbound, lowerbound) )
7061  {
7062  if( SCIPsetIsLT(set, tree->siblings[i]->lowerbound, lowerbound) || tree->siblingsprio[i] > bestprio )
7063  {
7064  lowerboundnode = tree->siblings[i];
7065  lowerbound = lowerboundnode->lowerbound;
7066  bestprio = tree->siblingsprio[i];
7067  }
7068  }
7069  }
7070 
7071  return lowerboundnode;
7072 }
7073 
7074 /** gets the average lower bound of all nodes in the tree */
7076  SCIP_TREE* tree, /**< branch and bound tree */
7077  SCIP_Real cutoffbound /**< global cutoff bound */
7078  )
7079 {
7080  SCIP_Real lowerboundsum;
7081  int nnodes;
7082  int i;
7083 
7084  assert(tree != NULL);
7085 
7086  /* get sum of lower bounds from nodes in the queue */
7087  lowerboundsum = SCIPnodepqGetLowerboundSum(tree->leaves);
7088  nnodes = SCIPtreeGetNLeaves(tree);
7089 
7090  /* add lower bound of focus node */
7091  if( tree->focusnode != NULL && tree->focusnode->lowerbound < cutoffbound )
7092  {
7093  lowerboundsum += tree->focusnode->lowerbound;
7094  nnodes++;
7095  }
7096 
7097  /* add lower bounds of siblings */
7098  for( i = 0; i < tree->nsiblings; ++i )
7099  {
7100  assert(tree->siblings[i] != NULL);
7101  lowerboundsum += tree->siblings[i]->lowerbound;
7102  }
7103  nnodes += tree->nsiblings;
7104 
7105  /* add lower bounds of children */
7106  for( i = 0; i < tree->nchildren; ++i )
7107  {
7108  assert(tree->children[i] != NULL);
7109  lowerboundsum += tree->children[i]->lowerbound;
7110  }
7111  nnodes += tree->nchildren;
7112 
7113  return nnodes == 0 ? 0.0 : lowerboundsum/nnodes;
7114 }
7115 
7116 
7117 
7118 
7119 /*
7120  * simple functions implemented as defines
7121  */
7122 
7123 /* In debug mode, the following methods are implemented as function calls to ensure
7124  * type validity.
7125  * In optimized mode, the methods are implemented as defines to improve performance.
7126  * However, we want to have them in the library anyways, so we have to undef the defines.
7127  */
7128 
7129 #undef SCIPnodeGetType
7130 #undef SCIPnodeGetNumber
7131 #undef SCIPnodeGetDepth
7132 #undef SCIPnodeGetLowerbound
7133 #undef SCIPnodeGetEstimate
7134 #undef SCIPnodeGetDomchg
7135 #undef SCIPnodeGetParent
7136 #undef SCIPnodeGetConssetchg
7137 #undef SCIPnodeIsActive
7138 #undef SCIPnodeIsPropagatedAgain
7139 #undef SCIPtreeGetNLeaves
7140 #undef SCIPtreeGetNChildren
7141 #undef SCIPtreeGetNSiblings
7142 #undef SCIPtreeGetNNodes
7143 #undef SCIPtreeIsPathComplete
7144 #undef SCIPtreeProbing
7145 #undef SCIPtreeGetProbingRoot
7146 #undef SCIPtreeGetProbingDepth
7147 #undef SCIPtreeGetFocusNode
7148 #undef SCIPtreeGetFocusDepth
7149 #undef SCIPtreeHasFocusNodeLP
7150 #undef SCIPtreeSetFocusNodeLP
7151 #undef SCIPtreeIsFocusNodeLPConstructed
7152 #undef SCIPtreeInRepropagation
7153 #undef SCIPtreeGetCurrentNode
7154 #undef SCIPtreeGetCurrentDepth
7155 #undef SCIPtreeHasCurrentNodeLP
7156 #undef SCIPtreeGetEffectiveRootDepth
7157 #undef SCIPtreeGetRootNode
7158 #undef SCIPtreeProbingObjChanged
7159 #undef SCIPtreeMarkProbingObjChanged
7160 
7161 /** gets the type of the node */
7163  SCIP_NODE* node /**< node */
7164  )
7165 {
7166  assert(node != NULL);
7167 
7168  return (SCIP_NODETYPE)(node->nodetype);
7169 }
7170 
7171 /** gets successively assigned number of the node */
7173  SCIP_NODE* node /**< node */
7174  )
7175 {
7176  assert(node != NULL);
7177 
7178  return node->number;
7179 }
7180 
7181 /** gets the depth of the node */
7183  SCIP_NODE* node /**< node */
7184  )
7185 {
7186  assert(node != NULL);
7187 
7188  return (int) node->depth;
7189 }
7190 
7191 /** gets the lower bound of the node */
7193  SCIP_NODE* node /**< node */
7194  )
7195 {
7196  assert(node != NULL);
7197 
7198  return node->lowerbound;
7199 }
7200 
7201 /** gets the estimated value of the best feasible solution in subtree of the node */
7203  SCIP_NODE* node /**< node */
7204  )
7205 {
7206  assert(node != NULL);
7207 
7208  return node->estimate;
7209 }
7210 
7211 /** gets the reoptimization type of this node */
7213  SCIP_NODE* node /**< node */
7214  )
7215 {
7216  assert(node != NULL);
7217 
7218  return (SCIP_REOPTTYPE)node->reopttype;
7219 }
7220 
7221 /** sets the reoptimization type of this node */
7223  SCIP_NODE* node, /**< node */
7224  SCIP_REOPTTYPE reopttype /**< reoptimization type */
7225  )
7226 {
7227  assert(node != NULL);
7228  assert(reopttype == SCIP_REOPTTYPE_NONE
7229  || reopttype == SCIP_REOPTTYPE_TRANSIT
7230  || reopttype == SCIP_REOPTTYPE_INFSUBTREE
7231  || reopttype == SCIP_REOPTTYPE_STRBRANCHED
7232  || reopttype == SCIP_REOPTTYPE_LOGICORNODE
7233  || reopttype == SCIP_REOPTTYPE_LEAF
7234  || reopttype == SCIP_REOPTTYPE_PRUNED
7235  || reopttype == SCIP_REOPTTYPE_FEASIBLE);
7236 
7237  node->reopttype = (unsigned int) reopttype;
7238 }
7239 
7240 /** gets the unique id to identify the node during reoptimization; the id is 0 if the node is the root or not part of
7241  * the reoptimization tree
7242  */
7243 unsigned int SCIPnodeGetReoptID(
7244  SCIP_NODE* node /**< node */
7245  )
7246 {
7247  assert(node != NULL);
7248 
7249  return node->reoptid; /*lint !e732*/
7250 }
7251 
7252 /** set a unique id to identify the node during reoptimization */
7254  SCIP_NODE* node, /**< node */
7255  unsigned int id /**< unique id */
7256  )
7257 {
7258  assert(node != NULL);
7259  assert(id <= 536870911); /* id has only 29 bits and needs to be smaller than 2^29 */
7260 
7261  node->reoptid = id;
7262 }
7263 
7264 /** gets the domain change information of the node, i.e., the information about the differences in the
7265  * variables domains to the parent node
7266  */
7268  SCIP_NODE* node /**< node */
7269  )
7270 {
7271  assert(node != NULL);
7272 
7273  return node->domchg;
7274 }
7275 
7276 /** counts the number of bound changes due to branching, constraint propagation, and propagation */
7278  SCIP_NODE* node, /**< node */
7279  int* nbranchings, /**< pointer to store number of branchings (or NULL if not needed) */
7280  int* nconsprop, /**< pointer to store number of constraint propagations (or NULL if not needed) */
7281  int* nprop /**< pointer to store number of propagations (or NULL if not needed) */
7282  )
7283 { /*lint --e{641}*/
7284  SCIP_Bool count_branchings;
7285  SCIP_Bool count_consprop;
7286  SCIP_Bool count_prop;
7287  int i;
7288 
7289  assert(node != NULL);
7290 
7291  count_branchings = (nbranchings != NULL);
7292  count_consprop = (nconsprop != NULL);
7293  count_prop = (nprop != NULL);
7294 
7295  /* set counter to zero */
7296  if( count_branchings )
7297  *nbranchings = 0;
7298  if( count_consprop )
7299  *nconsprop = 0;
7300  if( count_prop )
7301  *nprop = 0;
7302 
7303  if( node->domchg != NULL )
7304  {
7305  for( i = 0; i < (int) node->domchg->domchgbound.nboundchgs; i++ )
7306  {
7307  if( count_branchings && node->domchg->domchgbound.boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
7308  (*nbranchings)++;
7309  else if( count_consprop && node->domchg->domchgbound.boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER )
7310  (*nconsprop)++;
7311  else if( count_prop && node->domchg->domchgbound.boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER )
7312  (*nprop)++;
7313  }
7314  }
7315 }
7316 
7317 /* return the number of bound changes based on dual information.
7318  *
7319  * currently, this methods works only for bound changes made by strong branching on binary variables. we need this
7320  * method to ensure optimality within reoptimization.
7321  *
7322  * since the bound changes made by strong branching are stored as SCIP_BOUNDCHGTYPE_CONSINFER or SCIP_BOUNDCHGTYPE_PROPINFER
7323  * with no constraint or propagator, resp., we are are interested in bound changes with these attributes.
7324  *
7325  * all bound changes of type SCIP_BOUNDCHGTYPE_BRANCHING are stored in the beginning of the bound change array, afterwards,
7326  * we can find the other two types. thus, we start the search at the end of the list and stop when reaching the first
7327  * bound change of type SCIP_BOUNDCHGTYPE_BRANCHING.
7328  */
7330  SCIP_NODE* node /**< node */
7331  )
7332 { /*lint --e{641}*/
7333  SCIP_BOUNDCHG* boundchgs;
7334  int i;
7335  int nboundchgs;
7336  int npseudobranchvars;
7337 
7338  assert(node != NULL);
7339 
7340  if( node->domchg == NULL )
7341  return 0;
7342 
7343  nboundchgs = (int)node->domchg->domchgbound.nboundchgs;
7344  boundchgs = node->domchg->domchgbound.boundchgs;
7345 
7346  npseudobranchvars = 0;
7347 
7348  assert(boundchgs != NULL);
7349  assert(nboundchgs >= 0);
7350 
7351  /* count the number of pseudo-branching decisions; pseudo-branching decisions have to be in the ending of the bound change
7352  * array
7353  */
7354  for( i = nboundchgs-1; i >= 0; i--)
7355  {
7356  SCIP_Bool isint;
7357 
7358  isint = boundchgs[i].var->vartype == SCIP_VARTYPE_BINARY || boundchgs[i].var->vartype == SCIP_VARTYPE_INTEGER
7359  || boundchgs[i].var->vartype == SCIP_VARTYPE_IMPLINT;
7360 
7361  if( isint && ((boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER
7362  && boundchgs[i].data.inferencedata.reason.cons == NULL)
7363  || (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER
7364  && boundchgs[i].data.inferencedata.reason.prop == NULL)) )
7365  npseudobranchvars++;
7366  else if( boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
7367  break;
7368  }
7369 
7370  return npseudobranchvars;
7371 }
7372 
7373 /** returns the set of variable branchings that were performed in the parent node to create this node */
7375  SCIP_NODE* node, /**< node data */
7376  SCIP_VAR** vars, /**< array of variables on which the bound change is based on dual information */
7377  SCIP_Real* bounds, /**< array of bounds which are based on dual information */
7378  SCIP_BOUNDTYPE* boundtypes, /**< array of boundtypes which are based on dual information */
7379  int* nvars, /**< number of variables on which the bound change is based on dual information
7380  * if this is larger than the array size, arrays should be reallocated and method
7381  * should be called again */
7382  int varssize /**< available slots in arrays */
7383  )
7384 { /*lint --e{641}*/
7385  SCIP_BOUNDCHG* boundchgs;
7386  int nboundchgs;
7387  int i;
7388 
7389  assert(node != NULL);
7390  assert(vars != NULL);
7391  assert(bounds != NULL);
7392  assert(boundtypes != NULL);
7393  assert(nvars != NULL);
7394  assert(varssize >= 0);
7395 
7396  (*nvars) = 0;
7397 
7398  if( SCIPnodeGetDepth(node) == 0 || node->domchg == NULL )
7399  return;
7400 
7401  nboundchgs = (int)node->domchg->domchgbound.nboundchgs;
7402  boundchgs = node->domchg->domchgbound.boundchgs;
7403 
7404  assert(boundchgs != NULL);
7405  assert(nboundchgs >= 0);
7406 
7407  /* count the number of pseudo-branching decisions; pseudo-branching decisions have to be in the ending of the bound change
7408  * array
7409  */
7410  for( i = nboundchgs-1; i >= 0; i--)
7411  {
7412  if( boundchgs[i].var->vartype == SCIP_VARTYPE_BINARY || boundchgs[i].var->vartype == SCIP_VARTYPE_INTEGER
7413  || boundchgs[i].var->vartype == SCIP_VARTYPE_IMPLINT )
7414  {
7415  if( (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER
7416  && boundchgs[i].data.inferencedata.reason.cons == NULL)
7417  || (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER
7418  && boundchgs[i].data.inferencedata.reason.prop == NULL) )
7419  (*nvars)++;
7420  else if( boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
7421  break;
7422  }
7423  }
7424 
7425  /* if the arrays have enough space store the branching decisions */
7426  if( varssize >= *nvars )
7427  {
7428  int j;
7429  j = 0;
7430  for( i = i+1; i < nboundchgs; i++)
7431  {
7432  assert( boundchgs[i].boundchgtype != SCIP_BOUNDCHGTYPE_BRANCHING );
7433  if( boundchgs[i].var->vartype == SCIP_VARTYPE_BINARY || boundchgs[i].var->vartype == SCIP_VARTYPE_INTEGER
7434  || boundchgs[i].var->vartype == SCIP_VARTYPE_IMPLINT )
7435  {
7436  if( (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER
7437  && boundchgs[i].data.inferencedata.reason.cons == NULL)
7438  || (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER
7439  && boundchgs[i].data.inferencedata.reason.prop == NULL) )
7440  {
7441  vars[j] = boundchgs[i].var;
7442  bounds[j] = boundchgs[i].newbound;
7443  boundtypes[j] = (SCIP_BOUNDTYPE) boundchgs[i].boundtype;
7444  j++;
7445  }
7446  }
7447  }
7448  }
7449 }
7450 
7451 /** gets the parent node of a node in the branch-and-bound tree, if any */
7453  SCIP_NODE* node /**< node */
7454  )
7455 {
7456  assert(node != NULL);
7457 
7458  return node->parent;
7459 }
7460 
7461 /** returns the set of variable branchings that were performed in the parent node to create this node */
7463  SCIP_NODE* node, /**< node data */
7464  SCIP_VAR** branchvars, /**< array of variables on which the branching has been performed in the parent node */
7465  SCIP_Real* branchbounds, /**< array of bounds which the branching in the parent node set */
7466  SCIP_BOUNDTYPE* boundtypes, /**< array of boundtypes which the branching in the parent node set */
7467  int* nbranchvars, /**< number of variables on which branching has been performed in the parent node
7468  * if this is larger than the array size, arrays should be reallocated and method
7469  * should be called again */
7470  int branchvarssize /**< available slots in arrays */
7471  )
7472 {
7473  SCIP_BOUNDCHG* boundchgs;
7474  int nboundchgs;
7475  int i;
7476 
7477  assert(node != NULL);
7478  assert(branchvars != NULL);
7479  assert(branchbounds != NULL);
7480  assert(boundtypes != NULL);
7481  assert(nbranchvars != NULL);
7482  assert(branchvarssize >= 0);
7483 
7484  (*nbranchvars) = 0;
7485 
7486  if( SCIPnodeGetDepth(node) == 0 || node->domchg == NULL )
7487  return;
7488 
7489  nboundchgs = (int)node->domchg->domchgbound.nboundchgs;
7490  boundchgs = node->domchg->domchgbound.boundchgs;
7491 
7492  assert(boundchgs != NULL);
7493  assert(nboundchgs >= 0);
7494 
7495  /* count the number of branching decisions; branching decisions have to be in the beginning of the bound change
7496  * array
7497  */
7498  for( i = 0; i < nboundchgs; i++)
7499  {
7500  if( boundchgs[i].boundchgtype != SCIP_BOUNDCHGTYPE_BRANCHING ) /*lint !e641*/
7501  break;
7502 
7503  (*nbranchvars)++;
7504  }
7505 
7506 #ifndef NDEBUG
7507  /* check that the remaining bound change are no branching decisions */
7508  for( ; i < nboundchgs; i++)
7509  assert(boundchgs[i].boundchgtype != SCIP_BOUNDCHGTYPE_BRANCHING); /*lint !e641*/
7510 #endif
7511 
7512  /* if the arrays have enough space store the branching decisions */
7513  if( branchvarssize >= *nbranchvars )
7514  {
7515  for( i = 0; i < *nbranchvars; i++)
7516  {
7517  assert( boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ); /*lint !e641*/
7518  branchvars[i] = boundchgs[i].var;
7519  boundtypes[i] = (SCIP_BOUNDTYPE) boundchgs[i].boundtype;
7520  branchbounds[i] = boundchgs[i].newbound;
7521  }
7522  }
7523 }
7524 
7525 /** returns the set of variable branchings that were performed in all ancestor nodes (nodes on the path to the root) to create this node */
7527  SCIP_NODE* node, /**< node data */
7528  SCIP_VAR** branchvars, /**< array of variables on which the branchings has been performed in all ancestors */
7529  SCIP_Real* branchbounds, /**< array of bounds which the branchings in all ancestors set */
7530  SCIP_BOUNDTYPE* boundtypes, /**< array of boundtypes which the branchings in all ancestors set */
7531  int* nbranchvars, /**< number of variables on which branchings have been performed in all ancestors
7532  * if this is larger than the array size, arrays should be reallocated and method
7533  * should be called again */
7534  int branchvarssize /**< available slots in arrays */
7535  )
7536 {
7537  assert(node != NULL);
7538  assert(branchvars != NULL);
7539  assert(branchbounds != NULL);
7540  assert(boundtypes != NULL);
7541  assert(nbranchvars != NULL);
7542  assert(branchvarssize >= 0);
7543 
7544  (*nbranchvars) = 0;
7545 
7546  while( SCIPnodeGetDepth(node) != 0 )
7547  {
7548  int nodenbranchvars;
7549  int start;
7550  int size;
7551 
7552  start = *nbranchvars < branchvarssize - 1 ? *nbranchvars : branchvarssize - 1;
7553  size = *nbranchvars > branchvarssize ? 0 : branchvarssize-(*nbranchvars);
7554 
7555  SCIPnodeGetParentBranchings(node, &branchvars[start], &branchbounds[start], &boundtypes[start], &nodenbranchvars, size);
7556  *nbranchvars += nodenbranchvars;
7557 
7558  node = node->parent;
7559  }
7560 }
7561 
7562 /** returns the set of variable branchings that were performed between the given @p node and the given @p parent node. */
7564  SCIP_NODE* node, /**< node data */
7565  SCIP_NODE* parent, /**< node data of the last ancestor node */
7566  SCIP_VAR** branchvars, /**< array of variables on which the branchings has been performed in all ancestors */
7567  SCIP_Real* branchbounds, /**< array of bounds which the branchings in all ancestors set */
7568  SCIP_BOUNDTYPE* boundtypes, /**< array of boundtypes which the branchings in all ancestors set */
7569  int* nbranchvars, /**< number of variables on which branchings have been performed in all ancestors
7570  * if this is larger than the array size, arrays should be reallocated and method
7571  * should be called again */
7572  int branchvarssize /**< available slots in arrays */
7573  )
7574 {
7575  assert(node != NULL);
7576  assert(parent != NULL);
7577  assert(branchvars != NULL);
7578  assert(branchbounds != NULL);
7579  assert(boundtypes != NULL);
7580  assert(nbranchvars != NULL);
7581  assert(branchvarssize >= 0);
7582 
7583  (*nbranchvars) = 0;
7584 
7585  while( node != parent )
7586  {
7587  int nodenbranchvars;
7588  int start;
7589  int size;
7590 
7591  start = *nbranchvars < branchvarssize - 1 ? *nbranchvars : branchvarssize - 1;
7592  size = *nbranchvars > branchvarssize ? 0 : branchvarssize-(*nbranchvars);
7593 
7594  SCIPnodeGetParentBranchings(node, &branchvars[start], &branchbounds[start], &boundtypes[start], &nodenbranchvars, size);
7595  *nbranchvars += nodenbranchvars;
7596 
7597  node = node->parent;
7598  }
7599 }
7600 
7601 /** return all bound changes based on constraint propagation; stop saving the bound changes if we reach a branching
7602  * decision based on a dual information
7603  */
7605  SCIP_NODE* node, /**< node */
7606  SCIP_VAR** vars, /**< array of variables on which constraint propagation triggers a bound change */
7607  SCIP_Real* varbounds, /**< array of bounds set by constraint propagation */
7608  SCIP_BOUNDTYPE* varboundtypes, /**< array of boundtypes set by constraint propagation */
7609  int* nconspropvars, /**< number of variables on which constraint propagation triggers a bound change
7610  * if this is larger than the array size, arrays should be reallocated and method
7611  * should be called again */
7612  int conspropvarssize /**< available slots in arrays */
7613  )
7614 { /*lint --e{641}*/
7615  SCIP_BOUNDCHG* boundchgs;
7616  int nboundchgs;
7617  int first_dual;
7618  int nskip;
7619  int i;
7620 
7621  assert(node != NULL);
7622  assert(vars != NULL);
7623  assert(varbounds != NULL);
7624  assert(varboundtypes != NULL);
7625  assert(nconspropvars != NULL);
7626  assert(conspropvarssize >= 0);
7627 
7628  (*nconspropvars) = 0;
7629 
7630  if( SCIPnodeGetDepth(node) == 0 || node->domchg == NULL )
7631  return;
7632 
7633  nboundchgs = (int)node->domchg->domchgbound.nboundchgs;
7634  boundchgs = node->domchg->domchgbound.boundchgs;
7635 
7636  assert(boundchgs != NULL);
7637  assert(nboundchgs >= 0);
7638 
7639  SCIPnodeGetNDomchg(node, &nskip, NULL, NULL);
7640  i = nskip;
7641 
7642  while( i < nboundchgs
7643  && !(boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER && boundchgs[i].data.inferencedata.reason.cons == NULL)
7644  && !(boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER && boundchgs[i].data.inferencedata.reason.prop == NULL) )
7645  i++;
7646 
7647  first_dual = i;
7648 
7649  /* count the number of bound changes because of constraint propagation and propagation */
7650  for(i = nskip; i < first_dual; i++)
7651  {
7652  assert(boundchgs[i].boundchgtype != SCIP_BOUNDCHGTYPE_BRANCHING);
7653 
7654  if( (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER && boundchgs[i].data.inferencedata.reason.cons != NULL)
7655  || (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER && boundchgs[i].data.inferencedata.reason.prop != NULL) )
7656  {
7657  if( boundchgs[i].var->vartype != SCIP_VARTYPE_CONTINUOUS )
7658  (*nconspropvars)++;
7659  }
7660  else if( (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER && boundchgs[i].data.inferencedata.reason.cons == NULL)
7661  || (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER && boundchgs[i].data.inferencedata.reason.prop == NULL))
7662  break;
7663  }
7664 
7665  /* if the arrays have enough space store the branching decisions */
7666  if( conspropvarssize >= *nconspropvars )
7667  {
7668  int pos;
7669 
7670  for(i = nskip, pos = 0; i < first_dual; i++)
7671  {
7672  if( boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER && boundchgs[i].data.inferencedata.reason.cons != NULL )
7673  {
7674  if( boundchgs[i].var->vartype != SCIP_VARTYPE_CONTINUOUS )
7675  {
7676  vars[pos] = boundchgs[i].var;
7677  varboundtypes[pos] = (SCIP_BOUNDTYPE) boundchgs[i].boundtype;
7678  varbounds[pos] = boundchgs[i].newbound;
7679  pos++;
7680  }
7681  }
7682  }
7683  }
7684 
7685  return;
7686 }
7687 
7688 /** gets all bound changes applied after the first bound change based on dual information.
7689  *
7690  * @note: currently, we can only detect bound changes based in dual information if they arise from strong branching.
7691  */
7693  SCIP_NODE* node, /**< node */
7694  SCIP_VAR** vars, /**< array of variables on which the branching has been performed in the parent node */
7695  SCIP_Real* varbounds, /**< array of bounds which the branching in the parent node set */
7696  SCIP_BOUNDTYPE* varboundtypes, /**< array of boundtypes which the branching in the parent node set */
7697  int start, /**< first free slot in the arrays */
7698  int* nbranchvars, /**< number of variables on which branching has been performed in the parent node
7699  * if this is larger than the array size, arrays should be reallocated and method
7700  * should be called again */
7701  int branchvarssize /**< available slots in arrays */
7702  )
7703 { /*lint --e{641}*/
7704  SCIP_BOUNDCHG* boundchgs;
7705  int nboundchgs;
7706  int first_dual;
7707  int i;
7708 
7709  assert(node != NULL);
7710  assert(vars != NULL);
7711  assert(varbounds != NULL);
7712  assert(varboundtypes != NULL);
7713  assert(nbranchvars != NULL);
7714  assert(branchvarssize >= 0);
7715 
7716  (*nbranchvars) = 0;
7717 
7718  if( SCIPnodeGetDepth(node) == 0 || node->domchg == NULL )
7719  return;
7720 
7721  nboundchgs = (int)node->domchg->domchgbound.nboundchgs;
7722  boundchgs = node->domchg->domchgbound.boundchgs;
7723 
7724  assert(boundchgs != NULL);
7725  assert(nboundchgs >= 0);
7726 
7727  /* find the first based on dual information */
7728  i = 0;
7729  while( i < nboundchgs
7730  && !(boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER && boundchgs[i].data.inferencedata.reason.cons == NULL)
7731  && !(boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER && boundchgs[i].data.inferencedata.reason.prop == NULL) )
7732  i++;
7733 
7734  first_dual = i;
7735 
7736  /* count the number of branching decisions; branching decisions have to be in the beginning of the bound change array */
7737  for( ; i < nboundchgs; i++)
7738  {
7739  assert(boundchgs[i].boundchgtype != SCIP_BOUNDCHGTYPE_BRANCHING);
7740 
7741  if( (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER && boundchgs[i].data.inferencedata.reason.cons != NULL)
7742  || (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER && boundchgs[i].data.inferencedata.reason.prop != NULL) )
7743  {
7744  if( boundchgs[i].var->vartype != SCIP_VARTYPE_CONTINUOUS )
7745  (*nbranchvars)++;
7746  }
7747  }
7748 
7749  /* if the arrays have enough space store the branching decisions */
7750  if( branchvarssize >= *nbranchvars )
7751  {
7752  int p;
7753  for(i = first_dual, p = start; i < nboundchgs; i++)
7754  {
7755  if( (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER && boundchgs[i].data.inferencedata.reason.cons != NULL)
7756  || (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER && boundchgs[i].data.inferencedata.reason.prop != NULL) )
7757  {
7758  if( boundchgs[i].var->vartype != SCIP_VARTYPE_CONTINUOUS )
7759  {
7760  vars[p] = boundchgs[i].var;
7761  varboundtypes[p] = (SCIP_BOUNDTYPE) boundchgs[i].boundtype;
7762  varbounds[p] = boundchgs[i].newbound;
7763  p++;
7764  }
7765  }
7766  }
7767  }
7768 }
7769 
7770 /** outputs the path into given file stream in GML format */
7772  SCIP_NODE* node, /**< node data */
7773  FILE* file /**< file to output the path */
7774  )
7775 {
7776  int nbranchings;
7777 
7778  nbranchings = 0;
7779 
7780  /* print opening in GML format */
7781  SCIPgmlWriteOpening(file, TRUE);
7782 
7783  while( SCIPnodeGetDepth(node) != 0 )
7784  {
7785  SCIP_BOUNDCHG* boundchgs;
7786  char label[SCIP_MAXSTRLEN];
7787  int nboundchgs;
7788  int i;
7789 
7790  nboundchgs = (int)node->domchg->domchgbound.nboundchgs;
7791  boundchgs = node->domchg->domchgbound.boundchgs;
7792 
7793  for( i = 0; i < nboundchgs; i++)
7794  {
7795  if( boundchgs[i].boundchgtype != SCIP_BOUNDCHGTYPE_BRANCHING ) /*lint !e641*/
7796  break;
7797 
7798  (void) SCIPsnprintf(label, SCIP_MAXSTRLEN, "%s %s %g", SCIPvarGetName(boundchgs[i].var),
7799  (SCIP_BOUNDTYPE) boundchgs[i].boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", boundchgs[i].newbound);
7800 
7801  SCIPgmlWriteNode(file, (unsigned int)nbranchings, label, "circle", NULL, NULL);
7802 
7803  if( nbranchings > 0 )
7804  {
7805  SCIPgmlWriteArc(file, (unsigned int)nbranchings, (unsigned int)(nbranchings-1), NULL, NULL);
7806  }
7807 
7808  nbranchings++;
7809  }
7810 
7811  node = node->parent;
7812  }
7813 
7814  /* print closing in GML format */
7815  SCIPgmlWriteClosing(file);
7816 
7817  return SCIP_OKAY;
7818 }
7819 
7820 /** returns the set of variable branchings that were performed in all ancestor nodes (nodes on the path to the root) to create this node
7821  * sorted by the nodes, starting from the current node going up to the root
7822  */
7824  SCIP_NODE* node, /**< node data */
7825  SCIP_VAR** branchvars, /**< array of variables on which the branchings has been performed in all ancestors */
7826  SCIP_Real* branchbounds, /**< array of bounds which the branchings in all ancestors set */
7827  SCIP_BOUNDTYPE* boundtypes, /**< array of boundtypes which the branchings in all ancestors set */
7828  int* nbranchvars, /**< number of variables on which branchings have been performed in all ancestors
7829  * if this is larger than the array size, arrays should be reallocated and method
7830  * should be called again */
7831  int branchvarssize, /**< available slots in arrays */
7832  int* nodeswitches, /**< marks, where in the arrays the branching decisions of the next node on the path
7833  * start branchings performed at the parent of node always start at position 0.
7834  * For single variable branching, nodeswitches[i] = i holds */
7835  int* nnodes, /**< number of nodes in the nodeswitch array */
7836  int nodeswitchsize /**< available slots in node switch array */
7837  )
7838 {
7839  assert(node != NULL);
7840  assert(branchvars != NULL);
7841  assert(branchbounds != NULL);
7842  assert(boundtypes != NULL);
7843  assert(nbranchvars != NULL);
7844  assert(branchvarssize >= 0);
7845 
7846  (*nbranchvars) = 0;
7847  (*nnodes) = 0;
7848 
7849  /* go up to the root, in the root no domains were changed due to branching */
7850  while( SCIPnodeGetDepth(node) != 0 )
7851  {
7852  int nodenbranchvars;
7853  int start;
7854  int size;
7855 
7856  /* calculate the start position for the current node and the maximum remaining slots in the arrays */
7857  start = *nbranchvars < branchvarssize - 1 ? *nbranchvars : branchvarssize - 1;
7858  size = *nbranchvars > branchvarssize ? 0 : branchvarssize-(*nbranchvars);
7859  if( *nnodes < nodeswitchsize )
7860  nodeswitches[*nnodes] = start;
7861 
7862  /* get branchings for a single node */
7863  SCIPnodeGetParentBranchings(node, &branchvars[start], &branchbounds[start], &boundtypes[start], &nodenbranchvars, size);
7864  *nbranchvars += nodenbranchvars;
7865  (*nnodes)++;
7866 
7867  node = node->parent;
7868  }
7869 }
7870 
7871 /** checks for two nodes whether they share the same root path, i.e., whether one is an ancestor of the other */
7873  SCIP_NODE* node1, /**< node data */
7874  SCIP_NODE* node2 /**< node data */
7875  )
7876 {
7877  assert(node1 != NULL);
7878  assert(node2 != NULL);
7879  assert(SCIPnodeGetDepth(node1) >= 0);
7880  assert(SCIPnodeGetDepth(node2) >= 0);
7881 
7882  /* if node2 is deeper than node1, follow the path until the level of node2 */
7883  while( SCIPnodeGetDepth(node1) < SCIPnodeGetDepth(node2) )
7884  node2 = node2->parent;
7885 
7886  /* if node1 is deeper than node2, follow the path until the level of node1 */
7887  while( SCIPnodeGetDepth(node2) < SCIPnodeGetDepth(node1) )
7888  node1 = node1->parent;
7889 
7890  assert(SCIPnodeGetDepth(node2) == SCIPnodeGetDepth(node1));
7891 
7892  return (node1 == node2);
7893 }
7894 
7895 /** finds the common ancestor node of two given nodes */
7897  SCIP_NODE* node1, /**< node data */
7898  SCIP_NODE* node2 /**< node data */
7899  )
7900 {
7901  assert(node1 != NULL);
7902  assert(node2 != NULL);
7903  assert(SCIPnodeGetDepth(node1) >= 0);
7904  assert(SCIPnodeGetDepth(node2) >= 0);
7905 
7906  /* if node2 is deeper than node1, follow the path until the level of node2 */
7907  while( SCIPnodeGetDepth(node1) < SCIPnodeGetDepth(node2) )
7908  node2 = node2->parent;
7909 
7910  /* if node1 is deeper than node2, follow the path until the level of node1 */
7911  while( SCIPnodeGetDepth(node2) < SCIPnodeGetDepth(node1) )
7912  node1 = node1->parent;
7913 
7914  /* move up level by level until you found a common ancestor */
7915  while( node1 != node2 )
7916  {
7917  node1 = node1->parent;
7918  node2 = node2->parent;
7919  assert(SCIPnodeGetDepth(node1) == SCIPnodeGetDepth(node2));
7920  }
7921  assert(SCIPnodeGetDepth(node1) >= 0);
7922 
7923  return node1;
7924 }
7925 
7926 /** returns whether node is in the path to the current node */
7928  SCIP_NODE* node /**< node */
7929  )
7930 {
7931  assert(node != NULL);
7932 
7933  return node->active;
7934 }
7935 
7936 /** returns whether the node is marked to be propagated again */
7938  SCIP_NODE* node /**< node data */
7939  )
7940 {
7941  assert(node != NULL);
7942 
7943  return node->reprop;
7944 }
7945 
7946 /* returns the set of changed constraints for a particular node */
7948  SCIP_NODE* node /**< node data */
7949  )
7950 {
7951  assert(node != NULL);
7952 
7953  return node->conssetchg;
7954 }
7955 
7956 /** gets number of children of the focus node */
7958  SCIP_TREE* tree /**< branch and bound tree */
7959  )
7960 {
7961  assert(tree != NULL);
7962 
7963  return tree->nchildren;
7964 }
7965 
7966 /** gets number of siblings of the focus node */
7968  SCIP_TREE* tree /**< branch and bound tree */
7969  )
7970 {
7971  assert(tree != NULL);
7972 
7973  return tree->nsiblings;
7974 }
7975 
7976 /** gets number of leaves in the tree (excluding children and siblings of focus nodes) */
7978  SCIP_TREE* tree /**< branch and bound tree */
7979  )
7980 {
7981  assert(tree != NULL);
7982 
7983  return SCIPnodepqLen(tree->leaves);
7984 }
7985 
7986 /** gets number of open nodes in the tree (children + siblings + leaves) */
7988  SCIP_TREE* tree /**< branch and bound tree */
7989  )
7990 {
7991  assert(tree != NULL);
7992 
7993  return tree->nchildren + tree->nsiblings + SCIPtreeGetNLeaves(tree);
7994 }
7995 
7996 /** returns whether the active path goes completely down to the focus node */
7998  SCIP_TREE* tree /**< branch and bound tree */
7999  )
8000 {
8001  assert(tree != NULL);
8002  assert(tree->focusnode != NULL || !SCIPtreeProbing(tree));
8003  assert(tree->pathlen == 0 || tree->focusnode != NULL);
8004  assert(tree->pathlen >= 2 || !SCIPtreeProbing(tree));
8005  assert(tree->pathlen == 0 || tree->path[tree->pathlen-1] != NULL);
8006  assert(tree->pathlen == 0 || tree->path[tree->pathlen-1]->depth == tree->pathlen-1);
8007  assert(tree->focusnode == NULL || (int)tree->focusnode->depth >= tree->pathlen
8008  || tree->path[tree->focusnode->depth] == tree->focusnode);
8009 
8010  return (tree->focusnode == NULL || (int)tree->focusnode->depth < tree->pathlen);
8011 }
8012 
8013 /** returns whether the current node is a temporary probing node */
8015  SCIP_TREE* tree /**< branch and bound tree */
8016  )
8017 {
8018  assert(tree != NULL);
8020  assert(tree->probingroot == NULL || tree->pathlen > SCIPnodeGetDepth(tree->probingroot));
8021  assert(tree->probingroot == NULL || tree->path[SCIPnodeGetDepth(tree->probingroot)] == tree->probingroot);
8022 
8023  return (tree->probingroot != NULL);
8024 }
8025 
8026 /** returns the temporary probing root node, or NULL if the we are not in probing mode */
8028  SCIP_TREE* tree /**< branch and bound tree */
8029  )
8030 {
8031  assert(tree != NULL);
8033  assert(tree->probingroot == NULL || tree->pathlen > SCIPnodeGetDepth(tree->probingroot));
8034  assert(tree->probingroot == NULL || tree->path[SCIPnodeGetDepth(tree->probingroot)] == tree->probingroot);
8035 
8036  return tree->probingroot;
8037 }
8038 
8039 /** gets focus node of the tree */
8041  SCIP_TREE* tree /**< branch and bound tree */
8042  )
8043 {
8044  assert(tree != NULL);
8045  assert(tree->focusnode != NULL || !SCIPtreeProbing(tree));
8046  assert(tree->pathlen == 0 || tree->focusnode != NULL);
8047  assert(tree->pathlen >= 2 || !SCIPtreeProbing(tree));
8048  assert(tree->pathlen == 0 || tree->path[tree->pathlen-1] != NULL);
8049  assert(tree->pathlen == 0 || tree->path[tree->pathlen-1]->depth == tree->pathlen-1);
8050  assert(tree->focusnode == NULL || (int)tree->focusnode->depth >= tree->pathlen
8051  || tree->path[tree->focusnode->depth] == tree->focusnode);
8052 
8053  return tree->focusnode;
8054 }
8055 
8056 /** gets depth of focus node in the tree */
8058  SCIP_TREE* tree /**< branch and bound tree */
8059  )
8060 {
8061  assert(tree != NULL);
8062  assert(tree->focusnode != NULL || !SCIPtreeProbing(tree));
8063  assert(tree->pathlen == 0 || tree->focusnode != NULL);
8064  assert(tree->pathlen >= 2 || !SCIPtreeProbing(tree));
8065  assert(tree->pathlen == 0 || tree->path[tree->pathlen-1] != NULL);
8066  assert(tree->pathlen == 0 || tree->path[tree->pathlen-1]->depth == tree->pathlen-1);
8067  assert(tree->focusnode == NULL || (int)tree->focusnode->depth >= tree->pathlen
8068  || tree->path[tree->focusnode->depth] == tree->focusnode);
8069 
8070  return tree->focusnode != NULL ? (int)tree->focusnode->depth : -1;
8071 }
8072 
8073 /** returns, whether the LP was or is to be solved in the focus node */
8075  SCIP_TREE* tree /**< branch and bound tree */
8076  )
8077 {
8078  assert(tree != NULL);
8079 
8080  return tree->focusnodehaslp;
8081 }
8082 
8083 /** sets mark to solve or to ignore the LP while processing the focus node */
8085  SCIP_TREE* tree, /**< branch and bound tree */
8086  SCIP_Bool solvelp /**< should the LP be solved in focus node? */
8087  )
8088 {
8089  assert(tree != NULL);
8090 
8091  tree->focusnodehaslp = solvelp;
8092 }
8093 
8094 /** returns whether the LP of the focus node is already constructed */
8096  SCIP_TREE* tree /**< branch and bound tree */
8097  )
8098 {
8099  assert(tree != NULL);
8100 
8101  return tree->focuslpconstructed;
8102 }
8103 
8104 /** returns whether the focus node is already solved and only propagated again */
8106  SCIP_TREE* tree /**< branch and bound tree */
8107  )
8108 {
8109  assert(tree != NULL);
8110 
8111  return (tree->focusnode != NULL && SCIPnodeGetType(tree->focusnode) == SCIP_NODETYPE_REFOCUSNODE);
8112 }
8113 
8114 /** gets current node of the tree, i.e. the last node in the active path, or NULL if no current node exists */
8116  SCIP_TREE* tree /**< branch and bound tree */
8117  )
8118 {
8119  assert(tree != NULL);
8120  assert(tree->focusnode != NULL || !SCIPtreeProbing(tree));
8121  assert(tree->pathlen == 0 || tree->focusnode != NULL);
8122  assert(tree->pathlen >= 2 || !SCIPtreeProbing(tree));
8123  assert(tree->pathlen == 0 || tree->path[tree->pathlen-1] != NULL);
8124  assert(tree->pathlen == 0 || tree->path[tree->pathlen-1]->depth == tree->pathlen-1);
8125  assert(tree->focusnode == NULL || (int)tree->focusnode->depth >= tree->pathlen
8126  || tree->path[tree->focusnode->depth] == tree->focusnode);
8127 
8128  return (tree->pathlen > 0 ? tree->path[tree->pathlen-1] : NULL);
8129 }
8130 
8131 /** gets depth of current node in the tree, i.e. the length of the active path minus 1, or -1 if no current node exists */
8133  SCIP_TREE* tree /**< branch and bound tree */
8134  )
8135 {
8136  assert(tree != NULL);
8137  assert(tree->focusnode != NULL || !SCIPtreeProbing(tree));
8138  assert(tree->pathlen == 0 || tree->focusnode != NULL);
8139  assert(tree->pathlen >= 2 || !SCIPtreeProbing(tree));
8140  assert(tree->pathlen == 0 || tree->path[tree->pathlen-1] != NULL);
8141  assert(tree->pathlen == 0 || tree->path[tree->pathlen-1]->depth == tree->pathlen-1);
8142  assert(tree->focusnode == NULL || (int)tree->focusnode->depth >= tree->pathlen
8143  || tree->path[tree->focusnode->depth] == tree->focusnode);
8144 
8145  return tree->pathlen-1;
8146 }
8147 
8148 /** returns, whether the LP was or is to be solved in the current node */
8150  SCIP_TREE* tree /**< branch and bound tree */
8151  )
8152 {
8153  assert(tree != NULL);
8154  assert(SCIPtreeIsPathComplete(tree));
8155 
8156  return SCIPtreeProbing(tree) ? tree->probingnodehaslp : SCIPtreeHasFocusNodeLP(tree);
8157 }
8158 
8159 /** returns the current probing depth, i.e. the number of probing sub nodes existing in the probing path */
8161  SCIP_TREE* tree /**< branch and bound tree */
8162  )
8163 {
8164  assert(tree != NULL);
8165  assert(SCIPtreeProbing(tree));
8166 
8168 }
8169 
8170 /** returns the depth of the effective root node (i.e. the first depth level of a node with at least two children) */
8172  SCIP_TREE* tree /**< branch and bound tree */
8173  )
8174 {
8175  assert(tree != NULL);
8176  assert(tree->effectiverootdepth >= 0);
8177 
8178  return tree->effectiverootdepth;
8179 }
8180 
8181 /** gets the root node of the tree */
8183  SCIP_TREE* tree /**< branch and bound tree */
8184  )
8185 {
8186  assert(tree != NULL);
8187 
8188  return tree->root;
8189 }
8190 
8191 /** returns whether we are in probing and the objective value of at least one column was changed */
8192 
8194  SCIP_TREE* tree /**< branch and bound tree */
8195  )
8196 {
8197  assert(tree != NULL);
8198  assert(SCIPtreeProbing(tree) || !tree->probingobjchanged);
8199 
8200  return tree->probingobjchanged;
8201 }
8202 
8203 /** marks the current probing node to have a changed objective function */
8205  SCIP_TREE* tree /**< branch and bound tree */
8206  )
8207 {
8208  assert(tree != NULL);
8209  assert(SCIPtreeProbing(tree));
8210 
8211  tree->probingobjchanged = TRUE;
8212 }
SCIP_Real cutoffbound
Definition: struct_primal.h:46
SCIP_NODE * node
Definition: struct_tree.h:161
SCIP_RETCODE SCIPtreeClear(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: tree.c:4796
SCIP_Bool solisbasic
Definition: struct_lp.h:350
static SCIP_RETCODE forkAddLP(SCIP_NODE *fork, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp)
Definition: tree.c:3158
SCIP_DECL_SORTPTRCOMP(SCIPnodeCompLowerbound)
Definition: tree.c:142
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_RETCODE SCIPtreeAddDiveBoundChange(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Bool preferred)
Definition: tree.c:6162
int firstnewrow
Definition: struct_lp.h:315
SCIP_RETCODE SCIPlpGetProvedLowerbound(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *bound)
Definition: lp.c:15619
SCIP_RETCODE SCIPtreeCreatePresolvingRoot(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable)
Definition: tree.c:4901
void SCIPnodeGetParentBranchings(SCIP_NODE *node, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
Definition: tree.c:7462
void SCIPnodeGetDualBoundchgs(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *bounds, SCIP_BOUNDTYPE *boundtypes, int *nvars, int varssize)
Definition: tree.c:7374
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:17268
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5517
void SCIPrelaxationUpdateVarObj(SCIP_RELAXATION *relaxation, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: relax.c:748
SCIP_RETCODE SCIPtreeEndProbing(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_PRIMAL *primal, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable)
Definition: tree.c:6680
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:426
internal methods for managing events
SCIP_RETCODE SCIPlpFreeNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lp.c:9858
SCIP_RETCODE SCIPnodepqBound(SCIP_NODEPQ *nodepq, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_Real cutoffbound)
Definition: nodesel.c:618
SCIP_Bool lpwasdualchecked
Definition: struct_tree.h:57
SCIP_RETCODE SCIPnodeCreateChild(SCIP_NODE **node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_Real nodeselprio, SCIP_Real estimate)
Definition: tree.c:960
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition: implics.c:3304
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5575
SCIP_PSEUDOFORK * pseudofork
Definition: struct_tree.h:141
SCIP_RETCODE SCIPtreeBranchVar(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *var, SCIP_Real val, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
Definition: tree.c:5317
int SCIPlpGetNNewrows(SCIP_LP *lp)
Definition: lp.c:16717
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6025
void SCIPvisualRepropagatedNode(SCIP_VISUAL *visual, SCIP_STAT *stat, SCIP_NODE *node)
Definition: visual.c:638
static SCIP_RETCODE treeEnsurePendingbdchgsMem(SCIP_TREE *tree, SCIP_SET *set, int num)
Definition: tree.c:112
SCIP_NODE * focussubroot
Definition: struct_tree.h:185
unsigned int lpwasdualfeas
Definition: struct_tree.h:124
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:16799
SCIP_Bool SCIPtreeHasFocusNodeLP(SCIP_TREE *tree)
Definition: tree.c:8074
static SCIP_RETCODE junctionInit(SCIP_JUNCTION *junction, SCIP_TREE *tree)
Definition: tree.c:385
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:16899
SCIP_RETCODE SCIPconssetchgFree(SCIP_CONSSETCHG **conssetchg, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:5219
#define SCIPdebugRemoveNode(blkmem, set, node)
Definition: debug.h:257
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:107
SCIP_Real * origobjvals
Definition: struct_tree.h:52
SCIP_RETCODE SCIPlpShrinkRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int newnrows)
Definition: lp.c:9403
void SCIPlpSetIsRelax(SCIP_LP *lp, SCIP_Bool relax)
Definition: lp.c:16836
static SCIP_RETCODE probingnodeUpdate(SCIP_PROBINGNODE *probingnode, BMS_BLKMEM *blkmem, SCIP_TREE *tree, SCIP_LP *lp)
Definition: tree.c:314
internal methods for branch and bound tree
SCIP_Real SCIPtreeCalcChildEstimate(SCIP_TREE *tree, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_Real targetvalue)
Definition: tree.c:5258
int naddedcols
Definition: struct_tree.h:101
SCIP_RETCODE SCIPtreeBranchVarHole(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *var, SCIP_Real left, SCIP_Real right, SCIP_NODE **downchild, SCIP_NODE **upchild)
Definition: tree.c:5649
SCIP_Longint ndeactivatednodes
Definition: struct_stat.h:82
void SCIPtreeSetFocusNodeLP(SCIP_TREE *tree, SCIP_Bool solvelp)
Definition: tree.c:8084
SCIP_Bool primalfeasible
Definition: struct_lp.h:346
SCIP_NODE * SCIPnodesGetCommonAncestor(SCIP_NODE *node1, SCIP_NODE *node2)
Definition: tree.c:7896
SCIP_RETCODE SCIPeventqueueProcess(SCIP_EVENTQUEUE *eventqueue, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter)
Definition: event.c:2363
SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition: var.c:17351
union SCIP_BoundChg::@11 data
SCIP_CONS ** addedconss
Definition: struct_cons.h:108
SCIP_RETCODE SCIPlpFlush(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: lp.c:8416
SCIP_NODE * SCIPtreeGetLowerboundNode(SCIP_TREE *tree, SCIP_SET *set)
Definition: tree.c:7023
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5704
int nlpicols
Definition: struct_lp.h:297
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5915
SCIP_RETCODE SCIPlpRemoveAllObsoletes(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:14813
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:7192
SCIP_Longint nlps
Definition: struct_stat.h:171
methods for implications, variable bounds, and cliques
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17169
int SCIPnodepqCompare(SCIP_NODEPQ *nodepq, SCIP_SET *set, SCIP_NODE *node1, SCIP_NODE *node2)
Definition: nodesel.c:243
SCIP_Longint focuslpstateforklpcount
Definition: struct_tree.h:202
#define SCIP_MAXSTRLEN
Definition: def.h:225
static SCIP_RETCODE pseudoforkCreate(SCIP_PSEUDOFORK **pseudofork, BMS_BLKMEM *blkmem, SCIP_TREE *tree, SCIP_LP *lp)
Definition: tree.c:409
int * pathnlprows
Definition: struct_tree.h:196
SCIP_Real rootlowerbound
Definition: struct_stat.h:117
SCIP_RETCODE SCIPtreeSetNodesel(SCIP_TREE *tree, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_NODESEL *nodesel)
Definition: tree.c:4995
unsigned int active
Definition: struct_tree.h:150
void SCIPgmlWriteArc(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
Definition: misc.c:627
int validdepth
Definition: struct_cons.h:60
static SCIP_RETCODE treeEnsurePathMem(SCIP_TREE *tree, SCIP_SET *set, int num)
Definition: tree.c:86
internal methods for clocks and timing issues
SCIPInterval pow(const SCIPInterval &x, const SCIPInterval &y)
SCIP_BRANCHDIR * divebdchgdirs[2]
Definition: struct_tree.h:192
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:124
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5640
static long bound
int SCIPtreeGetProbingDepth(SCIP_TREE *tree)
Definition: tree.c:8160
SCIP_RETCODE SCIPnodeDelCons(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_CONS *cons)
Definition: tree.c:1588
SCIP_RETCODE SCIPnodeAddBoundinfer(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_Bool probingchange)
Definition: tree.c:1749
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17225
void SCIProwCapture(SCIP_ROW *row)
Definition: lp.c:5169
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17532
SCIP_PROBINGNODE * probingnode
Definition: struct_tree.h:136
SCIP_RETCODE SCIPtreeCreate(SCIP_TREE **tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_NODESEL *nodesel)
Definition: tree.c:4673
unsigned int repropsubtreemark
Definition: struct_tree.h:153
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7452
void SCIPgmlWriteNode(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
Definition: misc.c:485
void SCIPnodeGetAddedConss(SCIP_NODE *node, SCIP_CONS **addedconss, int *naddedconss, int addedconsssize)
Definition: tree.c:1618
void SCIPnodeSetReoptID(SCIP_NODE *node, unsigned int id)
Definition: tree.c:7253
SCIP_RETCODE SCIPvarAddHoleGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8403
interface methods for specific LP solvers
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16735
SCIP_NODE * SCIPtreeGetBestNode(SCIP_TREE *tree, SCIP_SET *set)
Definition: tree.c:6951
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:5379
SCIP_Longint nactiveconssadded
Definition: struct_stat.h:113
int naddedrows
Definition: struct_tree.h:102
SCIP_Bool probingchange
Definition: struct_tree.h:168
SCIP_NODE * SCIPtreeGetProbingRoot(SCIP_TREE *tree)
Definition: tree.c:8027
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:12561
SCIP_NODE * SCIPtreeGetBestChild(SCIP_TREE *tree, SCIP_SET *set)
Definition: tree.c:6887
SCIP_Real * divebdchgvals[2]
Definition: struct_tree.h:193
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:12654
int SCIPnodepqLen(const SCIP_NODEPQ *nodepq)
Definition: nodesel.c:550
SCIP_VAR * var
Definition: struct_tree.h:162
SCIP_RETCODE SCIPlpFreeState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lp.c:9797
void SCIPgmlWriteClosing(FILE *file)
Definition: misc.c:687
int nlpirows
Definition: struct_lp.h:300
SCIP_Real newbound
Definition: struct_tree.h:163
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16482
unsigned int nboundchgs
Definition: struct_var.h:122
unsigned int lpwasdualchecked
Definition: struct_tree.h:108
unsigned int cutoff
Definition: struct_tree.h:151
SCIP_Longint nholechgs
Definition: struct_stat.h:105
static SCIP_RETCODE subrootFree(SCIP_SUBROOT **subroot, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: tree.c:651
void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:350
static void forkCaptureLPIState(SCIP_FORK *fork, int nuses)
Definition: tree.c:157
unsigned int nodetype
Definition: struct_tree.h:149
#define FALSE
Definition: def.h:64
SCIP_LPINORMS * probinglpinorms
Definition: struct_tree.h:200
static SCIP_RETCODE focusnodeToLeaf(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_NODE *lpstatefork, SCIP_Real cutoffbound)
Definition: tree.c:3790
static void treeRemoveSibling(SCIP_TREE *tree, SCIP_NODE *sibling)
Definition: tree.c:684
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6058
SCIP_RETCODE SCIPdomchgUndo(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:1271
SCIP_Bool solved
Definition: struct_lp.h:345
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:9618
SCIP_Bool probinglpwasdualchecked
Definition: struct_tree.h:235
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:280
SCIP_Longint ncreatednodes
Definition: struct_stat.h:79
unsigned int reprop
Definition: struct_tree.h:152
SCIP_Bool dualchecked
Definition: struct_lp.h:349
SCIP_Bool sbprobing
Definition: struct_tree.h:231
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:9340
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5629
SCIP_RETCODE SCIPeventqueueDelay(SCIP_EVENTQUEUE *eventqueue)
Definition: event.c:2348
#define TRUE
Definition: def.h:63
SCIP_NODE * SCIPnodepqGetLowerboundNode(SCIP_NODEPQ *nodepq, SCIP_SET *set)
Definition: nodesel.c:584
static SCIP_RETCODE treeBacktrackProbing(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_PRIMAL *primal, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, int probingdepth)
Definition: tree.c:6498
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPtreeLoadLPState(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: tree.c:3449
unsigned int enabled
Definition: struct_cons.h:82
SCIP_RETCODE SCIPlpGetState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lp.c:9731
SCIP_Longint nbacktracks
Definition: struct_stat.h:85
int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
Definition: tree.c:8132
SCIP_Real SCIPnodepqGetLowerboundSum(SCIP_NODEPQ *nodepq)
Definition: nodesel.c:608
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16862
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5091
SCIP_Real estimate
Definition: struct_tree.h:133
SCIP_FORK * fork
Definition: struct_tree.h:142
SCIP_NODE * SCIPtreeGetFocusNode(SCIP_TREE *tree)
Definition: tree.c:8040
SCIP_Bool probinglpwasflushed
Definition: struct_tree.h:224
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15364
SCIP_RETCODE SCIPlpSolveAndEval(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_Longint itlim, SCIP_Bool limitresolveiters, SCIP_Bool aging, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:11960
SCIP_ROW ** SCIPlpGetRows(SCIP_LP *lp)
Definition: lp.c:16664
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_COL ** addedcols
Definition: struct_tree.h:97
int firstnewcol
Definition: struct_lp.h:311
SCIP_RETCODE SCIPlpCleanupAll(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_Bool root)
Definition: lp.c:15021
SCIP_Bool probingsolvedlp
Definition: struct_tree.h:228
SCIP_RETCODE SCIPlpSetNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS *lpinorms)
Definition: lp.c:9838
unsigned int domchgtype
Definition: struct_var.h:141
SCIP_NODE ** siblings
Definition: struct_tree.h:188
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7182
methods for creating output for visualization tools (VBC, BAK)
int divebdchgsize[2]
Definition: struct_tree.h:203
static SCIP_RETCODE treeAddChild(SCIP_TREE *tree, SCIP_SET *set, SCIP_NODE *child, SCIP_Real nodeselprio)
Definition: tree.c:710
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition: var.c:16832
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:16183
#define BMSfreeMemory(ptr)
Definition: memory.h:104
SCIP_RETCODE SCIPlpEndProbing(SCIP_LP *lp)
Definition: lp.c:15458
SCIP_NODESEL * SCIPnodepqGetNodesel(SCIP_NODEPQ *nodepq)
Definition: nodesel.c:193
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6052
SCIP_JUNCTION junction
Definition: struct_tree.h:140
static void treeChildrenToSiblings(SCIP_TREE *tree)
Definition: tree.c:4179
unsigned int lpwasdualfeas
Definition: struct_tree.h:107
SCIP_CONS ** disabledconss
Definition: struct_cons.h:109
int childrensize
Definition: struct_tree.h:207
static SCIP_RETCODE probingnodeFree(SCIP_PROBINGNODE **probingnode, BMS_BLKMEM *blkmem, SCIP_LP *lp)
Definition: tree.c:353
SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
Definition: lp.c:12527
SCIP_VISUAL * visual
Definition: struct_stat.h:163
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5715
unsigned int reoptid
Definition: struct_tree.h:154
int pathsize
Definition: struct_tree.h:212
static SCIP_RETCODE treeCreateProbingNode(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: tree.c:6232
#define SCIPstatIncrement(stat, set, field)
Definition: stat.h:251
int npendingbdchgs
Definition: struct_tree.h:206
internal methods for LP management
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:7942
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17521
SCIP_Bool SCIPtreeIsPathComplete(SCIP_TREE *tree)
Definition: tree.c:7997
SCIP_Longint number
Definition: struct_tree.h:131
SCIP_Bool SCIPtreeIsFocusNodeLPConstructed(SCIP_TREE *tree)
Definition: tree.c:8095
SCIP_Bool primalchecked
Definition: struct_lp.h:347
void SCIPnodeGetAncestorBranchings(SCIP_NODE *node, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
Definition: tree.c:7526
SCIP_ROW ** rows
Definition: struct_tree.h:115
internal methods for collecting primal CIP solutions and primal informations
SCIP_Bool SCIPconsIsGlobal(SCIP_CONS *cons)
Definition: cons.c:8110
int SCIPlpGetNCols(SCIP_LP *lp)
Definition: lp.c:16654
unsigned int lpwasprimchecked
Definition: struct_tree.h:106
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5611
int nlpistateref
Definition: struct_tree.h:103
internal methods for propagators
SCIP_Bool SCIPclockIsRunning(SCIP_CLOCK *clck)
Definition: clock.c:417
int pendingbdchgssize
Definition: struct_tree.h:205
SCIP_RETCODE SCIPnodepqInsert(SCIP_NODEPQ *nodepq, SCIP_SET *set, SCIP_NODE *node)
Definition: nodesel.c:259
int SCIPtreeGetFocusDepth(SCIP_TREE *tree)
Definition: tree.c:8057
SCIP_Real * siblingsprio
Definition: struct_tree.h:190
static SCIP_RETCODE pseudoforkAddLP(SCIP_NODE *pseudofork, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp)
Definition: tree.c:3203
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:39
SCIP_LPISTATE * lpistate
Definition: struct_tree.h:99
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7172
int SCIPtreeGetNChildren(SCIP_TREE *tree)
Definition: tree.c:7957
SCIP_NODE * SCIPtreeGetBestLeaf(SCIP_TREE *tree)
Definition: tree.c:6941
static SCIP_RETCODE nodeRepropagate(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
Definition: tree.c:1254
SCIP_RETCODE SCIPnodeCutoff(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_REOPT *reopt, SCIP_LP *lp, BMS_BLKMEM *blkmem)
Definition: tree.c:1126
unsigned int lpwasprimchecked
Definition: struct_tree.h:123
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17179
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5557
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11524
SCIP_Bool probinglpwassolved
Definition: struct_tree.h:225
SCIP_RETCODE SCIPlpCleanupNew(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_Bool root)
Definition: lp.c:14982
SCIP_Real SCIPtreeCalcNodeselPriority(SCIP_TREE *tree, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_BRANCHDIR branchdir, SCIP_Real targetvalue)
Definition: tree.c:5108
SCIP_REOPTTYPE SCIPnodeGetReopttype(SCIP_NODE *node)
Definition: tree.c:7212
SCIP_Bool probingloadlpistate
Definition: struct_tree.h:226
SCIP_DOMCHG * domchg
Definition: struct_tree.h:147
static SCIP_RETCODE subrootConstructLP(SCIP_NODE *subroot, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp)
Definition: tree.c:3113
SCIP_Bool SCIPtreeProbing(SCIP_TREE *tree)
Definition: tree.c:8014
SCIP_RETCODE SCIPprobPerformVarDeletions(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand)
Definition: prob.c:1054
SCIP_RETCODE SCIPlpSetState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LPISTATE *lpistate, SCIP_Bool wasprimfeas, SCIP_Bool wasprimchecked, SCIP_Bool wasdualfeas, SCIP_Bool wasdualchecked)
Definition: lp.c:9755
int nsiblings
Definition: struct_tree.h:210
SCIP_RETCODE SCIPvisualNewChild(SCIP_VISUAL *visual, SCIP_SET *set, SCIP_STAT *stat, SCIP_NODE *node)
Definition: visual.c:253
int cutoffdepth
Definition: struct_tree.h:216
SCIP_Real * childrenprio
Definition: struct_tree.h:189
void SCIPnodeUpdateLowerbound(SCIP_NODE *node, SCIP_STAT *stat, SCIP_SET *set, SCIP_TREE *tree, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_Real newbound)
Definition: tree.c:2279
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13780
int SCIPlpGetNNewcols(SCIP_LP *lp)
Definition: lp.c:16695
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:420
SCIP_SUBROOT * subroot
Definition: struct_tree.h:143
SCIP_RETCODE SCIPconssetchgApply(SCIP_CONSSETCHG *conssetchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, int depth, SCIP_Bool focusnode)
Definition: cons.c:5457
SCIP_Bool probingobjchanged
Definition: struct_tree.h:230
unsigned int reopttype
Definition: struct_tree.h:155
SCIP_RETCODE SCIPlpStartProbing(SCIP_LP *lp)
Definition: lp.c:15443
SCIP_RETCODE SCIPdomchgApplyGlobal(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
Definition: var.c:1306
SCIP_Bool SCIPnodesSharePath(SCIP_NODE *node1, SCIP_NODE *node2)
Definition: tree.c:7872
void SCIPnodeGetAncestorBranchingPath(SCIP_NODE *node, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize, int *nodeswitches, int *nnodes, int nodeswitchsize)
Definition: tree.c:7823
int repropsubtreecount
Definition: struct_tree.h:218
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:106
static SCIP_RETCODE forkReleaseLPIState(SCIP_FORK *fork, BMS_BLKMEM *blkmem, SCIP_LP *lp)
Definition: tree.c:172
static void treeFindSwitchForks(SCIP_TREE *tree, SCIP_NODE *node, SCIP_NODE **commonfork, SCIP_NODE **newlpfork, SCIP_NODE **newlpstatefork, SCIP_NODE **newsubroot, SCIP_Bool *cutoff)
Definition: tree.c:2678
internal methods for storing and manipulating the main problem
#define SCIPerrorMessage
Definition: pub_message.h:45
void SCIPmessagePrintVerbInfo(SCIP_MESSAGEHDLR *messagehdlr, SCIP_VERBLEVEL verblevel, SCIP_VERBLEVEL msgverblevel, const char *formatstr,...)
Definition: message.c:668
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16492
SCIP_RETCODE SCIPdomchgMakeStatic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:1084
static SCIP_RETCODE pseudoforkFree(SCIP_PSEUDOFORK **pseudofork, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: tree.c:464
SCIP_RETCODE SCIPdomchgFree(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:983
SCIP_Longint lpcount
Definition: struct_stat.h:169
SCIP_RETCODE SCIPvarChgObj(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newobj)
Definition: var.c:5801
void SCIPnodeGetNDomchg(SCIP_NODE *node, int *nbranchings, int *nconsprop, int *nprop)
Definition: tree.c:7277
static SCIP_RETCODE treeAddPendingBdchg(SCIP_TREE *tree, SCIP_SET *set, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_Bool probingchange)
Definition: tree.c:1662
SCIP_RETCODE SCIPlpAddCol(SCIP_LP *lp, SCIP_SET *set, SCIP_COL *col, int depth)
Definition: lp.c:9148
int siblingssize
Definition: struct_tree.h:209
SCIP_Bool SCIPtreeInRepropagation(SCIP_TREE *tree)
Definition: tree.c:8105
SCIP_RETCODE SCIPnodeFocus(SCIP_NODE **node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff, SCIP_Bool postponed, SCIP_Bool exitsolve)
Definition: tree.c:4216
#define SCIPdebugCheckInference(blkmem, set, node, var, newbound, boundtype)
Definition: debug.h:256
SCIP_Bool SCIPsetIsRelEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6402
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2765
SCIP_RETCODE SCIPlpShrinkCols(SCIP_LP *lp, SCIP_SET *set, int newncols)
Definition: lp.c:9331
SCIP_COL ** SCIPlpGetCols(SCIP_LP *lp)
Definition: lp.c:16644
SCIP_LPISTATE * probinglpistate
Definition: struct_tree.h:198
SCIP_RETCODE SCIPnodepqSetNodesel(SCIP_NODEPQ **nodepq, SCIP_SET *set, SCIP_NODESEL *nodesel)
Definition: nodesel.c:203
void SCIPnodeMarkPropagated(SCIP_NODE *node, SCIP_TREE *tree)
Definition: tree.c:1212
static SCIP_RETCODE focusnodeToPseudofork(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable)
Definition: tree.c:3856
SCIP_NODE ** path
Definition: struct_tree.h:176
int repropdepth
Definition: struct_tree.h:217
SCIP_NODE * focuslpstatefork
Definition: struct_tree.h:184
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7881
void SCIPlpMarkSize(SCIP_LP *lp)
Definition: lp.c:9488
SCIP_RETCODE SCIPnodePrintAncestorBranchings(SCIP_NODE *node, FILE *file)
Definition: tree.c:7771
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16555
SCIP_DOMCHGDYN domchgdyn
Definition: struct_var.h:154
SCIP_NODE * SCIPtreeGetBestSibling(SCIP_TREE *tree, SCIP_SET *set)
Definition: tree.c:6914
void SCIPnodeGetAncestorBranchingsPart(SCIP_NODE *node, SCIP_NODE *parent, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
Definition: tree.c:7563
SCIP_Bool SCIPnodeIsPropagatedAgain(SCIP_NODE *node)
Definition: tree.c:7937
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6093
static void treeCheckPath(SCIP_TREE *tree)
Definition: tree.c:3249
SCIP_DOMCHG * SCIPnodeGetDomchg(SCIP_NODE *node)
Definition: tree.c:7267
SCIP_Real cutoffbound
Definition: struct_lp.h:273
SCIP_RETCODE SCIPlpAddRow(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_ROW *row, int depth)
Definition: lp.c:9207
SCIP_RETCODE SCIPtreeLoadLP(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_Bool *initroot)
Definition: tree.c:3321
#define NULL
Definition: lpi_spx1.cpp:137
enum SCIP_ReoptType SCIP_REOPTTYPE
Definition: type_reopt.h:58
SCIP_Bool isrelax
Definition: struct_lp.h:352
int appliedeffectiverootdepth
Definition: struct_tree.h:214
static SCIP_RETCODE focusnodeToFork(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable)
Definition: tree.c:3907
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17543
SCIP_Bool SCIPsetIsRelGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6468
static void subrootCaptureLPIState(SCIP_SUBROOT *subroot, int nuses)
Definition: tree.c:196
internal methods for node selectors and node priority queues
static SCIP_RETCODE treeEnsureChildrenMem(SCIP_TREE *tree, SCIP_SET *set, int num)
Definition: tree.c:61
#define SCIP_PROPTIMING_ALWAYS
Definition: type_timing.h:64
int correctlpdepth
Definition: struct_tree.h:215
SCIP_SIBLING sibling
Definition: struct_tree.h:137
SCIP_NODEPQ * leaves
Definition: struct_tree.h:175
internal methods for global SCIP settings
internal methods for storing conflicts
SCIP * scip
Definition: struct_cons.h:40
#define SCIP_CALL(x)
Definition: def.h:316
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6003
int SCIPlpGetNRows(SCIP_LP *lp)
Definition: lp.c:16674
SCIP_CONSSETCHG * SCIPnodeGetConssetchg(SCIP_NODE *node)
Definition: tree.c:7947
int SCIPnodeselCompare(SCIP_NODESEL *nodesel, SCIP_SET *set, SCIP_NODE *node1, SCIP_NODE *node2)
Definition: nodesel.c:976
SCIP_RETCODE SCIPconsDisable(SCIP_CONS *cons, SCIP_SET *set, SCIP_STAT *stat)
Definition: cons.c:6748
SCIP_Bool resolvelperror
Definition: struct_lp.h:361
SCIP_Bool probinglpwasprimchecked
Definition: struct_tree.h:233
SCIP_COL ** cols
Definition: struct_tree.h:114
internal methods for relaxators
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5539
SCIP_CONS * infercons
Definition: struct_tree.h:165
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:254
unsigned int nboundchgs
Definition: struct_var.h:140
SCIP_Real SCIPlpGetObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:12543
SCIP_LPI * lpi
Definition: struct_lp.h:281
SCIP_Longint ncreatednodesrun
Definition: struct_stat.h:80
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5959
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition: debug.h:255
SCIP_BOUNDTYPE boundtype
Definition: struct_tree.h:164
SCIP_RETCODE SCIProwRelease(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:5182
SCIP_RETCODE SCIPnodepqFree(SCIP_NODEPQ **nodepq, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_TREE *tree, SCIP_LP *lp)
Definition: nodesel.c:130
SCIP_Real SCIPtreeGetAvgLowerbound(SCIP_TREE *tree, SCIP_Real cutoffbound)
Definition: tree.c:7075
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition: var.c:6086
void SCIPtreeClearDiveBoundChanges(SCIP_TREE *tree)
Definition: tree.c:6217
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:423
data structures and methods for collecting reoptimization information
internal methods for problem variables
void SCIPnodeSetEstimate(SCIP_NODE *node, SCIP_SET *set, SCIP_Real newestimate)
Definition: tree.c:2371
int SCIPnodeGetNDualBndchgs(SCIP_NODE *node)
Definition: tree.c:7329
static SCIP_RETCODE nodeReleaseParent(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_TREE *tree, SCIP_LP *lp)
Definition: tree.c:816
unsigned int vartype
Definition: struct_var.h:274
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17479
unsigned int boundchgtype
Definition: struct_var.h:90
void SCIPnodePropagateAgain(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree)
Definition: tree.c:1186
SCIP_VAR * var
Definition: struct_var.h:89
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:87
SCIP_RETCODE SCIPlpClear(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:9469
SCIP_Bool lpwasdualfeas
Definition: struct_tree.h:56
static SCIP_RETCODE treeUpdatePathLPSize(SCIP_TREE *tree, int startdepth)
Definition: tree.c:2570
int SCIPtreeGetEffectiveRootDepth(SCIP_TREE *tree)
Definition: tree.c:8171
#define SCIP_Bool
Definition: def.h:61
void SCIPlpRecomputeLocalAndGlobalPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:12626
static SCIP_RETCODE treeSwitchPath(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_NODE *fork, SCIP_NODE *focusnode, SCIP_Bool *cutoff)
Definition: tree.c:2978
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2753
SCIP_RETCODE SCIPreoptCheckCutoff(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, SCIP_EVENTTYPE eventtype, SCIP_LP *lp, SCIP_LPSOLSTAT lpsolstat, SCIP_Bool isrootnode, SCIP_Bool isfocusnode, SCIP_Real lowerbound, int effectiverootdepth)
Definition: reopt.c:5921
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:412
int arraypos
Definition: struct_tree.h:69
char * name
Definition: struct_cons.h:43
SCIP_Bool lpwasprimchecked
Definition: struct_tree.h:55
int SCIPsetCalcPathGrowSize(SCIP_SET *set, int num)
Definition: set.c:5109
SCIP_Bool focuslpconstructed
Definition: struct_tree.h:222
unsigned int depth
Definition: struct_tree.h:148
SCIP_NODE ** children
Definition: struct_tree.h:187
#define MAXREPROPMARK
Definition: tree.c:52
SCIP_VAR ** origobjvars
Definition: struct_tree.h:51
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:16894
SCIP_Longint nearlybacktracks
Definition: struct_stat.h:83
SCIP_RETCODE SCIPtreeCreateRoot(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: tree.c:4856
static SCIP_RETCODE nodeAssignParent(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_TREE *tree, SCIP_NODE *parent, SCIP_Real nodeselprio)
Definition: tree.c:761
SCIP_ROW ** SCIPlpGetNewrows(SCIP_LP *lp)
Definition: lp.c:16706
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:17341
SCIP_Real lastlowerbound
Definition: struct_stat.h:135
union SCIP_Node::@9 data
#define ARRAYGROWTH
Definition: tree.c:6161
SCIP_RETCODE SCIPnodepqRemove(SCIP_NODEPQ *nodepq, SCIP_SET *set, SCIP_NODE *node)
Definition: nodesel.c:503
SCIP_Bool divingobjchg
Definition: struct_lp.h:359
void SCIPtreeGetDiveBoundChangeData(SCIP_TREE *tree, SCIP_VAR ***variables, SCIP_BRANCHDIR **directions, SCIP_Real **values, int *ndivebdchgs, SCIP_Bool preferred)
Definition: tree.c:6194
unsigned int lpwasdualchecked
Definition: struct_tree.h:125
static SCIP_RETCODE focusnodeCleanupVars(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool inlp)
Definition: tree.c:3649
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17447
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:425
SCIP_Bool SCIPlpDivingObjChanged(SCIP_LP *lp)
Definition: lp.c:16909
SCIP_Longint nrepropcutoffs
Definition: struct_stat.h:89
int probingsumchgdobjs
Definition: struct_tree.h:219
#define MAX(x, y)
Definition: tclique_def.h:75
static SCIP_RETCODE probingnodeCreate(SCIP_PROBINGNODE **probingnode, BMS_BLKMEM *blkmem, SCIP_LP *lp)
Definition: tree.c:288
SCIP_RETCODE SCIPnodepqCreate(SCIP_NODEPQ **nodepq, SCIP_SET *set, SCIP_NODESEL *nodesel)
Definition: nodesel.c:95
static SCIP_RETCODE forkCreate(SCIP_FORK **fork, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_LP *lp)
Definition: tree.c:494
SCIP_RETCODE SCIPboundchgApply(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, int depth, int pos, SCIP_Bool *cutoff)
Definition: var.c:550
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16462
SCIP_Bool lpwasprimfeas
Definition: struct_tree.h:54
methods for debugging
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3316
SCIP_RETCODE SCIPnodeAddHolechg(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *var, SCIP_Real left, SCIP_Real right, SCIP_Bool probingchange, SCIP_Bool *added)
Definition: tree.c:2151
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:16510
SCIP_ROW ** addedrows
Definition: struct_tree.h:88
SCIP_RETCODE SCIPtreeStartProbing(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_Bool strongbranching)
Definition: tree.c:6316
#define SCIPsetDebugMsg
Definition: set.h:1870
#define SCIP_EVENTTYPE_NODEINFEASIBLE
Definition: type_event.h:79
SCIP_Bool SCIPsetIsRelLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6424
const char * SCIPnodeselGetName(SCIP_NODESEL *nodesel)
Definition: nodesel.c:993
SCIP_NODE * SCIPnodepqFirst(const SCIP_NODEPQ *nodepq)
Definition: nodesel.c:524
int * pathnlpcols
Definition: struct_tree.h:194
SCIP_Bool SCIPprobAllColsInLP(SCIP_PROB *prob, SCIP_SET *set, SCIP_LP *lp)
Definition: prob.c:2204
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17017
SCIP_RETCODE SCIPconshdlrsResetPropagationStatus(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_CONSHDLR **conshdlrs, int nconshdlrs)
Definition: cons.c:7770
SCIP_RETCODE SCIPpropagateDomains(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CONFLICT *conflict, SCIP_CLIQUETABLE *cliquetable, int depth, int maxproprounds, SCIP_PROPTIMING timingmask, SCIP_Bool *cutoff)
Definition: solve.c:610
SCIP_Bool probinglpwasrelax
Definition: struct_tree.h:227
SCIP_Bool SCIPtreeHasCurrentNodeLP(SCIP_TREE *tree)
Definition: tree.c:8149
SCIP_RETCODE SCIPvisualUpdateChild(SCIP_VISUAL *visual, SCIP_SET *set, SCIP_STAT *stat, SCIP_NODE *node)
Definition: visual.c:328
SCIP_RETCODE SCIPnodeCaptureLPIState(SCIP_NODE *node, int nuses)
Definition: tree.c:235
void SCIPlpSetSizeMark(SCIP_LP *lp, int nrows, int ncols)
Definition: lp.c:9500
static SCIP_RETCODE forkFree(SCIP_FORK **fork, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: tree.c:557
void SCIPnodeGetBdChgsAfterDual(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *varbounds, SCIP_BOUNDTYPE *varboundtypes, int start, int *nbranchvars, int branchvarssize)
Definition: tree.c:7692
SCIP_NODESEL * SCIPtreeGetNodesel(SCIP_TREE *tree)
Definition: tree.c:4985
SCIP_Bool cutoffdelayed
Definition: struct_tree.h:223
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17493
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5937
SCIP_RETCODE SCIPlpGetNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lp.c:9814
#define SCIP_MAXTREEDEPTH
Definition: def.h:252
SCIP_RETCODE SCIPnodeReleaseLPIState(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_LP *lp)
Definition: tree.c:263
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:887
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:11775
SCIP_CONSSETCHG * conssetchg
Definition: struct_tree.h:146
#define SCIP_REAL_MAX
Definition: def.h:146
int ndivebdchanges[2]
Definition: struct_tree.h:204
SCIP_NODE * probingroot
Definition: struct_tree.h:186
SCIP_RETCODE SCIPtreeFree(SCIP_TREE **tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: tree.c:4749
SCIP_Real SCIPnodeGetEstimate(SCIP_NODE *node)
Definition: tree.c:7202
SCIP_Real SCIPlpGetModifiedPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: lp.c:12750
enum SCIP_NodeType SCIP_NODETYPE
Definition: type_tree.h:44
SCIP_Real newbound
Definition: struct_var.h:83
#define SCIP_REAL_MIN
Definition: def.h:147
static SCIP_RETCODE nodeToLeaf(SCIP_NODE **node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_NODE *lpstatefork, SCIP_Real cutoffbound)
Definition: tree.c:3568
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17464
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6082
SCIP_DOMCHGBOUND domchgbound
Definition: struct_var.h:152
SCIP_RETCODE SCIPvarChgBdGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: var.c:7053
int SCIPtreeGetNSiblings(SCIP_TREE *tree)
Definition: tree.c:7967
int SCIPnodeGetNAddedConss(SCIP_NODE *node)
Definition: tree.c:1648
SCIP_Bool SCIPtreeProbingObjChanged(SCIP_TREE *tree)
Definition: tree.c:8193
SCIP_RETCODE SCIPtreeBranchVarNary(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *var, SCIP_Real val, int n, SCIP_Real minwidth, SCIP_Real widthfactor, int *nchildren)
Definition: tree.c:5791
static void treeNextRepropsubtreecount(SCIP_TREE *tree)
Definition: tree.c:1242
SCIP_NODE * parent
Definition: struct_tree.h:145
SCIP_Real SCIPnodepqGetLowerbound(SCIP_NODEPQ *nodepq, SCIP_SET *set)
Definition: nodesel.c:561
SCIP_LPISTATE * lpistate
Definition: struct_tree.h:46
SCIP_RETCODE SCIPlpSetCutoffbound(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_Real cutoffbound)
Definition: lp.c:9882
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8182
internal methods for main solving loop and node processing
SCIP_RETCODE SCIPconssetchgUndo(SCIP_CONSSETCHG *conssetchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: cons.c:5544
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:16502
unsigned int SCIPnodeGetReoptID(SCIP_NODE *node)
Definition: tree.c:7243
static SCIP_RETCODE nodeDeactivate(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue)
Definition: tree.c:1474
SCIP_RETCODE SCIPnodeAddBoundchg(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
Definition: tree.c:2001
SCIP_RETCODE SCIPnodeAddHoleinfer(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *var, SCIP_Real left, SCIP_Real right, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_Bool probingchange, SCIP_Bool *added)
Definition: tree.c:2030
SCIP_RETCODE SCIPconssetchgAddAddedCons(SCIP_CONSSETCHG **conssetchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_CONS *cons, int depth, SCIP_Bool focusnode, SCIP_Bool active)
Definition: cons.c:5293
SCIP_RETCODE SCIPtreeMarkProbingNodeHasLP(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_LP *lp)
Definition: tree.c:6470
SCIP_NODE * SCIPtreeGetCurrentNode(SCIP_TREE *tree)
Definition: tree.c:8115
SCIP_Bool flushed
Definition: struct_lp.h:344
SCIP_RETCODE SCIPtreeBacktrackProbing(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_PRIMAL *primal, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, int probingdepth)
Definition: tree.c:6645
unsigned int updatedisable
Definition: struct_cons.h:91
int nrows
Definition: struct_lp.h:313
SCIP_NODE * focuslpfork
Definition: struct_tree.h:183
public methods for message output
SCIP_Real lowerbound
Definition: struct_tree.h:132
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5593
SCIP_Longint nboundchgs
Definition: struct_stat.h:104
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16674
SCIP_LPISTATE * lpistate
Definition: struct_tree.h:116
SCIP_RETCODE SCIPnodepqClear(SCIP_NODEPQ *nodepq, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_TREE *tree, SCIP_LP *lp)
Definition: nodesel.c:153
static SCIP_RETCODE subrootReleaseLPIState(SCIP_SUBROOT *subroot, BMS_BLKMEM *blkmem, SCIP_LP *lp)
Definition: tree.c:212
SCIP_RETCODE SCIPtreeFreePresolvingRoot(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable)
Definition: tree.c:4942
SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
Definition: tree.c:7162
static SCIP_RETCODE nodeCreate(SCIP_NODE **node, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: tree.c:933
#define SCIP_Real
Definition: def.h:145
void SCIPvisualCutoffNode(SCIP_VISUAL *visual, SCIP_SET *set, SCIP_STAT *stat, SCIP_NODE *node, SCIP_Bool infeasible)
Definition: visual.c:520
internal methods for problem statistics
SCIP_VAR ** vars
Definition: struct_prob.h:55
void SCIPstatUpdatePrimalDualIntegral(SCIP_STAT *stat, SCIP_SET *set, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_Real upperbound, SCIP_Real lowerbound)
Definition: stat.c:394
SCIP_VAR ** divebdchgvars[2]
Definition: struct_tree.h:191
SCIP_RETCODE SCIPdomchgApply(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, int depth, SCIP_Bool *cutoff)
Definition: var.c:1222
#define MIN(x, y)
Definition: memory.c:75
SCIP_Real referencebound
Definition: struct_stat.h:138
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6036
SCIP_RETCODE SCIPtreeLoadProbingLPState(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: tree.c:6391
SCIP_Longint nrepropboundchgs
Definition: struct_stat.h:88
int effectiverootdepth
Definition: struct_tree.h:213
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition: var.c:11868
#define BMSallocMemory(ptr)
Definition: memory.h:78
#define SCIP_INVALID
Definition: def.h:165
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:86
internal methods for constraints and constraint handlers
SCIP_NODE * SCIPtreeGetPrioChild(SCIP_TREE *tree)
Definition: tree.c:6835
SCIP_Bool SCIPlpIsRelax(SCIP_LP *lp)
Definition: lp.c:16849
static SCIP_RETCODE treeApplyPendingBdchgs(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable)
Definition: tree.c:2184
SCIP_Bool SCIPnodeIsActive(SCIP_NODE *node)
Definition: tree.c:7927
SCIP_RETCODE SCIPnodeAddCons(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_CONS *cons)
Definition: tree.c:1545
#define SCIP_Longint
Definition: def.h:130
SCIP_Longint nactivatednodes
Definition: struct_stat.h:81
SCIP_Longint nreprops
Definition: struct_stat.h:87
SCIP_COL ** addedcols
Definition: struct_tree.h:87
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5981
SCIP_RETCODE SCIPnodeUpdateLowerboundLP(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp)
Definition: tree.c:2319
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16720
void SCIPnodeSetReopttype(SCIP_NODE *node, SCIP_REOPTTYPE reopttype)
Definition: tree.c:7222
static SCIP_RETCODE treeNodesToQueue(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_NODE **nodes, int *nnodes, SCIP_NODE *lpstatefork, SCIP_Real cutoffbound)
Definition: tree.c:4145
SCIP_RETCODE SCIPconssetchgMakeGlobal(SCIP_CONSSETCHG **conssetchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_REOPT *reopt)
Definition: cons.c:5630
SCIP_CLOCK * nodeactivationtime
Definition: struct_stat.h:155
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:5401
SCIP_Bool dualfeasible
Definition: struct_lp.h:348
SCIP_RETCODE SCIPconssetchgAddDisabledCons(SCIP_CONSSETCHG **conssetchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CONS *cons)
Definition: cons.c:5339
SCIP_Bool probinglpwasprimfeas
Definition: struct_tree.h:232
int nchildren
Definition: struct_tree.h:208
#define nnodes
Definition: gastrans.c:65
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17235
SCIP_Real SCIPtreeGetLowerbound(SCIP_TREE *tree, SCIP_SET *set)
Definition: tree.c:6985
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition: implics.c:3294
void SCIPgmlWriteOpening(FILE *file, SCIP_Bool directed)
Definition: misc.c:671
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6069
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:410
int plungedepth
Definition: struct_stat.h:215
SCIP_RETCODE SCIPtreeCutoff(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real cutoffbound)
Definition: tree.c:5023
SCIP_RETCODE SCIPlpiClearState(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:3315
SCIP_Bool inrestart
Definition: struct_stat.h:256
unsigned int lpwasprimfeas
Definition: struct_tree.h:122
SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
Definition: event.c:2435
SCIP_RETCODE SCIPprobDelVar(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *var, SCIP_Bool *deleted)
Definition: prob.c:993
common defines and data types used in all packages of SCIP
SCIP_Longint nnodes
Definition: struct_stat.h:71
SCIP_Real SCIPlpGetModifiedProvedPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: lp.c:12790
void SCIPvisualMarkedRepropagateNode(SCIP_VISUAL *visual, SCIP_STAT *stat, SCIP_NODE *node)
Definition: visual.c:617
SCIP_PENDINGBDCHG * pendingbdchgs
Definition: struct_tree.h:201
SCIP_Bool probingnodehaslp
Definition: struct_tree.h:221
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:396
int SCIPtreeGetNLeaves(SCIP_TREE *tree)
Definition: tree.c:7977
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:11953
static void treeRemoveChild(SCIP_TREE *tree, SCIP_NODE *child)
Definition: tree.c:733
SCIP_NODE * root
Definition: struct_tree.h:174
SCIP_RETCODE SCIPconshdlrsStorePropagationStatus(SCIP_SET *set, SCIP_CONSHDLR **conshdlrs, int nconshdlrs)
Definition: cons.c:7730
SCIP_COL ** SCIPlpGetNewcols(SCIP_LP *lp)
Definition: lp.c:16684
SCIP_RETCODE SCIPnodePropagateImplics(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
Definition: tree.c:2385
SCIP_CHILD child
Definition: struct_tree.h:138
unsigned int nchildren
Definition: struct_tree.h:121
static SCIP_RETCODE nodeActivate(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
Definition: tree.c:1405
#define SCIP_ALLOC(x)
Definition: def.h:327
int SCIPtreeGetNNodes(SCIP_TREE *tree)
Definition: tree.c:7987
#define SCIPABORT()
Definition: def.h:288
SCIP_Bool SCIPsetIsRelGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6490
static SCIP_RETCODE focusnodeToDeadend(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable)
Definition: tree.c:3750
SCIP_LPSOLSTAT lpsolstat
Definition: struct_lp.h:331
SCIP_Longint nprobholechgs
Definition: struct_stat.h:107
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16746
void SCIPchildChgNodeselPrio(SCIP_TREE *tree, SCIP_NODE *child, SCIP_Real priority)
Definition: tree.c:2353
SCIP_PROP * inferprop
Definition: struct_tree.h:166
SCIP_ROW ** addedrows
Definition: struct_tree.h:98
int ncols
Definition: struct_lp.h:307
unsigned int lpwasprimfeas
Definition: struct_tree.h:105
void SCIPnodeGetConsProps(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *varbounds, SCIP_BOUNDTYPE *varboundtypes, int *nconspropvars, int conspropvarssize)
Definition: tree.c:7604
SCIP_RETCODE SCIPnodeFree(SCIP_NODE **node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_TREE *tree, SCIP_LP *lp)
Definition: tree.c:1007
unsigned int nchildren
Definition: struct_tree.h:104
SCIP_RETCODE SCIPtreeCreateProbingNode(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: tree.c:6373
void SCIPlpUnmarkDivingObjChanged(SCIP_LP *lp)
Definition: lp.c:16930
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:416
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:142
SCIP_RETCODE SCIPdomchgAddBoundchg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_BOUNDCHGTYPE boundchgtype, SCIP_Real lpsolval, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype)
Definition: var.c:1345
static SCIP_RETCODE focusnodeToJunction(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_TREE *tree, SCIP_LP *lp)
Definition: tree.c:3819
void SCIPtreeMarkProbingObjChanged(SCIP_TREE *tree)
Definition: tree.c:8204
SCIP callable library.
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6047
SCIP_Bool probinglpwasdualfeas
Definition: struct_tree.h:234
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16842
SCIP_NODE * SCIPtreeGetPrioSibling(SCIP_TREE *tree)
Definition: tree.c:6861
SCIP_NODE * focusnode
Definition: struct_tree.h:179
SCIP_Bool focusnodehaslp
Definition: struct_tree.h:220