Scippy

SCIP

Solving Constraint Integer Programs

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