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