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