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