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