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