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