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