Scippy

SCIP

Solving Constraint Integer Programs

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