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-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file tree.c
    26 * @ingroup OTHER_CFILES
    27 * @brief methods for branch and bound tree
    28 * @author Tobias Achterberg
    29 * @author Timo Berthold
    30 * @author Gerald Gamrath
    31 */
    32
    33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    34#include <assert.h>
    35
    36#include "scip/def.h"
    37#include "scip/set.h"
    38#include "scip/stat.h"
    39#include "scip/clock.h"
    40#include "scip/certificate.h"
    41#include "scip/visual.h"
    42#include "scip/event.h"
    43#include "scip/lp.h"
    44#include "scip/lpexact.h"
    45#include "scip/relax.h"
    46#include "scip/var.h"
    47#include "scip/implics.h"
    48#include "scip/primal.h"
    49#include "scip/tree.h"
    50#include "scip/reopt.h"
    51#include "scip/conflictstore.h"
    52#include "scip/solve.h"
    53#include "scip/cons.h"
    54#include "scip/nodesel.h"
    55#include "scip/prop.h"
    56#include "scip/debug.h"
    57#include "scip/prob.h"
    58#include "scip/scip.h"
    59#include "scip/struct_scip.h"
    60#include "scip/struct_mem.h"
    61#include "scip/struct_event.h"
    62#include "scip/struct_lpexact.h"
    63#include "scip/pub_message.h"
    64#include "lpi/lpi.h"
    65
    66
    67#define MAXREPROPMARK 511 /**< maximal subtree repropagation marker; must correspond to node data structure */
    68
    69
    70/*
    71 * dynamic memory arrays
    72 */
    73
    74/** resizes children arrays to be able to store at least num nodes */
    75static
    77 SCIP_TREE* tree, /**< branch and bound tree */
    78 SCIP_SET* set, /**< global SCIP settings */
    79 int num /**< minimal number of node slots in array */
    80 )
    81{
    82 assert(tree != NULL);
    83 assert(set != NULL);
    84
    85 if( num > tree->childrensize )
    86 {
    87 int newsize;
    88
    89 newsize = SCIPsetCalcMemGrowSize(set, num);
    90 SCIP_ALLOC( BMSreallocMemoryArray(&tree->children, newsize) );
    92 tree->childrensize = newsize;
    93 }
    94 assert(num <= tree->childrensize);
    95
    96 return SCIP_OKAY;
    97}
    98
    99/** resizes path array to be able to store at least num nodes */
    100static
    102 SCIP_TREE* tree, /**< branch and bound tree */
    103 SCIP_SET* set, /**< global SCIP settings */
    104 int num /**< minimal number of node slots in path */
    105 )
    106{
    107 assert(tree != NULL);
    108 assert(set != NULL);
    109
    110 if( num > tree->pathsize )
    111 {
    112 int newsize;
    113
    114 newsize = SCIPsetCalcPathGrowSize(set, num);
    115 SCIP_ALLOC( BMSreallocMemoryArray(&tree->path, newsize) );
    116 SCIP_ALLOC( BMSreallocMemoryArray(&tree->pathnlpcols, newsize) );
    117 SCIP_ALLOC( BMSreallocMemoryArray(&tree->pathnlprows, newsize) );
    118 tree->pathsize = newsize;
    119 }
    120 assert(num <= tree->pathsize);
    121
    122 return SCIP_OKAY;
    123}
    124
    125/** resizes pendingbdchgs array to be able to store at least num nodes */
    126static
    128 SCIP_TREE* tree, /**< branch and bound tree */
    129 SCIP_SET* set, /**< global SCIP settings */
    130 int num /**< minimal number of node slots in path */
    131 )
    132{
    133 assert(tree != NULL);
    134 assert(set != NULL);
    135
    136 if( num > tree->pendingbdchgssize )
    137 {
    138 int newsize;
    139
    140 newsize = SCIPsetCalcMemGrowSize(set, num);
    142 tree->pendingbdchgssize = newsize;
    143 }
    144 assert(num <= tree->pendingbdchgssize);
    145
    146 return SCIP_OKAY;
    147}
    148
    149
    150
    151
    152/*
    153 * Node methods
    154 */
    155
    156/** node comparator for best lower bound */
    157SCIP_DECL_SORTPTRCOMP(SCIPnodeCompLowerbound)
    158{ /*lint --e{715}*/
    159 assert(elem1 != NULL);
    160 assert(elem2 != NULL);
    161
    162 if( ((SCIP_NODE*)elem1)->lowerbound < ((SCIP_NODE*)elem2)->lowerbound )
    163 return -1;
    164 else if( ((SCIP_NODE*)elem1)->lowerbound > ((SCIP_NODE*)elem2)->lowerbound )
    165 return +1;
    166 else
    167 return 0;
    168}
    169
    170/** increases the reference counter of the LP state in the fork */
    171static
    173 SCIP_FORK* fork, /**< fork data */
    174 int nuses /**< number to add to the usage counter */
    175 )
    176{
    177 assert(fork != NULL);
    178 assert(fork->nlpistateref >= 0);
    179 assert(nuses > 0);
    180
    181 fork->nlpistateref += nuses;
    182 SCIPdebugMessage("captured LPI state of fork %p %d times -> new nlpistateref=%d\n", (void*)fork, nuses, fork->nlpistateref);
    183}
    184
    185/** decreases the reference counter of the LP state in the fork */
    186static
    188 SCIP_FORK* fork, /**< fork data */
    189 BMS_BLKMEM* blkmem, /**< block memory buffers */
    190 SCIP_LP* lp /**< current LP data */
    191 )
    192{
    193 assert(fork != NULL);
    194 assert(fork->nlpistateref > 0);
    195 assert(blkmem != NULL);
    196 assert(lp != NULL);
    197
    198 fork->nlpistateref--;
    199 if( fork->nlpistateref == 0 )
    200 {
    201 SCIP_CALL( SCIPlpFreeState(lp, blkmem, &(fork->lpistate)) );
    202 }
    203
    204 SCIPdebugMessage("released LPI state of fork %p -> new nlpistateref=%d\n", (void*)fork, fork->nlpistateref);
    205
    206 return SCIP_OKAY;
    207}
    208
    209/** increases the reference counter of the LP state in the subroot */
    210static
    212 SCIP_SUBROOT* subroot, /**< subroot data */
    213 int nuses /**< number to add to the usage counter */
    214 )
    215{
    216 assert(subroot != NULL);
    217 assert(subroot->nlpistateref >= 0);
    218 assert(nuses > 0);
    219
    220 subroot->nlpistateref += nuses;
    221 SCIPdebugMessage("captured LPI state of subroot %p %d times -> new nlpistateref=%d\n",
    222 (void*)subroot, nuses, subroot->nlpistateref);
    223}
    224
    225/** decreases the reference counter of the LP state in the subroot */
    226static
    228 SCIP_SUBROOT* subroot, /**< subroot data */
    229 BMS_BLKMEM* blkmem, /**< block memory buffers */
    230 SCIP_LP* lp /**< current LP data */
    231 )
    232{
    233 assert(subroot != NULL);
    234 assert(subroot->nlpistateref > 0);
    235 assert(blkmem != NULL);
    236 assert(lp != NULL);
    237
    238 subroot->nlpistateref--;
    239 if( subroot->nlpistateref == 0 )
    240 {
    241 SCIP_CALL( SCIPlpFreeState(lp, blkmem, &(subroot->lpistate)) );
    242 }
    243
    244 SCIPdebugMessage("released LPI state of subroot %p -> new nlpistateref=%d\n", (void*)subroot, subroot->nlpistateref);
    245
    246 return SCIP_OKAY;
    247}
    248
    249/** increases the reference counter of the LP state in the fork or subroot node */
    251 SCIP_NODE* node, /**< fork/subroot node */
    252 int nuses /**< number to add to the usage counter */
    253 )
    254{
    255 assert(node != NULL);
    256
    257 SCIPdebugMessage("capture %d times LPI state of node #%" SCIP_LONGINT_FORMAT " at depth %d (current: %d)\n",
    258 nuses, SCIPnodeGetNumber(node), SCIPnodeGetDepth(node),
    260
    261 switch( SCIPnodeGetType(node) )
    262 {
    264 forkCaptureLPIState(node->data.fork, nuses);
    265 break;
    267 subrootCaptureLPIState(node->data.subroot, nuses);
    268 break;
    269 default:
    270 SCIPerrorMessage("node for capturing the LPI state is neither fork nor subroot\n");
    271 SCIPABORT();
    272 return SCIP_INVALIDDATA; /*lint !e527*/
    273 } /*lint !e788*/
    274 return SCIP_OKAY;
    275}
    276
    277/** decreases the reference counter of the LP state in the fork or subroot node */
    279 SCIP_NODE* node, /**< fork/subroot node */
    280 BMS_BLKMEM* blkmem, /**< block memory buffers */
    281 SCIP_LP* lp /**< current LP data */
    282 )
    283{
    284 assert(node != NULL);
    285
    286 SCIPdebugMessage("release LPI state of node #%" SCIP_LONGINT_FORMAT " at depth %d (current: %d)\n",
    289 switch( SCIPnodeGetType(node) )
    290 {
    292 return forkReleaseLPIState(node->data.fork, blkmem, lp);
    294 return subrootReleaseLPIState(node->data.subroot, blkmem, lp);
    295 default:
    296 SCIPerrorMessage("node for releasing the LPI state is neither fork nor subroot\n");
    297 return SCIP_INVALIDDATA;
    298 } /*lint !e788*/
    299}
    300
    301/** creates probingnode data without LP information */
    302static
    304 SCIP_PROBINGNODE** probingnode, /**< pointer to probingnode data */
    305 BMS_BLKMEM* blkmem, /**< block memory */
    306 SCIP_LP* lp /**< current LP data */
    307 )
    308{
    309 assert(probingnode != NULL);
    310
    311 SCIP_ALLOC( BMSallocBlockMemory(blkmem, probingnode) );
    312
    313 (*probingnode)->lpistate = NULL;
    314 (*probingnode)->lpinorms = NULL;
    315 (*probingnode)->ninitialcols = SCIPlpGetNCols(lp);
    316 (*probingnode)->ninitialrows = SCIPlpGetNRows(lp);
    317 (*probingnode)->ncols = (*probingnode)->ninitialcols;
    318 (*probingnode)->nrows = (*probingnode)->ninitialrows;
    319 (*probingnode)->origobjvars = NULL;
    320 (*probingnode)->origobjvals = NULL;
    321 (*probingnode)->nchgdobjs = 0;
    322
    323 SCIPdebugMessage("created probingnode information (%d cols, %d rows)\n", (*probingnode)->ncols, (*probingnode)->nrows);
    324
    325 return SCIP_OKAY;
    326}
    327
    328/** updates LP information in probingnode data */
    329static
    331 SCIP_PROBINGNODE* probingnode, /**< probingnode data */
    332 BMS_BLKMEM* blkmem, /**< block memory */
    333 SCIP_TREE* tree, /**< branch and bound tree */
    334 SCIP_LP* lp /**< current LP data */
    335 )
    336{
    337 SCIP_Bool storenorms = FALSE;
    338
    339 assert(probingnode != NULL);
    340 assert(SCIPtreeIsPathComplete(tree));
    341 assert(lp != NULL);
    342
    343 /* free old LP state */
    344 if( probingnode->lpistate != NULL )
    345 {
    346 SCIP_CALL( SCIPlpFreeState(lp, blkmem, &probingnode->lpistate) );
    347 }
    348
    349 /* free old LP norms */
    350 if( probingnode->lpinorms != NULL )
    351 {
    352 SCIP_CALL( SCIPlpFreeNorms(lp, blkmem, &probingnode->lpinorms) );
    353 probingnode->lpinorms = NULL;
    354 storenorms = TRUE;
    355 }
    356
    357 /* get current LP state */
    358 if( lp->flushed && lp->solved )
    359 {
    360 SCIP_CALL( SCIPlpGetState(lp, blkmem, &probingnode->lpistate) );
    361
    362 /* if LP norms were stored at this node before, store the new ones */
    363 if( storenorms )
    364 {
    365 SCIP_CALL( SCIPlpGetNorms(lp, blkmem, &probingnode->lpinorms) );
    366 }
    367 probingnode->lpwasprimfeas = lp->primalfeasible;
    368 probingnode->lpwasprimchecked = lp->primalchecked;
    369 probingnode->lpwasdualfeas = lp->dualfeasible;
    370 probingnode->lpwasdualchecked = lp->dualchecked;
    371 }
    372 else
    373 probingnode->lpistate = NULL;
    374
    375 probingnode->ncols = SCIPlpGetNCols(lp);
    376 probingnode->nrows = SCIPlpGetNRows(lp);
    377
    378 SCIPdebugMessage("updated probingnode information (%d cols, %d rows)\n", probingnode->ncols, probingnode->nrows);
    379
    380 return SCIP_OKAY;
    381}
    382
    383/** frees probingnode data */
    384static
    386 SCIP_PROBINGNODE** probingnode, /**< probingnode data */
    387 BMS_BLKMEM* blkmem, /**< block memory */
    388 SCIP_LP* lp /**< current LP data */
    389 )
    390{
    391 assert(probingnode != NULL);
    392 assert(*probingnode != NULL);
    393
    394 /* free the associated LP state */
    395 if( (*probingnode)->lpistate != NULL )
    396 {
    397 SCIP_CALL( SCIPlpFreeState(lp, blkmem, &(*probingnode)->lpistate) );
    398 }
    399 /* free the associated LP norms */
    400 if( (*probingnode)->lpinorms != NULL )
    401 {
    402 SCIP_CALL( SCIPlpFreeNorms(lp, blkmem, &(*probingnode)->lpinorms) );
    403 }
    404
    405 /* free objective information */
    406 if( (*probingnode)->nchgdobjs > 0 )
    407 {
    408 assert((*probingnode)->origobjvars != NULL);
    409 assert((*probingnode)->origobjvals != NULL);
    410
    411 BMSfreeMemoryArray(&(*probingnode)->origobjvars);
    412 BMSfreeMemoryArray(&(*probingnode)->origobjvals);
    413 }
    414
    415 BMSfreeBlockMemory(blkmem, probingnode);
    416
    417 return SCIP_OKAY;
    418}
    419
    420/** initializes junction data */
    421static
    423 SCIP_JUNCTION* junction, /**< pointer to junction data */
    424 SCIP_TREE* tree /**< branch and bound tree */
    425 )
    426{
    427 assert(junction != NULL);
    428 assert(tree != NULL);
    429 assert(tree->nchildren > 0);
    430 assert(SCIPtreeIsPathComplete(tree));
    431 assert(tree->focusnode != NULL);
    432
    433 junction->nchildren = tree->nchildren;
    434
    435 /* increase the LPI state usage counter of the current LP fork */
    436 if( tree->focuslpstatefork != NULL )
    437 {
    439 }
    440
    441 return SCIP_OKAY;
    442}
    443
    444/** creates pseudofork data */
    445static
    447 SCIP_PSEUDOFORK** pseudofork, /**< pointer to pseudofork data */
    448 BMS_BLKMEM* blkmem, /**< block memory */
    449 SCIP_TREE* tree, /**< branch and bound tree */
    450 SCIP_LP* lp /**< current LP data */
    451 )
    452{
    453 assert(pseudofork != NULL);
    454 assert(blkmem != NULL);
    455 assert(tree != NULL);
    456 assert(tree->nchildren > 0);
    457 assert(SCIPtreeIsPathComplete(tree));
    458 assert(tree->focusnode != NULL);
    459
    460 SCIP_ALLOC( BMSallocBlockMemory(blkmem, pseudofork) );
    461
    462 (*pseudofork)->addedcols = NULL;
    463 (*pseudofork)->addedrows = NULL;
    464 (*pseudofork)->naddedcols = SCIPlpGetNNewcols(lp);
    465 (*pseudofork)->naddedrows = SCIPlpGetNNewrows(lp);
    466 (*pseudofork)->nchildren = tree->nchildren;
    467
    468 SCIPdebugMessage("creating pseudofork information with %d children (%d new cols, %d new rows)\n",
    469 (*pseudofork)->nchildren, (*pseudofork)->naddedcols, (*pseudofork)->naddedrows);
    470
    471 if( (*pseudofork)->naddedcols > 0 )
    472 {
    473 /* copy the newly created columns to the pseudofork's col array */
    474 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*pseudofork)->addedcols, SCIPlpGetNewcols(lp), (*pseudofork)->naddedcols) ); /*lint !e666*/
    475 }
    476 if( (*pseudofork)->naddedrows > 0 )
    477 {
    478 int i;
    479
    480 /* copy the newly created rows to the pseudofork's row array */
    481 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*pseudofork)->addedrows, SCIPlpGetNewrows(lp), (*pseudofork)->naddedrows) ); /*lint !e666*/
    482
    483 /* capture the added rows */
    484 for( i = 0; i < (*pseudofork)->naddedrows; ++i )
    485 SCIProwCapture((*pseudofork)->addedrows[i]);
    486 }
    487
    488 /* increase the LPI state usage counter of the current LP fork */
    489 if( tree->focuslpstatefork != NULL )
    490 {
    492 }
    493
    494 return SCIP_OKAY;
    495}
    496
    497/** frees pseudofork data */
    498static
    500 SCIP_PSEUDOFORK** pseudofork, /**< pseudofork data */
    501 BMS_BLKMEM* blkmem, /**< block memory */
    502 SCIP_SET* set, /**< global SCIP settings */
    503 SCIP_LP* lp /**< current LP data */
    504 )
    505{
    506 int i;
    507
    508 assert(pseudofork != NULL);
    509 assert(*pseudofork != NULL);
    510 assert((*pseudofork)->nchildren == 0);
    511 assert(blkmem != NULL);
    512 assert(set != NULL);
    513
    514 /* release the added rows */
    515 for( i = 0; i < (*pseudofork)->naddedrows; ++i )
    516 {
    517 SCIP_CALL( SCIProwRelease(&(*pseudofork)->addedrows[i], blkmem, set, lp) );
    518 }
    519
    520 BMSfreeBlockMemoryArrayNull(blkmem, &(*pseudofork)->addedcols, (*pseudofork)->naddedcols);
    521 BMSfreeBlockMemoryArrayNull(blkmem, &(*pseudofork)->addedrows, (*pseudofork)->naddedrows);
    522 BMSfreeBlockMemory(blkmem, pseudofork);
    523
    524 return SCIP_OKAY;
    525}
    526
    527/** creates fork data */
    528static
    530 SCIP_FORK** fork, /**< pointer to fork data */
    531 BMS_BLKMEM* blkmem, /**< block memory */
    532 SCIP_SET* set, /**< global SCIP settings */
    533 SCIP_PROB* prob, /**< transformed problem after presolve */
    534 SCIP_TREE* tree, /**< branch and bound tree */
    535 SCIP_LP* lp /**< current LP data */
    536 )
    537{
    538 assert(fork != NULL);
    539 assert(blkmem != NULL);
    540 assert(tree != NULL);
    541 assert(tree->nchildren > 0);
    542 assert(tree->nchildren < (1 << 30));
    543 assert(SCIPtreeIsPathComplete(tree));
    544 assert(tree->focusnode != NULL);
    545 assert(lp != NULL);
    546 assert(lp->flushed);
    547 assert(lp->solved);
    549
    550 SCIP_ALLOC( BMSallocBlockMemory(blkmem, fork) );
    551
    552 SCIP_CALL( SCIPlpGetState(lp, blkmem, &((*fork)->lpistate)) );
    553 (*fork)->lpwasprimfeas = lp->primalfeasible;
    554 (*fork)->lpwasprimchecked = lp->primalchecked;
    555 (*fork)->lpwasdualfeas = lp->dualfeasible;
    556 (*fork)->lpwasdualchecked = lp->dualchecked;
    557 (*fork)->lpobjval = SCIPlpGetObjval(lp, set, prob);
    558 (*fork)->nlpistateref = 0;
    559 (*fork)->addedcols = NULL;
    560 (*fork)->addedrows = NULL;
    561 (*fork)->naddedcols = SCIPlpGetNNewcols(lp);
    562 (*fork)->naddedrows = SCIPlpGetNNewrows(lp);
    563 (*fork)->nchildren = (unsigned int) tree->nchildren;
    564
    565 SCIPsetDebugMsg(set, "creating fork information with %u children (%d new cols, %d new rows)\n", (*fork)->nchildren, (*fork)->naddedcols, (*fork)->naddedrows);
    566
    567 if( (*fork)->naddedcols > 0 )
    568 {
    569 /* copy the newly created columns to the fork's col array */
    570 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*fork)->addedcols, SCIPlpGetNewcols(lp), (*fork)->naddedcols) ); /*lint !e666*/
    571 }
    572 if( (*fork)->naddedrows > 0 )
    573 {
    574 int i;
    575
    576 /* copy the newly created rows to the fork's row array */
    577 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*fork)->addedrows, SCIPlpGetNewrows(lp), (*fork)->naddedrows) ); /*lint !e666*/
    578
    579 /* capture the added rows */
    580 for( i = 0; i < (*fork)->naddedrows; ++i )
    581 SCIProwCapture((*fork)->addedrows[i]);
    582 }
    583
    584 /* capture the LPI state for the children */
    585 forkCaptureLPIState(*fork, tree->nchildren);
    586
    587 return SCIP_OKAY;
    588}
    589
    590/** frees fork data */
    591static
    593 SCIP_FORK** fork, /**< fork data */
    594 BMS_BLKMEM* blkmem, /**< block memory */
    595 SCIP_SET* set, /**< global SCIP settings */
    596 SCIP_LP* lp /**< current LP data */
    597 )
    598{
    599 int i;
    600
    601 assert(fork != NULL);
    602 assert(*fork != NULL);
    603 assert((*fork)->nchildren == 0);
    604 assert((*fork)->nlpistateref == 0);
    605 assert((*fork)->lpistate == NULL);
    606 assert(blkmem != NULL);
    607 assert(set != NULL);
    608 assert(lp != NULL);
    609
    610 /* release the added rows */
    611 for( i = (*fork)->naddedrows - 1; i >= 0; --i )
    612 {
    613 SCIP_CALL( SCIProwRelease(&(*fork)->addedrows[i], blkmem, set, lp) );
    614 }
    615
    616 BMSfreeBlockMemoryArrayNull(blkmem, &(*fork)->addedcols, (*fork)->naddedcols);
    617 BMSfreeBlockMemoryArrayNull(blkmem, &(*fork)->addedrows, (*fork)->naddedrows);
    618 BMSfreeBlockMemory(blkmem, fork);
    619
    620 return SCIP_OKAY;
    621}
    622
    623#ifdef WITHSUBROOTS /** @todo test whether subroots should be created */
    624/** creates subroot data */
    625static
    626SCIP_RETCODE subrootCreate(
    627 SCIP_SUBROOT** subroot, /**< pointer to subroot data */
    628 BMS_BLKMEM* blkmem, /**< block memory */
    629 SCIP_SET* set, /**< global SCIP settings */
    630 SCIP_PROB* prob, /**< transformed problem after presolve */
    631 SCIP_TREE* tree, /**< branch and bound tree */
    632 SCIP_LP* lp /**< current LP data */
    633 )
    634{
    635 int i;
    636
    637 assert(subroot != NULL);
    638 assert(blkmem != NULL);
    639 assert(tree != NULL);
    640 assert(tree->nchildren > 0);
    641 assert(SCIPtreeIsPathComplete(tree));
    642 assert(tree->focusnode != NULL);
    643 assert(lp != NULL);
    644 assert(lp->flushed);
    645 assert(lp->solved);
    647
    648 SCIP_ALLOC( BMSallocBlockMemory(blkmem, subroot) );
    649 (*subroot)->lpobjval = SCIPlpGetObjval(lp, set, prob);
    650 (*subroot)->nlpistateref = 0;
    651 (*subroot)->ncols = SCIPlpGetNCols(lp);
    652 (*subroot)->nrows = SCIPlpGetNRows(lp);
    653 (*subroot)->nchildren = (unsigned int) tree->nchildren;
    654 SCIP_CALL( SCIPlpGetState(lp, blkmem, &((*subroot)->lpistate)) );
    655 (*subroot)->lpwasprimfeas = lp->primalfeasible;
    656 (*subroot)->lpwasprimchecked = lp->primalchecked;
    657 (*subroot)->lpwasdualfeas = lp->dualfeasible;
    658 (*subroot)->lpwasdualchecked = lp->dualchecked;
    659
    660 if( (*subroot)->ncols != 0 )
    661 {
    662 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*subroot)->cols, SCIPlpGetCols(lp), (*subroot)->ncols) );
    663 }
    664 else
    665 (*subroot)->cols = NULL;
    666 if( (*subroot)->nrows != 0 )
    667 {
    668 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*subroot)->rows, SCIPlpGetRows(lp), (*subroot)->nrows) );
    669 }
    670 else
    671 (*subroot)->rows = NULL;
    672
    673 /* capture the rows of the subroot */
    674 for( i = 0; i < (*subroot)->nrows; ++i )
    675 SCIProwCapture((*subroot)->rows[i]);
    676
    677 /* capture the LPI state for the children */
    678 subrootCaptureLPIState(*subroot, tree->nchildren);
    679
    680 return SCIP_OKAY;
    681}
    682#endif
    683
    684/** frees subroot */
    685static
    687 SCIP_SUBROOT** subroot, /**< subroot data */
    688 BMS_BLKMEM* blkmem, /**< block memory */
    689 SCIP_SET* set, /**< global SCIP settings */
    690 SCIP_LP* lp /**< current LP data */
    691 )
    692{
    693 int i;
    694
    695 assert(subroot != NULL);
    696 assert(*subroot != NULL);
    697 assert((*subroot)->nchildren == 0);
    698 assert((*subroot)->nlpistateref == 0);
    699 assert((*subroot)->lpistate == NULL);
    700 assert(blkmem != NULL);
    701 assert(set != NULL);
    702 assert(lp != NULL);
    703
    704 /* release the rows of the subroot */
    705 for( i = 0; i < (*subroot)->nrows; ++i )
    706 {
    707 SCIP_CALL( SCIProwRelease(&(*subroot)->rows[i], blkmem, set, lp) );
    708 }
    709
    710 BMSfreeBlockMemoryArrayNull(blkmem, &(*subroot)->cols, (*subroot)->ncols);
    711 BMSfreeBlockMemoryArrayNull(blkmem, &(*subroot)->rows, (*subroot)->nrows);
    712 BMSfreeBlockMemory(blkmem, subroot);
    713
    714 return SCIP_OKAY;
    715}
    716
    717/** removes given sibling node from the siblings array */
    718static
    720 SCIP_TREE* tree, /**< branch and bound tree */
    721 SCIP_NODE* sibling /**< sibling node to remove */
    722 )
    723{
    724 int delpos;
    725
    726 assert(tree != NULL);
    727 assert(sibling != NULL);
    728 assert(SCIPnodeGetType(sibling) == SCIP_NODETYPE_SIBLING);
    729 assert(sibling->data.sibling.arraypos >= 0 && sibling->data.sibling.arraypos < tree->nsiblings);
    730 assert(tree->siblings[sibling->data.sibling.arraypos] == sibling);
    731 assert(SCIPnodeGetType(tree->siblings[tree->nsiblings-1]) == SCIP_NODETYPE_SIBLING);
    732
    733 delpos = sibling->data.sibling.arraypos;
    734
    735 /* move last sibling in array to position of removed sibling */
    736 tree->siblings[delpos] = tree->siblings[tree->nsiblings-1];
    737 tree->siblingsprio[delpos] = tree->siblingsprio[tree->nsiblings-1];
    738 tree->siblings[delpos]->data.sibling.arraypos = delpos;
    739 sibling->data.sibling.arraypos = -1;
    740 tree->nsiblings--;
    741}
    742
    743/** adds given child node to children array of focus node */
    744static
    746 SCIP_TREE* tree, /**< branch and bound tree */
    747 SCIP_SET* set, /**< global SCIP settings */
    748 SCIP_NODE* child, /**< child node to add */
    749 SCIP_Real nodeselprio /**< node selection priority of child node */
    750 )
    751{
    752 assert(tree != NULL);
    753 assert(child != NULL);
    754 assert(SCIPnodeGetType(child) == SCIP_NODETYPE_CHILD);
    755 assert(child->data.child.arraypos == -1);
    756
    757 SCIP_CALL( treeEnsureChildrenMem(tree, set, tree->nchildren+1) );
    758 tree->children[tree->nchildren] = child;
    759 tree->childrenprio[tree->nchildren] = nodeselprio;
    760 child->data.child.arraypos = tree->nchildren;
    761 tree->nchildren++;
    762
    763 return SCIP_OKAY;
    764}
    765
    766/** removes given child node from the children array */
    767static
    769 SCIP_TREE* tree, /**< branch and bound tree */
    770 SCIP_NODE* child /**< child node to remove */
    771 )
    772{
    773 int delpos;
    774
    775 assert(tree != NULL);
    776 assert(child != NULL);
    777 assert(SCIPnodeGetType(child) == SCIP_NODETYPE_CHILD);
    778 assert(child->data.child.arraypos >= 0 && child->data.child.arraypos < tree->nchildren);
    779 assert(tree->children[child->data.child.arraypos] == child);
    780 assert(SCIPnodeGetType(tree->children[tree->nchildren-1]) == SCIP_NODETYPE_CHILD);
    781
    782 delpos = child->data.child.arraypos;
    783
    784 /* move last child in array to position of removed child */
    785 tree->children[delpos] = tree->children[tree->nchildren-1];
    786 tree->childrenprio[delpos] = tree->childrenprio[tree->nchildren-1];
    787 tree->children[delpos]->data.child.arraypos = delpos;
    788 child->data.child.arraypos = -1;
    789 tree->nchildren--;
    790}
    791
    792/** makes node a child of the given parent node, which must be the focus node; if the child is a probing node,
    793 * the parent node can also be a refocused node or a probing node
    794 */
    795static
    797 SCIP_NODE* node, /**< child node */
    798 BMS_BLKMEM* blkmem, /**< block memory buffers */
    799 SCIP_SET* set, /**< global SCIP settings */
    800 SCIP_TREE* tree, /**< branch and bound tree */
    801 SCIP_NODE* parent, /**< parent (= focus) node (or NULL, if node is root) */
    802 SCIP_Real nodeselprio /**< node selection priority of child node */
    803 )
    804{
    805 assert(node != NULL);
    806 assert(node->parent == NULL);
    808 assert(node->conssetchg == NULL);
    809 assert(node->domchg == NULL);
    810 assert(SCIPsetIsInfinity(set, -node->lowerbound)); /* node was just created */
    811 assert(blkmem != NULL);
    812 assert(set != NULL);
    813 assert(tree != NULL);
    814 assert(SCIPtreeIsPathComplete(tree));
    815 assert(tree->pathlen == 0 || tree->path[tree->pathlen-1] == parent);
    816 assert(parent == tree->focusnode || SCIPnodeGetType(parent) == SCIP_NODETYPE_PROBINGNODE);
    817 assert(parent == NULL || SCIPnodeGetType(parent) == SCIP_NODETYPE_FOCUSNODE
    821
    822 /* link node to parent */
    823 node->parent = parent;
    824 if( parent != NULL )
    825 {
    826 assert(parent->lowerbound <= parent->estimate);
    827 node->lowerbound = parent->lowerbound;
    828 node->estimate = parent->estimate;
    829 node->depth = parent->depth+1; /*lint !e732*/
    830 if( set->exact_enable )
    832
    833 if( parent->depth >= SCIP_MAXTREEDEPTH )
    834 {
    835 SCIPerrorMessage("maximal depth level exceeded\n");
    836 return SCIP_MAXDEPTHLEVEL;
    837 }
    838 }
    839 SCIPsetDebugMsg(set, "assigning parent #%" SCIP_LONGINT_FORMAT " to node #%" SCIP_LONGINT_FORMAT " at depth %d\n",
    840 parent != NULL ? SCIPnodeGetNumber(parent) : -1, SCIPnodeGetNumber(node), SCIPnodeGetDepth(node));
    841
    842 /* register node in the childlist of the focus (the parent) node */
    844 {
    845 assert(parent == NULL || SCIPnodeGetType(parent) == SCIP_NODETYPE_FOCUSNODE);
    846 SCIP_CALL( treeAddChild(tree, set, node, nodeselprio) );
    847 }
    848
    849 return SCIP_OKAY;
    850}
    851
    852/** frees node memory, decreases number of children of the parent, and replaces node with parent if no children left */
    853static
    855 SCIP_NODE** node, /**< child node */
    856 BMS_BLKMEM* blkmem, /**< block memory buffer */
    857 SCIP_SET* set, /**< global SCIP settings */
    858 SCIP_TREE* tree /**< branch and bound tree */
    859 )
    860{
    861 SCIP_NODE* parent;
    862 SCIP_Bool freeParent = FALSE;
    863
    864 assert(tree != NULL);
    865 assert(node != NULL);
    866 assert(*node != NULL);
    867
    868 SCIPsetDebugMsg(set, "releasing parent-child relationship of node #%" SCIP_LONGINT_FORMAT " at depth %d of type %d with parent #%" SCIP_LONGINT_FORMAT " of type %d\n",
    870 (*node)->parent != NULL ? SCIPnodeGetNumber((*node)->parent) : -1,
    871 (*node)->parent != NULL ? (int)SCIPnodeGetType((*node)->parent) : -1);
    872 parent = (*node)->parent;
    873 if( parent != NULL )
    874 {
    875 switch( SCIPnodeGetType(parent) )
    876 {
    878 assert(parent->active);
    882 treeRemoveChild(tree, *node);
    883 /* don't kill the focus node at this point => freeParent = FALSE */
    884 break;
    886 assert(SCIPtreeProbing(tree));
    887 /* probing nodes have to be freed individually => freeParent = FALSE */
    888 break;
    890 SCIPerrorMessage("sibling cannot be a parent node\n");
    891 return SCIP_INVALIDDATA;
    893 SCIPerrorMessage("child cannot be a parent node\n");
    894 return SCIP_INVALIDDATA;
    896 SCIPerrorMessage("leaf cannot be a parent node\n");
    897 return SCIP_INVALIDDATA;
    899 SCIPerrorMessage("dead-end cannot be a parent node\n");
    900 return SCIP_INVALIDDATA;
    902 assert(parent->data.junction.nchildren > 0);
    903 parent->data.junction.nchildren--;
    904 freeParent = (parent->data.junction.nchildren == 0); /* free parent if it has no more children */
    905 break;
    907 assert(parent->data.pseudofork != NULL);
    908 assert(parent->data.pseudofork->nchildren > 0);
    909 parent->data.pseudofork->nchildren--;
    910 freeParent = (parent->data.pseudofork->nchildren == 0); /* free parent if it has no more children */
    911 break;
    913 assert(parent->data.fork != NULL);
    914 assert(parent->data.fork->nchildren > 0);
    915 parent->data.fork->nchildren--;
    916 freeParent = (parent->data.fork->nchildren == 0); /* free parent if it has no more children */
    917 break;
    919 assert(parent->data.subroot != NULL);
    920 assert(parent->data.subroot->nchildren > 0);
    921 parent->data.subroot->nchildren--;
    922 freeParent = (parent->data.subroot->nchildren == 0); /* free parent if it has no more children */
    923 break;
    925 /* the only possible child a refocused node can have in its refocus state is the probing root node;
    926 * we don't want to free the refocused node, because we first have to convert it back to its original
    927 * type (where it possibly has children) => freeParent = FALSE
    928 */
    930 assert(!SCIPtreeProbing(tree));
    931 break;
    932 default:
    933 SCIPerrorMessage("unknown node type %d\n", SCIPnodeGetType(parent));
    934 return SCIP_INVALIDDATA;
    935 }
    936
    937 /* update the effective root depth if active parent has children and neither reoptimization nor certificate
    938 * printing is enabled
    939 */
    940 if( !freeParent && parent->active && !set->reopt_enable && !SCIPisCertified(set->scip) )
    941 {
    942 SCIP_Bool singleChild = FALSE;
    943 int focusdepth = SCIPtreeGetFocusDepth(tree);
    944
    945 assert(tree->updatedeffectiverootdepth >= 0);
    946
    947 while( tree->updatedeffectiverootdepth < focusdepth )
    948 {
    949 SCIP_NODE* effectiveroot = tree->path[tree->updatedeffectiverootdepth];
    950
    951 switch( SCIPnodeGetType(effectiveroot) )
    952 {
    954 SCIPerrorMessage("focus shallower than focus depth\n");
    955 return SCIP_INVALIDDATA;
    957 SCIPerrorMessage("probing shallower than focus depth\n");
    958 return SCIP_INVALIDDATA;
    960 SCIPerrorMessage("sibling shallower than focus depth\n");
    961 return SCIP_INVALIDDATA;
    963 SCIPerrorMessage("child shallower than focus depth\n");
    964 return SCIP_INVALIDDATA;
    966 SCIPerrorMessage("leaf on focus path\n");
    967 return SCIP_INVALIDDATA;
    969 SCIPerrorMessage("dead-end on focus path\n");
    970 return SCIP_INVALIDDATA;
    972 singleChild = (effectiveroot->data.junction.nchildren == 1);
    973 break;
    975 singleChild = (effectiveroot->data.pseudofork->nchildren == 1);
    976 break;
    978 singleChild = (effectiveroot->data.fork->nchildren == 1);
    979 break;
    981 singleChild = (effectiveroot->data.subroot->nchildren == 1);
    982 break;
    984 singleChild = FALSE;
    985 break;
    986 default:
    987 SCIPerrorMessage("unknown node type %d\n", SCIPnodeGetType(effectiveroot));
    988 return SCIP_INVALIDDATA;
    989 }
    990
    991 if( !singleChild )
    992 break;
    993
    995
    997 "unlinked node #%" SCIP_LONGINT_FORMAT " in depth %d -> new effective root depth: %d\n",
    999 }
    1000
    1001 assert(!singleChild || tree->updatedeffectiverootdepth == SCIPtreeGetFocusDepth(tree));
    1002 }
    1003 }
    1004
    1005 BMSfreeBlockMemory(blkmem, node);
    1006
    1007 /* free parent iteratively if it is not on the current active path */
    1008 if( freeParent && !parent->active )
    1009 *node = parent;
    1010
    1011 return SCIP_OKAY;
    1012}
    1013
    1014/** creates a node data structure */
    1015static
    1017 SCIP_NODE** node, /**< pointer to node data structure */
    1018 BMS_BLKMEM* blkmem, /**< block memory */
    1019 SCIP_SET* set /**< global SCIP settings */
    1020 )
    1021{
    1022 assert(node != NULL);
    1023
    1024 SCIP_ALLOC( BMSallocBlockMemory(blkmem, node) );
    1025 (*node)->parent = NULL;
    1026 (*node)->conssetchg = NULL;
    1027 (*node)->domchg = NULL;
    1028 (*node)->number = 0;
    1029 (*node)->lowerbound = -SCIPsetInfinity(set);
    1030 (*node)->estimate = -SCIPsetInfinity(set);
    1031 (*node)->reoptid = 0;
    1032 (*node)->reopttype = (unsigned int) SCIP_REOPTTYPE_NONE;
    1033 (*node)->depth = 0;
    1034 (*node)->active = FALSE;
    1035 (*node)->cutoff = FALSE;
    1036 (*node)->reprop = FALSE;
    1037 (*node)->repropsubtreemark = 0;
    1038 if( set->exact_enable )
    1039 {
    1040 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &(*node)->lowerboundexact) );
    1041 SCIPrationalSetNegInfinity((*node)->lowerboundexact);
    1042 }
    1043 else
    1044 (*node)->lowerboundexact = NULL;
    1045
    1046 return SCIP_OKAY;
    1047}
    1048
    1049/** creates a child node of the focus node */
    1051 SCIP_NODE** node, /**< pointer to node data structure */
    1052 BMS_BLKMEM* blkmem, /**< block memory */
    1053 SCIP_SET* set, /**< global SCIP settings */
    1054 SCIP_STAT* stat, /**< problem statistics */
    1055 SCIP_TREE* tree, /**< branch and bound tree */
    1056 SCIP_Real nodeselprio, /**< node selection priority of new node */
    1057 SCIP_Real estimate /**< estimate for (transformed) objective value of best feasible solution in subtree */
    1058 )
    1059{
    1060 assert(node != NULL);
    1061 assert(blkmem != NULL);
    1062 assert(set != NULL);
    1063 assert(stat != NULL);
    1064 assert(tree != NULL);
    1065 assert(SCIPtreeIsPathComplete(tree));
    1066 assert(tree->pathlen == 0 || tree->path != NULL);
    1067 assert((tree->pathlen == 0) == (tree->focusnode == NULL));
    1068 assert(tree->focusnode == NULL || tree->focusnode == tree->path[tree->pathlen-1]);
    1069 assert(tree->focusnode == NULL || SCIPnodeGetType(tree->focusnode) == SCIP_NODETYPE_FOCUSNODE);
    1070
    1071 stat->ncreatednodes++;
    1072 stat->ncreatednodesrun++;
    1073
    1074 /* create the node data structure */
    1075 SCIP_CALL( nodeCreate(node, blkmem, set) );
    1076 (*node)->number = stat->ncreatednodesrun;
    1077
    1078 /* mark node to be a child node */
    1079 (*node)->nodetype = SCIP_NODETYPE_CHILD; /*lint !e641*/
    1080 (*node)->data.child.arraypos = -1;
    1081
    1082 /* make focus node the parent of the new child */
    1083 SCIP_CALL( nodeAssignParent(*node, blkmem, set, tree, tree->focusnode, nodeselprio) );
    1084
    1085 /* update the estimate of the child */
    1086 SCIPnodeSetEstimate(*node, set, estimate);
    1087
    1088 tree->lastbranchparentid = tree->focusnode == NULL ? -1L : SCIPnodeGetNumber(tree->focusnode);
    1089
    1090 /* output node creation to visualization file */
    1091 SCIP_CALL( SCIPvisualNewChild(stat->visual, set, stat, *node) );
    1092
    1093 /* create certificate data for this node */
    1094 SCIP_CALL( SCIPcertificateNewNodeData(stat->certificate, stat, *node) );
    1095
    1096 SCIPsetDebugMsg(set, "created child node #%" SCIP_LONGINT_FORMAT " at depth %u (prio: %g)\n", SCIPnodeGetNumber(*node), (*node)->depth, nodeselprio);
    1097
    1098 return SCIP_OKAY;
    1099}
    1100
    1101/** query if focus node was already branched on */
    1103 SCIP_TREE* tree, /**< branch and bound tree */
    1104 SCIP_NODE* node /**< tree node, or NULL to check focus node */
    1105 )
    1106{
    1107 node = node == NULL ? tree->focusnode : node;
    1108 if( node != NULL && node->number == tree->lastbranchparentid )
    1109 return TRUE;
    1110
    1111 return FALSE;
    1112}
    1113
    1114/** frees node and inactive path iteratively */
    1116 SCIP_NODE** node, /**< node data */
    1117 BMS_BLKMEM* blkmem, /**< block memory buffer */
    1118 SCIP_SET* set, /**< global SCIP settings */
    1119 SCIP_STAT* stat, /**< problem statistics */
    1120 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    1121 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    1122 SCIP_TREE* tree, /**< branch and bound tree */
    1123 SCIP_LP* lp /**< current LP data */
    1124 )
    1125{
    1126 SCIP_Bool isroot;
    1127
    1128 assert(tree != NULL);
    1129 assert(node != NULL);
    1130 assert(*node != NULL);
    1131
    1132 do
    1133 {
    1134 assert(!(*node)->active);
    1135
    1136 SCIPsetDebugMsg(set, "free node #%" SCIP_LONGINT_FORMAT " at depth %d of type %d\n", SCIPnodeGetNumber(*node), SCIPnodeGetDepth(*node), SCIPnodeGetType(*node));
    1137
    1138 /* if certificate is active, unsplit current node and free the memory in hashmap of certificate */
    1140
    1141 /* check lower bound w.r.t. debugging solution */
    1143
    1145 {
    1146 SCIP_EVENT event;
    1147
    1148 /* trigger a node deletion event */
    1150 SCIP_CALL( SCIPeventChgNode(&event, *node) );
    1151 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
    1152 }
    1153
    1154 /* inform solution debugger, that the node has been freed */
    1155 SCIP_CALL( SCIPdebugRemoveNode(blkmem, set, *node) );
    1156
    1157 /* check, if the node to be freed is the root node */
    1158 isroot = (SCIPnodeGetDepth(*node) == 0);
    1159
    1160 /* free nodetype specific data, and release no longer needed LPI states */
    1161 switch( SCIPnodeGetType(*node) )
    1162 {
    1164 assert(tree->focusnode == *node);
    1165 assert(!SCIPtreeProbing(tree));
    1166 SCIPerrorMessage("cannot free focus node - has to be converted into a dead end first\n");
    1167 return SCIP_INVALIDDATA;
    1169 assert(SCIPtreeProbing(tree));
    1170 assert(SCIPnodeGetDepth(tree->probingroot) <= SCIPnodeGetDepth(*node));
    1171 assert(SCIPnodeGetDepth(*node) > 0);
    1172 SCIP_CALL( probingnodeFree(&((*node)->data.probingnode), blkmem, lp) );
    1173 break;
    1175 assert((*node)->data.sibling.arraypos >= 0);
    1176 assert((*node)->data.sibling.arraypos < tree->nsiblings);
    1177 assert(tree->siblings[(*node)->data.sibling.arraypos] == *node);
    1178 if( tree->focuslpstatefork != NULL )
    1179 {
    1183 }
    1184 treeRemoveSibling(tree, *node);
    1185 break;
    1187 assert((*node)->data.child.arraypos >= 0);
    1188 assert((*node)->data.child.arraypos < tree->nchildren);
    1189 assert(tree->children[(*node)->data.child.arraypos] == *node);
    1190 /* The children capture the LPI state at the moment, where the focus node is
    1191 * converted into a junction, pseudofork, fork, or subroot, and a new node is focused.
    1192 * At the same time, they become siblings or leaves, such that freeing a child
    1193 * of the focus node doesn't require to release the LPI state;
    1194 * we don't need to call treeRemoveChild(), because this is done in nodeReleaseParent()
    1195 */
    1196 break;
    1197 case SCIP_NODETYPE_LEAF:
    1198 if( (*node)->data.leaf.lpstatefork != NULL )
    1199 {
    1200 SCIP_CALL( SCIPnodeReleaseLPIState((*node)->data.leaf.lpstatefork, blkmem, lp) );
    1201 }
    1202 break;
    1205 break;
    1207 SCIP_CALL( pseudoforkFree(&((*node)->data.pseudofork), blkmem, set, lp) );
    1208 break;
    1209 case SCIP_NODETYPE_FORK:
    1210 /* release special root LPI state capture which is used to keep the root LPI state over the whole solving
    1211 * process
    1212 */
    1213 if( isroot )
    1214 {
    1215 SCIP_CALL( SCIPnodeReleaseLPIState(*node, blkmem, lp) );
    1216 }
    1217 SCIP_CALL( forkFree(&((*node)->data.fork), blkmem, set, lp) );
    1218 break;
    1220 SCIP_CALL( subrootFree(&((*node)->data.subroot), blkmem, set, lp) );
    1221 break;
    1223 SCIPerrorMessage("cannot free node as long it is refocused\n");
    1224 return SCIP_INVALIDDATA;
    1225 default:
    1226 SCIPerrorMessage("unknown node type %d\n", SCIPnodeGetType(*node));
    1227 return SCIP_INVALIDDATA;
    1228 }
    1229
    1230 /* free common data */
    1231 SCIP_CALL( SCIPconssetchgFree(&(*node)->conssetchg, blkmem, set) );
    1232 SCIP_CALL( SCIPdomchgFree(&(*node)->domchg, blkmem, set, eventqueue, lp) );
    1233
    1234 /* check, if the node is the current probing root */
    1235 if( *node == tree->probingroot )
    1236 {
    1238 tree->probingroot = NULL;
    1239 }
    1240
    1241 if( set->exact_enable )
    1242 SCIPrationalFreeBlock(blkmem, &(*node)->lowerboundexact);
    1243
    1244 /* delete the tree's root node pointer, if the freed node was the root */
    1245 if( isroot )
    1246 tree->root = NULL;
    1247
    1248 SCIP_CALL( nodeReleaseParent(node, blkmem, set, tree) );
    1249 }
    1250 while( *node != NULL );
    1251
    1252 return SCIP_OKAY;
    1253}
    1254
    1255/** cuts off node and whole sub tree from branch and bound tree
    1256 *
    1257 * @note must not be used on a leaf because the node priority queue remains untouched
    1258 */
    1260 SCIP_NODE* node, /**< node that should be cut off */
    1261 SCIP_SET* set, /**< global SCIP settings */
    1262 SCIP_STAT* stat, /**< problem statistics */
    1263 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    1264 SCIP_TREE* tree, /**< branch and bound tree */
    1265 SCIP_PROB* transprob, /**< transformed problem after presolve */
    1266 SCIP_PROB* origprob, /**< original problem */
    1267 SCIP_REOPT* reopt, /**< reoptimization data structure */
    1268 SCIP_LP* lp, /**< current LP */
    1269 BMS_BLKMEM* blkmem /**< block memory */
    1270 )
    1271{
    1272 SCIP_NODETYPE nodetype;
    1273
    1274 assert(set != NULL);
    1275 assert(stat != NULL);
    1276 assert(tree != NULL);
    1277 assert(set->stage < SCIP_STAGE_INITSOLVE
    1280 && (!set->exact_enable || SCIPrationalIsEQ(SCIPtreeGetLowerboundExact(tree, set), stat->lastlowerboundexact))));
    1281
    1282 SCIPsetDebugMsg(set, "cutting off %s node #%" SCIP_LONGINT_FORMAT " at depth %d (cutoffdepth: %d)\n",
    1283 node->active ? "active" : "inactive", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), tree->cutoffdepth);
    1284
    1285 /* check if the node should be stored for reoptimization */
    1286 if( set->reopt_enable )
    1287 {
    1289 SCIPlpGetSolstat(lp), tree->root == node, tree->focusnode == node, node->lowerbound,
    1290 tree->effectiverootdepth) );
    1291 }
    1292
    1293 nodetype = SCIPnodeGetType(node);
    1294 assert(nodetype != SCIP_NODETYPE_LEAF);
    1295
    1296 node->cutoff = TRUE;
    1297 if( set->exact_enable )
    1300 node->estimate = SCIPsetInfinity(set);
    1301
    1302 if( node->active && tree->cutoffdepth > node->depth )
    1303 tree->cutoffdepth = (int) node->depth;
    1304
    1305 if( node->depth == 0 )
    1307
    1308 /* update lower bound statistics during solving */
    1309 if( !stat->inrestart && set->stage >= SCIP_STAGE_INITSOLVE
    1310 && ( nodetype == SCIP_NODETYPE_FOCUSNODE || nodetype == SCIP_NODETYPE_CHILD || nodetype == SCIP_NODETYPE_SIBLING ) )
    1311 {
    1312 SCIP_Real lowerbound;
    1313
    1314 if( set->exact_enable )
    1315 {
    1316 SCIP_RATIONAL* lowerboundexact = SCIPtreeGetLowerboundExact(tree, set);
    1317 assert(SCIPrationalIsGEReal(lowerboundexact, SCIPtreeGetLowerbound(tree, set)));
    1318
    1319 /* exact lower bound improved */
    1320 if( SCIPrationalIsLT(stat->lastlowerboundexact, lowerboundexact) )
    1321 {
    1322 /* throw improvement event if upper bound not already exceeded */
    1323 if( SCIPrationalIsLT(stat->lastlowerboundexact, set->scip->primal->upperboundexact) )
    1324 {
    1325 SCIP_EVENT event;
    1326
    1328 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
    1329 }
    1330
    1331 /* update exact last lower bound */
    1332 SCIPrationalSetRational(stat->lastlowerboundexact, lowerboundexact);
    1333 }
    1334 }
    1335
    1336 lowerbound = SCIPtreeGetLowerbound(tree, set);
    1337 assert(lowerbound <= SCIPsetInfinity(set));
    1338
    1339 /* lower bound improved */
    1340 if( stat->lastlowerbound < lowerbound )
    1341 {
    1342 /* throw improvement event if not already done exactly */
    1343 if( !set->exact_enable && stat->lastlowerbound < set->scip->primal->upperbound )
    1344 {
    1345 SCIP_EVENT event;
    1346
    1348 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
    1349 }
    1350
    1351 /* update primal-dual integrals */
    1352 if( set->misc_calcintegral )
    1353 {
    1354 SCIPstatUpdatePrimalDualIntegrals(stat, set, transprob, origprob, SCIPsetInfinity(set), lowerbound);
    1355 assert(stat->lastlowerbound == lowerbound); /*lint !e777*/
    1356 }
    1357 else
    1358 stat->lastlowerbound = lowerbound;
    1359 }
    1360
    1361 SCIPvisualCutoffNode(stat->visual, set, stat, node, TRUE);
    1362 }
    1363
    1364 return SCIP_OKAY;
    1365}
    1366
    1367/** marks node, that propagation should be applied again the next time, a node of its subtree is focused */
    1369 SCIP_NODE* node, /**< node that should be propagated again */
    1370 SCIP_SET* set, /**< global SCIP settings */
    1371 SCIP_STAT* stat, /**< problem statistics */
    1372 SCIP_TREE* tree /**< branch and bound tree */
    1373 )
    1374{
    1375 assert(node != NULL);
    1376 assert(set != NULL);
    1377 assert(stat != NULL);
    1378 assert(tree != NULL);
    1379
    1380 if( !node->reprop )
    1381 {
    1382 node->reprop = TRUE;
    1383 if( node->active )
    1384 tree->repropdepth = MIN(tree->repropdepth, (int)node->depth);
    1385
    1386 SCIPvisualMarkedRepropagateNode(stat->visual, stat, node);
    1387
    1388 SCIPsetDebugMsg(set, "marked %s node #%" SCIP_LONGINT_FORMAT " at depth %d to be propagated again (repropdepth: %d)\n",
    1389 node->active ? "active" : "inactive", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), tree->repropdepth);
    1390 }
    1391}
    1392
    1393/** marks node, that it is completely propagated in the current repropagation subtree level */
    1395 SCIP_NODE* node, /**< node that should be marked to be propagated */
    1396 SCIP_TREE* tree /**< branch and bound tree */
    1397 )
    1398{
    1399 assert(node != NULL);
    1400 assert(tree != NULL);
    1401
    1402 if( node->parent != NULL )
    1403 node->repropsubtreemark = node->parent->repropsubtreemark; /*lint !e732*/
    1404 node->reprop = FALSE;
    1405
    1406 /* if the node was the highest repropagation node in the path, update the repropdepth in the tree data */
    1407 if( node->active && node->depth == tree->repropdepth )
    1408 {
    1409 do
    1410 {
    1411 assert(tree->repropdepth < tree->pathlen);
    1412 assert(tree->path[tree->repropdepth]->active);
    1413 assert(!tree->path[tree->repropdepth]->reprop);
    1414 tree->repropdepth++;
    1415 }
    1416 while( tree->repropdepth < tree->pathlen && !tree->path[tree->repropdepth]->reprop );
    1417 if( tree->repropdepth == tree->pathlen )
    1418 tree->repropdepth = INT_MAX;
    1419 }
    1420}
    1421
    1422/** moves the subtree repropagation counter to the next value */
    1423static
    1425 SCIP_TREE* tree /**< branch and bound tree */
    1426 )
    1427{
    1428 assert(tree != NULL);
    1429
    1430 tree->repropsubtreecount++;
    1431 tree->repropsubtreecount %= (MAXREPROPMARK+1);
    1432}
    1433
    1434/** applies propagation on the node, that was marked to be propagated again */
    1435static
    1437 SCIP_NODE* node, /**< node to apply propagation on */
    1438 BMS_BLKMEM* blkmem, /**< block memory buffers */
    1439 SCIP_SET* set, /**< global SCIP settings */
    1440 SCIP_STAT* stat, /**< dynamic problem statistics */
    1441 SCIP_PROB* transprob, /**< transformed problem */
    1442 SCIP_PROB* origprob, /**< original problem */
    1443 SCIP_PRIMAL* primal, /**< primal data */
    1444 SCIP_TREE* tree, /**< branch and bound tree */
    1445 SCIP_REOPT* reopt, /**< reoptimization data structure */
    1446 SCIP_LP* lp, /**< current LP data */
    1447 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    1448 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    1449 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    1450 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    1451 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    1452 SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
    1453 )
    1454{
    1455 SCIP_NODETYPE oldtype;
    1456 SCIP_NODE* oldfocusnode;
    1457 SCIP_NODE* oldfocuslpfork;
    1458 SCIP_NODE* oldfocuslpstatefork;
    1459 SCIP_NODE* oldfocussubroot;
    1460 SCIP_Longint oldfocuslpstateforklpcount;
    1461 int oldnchildren;
    1462 int oldnsiblings;
    1463 SCIP_Bool oldfocusnodehaslp;
    1464 SCIP_Longint oldnboundchgs;
    1465 SCIP_Bool initialreprop;
    1466 SCIP_Bool clockisrunning;
    1467
    1468 assert(node != NULL);
    1474 assert(node->active);
    1475 assert(node->reprop || node->repropsubtreemark != node->parent->repropsubtreemark);
    1476 assert(stat != NULL);
    1477 assert(tree != NULL);
    1478 assert(SCIPeventqueueIsDelayed(eventqueue));
    1479 assert(cutoff != NULL);
    1480
    1481 SCIPsetDebugMsg(set, "propagating again node #%" SCIP_LONGINT_FORMAT " at depth %d\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node));
    1482 initialreprop = node->reprop;
    1483
    1484 SCIPvisualRepropagatedNode(stat->visual, stat, node);
    1485
    1486 /* process the delayed events in order to flush the problem changes */
    1487 SCIP_CALL( SCIPeventqueueProcess(eventqueue, blkmem, set, primal, lp, branchcand, eventfilter) );
    1488
    1489 /* stop node activation timer */
    1490 clockisrunning = SCIPclockIsRunning(stat->nodeactivationtime);
    1491 if( clockisrunning )
    1493
    1494 /* mark the node refocused and temporarily install it as focus node */
    1495 oldtype = (SCIP_NODETYPE)node->nodetype;
    1496 oldfocusnode = tree->focusnode;
    1497 oldfocuslpfork = tree->focuslpfork;
    1498 oldfocuslpstatefork = tree->focuslpstatefork;
    1499 oldfocussubroot = tree->focussubroot;
    1500 oldfocuslpstateforklpcount = tree->focuslpstateforklpcount;
    1501 oldnchildren = tree->nchildren;
    1502 oldnsiblings = tree->nsiblings;
    1503 oldfocusnodehaslp = tree->focusnodehaslp;
    1504 node->nodetype = SCIP_NODETYPE_REFOCUSNODE; /*lint !e641*/
    1505 tree->focusnode = node;
    1506 tree->focuslpfork = NULL;
    1507 tree->focuslpstatefork = NULL;
    1508 tree->focussubroot = NULL;
    1509 tree->focuslpstateforklpcount = -1;
    1510 tree->nchildren = 0;
    1511 tree->nsiblings = 0;
    1512 tree->focusnodehaslp = FALSE;
    1513
    1514 /* propagate the domains again */
    1515 oldnboundchgs = stat->nboundchgs;
    1516 SCIP_CALL( SCIPpropagateDomains(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
    1517 eventqueue, eventfilter, conflict, cliquetable, SCIPnodeGetDepth(node), 0, SCIP_PROPTIMING_ALWAYS, cutoff) );
    1518 assert(!node->reprop || *cutoff);
    1519 assert(node->parent == NULL || node->repropsubtreemark == node->parent->repropsubtreemark);
    1521 assert(tree->focusnode == node);
    1522 assert(tree->focuslpfork == NULL);
    1523 assert(tree->focuslpstatefork == NULL);
    1524 assert(tree->focussubroot == NULL);
    1525 assert(tree->focuslpstateforklpcount == -1);
    1526 assert(tree->nchildren == 0);
    1527 assert(tree->nsiblings == 0);
    1528 assert(tree->focusnodehaslp == FALSE);
    1529 assert(stat->nboundchgs >= oldnboundchgs);
    1530 stat->nreprops++;
    1531 stat->nrepropboundchgs += stat->nboundchgs - oldnboundchgs;
    1532 if( *cutoff )
    1533 stat->nrepropcutoffs++;
    1534
    1535 SCIPsetDebugMsg(set, "repropagation %" SCIP_LONGINT_FORMAT " at depth %u changed %" SCIP_LONGINT_FORMAT " bounds (total reprop bound changes: %" SCIP_LONGINT_FORMAT "), cutoff: %u\n",
    1536 stat->nreprops, node->depth, stat->nboundchgs - oldnboundchgs, stat->nrepropboundchgs, *cutoff);
    1537
    1538 /* if a propagation marked with the reprop flag was successful, we want to repropagate the whole subtree */
    1539 /**@todo because repropsubtree is only a bit flag, we cannot mark a whole subtree a second time for
    1540 * repropagation; use a (small) part of the node's bits to be able to store larger numbers,
    1541 * and update tree->repropsubtreelevel with this number
    1542 */
    1543 if( initialreprop && !(*cutoff) && stat->nboundchgs > oldnboundchgs )
    1544 {
    1546 node->repropsubtreemark = tree->repropsubtreecount; /*lint !e732*/
    1547 SCIPsetDebugMsg(set, "initial repropagation at depth %u changed %" SCIP_LONGINT_FORMAT " bounds -> repropagating subtree (new mark: %d)\n",
    1548 node->depth, stat->nboundchgs - oldnboundchgs, tree->repropsubtreecount);
    1549 assert((int)(node->repropsubtreemark) == tree->repropsubtreecount); /* bitfield must be large enough */
    1550 }
    1551
    1552 /* reset the node's type and reinstall the old focus node */
    1553 node->nodetype = oldtype; /*lint !e641*/
    1554 tree->focusnode = oldfocusnode;
    1555 tree->focuslpfork = oldfocuslpfork;
    1556 tree->focuslpstatefork = oldfocuslpstatefork;
    1557 tree->focussubroot = oldfocussubroot;
    1558 tree->focuslpstateforklpcount = oldfocuslpstateforklpcount;
    1559 tree->nchildren = oldnchildren;
    1560 tree->nsiblings = oldnsiblings;
    1561 tree->focusnodehaslp = oldfocusnodehaslp;
    1562
    1563 /* make the domain change data static again to save memory */
    1565 {
    1566 SCIP_CALL( SCIPdomchgMakeStatic(&node->domchg, blkmem, set, eventqueue, lp) );
    1567 }
    1568
    1569 /* start node activation timer again */
    1570 if( clockisrunning )
    1572
    1573 /* delay events in path switching */
    1574 SCIP_CALL( SCIPeventqueueDelay(eventqueue) );
    1575
    1576 /* mark the node to be cut off if a cutoff was detected */
    1577 if( *cutoff )
    1578 {
    1579 SCIP_CALL( SCIPnodeCutoff(node, set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
    1580 }
    1581
    1582 return SCIP_OKAY;
    1583}
    1584
    1585/** informs node, that it is now on the active path and applies any domain and constraint set changes */
    1586static
    1588 SCIP_NODE* node, /**< node to activate */
    1589 BMS_BLKMEM* blkmem, /**< block memory buffers */
    1590 SCIP_SET* set, /**< global SCIP settings */
    1591 SCIP_STAT* stat, /**< problem statistics */
    1592 SCIP_PROB* transprob, /**< transformed problem */
    1593 SCIP_PROB* origprob, /**< original problem */
    1594 SCIP_PRIMAL* primal, /**< primal data */
    1595 SCIP_TREE* tree, /**< branch and bound tree */
    1596 SCIP_REOPT* reopt, /**< reotimization data structure */
    1597 SCIP_LP* lp, /**< current LP data */
    1598 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    1599 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    1600 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    1601 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    1602 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    1603 SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
    1604 )
    1605{
    1606 assert(node != NULL);
    1607 assert(!node->active);
    1608 assert(stat != NULL);
    1609 assert(tree != NULL);
    1610 assert(!SCIPtreeProbing(tree));
    1611 assert(cutoff != NULL);
    1612
    1613 SCIPsetDebugMsg(set, "activate node #%" SCIP_LONGINT_FORMAT " at depth %d of type %d (reprop subtree mark: %u)\n",
    1615
    1616 /* apply lower bound, variable domain, and constraint set changes */
    1617 if( node->parent != NULL )
    1618 {
    1619 SCIP_CALL( SCIPnodeUpdateLowerbound(node, stat, set, eventfilter, tree, transprob, origprob, node->parent->lowerbound, node->parent->lowerboundexact) );
    1620 }
    1621 SCIP_CALL( SCIPconssetchgApply(node->conssetchg, blkmem, set, stat, (int) node->depth,
    1623 SCIP_CALL( SCIPdomchgApply(node->domchg, blkmem, set, stat, lp, branchcand, eventqueue, (int) node->depth, cutoff) );
    1624
    1625 /* mark node active */
    1626 node->active = TRUE;
    1627 stat->nactivatednodes++;
    1628
    1629 /* check if the domain change produced a cutoff */
    1630 if( *cutoff )
    1631 {
    1632 /* try to repropagate the node to see, if the propagation also leads to a conflict and a conflict constraint
    1633 * could be generated; if propagation conflict analysis is turned off, repropagating the node makes no
    1634 * sense, since it is already cut off
    1635 */
    1636 node->reprop = set->conf_enable && set->conf_useprop;
    1637
    1638 /* mark the node to be cut off */
    1639 SCIP_CALL( SCIPnodeCutoff(node, set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
    1640 }
    1641
    1642 /* propagate node again, if the reprop flag is set; in the new focus node, no repropagation is necessary, because
    1643 * the focus node is propagated anyways
    1644 */
    1646 && (node->reprop || (node->parent != NULL && node->repropsubtreemark != node->parent->repropsubtreemark)) )
    1647 {
    1648 SCIP_Bool propcutoff;
    1649
    1650 SCIP_CALL( nodeRepropagate(node, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, conflict,
    1651 eventqueue, eventfilter, cliquetable, &propcutoff) );
    1652 *cutoff = *cutoff || propcutoff;
    1653 }
    1654
    1655 return SCIP_OKAY;
    1656}
    1657
    1658/** informs node, that it is no longer on the active path and undoes any domain and constraint set changes */
    1659static
    1661 SCIP_NODE* node, /**< node to deactivate */
    1662 BMS_BLKMEM* blkmem, /**< block memory buffers */
    1663 SCIP_SET* set, /**< global SCIP settings */
    1664 SCIP_STAT* stat, /**< problem statistics */
    1665 SCIP_TREE* tree, /**< branch and bound tree */
    1666 SCIP_LP* lp, /**< current LP data */
    1667 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    1668 SCIP_EVENTQUEUE* eventqueue /**< event queue */
    1669 )
    1670{
    1671 assert(node != NULL);
    1672 assert(node->active);
    1673 assert(tree != NULL);
    1675
    1676 SCIPsetDebugMsg(set, "deactivate node #%" SCIP_LONGINT_FORMAT " at depth %d of type %d (reprop subtree mark: %u)\n",
    1678
    1679 /* undo domain and constraint set changes */
    1680 SCIP_CALL( SCIPdomchgUndo(node->domchg, blkmem, set, stat, lp, branchcand, eventqueue) );
    1681 SCIP_CALL( SCIPconssetchgUndo(node->conssetchg, blkmem, set, stat) );
    1682
    1683 /* mark node inactive */
    1684 node->active = FALSE;
    1685
    1686 /* count number of deactivated nodes (ignoring probing switches) */
    1687 if( !SCIPtreeProbing(tree) )
    1688 stat->ndeactivatednodes++;
    1689
    1690 return SCIP_OKAY;
    1691}
    1692
    1693/** adds constraint locally to the node and captures it; activates constraint, if node is active;
    1694 * if a local constraint is added to the root node, it is automatically upgraded into a global constraint
    1695 */
    1697 SCIP_NODE* node, /**< node to add constraint to */
    1698 BMS_BLKMEM* blkmem, /**< block memory */
    1699 SCIP_SET* set, /**< global SCIP settings */
    1700 SCIP_STAT* stat, /**< problem statistics */
    1701 SCIP_TREE* tree, /**< branch and bound tree */
    1702 SCIP_CONS* cons /**< constraint to add */
    1703 )
    1704{
    1705 assert(node != NULL);
    1706 assert(cons != NULL);
    1707 assert(cons->validdepth <= SCIPnodeGetDepth(node));
    1708 assert(tree != NULL);
    1709 assert(tree->effectiverootdepth >= 0);
    1710 assert(tree->root != NULL);
    1711 assert(SCIPconsIsGlobal(cons) || SCIPnodeGetDepth(node) > tree->effectiverootdepth);
    1712
    1713#ifndef NDEBUG
    1714 /* check if we add this constraint to the same scip, where we create the constraint */
    1715 if( cons->scip != set->scip )
    1716 {
    1717 SCIPerrorMessage("try to add a constraint of another scip instance\n");
    1718 return SCIP_INVALIDDATA;
    1719 }
    1720#endif
    1721
    1722 /* add constraint addition to the node's constraint set change data, and activate constraint if node is active */
    1723 SCIP_CALL( SCIPconssetchgAddAddedCons(&node->conssetchg, blkmem, set, stat, cons, (int) node->depth,
    1724 (SCIPnodeGetType(node) == SCIP_NODETYPE_FOCUSNODE), node->active) );
    1725 assert(node->conssetchg != NULL);
    1726 assert(node->conssetchg->addedconss != NULL);
    1727 assert(!node->active || SCIPconsIsActive(cons));
    1728
    1729 /* if the constraint is added to an active node which is not a probing node, increment the corresponding counter */
    1730 if( node->active && SCIPnodeGetType(node) != SCIP_NODETYPE_PROBINGNODE )
    1731 stat->nactiveconssadded++;
    1732
    1733 return SCIP_OKAY;
    1734}
    1735
    1736/** locally deletes constraint at the given node by disabling its separation, enforcing, and propagation capabilities
    1737 * at the node; captures constraint; disables constraint, if node is active
    1738 */
    1740 SCIP_NODE* node, /**< node to add constraint to */
    1741 BMS_BLKMEM* blkmem, /**< block memory */
    1742 SCIP_SET* set, /**< global SCIP settings */
    1743 SCIP_STAT* stat, /**< problem statistics */
    1744 SCIP_TREE* tree, /**< branch and bound tree */
    1745 SCIP_CONS* cons /**< constraint to locally delete */
    1746 )
    1747{
    1748 assert(node != NULL);
    1749 assert(tree != NULL);
    1750 assert(cons != NULL);
    1751
    1752 SCIPsetDebugMsg(set, "disabling constraint <%s> at node at depth %u\n", cons->name, node->depth);
    1753
    1754 /* add constraint disabling to the node's constraint set change data */
    1755 SCIP_CALL( SCIPconssetchgAddDisabledCons(&node->conssetchg, blkmem, set, cons) );
    1756 assert(node->conssetchg != NULL);
    1757 assert(node->conssetchg->disabledconss != NULL);
    1758
    1759 /* disable constraint, if node is active */
    1760 if( node->active && cons->enabled && !cons->updatedisable )
    1761 {
    1762 SCIP_CALL( SCIPconsDisable(cons, set, stat) );
    1763 }
    1764
    1765 return SCIP_OKAY;
    1766}
    1767
    1768/** returns all constraints added to a given node */
    1770 SCIP_NODE* node, /**< node */
    1771 SCIP_CONS** addedconss, /**< array to store the constraints */
    1772 int* naddedconss, /**< number of added constraints */
    1773 int addedconsssize /**< size of the constraint array */
    1774 )
    1775{
    1776 int cons;
    1777
    1778 assert(node != NULL );
    1779 assert(node->conssetchg != NULL);
    1780 assert(node->conssetchg->addedconss != NULL);
    1781 assert(node->conssetchg->naddedconss >= 1);
    1782
    1783 *naddedconss = node->conssetchg->naddedconss;
    1784
    1785 /* check the size and return if the array is not large enough */
    1786 if( addedconsssize < *naddedconss )
    1787 return;
    1788
    1789 /* fill the array */
    1790 for( cons = 0; cons < *naddedconss; cons++ )
    1791 {
    1792 addedconss[cons] = node->conssetchg->addedconss[cons];
    1793 }
    1794
    1795 return;
    1796}
    1797
    1798/** returns the number of added constraints to the given node */
    1800 SCIP_NODE* node /**< node */
    1801 )
    1802{
    1803 assert(node != NULL);
    1804
    1805 if( node->conssetchg == NULL )
    1806 return 0;
    1807 else
    1808 return node->conssetchg->naddedconss;
    1809}
    1810
    1811/** adds the given bound change to the list of pending bound changes */
    1812static
    1814 SCIP_TREE* tree, /**< branch and bound tree */
    1815 SCIP_SET* set, /**< global SCIP settings */
    1816 SCIP_NODE* node, /**< node to add bound change to */
    1817 SCIP_VAR* var, /**< variable to change the bounds for */
    1818 SCIP_Real newbound, /**< new value for bound */
    1819 SCIP_RATIONAL* newboundexact, /**< new exact bound, or NULL if not needed */
    1820 SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
    1821 SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
    1822 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
    1823 int inferinfo, /**< user information for inference to help resolving the conflict */
    1824 SCIP_Bool probingchange /**< is the bound change a temporary setting due to probing? */
    1825 )
    1826{
    1827 assert(tree != NULL);
    1828
    1829 /* make sure that enough memory is allocated for the pendingbdchgs array */
    1831
    1832 /* capture the variable */
    1833 SCIPvarCapture(var);
    1834
    1835 /* add the bound change to the pending list */
    1836 tree->pendingbdchgs[tree->npendingbdchgs].node = node;
    1837 tree->pendingbdchgs[tree->npendingbdchgs].var = var;
    1838 tree->pendingbdchgs[tree->npendingbdchgs].newbound = newbound;
    1839 tree->pendingbdchgs[tree->npendingbdchgs].boundtype = boundtype;
    1840 tree->pendingbdchgs[tree->npendingbdchgs].infercons = infercons;
    1841 tree->pendingbdchgs[tree->npendingbdchgs].inferprop = inferprop;
    1842 tree->pendingbdchgs[tree->npendingbdchgs].inferinfo = inferinfo;
    1843 tree->pendingbdchgs[tree->npendingbdchgs].probingchange = probingchange;
    1844 if( newboundexact != NULL )
    1845 {
    1846 if( tree->pendingbdchgs[tree->npendingbdchgs].newboundexact == NULL )
    1847 {
    1849 }
    1851 }
    1852 tree->npendingbdchgs++;
    1853
    1854 /* check global pending boundchanges against debug solution */
    1855 if( node->depth == 0 )
    1856 {
    1857#ifndef NDEBUG
    1858 SCIP_Real bound = newbound;
    1859
    1860 /* get bound adjusted for integrality(, this should already be done) */
    1861 SCIPvarAdjustBd(var, set, boundtype, &bound);
    1862
    1863 if( boundtype == SCIP_BOUNDTYPE_LOWER )
    1864 {
    1865 /* check that the bound is feasible */
    1866 if( bound > SCIPvarGetUbGlobal(var) )
    1867 {
    1868 /* due to numerics we only want to be feasible in feasibility tolerance */
    1871 }
    1872 }
    1873 else
    1874 {
    1875 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
    1876
    1877 /* check that the bound is feasible */
    1878 if( bound < SCIPvarGetLbGlobal(var) )
    1879 {
    1880 /* due to numerics we only want to be feasible in feasibility tolerance */
    1883 }
    1884 }
    1885 /* check that the given bound was already adjusted for integrality */
    1886 assert(SCIPsetIsEQ(set, newbound, bound));
    1887#endif
    1888 if( boundtype == SCIP_BOUNDTYPE_LOWER )
    1889 {
    1890 /* check bound on debugging solution */
    1891 SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
    1892 }
    1893 else
    1894 {
    1895 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
    1896
    1897 /* check bound on debugging solution */
    1898 SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
    1899 }
    1900 }
    1901
    1902 return SCIP_OKAY;
    1903}
    1904
    1905/** adds bound change with inference information to focus node, child of focus node, or probing node;
    1906 * if possible, adjusts bound to integral value;
    1907 * at most one of infercons and inferprop may be non-NULL
    1908 */
    1910 SCIP_NODE* node, /**< node to add bound change to */
    1911 BMS_BLKMEM* blkmem, /**< block memory */
    1912 SCIP_SET* set, /**< global SCIP settings */
    1913 SCIP_STAT* stat, /**< problem statistics */
    1914 SCIP_PROB* transprob, /**< transformed problem after presolve */
    1915 SCIP_PROB* origprob, /**< original problem */
    1916 SCIP_TREE* tree, /**< branch and bound tree */
    1917 SCIP_REOPT* reopt, /**< reoptimization data structure */
    1918 SCIP_LP* lp, /**< current LP data */
    1919 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    1920 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    1921 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    1922 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    1923 SCIP_VAR* var, /**< variable to change the bounds for */
    1924 SCIP_Real newbound, /**< new value for bound */
    1925 SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
    1926 SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
    1927 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
    1928 int inferinfo, /**< user information for inference to help resolving the conflict */
    1929 SCIP_Bool probingchange /**< is the bound change a temporary setting due to probing? */
    1930 )
    1931{
    1932 SCIP_VAR* infervar;
    1933 SCIP_BOUNDTYPE inferboundtype;
    1934 SCIP_Real oldlb;
    1935 SCIP_Real oldub;
    1936 SCIP_Real oldbound;
    1937 SCIP_Bool useglobal;
    1938
    1939 useglobal = (int) node->depth <= tree->effectiverootdepth;
    1940 if( useglobal )
    1941 {
    1942 oldlb = SCIPvarGetLbGlobal(var);
    1943 oldub = SCIPvarGetUbGlobal(var);
    1944 }
    1945 else
    1946 {
    1947 oldlb = SCIPvarGetLbLocal(var);
    1948 oldub = SCIPvarGetUbLocal(var);
    1949 }
    1950 if( set->exact_enable && useglobal )
    1951 {
    1952 SCIP_RATIONAL* newboundex;
    1953
    1954 SCIP_CALL( SCIPrationalCreateBuffer(SCIPbuffer(set->scip), &newboundex) );
    1955
    1956 SCIPrationalSetReal(newboundex, newbound);
    1957 SCIP_CALL( SCIPcertificatePrintGlobalBound(set->scip, stat->certificate, var, boundtype,
    1958 newboundex, SCIPcertificateGetCurrentIndex(stat->certificate) - 1) );
    1959 SCIP_CALL( SCIPvarChgBdGlobalExact(var, blkmem, set, stat, lp->lpexact, branchcand,
    1960 eventqueue, cliquetable, newboundex, boundtype) );
    1961
    1962 SCIPrationalFreeBuffer(SCIPbuffer(set->scip), &newboundex);
    1963 }
    1964
    1965 assert(node != NULL);
    1970 || node->depth == 0);
    1971 assert(set != NULL);
    1972 assert(tree != NULL);
    1973 assert(tree->effectiverootdepth >= 0);
    1974 assert(tree->root != NULL);
    1975 assert(var != NULL);
    1976 assert(node->active || (infercons == NULL && inferprop == NULL));
    1977 assert((SCIP_NODETYPE)node->nodetype == SCIP_NODETYPE_PROBINGNODE || !probingchange);
    1978 assert((boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, oldlb))
    1979 || (boundtype == SCIP_BOUNDTYPE_LOWER && newbound > oldlb && newbound * oldlb <= 0.0)
    1980 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, oldub))
    1981 || (boundtype == SCIP_BOUNDTYPE_UPPER && newbound < oldub && newbound * oldub <= 0.0));
    1982
    1983 SCIPsetDebugMsg(set, "adding boundchange at node %" SCIP_LONGINT_FORMAT " at depth %u to variable <%s>: old bounds=[%g,%g], new %s bound: %g (infer%s=<%s>, inferinfo=%d)\n",
    1984 node->number, node->depth, SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
    1985 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", newbound, infercons != NULL ? "cons" : "prop",
    1986 infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo);
    1987
    1988 /* remember variable as inference variable, and get corresponding active variable, bound and bound type */
    1989 infervar = var;
    1990 inferboundtype = boundtype;
    1991
    1992 SCIP_CALL( SCIPvarGetProbvarBound(&var, &newbound, &boundtype) );
    1993
    1995 {
    1996 SCIPerrorMessage("cannot change bounds of multi-aggregated variable <%s>\n", SCIPvarGetName(var));
    1997 SCIPABORT();
    1998 return SCIP_INVALIDDATA; /*lint !e527*/
    1999 }
    2001
    2002 /* the variable may have changed, make sure we have the correct bounds */
    2003 if( useglobal )
    2004 {
    2005 oldlb = SCIPvarGetLbGlobal(var);
    2006 oldub = SCIPvarGetUbGlobal(var);
    2007 }
    2008 else
    2009 {
    2010 oldlb = SCIPvarGetLbLocal(var);
    2011 oldub = SCIPvarGetUbLocal(var);
    2012 }
    2013 assert(SCIPsetIsLE(set, oldlb, oldub));
    2014
    2015 if( boundtype == SCIP_BOUNDTYPE_LOWER )
    2016 {
    2017 /* adjust lower bound w.r.t. to integrality */
    2018 SCIPvarAdjustLb(var, set, &newbound);
    2019 assert(SCIPsetIsFeasLE(set, newbound, oldub));
    2020 oldbound = oldlb;
    2021 newbound = MIN(newbound, oldub);
    2022
    2023 if ( set->stage == SCIP_STAGE_SOLVING && SCIPsetIsInfinity(set, newbound) )
    2024 {
    2025 SCIPerrorMessage("cannot change lower bound of variable <%s> to infinity.\n", SCIPvarGetName(var));
    2026 SCIPABORT();
    2027 return SCIP_INVALIDDATA; /*lint !e527*/
    2028 }
    2029 }
    2030 else
    2031 {
    2032 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
    2033
    2034 /* adjust the new upper bound */
    2035 SCIPvarAdjustUb(var, set, &newbound);
    2036 assert(SCIPsetIsFeasGE(set, newbound, oldlb));
    2037 oldbound = oldub;
    2038 newbound = MAX(newbound, oldlb);
    2039
    2040 if ( set->stage == SCIP_STAGE_SOLVING && SCIPsetIsInfinity(set, -newbound) )
    2041 {
    2042 SCIPerrorMessage("cannot change upper bound of variable <%s> to minus infinity.\n", SCIPvarGetName(var));
    2043 SCIPABORT();
    2044 return SCIP_INVALIDDATA; /*lint !e527*/
    2045 }
    2046 }
    2047
    2048 /* after switching to the active variable, the bounds might become redundant
    2049 * if this happens, ignore the bound change
    2050 */
    2051 if( (boundtype == SCIP_BOUNDTYPE_LOWER && !SCIPsetIsGT(set, newbound, oldlb))
    2052 || (boundtype == SCIP_BOUNDTYPE_UPPER && !SCIPsetIsLT(set, newbound, oldub)) )
    2053 return SCIP_OKAY;
    2054
    2055 SCIPsetDebugMsg(set, " -> transformed to active variable <%s>: old bounds=[%g,%g], new %s bound: %g, obj: %g\n",
    2056 SCIPvarGetName(var), oldlb, oldub, boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", newbound,
    2057 SCIPvarGetObj(var));
    2058
    2059 /* if the bound change takes place at an active node but is conflicting with the current local bounds,
    2060 * we cannot apply it immediately because this would introduce inconsistencies to the bound change data structures
    2061 * in the tree and to the bound change information data in the variable;
    2062 * instead we have to remember the bound change as a pending bound change and mark the affected nodes on the active
    2063 * path to be infeasible
    2064 */
    2065 if( node->active )
    2066 {
    2067 int conflictingdepth;
    2068
    2069 conflictingdepth = SCIPvarGetConflictingBdchgDepth(var, set, boundtype, newbound);
    2070
    2071 if( conflictingdepth >= 0 )
    2072 {
    2073 /* 0 would mean the bound change conflicts with a global bound */
    2074 assert(conflictingdepth > 0);
    2075 assert(conflictingdepth < tree->pathlen);
    2076
    2077 SCIPsetDebugMsg(set, " -> bound change <%s> %s %g violates current local bounds [%g,%g] since depth %d: remember for later application\n",
    2078 SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound,
    2079 SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), conflictingdepth);
    2080
    2081 /* remember the pending bound change */
    2082 SCIP_CALL( treeAddPendingBdchg(tree, set, node, var, newbound, NULL, boundtype, infercons, inferprop, inferinfo,
    2083 probingchange) );
    2084
    2085 /* mark the node with the conflicting bound change to be cut off */
    2086 SCIP_CALL( SCIPnodeCutoff(tree->path[conflictingdepth], set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
    2087
    2088 return SCIP_OKAY;
    2089 }
    2090 }
    2091
    2092 SCIPstatIncrement(stat, set, nboundchgs);
    2093
    2094 /* if we are in probing mode we have to additionally count the bound changes for the probing statistic */
    2095 if( tree->probingroot != NULL )
    2096 SCIPstatIncrement(stat, set, nprobboundchgs);
    2097
    2098 /* if the node is the root node: change local and global bound immediately */
    2099 if( SCIPnodeGetDepth(node) <= tree->effectiverootdepth )
    2100 {
    2101 assert(node->active || tree->focusnode == NULL );
    2103 assert(!probingchange);
    2104
    2105 SCIPsetDebugMsg(set, " -> bound change in root node: perform global bound change\n");
    2106 SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
    2107
    2108 if( set->stage == SCIP_STAGE_SOLVING )
    2109 {
    2110 /* the root should be repropagated due to the bound change */
    2111 SCIPnodePropagateAgain(tree->root, set, stat, tree);
    2112 SCIPsetDebugMsg(set, "marked root node to be repropagated due to global bound change <%s>:[%g,%g] -> [%g,%g] found in depth %u\n",
    2113 SCIPvarGetName(var), oldlb, oldub, boundtype == SCIP_BOUNDTYPE_LOWER ? newbound : oldlb,
    2114 boundtype == SCIP_BOUNDTYPE_LOWER ? oldub : newbound, node->depth);
    2115 }
    2116
    2117 return SCIP_OKAY;
    2118 }
    2119
    2120 /* if the node is a child, or the bound is a temporary probing bound
    2121 * - the bound change is a branching decision
    2122 * - the child's lower bound can be updated due to the changed pseudo solution
    2123 * otherwise:
    2124 * - the bound change is an inference
    2125 */
    2126 if( SCIPnodeGetType(node) == SCIP_NODETYPE_CHILD || probingchange )
    2127 {
    2128 SCIP_Real newpseudoobjval;
    2129 SCIP_Real lpsolval;
    2130
    2131 assert(!node->active || SCIPnodeGetType(node) == SCIP_NODETYPE_PROBINGNODE);
    2132
    2133 /* compute the child's new lower bound */
    2134 newpseudoobjval = SCIPlpGetModifiedPseudoObjval(lp, set, transprob, var, oldbound, newbound, boundtype);
    2135
    2136 if( SCIPsetIsInfinity(set, newpseudoobjval) )
    2137 {
    2138 SCIPmessageFPrintWarning(set->scip->messagehdlr, "Cutting off node with pseudo objective bound %g larger than numerics/infinity (%g)\n", newpseudoobjval, SCIPsetInfinity(set));
    2139 SCIP_CALL( SCIPnodeCutoff(node, set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
    2140
    2141 return SCIP_OKAY;
    2142 }
    2143
    2144 /* get the solution value of variable in last solved LP on the active path:
    2145 * - if the LP was solved at the current node, the LP values of the columns are valid
    2146 * - if the last solved LP was the one in the current lpstatefork, the LP value in the columns are still valid
    2147 * - otherwise, the LP values are invalid
    2148 */
    2149 if( SCIPtreeHasCurrentNodeLP(tree)
    2151 {
    2152 lpsolval = SCIPvarGetLPSol(var);
    2153 }
    2154 else
    2155 lpsolval = SCIP_INVALID;
    2156
    2157 /* remember the bound change as branching decision (infervar/infercons/inferprop are not important: use NULL) */
    2158 SCIP_CALL( SCIPdomchgAddBoundchg(&node->domchg, blkmem, set, var, newbound, NULL, boundtype, SCIP_BOUNDCHGTYPE_BRANCHING,
    2159 lpsolval, NULL, NULL, NULL, 0, inferboundtype) );
    2160
    2163
    2164 /* print bound to certificate */
    2165 if( set->exact_enable && SCIPisCertified(set->scip)
    2166 && !SCIPtreeProbing(tree) && newpseudoobjval > SCIPnodeGetLowerbound(node) )
    2167 {
    2168 /* we change the exact local bound here temporarily such that the correct pseudo solution gets printed to the
    2169 certificate */
    2172 SCIPrationalSetReal(bound, newbound);
    2174 node, set, transprob, inferboundtype == SCIP_BOUNDTYPE_LOWER,
    2176 newpseudoobjval) );
    2177 SCIPrationalSetReal(bound, oldbound);
    2178 }
    2179
    2180 /* update the child's lower bound */
    2181 SCIP_CALL( SCIPnodeUpdateLowerbound(node, stat, set, eventfilter, tree, transprob, origprob, newpseudoobjval, NULL) );
    2182 }
    2183 else
    2184 {
    2185 /* check the inferred bound change on the debugging solution */
    2186 SCIP_CALL( SCIPdebugCheckInference(blkmem, set, node, var, newbound, boundtype) ); /*lint !e506 !e774*/
    2187
    2188 /* remember the bound change as inference (lpsolval is not important: use 0.0) */
    2189 SCIP_CALL( SCIPdomchgAddBoundchg(&node->domchg, blkmem, set, var, newbound, NULL, boundtype,
    2191 0.0, infervar, infercons, inferprop, inferinfo, inferboundtype) );
    2192
    2195 }
    2196
    2197 assert(node->domchg != NULL);
    2198 assert(node->domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
    2199 assert(node->domchg->domchgdyn.boundchgs != NULL);
    2200 assert(node->domchg->domchgdyn.nboundchgs > 0);
    2201 assert(node->domchg->domchgdyn.boundchgs[node->domchg->domchgdyn.nboundchgs-1].var == var);
    2202 assert(node->domchg->domchgdyn.boundchgs[node->domchg->domchgdyn.nboundchgs-1].newbound == newbound); /*lint !e777*/
    2203
    2204 /* if node is active, apply the bound change immediately */
    2205 if( node->active )
    2206 {
    2207 SCIP_Bool cutoff;
    2208
    2209 /**@todo if the node is active, it currently must either be the effective root (see above) or the current node;
    2210 * if a bound change to an intermediate active node should be added, we must make sure, the bound change
    2211 * information array of the variable stays sorted (new info must be sorted in instead of putting it to
    2212 * the end of the array), and we should identify now redundant bound changes that are applied at a
    2213 * later node on the active path
    2214 */
    2215 assert(SCIPtreeGetCurrentNode(tree) == node);
    2217 blkmem, set, stat, lp, branchcand, eventqueue, (int) node->depth, node->domchg->domchgdyn.nboundchgs-1, &cutoff) );
    2218 assert(node->domchg->domchgdyn.boundchgs[node->domchg->domchgdyn.nboundchgs-1].var == var);
    2219 assert(!cutoff);
    2220 }
    2221
    2222 return SCIP_OKAY;
    2223}
    2224
    2225/** adds exact bound change with inference information to focus node, child of focus node, or probing node;
    2226 * if possible, adjusts bound to integral value;
    2227 * at most one of infercons and inferprop may be non-NULL
    2228 */
    2230 SCIP_NODE* node, /**< node to add bound change to */
    2231 BMS_BLKMEM* blkmem, /**< block memory */
    2232 SCIP_SET* set, /**< global SCIP settings */
    2233 SCIP_STAT* stat, /**< problem statistics */
    2234 SCIP_PROB* transprob, /**< transformed problem after presolve */
    2235 SCIP_PROB* origprob, /**< original problem */
    2236 SCIP_TREE* tree, /**< branch and bound tree */
    2237 SCIP_REOPT* reopt, /**< reoptimization data structure */
    2238 SCIP_LPEXACT* lpexact, /**< current LP data */
    2239 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    2240 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    2241 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    2242 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    2243 SCIP_VAR* var, /**< variable to change the bounds for */
    2244 SCIP_RATIONAL* newbound, /**< new value for bound */
    2245 SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
    2246 SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
    2247 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
    2248 int inferinfo, /**< user information for inference to help resolving the conflict */
    2249 SCIP_Bool probingchange /**< is the bound change a temporary setting due to probing? */
    2250 )
    2251{
    2252 SCIP_VAR* infervar;
    2253 SCIP_BOUNDTYPE inferboundtype;
    2254 SCIP_RATIONAL* oldlb;
    2255 SCIP_RATIONAL* oldub;
    2256 SCIP_RATIONAL* oldbound;
    2257 SCIP_Real newboundreal;
    2258 SCIP_Real oldboundreal;
    2259 SCIP_Bool useglobal;
    2260
    2261 useglobal = (int) node->depth <= tree->effectiverootdepth;
    2262
    2263 if( useglobal )
    2264 {
    2265 oldlb = SCIPvarGetLbGlobalExact(var);
    2266 oldub = SCIPvarGetUbGlobalExact(var);
    2267 }
    2268 else
    2269 {
    2270 oldlb = SCIPvarGetLbLocalExact(var);
    2271 oldub = SCIPvarGetUbLocalExact(var);
    2272 }
    2273 if( set->stage > SCIP_STAGE_PRESOLVING && useglobal )
    2274 {
    2276 boundtype, newbound, SCIPcertificateGetCurrentIndex(stat->certificate) - 1) );
    2277 }
    2278
    2279 assert(node != NULL);
    2284 || node->depth == 0);
    2285 assert(set != NULL);
    2286 assert(tree != NULL);
    2287 assert(tree->effectiverootdepth >= 0);
    2288 assert(tree->root != NULL);
    2289 assert(var != NULL);
    2290 assert(node->active || (infercons == NULL && inferprop == NULL));
    2291 assert((SCIP_NODETYPE)node->nodetype == SCIP_NODETYPE_PROBINGNODE || !probingchange);
    2292 assert((boundtype == SCIP_BOUNDTYPE_LOWER && SCIPrationalIsGT(newbound, oldlb))
    2293 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPrationalIsLT(newbound, oldub)));
    2294
    2295 SCIPrationalDebugMessage("adding boundchange at node %llu at depth %u to variable <%s>: old bounds=[%q,%q], new %s bound: %q (infer%s=<%s>, inferinfo=%d)\n",
    2297 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", newbound, infercons != NULL ? "cons" : "prop",
    2298 infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo);
    2299
    2300 /* remember variable as inference variable, and get corresponding active variable, bound and bound type */
    2301 infervar = var;
    2302 inferboundtype = boundtype;
    2303
    2304 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &oldbound) );
    2305
    2306 SCIP_CALL( SCIPvarGetProbvarBoundExact(&var, newbound, &boundtype) );
    2308
    2310 {
    2311 SCIPerrorMessage("cannot change bounds of multi-aggregated variable <%s>\n", SCIPvarGetName(var));
    2312 SCIPABORT();
    2313 return SCIP_INVALIDDATA; /*lint !e527*/
    2314 }
    2316
    2317 /* the variable may have changed, make sure we have the correct bounds */
    2318 if( useglobal )
    2319 {
    2320 oldlb = SCIPvarGetLbGlobalExact(var);
    2321 oldub = SCIPvarGetUbGlobalExact(var);
    2322 }
    2323 else
    2324 {
    2325 oldlb = SCIPvarGetLbLocalExact(var);
    2326 oldub = SCIPvarGetUbLocalExact(var);
    2327 }
    2328 assert(SCIPrationalIsLE(oldlb, oldub));
    2329
    2330 if( boundtype == SCIP_BOUNDTYPE_LOWER )
    2331 {
    2332 /* adjust lower bound w.r.t. to integrality */
    2333 SCIPvarAdjustLbExact(var, set, newbound);
    2334 assert(SCIPrationalIsLE(newbound, oldub));
    2335 SCIPrationalSetRational(oldbound, oldlb);
    2336 SCIPrationalMin(newbound, newbound, oldub);
    2337 oldboundreal = SCIPrationalRoundReal(oldbound, SCIP_R_ROUND_UPWARDS);
    2338
    2339 if ( set->stage == SCIP_STAGE_SOLVING && SCIPrationalIsInfinity(newbound) )
    2340 {
    2341 SCIPerrorMessage("cannot change lower bound of variable <%s> to infinity.\n", SCIPvarGetName(var));
    2342 SCIPABORT();
    2343 return SCIP_INVALIDDATA; /*lint !e527*/
    2344 }
    2345 }
    2346 else
    2347 {
    2348 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
    2349
    2350 /* adjust the new upper bound */
    2351 SCIPvarAdjustUbExact(var, set, newbound);
    2352 assert(SCIPrationalIsGE(newbound, oldlb));
    2353 SCIPrationalSetRational(oldbound, oldub);
    2354 SCIPrationalMax(newbound, newbound, oldlb);
    2355 oldboundreal = SCIPrationalRoundReal(oldbound, SCIP_R_ROUND_DOWNWARDS);
    2356
    2357 if ( set->stage == SCIP_STAGE_SOLVING && SCIPrationalIsNegInfinity(newbound) )
    2358 {
    2359 SCIPerrorMessage("cannot change upper bound of variable <%s> to minus infinity.\n", SCIPvarGetName(var));
    2360 SCIPABORT();
    2361 return SCIP_INVALIDDATA; /*lint !e527*/
    2362 }
    2363 }
    2364
    2365 /* after switching to the active variable, the bounds might become redundant
    2366 * if this happens, ignore the bound change
    2367 */
    2368 if( (boundtype == SCIP_BOUNDTYPE_LOWER && !SCIPrationalIsGT(newbound, oldlb))
    2369 || (boundtype == SCIP_BOUNDTYPE_UPPER && !SCIPrationalIsLT(newbound, oldub)) )
    2370 {
    2371 SCIPrationalFreeBuffer(set->buffer, &oldbound);
    2372 return SCIP_OKAY;
    2373 }
    2374
    2375 SCIPrationalDebugMessage(" -> transformed to active variable <%s>: old bounds=[%q,%q], new %s bound: %q, obj: %q\n",
    2376 SCIPvarGetName(var), oldlb, oldub, boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", newbound,
    2377 SCIPvarGetObjExact(var));
    2378
    2379 /* if the bound change takes place at an active node but is conflicting with the current local bounds,
    2380 * we cannot apply it immediately because this would introduce inconsistencies to the bound change data structures
    2381 * in the tree and to the bound change information data in the variable;
    2382 * instead we have to remember the bound change as a pending bound change and mark the affected nodes on the active
    2383 * path to be infeasible
    2384 */
    2385 if( node->active )
    2386 {
    2387 int conflictingdepth;
    2388
    2389 conflictingdepth = SCIPvarGetConflictingBdchgDepth(var, set, boundtype, newboundreal);
    2390
    2391 if( conflictingdepth >= 0 )
    2392 {
    2393 /* 0 would mean the bound change conflicts with a global bound */
    2394 assert(conflictingdepth > 0);
    2395 assert(conflictingdepth < tree->pathlen);
    2396
    2397 SCIPrationalDebugMessage(" -> bound change <%s> %s %g violates current local bounds [%q,%q] since depth %d: remember for later application\n",
    2398 SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound,
    2399 SCIPvarGetLbLocalExact(var), SCIPvarGetUbLocalExact(var), conflictingdepth);
    2400
    2401 /* remember the pending bound change */
    2402 SCIP_CALL( treeAddPendingBdchg(tree, set, node, var, newboundreal, newbound, boundtype, infercons, inferprop, inferinfo,
    2403 probingchange) );
    2404
    2405 /* mark the node with the conflicting bound change to be cut off */
    2406 SCIP_CALL( SCIPnodeCutoff(tree->path[conflictingdepth], set, stat, eventfilter, tree, transprob, origprob, reopt, lpexact->fplp, blkmem) );
    2407
    2408 SCIPrationalFreeBuffer(set->buffer, &oldbound);
    2409 return SCIP_OKAY;
    2410 }
    2411 }
    2412
    2413 SCIPstatIncrement(stat, set, nboundchgs);
    2414
    2415 /* if we are in probing mode we have to additionally count the bound changes for the probing statistic */
    2416 if( tree->probingroot != NULL )
    2417 SCIPstatIncrement(stat, set, nprobboundchgs);
    2418
    2419 /* if the node is the root node: change local and global bound immediately */
    2420 if( SCIPnodeGetDepth(node) <= tree->effectiverootdepth )
    2421 {
    2422 assert(node->active || tree->focusnode == NULL );
    2424 assert(!probingchange);
    2425
    2426 SCIPsetDebugMsg(set, " -> bound change in root node: perform global bound change\n");
    2427 SCIP_CALL( SCIPvarChgBdGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound, boundtype) );
    2428
    2429 if( set->stage == SCIP_STAGE_SOLVING )
    2430 {
    2431 /* the root should be repropagated due to the bound change */
    2432 SCIPnodePropagateAgain(tree->root, set, stat, tree);
    2433 SCIPrationalDebugMessage("marked root node to be repropagated due to global bound change <%s>:[%q,%q] -> [%q,%q] found in depth %u\n",
    2434 SCIPvarGetName(var), oldlb, oldub, boundtype == SCIP_BOUNDTYPE_LOWER ? newbound : oldlb,
    2435 boundtype == SCIP_BOUNDTYPE_LOWER ? oldub : newbound, node->depth);
    2436 }
    2437
    2438 SCIPrationalFreeBuffer(set->buffer, &oldbound);
    2439 return SCIP_OKAY;
    2440 }
    2441
    2442 /* if the node is a child, or the bound is a temporary probing bound
    2443 * - the bound change is a branching decision
    2444 * - the child's lower bound can be updated due to the changed pseudo solution
    2445 * otherwise:
    2446 * - the bound change is an inference
    2447 */
    2448 if( SCIPnodeGetType(node) == SCIP_NODETYPE_CHILD || probingchange )
    2449 {
    2450 SCIP_Real newpseudoobjval;
    2451 SCIP_Real lpsolval;
    2452
    2453 assert(!node->active || SCIPnodeGetType(node) == SCIP_NODETYPE_PROBINGNODE);
    2454
    2455 /* get the solution value of variable in last solved LP on the active path:
    2456 * - if the LP was solved at the current node, the LP values of the columns are valid
    2457 * - if the last solved LP was the one in the current lpstatefork, the LP value in the columns are still valid
    2458 * - otherwise, the LP values are invalid
    2459 */
    2460 if( lpexact->fplp->hasprovedbound && (SCIPtreeHasCurrentNodeLP(tree)
    2462 {
    2463 lpsolval = SCIPvarGetLPSol(var);
    2464 }
    2465 else
    2466 lpsolval = SCIP_INVALID;
    2467
    2468 /* remember the bound change as branching decision (infervar/infercons/inferprop are not important: use NULL) */
    2469 SCIP_CALL( SCIPdomchgAddBoundchg(&node->domchg, blkmem, set, var, newboundreal, SCIPrationalIsIntegral(newbound) ? NULL : newbound, boundtype, SCIP_BOUNDCHGTYPE_BRANCHING,
    2470 lpsolval, NULL, NULL, NULL, 0, inferboundtype) );
    2471
    2474
    2475 /* update the child's lower bound (pseudoobjval is safe, so can use the fp version) */
    2476 newpseudoobjval = SCIPlpGetModifiedPseudoObjval(lpexact->fplp, set, transprob, var, oldboundreal, newboundreal, boundtype);
    2477
    2478 /* print bound to the certificate */
    2479 if( SCIPisCertified(set->scip) && newpseudoobjval > SCIPnodeGetLowerbound(node) )
    2480 {
    2481 /* we change the exact local bound here temporarily such that the correct pseudo solution gets printed to the
    2482 certificate */
    2485 SCIPrationalSetRational(bound, newbound);
    2486 SCIP_CALL( SCIPcertificatePrintDualboundPseudo(stat->certificate, lpexact, node, set, transprob,
    2487 inferboundtype == SCIP_BOUNDTYPE_LOWER, SCIPvarGetCertificateIndex(var),
    2488 SCIPcertificateGetCurrentIndex(stat->certificate) -1, newpseudoobjval) );
    2489 SCIPrationalSetRational(bound, oldbound);
    2490 }
    2491
    2492 SCIP_CALL( SCIPnodeUpdateLowerbound(node, stat, set, eventfilter, tree, transprob, origprob, newpseudoobjval, NULL) );
    2493 }
    2494 else
    2495 {
    2496 /* check the infered bound change on the debugging solution */
    2497
    2498 /* remember the bound change as inference (lpsolval is not important: use 0.0) */
    2499 SCIP_CALL( SCIPdomchgAddBoundchg(&node->domchg, blkmem, set, var, newboundreal, SCIPrationalIsIntegral(newbound) ? NULL : newbound, boundtype,
    2501 0.0, infervar, infercons, inferprop, inferinfo, inferboundtype) );
    2502
    2505 }
    2506
    2507 assert(node->domchg != NULL);
    2508 assert(node->domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
    2509 assert(node->domchg->domchgdyn.boundchgs != NULL);
    2510 assert(node->domchg->domchgdyn.nboundchgs > 0);
    2511 assert(node->domchg->domchgdyn.boundchgs[node->domchg->domchgdyn.nboundchgs-1].var == var);
    2512 assert(node->domchg->domchgdyn.boundchgs[node->domchg->domchgdyn.nboundchgs-1].newbound == newboundreal); /*lint !e777*/
    2513
    2514 /* if node is active, apply the bound change immediately */
    2515 if( node->active )
    2516 {
    2517 SCIP_Bool cutoff;
    2518
    2519 /**@todo if the node is active, it currently must either be the effective root (see above) or the current node;
    2520 * if a bound change to an intermediate active node should be added, we must make sure, the bound change
    2521 * information array of the variable stays sorted (new info must be sorted in instead of putting it to
    2522 * the end of the array), and we should identify now redundant bound changes that are applied at a
    2523 * later node on the active path
    2524 */
    2525 assert(SCIPtreeGetCurrentNode(tree) == node);
    2527 blkmem, set, stat, lpexact->fplp, branchcand, eventqueue, (int) node->depth, node->domchg->domchgdyn.nboundchgs-1, &cutoff) );
    2528 assert(node->domchg->domchgdyn.boundchgs[node->domchg->domchgdyn.nboundchgs-1].var == var);
    2529 assert(!cutoff);
    2530 }
    2531
    2532 SCIPrationalFreeBuffer(set->buffer, &oldbound);
    2533 return SCIP_OKAY;
    2534}
    2535
    2536/** adds bound change to focus node, or child of focus node, or probing node;
    2537 * if possible, adjusts bound to integral value
    2538 */
    2540 SCIP_NODE* node, /**< node to add bound change to */
    2541 BMS_BLKMEM* blkmem, /**< block memory */
    2542 SCIP_SET* set, /**< global SCIP settings */
    2543 SCIP_STAT* stat, /**< problem statistics */
    2544 SCIP_PROB* transprob, /**< transformed problem after presolve */
    2545 SCIP_PROB* origprob, /**< original problem */
    2546 SCIP_TREE* tree, /**< branch and bound tree */
    2547 SCIP_REOPT* reopt, /**< reoptimization data structure */
    2548 SCIP_LP* lp, /**< current LP data */
    2549 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    2550 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    2551 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    2552 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    2553 SCIP_VAR* var, /**< variable to change the bounds for */
    2554 SCIP_Real newbound, /**< new value for bound */
    2555 SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
    2556 SCIP_Bool probingchange /**< is the bound change a temporary setting due to probing? */
    2557 )
    2558{
    2559 SCIP_CALL( SCIPnodeAddBoundinfer(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    2560 eventfilter, cliquetable, var, newbound, boundtype, NULL, NULL, 0, probingchange) );
    2561
    2562 return SCIP_OKAY;
    2563}
    2564
    2565/** adds exact bound change to focus node, or child of focus node, or probing node;
    2566 * if possible, adjusts bound to integral value
    2567 */
    2569 SCIP_NODE* node, /**< node to add bound change to */
    2570 BMS_BLKMEM* blkmem, /**< block memory */
    2571 SCIP_SET* set, /**< global SCIP settings */
    2572 SCIP_STAT* stat, /**< problem statistics */
    2573 SCIP_PROB* transprob, /**< transformed problem after presolve */
    2574 SCIP_PROB* origprob, /**< original problem */
    2575 SCIP_TREE* tree, /**< branch and bound tree */
    2576 SCIP_REOPT* reopt, /**< reoptimization data structure */
    2577 SCIP_LPEXACT* lpexact, /**< current LP data */
    2578 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    2579 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    2580 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    2581 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    2582 SCIP_VAR* var, /**< variable to change the bounds for */
    2583 SCIP_RATIONAL* newbound, /**< new value for bound */
    2584 SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
    2585 SCIP_Bool probingchange /**< is the bound change a temporary setting due to probing? */
    2586 )
    2587{
    2588 SCIP_CALL( SCIPnodeAddBoundinferExact(node, blkmem, set, stat, transprob, origprob, tree, reopt, lpexact, branchcand,
    2589 eventqueue, eventfilter, cliquetable, var, newbound, boundtype, NULL, NULL, 0, probingchange) );
    2590
    2591 return SCIP_OKAY;
    2592}
    2593
    2594/** adds hole with inference information to focus node, child of focus node, or probing node;
    2595 * if possible, adjusts bound to integral value;
    2596 * at most one of infercons and inferprop may be non-NULL
    2597 */
    2599 SCIP_NODE* node, /**< node to add bound change to */
    2600 BMS_BLKMEM* blkmem, /**< block memory */
    2601 SCIP_SET* set, /**< global SCIP settings */
    2602 SCIP_STAT* stat, /**< problem statistics */
    2603 SCIP_TREE* tree, /**< branch and bound tree */
    2604 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    2605 SCIP_VAR* var, /**< variable to change the bounds for */
    2606 SCIP_Real left, /**< left bound of open interval defining the hole (left,right) */
    2607 SCIP_Real right, /**< right bound of open interval defining the hole (left,right) */
    2608 SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
    2609 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
    2610 int inferinfo, /**< user information for inference to help resolving the conflict */
    2611 SCIP_Bool probingchange, /**< is the bound change a temporary setting due to probing? */
    2612 SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
    2613 )
    2614{
    2615 assert(node != NULL);
    2620 || node->depth == 0);
    2621 assert(blkmem != NULL);
    2622 assert(set != NULL);
    2623 assert(tree != NULL);
    2624 assert(tree->effectiverootdepth >= 0);
    2625 assert(tree->root != NULL);
    2626 assert(var != NULL);
    2627 assert(node->active || (infercons == NULL && inferprop == NULL));
    2628 assert((SCIP_NODETYPE)node->nodetype == SCIP_NODETYPE_PROBINGNODE || !probingchange);
    2629
    2630 /* the interval should not be empty */
    2631 assert(SCIPsetIsLT(set, left, right));
    2632
    2633#ifndef NDEBUG
    2634 {
    2635 SCIP_Real adjustedleft;
    2636 SCIP_Real adjustedright;
    2637
    2638 adjustedleft = left;
    2639 adjustedright = right;
    2640
    2641 SCIPvarAdjustUb(var, set, &adjustedleft);
    2642 SCIPvarAdjustLb(var, set, &adjustedright);
    2643
    2644 assert(SCIPsetIsEQ(set, left, adjustedleft));
    2645 assert(SCIPsetIsEQ(set, right, adjustedright));
    2646 }
    2647#endif
    2648
    2649 /* the hole should lay within the lower and upper bounds */
    2650 assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
    2651 assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
    2652
    2653 SCIPsetDebugMsg(set, "adding hole (%g,%g) at node at depth %u to variable <%s>: bounds=[%g,%g], (infer%s=<%s>, inferinfo=%d)\n",
    2654 left, right, node->depth, SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), infercons != NULL ? "cons" : "prop",
    2655 infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo);
    2656
    2657 SCIP_CALL( SCIPvarGetProbvarHole(&var, &left, &right) );
    2658
    2660 {
    2661 SCIPerrorMessage("cannot change bounds of multi-aggregated variable <%s>\n", SCIPvarGetName(var));
    2662 SCIPABORT();
    2663 return SCIP_INVALIDDATA; /*lint !e527*/
    2664 }
    2666
    2667 SCIPsetDebugMsg(set, " -> transformed to active variable <%s>: hole (%g,%g), obj: %g\n", SCIPvarGetName(var), left, right, SCIPvarGetObj(var));
    2668
    2669 stat->nholechgs++;
    2670
    2671 /* if we are in probing mode we have to additionally count the bound changes for the probing statistic */
    2672 if( tree->probingroot != NULL )
    2673 stat->nprobholechgs++;
    2674
    2675 /* if the node is the root node: change local and global bound immediately */
    2676 if( SCIPnodeGetDepth(node) <= tree->effectiverootdepth )
    2677 {
    2678 assert(node->active || tree->focusnode == NULL );
    2680 assert(!probingchange);
    2681
    2682 SCIPsetDebugMsg(set, " -> hole added in root node: perform global domain change\n");
    2683 SCIP_CALL( SCIPvarAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
    2684
    2685 if( set->stage == SCIP_STAGE_SOLVING && (*added) )
    2686 {
    2687 /* the root should be repropagated due to the bound change */
    2688 SCIPnodePropagateAgain(tree->root, set, stat, tree);
    2689 SCIPsetDebugMsg(set, "marked root node to be repropagated due to global added hole <%s>: (%g,%g) found in depth %u\n",
    2690 SCIPvarGetName(var), left, right, node->depth);
    2691 }
    2692
    2693 return SCIP_OKAY;
    2694 }
    2695
    2696 /**@todo add adding of local domain holes */
    2697
    2698 (*added) = FALSE;
    2699 SCIPerrorMessage("WARNING: currently domain holes can only be handled globally!\n");
    2700
    2701 stat->nholechgs--;
    2702
    2703 /* if we are in probing mode we have to additionally count the bound changes for the probing statistic */
    2704 if( tree->probingroot != NULL )
    2705 stat->nprobholechgs--;
    2706
    2707 return SCIP_OKAY;
    2708}
    2709
    2710/** adds hole change to focus node, or child of focus node */
    2712 SCIP_NODE* node, /**< node to add bound change to */
    2713 BMS_BLKMEM* blkmem, /**< block memory */
    2714 SCIP_SET* set, /**< global SCIP settings */
    2715 SCIP_STAT* stat, /**< problem statistics */
    2716 SCIP_TREE* tree, /**< branch and bound tree */
    2717 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    2718 SCIP_VAR* var, /**< variable to change the bounds for */
    2719 SCIP_Real left, /**< left bound of open interval defining the hole (left,right) */
    2720 SCIP_Real right, /**< right bound of open interval defining the hole (left,right) */
    2721 SCIP_Bool probingchange, /**< is the bound change a temporary setting due to probing? */
    2722 SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
    2723 )
    2724{
    2725 assert(node != NULL);
    2729 assert(blkmem != NULL);
    2730
    2731 SCIPsetDebugMsg(set, "adding hole (%g,%g) at node at depth %u of variable <%s>\n",
    2732 left, right, node->depth, SCIPvarGetName(var));
    2733
    2734 SCIP_CALL( SCIPnodeAddHoleinfer(node, blkmem, set, stat, tree, eventqueue, var, left, right,
    2735 NULL, NULL, 0, probingchange, added) );
    2736
    2737 /**@todo apply hole change on active nodes and issue event */
    2738
    2739 return SCIP_OKAY;
    2740}
    2741
    2742/** applies the pending bound changes */
    2743static
    2745 SCIP_TREE* tree, /**< branch and bound tree */
    2746 SCIP_REOPT* reopt, /**< reoptimization data structure */
    2747 BMS_BLKMEM* blkmem, /**< block memory */
    2748 SCIP_SET* set, /**< global SCIP settings */
    2749 SCIP_STAT* stat, /**< problem statistics */
    2750 SCIP_PROB* transprob, /**< transformed problem after presolve */
    2751 SCIP_PROB* origprob, /**< original problem */
    2752 SCIP_LP* lp, /**< current LP data */
    2753 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    2754 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    2755 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    2756 SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
    2757 )
    2758{
    2759 SCIP_VAR* var;
    2760 int npendingbdchgs;
    2761 int conflictdepth;
    2762 int i;
    2763
    2764 assert(tree != NULL);
    2765
    2766 if( tree->cutoffdepth > tree->effectiverootdepth )
    2767 {
    2768 npendingbdchgs = tree->npendingbdchgs;
    2769 for( i = 0; i < npendingbdchgs; ++i )
    2770 {
    2771 assert(tree->pendingbdchgs[i].node != NULL);
    2772 if( tree->pendingbdchgs[i].node->cutoff )
    2773 continue;
    2774 assert(tree->pendingbdchgs[i].node->depth < tree->cutoffdepth);
    2775 assert(tree->effectiverootdepth < tree->cutoffdepth);
    2776
    2777 var = tree->pendingbdchgs[i].var;
    2778 conflictdepth = SCIPvarGetConflictingBdchgDepth(var, set, tree->pendingbdchgs[i].boundtype,
    2779 tree->pendingbdchgs[i].newbound);
    2780
    2781 /* It can happen, that a pending bound change conflicts with the global bounds, because when it was collected, it
    2782 * just conflicted with the local bounds, but a conflicting global bound change was applied afterwards. In this
    2783 * case, we can cut off the node where the pending bound change should be applied.
    2784 */
    2785 if( conflictdepth == 0 )
    2786 {
    2787 SCIP_CALL( SCIPnodeCutoff(tree->pendingbdchgs[i].node, set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
    2788
    2789 /* break here to clear all pending bound changes below */
    2790 if( tree->effectiverootdepth >= tree->cutoffdepth )
    2791 break;
    2792 else
    2793 continue;
    2794 }
    2795
    2796 assert(conflictdepth == -1);
    2797
    2798 SCIPsetDebugMsg(set, "applying pending bound change <%s>[%g,%g] %s %g\n", SCIPvarGetName(var),
    2800 tree->pendingbdchgs[i].boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
    2801 tree->pendingbdchgs[i].newbound);
    2802
    2803 /* ignore bounds that are now redundant (for example, multiple entries in the pendingbdchgs for the same
    2804 * variable)
    2805 */
    2807 {
    2808 SCIP_Real lb;
    2809
    2810 lb = SCIPvarGetLbLocal(var);
    2811 if( !SCIPsetIsGT(set, tree->pendingbdchgs[i].newbound, lb) )
    2812 continue;
    2813 }
    2814 else
    2815 {
    2816 SCIP_Real ub;
    2817
    2818 assert(tree->pendingbdchgs[i].boundtype == SCIP_BOUNDTYPE_UPPER);
    2819 ub = SCIPvarGetUbLocal(var);
    2820 if( !SCIPsetIsLT(set, tree->pendingbdchgs[i].newbound, ub) )
    2821 continue;
    2822 }
    2823
    2824 SCIP_CALL( SCIPnodeAddBoundinfer(tree->pendingbdchgs[i].node, blkmem, set, stat, transprob, origprob, tree, reopt,
    2825 lp, branchcand, eventqueue, eventfilter, cliquetable, var, tree->pendingbdchgs[i].newbound, tree->pendingbdchgs[i].boundtype,
    2827 tree->pendingbdchgs[i].probingchange) );
    2828 assert(tree->npendingbdchgs == npendingbdchgs); /* this time, the bound change can be applied! */
    2829 }
    2830 }
    2831
    2832 /* clear pending bound changes */
    2833 for( i = 0; i < tree->npendingbdchgs; ++i )
    2834 {
    2835 var = tree->pendingbdchgs[i].var;
    2836 assert(var != NULL);
    2837
    2838 /* release the variable */
    2839 SCIP_CALL( SCIPvarRelease(&var, blkmem, set, eventqueue, lp) );
    2840 }
    2841
    2842 tree->npendingbdchgs = 0;
    2843
    2844 return SCIP_OKAY;
    2845}
    2846
    2847/** if given value is larger than the node's lower bound, sets the node's lower bound to the new value
    2848 *
    2849 * @note must not be used on a leaf because the node priority queue remains untouched
    2850 */
    2852 SCIP_NODE* node, /**< node to update lower bound for */
    2853 SCIP_STAT* stat, /**< problem statistics */
    2854 SCIP_SET* set, /**< global SCIP settings */
    2855 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    2856 SCIP_TREE* tree, /**< branch and bound tree */
    2857 SCIP_PROB* transprob, /**< transformed problem after presolve */
    2858 SCIP_PROB* origprob, /**< original problem */
    2859 SCIP_Real newbound, /**< new lower bound (or SCIP_INVALID to use newboundexact in exact) */
    2860 SCIP_RATIONAL* newboundexact /**< new exact lower bound (or NULL to use newbound) */
    2861 )
    2862{
    2863 assert(stat != NULL);
    2864 assert(set != NULL);
    2865 assert(set->stage < SCIP_STAGE_INITSOLVE
    2868 && (!set->exact_enable || SCIPrationalIsEQ(SCIPtreeGetLowerboundExact(tree, set), stat->lastlowerboundexact))));
    2869 assert(newbound == SCIP_INVALID || !SCIPsetIsInfinity(set, newbound)); /*lint !e777*/
    2870 assert(newboundexact == NULL || !SCIPrationalIsInfinity(newboundexact));
    2871
    2872 if( set->exact_enable )
    2873 {
    2874 SCIP_NODETYPE nodetype;
    2875
    2876 if( newboundexact != NULL )
    2877 {
    2878 assert(newbound == SCIP_INVALID || SCIPrationalIsGEReal(newboundexact, newbound)); /*lint !e777*/
    2879
    2880 if( SCIPrationalIsGE(node->lowerboundexact, newboundexact) )
    2881 return SCIP_OKAY;
    2882
    2883 SCIPrationalSetRational(node->lowerboundexact, newboundexact);
    2884 newbound = SCIPrationalRoundReal(newboundexact, SCIP_R_ROUND_DOWNWARDS);
    2885 }
    2886 else
    2887 {
    2888 assert(newbound != SCIP_INVALID); /*lint !e777*/
    2889
    2890 if( SCIPrationalIsGEReal(node->lowerboundexact, newbound) )
    2891 return SCIP_OKAY;
    2892
    2893 SCIPrationalSetReal(node->lowerboundexact, newbound);
    2894 }
    2895
    2896 nodetype = SCIPnodeGetType(node);
    2897 assert(nodetype != SCIP_NODETYPE_LEAF);
    2898
    2899 /* update exact lower bound statistics during solving */
    2900 if( !stat->inrestart && set->stage >= SCIP_STAGE_INITSOLVE
    2901 && ( nodetype == SCIP_NODETYPE_FOCUSNODE || nodetype == SCIP_NODETYPE_CHILD || nodetype == SCIP_NODETYPE_SIBLING ) )
    2902 {
    2903 SCIP_RATIONAL* lowerboundexact = SCIPtreeGetLowerboundExact(tree, set);
    2904 assert(SCIPrationalIsGEReal(lowerboundexact, SCIPtreeGetLowerbound(tree, set)));
    2905
    2906 /* exact lower bound improved */
    2907 if( SCIPrationalIsLT(stat->lastlowerboundexact, lowerboundexact) )
    2908 {
    2909 SCIP_EVENT event;
    2910
    2911 /* throw improvement event */
    2913 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
    2914
    2915 /* update exact last lower bound */
    2916 SCIPrationalSetRational(stat->lastlowerboundexact, lowerboundexact);
    2917 }
    2918 }
    2919 }
    2920
    2921 assert(newbound != SCIP_INVALID); /*lint !e777*/
    2922
    2923 if( SCIPnodeGetLowerbound(node) < newbound )
    2924 {
    2925 SCIP_NODETYPE nodetype = SCIPnodeGetType(node);
    2926 assert(nodetype != SCIP_NODETYPE_LEAF);
    2927
    2928 node->lowerbound = newbound;
    2929
    2930 if( node->estimate < newbound )
    2931 node->estimate = newbound;
    2932
    2933 if( node->depth == 0 )
    2934 stat->rootlowerbound = newbound;
    2935
    2936 /* update real lower bound statistics during solving */
    2937 if( !stat->inrestart && set->stage >= SCIP_STAGE_INITSOLVE
    2938 && ( nodetype == SCIP_NODETYPE_FOCUSNODE || nodetype == SCIP_NODETYPE_CHILD || nodetype == SCIP_NODETYPE_SIBLING ) )
    2939 {
    2940 SCIP_Real lowerbound = SCIPtreeGetLowerbound(tree, set);
    2941 assert(lowerbound <= newbound);
    2942
    2943 /* lower bound improved */
    2944 if( stat->lastlowerbound < lowerbound )
    2945 {
    2946 /* throw improvement event if not already done exactly */
    2947 if( !set->exact_enable )
    2948 {
    2949 SCIP_EVENT event;
    2950
    2952 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
    2953 }
    2954
    2955 /* update primal-dual integrals */
    2956 if( set->misc_calcintegral )
    2957 {
    2958 SCIPstatUpdatePrimalDualIntegrals(stat, set, transprob, origprob, SCIPsetInfinity(set), lowerbound);
    2959 assert(stat->lastlowerbound == lowerbound); /*lint !e777*/
    2960 }
    2961 else
    2962 stat->lastlowerbound = lowerbound;
    2963 }
    2964
    2965 SCIPvisualLowerbound(stat->visual, set, stat, lowerbound);
    2966 }
    2967 }
    2968
    2969 return SCIP_OKAY;
    2970}
    2971
    2972/** updates lower bound of node using lower bound of LP */
    2974 SCIP_NODE* node, /**< node to set lower bound for */
    2975 SCIP_SET* set, /**< global SCIP settings */
    2976 SCIP_STAT* stat, /**< problem statistics */
    2977 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
    2978 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    2979 SCIP_TREE* tree, /**< branch and bound tree */
    2980 SCIP_PROB* transprob, /**< transformed problem after presolve */
    2981 SCIP_PROB* origprob, /**< original problem */
    2982 SCIP_LP* lp /**< LP data */
    2983 )
    2984{
    2985 SCIP_Real lpobjval;
    2986 SCIP_RATIONAL* lpobjvalexact;
    2987
    2988 assert(set != NULL);
    2989 assert(lp != NULL);
    2990 assert(lp->flushed);
    2991
    2992 /* in case of iteration or time limit, the LP value may not be a valid dual bound */
    2993 /* @todo check for dual feasibility of LP solution and use sub-optimal solution if they are dual feasible */
    2995 return SCIP_OKAY;
    2996
    2997 if( set->exact_enable && !lp->hasprovedbound )
    2998 {
    2999 SCIPerrorMessage("Trying to update lower bound with non-proven value in exact solving mode \n.");
    3000 SCIPABORT();
    3001 }
    3002
    3003 lpobjval = SCIPlpGetObjval(lp, set, transprob);
    3004 lpobjvalexact = NULL;
    3005
    3006 /* possibly set the exact lpobjval */
    3007 if( set->exact_enable && !SCIPtreeProbing(tree) )
    3008 {
    3009 SCIP_LPSOLSTAT lpexactsolstat;
    3010
    3011 assert(lp->lpexact != NULL);
    3012
    3013 lpexactsolstat = SCIPlpExactGetSolstat(lp->lpexact);
    3014
    3015 /* if the exact LP has status objective limit, we still query the objective value and call
    3016 * SCIPnodeUpdateLowerbound() below; this seems necessary for correct certification
    3017 */
    3018 if( lpexactsolstat == SCIP_LPSOLSTAT_OPTIMAL || lpexactsolstat == SCIP_LPSOLSTAT_OBJLIMIT )
    3019 {
    3020 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &lpobjvalexact) );
    3021 SCIPlpExactGetObjval(lp->lpexact, set, lpobjvalexact);
    3022 }
    3023
    3024 if( SCIPisCertified(set->scip) )
    3025 {
    3026 if( lp->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE || lpexactsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
    3027 {
    3029 }
    3030 else if( lpobjval > SCIPnodeGetLowerbound(node)
    3031 || (lpobjvalexact != NULL && SCIPrationalIsGT(lpobjvalexact, SCIPnodeGetLowerboundExact(node))) )
    3032 {
    3034 }
    3035 }
    3036 }
    3037
    3038 /* check for cutoff */
    3040 || (set->exact_enable && (SCIPlpExactGetSolstat(lp->lpexact) == SCIP_LPSOLSTAT_INFEASIBLE)) )
    3041 {
    3042 SCIP_CALL( SCIPnodeCutoff(node, set, stat, eventfilter, tree, transprob, origprob, set->scip->reopt, lp, set->scip->mem->probmem) );
    3043 }
    3044 else if( lpobjvalexact != NULL && SCIPrationalIsInfinity(lpobjvalexact) )
    3045 {
    3046 SCIPmessageFPrintWarning(messagehdlr, "Cutting off node with feasible LP relaxation but exact LP bound %g larger than infinity (%g)\n", SCIPrationalGetReal(lpobjvalexact), SCIPrationalGetInfinity());
    3047 SCIP_CALL( SCIPnodeCutoff(node, set, stat, eventfilter, tree, transprob, origprob, set->scip->reopt, lp, set->scip->mem->probmem) );
    3048 }
    3049 else if( SCIPsetIsInfinity(set, lpobjval) )
    3050 {
    3051 SCIPmessageFPrintWarning(messagehdlr, "Cutting off node with feasible LP relaxation but LP bound %g larger than numerics/infinity (%g)\n", lpobjval, SCIPsetInfinity(set));
    3052 SCIP_CALL( SCIPnodeCutoff(node, set, stat, eventfilter, tree, transprob, origprob, set->scip->reopt, lp, set->scip->mem->probmem) );
    3053 }
    3054 else
    3055 {
    3056 SCIP_CALL( SCIPnodeUpdateLowerbound(node, stat, set, eventfilter, tree, transprob, origprob, lpobjval, lpobjvalexact) );
    3057 }
    3058
    3059 if( lpobjvalexact != NULL )
    3060 SCIPrationalFreeBuffer(set->buffer, &lpobjvalexact);
    3061
    3062 return SCIP_OKAY;
    3063}
    3064
    3065/** change the node selection priority of the given child */
    3067 SCIP_TREE* tree, /**< branch and bound tree */
    3068 SCIP_NODE* child, /**< child to update the node selection priority */
    3069 SCIP_Real priority /**< node selection priority value */
    3070 )
    3071{
    3072 int pos;
    3073
    3074 assert( SCIPnodeGetType(child) == SCIP_NODETYPE_CHILD );
    3075
    3076 pos = child->data.child.arraypos;
    3077 assert( pos >= 0 );
    3078
    3079 tree->childrenprio[pos] = priority;
    3080}
    3081
    3082
    3083/** sets the node's estimated bound to the new value */
    3085 SCIP_NODE* node, /**< node to update lower bound for */
    3086 SCIP_SET* set, /**< global SCIP settings */
    3087 SCIP_Real newestimate /**< new estimated bound for the node */
    3088 )
    3089{
    3090 assert(node != NULL);
    3091 assert(set != NULL);
    3092 assert(SCIPsetIsRelGE(set, newestimate, node->lowerbound));
    3093
    3094 /* due to numerical reasons we need this check, see https://git.zib.de/integer/scip/issues/2866 */
    3095 if( node->lowerbound <= newestimate )
    3096 node->estimate = newestimate;
    3097}
    3098
    3099/** propagates implications of binary fixings at the given node triggered by the implication graph and the clique table */
    3101 SCIP_NODE* node, /**< node to propagate implications on */
    3102 BMS_BLKMEM* blkmem, /**< block memory */
    3103 SCIP_SET* set, /**< global SCIP settings */
    3104 SCIP_STAT* stat, /**< problem statistics */
    3105 SCIP_PROB* transprob, /**< transformed problem after presolve */
    3106 SCIP_PROB* origprob, /**< original problem */
    3107 SCIP_TREE* tree, /**< branch and bound tree */
    3108 SCIP_REOPT* reopt, /**< reoptimization data structure */
    3109 SCIP_LP* lp, /**< current LP data */
    3110 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    3111 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    3112 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    3113 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    3114 SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
    3115 )
    3116{
    3117 int nboundchgs;
    3118 int i;
    3119
    3120 assert(node != NULL);
    3121 assert(SCIPnodeIsActive(node));
    3125 assert(cutoff != NULL);
    3126
    3127 SCIPsetDebugMsg(set, "implication graph propagation of node #%" SCIP_LONGINT_FORMAT " in depth %d\n",
    3128 SCIPnodeGetNumber(node), SCIPnodeGetDepth(node));
    3129
    3130 *cutoff = FALSE;
    3131
    3132 /* propagate all fixings of binary variables performed at this node */
    3133 nboundchgs = SCIPdomchgGetNBoundchgs(node->domchg);
    3134 for( i = 0; i < nboundchgs && !(*cutoff); ++i )
    3135 {
    3136 SCIP_BOUNDCHG* boundchg;
    3137 SCIP_VAR* var;
    3138
    3139 boundchg = SCIPdomchgGetBoundchg(node->domchg, i);
    3140
    3141 /* ignore redundant bound changes */
    3142 if( SCIPboundchgIsRedundant(boundchg) )
    3143 continue;
    3144
    3145 var = SCIPboundchgGetVar(boundchg);
    3146 if( SCIPvarIsBinary(var) )
    3147 {
    3148 SCIP_Bool varfixing;
    3149 int nimpls;
    3150 SCIP_VAR** implvars;
    3151 SCIP_BOUNDTYPE* impltypes;
    3152 SCIP_Real* implbounds;
    3153 SCIP_CLIQUE** cliques;
    3154 int ncliques;
    3155 int j;
    3156
    3157 varfixing = (SCIPboundchgGetBoundtype(boundchg) == SCIP_BOUNDTYPE_LOWER);
    3158 nimpls = SCIPvarGetNImpls(var, varfixing);
    3159 implvars = SCIPvarGetImplVars(var, varfixing);
    3160 impltypes = SCIPvarGetImplTypes(var, varfixing);
    3161 implbounds = SCIPvarGetImplBounds(var, varfixing);
    3162
    3163 /* apply implications */
    3164 for( j = 0; j < nimpls; ++j )
    3165 {
    3166 SCIP_Real lb;
    3167 SCIP_Real ub;
    3168
    3169 /* @note should this be checked here (because SCIPnodeAddBoundinfer fails for multi-aggregated variables)
    3170 * or should SCIPnodeAddBoundinfer() just return for multi-aggregated variables?
    3171 */
    3172 if( SCIPvarGetStatus(implvars[j]) == SCIP_VARSTATUS_MULTAGGR ||
    3174 continue;
    3175
    3176 /* check for infeasibility */
    3177 lb = SCIPvarGetLbLocal(implvars[j]);
    3178 ub = SCIPvarGetUbLocal(implvars[j]);
    3179 if( impltypes[j] == SCIP_BOUNDTYPE_LOWER )
    3180 {
    3181 if( SCIPsetIsFeasGT(set, implbounds[j], ub) )
    3182 {
    3183 *cutoff = TRUE;
    3184 return SCIP_OKAY;
    3185 }
    3186 if( SCIPsetIsFeasLE(set, implbounds[j], lb) )
    3187 continue;
    3188 }
    3189 else
    3190 {
    3191 if( SCIPsetIsFeasLT(set, implbounds[j], lb) )
    3192 {
    3193 *cutoff = TRUE;
    3194 return SCIP_OKAY;
    3195 }
    3196 if( SCIPsetIsFeasGE(set, implbounds[j], ub) )
    3197 continue;
    3198 }
    3199
    3200 /* @note the implication might affect a fixed variable (after resolving (multi-)aggregations);
    3201 * normally, the implication should have been deleted in that case, but this is only possible
    3202 * if the implied variable has the reverse implication stored as a variable bound;
    3203 * due to numerics, the variable bound may not be present and so the implication is not deleted
    3204 */
    3206 continue;
    3207
    3208 /* apply the implication */
    3209 SCIP_CALL( SCIPnodeAddBoundinfer(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
    3210 eventqueue, eventfilter, cliquetable, implvars[j], implbounds[j], impltypes[j], NULL, NULL, 0, FALSE) );
    3211 }
    3212
    3213 /* apply cliques */
    3214 ncliques = SCIPvarGetNCliques(var, varfixing);
    3215 cliques = SCIPvarGetCliques(var, varfixing);
    3216 for( j = 0; j < ncliques; ++j )
    3217 {
    3218 SCIP_VAR** vars;
    3219 SCIP_Bool* values;
    3220 int nvars;
    3221 int k;
    3222
    3223 nvars = SCIPcliqueGetNVars(cliques[j]);
    3224 vars = SCIPcliqueGetVars(cliques[j]);
    3225 values = SCIPcliqueGetValues(cliques[j]);
    3226 for( k = 0; k < nvars; ++k )
    3227 {
    3228 SCIP_Real lb;
    3229 SCIP_Real ub;
    3230
    3231 assert(SCIPvarIsBinary(vars[k]));
    3232
    3233 if( SCIPvarGetStatus(vars[k]) == SCIP_VARSTATUS_MULTAGGR ||
    3235 continue;
    3236
    3237 if( vars[k] == var && values[k] == varfixing )
    3238 continue;
    3239
    3240 /* check for infeasibility */
    3241 lb = SCIPvarGetLbLocal(vars[k]);
    3242 ub = SCIPvarGetUbLocal(vars[k]);
    3243 if( values[k] == FALSE )
    3244 {
    3245 if( ub < 0.5 )
    3246 {
    3247 *cutoff = TRUE;
    3248 return SCIP_OKAY;
    3249 }
    3250 if( lb > 0.5 )
    3251 continue;
    3252 }
    3253 else
    3254 {
    3255 if( lb > 0.5 )
    3256 {
    3257 *cutoff = TRUE;
    3258 return SCIP_OKAY;
    3259 }
    3260 if( ub < 0.5 )
    3261 continue;
    3262 }
    3263
    3265 continue;
    3266
    3267 /* apply the clique implication */
    3268 SCIP_CALL( SCIPnodeAddBoundinfer(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
    3269 eventqueue, eventfilter, cliquetable, vars[k], (SCIP_Real)(!values[k]), values[k] ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER,
    3270 NULL, NULL, 0, FALSE) );
    3271 }
    3272 }
    3273 }
    3274 }
    3275
    3276 return SCIP_OKAY;
    3277}
    3278
    3279
    3280
    3281
    3282/*
    3283 * Path Switching
    3284 */
    3285
    3286/** updates the LP sizes of the active path starting at the given depth */
    3287static
    3289 SCIP_TREE* tree, /**< branch and bound tree */
    3290 int startdepth /**< depth to start counting */
    3291 )
    3292{
    3293 SCIP_NODE* node;
    3294 int ncols;
    3295 int nrows;
    3296 int i;
    3297
    3298 assert(tree != NULL);
    3299 assert(startdepth >= 0);
    3300 assert(startdepth <= tree->pathlen);
    3301
    3302 if( startdepth == 0 )
    3303 {
    3304 ncols = 0;
    3305 nrows = 0;
    3306 }
    3307 else
    3308 {
    3309 ncols = tree->pathnlpcols[startdepth-1];
    3310 nrows = tree->pathnlprows[startdepth-1];
    3311 }
    3312
    3313 for( i = startdepth; i < tree->pathlen; ++i )
    3314 {
    3315 node = tree->path[i];
    3316 assert(node != NULL);
    3317 assert(node->active);
    3318 assert((int)(node->depth) == i);
    3319
    3320 switch( SCIPnodeGetType(node) )
    3321 {
    3323 assert(i == tree->pathlen-1 || SCIPtreeProbing(tree));
    3324 break;
    3326 assert(SCIPtreeProbing(tree));
    3327 assert(i >= 1);
    3328 assert(SCIPnodeGetType(tree->path[i-1]) == SCIP_NODETYPE_FOCUSNODE
    3329 || (ncols == node->data.probingnode->ninitialcols && nrows == node->data.probingnode->ninitialrows));
    3330 assert(ncols <= node->data.probingnode->ncols || !tree->focuslpconstructed);
    3331 assert(nrows <= node->data.probingnode->nrows || !tree->focuslpconstructed);
    3332 if( i < tree->pathlen-1 )
    3333 {
    3334 ncols = node->data.probingnode->ncols;
    3335 nrows = node->data.probingnode->nrows;
    3336 }
    3337 else
    3338 {
    3339 /* for the current probing node, the initial LP size is stored in the path */
    3340 ncols = node->data.probingnode->ninitialcols;
    3341 nrows = node->data.probingnode->ninitialrows;
    3342 }
    3343 break;
    3345 SCIPerrorMessage("sibling cannot be in the active path\n");
    3346 SCIPABORT();
    3347 return SCIP_INVALIDDATA; /*lint !e527*/
    3349 SCIPerrorMessage("child cannot be in the active path\n");
    3350 SCIPABORT();
    3351 return SCIP_INVALIDDATA; /*lint !e527*/
    3352 case SCIP_NODETYPE_LEAF:
    3353 SCIPerrorMessage("leaf cannot be in the active path\n");
    3354 SCIPABORT();
    3355 return SCIP_INVALIDDATA; /*lint !e527*/
    3357 SCIPerrorMessage("dead-end cannot be in the active path\n");
    3358 SCIPABORT();
    3359 return SCIP_INVALIDDATA; /*lint !e527*/
    3361 break;
    3363 assert(node->data.pseudofork != NULL);
    3364 ncols += node->data.pseudofork->naddedcols;
    3365 nrows += node->data.pseudofork->naddedrows;
    3366 break;
    3367 case SCIP_NODETYPE_FORK:
    3368 assert(node->data.fork != NULL);
    3369 ncols += node->data.fork->naddedcols;
    3370 nrows += node->data.fork->naddedrows;
    3371 break;
    3373 assert(node->data.subroot != NULL);
    3374 ncols = node->data.subroot->ncols;
    3375 nrows = node->data.subroot->nrows;
    3376 break;
    3378 SCIPerrorMessage("node cannot be of type REFOCUSNODE at this point\n");
    3379 SCIPABORT();
    3380 return SCIP_INVALIDDATA; /*lint !e527*/
    3381 default:
    3382 SCIPerrorMessage("unknown node type %d\n", SCIPnodeGetType(node));
    3383 SCIPABORT();
    3384 return SCIP_INVALIDDATA; /*lint !e527*/
    3385 }
    3386 tree->pathnlpcols[i] = ncols;
    3387 tree->pathnlprows[i] = nrows;
    3388 }
    3389 return SCIP_OKAY;
    3390}
    3391
    3392/** finds the common fork node, the new LP state defining fork, and the new focus subroot, if the path is switched to
    3393 * the given node
    3394 */
    3395static
    3397 SCIP_TREE* tree, /**< branch and bound tree */
    3398 SCIP_NODE* node, /**< new focus node, or NULL */
    3399 SCIP_NODE** commonfork, /**< pointer to store common fork node of old and new focus node */
    3400 SCIP_NODE** newlpfork, /**< pointer to store the new LP defining fork node */
    3401 SCIP_NODE** newlpstatefork, /**< pointer to store the new LP state defining fork node */
    3402 SCIP_NODE** newsubroot, /**< pointer to store the new subroot node */
    3403 SCIP_Bool* cutoff /**< pointer to store whether the given node can be cut off and no path switching
    3404 * should be performed */
    3405 )
    3406{
    3407 SCIP_NODE* fork;
    3408 SCIP_NODE* lpfork;
    3409 SCIP_NODE* lpstatefork;
    3410 SCIP_NODE* subroot;
    3411
    3412 assert(tree != NULL);
    3413 assert(tree->root != NULL);
    3414 assert((tree->focusnode == NULL) == !tree->root->active);
    3415 assert(tree->focuslpfork == NULL || tree->focusnode != NULL);
    3416 assert(tree->focuslpfork == NULL || tree->focuslpfork->depth < tree->focusnode->depth);
    3417 assert(tree->focuslpstatefork == NULL || tree->focuslpfork != NULL);
    3418 assert(tree->focuslpstatefork == NULL || tree->focuslpstatefork->depth <= tree->focuslpfork->depth);
    3419 assert(tree->focussubroot == NULL || tree->focuslpstatefork != NULL);
    3420 assert(tree->focussubroot == NULL || tree->focussubroot->depth <= tree->focuslpstatefork->depth);
    3421 assert(tree->cutoffdepth >= 0);
    3422 assert(tree->cutoffdepth == INT_MAX || tree->cutoffdepth < tree->pathlen);
    3423 assert(tree->cutoffdepth == INT_MAX || tree->path[tree->cutoffdepth]->cutoff);
    3424 assert(tree->repropdepth >= 0);
    3425 assert(tree->repropdepth == INT_MAX || tree->repropdepth < tree->pathlen);
    3426 assert(tree->repropdepth == INT_MAX || tree->path[tree->repropdepth]->reprop);
    3427 assert(commonfork != NULL);
    3428 assert(newlpfork != NULL);
    3429 assert(newlpstatefork != NULL);
    3430 assert(newsubroot != NULL);
    3431 assert(cutoff != NULL);
    3432
    3433 *commonfork = NULL;
    3434 *newlpfork = NULL;
    3435 *newlpstatefork = NULL;
    3436 *newsubroot = NULL;
    3437 *cutoff = FALSE;
    3438
    3439 /* if the new focus node is NULL, there is no common fork node, and the new LP fork, LP state fork, and subroot
    3440 * are NULL
    3441 */
    3442 if( node == NULL )
    3443 {
    3444 tree->repropdepth = INT_MAX;
    3445 return;
    3446 }
    3447
    3448 /* check if the new node is marked to be cut off */
    3449 if( node->cutoff )
    3450 {
    3451 *cutoff = TRUE;
    3452 return;
    3453 }
    3454
    3455 /* 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
    3456 * and subroot
    3457 */
    3458 if( tree->focusnode == NULL )
    3459 {
    3460 assert(!tree->root->active);
    3461 assert(tree->pathlen == 0);
    3462 assert(tree->cutoffdepth == INT_MAX);
    3463 assert(tree->repropdepth == INT_MAX);
    3464
    3465 lpfork = node;
    3468 {
    3469 lpfork = lpfork->parent;
    3470 if( lpfork == NULL )
    3471 return;
    3472 if( lpfork->cutoff )
    3473 {
    3474 *cutoff = TRUE;
    3475 return;
    3476 }
    3477 }
    3478 *newlpfork = lpfork;
    3479
    3480 lpstatefork = lpfork;
    3481 while( SCIPnodeGetType(lpstatefork) != SCIP_NODETYPE_FORK && SCIPnodeGetType(lpstatefork) != SCIP_NODETYPE_SUBROOT )
    3482 {
    3483 lpstatefork = lpstatefork->parent;
    3484 if( lpstatefork == NULL )
    3485 return;
    3486 if( lpstatefork->cutoff )
    3487 {
    3488 *cutoff = TRUE;
    3489 return;
    3490 }
    3491 }
    3492 *newlpstatefork = lpstatefork;
    3493
    3494 subroot = lpstatefork;
    3495 while( SCIPnodeGetType(subroot) != SCIP_NODETYPE_SUBROOT )
    3496 {
    3497 subroot = subroot->parent;
    3498 if( subroot == NULL )
    3499 return;
    3500 if( subroot->cutoff )
    3501 {
    3502 *cutoff = TRUE;
    3503 return;
    3504 }
    3505 }
    3506 *newsubroot = subroot;
    3507
    3508 fork = subroot;
    3509 while( fork->parent != NULL )
    3510 {
    3511 fork = fork->parent;
    3512 if( fork->cutoff )
    3513 {
    3514 *cutoff = TRUE;
    3515 return;
    3516 }
    3517 }
    3518 return;
    3519 }
    3520
    3521 /* find the common fork node, the new LP defining fork, the new LP state defining fork, and the new focus subroot */
    3522 fork = node;
    3523 lpfork = NULL;
    3524 lpstatefork = NULL;
    3525 subroot = NULL;
    3526 assert(fork != NULL);
    3527
    3528 while( !fork->active )
    3529 {
    3530 fork = fork->parent;
    3531 assert(fork != NULL); /* because the root is active, there must be a common fork node */
    3532
    3533 if( fork->cutoff )
    3534 {
    3535 *cutoff = TRUE;
    3536 return;
    3537 }
    3538 if( lpfork == NULL
    3541 lpfork = fork;
    3542 if( lpstatefork == NULL
    3544 lpstatefork = fork;
    3545 if( subroot == NULL && SCIPnodeGetType(fork) == SCIP_NODETYPE_SUBROOT )
    3546 subroot = fork;
    3547 }
    3548 assert(lpfork == NULL || !lpfork->active || lpfork == fork);
    3549 assert(lpstatefork == NULL || !lpstatefork->active || lpstatefork == fork);
    3550 assert(subroot == NULL || !subroot->active || subroot == fork);
    3551 SCIPdebugMessage("find switch forks: forkdepth=%u\n", fork->depth);
    3552
    3553 /* if the common fork node is below the current cutoff depth, the cutoff node is an ancestor of the common fork
    3554 * and thus an ancestor of the new focus node, s.t. the new node can also be cut off
    3555 */
    3556 assert((int)fork->depth != tree->cutoffdepth);
    3557 if( (int)fork->depth > tree->cutoffdepth )
    3558 {
    3559#ifndef NDEBUG
    3560 while( !fork->cutoff )
    3561 {
    3562 fork = fork->parent;
    3563 assert(fork != NULL);
    3564 }
    3565 assert((int)fork->depth >= tree->cutoffdepth);
    3566#endif
    3567 *cutoff = TRUE;
    3568 return;
    3569 }
    3570
    3571 /* if not already found, continue searching the LP defining fork; it cannot be deeper than the common fork */
    3572 if( lpfork == NULL )
    3573 {
    3574 if( tree->focuslpfork != NULL && tree->focuslpfork->depth > fork->depth )
    3575 {
    3576 /* focuslpfork is not on the same active path as the new node: we have to continue searching */
    3577 lpfork = fork;
    3578 while( lpfork != NULL
    3582 {
    3583 assert(lpfork->active);
    3584 lpfork = lpfork->parent;
    3585 }
    3586 }
    3587 else
    3588 {
    3589 /* focuslpfork is on the same active path as the new node: old and new node have the same lpfork */
    3590 lpfork = tree->focuslpfork;
    3591 }
    3592 assert(lpfork == NULL || lpfork->depth <= fork->depth);
    3593 assert(lpfork == NULL || lpfork->active);
    3594 }
    3595 assert(lpfork == NULL
    3599 SCIPdebugMessage("find switch forks: lpforkdepth=%d\n", lpfork == NULL ? -1 : (int)(lpfork->depth));
    3600
    3601 /* if not already found, continue searching the LP state defining fork; it cannot be deeper than the
    3602 * LP defining fork and the common fork
    3603 */
    3604 if( lpstatefork == NULL )
    3605 {
    3606 if( tree->focuslpstatefork != NULL && tree->focuslpstatefork->depth > fork->depth )
    3607 {
    3608 /* focuslpstatefork is not on the same active path as the new node: we have to continue searching */
    3609 if( lpfork != NULL && lpfork->depth < fork->depth )
    3610 lpstatefork = lpfork;
    3611 else
    3612 lpstatefork = fork;
    3613 while( lpstatefork != NULL
    3614 && SCIPnodeGetType(lpstatefork) != SCIP_NODETYPE_FORK
    3615 && SCIPnodeGetType(lpstatefork) != SCIP_NODETYPE_SUBROOT )
    3616 {
    3617 assert(lpstatefork->active);
    3618 lpstatefork = lpstatefork->parent;
    3619 }
    3620 }
    3621 else
    3622 {
    3623 /* focuslpstatefork is on the same active path as the new node: old and new node have the same lpstatefork */
    3624 lpstatefork = tree->focuslpstatefork;
    3625 }
    3626 assert(lpstatefork == NULL || lpstatefork->depth <= fork->depth);
    3627 assert(lpstatefork == NULL || lpstatefork->active);
    3628 }
    3629 assert(lpstatefork == NULL
    3630 || SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_FORK
    3631 || SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_SUBROOT);
    3632 assert(lpstatefork == NULL || (lpfork != NULL && lpstatefork->depth <= lpfork->depth));
    3633 SCIPdebugMessage("find switch forks: lpstateforkdepth=%d\n", lpstatefork == NULL ? -1 : (int)(lpstatefork->depth));
    3634
    3635 /* if not already found, continue searching the subroot; it cannot be deeper than the LP defining fork, the
    3636 * LP state fork and the common fork
    3637 */
    3638 if( subroot == NULL )
    3639 {
    3640 if( tree->focussubroot != NULL && tree->focussubroot->depth > fork->depth )
    3641 {
    3642 /* focussubroot is not on the same active path as the new node: we have to continue searching */
    3643 if( lpstatefork != NULL && lpstatefork->depth < fork->depth )
    3644 subroot = lpstatefork;
    3645 else if( lpfork != NULL && lpfork->depth < fork->depth )
    3646 subroot = lpfork;
    3647 else
    3648 subroot = fork;
    3649 while( subroot != NULL && SCIPnodeGetType(subroot) != SCIP_NODETYPE_SUBROOT )
    3650 {
    3651 assert(subroot->active);
    3652 subroot = subroot->parent;
    3653 }
    3654 }
    3655 else
    3656 subroot = tree->focussubroot;
    3657 assert(subroot == NULL || subroot->depth <= fork->depth);
    3658 assert(subroot == NULL || subroot->active);
    3659 }
    3660 assert(subroot == NULL || SCIPnodeGetType(subroot) == SCIP_NODETYPE_SUBROOT);
    3661 assert(subroot == NULL || (lpstatefork != NULL && subroot->depth <= lpstatefork->depth));
    3662 SCIPdebugMessage("find switch forks: subrootdepth=%d\n", subroot == NULL ? -1 : (int)(subroot->depth));
    3663
    3664 /* if a node prior to the common fork should be repropagated, we select the node to be repropagated as common
    3665 * fork in order to undo all bound changes up to this node, repropagate the node, and redo the bound changes
    3666 * afterwards
    3667 */
    3668 if( (int)fork->depth > tree->repropdepth )
    3669 {
    3670 fork = tree->path[tree->repropdepth];
    3671 assert(fork->active);
    3672 assert(fork->reprop);
    3673 }
    3674
    3675 *commonfork = fork;
    3676 *newlpfork = lpfork;
    3677 *newlpstatefork = lpstatefork;
    3678 *newsubroot = subroot;
    3679
    3680#ifndef NDEBUG
    3681 while( fork != NULL )
    3682 {
    3683 assert(fork->active);
    3684 assert(!fork->cutoff);
    3685 assert(fork->parent == NULL || !fork->parent->reprop);
    3686 fork = fork->parent;
    3687 }
    3688#endif
    3689 tree->repropdepth = INT_MAX;
    3690}
    3691
    3692/** switches the active path to the new focus node, frees dead end, applies domain and constraint set changes */
    3693static
    3695 SCIP_TREE* tree, /**< branch and bound tree */
    3696 SCIP_REOPT* reopt, /**< reoptimization data structure */
    3697 BMS_BLKMEM* blkmem, /**< block memory buffers */
    3698 SCIP_SET* set, /**< global SCIP settings */
    3699 SCIP_STAT* stat, /**< problem statistics */
    3700 SCIP_PROB* transprob, /**< transformed problem after presolve */
    3701 SCIP_PROB* origprob, /**< original problem */
    3702 SCIP_PRIMAL* primal, /**< primal data */
    3703 SCIP_LP* lp, /**< current LP data */
    3704 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    3705 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    3706 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    3707 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    3708 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    3709 SCIP_NODE* fork, /**< common fork node of old and new focus node, or NULL */
    3710 SCIP_NODE* focusnode, /**< new focus node, or NULL */
    3711 SCIP_Bool* cutoff /**< pointer to store whether the new focus node can be cut off */
    3712 )
    3713{
    3714 int neweffectiverootdepth;
    3715 int forklen; /* length of the path to subroot/fork/pseudofork/junction node, or 0 if no fork */
    3716 int focusnodedepth; /* depth of the new focus node, or -1 if focusnode == NULL */
    3717 int i;
    3718 SCIP_NODE* oldfocusnode;
    3719
    3720 assert(tree != NULL);
    3721 assert(fork == NULL || (fork->active && !fork->cutoff));
    3722 assert(fork == NULL || fork->depth < tree->cutoffdepth);
    3723 assert(fork == NULL || focusnode != NULL);
    3724 assert(focusnode == NULL || (!focusnode->active && !focusnode->cutoff));
    3725 assert(focusnode == NULL || SCIPnodeGetType(focusnode) == SCIP_NODETYPE_FOCUSNODE);
    3726 assert(cutoff != NULL);
    3727
    3728 /* set new focus node */
    3729 oldfocusnode = tree->focusnode;
    3730 tree->focusnode = focusnode;
    3731
    3732 SCIPsetDebugMsg(set, "switch path: old pathlen=%d\n", tree->pathlen);
    3733
    3734 /* get the nodes' depths */
    3735 focusnodedepth = (focusnode != NULL ? (int)focusnode->depth : -1);
    3736 forklen = (fork != NULL ? (int)fork->depth + 1 : 0);
    3737 assert(forklen <= focusnodedepth + 1);
    3738
    3739 /* delay events in node deactivations to fork and node activations to parent of new focus node */
    3740 SCIP_CALL( SCIPeventqueueDelay(eventqueue) );
    3741
    3742 /* undo the domain and constraint set changes of the old active path by deactivating the path's nodes */
    3743 while( tree->pathlen > forklen )
    3744 {
    3745 SCIP_CALL( nodeDeactivate(tree->path[tree->pathlen - 1], blkmem, set, stat, tree, lp, branchcand, eventqueue) );
    3746 --tree->pathlen;
    3747 }
    3748 assert(tree->pathlen == forklen);
    3749
    3750 /* apply the pending bound changes */
    3751 SCIP_CALL( treeApplyPendingBdchgs(tree, reopt, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue, eventfilter, cliquetable) );
    3752
    3753 /* create the new active path */
    3754 SCIP_CALL( treeEnsurePathMem(tree, set, focusnodedepth+1) );
    3755
    3756 while( focusnode != fork )
    3757 {
    3758 assert(focusnode != NULL);
    3759 assert(!focusnode->active);
    3760 assert(!focusnode->cutoff);
    3761 /* coverity[var_deref_op] */
    3762 tree->path[focusnode->depth] = focusnode;
    3763 focusnode = focusnode->parent;
    3764 }
    3765
    3766 /* if the old focus node is a dead end (has no children), delete it */
    3767 if( oldfocusnode != NULL )
    3768 {
    3769 SCIP_Bool freeNode;
    3770
    3771 switch( SCIPnodeGetType(oldfocusnode) )
    3772 {
    3776 case SCIP_NODETYPE_LEAF:
    3778 freeNode = FALSE;
    3779 break;
    3781 freeNode = TRUE;
    3782 break;
    3784 freeNode = (oldfocusnode->data.junction.nchildren == 0);
    3785 break;
    3787 freeNode = (oldfocusnode->data.pseudofork->nchildren == 0);
    3788 break;
    3789 case SCIP_NODETYPE_FORK:
    3790 freeNode = (oldfocusnode->data.fork->nchildren == 0);
    3791 break;
    3793 freeNode = (oldfocusnode->data.subroot->nchildren == 0);
    3794 break;
    3796 SCIPerrorMessage("probing node could not be the focus node\n");
    3797 return SCIP_INVALIDDATA;
    3798 default:
    3799 SCIPerrorMessage("unknown node type %d\n", SCIPnodeGetType(oldfocusnode));
    3800 return SCIP_INVALIDDATA;
    3801 }
    3802
    3803 if( freeNode )
    3804 {
    3805 assert(tree->effectiverootdepth <= tree->updatedeffectiverootdepth);
    3806 SCIP_CALL( SCIPnodeFree(&oldfocusnode, blkmem, set, stat, eventqueue, eventfilter, tree, lp) );
    3807 assert(tree->updatedeffectiverootdepth <= focusnodedepth || tree->focusnode == NULL);
    3808 }
    3809 }
    3810
    3811 /* apply effective root shift up to the new focus node */
    3812 *cutoff = FALSE;
    3813 tree->cutoffdepth = INT_MAX;
    3814 neweffectiverootdepth = MIN(tree->updatedeffectiverootdepth, focusnodedepth);
    3815
    3816 /* promote the constraint set and bound changes up to the new effective root to be global changes */
    3817 if( tree->effectiverootdepth < neweffectiverootdepth )
    3818 {
    3820 "shift effective root from depth %d to %d: applying constraint set and bound changes to global problem\n",
    3821 tree->effectiverootdepth, neweffectiverootdepth);
    3822
    3823 /* at first globalize constraint changes to update constraint handlers before changing bounds */
    3824 for( i = tree->effectiverootdepth + 1; i <= neweffectiverootdepth; ++i )
    3825 {
    3826 SCIPsetDebugMsg(set, " -> applying constraint set changes of depth %d\n", i);
    3827
    3828 SCIP_CALL( SCIPconssetchgMakeGlobal(&tree->path[i]->conssetchg, blkmem, set, stat, transprob, reopt) );
    3829 }
    3830
    3831 /* at last globalize bound changes triggering delayed events processed after the path switch */
    3832 for( i = tree->effectiverootdepth + 1; i <= neweffectiverootdepth && !(*cutoff); ++i )
    3833 {
    3834 SCIPsetDebugMsg(set, " -> applying bound changes of depth %d\n", i);
    3835
    3836 SCIP_CALL( SCIPdomchgApplyGlobal(tree->path[i]->domchg, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, cutoff) );
    3837 }
    3838
    3839 /* update applied effective root depth */
    3840 tree->effectiverootdepth = neweffectiverootdepth;
    3841 }
    3842
    3843 /* fork might be cut off when applying the pending bound changes */
    3844 if( fork != NULL && fork->cutoff )
    3845 *cutoff = TRUE;
    3846 else if( fork != NULL && fork->reprop && !(*cutoff) )
    3847 {
    3848 /* propagate common fork again, if the reprop flag is set */
    3849 assert(fork == tree->path[tree->pathlen - 1]);
    3850 assert(fork->active);
    3851 assert(!fork->cutoff);
    3852
    3853 SCIP_CALL( nodeRepropagate(fork, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
    3854 conflict, eventqueue, eventfilter, cliquetable, cutoff) );
    3855 }
    3856 assert(fork != NULL || !(*cutoff));
    3857
    3858 /* Apply domain and constraint set changes of the new path by activating the path's nodes;
    3859 * on the way, domain propagation might be applied again to the path's nodes, which can result in the cutoff of
    3860 * the node (and its subtree).
    3861 * We only activate all nodes down to the parent of the new focus node, because the events in this process are
    3862 * delayed, which means that multiple changes of a bound of a variable are merged (and might even be cancelled out,
    3863 * if the bound is first relaxed when deactivating a node on the old path and then tightened to the same value
    3864 * when activating a node on the new path).
    3865 * This is valid for all nodes down to the parent of the new focus node, since they have already been propagated.
    3866 * Bound change events on the new focus node, however, must not be cancelled out, since they need to be propagated
    3867 * and thus, the event must be thrown and catched by the constraint handlers to mark constraints for propagation.
    3868 */
    3869 while( tree->pathlen < focusnodedepth && !(*cutoff) )
    3870 {
    3871 /* activate the node, and apply domain propagation if the reprop flag is set */
    3872 ++tree->pathlen;
    3873 assert(!tree->path[tree->pathlen - 1]->cutoff);
    3874 SCIP_CALL( nodeActivate(tree->path[tree->pathlen - 1], blkmem, set, stat, transprob, origprob, primal, tree, reopt,
    3875 lp, branchcand, conflict, eventqueue, eventfilter, cliquetable, cutoff) );
    3876 }
    3877
    3878 /* process the delayed events */
    3879 SCIP_CALL( SCIPeventqueueProcess(eventqueue, blkmem, set, primal, lp, branchcand, eventfilter) );
    3880
    3881 /* activate the new focus node; there is no need to delay these events */
    3882 if( tree->pathlen == focusnodedepth && !(*cutoff) )
    3883 {
    3884 /* activate the node, and apply domain propagation if the reprop flag is set */
    3885 ++tree->pathlen;
    3886 assert(!tree->path[tree->pathlen - 1]->cutoff);
    3887 SCIP_CALL( nodeActivate(tree->path[tree->pathlen - 1], blkmem, set, stat, transprob, origprob, primal, tree, reopt,
    3888 lp, branchcand, conflict, eventqueue, eventfilter, cliquetable, cutoff) );
    3889 }
    3890
    3891 /* count the new LP sizes of the path */
    3892 SCIP_CALL( treeUpdatePathLPSize(tree, forklen) );
    3893
    3894 SCIPsetDebugMsg(set, "switch path: new pathlen=%d\n", tree->pathlen);
    3895
    3896 return SCIP_OKAY;
    3897}
    3898
    3899/** loads the subroot's LP data */
    3900static
    3902 SCIP_NODE* subroot, /**< subroot node to construct LP for */
    3903 BMS_BLKMEM* blkmem, /**< block memory buffers */
    3904 SCIP_SET* set, /**< global SCIP settings */
    3905 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    3906 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    3907 SCIP_LP* lp /**< current LP data */
    3908 )
    3909{
    3910 SCIP_COL** cols;
    3911 SCIP_ROW** rows;
    3912 int ncols;
    3913 int nrows;
    3914 int c;
    3915 int r;
    3916
    3917 assert(subroot != NULL);
    3918 assert(SCIPnodeGetType(subroot) == SCIP_NODETYPE_SUBROOT);
    3919 assert(subroot->data.subroot != NULL);
    3920 assert(blkmem != NULL);
    3921 assert(set != NULL);
    3922 assert(lp != NULL);
    3923
    3924 cols = subroot->data.subroot->cols;
    3925 rows = subroot->data.subroot->rows;
    3926 ncols = subroot->data.subroot->ncols;
    3927 nrows = subroot->data.subroot->nrows;
    3928
    3929 assert(ncols == 0 || cols != NULL);
    3930 assert(nrows == 0 || rows != NULL);
    3931
    3932 for( c = 0; c < ncols; ++c )
    3933 {
    3934 SCIP_CALL( SCIPlpAddCol(lp, set, cols[c], (int) subroot->depth) );
    3935 }
    3936 for( r = 0; r < nrows; ++r )
    3937 {
    3938 SCIP_CALL( SCIPlpAddRow(lp, blkmem, set, eventqueue, eventfilter, rows[r], (int) subroot->depth) );
    3939 }
    3940
    3941 return SCIP_OKAY;
    3942}
    3943
    3944/** loads the fork's additional LP data */
    3945static
    3947 SCIP_NODE* fork, /**< fork node to construct additional LP for */
    3948 BMS_BLKMEM* blkmem, /**< block memory buffers */
    3949 SCIP_SET* set, /**< global SCIP settings */
    3950 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    3951 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    3952 SCIP_LP* lp /**< current LP data */
    3953 )
    3954{
    3955 SCIP_COL** cols;
    3956 SCIP_ROW** rows;
    3957 int ncols;
    3958 int nrows;
    3959 int c;
    3960 int r;
    3961
    3962 assert(fork != NULL);
    3963 assert(SCIPnodeGetType(fork) == SCIP_NODETYPE_FORK);
    3964 assert(fork->data.fork != NULL);
    3965 assert(blkmem != NULL);
    3966 assert(set != NULL);
    3967 assert(lp != NULL);
    3968
    3969 cols = fork->data.fork->addedcols;
    3970 rows = fork->data.fork->addedrows;
    3971 ncols = fork->data.fork->naddedcols;
    3972 nrows = fork->data.fork->naddedrows;
    3973
    3974 assert(ncols == 0 || cols != NULL);
    3975 assert(nrows == 0 || rows != NULL);
    3976
    3977 for( c = 0; c < ncols; ++c )
    3978 {
    3979 SCIP_CALL( SCIPlpAddCol(lp, set, cols[c], (int) fork->depth) );
    3980 }
    3981 for( r = 0; r < nrows; ++r )
    3982 {
    3983 SCIP_CALL( SCIPlpAddRow(lp, blkmem, set, eventqueue, eventfilter, rows[r], (int) fork->depth) );
    3984 }
    3985
    3986 return SCIP_OKAY;
    3987}
    3988
    3989/** loads the pseudofork's additional LP data */
    3990static
    3992 SCIP_NODE* pseudofork, /**< pseudofork node to construct additional LP for */
    3993 BMS_BLKMEM* blkmem, /**< block memory buffers */
    3994 SCIP_SET* set, /**< global SCIP settings */
    3995 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    3996 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    3997 SCIP_LP* lp /**< current LP data */
    3998 )
    3999{
    4000 SCIP_COL** cols;
    4001 SCIP_ROW** rows;
    4002 int ncols;
    4003 int nrows;
    4004 int c;
    4005 int r;
    4006
    4007 assert(pseudofork != NULL);
    4008 assert(SCIPnodeGetType(pseudofork) == SCIP_NODETYPE_PSEUDOFORK);
    4009 assert(pseudofork->data.pseudofork != NULL);
    4010 assert(blkmem != NULL);
    4011 assert(set != NULL);
    4012 assert(lp != NULL);
    4013
    4014 cols = pseudofork->data.pseudofork->addedcols;
    4015 rows = pseudofork->data.pseudofork->addedrows;
    4016 ncols = pseudofork->data.pseudofork->naddedcols;
    4017 nrows = pseudofork->data.pseudofork->naddedrows;
    4018
    4019 assert(ncols == 0 || cols != NULL);
    4020 assert(nrows == 0 || rows != NULL);
    4021
    4022 for( c = 0; c < ncols; ++c )
    4023 {
    4024 SCIP_CALL( SCIPlpAddCol(lp, set, cols[c], (int) pseudofork->depth) );
    4025 }
    4026 for( r = 0; r < nrows; ++r )
    4027 {
    4028 SCIP_CALL( SCIPlpAddRow(lp, blkmem, set, eventqueue, eventfilter, rows[r], (int) pseudofork->depth) );
    4029 }
    4030
    4031 return SCIP_OKAY;
    4032}
    4033
    4034#ifndef NDEBUG
    4035/** checks validity of active path */
    4036static
    4038 SCIP_TREE* tree /**< branch and bound tree */
    4039 )
    4040{
    4041 SCIP_NODE* node;
    4042 int ncols;
    4043 int nrows;
    4044 int d;
    4045
    4046 assert(tree != NULL);
    4047 assert(tree->path != NULL);
    4048
    4049 ncols = 0;
    4050 nrows = 0;
    4051 for( d = 0; d < tree->pathlen; ++d )
    4052 {
    4053 node = tree->path[d];
    4054 assert(node != NULL);
    4055 assert((int)(node->depth) == d);
    4056 switch( SCIPnodeGetType(node) )
    4057 {
    4059 assert(SCIPtreeProbing(tree));
    4060 assert(d >= 1);
    4061 assert(SCIPnodeGetType(tree->path[d-1]) == SCIP_NODETYPE_FOCUSNODE
    4062 || (ncols == node->data.probingnode->ninitialcols && nrows == node->data.probingnode->ninitialrows));
    4063 assert(ncols <= node->data.probingnode->ncols || !tree->focuslpconstructed);
    4064 assert(nrows <= node->data.probingnode->nrows || !tree->focuslpconstructed);
    4065 if( d < tree->pathlen-1 )
    4066 {
    4067 ncols = node->data.probingnode->ncols;
    4068 nrows = node->data.probingnode->nrows;
    4069 }
    4070 else
    4071 {
    4072 /* for the current probing node, the initial LP size is stored in the path */
    4073 ncols = node->data.probingnode->ninitialcols;
    4074 nrows = node->data.probingnode->ninitialrows;
    4075 }
    4076 break;
    4078 break;
    4080 ncols += node->data.pseudofork->naddedcols;
    4081 nrows += node->data.pseudofork->naddedrows;
    4082 break;
    4083 case SCIP_NODETYPE_FORK:
    4084 ncols += node->data.fork->naddedcols;
    4085 nrows += node->data.fork->naddedrows;
    4086 break;
    4088 ncols = node->data.subroot->ncols;
    4089 nrows = node->data.subroot->nrows;
    4090 break;
    4093 assert(d == tree->pathlen-1 || SCIPtreeProbing(tree));
    4094 break;
    4095 default:
    4096 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",
    4097 d, SCIPnodeGetType(node));
    4098 SCIPABORT();
    4099 } /*lint !e788*/
    4100 assert(tree->pathnlpcols[d] == ncols);
    4101 assert(tree->pathnlprows[d] == nrows);
    4102 }
    4103}
    4104#else
    4105#define treeCheckPath(tree) /**/
    4106#endif
    4107
    4108/** constructs the LP relaxation of the focus node */
    4110 SCIP_TREE* tree, /**< branch and bound tree */
    4111 BMS_BLKMEM* blkmem, /**< block memory buffers */
    4112 SCIP_SET* set, /**< global SCIP settings */
    4113 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    4114 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    4115 SCIP_LP* lp, /**< current LP data */
    4116 SCIP_Bool* initroot /**< pointer to store whether the root LP relaxation has to be initialized */
    4117 )
    4118{
    4119 SCIP_NODE* lpfork;
    4120 int lpforkdepth;
    4121 int d;
    4122
    4123 assert(tree != NULL);
    4124 assert(!tree->focuslpconstructed);
    4125 assert(tree->path != NULL);
    4126 assert(tree->pathlen > 0);
    4127 assert(tree->focusnode != NULL);
    4129 assert(SCIPnodeGetDepth(tree->focusnode) == tree->pathlen-1);
    4130 assert(!SCIPtreeProbing(tree));
    4131 assert(tree->focusnode == tree->path[tree->pathlen-1]);
    4132 assert(blkmem != NULL);
    4133 assert(set != NULL);
    4134 assert(lp != NULL);
    4135 assert(initroot != NULL);
    4136
    4137 SCIPsetDebugMsg(set, "load LP for current fork node #%" SCIP_LONGINT_FORMAT " at depth %d\n",
    4138 tree->focuslpfork == NULL ? -1 : SCIPnodeGetNumber(tree->focuslpfork),
    4139 tree->focuslpfork == NULL ? -1 : SCIPnodeGetDepth(tree->focuslpfork));
    4140 SCIPsetDebugMsg(set, "-> old LP has %d cols and %d rows\n", SCIPlpGetNCols(lp), SCIPlpGetNRows(lp));
    4141 SCIPsetDebugMsg(set, "-> correct LP has %d cols and %d rows\n",
    4142 tree->correctlpdepth >= 0 ? tree->pathnlpcols[tree->correctlpdepth] : 0,
    4143 tree->correctlpdepth >= 0 ? tree->pathnlprows[tree->correctlpdepth] : 0);
    4144 SCIPsetDebugMsg(set, "-> old correctlpdepth: %d\n", tree->correctlpdepth);
    4145
    4146 treeCheckPath(tree);
    4147
    4148 lpfork = tree->focuslpfork;
    4149
    4150 /* find out the lpfork's depth (or -1, if lpfork is NULL) */
    4151 if( lpfork == NULL )
    4152 {
    4153 assert(tree->correctlpdepth == -1 || tree->pathnlpcols[tree->correctlpdepth] == 0);
    4154 assert(tree->correctlpdepth == -1 || tree->pathnlprows[tree->correctlpdepth] == 0);
    4155 assert(tree->focuslpstatefork == NULL);
    4156 assert(tree->focussubroot == NULL);
    4157 lpforkdepth = -1;
    4158 }
    4159 else
    4160 {
    4163 assert(lpfork->active);
    4164 assert(tree->path[lpfork->depth] == lpfork);
    4165 lpforkdepth = (int) lpfork->depth;
    4166 }
    4167 assert(lpforkdepth < tree->pathlen-1); /* lpfork must not be the last (the focus) node of the active path */
    4168
    4169 /* find out, if we are in the same subtree */
    4170 if( tree->correctlpdepth >= 0 )
    4171 {
    4172 /* same subtree: shrink LP to the deepest node with correct LP */
    4173 assert(lpforkdepth == -1 || tree->pathnlpcols[tree->correctlpdepth] <= tree->pathnlpcols[lpforkdepth]);
    4174 assert(lpforkdepth == -1 || tree->pathnlprows[tree->correctlpdepth] <= tree->pathnlprows[lpforkdepth]);
    4175 assert(lpforkdepth >= 0 || tree->pathnlpcols[tree->correctlpdepth] == 0);
    4176 assert(lpforkdepth >= 0 || tree->pathnlprows[tree->correctlpdepth] == 0);
    4178 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, tree->pathnlprows[tree->correctlpdepth]) );
    4179 }
    4180 else
    4181 {
    4182 /* other subtree: fill LP with the subroot LP data */
    4183 SCIP_CALL( SCIPlpClear(lp, blkmem, set, eventqueue, eventfilter) );
    4184 if( tree->focussubroot != NULL )
    4185 {
    4186 SCIP_CALL( subrootConstructLP(tree->focussubroot, blkmem, set, eventqueue, eventfilter, lp) );
    4187
    4188 tree->correctlpdepth = (int) tree->focussubroot->depth;
    4189 }
    4190 }
    4191
    4192 assert(lpforkdepth < tree->pathlen);
    4193
    4194 /* add the missing columns and rows */
    4195 for( d = tree->correctlpdepth+1; d <= lpforkdepth; ++d )
    4196 {
    4197 SCIP_NODE* pathnode;
    4198
    4199 pathnode = tree->path[d];
    4200 assert(pathnode != NULL);
    4201 assert((int)(pathnode->depth) == d);
    4202 assert(SCIPnodeGetType(pathnode) == SCIP_NODETYPE_JUNCTION
    4204 || SCIPnodeGetType(pathnode) == SCIP_NODETYPE_FORK);
    4205 if( SCIPnodeGetType(pathnode) == SCIP_NODETYPE_FORK )
    4206 {
    4207 SCIP_CALL( forkAddLP(pathnode, blkmem, set, eventqueue, eventfilter, lp) );
    4208 }
    4209 else if( SCIPnodeGetType(pathnode) == SCIP_NODETYPE_PSEUDOFORK )
    4210 {
    4211 SCIP_CALL( pseudoforkAddLP(pathnode, blkmem, set, eventqueue, eventfilter, lp) );
    4212 }
    4213 }
    4214 tree->correctlpdepth = MAX(tree->correctlpdepth, lpforkdepth);
    4215 assert(lpforkdepth == -1 || tree->pathnlpcols[tree->correctlpdepth] == tree->pathnlpcols[lpforkdepth]);
    4216 assert(lpforkdepth == -1 || tree->pathnlprows[tree->correctlpdepth] == tree->pathnlprows[lpforkdepth]);
    4217 assert(lpforkdepth == -1 || SCIPlpGetNCols(lp) == tree->pathnlpcols[lpforkdepth]);
    4218 assert(lpforkdepth == -1 || SCIPlpGetNRows(lp) == tree->pathnlprows[lpforkdepth]);
    4219 assert(lpforkdepth >= 0 || SCIPlpGetNCols(lp) == 0);
    4220 assert(lpforkdepth >= 0 || SCIPlpGetNRows(lp) == 0);
    4221
    4222 /* mark the LP's size, such that we know which rows and columns were added in the new node */
    4223 SCIPlpMarkSize(lp);
    4224
    4225 SCIPsetDebugMsg(set, "-> new correctlpdepth: %d\n", tree->correctlpdepth);
    4226 SCIPsetDebugMsg(set, "-> new LP has %d cols and %d rows\n", SCIPlpGetNCols(lp), SCIPlpGetNRows(lp));
    4227
    4228 /* if the correct LP depth is still -1, the root LP relaxation has to be initialized */
    4229 *initroot = (tree->correctlpdepth == -1);
    4230
    4231 /* mark the LP of the focus node constructed */
    4232 tree->focuslpconstructed = TRUE;
    4233
    4234 return SCIP_OKAY;
    4235}
    4236
    4237/** loads LP state for fork/subroot of the focus node */
    4239 SCIP_TREE* tree, /**< branch and bound tree */
    4240 BMS_BLKMEM* blkmem, /**< block memory buffers */
    4241 SCIP_SET* set, /**< global SCIP settings */
    4242 SCIP_PROB* prob, /**< problem data */
    4243 SCIP_STAT* stat, /**< dynamic problem statistics */
    4244 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    4245 SCIP_LP* lp /**< current LP data */
    4246 )
    4247{
    4248 SCIP_NODE* lpstatefork;
    4249 SCIP_Bool updatefeas;
    4250 SCIP_Bool checkbdchgs;
    4251 int lpstateforkdepth;
    4252 int d;
    4253
    4254 assert(tree != NULL);
    4255 assert(tree->focuslpconstructed);
    4256 assert(tree->path != NULL);
    4257 assert(tree->pathlen > 0);
    4258 assert(tree->focusnode != NULL);
    4259 assert(tree->correctlpdepth < tree->pathlen);
    4261 assert(SCIPnodeGetDepth(tree->focusnode) == tree->pathlen-1);
    4262 assert(!SCIPtreeProbing(tree));
    4263 assert(tree->focusnode == tree->path[tree->pathlen-1]);
    4264 assert(blkmem != NULL);
    4265 assert(set != NULL);
    4266 assert(lp != NULL);
    4267
    4268 SCIPsetDebugMsg(set, "load LP state for current fork node #%" SCIP_LONGINT_FORMAT " at depth %d\n",
    4271
    4272 lpstatefork = tree->focuslpstatefork;
    4273
    4274 /* if there is no LP state defining fork, nothing can be done */
    4275 if( lpstatefork == NULL )
    4276 return SCIP_OKAY;
    4277
    4278 /* get the lpstatefork's depth */
    4279 assert(SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_FORK || SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_SUBROOT);
    4280 assert(lpstatefork->active);
    4281 assert(tree->path[lpstatefork->depth] == lpstatefork);
    4282 lpstateforkdepth = (int) lpstatefork->depth;
    4283 assert(lpstateforkdepth < tree->pathlen-1); /* lpstatefork must not be the last (the focus) node of the active path */
    4284 assert(lpstateforkdepth <= tree->correctlpdepth); /* LP must have been constructed at least up to the fork depth */
    4285 assert(tree->pathnlpcols[tree->correctlpdepth] >= tree->pathnlpcols[lpstateforkdepth]); /* LP can only grow */
    4286 assert(tree->pathnlprows[tree->correctlpdepth] >= tree->pathnlprows[lpstateforkdepth]); /* LP can only grow */
    4287
    4288 /* load LP state */
    4289 if( tree->focuslpstateforklpcount != stat->lpcount )
    4290 {
    4291 if( SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_FORK )
    4292 {
    4293 assert(lpstatefork->data.fork != NULL);
    4294 SCIP_CALL( SCIPlpSetState(lp, blkmem, set, prob, eventqueue, lpstatefork->data.fork->lpistate,
    4295 lpstatefork->data.fork->lpwasprimfeas, lpstatefork->data.fork->lpwasprimchecked,
    4296 lpstatefork->data.fork->lpwasdualfeas, lpstatefork->data.fork->lpwasdualchecked) );
    4297 }
    4298 else
    4299 {
    4300 assert(SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_SUBROOT);
    4301 assert(lpstatefork->data.subroot != NULL);
    4302 SCIP_CALL( SCIPlpSetState(lp, blkmem, set, prob, eventqueue, lpstatefork->data.subroot->lpistate,
    4303 lpstatefork->data.subroot->lpwasprimfeas, lpstatefork->data.subroot->lpwasprimchecked,
    4304 lpstatefork->data.subroot->lpwasdualfeas, lpstatefork->data.subroot->lpwasdualchecked) );
    4305 }
    4306 updatefeas = !lp->solved || !lp->solisbasic;
    4307 checkbdchgs = TRUE;
    4308 }
    4309 else
    4310 {
    4311 updatefeas = TRUE;
    4312
    4313 /* we do not need to check the bounds, since primalfeasible is updated anyway when flushing the LP */
    4314 checkbdchgs = FALSE;
    4315 }
    4316
    4317 if( updatefeas )
    4318 {
    4319 /* check whether the size of the LP increased (destroying primal/dual feasibility) */
    4321 && (tree->pathnlprows[tree->correctlpdepth] == tree->pathnlprows[lpstateforkdepth]);
    4323 && (tree->pathnlprows[tree->correctlpdepth] == tree->pathnlprows[lpstateforkdepth]);
    4324 lp->dualfeasible = lp->dualfeasible
    4325 && (tree->pathnlpcols[tree->correctlpdepth] == tree->pathnlpcols[lpstateforkdepth]);
    4326 lp->dualchecked = lp->dualchecked
    4327 && (tree->pathnlpcols[tree->correctlpdepth] == tree->pathnlpcols[lpstateforkdepth]);
    4328
    4329 /* check the path from LP fork to focus node for domain changes (destroying primal feasibility of LP basis) */
    4330 if( checkbdchgs )
    4331 {
    4332 for( d = lpstateforkdepth; d < (int)(tree->focusnode->depth) && lp->primalfeasible; ++d )
    4333 {
    4334 assert(d < tree->pathlen);
    4335 lp->primalfeasible = (tree->path[d]->domchg == NULL || tree->path[d]->domchg->domchgbound.nboundchgs == 0);
    4336 lp->primalchecked = lp->primalfeasible;
    4337 }
    4338 }
    4339 }
    4340
    4341 SCIPsetDebugMsg(set, "-> primalfeasible=%u, dualfeasible=%u\n", lp->primalfeasible, lp->dualfeasible);
    4342
    4343 return SCIP_OKAY;
    4344}
    4345
    4346
    4347
    4348
    4349/*
    4350 * Node Conversion
    4351 */
    4352
    4353/** converts node into LEAF and moves it into the array of the node queue
    4354 * if node's lower bound is greater or equal than the given upper bound, the node is deleted;
    4355 * otherwise, it is moved to the node queue; anyways, the given pointer is NULL after the call
    4356 */
    4357static
    4359 SCIP_NODE** node, /**< pointer to child or sibling node to convert */
    4360 BMS_BLKMEM* blkmem, /**< block memory buffers */
    4361 SCIP_SET* set, /**< global SCIP settings */
    4362 SCIP_STAT* stat, /**< dynamic problem statistics */
    4363 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    4364 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    4365 SCIP_TREE* tree, /**< branch and bound tree */
    4366 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4367 SCIP_LP* lp, /**< current LP data */
    4368 SCIP_NODE* lpstatefork, /**< LP state defining fork of the node */
    4369 SCIP_Real cutoffbound /**< cutoff bound: all nodes with lowerbound >= cutoffbound are cut off */
    4370 )
    4371{
    4374 assert(stat != NULL);
    4375 assert(lpstatefork == NULL || lpstatefork->depth < (*node)->depth);
    4376 assert(lpstatefork == NULL || lpstatefork->active || SCIPsetIsGE(set, (*node)->lowerbound, cutoffbound));
    4377 assert(lpstatefork == NULL
    4378 || SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_FORK
    4379 || SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_SUBROOT);
    4380
    4381#ifndef NDEBUG
    4382 /* check, if the LP state fork is the first node with LP state information on the path back to the root */
    4383 if( !SCIPsetIsInfinity(set, -cutoffbound) ) /* if the node was cut off in SCIPnodeFocus(), the lpstatefork is invalid */
    4384 {
    4385 SCIP_NODE* pathnode;
    4386 pathnode = (*node)->parent;
    4387 while( pathnode != NULL && pathnode != lpstatefork )
    4388 {
    4389 assert(SCIPnodeGetType(pathnode) == SCIP_NODETYPE_JUNCTION
    4391 pathnode = pathnode->parent;
    4392 }
    4393 assert(pathnode == lpstatefork);
    4394 }
    4395#endif
    4396
    4397 /* if node is good enough to keep, put it on the node queue */
    4398 if( (!SCIPsetIsInfinity(set, (*node)->lowerbound) && SCIPsetIsLT(set, (*node)->lowerbound, cutoffbound))
    4399 || (set->exact_enable && (*node)->lowerbound < cutoffbound) )
    4400 {
    4401 /* convert node into leaf */
    4402 SCIPsetDebugMsg(set, "convert node #%" SCIP_LONGINT_FORMAT " at depth %d to leaf with lpstatefork #%" SCIP_LONGINT_FORMAT " at depth %d\n",
    4403 SCIPnodeGetNumber(*node), SCIPnodeGetDepth(*node),
    4404 lpstatefork == NULL ? -1 : SCIPnodeGetNumber(lpstatefork),
    4405 lpstatefork == NULL ? -1 : SCIPnodeGetDepth(lpstatefork));
    4406 (*node)->nodetype = SCIP_NODETYPE_LEAF; /*lint !e641*/
    4407 (*node)->data.leaf.lpstatefork = lpstatefork;
    4408
    4409 /* insert leaf in node queue */
    4410 SCIP_CALL( SCIPnodepqInsert(tree->leaves, set, *node) );
    4411
    4412 /* make the domain change data static to save memory */
    4413 SCIP_CALL( SCIPdomchgMakeStatic(&(*node)->domchg, blkmem, set, eventqueue, lp) );
    4414
    4415 /* node is now member of the node queue: delete the pointer to forbid further access */
    4416 *node = NULL;
    4417 }
    4418 else
    4419 {
    4420 /* delete node due to bound cut off */
    4421 SCIP_CALL( SCIPnodeCutoff(*node, set, stat, eventfilter, tree, set->scip->transprob, set->scip->origprob, reopt, lp, blkmem) );
    4422 if( SCIPnodeGetType(*node) == SCIP_NODETYPE_CHILD && lpstatefork != NULL )
    4423 {
    4424 SCIP_CALL( SCIPnodeReleaseLPIState(lpstatefork, blkmem, lp) );
    4425 }
    4426 SCIP_CALL( SCIPnodeFree(node, blkmem, set, stat, eventqueue, eventfilter, tree, lp) );
    4427 }
    4428 assert(*node == NULL);
    4429
    4430 return SCIP_OKAY;
    4431}
    4432
    4433/** removes variables from the problem, that are marked to be deletable, and were created at the focusnode;
    4434 * only removes variables that were created at the focusnode, unless inlp is TRUE (e.g., when the node is cut off, anyway)
    4435 */
    4436static
    4438 BMS_BLKMEM* blkmem, /**< block memory buffers */
    4439 SCIP_SET* set, /**< global SCIP settings */
    4440 SCIP_STAT* stat, /**< dynamic problem statistics */
    4441 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    4442 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    4443 SCIP_PROB* transprob, /**< transformed problem after presolve */
    4444 SCIP_PROB* origprob, /**< original problem */
    4445 SCIP_TREE* tree, /**< branch and bound tree */
    4446 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4447 SCIP_LP* lp, /**< current LP data */
    4448 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    4449 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    4450 SCIP_Bool inlp /**< should variables in the LP be deleted, too?*/
    4451 )
    4452{
    4453 SCIP_VAR* var;
    4454 int i;
    4455 int ndelvars;
    4456 SCIP_Bool needdel;
    4457 SCIP_Bool deleted;
    4458
    4459 assert(blkmem != NULL);
    4460 assert(set != NULL);
    4461 assert(stat != NULL);
    4462 assert(tree != NULL);
    4463 assert(!SCIPtreeProbing(tree));
    4464 assert(tree->focusnode != NULL);
    4466 assert(lp != NULL);
    4467
    4468 /* check the settings, whether variables should be deleted */
    4469 needdel = (tree->focusnode == tree->root ? set->price_delvarsroot : set->price_delvars);
    4470
    4471 if( !needdel )
    4472 return SCIP_OKAY;
    4473
    4474 ndelvars = 0;
    4475
    4476 /* also delete variables currently in the LP, thus remove all new variables from the LP, first */
    4477 if( inlp )
    4478 {
    4479 /* remove all additions to the LP at this node */
    4481
    4482 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, transprob, eventqueue) );
    4483 }
    4484
    4485 /* mark variables as deleted */
    4486 for( i = 0; i < SCIPprobGetNVars(transprob); i++ )
    4487 {
    4488 var = SCIPprobGetVars(transprob)[i];
    4489 assert(var != NULL);
    4490
    4491 /* check whether variable is deletable */
    4492 if( SCIPvarIsDeletable(var) )
    4493 {
    4494 if( !SCIPvarIsInLP(var) )
    4495 {
    4496 /* fix the variable to 0, first */
    4499
    4501 {
    4502 SCIP_CALL( SCIPnodeAddBoundchg(tree->root, blkmem, set, stat, transprob, origprob,
    4503 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, 0.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
    4504 }
    4506 {
    4507 SCIP_CALL( SCIPnodeAddBoundchg(tree->root, blkmem, set, stat, transprob, origprob,
    4508 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
    4509 }
    4510
    4511 SCIP_CALL( SCIPprobDelVar(transprob, blkmem, set, eventqueue, var, &deleted) );
    4512
    4513 if( deleted )
    4514 ndelvars++;
    4515 }
    4516 else
    4517 {
    4518 /* mark variable to be non-deletable, because it will be contained in the basis information
    4519 * at this node and must not be deleted from now on
    4520 */
    4522 }
    4523 }
    4524 }
    4525
    4526 SCIPsetDebugMsg(set, "delvars at node %" SCIP_LONGINT_FORMAT ", deleted %d vars\n", stat->nnodes, ndelvars);
    4527
    4528 if( ndelvars > 0 )
    4529 {
    4530 /* perform the variable deletions from the problem */
    4531 SCIP_CALL( SCIPprobPerformVarDeletions(transprob, blkmem, set, stat, eventqueue, cliquetable, lp, branchcand) );
    4532 }
    4533
    4534 return SCIP_OKAY;
    4535}
    4536
    4537/** converts the focus node into a dead-end node */
    4538static
    4540 BMS_BLKMEM* blkmem, /**< block memory buffers */
    4541 SCIP_SET* set, /**< global SCIP settings */
    4542 SCIP_STAT* stat, /**< dynamic problem statistics */
    4543 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    4544 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    4545 SCIP_PROB* transprob, /**< transformed problem after presolve */
    4546 SCIP_PROB* origprob, /**< original problem */
    4547 SCIP_TREE* tree, /**< branch and bound tree */
    4548 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4549 SCIP_LP* lp, /**< current LP data */
    4550 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    4551 SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
    4552 )
    4553{
    4554 assert(blkmem != NULL);
    4555 assert(tree != NULL);
    4556 assert(!SCIPtreeProbing(tree));
    4557 assert(tree->focusnode != NULL);
    4559 assert(tree->nchildren == 0);
    4560
    4561 SCIPsetDebugMsg(set, "focusnode #%" SCIP_LONGINT_FORMAT " to dead-end at depth %d\n",
    4563
    4564 /* delete focus node due to cut off */
    4565 SCIP_CALL( SCIPnodeCutoff(tree->focusnode, set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
    4566
    4567 /* remove variables from the problem that are marked as deletable and were created at this node */
    4568 SCIP_CALL( focusnodeCleanupVars(blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp, branchcand, cliquetable, TRUE) );
    4569
    4570 tree->focusnode->nodetype = SCIP_NODETYPE_DEADEND; /*lint !e641*/
    4571
    4572 /* release LPI state */
    4573 if( tree->focuslpstatefork != NULL )
    4574 {
    4576 }
    4577
    4578 return SCIP_OKAY;
    4579}
    4580
    4581/** converts the focus node into a leaf node (if it was postponed) */
    4582static
    4584 BMS_BLKMEM* blkmem, /**< block memory buffers */
    4585 SCIP_SET* set, /**< global SCIP settings */
    4586 SCIP_STAT* stat, /**< dynamic problem statistics */
    4587 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    4588 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    4589 SCIP_TREE* tree, /**< branch and bound tree */
    4590 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4591 SCIP_LP* lp, /**< current LP data */
    4592 SCIP_NODE* lpstatefork, /**< LP state defining fork of the node */
    4593 SCIP_Real cutoffbound /**< cutoff bound: all nodes with lowerbound >= cutoffbound are cut off */
    4594
    4595 )
    4596{
    4597 assert(tree != NULL);
    4598 assert(!SCIPtreeProbing(tree));
    4599 assert(tree->focusnode != NULL);
    4600 assert(tree->focusnode->active);
    4602
    4603 SCIPsetDebugMsg(set, "focusnode #%" SCIP_LONGINT_FORMAT " to leaf at depth %d\n",
    4605
    4606 SCIP_CALL( nodeToLeaf(&tree->focusnode, blkmem, set, stat, eventqueue, eventfilter, tree, reopt, lp, lpstatefork, cutoffbound) );
    4607
    4608 return SCIP_OKAY;
    4609}
    4610
    4611/** converts the focus node into a junction node */
    4612static
    4614 BMS_BLKMEM* blkmem, /**< block memory buffers */
    4615 SCIP_SET* set, /**< global SCIP settings */
    4616 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    4617 SCIP_TREE* tree, /**< branch and bound tree */
    4618 SCIP_LP* lp /**< current LP data */
    4619 )
    4620{
    4621 assert(tree != NULL);
    4622 assert(!SCIPtreeProbing(tree));
    4623 assert(tree->focusnode != NULL);
    4624 assert(tree->focusnode->active); /* otherwise, no children could be created at the focus node */
    4626 assert(SCIPlpGetNNewcols(lp) == 0);
    4627
    4628 SCIPsetDebugMsg(set, "focusnode #%" SCIP_LONGINT_FORMAT " to junction at depth %d\n",
    4630
    4631 /* convert node into junction */
    4632 tree->focusnode->nodetype = SCIP_NODETYPE_JUNCTION; /*lint !e641*/
    4633
    4634 SCIP_CALL( junctionInit(&tree->focusnode->data.junction, tree) );
    4635
    4636 /* release LPI state */
    4637 if( tree->focuslpstatefork != NULL )
    4638 {
    4640 }
    4641
    4642 /* make the domain change data static to save memory */
    4643 SCIP_CALL( SCIPdomchgMakeStatic(&tree->focusnode->domchg, blkmem, set, eventqueue, lp) );
    4644
    4645 return SCIP_OKAY;
    4646}
    4647
    4648/** converts the focus node into a pseudofork node */
    4649static
    4651 BMS_BLKMEM* blkmem, /**< block memory buffers */
    4652 SCIP_SET* set, /**< global SCIP settings */
    4653 SCIP_STAT* stat, /**< dynamic problem statistics */
    4654 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    4655 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    4656 SCIP_PROB* transprob, /**< transformed problem after presolve */
    4657 SCIP_PROB* origprob, /**< original problem */
    4658 SCIP_TREE* tree, /**< branch and bound tree */
    4659 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4660 SCIP_LP* lp, /**< current LP data */
    4661 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    4662 SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
    4663 )
    4664{
    4665 SCIP_PSEUDOFORK* pseudofork;
    4666
    4667 assert(blkmem != NULL);
    4668 assert(tree != NULL);
    4669 assert(!SCIPtreeProbing(tree));
    4670 assert(tree->focusnode != NULL);
    4671 assert(tree->focusnode->active); /* otherwise, no children could be created at the focus node */
    4673 assert(tree->nchildren > 0);
    4674 assert(lp != NULL);
    4675
    4676 SCIPsetDebugMsg(set, "focusnode #%" SCIP_LONGINT_FORMAT " to pseudofork at depth %d\n",
    4678
    4679 /* remove variables from the problem that are marked as deletable and were created at this node */
    4680 SCIP_CALL( focusnodeCleanupVars(blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp, branchcand, cliquetable, FALSE) );
    4681
    4682 /* create pseudofork data */
    4683 SCIP_CALL( pseudoforkCreate(&pseudofork, blkmem, tree, lp) );
    4684
    4685 tree->focusnode->nodetype = SCIP_NODETYPE_PSEUDOFORK; /*lint !e641*/
    4686 tree->focusnode->data.pseudofork = pseudofork;
    4687
    4688 /* release LPI state */
    4689 if( tree->focuslpstatefork != NULL )
    4690 {
    4692 }
    4693
    4694 /* make the domain change data static to save memory */
    4695 SCIP_CALL( SCIPdomchgMakeStatic(&tree->focusnode->domchg, blkmem, set, eventqueue, lp) );
    4696
    4697 return SCIP_OKAY;
    4698}
    4699
    4700/** converts the focus node into a fork node */
    4701static
    4703 BMS_BLKMEM* blkmem, /**< block memory buffers */
    4704 SCIP_SET* set, /**< global SCIP settings */
    4705 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
    4706 SCIP_STAT* stat, /**< dynamic problem statistics */
    4707 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    4708 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    4709 SCIP_PROB* transprob, /**< transformed problem after presolve */
    4710 SCIP_PROB* origprob, /**< original problem */
    4711 SCIP_TREE* tree, /**< branch and bound tree */
    4712 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4713 SCIP_LP* lp, /**< current LP data */
    4714 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    4715 SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
    4716 )
    4717{
    4718 SCIP_FORK* fork;
    4719 SCIP_Bool lperror;
    4720
    4721 assert(blkmem != NULL);
    4722 assert(tree != NULL);
    4723 assert(!SCIPtreeProbing(tree));
    4724 assert(tree->focusnode != NULL);
    4725 assert(tree->focusnode->active); /* otherwise, no children could be created at the focus node */
    4727 assert(tree->nchildren > 0);
    4728 assert(lp != NULL);
    4729 assert(lp->flushed);
    4730 assert(lp->solved || lp->resolvelperror);
    4731
    4732 SCIPsetDebugMsg(set, "focusnode #%" SCIP_LONGINT_FORMAT " to fork at depth %d\n",
    4734
    4735 /* usually, the LP should be solved to optimality; otherwise, numerical troubles occured,
    4736 * and we have to forget about the LP and transform the node into a junction (see below)
    4737 */
    4738 lperror = FALSE;
    4740 {
    4741 /* clean up newly created part of LP to keep only necessary columns and rows */
    4742 SCIP_CALL( SCIPlpCleanupNew(lp, blkmem, set, stat, eventqueue, eventfilter, (tree->focusnode->depth == 0)) );
    4743
    4744 /* resolve LP after cleaning up */
    4745 SCIPsetDebugMsg(set, "resolving LP after cleanup\n");
    4746 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, TRUE, FALSE, &lperror) );
    4747 }
    4748 assert(lp->flushed);
    4749 assert(lp->solved || lperror || lp->resolvelperror);
    4750
    4751 /* There are two reasons, that the (reduced) LP is not solved to optimality:
    4752 * - The primal heuristics (called after the current node's LP was solved) found a new
    4753 * solution, that is better than the current node's lower bound.
    4754 * (But in this case, all children should be cut off and the node should be converted
    4755 * into a dead-end instead of a fork.)
    4756 * - Something numerically weird happened after cleaning up or after resolving a diving or probing LP.
    4757 * The only thing we can do, is to completely forget about the LP and treat the node as
    4758 * if it was only a pseudo-solution node. Therefore we have to remove all additional
    4759 * columns and rows from the LP and convert the node into a junction.
    4760 * However, the node's lower bound is kept, thus automatically throwing away nodes that
    4761 * were cut off due to a primal solution.
    4762 */
    4763 if( lperror || lp->resolvelperror || SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_OPTIMAL )
    4764 {
    4765 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
    4766 "(node %" SCIP_LONGINT_FORMAT ") numerical troubles: LP %" SCIP_LONGINT_FORMAT " not optimal -- convert node into junction instead of fork\n",
    4767 stat->nnodes, stat->nlps);
    4768
    4769 /* remove all additions to the LP at this node */
    4771 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, SCIPlpGetNRows(lp) - SCIPlpGetNNewrows(lp)) );
    4772
    4773 /* convert node into a junction */
    4774 SCIP_CALL( focusnodeToJunction(blkmem, set, eventqueue, tree, lp) );
    4775
    4776 return SCIP_OKAY;
    4777 }
    4778 assert(lp->flushed);
    4779 assert(lp->solved);
    4781
    4782 /* remove variables from the problem that are marked as deletable, were created at this node and are not contained in the LP */
    4783 SCIP_CALL( focusnodeCleanupVars(blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp, branchcand, cliquetable, FALSE) );
    4784
    4785 assert(lp->flushed);
    4786 assert(lp->solved);
    4787
    4788 /* create fork data */
    4789 SCIP_CALL( forkCreate(&fork, blkmem, set, transprob, tree, lp) );
    4790
    4791 tree->focusnode->nodetype = SCIP_NODETYPE_FORK; /*lint !e641*/
    4792 tree->focusnode->data.fork = fork;
    4793
    4794 /* capture the LPI state of the root node to ensure that the LPI state of the root stays for the whole solving
    4795 * process
    4796 */
    4797 if( tree->focusnode == tree->root )
    4798 forkCaptureLPIState(fork, 1);
    4799
    4800 /* release LPI state */
    4801 if( tree->focuslpstatefork != NULL )
    4802 {
    4804 }
    4805
    4806 /* make the domain change data static to save memory */
    4807 SCIP_CALL( SCIPdomchgMakeStatic(&tree->focusnode->domchg, blkmem, set, eventqueue, lp) );
    4808
    4809 return SCIP_OKAY;
    4810}
    4811
    4812#ifdef WITHSUBROOTS /** @todo test whether subroots should be created */
    4813/** converts the focus node into a subroot node */
    4814static
    4815SCIP_RETCODE focusnodeToSubroot(
    4816 BMS_BLKMEM* blkmem, /**< block memory buffers */
    4817 SCIP_SET* set, /**< global SCIP settings */
    4818 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
    4819 SCIP_STAT* stat, /**< dynamic problem statistics */
    4820 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    4821 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    4822 SCIP_PROB* transprob, /**< transformed problem after presolve */
    4823 SCIP_PROB* origprob, /**< original problem */
    4824 SCIP_TREE* tree, /**< branch and bound tree */
    4825 SCIP_LP* lp, /**< current LP data */
    4826 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    4827 SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
    4828 )
    4829{
    4830 SCIP_SUBROOT* subroot;
    4831 SCIP_Bool lperror;
    4832
    4833 assert(blkmem != NULL);
    4834 assert(tree != NULL);
    4835 assert(!SCIPtreeProbing(tree));
    4836 assert(tree->focusnode != NULL);
    4838 assert(tree->focusnode->active); /* otherwise, no children could be created at the focus node */
    4839 assert(tree->nchildren > 0);
    4840 assert(lp != NULL);
    4841 assert(lp->flushed);
    4842 assert(lp->solved);
    4843
    4844 SCIPsetDebugMsg(set, "focusnode #%" SCIP_LONGINT_FORMAT " to subroot at depth %d\n",
    4846
    4847 /* usually, the LP should be solved to optimality; otherwise, numerical troubles occured,
    4848 * and we have to forget about the LP and transform the node into a junction (see below)
    4849 */
    4850 lperror = FALSE;
    4852 {
    4853 /* clean up whole LP to keep only necessary columns and rows */
    4854#ifdef SCIP_DISABLED_CODE
    4855 if( tree->focusnode->depth == 0 )
    4856 {
    4857 SCIP_CALL( SCIPlpCleanupAll(lp, blkmem, set, stat, eventqueue, eventfilter, (tree->focusnode->depth == 0)) );
    4858 }
    4859 else
    4860#endif
    4861 {
    4862 SCIP_CALL( SCIPlpRemoveAllObsoletes(lp, blkmem, set, stat, eventqueue, eventfilter) );
    4863 }
    4864
    4865 /* resolve LP after cleaning up */
    4866 SCIPsetDebugMsg(set, "resolving LP after cleanup\n");
    4867 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, TRUE, FALSE, &lperror) );
    4868 }
    4869 assert(lp->flushed);
    4870 assert(lp->solved || lperror);
    4871
    4872 /* There are two reasons, that the (reduced) LP is not solved to optimality:
    4873 * - The primal heuristics (called after the current node's LP was solved) found a new
    4874 * solution, that is better than the current node's lower bound.
    4875 * (But in this case, all children should be cut off and the node should be converted
    4876 * into a dead-end instead of a subroot.)
    4877 * - Something numerically weird happened after cleaning up.
    4878 * The only thing we can do, is to completely forget about the LP and treat the node as
    4879 * if it was only a pseudo-solution node. Therefore we have to remove all additional
    4880 * columns and rows from the LP and convert the node into a junction.
    4881 * However, the node's lower bound is kept, thus automatically throwing away nodes that
    4882 * were cut off due to a primal solution.
    4883 */
    4884 if( lperror || SCIPlpGetSolstat(lp) != SCIP_LPSOLSTAT_OPTIMAL )
    4885 {
    4886 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
    4887 "(node %" SCIP_LONGINT_FORMAT ") numerical troubles: LP %" SCIP_LONGINT_FORMAT " not optimal -- convert node into junction instead of subroot\n",
    4888 stat->nnodes, stat->nlps);
    4889
    4890 /* remove all additions to the LP at this node */
    4892 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, SCIPlpGetNRows(lp) - SCIPlpGetNNewrows(lp)) );
    4893
    4894 /* convert node into a junction */
    4895 SCIP_CALL( focusnodeToJunction(blkmem, set, eventqueue, tree, lp) );
    4896
    4897 return SCIP_OKAY;
    4898 }
    4899 assert(lp->flushed);
    4900 assert(lp->solved);
    4902
    4903 /* remove variables from the problem that are marked as deletable, were created at this node and are not contained in the LP */
    4904 SCIP_CALL( focusnodeCleanupVars(blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, lp, branchcand, cliquetable, FALSE) );
    4905
    4906 assert(lp->flushed);
    4907 assert(lp->solved);
    4908
    4909 /* create subroot data */
    4910 SCIP_CALL( subrootCreate(&subroot, blkmem, set, transprob, tree, lp) );
    4911
    4912 tree->focusnode->nodetype = SCIP_NODETYPE_SUBROOT; /*lint !e641*/
    4913 tree->focusnode->data.subroot = subroot;
    4914
    4915 /* update the LP column and row counter for the converted node */
    4917
    4918 /* release LPI state */
    4919 if( tree->focuslpstatefork != NULL )
    4920 {
    4922 }
    4923
    4924 /* make the domain change data static to save memory */
    4925 SCIP_CALL( SCIPdomchgMakeStatic(&tree->focusnode->domchg, blkmem, set, eventqueue, lp) );
    4926
    4927 return SCIP_OKAY;
    4928}
    4929#endif
    4930
    4931/** puts all nodes in the array on the node queue and makes them LEAFs */
    4932static
    4934 SCIP_TREE* tree, /**< branch and bound tree */
    4935 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4936 BMS_BLKMEM* blkmem, /**< block memory buffers */
    4937 SCIP_SET* set, /**< global SCIP settings */
    4938 SCIP_STAT* stat, /**< dynamic problem statistics */
    4939 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    4940 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    4941 SCIP_LP* lp, /**< current LP data */
    4942 SCIP_NODE** nodes, /**< array of nodes to put on the queue */
    4943 int* nnodes, /**< pointer to number of nodes in the array */
    4944 SCIP_NODE* lpstatefork, /**< LP state defining fork of the nodes */
    4945 SCIP_Real cutoffbound /**< cutoff bound: all nodes with lowerbound >= cutoffbound are cut off */
    4946 )
    4947{
    4948 assert(tree != NULL);
    4949 assert(set != NULL);
    4950 assert(nnodes != NULL);
    4951 assert(*nnodes == 0 || nodes != NULL);
    4952
    4953 /* as long as the node array has slots */
    4954 while( *nnodes >= 1 )
    4955 {
    4956 /* convert last node to LEAF and put it into leaves queue, or delete it if its lower bound exceeds the cutoff bound */
    4957 if( nodes[*nnodes-1] != NULL )
    4958 {
    4959 SCIP_CALL( nodeToLeaf(&nodes[*nnodes-1], blkmem, set, stat, eventqueue, eventfilter, tree, reopt, lp, lpstatefork, cutoffbound) );
    4960 }
    4961 else
    4962 --(*nnodes);
    4963 }
    4964
    4965 return SCIP_OKAY;
    4966}
    4967
    4968/** converts children into siblings, clears children array */
    4969static
    4971 SCIP_TREE* tree /**< branch and bound tree */
    4972 )
    4973{
    4974 SCIP_NODE** tmpnodes;
    4975 SCIP_Real* tmpprios;
    4976 int tmpnodessize;
    4977 int i;
    4978
    4979 assert(tree != NULL);
    4980 assert(tree->nsiblings == 0);
    4981
    4982 tmpnodes = tree->siblings;
    4983 tmpprios = tree->siblingsprio;
    4984 tmpnodessize = tree->siblingssize;
    4985
    4986 tree->siblings = tree->children;
    4987 tree->siblingsprio = tree->childrenprio;
    4988 tree->nsiblings = tree->nchildren;
    4989 tree->siblingssize = tree->childrensize;
    4990
    4991 tree->children = tmpnodes;
    4992 tree->childrenprio = tmpprios;
    4993 tree->nchildren = 0;
    4994 tree->childrensize = tmpnodessize;
    4995
    4996 for( i = 0; i < tree->nsiblings; ++i )
    4997 {
    4998 assert(SCIPnodeGetType(tree->siblings[i]) == SCIP_NODETYPE_CHILD);
    4999 tree->siblings[i]->nodetype = SCIP_NODETYPE_SIBLING; /*lint !e641*/
    5000
    5001 /* because CHILD and SIBLING structs contain the same data in the same order, we do not have to copy it */
    5002 assert(&(tree->siblings[i]->data.sibling.arraypos) == &(tree->siblings[i]->data.child.arraypos));
    5003 }
    5004}
    5005
    5006/** installs a child, a sibling, or a leaf node as the new focus node */
    5008 SCIP_NODE** node, /**< pointer to node to focus (or NULL to remove focus); the node
    5009 * is freed, if it was cut off due to a cut off subtree */
    5010 BMS_BLKMEM* blkmem, /**< block memory buffers */
    5011 SCIP_SET* set, /**< global SCIP settings */
    5012 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
    5013 SCIP_STAT* stat, /**< problem statistics */
    5014 SCIP_PROB* transprob, /**< transformed problem */
    5015 SCIP_PROB* origprob, /**< original problem */
    5016 SCIP_PRIMAL* primal, /**< primal data */
    5017 SCIP_TREE* tree, /**< branch and bound tree */
    5018 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5019 SCIP_LP* lp, /**< current LP data */
    5020 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    5021 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    5022 SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
    5023 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    5024 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    5025 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    5026 SCIP_Bool* cutoff, /**< pointer to store whether the given node can be cut off */
    5027 SCIP_Bool postponed, /**< was the current focus node postponed? */
    5028 SCIP_Bool exitsolve /**< are we in exitsolve stage, so we only need to loose the children */
    5029 )
    5030{ /*lint --e{715}*/
    5031 SCIP_NODE* fork;
    5032 SCIP_NODE* lpfork;
    5033 SCIP_NODE* lpstatefork;
    5034 SCIP_NODE* subroot;
    5035 SCIP_NODE* childrenlpstatefork;
    5036
    5037 assert(node != NULL);
    5038 assert(*node == NULL
    5041 || SCIPnodeGetType(*node) == SCIP_NODETYPE_LEAF);
    5042 assert(*node == NULL || !(*node)->active);
    5043 assert(stat != NULL);
    5044 assert(primal != NULL);
    5045 assert(tree != NULL);
    5046 assert(!SCIPtreeProbing(tree));
    5047 assert(lp != NULL);
    5048 assert(conflictstore != NULL);
    5049 assert(cutoff != NULL);
    5050
    5051 /* check global lower bound w.r.t. debugging solution */
    5053
    5054 /* check local lower bound w.r.t. debugging solution */
    5055 SCIP_CALL( SCIPdebugCheckLocalLowerbound(blkmem, set, *node) );
    5056
    5057 SCIPsetDebugMsg(set, "focusing node #%" SCIP_LONGINT_FORMAT " of type %d in depth %d\n",
    5058 *node != NULL ? SCIPnodeGetNumber(*node) : -1, *node != NULL ? (int)SCIPnodeGetType(*node) : 0,
    5059 *node != NULL ? SCIPnodeGetDepth(*node) : -1);
    5060
    5061 /* find the common fork node, the new LP defining fork, and the new focus subroot,
    5062 * thereby checking, if the new node can be cut off
    5063 */
    5064 treeFindSwitchForks(tree, *node, &fork, &lpfork, &lpstatefork, &subroot, cutoff);
    5065 SCIPsetDebugMsg(set, "focus node: focusnodedepth=%ld, forkdepth=%ld, lpforkdepth=%ld, lpstateforkdepth=%ld, subrootdepth=%ld, cutoff=%u\n",
    5066 *node != NULL ? (long)((*node)->depth) : -1, fork != NULL ? (long)(fork->depth) : -1, /*lint !e705 */
    5067 lpfork != NULL ? (long)(lpfork->depth) : -1, lpstatefork != NULL ? (long)(lpstatefork->depth) : -1, /*lint !e705 */
    5068 subroot != NULL ? (long)(subroot->depth) : -1, *cutoff); /*lint !e705 */
    5069
    5070 /* free the new node, if it is located in a cut off subtree */
    5071 if( *cutoff )
    5072 {
    5073 SCIP_Real lowerbound;
    5074
    5075 assert(*node != NULL);
    5076
    5077 /* cut off node */
    5078 if( SCIPnodeGetType(*node) == SCIP_NODETYPE_LEAF )
    5079 {
    5080 assert(!(*node)->active);
    5081 assert((*node)->depth != 0 || tree->focusnode == NULL);
    5082
    5083 SCIPsetDebugMsg(set, "cutting off leaf node #%lld (queuelen=%d) at depth %d with lowerbound=%g\n",
    5085
    5086 /* check if the node should be stored for reoptimization */
    5087 if( set->reopt_enable )
    5088 {
    5090 SCIPlpGetSolstat(lp), tree->root == *node, FALSE, (*node)->lowerbound, tree->effectiverootdepth) );
    5091 }
    5092
    5093 /* remove node from the queue */
    5094 SCIP_CALL( SCIPnodepqRemove(tree->leaves, set, *node) );
    5095
    5096 (*node)->cutoff = TRUE;
    5097 if( set->exact_enable )
    5098 SCIPrationalSetInfinity((*node)->lowerboundexact);
    5099 (*node)->lowerbound = SCIPsetInfinity(set);
    5100 (*node)->estimate = SCIPsetInfinity(set);
    5101
    5102 if( (*node)->depth == 0 )
    5104
    5105 if( set->exact_enable )
    5106 {
    5107 SCIP_RATIONAL* lowerboundexact = SCIPtreeGetLowerboundExact(tree, set);
    5108
    5109 assert(SCIPrationalIsGEReal(lowerboundexact, SCIPtreeGetLowerbound(tree, set)));
    5110
    5111 /* exact lower bound improved */
    5112 if( SCIPrationalIsLT(stat->lastlowerboundexact, lowerboundexact) )
    5113 {
    5114 /* throw improvement event if upper bound not already exceeded */
    5116 {
    5117 SCIP_EVENT event;
    5118
    5120 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
    5121 }
    5122
    5123 /* update exact last lower bound */
    5124 SCIPrationalSetRational(stat->lastlowerboundexact, lowerboundexact);
    5125 }
    5126 }
    5127
    5128 lowerbound = SCIPtreeGetLowerbound(tree, set);
    5129 assert(lowerbound <= SCIPsetInfinity(set));
    5130
    5131 /* lower bound improved */
    5132 if( stat->lastlowerbound < lowerbound )
    5133 {
    5134 /* throw improvement event if not already done exactly */
    5135 if( !set->exact_enable && stat->lastlowerbound < primal->upperbound )
    5136 {
    5137 SCIP_EVENT event;
    5138
    5140 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
    5141 }
    5142
    5143 /* update primal-dual integrals */
    5144 if( set->misc_calcintegral )
    5145 {
    5146 SCIPstatUpdatePrimalDualIntegrals(stat, set, transprob, origprob, SCIPsetInfinity(set), lowerbound);
    5147 assert(stat->lastlowerbound == lowerbound); /*lint !e777*/
    5148 }
    5149 else
    5150 stat->lastlowerbound = lowerbound;
    5151 }
    5152
    5153 SCIPvisualCutoffNode(stat->visual, set, stat, *node, TRUE);
    5154 }
    5155 else
    5156 {
    5157 SCIP_CALL( SCIPnodeCutoff(*node, set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
    5158 }
    5159
    5160 /* free node memory */
    5161 SCIP_CALL( SCIPnodeFree(node, blkmem, set, stat, eventqueue, eventfilter, tree, lp) );
    5162
    5163 return SCIP_OKAY;
    5164 }
    5165
    5166 assert(fork == NULL || fork->active);
    5167 assert(lpstatefork == NULL || lpfork != NULL);
    5168 assert(subroot == NULL || lpstatefork != NULL);
    5169
    5170 /* remember the depth of the common fork node for LP updates */
    5171 SCIPsetDebugMsg(set, "focus node: old correctlpdepth=%d\n", tree->correctlpdepth);
    5172 if( subroot == tree->focussubroot && fork != NULL && lpfork != NULL )
    5173 {
    5174 /* we are in the same subtree with valid LP fork: the LP is correct at most upto the common fork depth */
    5175 assert(subroot == NULL || subroot->active);
    5176 tree->correctlpdepth = MIN(tree->correctlpdepth, (int)fork->depth);
    5177 }
    5178 else
    5179 {
    5180 /* we are in a different subtree, or no valid LP fork exists: the LP is completely incorrect */
    5181 assert(subroot == NULL || !subroot->active
    5182 || (tree->focussubroot != NULL && tree->focussubroot->depth > subroot->depth));
    5183 tree->correctlpdepth = -1;
    5184 }
    5185
    5186 /* if the LP state fork changed, the lpcount information for the new LP state fork is unknown */
    5187 if( lpstatefork != tree->focuslpstatefork )
    5188 tree->focuslpstateforklpcount = -1;
    5189
    5190 /* in exitsolve we only need to take care of open children
    5191 *
    5192 * @note because we might do a 'newstart' and converted cuts to constraints might have rendered the LP in the current
    5193 * focusnode unsolved the latter code would have resolved the LP unnecessarily
    5194 */
    5195 if( exitsolve && tree->nchildren > 0 )
    5196 {
    5197 SCIPsetDebugMsg(set, " -> deleting the %d children (in exitsolve) of the old focus node\n", tree->nchildren);
    5198 SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, eventfilter, lp, tree->children, &tree->nchildren, NULL, -SCIPsetInfinity(set)) );
    5199 assert(tree->nchildren == 0);
    5200 }
    5201
    5202 /* if the old focus node was cut off, we can delete its children;
    5203 * if the old focus node's parent was cut off, we can also delete the focus node's siblings
    5204 */
    5205 /* coverity[var_compare_op] */
    5206 if( tree->focusnode != NULL && tree->cutoffdepth <= tree->focusnode->depth )
    5207 {
    5208 SCIPsetDebugMsg(set, "path to old focus node of depth %u was cut off at depth %d\n", tree->focusnode->depth, tree->cutoffdepth);
    5209
    5210 /* delete the focus node's children by converting them to leaves with a cutoffbound of -SCIPsetInfinity(set);
    5211 * we cannot delete them directly, because in SCIPnodeFree(), the children array is changed, which is the
    5212 * same array we would have to iterate over here;
    5213 * the children don't have an LP fork, because the old focus node is not yet converted into a fork or subroot
    5214 */
    5215 SCIPsetDebugMsg(set, " -> deleting the %d children of the old focus node\n", tree->nchildren);
    5216 SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, eventfilter, lp, tree->children, &tree->nchildren, NULL, -SCIPsetInfinity(set)) );
    5217 assert(tree->nchildren == 0);
    5218
    5219 if( tree->cutoffdepth < tree->focusnode->depth )
    5220 {
    5221 /* delete the focus node's siblings by converting them to leaves with a cutoffbound of -SCIPsetInfinity(set);
    5222 * we cannot delete them directly, because in SCIPnodeFree(), the siblings array is changed, which is the
    5223 * same array we would have to iterate over here;
    5224 * the siblings have the same LP state fork as the old focus node
    5225 */
    5226 SCIPsetDebugMsg(set, " -> deleting the %d siblings of the old focus node\n", tree->nsiblings);
    5227 SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, eventfilter, lp, tree->siblings, &tree->nsiblings, tree->focuslpstatefork,
    5228 -SCIPsetInfinity(set)) );
    5229 assert(tree->nsiblings == 0);
    5230 }
    5231 }
    5232
    5233 /* convert the old focus node into a fork or subroot node, if it has children;
    5234 * otherwise, convert it into a dead-end, which will be freed later in treeSwitchPath();
    5235 * if the node was postponed, make it a leaf.
    5236 */
    5237 childrenlpstatefork = tree->focuslpstatefork;
    5238
    5239 assert(!postponed || *node == NULL);
    5240 assert(!postponed || tree->focusnode != NULL);
    5241
    5242 if( postponed )
    5243 {
    5244 assert(tree->nchildren == 0);
    5245 assert(*node == NULL);
    5246
    5247 /* if the node is infeasible, convert it into a dead-end; otherwise, put it into the LEAF queue */
    5248 if( SCIPsetIsGE(set, tree->focusnode->lowerbound, primal->cutoffbound) )
    5249 {
    5250 /* in case the LP was not constructed (due to the parameter settings for example) we have the finally remember the
    5251 * old size of the LP (if it was constructed in an earlier node) before we change the current node into a dead-end
    5252 */
    5253 if( !tree->focuslpconstructed )
    5254 SCIPlpMarkSize(lp);
    5255
    5256 /* convert old focus node into dead-end */
    5257 SCIP_CALL( focusnodeToDeadend(blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp,
    5258 branchcand, cliquetable) );
    5259 }
    5260 else
    5261 {
    5262 SCIP_CALL( focusnodeToLeaf(blkmem, set, stat, eventqueue, eventfilter, tree, reopt, lp, tree->focuslpstatefork,
    5263 SCIPsetInfinity(set)) );
    5264 }
    5265 }
    5266 else if( tree->nchildren > 0 )
    5267 {
    5268 SCIP_Bool selectedchild;
    5269 int c;
    5270
    5271 assert(tree->focusnode != NULL);
    5273
    5274 /* update exact lower bound of focus */
    5275 if( set->exact_enable )
    5276 {
    5277 SCIP_RATIONAL* focuslowerboundexact;
    5278 SCIP_RATIONAL* childlowerboundexact;
    5279
    5280 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &focuslowerboundexact) );
    5281 SCIPrationalSetInfinity(focuslowerboundexact);
    5282
    5283 for( c = 0; c < tree->nchildren; ++c )
    5284 {
    5285 childlowerboundexact = SCIPnodeGetLowerboundExact(tree->children[c]);
    5286 if( SCIPrationalIsGT(focuslowerboundexact, childlowerboundexact) )
    5287 SCIPrationalSetRational(focuslowerboundexact, childlowerboundexact);
    5288 }
    5289
    5290 SCIP_CALL( SCIPnodeUpdateLowerbound(tree->focusnode, stat, set, eventfilter, tree, transprob, origprob, SCIP_INVALID, focuslowerboundexact) );
    5291 SCIPrationalFreeBlock(blkmem, &focuslowerboundexact);
    5292 }
    5293 /* update real lower bound of focus */
    5294 else
    5295 {
    5296 SCIP_Real focuslowerbound;
    5297 SCIP_Real childlowerbound;
    5298
    5299 focuslowerbound = SCIPsetInfinity(set);
    5300
    5301 for( c = 0; c < tree->nchildren; ++c )
    5302 {
    5303 childlowerbound = SCIPnodeGetLowerbound(tree->children[c]);
    5304 if( focuslowerbound > childlowerbound )
    5305 focuslowerbound = childlowerbound;
    5306 }
    5307
    5308 SCIP_CALL( SCIPnodeUpdateLowerbound(tree->focusnode, stat, set, eventfilter, tree, transprob, origprob, focuslowerbound, NULL) );
    5309 }
    5310
    5311 /* check whether the next focus node is a child of the old focus node */
    5312 selectedchild = (*node != NULL && SCIPnodeGetType(*node) == SCIP_NODETYPE_CHILD);
    5313
    5314 if( tree->focusnodehaslp && lp->isrelax )
    5315 {
    5316 assert(tree->focuslpconstructed);
    5317
    5318#ifdef WITHSUBROOTS /** @todo test whether subroots should be created, decide: old focus node becomes fork or subroot */
    5319 if( tree->focusnode->depth > 0 && tree->focusnode->depth % 25 == 0 )
    5320 {
    5321 /* convert old focus node into a subroot node */
    5322 SCIP_CALL( focusnodeToSubroot(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, origprob, tree, lp, branchcand) );
    5323 if( *node != NULL && SCIPnodeGetType(*node) == SCIP_NODETYPE_CHILD
    5325 subroot = tree->focusnode;
    5326 }
    5327 else
    5328#endif
    5329 {
    5330 /* convert old focus node into a fork node */
    5331 SCIP_CALL( focusnodeToFork(blkmem, set, messagehdlr, stat, eventqueue, eventfilter, transprob, origprob, tree,
    5332 reopt, lp, branchcand, cliquetable) );
    5333 }
    5334
    5335 /* check, if the conversion into a subroot or fork was successful */
    5338 {
    5339 childrenlpstatefork = tree->focusnode;
    5340
    5341 /* if a child of the old focus node was selected as new focus node, the old node becomes the new focus
    5342 * LP fork and LP state fork
    5343 */
    5344 if( selectedchild )
    5345 {
    5346 lpfork = tree->focusnode;
    5347 tree->correctlpdepth = (int) tree->focusnode->depth;
    5348 lpstatefork = tree->focusnode;
    5349 tree->focuslpstateforklpcount = stat->lpcount;
    5350 }
    5351 }
    5352
    5353 /* update the path's LP size */
    5354 tree->pathnlpcols[tree->focusnode->depth] = SCIPlpGetNCols(lp);
    5355 tree->pathnlprows[tree->focusnode->depth] = SCIPlpGetNRows(lp);
    5356 }
    5357 else if( tree->focuslpconstructed && (SCIPlpGetNNewcols(lp) > 0 || SCIPlpGetNNewrows(lp) > 0) )
    5358 {
    5359 /* convert old focus node into pseudofork */
    5360 SCIP_CALL( focusnodeToPseudofork(blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree,
    5361 reopt, lp, branchcand, cliquetable) );
    5363
    5364 /* update the path's LP size */
    5365 tree->pathnlpcols[tree->focusnode->depth] = SCIPlpGetNCols(lp);
    5366 tree->pathnlprows[tree->focusnode->depth] = SCIPlpGetNRows(lp);
    5367
    5368 /* if a child of the old focus node was selected as new focus node, the old node becomes the new focus LP fork */
    5369 if( selectedchild )
    5370 {
    5371 lpfork = tree->focusnode;
    5372 tree->correctlpdepth = (int) tree->focusnode->depth;
    5373 }
    5374 }
    5375 else
    5376 {
    5377 /* in case the LP was not constructed (due to the parameter settings for example) we have the finally remember the
    5378 * old size of the LP (if it was constructed in an earlier node) before we change the current node into a junction
    5379 */
    5380 SCIPlpMarkSize(lp);
    5381
    5382 /* convert old focus node into junction */
    5383 SCIP_CALL( focusnodeToJunction(blkmem, set, eventqueue, tree, lp) );
    5384 }
    5385 }
    5386 else if( tree->focusnode != NULL )
    5387 {
    5388 /* in case the LP was not constructed (due to the parameter settings for example) we have the finally remember the
    5389 * old size of the LP (if it was constructed in an earlier node) before we change the current node into a dead-end
    5390 */
    5391 if( !tree->focuslpconstructed )
    5392 SCIPlpMarkSize(lp);
    5393
    5394 /* convert old focus node into dead-end */
    5395 SCIP_CALL( focusnodeToDeadend(blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp, branchcand, cliquetable) );
    5396 }
    5397 assert(subroot == NULL || SCIPnodeGetType(subroot) == SCIP_NODETYPE_SUBROOT);
    5398 assert(lpstatefork == NULL
    5399 || SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_SUBROOT
    5400 || SCIPnodeGetType(lpstatefork) == SCIP_NODETYPE_FORK);
    5401 assert(childrenlpstatefork == NULL
    5402 || SCIPnodeGetType(childrenlpstatefork) == SCIP_NODETYPE_SUBROOT
    5403 || SCIPnodeGetType(childrenlpstatefork) == SCIP_NODETYPE_FORK);
    5404 assert(lpfork == NULL
    5408 SCIPsetDebugMsg(set, "focus node: new correctlpdepth=%d\n", tree->correctlpdepth);
    5409
    5410 /* set up the new lists of siblings and children */
    5411 if( *node == NULL )
    5412 {
    5413 /* move siblings to the queue, make them LEAFs */
    5414 SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, eventfilter, lp, tree->siblings, &tree->nsiblings, tree->focuslpstatefork,
    5415 primal->cutoffbound) );
    5416
    5417 /* move children to the queue, make them LEAFs */
    5418 SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, eventfilter, lp, tree->children, &tree->nchildren, childrenlpstatefork,
    5419 primal->cutoffbound) );
    5420 }
    5421 else
    5422 {
    5423 SCIP_NODE* bestleaf;
    5424
    5425 switch( SCIPnodeGetType(*node) )
    5426 {
    5428 /* reset plunging depth, if the selected node is better than all leaves */
    5429 bestleaf = SCIPtreeGetBestLeaf(tree);
    5430 if( bestleaf == NULL || SCIPnodepqCompare(tree->leaves, set, *node, bestleaf) <= 0 )
    5431 stat->plungedepth = 0;
    5432
    5433 /* move children to the queue, make them LEAFs */
    5434 SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, eventfilter, lp, tree->children, &tree->nchildren, childrenlpstatefork,
    5435 primal->cutoffbound) );
    5436
    5437 /* remove selected sibling from the siblings array */
    5438 treeRemoveSibling(tree, *node);
    5439
    5440 SCIPsetDebugMsg(set, "selected sibling node, lowerbound=%g, plungedepth=%d\n", (*node)->lowerbound, stat->plungedepth);
    5441 break;
    5442
    5444 /* reset plunging depth, if the selected node is better than all leaves; otherwise, increase plunging depth */
    5445 bestleaf = SCIPtreeGetBestLeaf(tree);
    5446 if( bestleaf == NULL || SCIPnodepqCompare(tree->leaves, set, *node, bestleaf) <= 0 )
    5447 stat->plungedepth = 0;
    5448 else
    5449 stat->plungedepth++;
    5450
    5451 /* move siblings to the queue, make them LEAFs */
    5452 SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, eventfilter, lp, tree->siblings, &tree->nsiblings, tree->focuslpstatefork,
    5453 primal->cutoffbound) );
    5454
    5455 /* remove selected child from the children array */
    5456 treeRemoveChild(tree, *node);
    5457
    5458 /* move remaining children to the siblings array, make them SIBLINGs */
    5460
    5461 SCIPsetDebugMsg(set, "selected child node, lowerbound=%g, plungedepth=%d\n", (*node)->lowerbound, stat->plungedepth);
    5462 break;
    5463
    5464 case SCIP_NODETYPE_LEAF:
    5465 /* move siblings to the queue, make them LEAFs */
    5466 SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, eventfilter, lp, tree->siblings, &tree->nsiblings, tree->focuslpstatefork,
    5467 primal->cutoffbound) );
    5468
    5469 /* encounter an early backtrack if there is a child which does not exceed given reference bound */
    5470 if( !SCIPsetIsInfinity(set, stat->referencebound) )
    5471 {
    5472 int c;
    5473
    5474 /* loop over children and stop if we find a child with a lower bound below given reference bound */
    5475 for( c = 0; c < tree->nchildren; ++c )
    5476 {
    5478 {
    5479 ++stat->nearlybacktracks;
    5480 break;
    5481 }
    5482 }
    5483 }
    5484 /* move children to the queue, make them LEAFs */
    5485 SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, eventfilter, lp, tree->children, &tree->nchildren, childrenlpstatefork,
    5486 primal->cutoffbound) );
    5487
    5488 /* remove node from the queue */
    5489 SCIP_CALL( SCIPnodepqRemove(tree->leaves, set, *node) );
    5490
    5491 stat->plungedepth = 0;
    5492 if( SCIPnodeGetDepth(*node) > 0 )
    5493 stat->nbacktracks++;
    5494 SCIPsetDebugMsg(set, "selected leaf node, lowerbound=%g, plungedepth=%d\n", (*node)->lowerbound, stat->plungedepth);
    5495 break;
    5496
    5497 default:
    5498 SCIPerrorMessage("selected node is neither sibling, child, nor leaf (nodetype=%d)\n", SCIPnodeGetType(*node));
    5499 return SCIP_INVALIDDATA;
    5500 } /*lint !e788*/
    5501
    5502 /* convert node into the focus node */
    5503 (*node)->nodetype = SCIP_NODETYPE_FOCUSNODE; /*lint !e641*/
    5504 }
    5505 assert(tree->nchildren == 0);
    5506
    5507 /* set LP fork, LP state fork, and subroot */
    5508 assert(subroot == NULL || (lpstatefork != NULL && subroot->depth <= lpstatefork->depth));
    5509 assert(lpstatefork == NULL || (lpfork != NULL && lpstatefork->depth <= lpfork->depth));
    5510 assert(lpfork == NULL || (*node != NULL && lpfork->depth < (*node)->depth));
    5511 tree->focuslpfork = lpfork;
    5512 tree->focuslpstatefork = lpstatefork;
    5513 tree->focussubroot = subroot;
    5514 tree->focuslpconstructed = FALSE;
    5515 lp->resolvelperror = FALSE;
    5516
    5517 /* track the path from the old focus node to the new node, free dead end, set new focus node, and perform domain and constraint set changes */
    5518 SCIP_CALL( treeSwitchPath(tree, reopt, blkmem, set, stat, transprob, origprob, primal, lp, branchcand, conflict,
    5519 eventqueue, eventfilter, cliquetable, fork, *node, cutoff) );
    5520 assert(tree->focusnode == *node);
    5521 assert(tree->pathlen >= 0);
    5522 assert(*node != NULL || tree->pathlen == 0);
    5523 assert(*node == NULL || tree->pathlen-1 <= (int)(*node)->depth);
    5524 assert(*cutoff || SCIPtreeIsPathComplete(tree));
    5525
    5526 return SCIP_OKAY;
    5527}
    5528
    5529
    5530
    5531
    5532/*
    5533 * Tree methods
    5534 */
    5535
    5536/** creates an initialized tree data structure */
    5538 SCIP_TREE** tree, /**< pointer to tree data structure */
    5539 BMS_BLKMEM* blkmem, /**< block memory buffers */
    5540 SCIP_SET* set, /**< global SCIP settings */
    5541 SCIP_NODESEL* nodesel /**< node selector to use for sorting leaves in the priority queue */
    5542 )
    5543{
    5544 int p;
    5545
    5546 assert(tree != NULL);
    5547 assert(blkmem != NULL);
    5548
    5549 SCIP_ALLOC( BMSallocMemory(tree) );
    5550
    5551 (*tree)->root = NULL;
    5552
    5553 SCIP_CALL( SCIPnodepqCreate(&(*tree)->leaves, set, nodesel) );
    5554
    5555 /* allocate one slot for the prioritized and the unprioritized bound change */
    5556 for( p = 0; p <= 1; ++p )
    5557 {
    5558 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*tree)->divebdchgdirs[p], 1) ); /*lint !e866*/
    5559 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*tree)->divebdchgvars[p], 1) ); /*lint !e866*/
    5560 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*tree)->divebdchgvals[p], 1) ); /*lint !e866*/
    5561 (*tree)->ndivebdchanges[p] = 0;
    5562 (*tree)->divebdchgsize[p] = 1;
    5563 }
    5564
    5565 (*tree)->path = NULL;
    5566 (*tree)->focusnode = NULL;
    5567 (*tree)->focuslpfork = NULL;
    5568 (*tree)->focuslpstatefork = NULL;
    5569 (*tree)->focussubroot = NULL;
    5570 (*tree)->children = NULL;
    5571 (*tree)->siblings = NULL;
    5572 (*tree)->probingroot = NULL;
    5573 (*tree)->childrenprio = NULL;
    5574 (*tree)->siblingsprio = NULL;
    5575 (*tree)->pathnlpcols = NULL;
    5576 (*tree)->pathnlprows = NULL;
    5577 (*tree)->probinglpistate = NULL;
    5578 (*tree)->probinglpinorms = NULL;
    5579 (*tree)->pendingbdchgs = NULL;
    5580 (*tree)->probdiverelaxsol = NULL;
    5581 (*tree)->nprobdiverelaxsol = 0;
    5582 (*tree)->pendingbdchgssize = 0;
    5583 (*tree)->npendingbdchgs = 0;
    5584 (*tree)->focuslpstateforklpcount = -1;
    5585 (*tree)->childrensize = 0;
    5586 (*tree)->nchildren = 0;
    5587 (*tree)->siblingssize = 0;
    5588 (*tree)->nsiblings = 0;
    5589 (*tree)->pathlen = 0;
    5590 (*tree)->pathsize = 0;
    5591 (*tree)->effectiverootdepth = 0;
    5592 (*tree)->updatedeffectiverootdepth = 0;
    5593 (*tree)->lastbranchparentid = -1L;
    5594 (*tree)->correctlpdepth = -1;
    5595 (*tree)->cutoffdepth = INT_MAX;
    5596 (*tree)->repropdepth = INT_MAX;
    5597 (*tree)->repropsubtreecount = 0;
    5598 (*tree)->focusnodehaslp = FALSE;
    5599 (*tree)->probingnodehaslp = FALSE;
    5600 (*tree)->focuslpconstructed = FALSE;
    5601 (*tree)->cutoffdelayed = FALSE;
    5602 (*tree)->probinglpwasflushed = FALSE;
    5603 (*tree)->probinglpwassolved = FALSE;
    5604 (*tree)->probingloadlpistate = FALSE;
    5605 (*tree)->probinglpwasrelax = FALSE;
    5606 (*tree)->probingsolvedlp = FALSE;
    5607 (*tree)->forcinglpmessage = FALSE;
    5608 (*tree)->sbprobing = FALSE;
    5609 (*tree)->probinglpwasprimfeas = TRUE;
    5610 (*tree)->probinglpwasdualfeas = TRUE;
    5611 (*tree)->probdiverelaxstored = FALSE;
    5612 (*tree)->probdiverelaxincludeslp = FALSE;
    5613
    5614 return SCIP_OKAY;
    5615}
    5616
    5617/** frees tree data structure */
    5619 SCIP_TREE** tree, /**< pointer to tree data structure */
    5620 BMS_BLKMEM* blkmem, /**< block memory buffers */
    5621 SCIP_SET* set, /**< global SCIP settings */
    5622 SCIP_STAT* stat, /**< problem statistics */
    5623 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    5624 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    5625 SCIP_LP* lp /**< current LP data */
    5626 )
    5627{
    5628 int p;
    5629
    5630 assert(tree != NULL);
    5631 assert(*tree != NULL);
    5632 assert((*tree)->nchildren == 0);
    5633 assert((*tree)->nsiblings == 0);
    5634 assert((*tree)->focusnode == NULL);
    5635 assert(!SCIPtreeProbing(*tree));
    5636
    5637 SCIPsetDebugMsg(set, "free tree\n");
    5638
    5639 /* free node queue */
    5640 SCIP_CALL( SCIPnodepqFree(&(*tree)->leaves, blkmem, set, stat, eventqueue, eventfilter, *tree, lp) );
    5641
    5642 /* free diving bound change storage */
    5643 for( p = 0; p <= 1; ++p )
    5644 {
    5645 BMSfreeBlockMemoryArray(blkmem, &(*tree)->divebdchgdirs[p], (*tree)->divebdchgsize[p]); /*lint !e866*/
    5646 BMSfreeBlockMemoryArray(blkmem, &(*tree)->divebdchgvals[p], (*tree)->divebdchgsize[p]); /*lint !e866*/
    5647 BMSfreeBlockMemoryArray(blkmem, &(*tree)->divebdchgvars[p], (*tree)->divebdchgsize[p]); /*lint !e866*/
    5648 }
    5649
    5650 /* free pointer arrays */
    5651 BMSfreeMemoryArrayNull(&(*tree)->path);
    5652 BMSfreeMemoryArrayNull(&(*tree)->children);
    5653 BMSfreeMemoryArrayNull(&(*tree)->siblings);
    5654 BMSfreeMemoryArrayNull(&(*tree)->childrenprio);
    5655 BMSfreeMemoryArrayNull(&(*tree)->siblingsprio);
    5656 BMSfreeMemoryArrayNull(&(*tree)->pathnlpcols);
    5657 BMSfreeMemoryArrayNull(&(*tree)->pathnlprows);
    5658 BMSfreeMemoryArrayNull(&(*tree)->probdiverelaxsol);
    5659 BMSfreeMemoryArrayNull(&(*tree)->pendingbdchgs);
    5660
    5661 BMSfreeMemory(tree);
    5662
    5663 return SCIP_OKAY;
    5664}
    5665
    5666/** clears and resets tree data structure and deletes all nodes */
    5668 SCIP_TREE* tree, /**< tree data structure */
    5669 BMS_BLKMEM* blkmem, /**< block memory buffers */
    5670 SCIP_SET* set, /**< global SCIP settings */
    5671 SCIP_STAT* stat, /**< problem statistics */
    5672 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    5673 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    5674 SCIP_LP* lp /**< current LP data */
    5675 )
    5676{
    5677 int v;
    5678
    5679 assert(tree != NULL);
    5680 assert(tree->nchildren == 0);
    5681 assert(tree->nsiblings == 0);
    5682 assert(tree->focusnode == NULL);
    5683 assert(!SCIPtreeProbing(tree));
    5684
    5685 SCIPsetDebugMsg(set, "clearing tree\n");
    5686
    5687 /* clear node queue */
    5688 SCIP_CALL( SCIPnodepqClear(tree->leaves, blkmem, set, stat, eventqueue, eventfilter, tree, lp) );
    5689 assert(tree->root == NULL);
    5690
    5691 /* we have to remove the captures of the variables within the pending bound change data structure */
    5692 for( v = tree->npendingbdchgs-1; v >= 0; --v )
    5693 {
    5694 SCIP_VAR* var;
    5695
    5696 var = tree->pendingbdchgs[v].var;
    5697 assert(var != NULL);
    5698
    5699 /* release the variable */
    5700 SCIP_CALL( SCIPvarRelease(&var, blkmem, set, eventqueue, lp) );
    5701 }
    5702
    5703 /* mark working arrays to be empty and reset data */
    5704 tree->focuslpstateforklpcount = -1;
    5705 tree->nchildren = 0;
    5706 tree->nsiblings = 0;
    5707 tree->pathlen = 0;
    5708 tree->effectiverootdepth = 0;
    5709 tree->updatedeffectiverootdepth = 0;
    5710 tree->correctlpdepth = -1;
    5711 tree->cutoffdepth = INT_MAX;
    5712 tree->repropdepth = INT_MAX;
    5713 tree->repropsubtreecount = 0;
    5714 tree->npendingbdchgs = 0;
    5715 tree->focusnodehaslp = FALSE;
    5716 tree->probingnodehaslp = FALSE;
    5717 tree->cutoffdelayed = FALSE;
    5718 tree->probinglpwasflushed = FALSE;
    5719 tree->probinglpwassolved = FALSE;
    5720 tree->probingloadlpistate = FALSE;
    5721 tree->probinglpwasrelax = FALSE;
    5722 tree->probingsolvedlp = FALSE;
    5723
    5724 return SCIP_OKAY;
    5725}
    5726
    5727/** creates the root node of the tree and puts it into the leaves queue */
    5729 SCIP_TREE* tree, /**< tree data structure */
    5730 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5731 BMS_BLKMEM* blkmem, /**< block memory buffers */
    5732 SCIP_SET* set, /**< global SCIP settings */
    5733 SCIP_STAT* stat, /**< problem statistics */
    5734 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    5735 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    5736 SCIP_LP* lp /**< current LP data */
    5737 )
    5738{
    5739 assert(tree != NULL);
    5740 assert(tree->nchildren == 0);
    5741 assert(tree->nsiblings == 0);
    5742 assert(tree->root == NULL);
    5743 assert(tree->focusnode == NULL);
    5744 assert(!SCIPtreeProbing(tree));
    5745
    5746 /* create root node */
    5747 SCIP_CALL( SCIPnodeCreateChild(&tree->root, blkmem, set, stat, tree, 0.0, -SCIPsetInfinity(set)) );
    5748 assert(tree->nchildren == 1);
    5749
    5750#ifndef NDEBUG
    5751 /* check, if the sizes in the data structures match the maximal numbers defined here */
    5752 tree->root->depth = SCIP_MAXTREEDEPTH + 1;
    5754 assert(tree->root->depth - 1 == SCIP_MAXTREEDEPTH); /*lint !e650*/
    5755 assert(tree->root->repropsubtreemark == MAXREPROPMARK);
    5756 tree->root->depth++; /* this should produce an overflow and reset the value to 0 */
    5757 tree->root->repropsubtreemark++; /* this should produce an overflow and reset the value to 0 */
    5758 assert(tree->root->depth == 0);
    5760 assert(!tree->root->active);
    5761 assert(!tree->root->cutoff);
    5762 assert(!tree->root->reprop);
    5763 assert(tree->root->repropsubtreemark == 0);
    5764#endif
    5765
    5766 /* move root to the queue, convert it to LEAF */
    5767 SCIP_CALL( treeNodesToQueue(tree, reopt, blkmem, set, stat, eventqueue, eventfilter, lp, tree->children, &tree->nchildren, NULL,
    5768 SCIPsetInfinity(set)) );
    5769
    5770 return SCIP_OKAY;
    5771}
    5772
    5773/** creates a temporary presolving root node of the tree and installs it as focus node */
    5775 SCIP_TREE* tree, /**< tree data structure */
    5776 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5777 BMS_BLKMEM* blkmem, /**< block memory buffers */
    5778 SCIP_SET* set, /**< global SCIP settings */
    5779 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
    5780 SCIP_STAT* stat, /**< problem statistics */
    5781 SCIP_PROB* transprob, /**< transformed problem */
    5782 SCIP_PROB* origprob, /**< original problem */
    5783 SCIP_PRIMAL* primal, /**< primal data */
    5784 SCIP_LP* lp, /**< current LP data */
    5785 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    5786 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    5787 SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
    5788 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    5789 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    5790 SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
    5791 )
    5792{
    5793 SCIP_Bool cutoff;
    5794
    5795 assert(tree != NULL);
    5796 assert(tree->nchildren == 0);
    5797 assert(tree->nsiblings == 0);
    5798 assert(tree->root == NULL);
    5799 assert(tree->focusnode == NULL);
    5800 assert(!SCIPtreeProbing(tree));
    5801
    5802 /* create temporary presolving root node */
    5803 SCIP_CALL( SCIPtreeCreateRoot(tree, reopt, blkmem, set, stat, eventqueue, eventfilter, lp) );
    5804 assert(tree->root != NULL);
    5805
    5806 /* install the temporary root node as focus node */
    5807 SCIP_CALL( SCIPnodeFocus(&tree->root, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
    5808 conflict, conflictstore, eventqueue, eventfilter, cliquetable, &cutoff, FALSE, FALSE) );
    5809 assert(!cutoff);
    5810
    5811 return SCIP_OKAY;
    5812}
    5813
    5814/** frees the temporary presolving root and resets tree data structure */
    5816 SCIP_TREE* tree, /**< tree data structure */
    5817 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5818 BMS_BLKMEM* blkmem, /**< block memory buffers */
    5819 SCIP_SET* set, /**< global SCIP settings */
    5820 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
    5821 SCIP_STAT* stat, /**< problem statistics */
    5822 SCIP_PROB* transprob, /**< transformed problem */
    5823 SCIP_PROB* origprob, /**< original problem */
    5824 SCIP_PRIMAL* primal, /**< primal data */
    5825 SCIP_LP* lp, /**< current LP data */
    5826 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    5827 SCIP_CONFLICT* conflict, /**< conflict analysis data */
    5828 SCIP_CONFLICTSTORE* conflictstore, /**< conflict store */
    5829 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    5830 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    5831 SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
    5832 )
    5833{
    5834 SCIP_NODE* node;
    5835 SCIP_Bool cutoff;
    5836
    5837 assert(tree != NULL);
    5838 assert(tree->root != NULL);
    5839 assert(tree->focusnode == tree->root);
    5840 assert(tree->pathlen == 1);
    5841
    5842 /* unfocus the temporary root node */
    5843 node = NULL;
    5844 SCIP_CALL( SCIPnodeFocus(&node, blkmem, set, messagehdlr, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
    5845 conflict, conflictstore, eventqueue, eventfilter, cliquetable, &cutoff, FALSE, FALSE) );
    5846 assert(!cutoff);
    5847 assert(tree->root == NULL);
    5848 assert(tree->focusnode == NULL);
    5849 assert(tree->pathlen == 0);
    5850
    5851 /* reset tree data structure */
    5852 SCIP_CALL( SCIPtreeClear(tree, blkmem, set, stat, eventqueue, eventfilter, lp) );
    5853
    5854 return SCIP_OKAY;
    5855}
    5856
    5857/** returns the node selector associated with the given node priority queue */
    5859 SCIP_TREE* tree /**< branch and bound tree */
    5860 )
    5861{
    5862 assert(tree != NULL);
    5863
    5864 return SCIPnodepqGetNodesel(tree->leaves);
    5865}
    5866
    5867/** sets the node selector used for sorting the nodes in the priority queue, and resorts the queue if necessary */
    5869 SCIP_TREE* tree, /**< branch and bound tree */
    5870 SCIP_SET* set, /**< global SCIP settings */
    5871 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
    5872 SCIP_STAT* stat, /**< problem statistics */
    5873 SCIP_NODESEL* nodesel /**< node selector to use for sorting the nodes in the queue */
    5874 )
    5875{
    5876 assert(tree != NULL);
    5877 assert(stat != NULL);
    5878
    5879 if( SCIPnodepqGetNodesel(tree->leaves) != nodesel )
    5880 {
    5881 /* change the node selector used in the priority queue and resort the queue */
    5882 SCIP_CALL( SCIPnodepqSetNodesel(&tree->leaves, set, nodesel) );
    5883
    5884 /* issue message */
    5885 if( stat->nnodes > 0 )
    5886 {
    5887 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
    5888 "(node %" SCIP_LONGINT_FORMAT ") switching to node selector <%s>\n", stat->nnodes, SCIPnodeselGetName(nodesel));
    5889 }
    5890 }
    5891
    5892 return SCIP_OKAY;
    5893}
    5894
    5895/** cuts off nodes with lower bound not better than given cutoff bound */
    5897 SCIP_TREE* tree, /**< branch and bound tree */
    5898 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5899 BMS_BLKMEM* blkmem, /**< block memory */
    5900 SCIP_SET* set, /**< global SCIP settings */
    5901 SCIP_STAT* stat, /**< dynamic problem statistics */
    5902 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    5903 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    5904 SCIP_LP* lp, /**< current LP data */
    5905 SCIP_Real cutoffbound /**< cutoff bound: all nodes with lowerbound >= cutoffbound are cut off */
    5906 )
    5907{
    5908 SCIP_NODE* node;
    5909 int i;
    5910
    5911 assert(tree != NULL);
    5912 assert(stat != NULL);
    5913 assert(lp != NULL);
    5914
    5915 /* if we are in diving mode, it is not allowed to cut off nodes, because this can lead to deleting LP rows which
    5916 * would modify the currently unavailable (due to diving modifications) SCIP_LP
    5917 * -> the cutoff must be delayed and executed after the diving ends
    5918 */
    5919 if( SCIPlpDiving(lp) )
    5920 {
    5921 tree->cutoffdelayed = TRUE;
    5922 return SCIP_OKAY;
    5923 }
    5924
    5925 tree->cutoffdelayed = FALSE;
    5926
    5927 /* cut off leaf nodes in the queue */
    5928 SCIP_CALL( SCIPnodepqBound(tree->leaves, blkmem, set, stat, eventqueue, eventfilter, tree, reopt, lp, cutoffbound) );
    5929
    5930 /* cut off siblings: we have to loop backwards, because a removal leads to moving the last node in empty slot */
    5931 for( i = tree->nsiblings-1; i >= 0; --i )
    5932 {
    5933 node = tree->siblings[i];
    5934
    5935 if( node->lowerbound >= cutoffbound
    5936 || ( !set->exact_enable && SCIPsetIsGE(set, node->lowerbound, cutoffbound) ) )
    5937 {
    5938 /* delete sibling due to bound cut off */
    5939 SCIP_CALL( SCIPnodeCutoff(node, set, stat, eventfilter, tree, set->scip->transprob, set->scip->origprob, reopt, lp, blkmem) );
    5940 SCIP_CALL( SCIPnodeFree(&node, blkmem, set, stat, eventqueue, eventfilter, tree, lp) );
    5941 }
    5942 }
    5943
    5944 /* cut off children: we have to loop backwards, because a removal leads to moving the last node in empty slot */
    5945 for( i = tree->nchildren-1; i >= 0; --i )
    5946 {
    5947 node = tree->children[i];
    5948
    5949 if( node->lowerbound >= cutoffbound
    5950 || ( !set->exact_enable && SCIPsetIsGE(set, node->lowerbound, cutoffbound) ) )
    5951 {
    5952 /* delete child due to bound cut off */
    5953 SCIP_CALL( SCIPnodeCutoff(node, set, stat, eventfilter, tree, set->scip->transprob, set->scip->origprob, reopt, lp, blkmem) );
    5954 SCIP_CALL( SCIPnodeFree(&node, blkmem, set, stat, eventqueue, eventfilter, tree, lp) );
    5955 }
    5956 }
    5957
    5958 return SCIP_OKAY;
    5959}
    5960
    5961/** calculates the node selection priority for moving the given variable's LP value to the given target value;
    5962 * this node selection priority can be given to the SCIPcreateChild() call
    5963 */
    5965 SCIP_TREE* tree, /**< branch and bound tree */
    5966 SCIP_SET* set, /**< global SCIP settings */
    5967 SCIP_STAT* stat, /**< dynamic problem statistics */
    5968 SCIP_VAR* var, /**< variable, of which the branching factor should be applied, or NULL */
    5969 SCIP_BRANCHDIR branchdir, /**< type of branching that was performed: upwards, downwards, or fixed
    5970 * fixed should only be used, when both bounds changed
    5971 */
    5972 SCIP_Real targetvalue /**< new value of the variable in the child node */
    5973 )
    5974{
    5975 SCIP_Real prio;
    5976 SCIP_Real varsol;
    5977 SCIP_Real varrootsol;
    5978 SCIP_Real downinfs;
    5979 SCIP_Real upinfs;
    5980 SCIP_Bool isroot;
    5981 SCIP_Bool haslp;
    5982
    5983 assert(set != NULL);
    5984
    5985 /* extract necessary information */
    5986 isroot = (SCIPtreeGetCurrentDepth(tree) == 0);
    5987 haslp = SCIPtreeHasFocusNodeLP(tree);
    5988 varsol = SCIPvarGetSol(var, haslp);
    5989 varrootsol = SCIPvarGetRootSol(var);
    5992
    5993 switch( branchdir )
    5994 {
    5996 switch( SCIPvarGetBranchDirection(var) )
    5997 {
    5999 prio = +1.0;
    6000 break;
    6002 prio = -1.0;
    6003 break;
    6005 switch( set->nodesel_childsel )
    6006 {
    6007 case 'd':
    6008 prio = +1.0;
    6009 break;
    6010 case 'u':
    6011 prio = -1.0;
    6012 break;
    6013 case 'p':
    6014 prio = -SCIPvarGetPseudocost(var, stat, targetvalue - varsol);
    6015 break;
    6016 case 'i':
    6017 prio = downinfs;
    6018 break;
    6019 case 'l':
    6020 prio = targetvalue - varsol;
    6021 break;
    6022 case 'r':
    6023 prio = varrootsol - varsol;
    6024 break;
    6025 case 'h':
    6026 prio = downinfs + SCIPsetEpsilon(set);
    6027 if( !isroot && haslp )
    6028 prio *= (varrootsol - varsol + 1.0);
    6029 break;
    6030 default:
    6031 SCIPerrorMessage("invalid child selection rule <%c>\n", set->nodesel_childsel);
    6032 prio = 0.0;
    6033 break;
    6034 }
    6035 break;
    6036 default:
    6037 SCIPerrorMessage("invalid preferred branching direction <%d> of variable <%s>\n",
    6039 prio = 0.0;
    6040 break;
    6041 }
    6042 break;
    6044 /* the branch is directed upwards */
    6045 switch( SCIPvarGetBranchDirection(var) )
    6046 {
    6048 prio = -1.0;
    6049 break;
    6051 prio = +1.0;
    6052 break;
    6054 switch( set->nodesel_childsel )
    6055 {
    6056 case 'd':
    6057 prio = -1.0;
    6058 break;
    6059 case 'u':
    6060 prio = +1.0;
    6061 break;
    6062 case 'p':
    6063 prio = -SCIPvarGetPseudocost(var, stat, targetvalue - varsol);
    6064 break;
    6065 case 'i':
    6066 prio = upinfs;
    6067 break;
    6068 case 'l':
    6069 prio = varsol - targetvalue;
    6070 break;
    6071 case 'r':
    6072 prio = varsol - varrootsol;
    6073 break;
    6074 case 'h':
    6075 prio = upinfs + SCIPsetEpsilon(set);
    6076 if( !isroot && haslp )
    6077 prio *= (varsol - varrootsol + 1.0);
    6078 break;
    6079 default:
    6080 SCIPerrorMessage("invalid child selection rule <%c>\n", set->nodesel_childsel);
    6081 prio = 0.0;
    6082 break;
    6083 }
    6084 /* since choosing the upwards direction is usually superior than the downwards direction (see results of
    6085 * Achterberg's thesis (2007)), we break ties towards upwards branching
    6086 */
    6087 prio += SCIPsetEpsilon(set);
    6088 break;
    6089
    6090 default:
    6091 SCIPerrorMessage("invalid preferred branching direction <%d> of variable <%s>\n",
    6093 prio = 0.0;
    6094 break;
    6095 }
    6096 break;
    6098 prio = SCIPsetInfinity(set);
    6099 break;
    6101 default:
    6102 SCIPerrorMessage("invalid branching direction <%d> of variable <%s>\n",
    6104 prio = 0.0;
    6105 break;
    6106 }
    6107
    6108 return prio;
    6109}
    6110
    6111/** calculates an estimate for the objective of the best feasible solution contained in the subtree after applying the given
    6112 * branching; this estimate can be given to the SCIPcreateChild() call
    6113 */
    6115 SCIP_TREE* tree, /**< branch and bound tree */
    6116 SCIP_SET* set, /**< global SCIP settings */
    6117 SCIP_STAT* stat, /**< dynamic problem statistics */
    6118 SCIP_VAR* var, /**< variable, of which the branching factor should be applied, or NULL */
    6119 SCIP_Real targetvalue /**< new value of the variable in the child node */
    6120 )
    6121{
    6122 SCIP_Real estimateinc;
    6123 SCIP_Real estimate;
    6124 SCIP_Real varsol;
    6125
    6126 assert(tree != NULL);
    6127 assert(var != NULL);
    6128
    6129 estimate = SCIPnodeGetEstimate(tree->focusnode);
    6130 varsol = SCIPvarGetSol(var, SCIPtreeHasFocusNodeLP(tree));
    6131
    6132 /* compute increase above parent node's (i.e., focus node's) estimate value */
    6133 if( !SCIPvarIsIntegral(var) )
    6134 estimateinc = SCIPvarGetPseudocost(var, stat, targetvalue - varsol);
    6135 else
    6136 {
    6137 SCIP_Real pscdown;
    6138 SCIP_Real pscup;
    6139
    6140 /* calculate estimate based on pseudo costs:
    6141 * estimate = lowerbound + sum(min{f_j * pscdown_j, (1-f_j) * pscup_j})
    6142 * = parentestimate - min{f_b * pscdown_b, (1-f_b) * pscup_b} + (targetvalue-oldvalue)*{pscdown_b or pscup_b}
    6143 */
    6144 pscdown = SCIPvarGetPseudocost(var, stat, SCIPsetFeasFloor(set, varsol) - varsol);
    6145 pscup = SCIPvarGetPseudocost(var, stat, SCIPsetFeasCeil(set, varsol) - varsol);
    6146 estimateinc = SCIPvarGetPseudocost(var, stat, targetvalue - varsol) - MIN(pscdown, pscup);
    6147 }
    6148
    6149 /* due to rounding errors estimateinc might be slightly negative; in this case return the parent node's estimate */
    6150 if( estimateinc > 0.0 )
    6151 estimate += estimateinc;
    6152
    6153 return estimate;
    6154}
    6155
    6156/** branches on a variable x
    6157 * if x is a continuous variable, then two child nodes will be created
    6158 * (x <= x', x >= x')
    6159 * but if the bounds of x are such that their relative difference is smaller than epsilon,
    6160 * the variable is fixed to val (if not SCIP_INVALID) or a well chosen alternative in the current node,
    6161 * i.e., no children are created
    6162 * if x is not a continuous variable, then:
    6163 * if solution value x' is fractional, two child nodes will be created
    6164 * (x <= floor(x'), x >= ceil(x')),
    6165 * if solution value is integral, the x' is equal to lower or upper bound of the branching
    6166 * variable and the bounds of x are finite, then two child nodes will be created
    6167 * (x <= x", x >= x"+1 with x" = floor((lb + ub)/2)),
    6168 * otherwise (up to) three child nodes will be created
    6169 * (x <= x'-1, x == x', x >= x'+1)
    6170 * if solution value is equal to one of the bounds and the other bound is infinite, only two child nodes
    6171 * will be created (the third one would be infeasible anyway)
    6172 */
    6174 SCIP_TREE* tree, /**< branch and bound tree */
    6175 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6176 BMS_BLKMEM* blkmem, /**< block memory */
    6177 SCIP_SET* set, /**< global SCIP settings */
    6178 SCIP_STAT* stat, /**< problem statistics data */
    6179 SCIP_PROB* transprob, /**< transformed problem after presolve */
    6180 SCIP_PROB* origprob, /**< original problem */
    6181 SCIP_LP* lp, /**< current LP data */
    6182 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    6183 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    6184 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    6185 SCIP_VAR* var, /**< variable to branch on */
    6186 SCIP_Real val, /**< value to branch on or SCIP_INVALID for branching on current LP/pseudo solution.
    6187 * A branching value is required for branching on continuous variables */
    6188 SCIP_NODE** downchild, /**< pointer to return the left child with variable rounded down, or NULL */
    6189 SCIP_NODE** eqchild, /**< pointer to return the middle child with variable fixed, or NULL */
    6190 SCIP_NODE** upchild /**< pointer to return the right child with variable rounded up, or NULL */
    6191 )
    6192{
    6193 SCIP_NODE* node;
    6194 SCIP_Real priority;
    6195 SCIP_Real estimate;
    6196
    6197 SCIP_Real downub;
    6198 SCIP_Real fixval;
    6199 SCIP_Real uplb;
    6200 SCIP_Real lpval;
    6201
    6202 SCIP_Bool validval;
    6203
    6204 assert(tree != NULL);
    6205 assert(set != NULL);
    6206 assert(var != NULL);
    6207
    6208 /* initialize children pointer */
    6209 if( downchild != NULL )
    6210 *downchild = NULL;
    6211 if( eqchild != NULL )
    6212 *eqchild = NULL;
    6213 if( upchild != NULL )
    6214 *upchild = NULL;
    6215
    6216 /* store whether a valid value was given for branching */
    6217 validval = (val != SCIP_INVALID); /*lint !e777 */
    6218
    6219 /* get the corresponding active problem variable
    6220 * if branching value is given, then transform it to the value of the active variable */
    6221 if( validval )
    6222 {
    6223 SCIP_Real scalar;
    6224 SCIP_Real constant;
    6225
    6226 scalar = 1.0;
    6227 constant = 0.0;
    6228
    6229 SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &constant) );
    6230
    6231 if( scalar == 0.0 )
    6232 {
    6233 SCIPerrorMessage("cannot branch on fixed variable <%s>\n", SCIPvarGetName(var));
    6234 return SCIP_INVALIDDATA;
    6235 }
    6236
    6237 /* we should have givenvariable = scalar * activevariable + constant */
    6238 val = (val - constant) / scalar;
    6239 }
    6240 else
    6241 var = SCIPvarGetProbvar(var);
    6242
    6244 {
    6245 SCIPerrorMessage("cannot branch on fixed or multi-aggregated variable <%s>\n", SCIPvarGetName(var));
    6246 SCIPABORT();
    6247 return SCIP_INVALIDDATA; /*lint !e527*/
    6248 }
    6249
    6250 /* ensure that branching on continuous variables will only be performed when a branching point is given */
    6251 if( !SCIPvarIsIntegral(var) && !validval )
    6252 {
    6253 SCIPerrorMessage("Cannot branch on continuous variable <%s> without a given branching value.", SCIPvarGetName(var));
    6254 SCIPABORT();
    6255 return SCIP_INVALIDDATA; /*lint !e527*/
    6256 }
    6257
    6258 assert(SCIPvarIsActive(var));
    6259 assert(SCIPvarGetProbindex(var) >= 0);
    6264
    6265 /* update the information for the focus node before creating children */
    6266 SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, tree->focusnode) );
    6267
    6268 /* get value of variable in current LP or pseudo solution */
    6269 lpval = SCIPvarGetSol(var, tree->focusnodehaslp);
    6270
    6271 /* if there was no explicit value given for branching, branch on current LP or pseudo solution value */
    6272 if( !validval )
    6273 {
    6274 val = lpval;
    6275
    6276 /* avoid branching on infinite values in pseudo solution */
    6277 if( SCIPsetIsInfinity(set, -val) || SCIPsetIsInfinity(set, val) )
    6278 {
    6279 val = SCIPvarGetWorstBoundLocal(var);
    6280
    6281 /* if both bounds are infinite, choose zero as branching point */
    6282 if( SCIPsetIsInfinity(set, -val) || SCIPsetIsInfinity(set, val) )
    6283 {
    6284 assert(SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(var)));
    6286 val = 0.0;
    6287 }
    6288 }
    6289 }
    6290
    6291 assert(SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)));
    6292 assert(SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)));
    6293 /* see comment in SCIPbranchVarVal */
    6294 assert(SCIPvarIsIntegral(var)
    6297 || (SCIPsetIsLT(set, 2.1*SCIPvarGetLbLocal(var), 2.1*val) && SCIPsetIsLT(set, 2.1*val, 2.1*SCIPvarGetUbLocal(var))));
    6298
    6299 downub = SCIP_INVALID;
    6300 fixval = SCIP_INVALID;
    6301 uplb = SCIP_INVALID;
    6302
    6303 if( !SCIPvarIsIntegral(var) )
    6304 {
    6306 {
    6307 SCIPsetDebugMsg(set, "fixing continuous variable <%s> with value %g and bounds [%.15g, %.15g], priority %d (current lower bound: %g)\n",
    6309
    6310 /* if val is at least epsilon away from both bounds, then we change both bounds to this value
    6311 * otherwise, we fix the variable to its worst bound
    6312 */
    6313 if( SCIPsetIsGT(set, val, SCIPvarGetLbLocal(var)) && SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var)) )
    6314 {
    6315 SCIP_CALL( SCIPnodeAddBoundchg(tree->focusnode, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
    6316 branchcand, eventqueue, eventfilter, NULL, var, val, SCIP_BOUNDTYPE_LOWER, FALSE) );
    6317 SCIP_CALL( SCIPnodeAddBoundchg(tree->focusnode, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
    6318 branchcand, eventqueue, eventfilter, NULL, var, val, SCIP_BOUNDTYPE_UPPER, FALSE) );
    6319 }
    6320 else if( SCIPvarGetObj(var) >= 0.0 )
    6321 {
    6322 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob,
    6323 tree, reopt, lp, branchcand, eventqueue, eventfilter, NULL, var, SCIPvarGetUbLocal(var), SCIP_BOUNDTYPE_LOWER, FALSE) );
    6324 }
    6325 else
    6326 {
    6327 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob,
    6328 tree, reopt, lp, branchcand, eventqueue, eventfilter, NULL, var, SCIPvarGetLbLocal(var), SCIP_BOUNDTYPE_UPPER, FALSE) );
    6329 }
    6330 }
    6331 else if( SCIPrelDiff(SCIPvarGetUbLocal(var), SCIPvarGetLbLocal(var)) <= 2.02 * SCIPsetEpsilon(set) )
    6332 {
    6333 /* if the only way to branch is such that in both sides the relative domain width becomes smaller epsilon,
    6334 * then fix the variable in both branches right away
    6335 *
    6336 * 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),
    6337 * then fix the variable to the non-infinite value, as we cannot fix a variable to infinity
    6338 */
    6339 SCIPsetDebugMsg(set, "continuous branch on variable <%s> with bounds [%.15g, %.15g], priority %d (current lower bound: %g), node %p\n",
    6342 {
    6343 assert(!SCIPsetIsInfinity(set, -SCIPvarGetUbLocal(var)));
    6344 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob,
    6345 tree, reopt, lp, branchcand, eventqueue, eventfilter, NULL, var, SCIPvarGetUbLocal(var), SCIP_BOUNDTYPE_LOWER, FALSE) );
    6346 }
    6347 else if( SCIPsetIsInfinity(set, SCIPvarGetUbLocal(var)) )
    6348 {
    6349 assert(!SCIPsetIsInfinity(set, SCIPvarGetLbLocal(var)));
    6350 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob,
    6351 tree, reopt, lp, branchcand, eventqueue, eventfilter, NULL, var, SCIPvarGetLbLocal(var), SCIP_BOUNDTYPE_UPPER, FALSE) );
    6352 }
    6353 else
    6354 {
    6355 downub = SCIPvarGetLbLocal(var);
    6356 uplb = SCIPvarGetUbLocal(var);
    6357 }
    6358 }
    6359 else
    6360 {
    6361 /* in the general case, there is enough space for two branches
    6362 * a sophisticated user should have also chosen the branching value such that it is not very close to the bounds
    6363 * so here we only ensure that it is at least epsilon away from both bounds
    6364 */
    6365 SCIPsetDebugMsg(set, "continuous branch on variable <%s> with value %g, priority %d (current lower bound: %g)\n",
    6367 downub = MIN(val, SCIPvarGetUbLocal(var) - SCIPsetEpsilon(set)); /*lint !e666*/
    6368 uplb = MAX(val, SCIPvarGetLbLocal(var) + SCIPsetEpsilon(set)); /*lint !e666*/
    6369 }
    6370 }
    6371 else if( set->exact_enable && EPSISINT(val, 0.0) ) /*lint !e835*/
    6372 {
    6373 SCIP_Real lb;
    6374 SCIP_Real ub;
    6375
    6376 lb = SCIPvarGetLbLocal(var);
    6377 ub = SCIPvarGetUbLocal(var);
    6378
    6379 /* if there was no explicit value given for branching, the variable has a finite domain, and the current LP/pseudo
    6380 * solution is one of the bounds, we branch in the center of the domain */
    6381 if( !validval && !SCIPsetIsInfinity(set, -lb) && !SCIPsetIsInfinity(set, ub) && ( val == lb || val == ub ) ) /*lint !e777*/
    6382 {
    6383 SCIP_Real center;
    6384
    6385 /* create child nodes with x <= x", and x >= x"+1 with x" = floor((lb + ub)/2);
    6386 * if x" is integral, make the interval smaller in the child in which the current solution x'
    6387 * is still feasible
    6388 */
    6389 center = (ub + lb) / 2.0;
    6390 if( val <= center )
    6391 {
    6392 downub = floor(center);
    6393 uplb = downub + 1.0;
    6394 }
    6395 else
    6396 {
    6397 uplb = ceil(center);
    6398 downub = uplb - 1.0;
    6399 }
    6400 }
    6401 else
    6402 {
    6403 /* create child nodes with x <= x'-1, x = x', and x >= x'+1 */
    6404 fixval = val;
    6405
    6406 /* create child node with x <= x'-1, if this would be feasible */
    6407 if( fixval - 1.0 >= lb )
    6408 downub = fixval - 1.0;
    6409
    6410 /* create child node with x >= x'+1, if this would be feasible */
    6411 if( fixval + 1.0 <= ub )
    6412 uplb = fixval + 1.0;
    6413 }
    6414 SCIPsetDebugMsg(set, "integral branch on variable <%s> with value %g, priority %d (current lower bound: %g)\n",
    6416 }
    6417 else if( !set->exact_enable && SCIPsetIsFeasIntegral(set, val) )
    6418 {
    6419 SCIP_Real lb;
    6420 SCIP_Real ub;
    6421
    6422 lb = SCIPvarGetLbLocal(var);
    6423 ub = SCIPvarGetUbLocal(var);
    6424
    6425 /* if there was no explicit value given for branching, the variable has a finite domain, and the current LP/pseudo
    6426 * solution is one of the bounds, we branch in the center of the domain */
    6427 if( !validval && !SCIPsetIsInfinity(set, -lb) && !SCIPsetIsInfinity(set, ub)
    6428 && ( SCIPsetIsFeasEQ(set, val, lb) || SCIPsetIsFeasEQ(set, val, ub) ) )
    6429 {
    6430 SCIP_Real center;
    6431
    6432 /* create child nodes with x <= x", and x >= x"+1 with x" = floor((lb + ub)/2);
    6433 * if x" is integral, make the interval smaller in the child in which the current solution x'
    6434 * is still feasible
    6435 */
    6436 center = (ub + lb) / 2.0;
    6437 if( val <= center )
    6438 {
    6439 downub = SCIPsetFeasFloor(set, center);
    6440 uplb = downub + 1.0;
    6441 }
    6442 else
    6443 {
    6444 uplb = SCIPsetFeasCeil(set, center);
    6445 downub = uplb - 1.0;
    6446 }
    6447 }
    6448 else
    6449 {
    6450 /* create child nodes with x <= x'-1, x = x', and x >= x'+1 */
    6451 fixval = round(val);
    6452
    6453 /* create child node with x <= x'-1, if this would be feasible */
    6454 if( SCIPsetIsFeasGE(set, fixval - 1.0, lb) )
    6455 downub = fixval - 1.0;
    6456
    6457 /* create child node with x >= x'+1, if this would be feasible */
    6458 if( SCIPsetIsFeasLE(set, fixval + 1.0, ub) )
    6459 uplb = fixval + 1.0;
    6460 }
    6461 SCIPsetDebugMsg(set, "integral branch on variable <%s> with value %g, priority %d (current lower bound: %g)\n",
    6463 }
    6464 else
    6465 {
    6466 /* create child nodes with x <= floor(x'), and x >= ceil(x') */
    6467 if( set->exact_enable )
    6468 {
    6469 assert(val < SCIPvarGetUbLocal(var));
    6470 downub = floor(val);
    6471 uplb = downub + 1.0;
    6472 assert(uplb == ceil(val)); /*lint !e777*/
    6473 }
    6474 else
    6475 {
    6476 downub = SCIPsetFeasFloor(set, val);
    6477 uplb = downub + 1.0;
    6478 assert( SCIPsetIsRelEQ(set, SCIPsetCeil(set, val), uplb) );
    6479 }
    6480 SCIPsetDebugMsg(set, "fractional branch on variable <%s> with value %g, root value %g, priority %d (current lower bound: %g)\n",
    6482 }
    6483
    6484 /* perform the branching;
    6485 * set the node selection priority in a way, s.t. a node is preferred whose branching goes in the same direction
    6486 * as the deviation from the variable's root solution
    6487 */
    6488 if( downub != SCIP_INVALID ) /*lint !e777*/
    6489 {
    6490 /* create child node x <= downub */
    6491 priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_DOWNWARDS, downub);
    6492 /* if LP solution is cutoff in child, compute a new estimate
    6493 * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node */
    6494 if( SCIPsetIsGT(set, lpval, downub) )
    6495 estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, downub);
    6496 else
    6497 estimate = SCIPnodeGetEstimate(tree->focusnode);
    6498 SCIPsetDebugMsg(set, " -> creating child: <%s> <= %g (priority: %g, estimate: %g)\n",
    6499 SCIPvarGetName(var), downub, priority, estimate);
    6500 SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
    6501
    6502 /* update branching information in certificate, if certificate is active */
    6503 SCIP_CALL( SCIPcertificateUpdateBranchingData(set, stat->certificate, stat, lp, node, var, SCIP_BOUNDTYPE_UPPER, downub) );
    6504
    6505 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    6506 eventfilter, NULL, var, downub, SCIP_BOUNDTYPE_UPPER, FALSE) );
    6507 /* output branching bound change to visualization file */
    6508 SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
    6509
    6510 if( downchild != NULL )
    6511 *downchild = node;
    6512 }
    6513
    6514 if( fixval != SCIP_INVALID ) /*lint !e777*/
    6515 {
    6516 /* create child node with x = fixval */
    6517 priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_FIXED, fixval);
    6518 estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, fixval);
    6519 SCIPsetDebugMsg(set, " -> creating child: <%s> == %g (priority: %g, estimate: %g)\n",
    6520 SCIPvarGetName(var), fixval, priority, estimate);
    6521 SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
    6522
    6523 /* update branching information in certificate, if certificate is active */
    6524 if( downub == SCIP_INVALID ) /*lint !e777*/
    6525 {
    6526 SCIP_CALL( SCIPcertificateUpdateBranchingData(set, stat->certificate, stat, lp, node, var, SCIP_BOUNDTYPE_UPPER, fixval) );
    6527 }
    6528 else if( uplb == SCIP_INVALID ) /*lint !e777*/
    6529 {
    6530 SCIP_CALL( SCIPcertificateUpdateBranchingData(set, stat->certificate, stat, lp, node, var, SCIP_BOUNDTYPE_LOWER, fixval) );
    6531 }
    6532 else if( SCIPisCertified(set->scip) )
    6533 {
    6534 SCIPerrorMessage("Cannot resolve 3-way branching in certificate currently \n");
    6535 SCIPABORT();
    6536 }
    6537
    6538 if( !SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), fixval) )
    6539 {
    6540 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    6541 eventfilter, NULL, var, fixval, SCIP_BOUNDTYPE_LOWER, FALSE) );
    6542 }
    6543 if( !SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), fixval) )
    6544 {
    6545 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    6546 eventfilter, NULL, var, fixval, SCIP_BOUNDTYPE_UPPER, FALSE) );
    6547 }
    6548 /* output branching bound change to visualization file */
    6549 SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
    6550
    6551 if( eqchild != NULL )
    6552 *eqchild = node;
    6553 }
    6554
    6555 if( uplb != SCIP_INVALID ) /*lint !e777*/
    6556 {
    6557 /* create child node with x >= uplb */
    6558 priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_UPWARDS, uplb);
    6559 if( SCIPsetIsLT(set, lpval, uplb) )
    6560 estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, uplb);
    6561 else
    6562 estimate = SCIPnodeGetEstimate(tree->focusnode);
    6563 SCIPsetDebugMsg(set, " -> creating child: <%s> >= %g (priority: %g, estimate: %g)\n",
    6564 SCIPvarGetName(var), uplb, priority, estimate);
    6565 SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
    6566
    6567 /* update branching information in certificate, if certificate is active */
    6569
    6570 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    6571 eventfilter, NULL, var, uplb, SCIP_BOUNDTYPE_LOWER, FALSE) );
    6572 /* output branching bound change to visualization file */
    6573 SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
    6574
    6575 if( upchild != NULL )
    6576 *upchild = node;
    6577 }
    6578
    6579 return SCIP_OKAY;
    6580}
    6581
    6582/** branches on a variable x; unlike the fp-version this will also branch x <= floor(x'), x >= ceil(x')
    6583 * if x' is very close to being integral at one of its bounds;
    6584 * in the fp version this case would be branched in the middle of the domain;
    6585 * not meant for branching on a continuous variables
    6586 */
    6588 SCIP_TREE* tree, /**< branch and bound tree */
    6589 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6590 BMS_BLKMEM* blkmem, /**< block memory */
    6591 SCIP_SET* set, /**< global SCIP settings */
    6592 SCIP_STAT* stat, /**< problem statistics data */
    6593 SCIP_PROB* transprob, /**< transformed problem after presolve */
    6594 SCIP_PROB* origprob, /**< original problem */
    6595 SCIP_LP* lp, /**< current LP data */
    6596 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    6597 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    6598 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    6599 SCIP_VAR* var, /**< variable to branch on */
    6600 SCIP_NODE** downchild, /**< pointer to return the left child with variable rounded down, or NULL */
    6601 SCIP_NODE** upchild /**< pointer to return the right child with variable rounded up, or NULL */
    6602 )
    6603{
    6604 SCIP_NODE* node;
    6605 SCIP_Real priority;
    6606 SCIP_Real estimate;
    6607
    6608 SCIP_Real downub;
    6609 SCIP_Real uplb;
    6610 SCIP_Real val;
    6611
    6612 assert(tree != NULL);
    6613 assert(set != NULL);
    6614 assert(var != NULL);
    6615 assert(set->exact_enable);
    6616
    6617 /* initialize children pointer */
    6618 if( downchild != NULL )
    6619 *downchild = NULL;
    6620 if( upchild != NULL )
    6621 *upchild = NULL;
    6622
    6623 var = SCIPvarGetProbvar(var);
    6624
    6626 {
    6627 SCIPerrorMessage("cannot branch on fixed or multi-aggregated variable <%s>\n", SCIPvarGetName(var));
    6628 SCIPABORT();
    6629 return SCIP_INVALIDDATA; /*lint !e527*/
    6630 }
    6631
    6632 /* ensure, that branching on continuous variables will only be performed when a branching point is given. */
    6633 if( !SCIPvarIsIntegral(var) )
    6634 {
    6635 SCIPerrorMessage("Cannot branch exactly on continuous variable %s.\n", SCIPvarGetName(var));
    6636 SCIPABORT();
    6637 return SCIP_INVALIDDATA; /*lint !e527*/
    6638 }
    6639
    6640 assert(SCIPvarIsActive(var));
    6641 assert(SCIPvarGetProbindex(var) >= 0);
    6643 assert(SCIPvarGetLbLocal(var) == round(SCIPvarGetLbLocal(var))); /*lint !e777*/
    6644 assert(SCIPvarGetUbLocal(var) == round(SCIPvarGetUbLocal(var))); /*lint !e777*/
    6645 assert(SCIPvarGetLbLocal(var) < SCIPvarGetUbLocal(var));
    6646
    6647 /* update the information for the focus node before creating children */
    6648 SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, tree->focusnode) );
    6649
    6650 /* get value of variable in current LP or pseudo solution */
    6651 val = SCIPvarGetSol(var, tree->focusnodehaslp);
    6652
    6653 /* avoid branching on infinite values in pseudo solution */
    6654 if( SCIPsetIsInfinity(set, -val) || SCIPsetIsInfinity(set, val) )
    6655 {
    6656 val = SCIPvarGetWorstBoundLocal(var);
    6657
    6658 /* if both bounds are infinite, choose zero as branching point */
    6659 if( SCIPsetIsInfinity(set, -val) || SCIPsetIsInfinity(set, val) )
    6660 {
    6661 assert(SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(var)));
    6663 val = 0.0;
    6664 }
    6665 }
    6666
    6667 /* create child nodes with x <= floor(x'), and x >= ceil(x') */
    6668 assert(val >= SCIPvarGetLbLocal(var));
    6669 assert(val <= SCIPvarGetUbLocal(var));
    6670 downub = floor(val);
    6671 if( val == SCIPvarGetUbLocal(var) ) /*lint !e777*/
    6672 downub -= 1.0;
    6673 uplb = downub + 1.0;
    6674 assert(downub < uplb);
    6675 assert(downub >= SCIPvarGetLbLocal(var));
    6676 assert(uplb <= SCIPvarGetUbLocal(var));
    6677 SCIPsetDebugMsg(set, "exact branch on variable <%s> with value %g, root value %g, priority %d (current lower bound: %g)\n",
    6679
    6680 /* perform the branching;
    6681 * set the node selection priority in a way, s.t. a node is preferred whose branching goes in the same direction
    6682 * as the deviation from the variable's root solution
    6683 */
    6684 if( downub != SCIP_INVALID ) /*lint !e777*/
    6685 {
    6686 /* create child node x <= downub */
    6687 priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_DOWNWARDS, downub);
    6688 /* if LP solution is cutoff in child, compute a new estimate
    6689 * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node */
    6690 if( SCIPsetIsGT(set, val, downub) )
    6691 estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, downub);
    6692 else
    6693 estimate = SCIPnodeGetEstimate(tree->focusnode);
    6694 SCIPsetDebugMsg(set, " -> creating child: <%s> <= %g (priority: %g, estimate: %g)\n",
    6695 SCIPvarGetName(var), downub, priority, estimate);
    6696 SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
    6697
    6698 /* update branching information in certificate, if certificate is active */
    6699 SCIP_CALL( SCIPcertificateUpdateBranchingData(set, stat->certificate, stat, lp, node, var, SCIP_BOUNDTYPE_UPPER, downub) );
    6700
    6701 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
    6702 eventqueue, eventfilter, NULL, var, downub, SCIP_BOUNDTYPE_UPPER, FALSE) );
    6703 /* output branching bound change to visualization file */
    6704 SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
    6705
    6706 if( downchild != NULL )
    6707 *downchild = node;
    6708 }
    6709
    6710 if( uplb != SCIP_INVALID ) /*lint !e777*/
    6711 {
    6712 /* create child node with x >= uplb */
    6713 priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_UPWARDS, uplb);
    6714 if( SCIPsetIsLT(set, val, uplb) )
    6715 estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, uplb);
    6716 else
    6717 estimate = SCIPnodeGetEstimate(tree->focusnode);
    6718 SCIPsetDebugMsg(set, " -> creating child: <%s> >= %g (priority: %g, estimate: %g)\n",
    6719 SCIPvarGetName(var), uplb, priority, estimate);
    6720 SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
    6721
    6722 /* update branching information in certificate, if certificate is active */
    6724
    6725 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
    6726 eventqueue, eventfilter, NULL, var, uplb, SCIP_BOUNDTYPE_LOWER, FALSE) );
    6727 /* output branching bound change to visualization file */
    6728 SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
    6729
    6730 if( upchild != NULL )
    6731 *upchild = node;
    6732 }
    6733
    6734 return SCIP_OKAY;
    6735}
    6736
    6737/** branches a variable x using the given domain hole; two child nodes will be created (x <= left, x >= right) */
    6739 SCIP_TREE* tree, /**< branch and bound tree */
    6740 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6741 BMS_BLKMEM* blkmem, /**< block memory */
    6742 SCIP_SET* set, /**< global SCIP settings */
    6743 SCIP_STAT* stat, /**< problem statistics data */
    6744 SCIP_PROB* transprob, /**< transformed problem after presolve */
    6745 SCIP_PROB* origprob, /**< original problem */
    6746 SCIP_LP* lp, /**< current LP data */
    6747 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    6748 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    6749 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    6750 SCIP_VAR* var, /**< variable to branch on */
    6751 SCIP_Real left, /**< left side of the domain hole */
    6752 SCIP_Real right, /**< right side of the domain hole */
    6753 SCIP_NODE** downchild, /**< pointer to return the left child with variable rounded down, or NULL */
    6754 SCIP_NODE** upchild /**< pointer to return the right child with variable rounded up, or NULL */
    6755 )
    6756{
    6757 SCIP_NODE* node;
    6758 SCIP_Real priority;
    6759 SCIP_Real estimate;
    6760 SCIP_Real lpval;
    6761
    6762 assert(tree != NULL);
    6763 assert(set != NULL);
    6764 assert(var != NULL);
    6765 assert(SCIPsetIsLT(set, left, SCIPvarGetUbLocal(var)));
    6766 assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
    6767 assert(SCIPsetIsGT(set, right, SCIPvarGetLbLocal(var)));
    6768 assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
    6769 assert(SCIPsetIsLE(set, left, right));
    6770
    6771 /* initialize children pointer */
    6772 if( downchild != NULL )
    6773 *downchild = NULL;
    6774 if( upchild != NULL )
    6775 *upchild = NULL;
    6776
    6777 /* get the corresponding active problem variable */
    6778 SCIP_CALL( SCIPvarGetProbvarHole(&var, &left, &right) );
    6779
    6781 {
    6782 SCIPerrorMessage("cannot branch on fixed or multi-aggregated variable <%s>\n", SCIPvarGetName(var));
    6783 SCIPABORT();
    6784 return SCIP_INVALIDDATA; /*lint !e527*/
    6785 }
    6786
    6787 assert(SCIPvarIsActive(var));
    6788 assert(SCIPvarGetProbindex(var) >= 0);
    6793
    6794 assert(SCIPsetIsFeasGE(set, left, SCIPvarGetLbLocal(var)));
    6795 assert(SCIPsetIsFeasLE(set, right, SCIPvarGetUbLocal(var)));
    6796
    6797 /* adjust left and right side of the domain hole if the variable is integral */
    6798 if( SCIPvarIsIntegral(var) )
    6799 {
    6800 left = SCIPsetFeasFloor(set, left);
    6801 right = SCIPsetFeasCeil(set, right);
    6802 }
    6803
    6804 assert(SCIPsetIsLT(set, left, SCIPvarGetUbLocal(var)));
    6805 assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
    6806 assert(SCIPsetIsGT(set, right, SCIPvarGetLbLocal(var)));
    6807 assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
    6808 assert(SCIPsetIsLE(set, left, right));
    6809
    6810 /* get value of variable in current LP or pseudo solution */
    6811 lpval = SCIPvarGetSol(var, tree->focusnodehaslp);
    6812
    6813 /* perform the branching;
    6814 * set the node selection priority in a way, s.t. a node is preferred whose branching goes in the same direction
    6815 * as the deviation from the variable's root solution
    6816 */
    6817
    6818 /* create child node x <= left */
    6819 priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_DOWNWARDS, left);
    6820
    6821 /* if LP solution is cutoff in child, compute a new estimate
    6822 * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node
    6823 */
    6824 if( SCIPsetIsGT(set, lpval, left) )
    6825 estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, left);
    6826 else
    6827 estimate = SCIPnodeGetEstimate(tree->focusnode);
    6828
    6829 SCIPsetDebugMsg(set, " -> creating child: <%s> <= %g (priority: %g, estimate: %g)\n",
    6830 SCIPvarGetName(var), left, priority, estimate);
    6831
    6832 SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
    6833 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    6834 eventfilter, NULL, var, left, SCIP_BOUNDTYPE_UPPER, FALSE) );
    6835 /* output branching bound change to visualization file */
    6836 SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
    6837
    6838 if( downchild != NULL )
    6839 *downchild = node;
    6840
    6841 /* create child node with x >= right */
    6842 priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_UPWARDS, right);
    6843
    6844 if( SCIPsetIsLT(set, lpval, right) )
    6845 estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, right);
    6846 else
    6847 estimate = SCIPnodeGetEstimate(tree->focusnode);
    6848
    6849 SCIPsetDebugMsg(set, " -> creating child: <%s> >= %g (priority: %g, estimate: %g)\n",
    6850 SCIPvarGetName(var), right, priority, estimate);
    6851
    6852 SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
    6853 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    6854 eventfilter, NULL, var, right, SCIP_BOUNDTYPE_LOWER, FALSE) );
    6855 /* output branching bound change to visualization file */
    6856 SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
    6857
    6858 if( upchild != NULL )
    6859 *upchild = node;
    6860
    6861 return SCIP_OKAY;
    6862}
    6863
    6864/** n-ary branching on a variable x
    6865 * Branches on variable x such that up to n/2 children are created on each side of the usual branching value.
    6866 * The branching value is selected as in SCIPtreeBranchVar().
    6867 * If n is 2 or the variables local domain is too small for a branching into n pieces, SCIPtreeBranchVar() is called.
    6868 * The parameters minwidth and widthfactor determine the domain width of the branching variable in the child nodes.
    6869 * If n is odd, one child with domain width 'width' and having the branching value in the middle is created.
    6870 * Otherwise, two children with domain width 'width' and being left and right of the branching value are created.
    6871 * Next further nodes to the left and right are created, where width is multiplied by widthfactor with increasing distance from the first nodes.
    6872 * The initial width is calculated such that n/2 nodes are created to the left and to the right of the branching value.
    6873 * If this value is below minwidth, the initial width is set to minwidth, which may result in creating less than n nodes.
    6874 *
    6875 * Giving a large value for widthfactor results in creating children with small domain when close to the branching value
    6876 * and large domain when closer to the current variable bounds. That is, setting widthfactor to a very large value and n to 3
    6877 * results in a ternary branching where the branching variable is mostly fixed in the middle child.
    6878 * Setting widthfactor to 1.0 results in children where the branching variable always has the same domain width
    6879 * (except for one child if the branching value is not in the middle).
    6880 */
    6882 SCIP_TREE* tree, /**< branch and bound tree */
    6883 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6884 BMS_BLKMEM* blkmem, /**< block memory */
    6885 SCIP_SET* set, /**< global SCIP settings */
    6886 SCIP_STAT* stat, /**< problem statistics data */
    6887 SCIP_PROB* transprob, /**< transformed problem after presolve */
    6888 SCIP_PROB* origprob, /**< original problem */
    6889 SCIP_LP* lp, /**< current LP data */
    6890 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    6891 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    6892 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    6893 SCIP_VAR* var, /**< variable to branch on */
    6894 SCIP_Real val, /**< value to branch on or SCIP_INVALID for branching on current LP/pseudo solution.
    6895 * A branching value is required for branching on continuous variables */
    6896 int n, /**< attempted number of children to be created, must be >= 2 */
    6897 SCIP_Real minwidth, /**< minimal domain width in children */
    6898 SCIP_Real widthfactor, /**< multiplier for children domain width with increasing distance from val, must be >= 1.0 */
    6899 int* nchildren /**< buffer to store number of created children, or NULL */
    6900 )
    6901{
    6902 SCIP_NODE* node;
    6903 SCIP_Real priority;
    6904 SCIP_Real estimate;
    6905 SCIP_Real lpval;
    6906 SCIP_Real width;
    6907 SCIP_Bool validval;
    6908 SCIP_Real left;
    6909 SCIP_Real right;
    6910 SCIP_Real bnd;
    6911 int i;
    6912
    6913 assert(tree != NULL);
    6914 assert(set != NULL);
    6915 assert(var != NULL);
    6916 assert(n >= 2);
    6917 assert(minwidth >= 0.0);
    6918
    6919 /* if binary branching is requested or we have not enough space for n children, delegate to SCIPtreeBranchVar */
    6920 if( n == 2 ||
    6921 2.0 * minwidth >= SCIPvarGetUbLocal(var) - SCIPvarGetLbLocal(var) ||
    6923 {
    6924 SCIP_NODE* downchild;
    6925 SCIP_NODE* fixchild;
    6926 SCIP_NODE* upchild;
    6927
    6928 SCIP_CALL( SCIPtreeBranchVar(tree, reopt, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue, eventfilter,
    6929 var, val, &downchild, &fixchild, &upchild) );
    6930
    6931 if( nchildren != NULL )
    6932 *nchildren = (downchild != NULL ? 1 : 0) + (fixchild != NULL ? 1 : 0) + (upchild != NULL ? 1 : 0);
    6933
    6934 return SCIP_OKAY;
    6935 }
    6936
    6937 /* store whether a valid value was given for branching */
    6938 validval = (val != SCIP_INVALID); /*lint !e777 */
    6939
    6940 /* get the corresponding active problem variable
    6941 * if branching value is given, then transform it to the value of the active variable */
    6942 if( validval )
    6943 {
    6944 SCIP_Real scalar;
    6945 SCIP_Real constant;
    6946
    6947 scalar = 1.0;
    6948 constant = 0.0;
    6949
    6950 SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &constant) );
    6951
    6952 if( scalar == 0.0 )
    6953 {
    6954 SCIPerrorMessage("cannot branch on fixed variable <%s>\n", SCIPvarGetName(var));
    6955 return SCIP_INVALIDDATA;
    6956 }
    6957
    6958 /* we should have givenvariable = scalar * activevariable + constant */
    6959 val = (val - constant) / scalar;
    6960 }
    6961 else
    6962 var = SCIPvarGetProbvar(var);
    6963
    6965 {
    6966 SCIPerrorMessage("cannot branch on fixed or multi-aggregated variable <%s>\n", SCIPvarGetName(var));
    6967 SCIPABORT();
    6968 return SCIP_INVALIDDATA; /*lint !e527*/
    6969 }
    6970
    6971 /* ensure that branching on continuous variables will only be performed when a branching point is given */
    6972 if( !SCIPvarIsIntegral(var) && !validval )
    6973 {
    6974 SCIPerrorMessage("Cannot branch on continuous variable <%s> without a given branching value.", SCIPvarGetName(var));
    6975 SCIPABORT();
    6976 return SCIP_INVALIDDATA; /*lint !e527*/
    6977 }
    6978
    6979 assert(SCIPvarIsActive(var));
    6980 assert(SCIPvarGetProbindex(var) >= 0);
    6985
    6986 /* get value of variable in current LP or pseudo solution */
    6987 lpval = SCIPvarGetSol(var, tree->focusnodehaslp);
    6988
    6989 /* if there was no explicit value given for branching, branch on current LP or pseudo solution value */
    6990 if( !validval )
    6991 {
    6992 val = lpval;
    6993
    6994 /* avoid branching on infinite values in pseudo solution */
    6995 if( SCIPsetIsInfinity(set, -val) || SCIPsetIsInfinity(set, val) )
    6996 {
    6997 val = SCIPvarGetWorstBoundLocal(var);
    6998
    6999 /* if both bounds are infinite, choose zero as branching point */
    7000 if( SCIPsetIsInfinity(set, -val) || SCIPsetIsInfinity(set, val) )
    7001 {
    7002 assert(SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(var)));
    7004 val = 0.0;
    7005 }
    7006 }
    7007 }
    7008
    7009 assert(SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)));
    7010 assert(SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)));
    7011 /* see comment in SCIPbranchVarVal */
    7012 assert(SCIPvarIsIntegral(var)
    7014 || (SCIPsetIsLT(set, 2.1*SCIPvarGetLbLocal(var), 2.1*val) && SCIPsetIsLT(set, 2.1*val, 2.1*SCIPvarGetUbLocal(var))));
    7015
    7016 /* calculate minimal distance of val from bounds */
    7017 width = SCIP_REAL_MAX;
    7019 {
    7020 width = val - SCIPvarGetLbLocal(var);
    7021 }
    7023 {
    7024 width = MIN(width, SCIPvarGetUbLocal(var) - val); /*lint !e666*/
    7025 }
    7026 /* calculate initial domain width of child nodes
    7027 * 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
    7028 */
    7029 if( width == SCIP_REAL_MAX ) /*lint !e777*/
    7030 {
    7031 /* unbounded variable, let's create a child with a small domain */
    7032 width = 1.0;
    7033 }
    7034 else if( widthfactor == 1.0 )
    7035 {
    7036 /* most domains get same size */
    7037 width /= n/2; /*lint !e653*/ /* rounding is ok at this point */
    7038 }
    7039 else
    7040 {
    7041 /* width is increased by widthfactor for each child
    7042 * if n is even, compute width such that we can create n/2 nodes with width
    7043 * width, widthfactor*width, ..., widthfactor^(n/2)*width on each side, i.e.,
    7044 * sum(width * widthfactor^(i-1), i = 1..n/2) = min(ub-val, val-lb)
    7045 * <-> width * (widthfactor^(n/2) - 1) / (widthfactor - 1) = min(ub-val, val-lb)
    7046 *
    7047 * if n is odd, compute width such that we can create one middle node with width width
    7048 * and n/2 nodes with width widthfactor*width, ..., widthfactor^(n/2)*width on each side, i.e.,
    7049 * width/2 + sum(width * widthfactor^i, i = 1..n/2) = min(ub-val, val-lb)
    7050 * <-> width * (1/2 + widthfactor * (widthfactor^(n/2) - 1) / (widthfactor - 1) = min(ub-val, val-lb)
    7051 */
    7052 assert(widthfactor > 1.0);
    7053 if( n % 2 == 0 )
    7054 width *= (widthfactor - 1.0) / (pow(widthfactor, (SCIP_Real)(n/2)) - 1.0); /*lint !e653*/
    7055 else
    7056 width /= 0.5 + widthfactor * (pow(widthfactor, (SCIP_Real)(n/2)) - 1.0) / (widthfactor - 1.0); /*lint !e653*/
    7057 }
    7058 if( SCIPvarIsIntegral(var) )
    7059 minwidth = MAX(1.0, minwidth);
    7060 if( width < minwidth )
    7061 width = minwidth;
    7062 assert(SCIPsetIsPositive(set, width));
    7063
    7064 SCIPsetDebugMsg(set, "%d-ary branching on variable <%s> [%g, %g] around %g, initial width = %g\n",
    7065 n, SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), val, width);
    7066
    7067 if( nchildren != NULL )
    7068 *nchildren = 0;
    7069
    7070 /* initialize upper bound on children left of val and children right of val
    7071 * if we are supposed to create an odd number of children, then create a child that has val in the middle of its domain */
    7072 if( n % 2 == 1 )
    7073 {
    7074 left = val - width/2.0;
    7075 right = val + width/2.0;
    7076 SCIPvarAdjustLb(var, set, &left);
    7077 SCIPvarAdjustUb(var, set, &right);
    7078
    7079 /* create child node left <= x <= right, if left <= right */
    7080 if( left <= right )
    7081 {
    7082 priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_FIXED, val); /* ????????????? how to compute priority for such a child? */
    7083 /* if LP solution is cutoff in child, compute a new estimate
    7084 * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node */
    7085 if( SCIPsetIsLT(set, lpval, left) )
    7086 estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, left);
    7087 else if( SCIPsetIsGT(set, lpval, right) )
    7088 estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, right);
    7089 else
    7090 estimate = SCIPnodeGetEstimate(tree->focusnode);
    7091
    7092 SCIPsetDebugMsg(set, " -> creating middle child: %g <= <%s> <= %g (priority: %g, estimate: %g, width: %g)\n",
    7093 left, SCIPvarGetName(var), right, priority, estimate, right - left);
    7094
    7095 SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
    7096 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
    7097 eventqueue, eventfilter, NULL, var, left , SCIP_BOUNDTYPE_LOWER, FALSE) );
    7098 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    7099 eventfilter, NULL, var, right, SCIP_BOUNDTYPE_UPPER, FALSE) );
    7100 /* output branching bound change to visualization file */
    7101 SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
    7102
    7103 if( nchildren != NULL )
    7104 ++*nchildren;
    7105 }
    7106 --n;
    7107
    7108 if( SCIPvarIsIntegral(var) )
    7109 {
    7110 /* 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. */
    7111 left -= 1.0;
    7112 right += 1.0;
    7113 }
    7114
    7115 width *= widthfactor;
    7116 }
    7117 else
    7118 {
    7119 if( SCIPvarIsIntegral(var) )
    7120 {
    7121 left = SCIPsetFloor(set, val);
    7122 right = SCIPsetCeil(set, val);
    7123 if( right - left < 0.5 )
    7124 left -= 1.0;
    7125 }
    7126 else if( SCIPsetIsZero(set, val) )
    7127 {
    7128 left = 0.0;
    7129 right = 0.0;
    7130 }
    7131 else
    7132 {
    7133 left = val;
    7134 right = val;
    7135 }
    7136 }
    7137
    7138 assert(n % 2 == 0);
    7139 n /= 2;
    7140 for( i = 0; i < n; ++i )
    7141 {
    7142 /* create child node left - width <= x <= left, if x is discrete or left > lb(x) */
    7143 if( SCIPvarIsIntegral(var) || SCIPsetIsRelLT(set, SCIPvarGetLbLocal(var), left) )
    7144 {
    7145 /* new lower bound should be variables lower bound, if we are in the last round or left - width is very close to lower bound
    7146 * otherwise we take left - width
    7147 */
    7148 if( i == n-1 || SCIPsetIsRelEQ(set, SCIPvarGetLbLocal(var), left - width))
    7149 {
    7150 bnd = SCIPvarGetLbLocal(var);
    7151 }
    7152 else
    7153 {
    7154 bnd = left - width;
    7155 SCIPvarAdjustLb(var, set, &bnd);
    7156 bnd = MAX(SCIPvarGetLbLocal(var), bnd); /*lint !e666*/
    7157 }
    7158 assert(SCIPsetIsRelLT(set, bnd, left));
    7159
    7160 /* the nodeselection priority of nodes is decreased as more as they are away from val */
    7161 priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_DOWNWARDS, bnd) / (i+1);
    7162 /* if LP solution is cutoff in child, compute a new estimate
    7163 * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node */
    7164 if( SCIPsetIsLT(set, lpval, bnd) )
    7165 estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, bnd);
    7166 else if( SCIPsetIsGT(set, lpval, left) )
    7167 estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, left);
    7168 else
    7169 estimate = SCIPnodeGetEstimate(tree->focusnode);
    7170
    7171 SCIPsetDebugMsg(set, " -> creating left child: %g <= <%s> <= %g (priority: %g, estimate: %g, width: %g)\n",
    7172 bnd, SCIPvarGetName(var), left, priority, estimate, left - bnd);
    7173
    7174 SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
    7175 if( SCIPsetIsGT(set, bnd, SCIPvarGetLbLocal(var)) )
    7176 {
    7177 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    7178 eventfilter, NULL, var, bnd, SCIP_BOUNDTYPE_LOWER, FALSE) );
    7179 }
    7180 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    7181 eventfilter, NULL, var, left, SCIP_BOUNDTYPE_UPPER, FALSE) );
    7182 /* output branching bound change to visualization file */
    7183 SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
    7184
    7185 if( nchildren != NULL )
    7186 ++*nchildren;
    7187
    7188 left = bnd;
    7189 if( SCIPvarIsIntegral(var) )
    7190 left -= 1.0;
    7191 }
    7192
    7193 /* create child node right <= x <= right + width, if x is discrete or right < ub(x) */
    7194 if( SCIPvarIsIntegral(var) || SCIPsetIsRelGT(set, SCIPvarGetUbLocal(var), right) )
    7195 {
    7196 /* new upper bound should be variables upper bound, if we are in the last round or right + width is very close to upper bound
    7197 * otherwise we take right + width
    7198 */
    7199 if( i == n-1 || SCIPsetIsRelEQ(set, SCIPvarGetUbLocal(var), right + width))
    7200 {
    7201 bnd = SCIPvarGetUbLocal(var);
    7202 }
    7203 else
    7204 {
    7205 bnd = right + width;
    7206 SCIPvarAdjustUb(var, set, &bnd);
    7207 bnd = MIN(SCIPvarGetUbLocal(var), bnd); /*lint !e666*/
    7208 }
    7209 assert(SCIPsetIsRelGT(set, bnd, right));
    7210
    7211 /* the nodeselection priority of nodes is decreased as more as they are away from val */
    7212 priority = SCIPtreeCalcNodeselPriority(tree, set, stat, var, SCIP_BRANCHDIR_UPWARDS, bnd) / (i+1);
    7213 /* if LP solution is cutoff in child, compute a new estimate
    7214 * otherwise we cannot expect a direct change in the best solution, so we keep the estimate of the parent node */
    7215 if( SCIPsetIsLT(set, lpval, right) )
    7216 estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, right);
    7217 else if( SCIPsetIsGT(set, lpval, bnd) )
    7218 estimate = SCIPtreeCalcChildEstimate(tree, set, stat, var, bnd);
    7219 else
    7220 estimate = SCIPnodeGetEstimate(tree->focusnode);
    7221
    7222 SCIPsetDebugMsg(set, " -> creating right child: %g <= <%s> <= %g (priority: %g, estimate: %g, width: %g)\n",
    7223 right, SCIPvarGetName(var), bnd, priority, estimate, bnd - right);
    7224
    7225 SCIP_CALL( SCIPnodeCreateChild(&node, blkmem, set, stat, tree, priority, estimate) );
    7226 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    7227 eventfilter, NULL, var, right, SCIP_BOUNDTYPE_LOWER, FALSE) );
    7228 if( SCIPsetIsLT(set, bnd, SCIPvarGetUbLocal(var)) )
    7229 {
    7230 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    7231 eventfilter, NULL, var, bnd, SCIP_BOUNDTYPE_UPPER, FALSE) );
    7232 }
    7233 /* output branching bound change to visualization file */
    7234 SCIP_CALL( SCIPvisualUpdateChild(stat->visual, set, stat, node) );
    7235
    7236 if( nchildren != NULL )
    7237 ++*nchildren;
    7238
    7239 right = bnd;
    7240 if( SCIPvarIsIntegral(var) )
    7241 right += 1.0;
    7242 }
    7243
    7244 width *= widthfactor;
    7245 }
    7246
    7247 return SCIP_OKAY;
    7248}
    7249
    7250/** adds a diving bound change to the tree together with the information if this is a bound change
    7251 * for the preferred direction or not
    7252 */
    7253#define ARRAYGROWTH 5
    7255 SCIP_TREE* tree, /**< branch and bound tree */
    7256 BMS_BLKMEM* blkmem, /**< block memory buffers */
    7257 SCIP_VAR* var, /**< variable to apply the bound change to */
    7258 SCIP_BRANCHDIR dir, /**< direction of the bound change */
    7259 SCIP_Real value, /**< value to adjust this variable bound to */
    7260 SCIP_Bool preferred /**< is this a bound change for the preferred child? */
    7261 )
    7262{
    7263 int idx = preferred ? 0 : 1;
    7264 int pos = tree->ndivebdchanges[idx];
    7265
    7266 assert(pos < tree->divebdchgsize[idx]);
    7267
    7268 if( pos == tree->divebdchgsize[idx] - 1 )
    7269 {
    7270 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tree->divebdchgdirs[idx], tree->divebdchgsize[idx], tree->divebdchgsize[idx] + ARRAYGROWTH) ); /*lint !e866*/
    7271 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tree->divebdchgvars[idx], tree->divebdchgsize[idx], tree->divebdchgsize[idx] + ARRAYGROWTH) ); /*lint !e866*/
    7272 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tree->divebdchgvals[idx], tree->divebdchgsize[idx], tree->divebdchgsize[idx] + ARRAYGROWTH) ); /*lint !e866*/
    7273 tree->divebdchgsize[idx] += ARRAYGROWTH;
    7274 }
    7275
    7276 tree->divebdchgvars[idx][pos] = var;
    7277 tree->divebdchgdirs[idx][pos] = dir;
    7278 tree->divebdchgvals[idx][pos] = value;
    7279
    7280 ++tree->ndivebdchanges[idx];
    7281
    7282 return SCIP_OKAY;
    7283}
    7284
    7285/** get the dive bound change data for the preferred or the alternative direction */
    7287 SCIP_TREE* tree, /**< branch and bound tree */
    7288 SCIP_VAR*** variables, /**< pointer to store variables for the specified direction */
    7289 SCIP_BRANCHDIR** directions, /**< pointer to store the branching directions */
    7290 SCIP_Real** values, /**< pointer to store bound change values */
    7291 int* ndivebdchgs, /**< pointer to store the number of dive bound changes */
    7292 SCIP_Bool preferred /**< should the dive bound changes for the preferred child be output? */
    7293 )
    7294{
    7295 int idx = preferred ? 0 : 1;
    7296
    7297 assert(variables != NULL);
    7298 assert(directions != NULL);
    7299 assert(values != NULL);
    7300 assert(ndivebdchgs != NULL);
    7301
    7302 *variables = tree->divebdchgvars[idx];
    7303 *directions = tree->divebdchgdirs[idx];
    7304 *values = tree->divebdchgvals[idx];
    7305 *ndivebdchgs = tree->ndivebdchanges[idx];
    7306}
    7307
    7308/** clear the tree bound change data structure */
    7310 SCIP_TREE* tree /**< branch and bound tree */
    7311 )
    7312{
    7313 int p;
    7314
    7315 for( p = 0; p < 2; ++p )
    7316 tree->ndivebdchanges[p] = 0;
    7317}
    7318
    7319/** creates a probing child node of the current node, which must be the focus node, the current refocused node,
    7320 * or another probing node; if the current node is the focus or a refocused node, the created probing node is
    7321 * installed as probing root node
    7322 */
    7323static
    7325 SCIP_TREE* tree, /**< branch and bound tree */
    7326 BMS_BLKMEM* blkmem, /**< block memory */
    7327 SCIP_SET* set, /**< global SCIP settings */
    7328 SCIP_LP* lp /**< current LP data */
    7329 )
    7330{
    7331 SCIP_NODE* currentnode;
    7332 SCIP_NODE* node;
    7333 SCIP_RETCODE retcode;
    7334
    7335 assert(tree != NULL);
    7336 assert(SCIPtreeIsPathComplete(tree));
    7337 assert(tree->pathlen > 0);
    7338 assert(blkmem != NULL);
    7339 assert(set != NULL);
    7340
    7341 /* get the current node */
    7342 currentnode = SCIPtreeGetCurrentNode(tree);
    7343 assert(currentnode != NULL);
    7344 assert(SCIPnodeGetType(currentnode) == SCIP_NODETYPE_FOCUSNODE
    7346 || SCIPnodeGetType(currentnode) == SCIP_NODETYPE_PROBINGNODE);
    7347 assert((SCIPnodeGetType(currentnode) == SCIP_NODETYPE_PROBINGNODE) == SCIPtreeProbing(tree));
    7348
    7349 /* create the node data structure */
    7350 SCIP_CALL( nodeCreate(&node, blkmem, set) );
    7351 assert(node != NULL);
    7352
    7353 /* mark node to be a probing node */
    7354 node->nodetype = SCIP_NODETYPE_PROBINGNODE; /*lint !e641*/
    7355
    7356 /* create the probingnode data */
    7357 SCIP_CALL( probingnodeCreate(&node->data.probingnode, blkmem, lp) );
    7358
    7359 /* make the current node the parent of the new probing node */
    7360 retcode = nodeAssignParent(node, blkmem, set, tree, currentnode, 0.0);
    7361
    7362 /* if we reached the maximal depth level we clean up the allocated memory and stop */
    7363 if( retcode == SCIP_MAXDEPTHLEVEL )
    7364 {
    7365 SCIP_CALL( probingnodeFree(&(node->data.probingnode), blkmem, lp) );
    7366 BMSfreeBlockMemory(blkmem, &node);
    7367 }
    7368 SCIP_CALL( retcode );
    7369 assert(SCIPnodeGetDepth(node) == tree->pathlen);
    7370
    7371 /* check, if the node is the probing root node */
    7372 if( tree->probingroot == NULL )
    7373 {
    7374 tree->probingroot = node;
    7375 SCIPsetDebugMsg(set, "created probing root node #%" SCIP_LONGINT_FORMAT " at depth %d\n",
    7376 SCIPnodeGetNumber(node), SCIPnodeGetDepth(node));
    7377 }
    7378 else
    7379 {
    7381 assert(SCIPnodeGetDepth(tree->probingroot) < SCIPnodeGetDepth(node));
    7382
    7383 SCIPsetDebugMsg(set, "created probing child node #%" SCIP_LONGINT_FORMAT " at depth %d, probing depth %d\n",
    7385
    7386 currentnode->data.probingnode->ncols = SCIPlpGetNCols(lp);
    7387 currentnode->data.probingnode->nrows = SCIPlpGetNRows(lp);
    7388
    7389 SCIPsetDebugMsg(set, "updated probingnode information of parent (%d cols, %d rows)\n",
    7390 currentnode->data.probingnode->ncols, currentnode->data.probingnode->nrows);
    7391 }
    7392
    7393 /* create the new active path */
    7394 SCIP_CALL( treeEnsurePathMem(tree, set, tree->pathlen+1) );
    7395 node->active = TRUE;
    7396 tree->path[tree->pathlen] = node;
    7397 tree->pathlen++;
    7398
    7399 /* update the path LP size for the previous node and set the (initial) path LP size for the newly created node */
    7400 SCIP_CALL( treeUpdatePathLPSize(tree, tree->pathlen-2) );
    7401
    7402 /* mark the LP's size */
    7403 SCIPlpMarkSize(lp);
    7404 assert(tree->pathlen >= 2);
    7405 assert(lp->firstnewrow == tree->pathnlprows[tree->pathlen-1]); /* marked LP size should be initial size of new node */
    7406 assert(lp->firstnewcol == tree->pathnlpcols[tree->pathlen-1]);
    7407
    7408 /* the current probing node does not yet have a solved LP */
    7409 tree->probingnodehaslp = FALSE;
    7410
    7411 return SCIP_OKAY;
    7412}
    7413
    7414/** switches to probing mode and creates a probing root */
    7416 SCIP_TREE* tree, /**< branch and bound tree */
    7417 BMS_BLKMEM* blkmem, /**< block memory */
    7418 SCIP_SET* set, /**< global SCIP settings */
    7419 SCIP_LP* lp, /**< current LP data */
    7420 SCIP_RELAXATION* relaxation, /**< global relaxation data */
    7421 SCIP_PROB* transprob, /**< transformed problem after presolve */
    7422 SCIP_Bool strongbranching /**< is the probing mode used for strongbranching? */
    7423 )
    7424{
    7425 assert(tree != NULL);
    7426 assert(tree->probinglpistate == NULL);
    7427 assert(tree->probinglpinorms == NULL);
    7428 assert(!SCIPtreeProbing(tree));
    7429 assert(lp != NULL);
    7430
    7431 SCIPsetDebugMsg(set, "probing started in depth %d (LP flushed: %u, LP solved: %u, solstat: %d), probing root in depth %d\n",
    7432 tree->pathlen-1, lp->flushed, lp->solved, SCIPlpGetSolstat(lp), tree->pathlen);
    7433
    7434 /* store all marked constraints for propagation */
    7435 SCIP_CALL( SCIPconshdlrsStorePropagationStatus(set, set->conshdlrs, set->nconshdlrs) );
    7436
    7437 /* inform LP about probing mode */
    7439
    7440 assert(!lp->divingobjchg);
    7441
    7442 /* remember, whether the LP was flushed and solved */
    7443 tree->probinglpwasflushed = lp->flushed;
    7444 tree->probinglpwassolved = lp->solved;
    7445 tree->probingloadlpistate = FALSE;
    7446 tree->probinglpwasrelax = lp->isrelax;
    7447 lp->isrelax = TRUE;
    7448 tree->probingsolvedlp = FALSE;
    7449 tree->probingobjchanged = FALSE;
    7450 lp->divingobjchg = FALSE;
    7451 tree->probingsumchgdobjs = 0;
    7452 tree->sbprobing = strongbranching;
    7454 if( set->exact_enable && lp->solved )
    7455 tree->probinglpobjval = SCIPlpGetObjval(lp, set, transprob);
    7456
    7457 /* remember the LP state in order to restore the LP solution quickly after probing */
    7458 /**@todo could the lp state be worth storing if the LP is not flushed (and hence not solved)? */
    7459 if( lp->flushed && lp->solved )
    7460 {
    7461 SCIP_CALL( SCIPlpGetState(lp, blkmem, &tree->probinglpistate) );
    7462 SCIP_CALL( SCIPlpGetNorms(lp, blkmem, &tree->probinglpinorms) );
    7467 }
    7468
    7469 /* remember the relaxation solution to reset it later */
    7470 if( SCIPrelaxationIsSolValid(relaxation) )
    7471 {
    7472 SCIP_CALL( SCIPtreeStoreRelaxSol(tree, set, relaxation, transprob) );
    7473 }
    7474
    7475 /* create temporary probing root node */
    7476 SCIP_CALL( treeCreateProbingNode(tree, blkmem, set, lp) );
    7477 assert(SCIPtreeProbing(tree));
    7478
    7479 return SCIP_OKAY;
    7480}
    7481
    7482/** creates a new probing child node in the probing path */
    7484 SCIP_TREE* tree, /**< branch and bound tree */
    7485 BMS_BLKMEM* blkmem, /**< block memory */
    7486 SCIP_SET* set, /**< global SCIP settings */
    7487 SCIP_LP* lp /**< current LP data */
    7488 )
    7489{
    7490 assert(SCIPtreeProbing(tree));
    7491
    7492 SCIPsetDebugMsg(set, "new probing child in depth %d (probing depth: %d)\n", tree->pathlen, tree->pathlen-1 - SCIPnodeGetDepth(tree->probingroot));
    7493
    7494 /* create temporary probing root node */
    7495 SCIP_CALL( treeCreateProbingNode(tree, blkmem, set, lp) );
    7496
    7497 return SCIP_OKAY;
    7498}
    7499
    7500/** sets the LP state for the current probing node
    7501 *
    7502 * @note state and norms are stored at the node and later released by SCIP; therefore, the pointers are set
    7503 * to NULL by the method
    7504 *
    7505 * @note the pointers to state and norms must not be NULL; however, they may point to a NULL pointer if the
    7506 * respective information should not be set
    7507 */
    7509 SCIP_TREE* tree, /**< branch and bound tree */
    7510 BMS_BLKMEM* blkmem, /**< block memory */
    7511 SCIP_LP* lp, /**< current LP data */
    7512 SCIP_LPISTATE** lpistate, /**< pointer to LP state information (like basis information) */
    7513 SCIP_LPINORMS** lpinorms, /**< pointer to LP pricing norms information */
    7514 SCIP_Bool primalfeas, /**< primal feasibility when LP state information was stored */
    7515 SCIP_Bool dualfeas /**< dual feasibility when LP state information was stored */
    7516 )
    7517{
    7518 SCIP_NODE* node;
    7519
    7520 assert(tree != NULL);
    7521 assert(SCIPtreeProbing(tree));
    7522 assert(lpistate != NULL);
    7523 assert(lpinorms != NULL);
    7524
    7525 /* get the current probing node */
    7526 node = SCIPtreeGetCurrentNode(tree);
    7527
    7528 /* this check is necessary to avoid cppcheck warnings */
    7529 if( node == NULL )
    7530 return SCIP_INVALIDDATA;
    7531
    7533 assert(node->data.probingnode != NULL);
    7534
    7535 /* free already present LP state */
    7536 if( node->data.probingnode->lpistate != NULL )
    7537 {
    7538 SCIP_CALL( SCIPlpFreeState(lp, blkmem, &(node->data.probingnode->lpistate)) );
    7539 }
    7540
    7541 /* free already present LP pricing norms */
    7542 if( node->data.probingnode->lpinorms != NULL )
    7543 {
    7544 SCIP_CALL( SCIPlpFreeNorms(lp, blkmem, &(node->data.probingnode->lpinorms)) );
    7545 }
    7546
    7547 node->data.probingnode->lpistate = *lpistate;
    7548 node->data.probingnode->lpinorms = *lpinorms;
    7549 node->data.probingnode->lpwasprimfeas = primalfeas;
    7550 node->data.probingnode->lpwasdualfeas = dualfeas;
    7551
    7552 /* set the pointers to NULL to avoid that they are still used and modified by the caller */
    7553 *lpistate = NULL;
    7554 *lpinorms = NULL;
    7555
    7556 tree->probingloadlpistate = TRUE;
    7557
    7558 return SCIP_OKAY;
    7559}
    7560
    7561/** loads the LP state for the current probing node */
    7563 SCIP_TREE* tree, /**< branch and bound tree */
    7564 BMS_BLKMEM* blkmem, /**< block memory buffers */
    7565 SCIP_SET* set, /**< global SCIP settings */
    7566 SCIP_PROB* prob, /**< problem data */
    7567 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    7568 SCIP_LP* lp /**< current LP data */
    7569 )
    7570{
    7571 assert(tree != NULL);
    7572 assert(SCIPtreeProbing(tree));
    7573
    7574 /* loading the LP state is only necessary if we backtracked */
    7575 if( tree->probingloadlpistate )
    7576 {
    7577 SCIP_NODE* node;
    7578 SCIP_LPISTATE* lpistate;
    7579 SCIP_LPINORMS* lpinorms;
    7580 SCIP_Bool lpwasprimfeas = FALSE;
    7581 SCIP_Bool lpwasprimchecked = FALSE;
    7582 SCIP_Bool lpwasdualfeas = FALSE;
    7583 SCIP_Bool lpwasdualchecked = FALSE;
    7584
    7585 /* get the current probing node */
    7586 node = SCIPtreeGetCurrentNode(tree);
    7587 assert(node != NULL);
    7589
    7590 /* search the last node where an LP state information was attached */
    7591 lpistate = NULL;
    7592 lpinorms = NULL;
    7593 do
    7594 {
    7596 assert(node->data.probingnode != NULL);
    7597 if( node->data.probingnode->lpistate != NULL )
    7598 {
    7599 lpistate = node->data.probingnode->lpistate;
    7600 lpinorms = node->data.probingnode->lpinorms;
    7601 lpwasprimfeas = node->data.probingnode->lpwasprimfeas;
    7602 lpwasprimchecked = node->data.probingnode->lpwasprimchecked;
    7603 lpwasdualfeas = node->data.probingnode->lpwasdualfeas;
    7604 lpwasdualchecked = node->data.probingnode->lpwasdualchecked;
    7605 break;
    7606 }
    7607 node = node->parent;
    7608 assert(node != NULL); /* the root node cannot be a probing node! */
    7609 }
    7611
    7612 /* if there was no LP information stored in the probing nodes, use the one stored before probing started */
    7613 if( lpistate == NULL )
    7614 {
    7615 lpistate = tree->probinglpistate;
    7616 lpinorms = tree->probinglpinorms;
    7617 lpwasprimfeas = tree->probinglpwasprimfeas;
    7618 lpwasprimchecked = tree->probinglpwasprimchecked;
    7619 lpwasdualfeas = tree->probinglpwasdualfeas;
    7620 lpwasdualchecked = tree->probinglpwasdualchecked;
    7621 }
    7622
    7623 /* set the LP state */
    7624 if( lpistate != NULL )
    7625 {
    7626 SCIP_CALL( SCIPlpSetState(lp, blkmem, set, prob, eventqueue, lpistate,
    7627 lpwasprimfeas, lpwasprimchecked, lpwasdualfeas, lpwasdualchecked) );
    7628 }
    7629
    7630 /* set the LP pricing norms */
    7631 if( lpinorms != NULL )
    7632 {
    7633 SCIP_CALL( SCIPlpSetNorms(lp, blkmem, lpinorms) );
    7634 }
    7635
    7636 /* now we don't need to load the LP state again until the next backtracking */
    7637 tree->probingloadlpistate = FALSE;
    7638 }
    7639
    7640 return SCIP_OKAY;
    7641}
    7642
    7643/** marks the probing node to have a solved LP relaxation */
    7645 SCIP_TREE* tree, /**< branch and bound tree */
    7646 BMS_BLKMEM* blkmem, /**< block memory */
    7647 SCIP_LP* lp /**< current LP data */
    7648 )
    7649{
    7650 SCIP_NODE* node;
    7651
    7652 assert(tree != NULL);
    7653 assert(SCIPtreeProbing(tree));
    7654
    7655 /* mark the probing node to have an LP */
    7656 tree->probingnodehaslp = TRUE;
    7657
    7658 /* get current probing node */
    7659 node = SCIPtreeGetCurrentNode(tree);
    7660 assert(node != NULL);
    7662 assert(node->data.probingnode != NULL);
    7663
    7664 /* update LP information in probingnode data */
    7665 SCIP_CALL( probingnodeUpdate(node->data.probingnode, blkmem, tree, lp) );
    7666
    7667 return SCIP_OKAY;
    7668}
    7669
    7670/** undoes all changes to the problem applied in probing up to the given probing depth */
    7671static
    7673 SCIP_TREE* tree, /**< branch and bound tree */
    7674 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7675 BMS_BLKMEM* blkmem, /**< block memory buffers */
    7676 SCIP_SET* set, /**< global SCIP settings */
    7677 SCIP_STAT* stat, /**< problem statistics */
    7678 SCIP_PROB* transprob, /**< transformed problem after presolve */
    7679 SCIP_PROB* origprob, /**< original problem */
    7680 SCIP_LP* lp, /**< current LP data */
    7681 SCIP_PRIMAL* primal, /**< primal data structure */
    7682 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    7683 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    7684 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    7685 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    7686 int probingdepth /**< probing depth of the node in the probing path that should be reactivated,
    7687 * -1 to even deactivate the probing root, thus exiting probing mode */
    7688 )
    7689{
    7690 int newpathlen;
    7691 int i;
    7692
    7693 assert(tree != NULL);
    7694 assert(SCIPtreeProbing(tree));
    7695 assert(tree->probingroot != NULL);
    7696 assert(tree->focusnode != NULL);
    7700 assert(tree->probingroot->parent == tree->focusnode);
    7701 assert(SCIPnodeGetDepth(tree->probingroot) == SCIPnodeGetDepth(tree->focusnode)+1);
    7702 assert(tree->pathlen >= 2);
    7703 assert(SCIPnodeGetType(tree->path[tree->pathlen-1]) == SCIP_NODETYPE_PROBINGNODE);
    7704 assert(-1 <= probingdepth && probingdepth <= SCIPtreeGetProbingDepth(tree));
    7705
    7706 treeCheckPath(tree);
    7707
    7708 newpathlen = SCIPnodeGetDepth(tree->probingroot) + probingdepth + 1;
    7709 assert(newpathlen >= 1); /* at least root node of the tree remains active */
    7710
    7711 /* check if we have to do any backtracking */
    7712 if( newpathlen < tree->pathlen )
    7713 {
    7714 int ncols;
    7715 int nrows;
    7716
    7717 /* the correct LP size of the node to which we backtracked is stored as initial LP size for its child */
    7718 assert(SCIPnodeGetType(tree->path[newpathlen]) == SCIP_NODETYPE_PROBINGNODE);
    7719 ncols = tree->path[newpathlen]->data.probingnode->ninitialcols;
    7720 nrows = tree->path[newpathlen]->data.probingnode->ninitialrows;
    7721 assert(ncols >= tree->pathnlpcols[newpathlen-1] || !tree->focuslpconstructed);
    7722 assert(nrows >= tree->pathnlprows[newpathlen-1] || !tree->focuslpconstructed);
    7723
    7724 while( tree->pathlen > newpathlen )
    7725 {
    7726 SCIP_NODE* node;
    7727
    7728 node = tree->path[tree->pathlen-1];
    7729
    7731 assert(tree->pathlen-1 == SCIPnodeGetDepth(node));
    7732 assert(tree->pathlen-1 >= SCIPnodeGetDepth(tree->probingroot));
    7733
    7734 if( node->data.probingnode->nchgdobjs > 0 )
    7735 {
    7736 /* @todo only do this if we don't backtrack to the root node - in that case, we can just restore the unchanged
    7737 * objective values
    7738 */
    7739 for( i = node->data.probingnode->nchgdobjs - 1; i >= 0; --i )
    7740 {
    7741 assert(tree->probingobjchanged);
    7742
    7743 SCIP_CALL( SCIPvarChgObj(node->data.probingnode->origobjvars[i], blkmem, set, transprob, primal, lp,
    7744 eventqueue, node->data.probingnode->origobjvals[i]) );
    7745 }
    7747 assert(tree->probingsumchgdobjs >= 0);
    7748
    7749 /* reset probingobjchanged flag and cutoff bound */
    7750 if( tree->probingsumchgdobjs == 0 )
    7751 {
    7753 tree->probingobjchanged = FALSE;
    7754
    7755 SCIP_CALL( SCIPlpSetCutoffbound(lp, set, transprob, primal->cutoffbound) );
    7756 }
    7757
    7758 /* recompute global and local pseudo objective values */
    7760 }
    7761
    7762 /* undo bound changes by deactivating the probing node */
    7763 SCIP_CALL( nodeDeactivate(node, blkmem, set, stat, tree, lp, branchcand, eventqueue) );
    7764
    7765 /* free the probing node */
    7766 SCIP_CALL( SCIPnodeFree(&tree->path[tree->pathlen-1], blkmem, set, stat, eventqueue, eventfilter, tree, lp) );
    7767 tree->pathlen--;
    7768 }
    7769 assert(tree->pathlen == newpathlen);
    7770
    7771 /* reset the path LP size to the initial size of the probing node */
    7772 if( SCIPnodeGetType(tree->path[tree->pathlen-1]) == SCIP_NODETYPE_PROBINGNODE )
    7773 {
    7774 tree->pathnlpcols[tree->pathlen-1] = tree->path[tree->pathlen-1]->data.probingnode->ninitialcols;
    7775 tree->pathnlprows[tree->pathlen-1] = tree->path[tree->pathlen-1]->data.probingnode->ninitialrows;
    7776 }
    7777 else
    7778 assert(SCIPnodeGetType(tree->path[tree->pathlen-1]) == SCIP_NODETYPE_FOCUSNODE);
    7779 treeCheckPath(tree);
    7780
    7781 /* undo LP extensions */
    7782 SCIP_CALL( SCIPlpShrinkCols(lp, set, ncols) );
    7783 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, nrows) );
    7784 tree->probingloadlpistate = TRUE; /* LP state must be reloaded if the next LP is solved */
    7785
    7786 /* reset the LP's marked size to the initial size of the LP at the node stored in the path */
    7787 assert(lp->nrows >= tree->pathnlprows[tree->pathlen-1] || !tree->focuslpconstructed);
    7788 assert(lp->ncols >= tree->pathnlpcols[tree->pathlen-1] || !tree->focuslpconstructed);
    7789 SCIPlpSetSizeMark(lp, tree->pathnlprows[tree->pathlen-1], tree->pathnlpcols[tree->pathlen-1]);
    7790
    7791 /* if the highest cutoff or repropagation depth is inside the deleted part of the probing path,
    7792 * reset them to infinity
    7793 */
    7794 if( tree->cutoffdepth >= tree->pathlen )
    7795 {
    7796 /* apply the pending bound changes */
    7797 SCIP_CALL( treeApplyPendingBdchgs(tree, reopt, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue, eventfilter, cliquetable) );
    7798
    7799 /* applying the pending bound changes might have changed the cutoff depth; so the highest cutoff depth might
    7800 * be outside of the deleted part of the probing path now
    7801 */
    7802 if( tree->cutoffdepth >= tree->pathlen )
    7803 tree->cutoffdepth = INT_MAX;
    7804 }
    7805 if( tree->repropdepth >= tree->pathlen )
    7806 tree->repropdepth = INT_MAX;
    7807 }
    7808
    7809 SCIPsetDebugMsg(set, "probing backtracked to depth %d (%d cols, %d rows)\n", tree->pathlen-1, SCIPlpGetNCols(lp), SCIPlpGetNRows(lp));
    7810
    7811 return SCIP_OKAY;
    7812}
    7813
    7814/** undoes all changes to the problem applied in probing up to the given probing depth;
    7815 * the changes of the probing node of the given probing depth are the last ones that remain active;
    7816 * changes that were applied before calling SCIPtreeCreateProbingNode() cannot be undone
    7817 */
    7819 SCIP_TREE* tree, /**< branch and bound tree */
    7820 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7821 BMS_BLKMEM* blkmem, /**< block memory buffers */
    7822 SCIP_SET* set, /**< global SCIP settings */
    7823 SCIP_STAT* stat, /**< problem statistics */
    7824 SCIP_PROB* transprob, /**< transformed problem */
    7825 SCIP_PROB* origprob, /**< original problem */
    7826 SCIP_LP* lp, /**< current LP data */
    7827 SCIP_PRIMAL* primal, /**< primal data structure */
    7828 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    7829 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    7830 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    7831 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    7832 int probingdepth /**< probing depth of the node in the probing path that should be reactivated */
    7833 )
    7834{
    7835 assert(tree != NULL);
    7836 assert(SCIPtreeProbing(tree));
    7837 assert(0 <= probingdepth && probingdepth <= SCIPtreeGetProbingDepth(tree));
    7838
    7839 /* undo the domain and constraint set changes and free the temporary probing nodes below the given probing depth */
    7840 SCIP_CALL( treeBacktrackProbing(tree, reopt, blkmem, set, stat, transprob, origprob, lp, primal, branchcand,
    7841 eventqueue, eventfilter, cliquetable, probingdepth) );
    7842
    7843 assert(SCIPtreeProbing(tree));
    7845
    7846 return SCIP_OKAY;
    7847}
    7848
    7849/** switches back from probing to normal operation mode, frees all nodes on the probing path, restores bounds of all
    7850 * variables and restores active constraints arrays of focus node
    7851 */
    7853 SCIP_TREE* tree, /**< branch and bound tree */
    7854 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7855 BMS_BLKMEM* blkmem, /**< block memory buffers */
    7856 SCIP_SET* set, /**< global SCIP settings */
    7857 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
    7858 SCIP_STAT* stat, /**< problem statistics */
    7859 SCIP_PROB* transprob, /**< transformed problem after presolve */
    7860 SCIP_PROB* origprob, /**< original problem */
    7861 SCIP_LP* lp, /**< current LP data */
    7862 SCIP_RELAXATION* relaxation, /**< global relaxation data */
    7863 SCIP_PRIMAL* primal, /**< Primal LP data */
    7864 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    7865 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    7866 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    7867 SCIP_CLIQUETABLE* cliquetable /**< clique table data structure */
    7868 )
    7869{
    7870 assert(tree != NULL);
    7871 assert(SCIPtreeProbing(tree));
    7872 assert(tree->probingroot != NULL);
    7873 assert(tree->focusnode != NULL);
    7877 assert(tree->probingroot->parent == tree->focusnode);
    7878 assert(SCIPnodeGetDepth(tree->probingroot) == SCIPnodeGetDepth(tree->focusnode)+1);
    7879 assert(tree->pathlen >= 2);
    7880 assert(SCIPnodeGetType(tree->path[tree->pathlen-1]) == SCIP_NODETYPE_PROBINGNODE);
    7881 assert(set != NULL);
    7882
    7883 /* undo the domain and constraint set changes of the temporary probing nodes and free the probing nodes */
    7884 SCIP_CALL( treeBacktrackProbing(tree, reopt, blkmem, set, stat, transprob, origprob, lp, primal, branchcand,
    7885 eventqueue, eventfilter, cliquetable, -1) );
    7886 assert(tree->probingsumchgdobjs == 0);
    7887 assert(!tree->probingobjchanged);
    7888 assert(!lp->divingobjchg);
    7889 assert(lp->cutoffbound == primal->cutoffbound); /*lint !e777*/
    7890 assert(SCIPtreeGetCurrentNode(tree) == tree->focusnode);
    7891 assert(!SCIPtreeProbing(tree));
    7892
    7893 /* if the LP was flushed before probing starts, flush it again */
    7894 if( tree->probinglpwasflushed )
    7895 {
    7896 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, transprob, eventqueue) );
    7897
    7898 /* if the LP was solved before probing starts, solve it again to restore the LP solution */
    7899 if( tree->probinglpwassolved )
    7900 {
    7901 SCIP_Bool lperror;
    7902
    7903 /* reset the LP state before probing started */
    7904 if( tree->probinglpistate == NULL )
    7905 {
    7906 assert(tree->probinglpinorms == NULL);
    7908 lp->primalfeasible = (lp->nlpicols == 0 && lp->nlpirows == 0);
    7909 lp->primalchecked = (lp->nlpicols == 0 && lp->nlpirows == 0);
    7910 lp->dualfeasible = (lp->nlpicols == 0 && lp->nlpirows == 0);
    7911 lp->dualchecked = (lp->nlpicols == 0 && lp->nlpirows == 0);
    7912 lp->solisbasic = FALSE;
    7913 }
    7914 else
    7915 {
    7916 SCIP_CALL( SCIPlpSetState(lp, blkmem, set, transprob, eventqueue, tree->probinglpistate,
    7918 tree->probinglpwasdualchecked) );
    7919 SCIP_CALL( SCIPlpFreeState(lp, blkmem, &tree->probinglpistate) );
    7920
    7921 if( tree->probinglpinorms != NULL )
    7922 {
    7923 SCIP_CALL( SCIPlpSetNorms(lp, blkmem, tree->probinglpinorms) );
    7924 SCIP_CALL( SCIPlpFreeNorms(lp, blkmem, &tree->probinglpinorms) );
    7925 tree->probinglpinorms = NULL;
    7926 }
    7927 }
    7929
    7930 /* resolve LP to reset solution */
    7931 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, FALSE, FALSE, &lperror) );
    7932
    7933 if( set->exact_enable )
    7934 {
    7936 {
    7937 lp->solved = FALSE;
    7939 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, transprob, -1LL, FALSE, FALSE, FALSE, FALSE, &lperror) );
    7940 }
    7941 /* here we always set this, or the lpobjval would not longer be safe */
    7942 lp->lpobjval = tree->probinglpobjval;
    7944 }
    7945
    7946 if( lperror )
    7947 {
    7948 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
    7949 "(node %" SCIP_LONGINT_FORMAT ") unresolved numerical troubles while resolving LP %" SCIP_LONGINT_FORMAT " after probing\n",
    7950 stat->nnodes, stat->nlps);
    7951 lp->resolvelperror = TRUE;
    7952 tree->focusnodehaslp = FALSE;
    7953 }
    7958 {
    7959 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
    7960 "LP was not resolved to a sufficient status after probing\n");
    7961 lp->resolvelperror = TRUE;
    7962 tree->focusnodehaslp = FALSE;
    7963 }
    7964 else if( tree->focuslpconstructed && SCIPlpIsRelax(lp) && SCIPprobAllColsInLP(transprob, set, lp)
    7965 && (!set->exact_enable || lp->hasprovedbound) )
    7966 {
    7967 SCIP_CALL( SCIPnodeUpdateLowerboundLP(tree->focusnode, set, stat, messagehdlr, eventfilter, tree, transprob, origprob, lp) );
    7968 }
    7969 }
    7970 }
    7971 else
    7972 lp->flushed = FALSE;
    7973
    7974 assert(tree->probinglpistate == NULL);
    7975
    7976 /* if no LP was solved during probing and the LP before probing was not solved, then it should not be solved now */
    7977 assert(tree->probingsolvedlp || tree->probinglpwassolved || !lp->solved);
    7978
    7979 /* if the LP was solved (and hence flushed) before probing, then lp->solved should be TRUE unless we occured an error
    7980 * during resolving right above
    7981 */
    7982 assert(!tree->probinglpwassolved || !tree->probinglpwasflushed || lp->solved || lp->resolvelperror);
    7983
    7984 /* if the LP was not solved before probing it should be marked unsolved now; this can occur if a probing LP was
    7985 * solved in between
    7986 */
    7987 if( !tree->probinglpwassolved )
    7988 {
    7989 lp->solved = FALSE;
    7991 }
    7992
    7993 /* if the LP was solved during probing, but had been unsolved before probing started, we discard the LP state */
    7994 if( set->lp_clearinitialprobinglp && tree->probingsolvedlp && !tree->probinglpwassolved )
    7995 {
    7996 SCIPsetDebugMsg(set, "clearing lp state at end of probing mode because LP was initially unsolved\n");
    7998 }
    7999
    8000 /* if a relaxation was stored before probing, restore it now */
    8001 if( tree->probdiverelaxstored )
    8002 {
    8003 SCIP_CALL( SCIPtreeRestoreRelaxSol(tree, set, relaxation, transprob) );
    8004 }
    8005
    8006 assert(tree->probingobjchanged == SCIPlpDivingObjChanged(lp));
    8007
    8008 /* reset flags */
    8009 tree->probinglpwasflushed = FALSE;
    8010 tree->probinglpwassolved = FALSE;
    8011 tree->probingloadlpistate = FALSE;
    8012 tree->probinglpwasrelax = FALSE;
    8013 tree->probingsolvedlp = FALSE;
    8014 tree->sbprobing = FALSE;
    8015
    8016 /* inform LP about end of probing mode */
    8018
    8019 if( set->exact_enable )
    8020 {
    8021 lp->pseudoobjvalid = FALSE;
    8022 if( SCIPnodeGetDepth(tree->focusnode) == 0 )
    8024 }
    8025
    8026 /* reset all marked constraints for propagation */
    8027 SCIP_CALL( SCIPconshdlrsResetPropagationStatus(set, blkmem, set->conshdlrs, set->nconshdlrs) );
    8028
    8029 SCIPsetDebugMsg(set, "probing ended in depth %d (LP flushed: %u, solstat: %d)\n", tree->pathlen-1, lp->flushed, SCIPlpGetSolstat(lp));
    8030
    8031 return SCIP_OKAY;
    8032}
    8033
    8034/** stores relaxation solution before diving or probing */
    8036 SCIP_TREE* tree, /**< branch and bound tree */
    8037 SCIP_SET* set, /**< global SCIP settings */
    8038 SCIP_RELAXATION* relaxation, /**< global relaxation data */
    8039 SCIP_PROB* transprob /**< transformed problem after presolve */
    8040 )
    8041{
    8042 SCIP_VAR** vars;
    8043 int nvars;
    8044 int v;
    8045
    8046 assert(tree != NULL);
    8047 assert(set != NULL);
    8048 assert(relaxation != NULL);
    8049 assert(transprob != NULL);
    8050 assert(SCIPrelaxationIsSolValid(relaxation));
    8051
    8052 nvars = SCIPprobGetNVars(transprob);
    8053 vars = SCIPprobGetVars(transprob);
    8054
    8055 /* check if memory still needs to be allocated or resized */
    8056 if( tree->probdiverelaxsol == NULL )
    8057 {
    8059 tree->nprobdiverelaxsol = nvars;
    8060 }
    8061 else if( nvars > tree->nprobdiverelaxsol )
    8062 {
    8064 tree->nprobdiverelaxsol = nvars;
    8065 }
    8066 assert(tree->nprobdiverelaxsol >= nvars);
    8067
    8068 /* iterate over all variables to save the relaxation solution */
    8069 for( v = 0; v < nvars; ++v )
    8070 tree->probdiverelaxsol[v] = SCIPvarGetRelaxSol(vars[v], set);
    8071
    8072 tree->probdiverelaxstored = TRUE;
    8074
    8075 return SCIP_OKAY;
    8076}
    8077
    8078/** restores relaxation solution after diving or probing */
    8080 SCIP_TREE* tree, /**< branch and bound tree */
    8081 SCIP_SET* set, /**< global SCIP settings */
    8082 SCIP_RELAXATION* relaxation, /**< global relaxation data */
    8083 SCIP_PROB* transprob /**< transformed problem after presolve */
    8084 )
    8085{
    8086 SCIP_VAR** vars;
    8087 int nvars;
    8088 int v;
    8089
    8090 assert(tree != NULL);
    8091 assert(set != NULL);
    8092 assert(tree->probdiverelaxstored);
    8093 assert(tree->probdiverelaxsol != NULL);
    8094
    8095 nvars = SCIPprobGetNVars(transprob);
    8096 vars = SCIPprobGetVars(transprob);
    8097 assert( nvars <= tree->nprobdiverelaxsol );
    8098
    8099 /* iterate over all variables to restore the relaxation solution */
    8100 for( v = 0; v < nvars; ++v )
    8101 {
    8102 SCIP_CALL( SCIPvarSetRelaxSol(vars[v], set, relaxation, tree->probdiverelaxsol[v], TRUE) );
    8103 }
    8104
    8105 tree->probdiverelaxstored = FALSE;
    8107
    8108 return SCIP_OKAY;
    8109}
    8110
    8111/** gets the best child of the focus node w.r.t. the node selection priority assigned by the branching rule */
    8113 SCIP_TREE* tree /**< branch and bound tree */
    8114 )
    8115{
    8116 SCIP_NODE* bestnode;
    8117 SCIP_Real bestprio;
    8118 int i;
    8119
    8120 assert(tree != NULL);
    8121
    8122 bestnode = NULL;
    8123 bestprio = SCIP_REAL_MIN;
    8124 for( i = 0; i < tree->nchildren; ++i )
    8125 {
    8126 if( tree->childrenprio[i] > bestprio )
    8127 {
    8128 bestnode = tree->children[i];
    8129 bestprio = tree->childrenprio[i];
    8130 }
    8131 }
    8132 assert((tree->nchildren == 0) == (bestnode == NULL));
    8133
    8134 return bestnode;
    8135}
    8136
    8137/** gets the best sibling of the focus node w.r.t. the node selection priority assigned by the branching rule */
    8139 SCIP_TREE* tree /**< branch and bound tree */
    8140 )
    8141{
    8142 SCIP_NODE* bestnode;
    8143 SCIP_Real bestprio;
    8144 int i;
    8145
    8146 assert(tree != NULL);
    8147
    8148 bestnode = NULL;
    8149 bestprio = SCIP_REAL_MIN;
    8150 for( i = 0; i < tree->nsiblings; ++i )
    8151 {
    8152 if( tree->siblingsprio[i] > bestprio )
    8153 {
    8154 bestnode = tree->siblings[i];
    8155 bestprio = tree->siblingsprio[i];
    8156 }
    8157 }
    8158 assert((tree->nsiblings == 0) == (bestnode == NULL));
    8159
    8160 return bestnode;
    8161}
    8162
    8163/** gets the best child of the focus node w.r.t. the node selection strategy */
    8165 SCIP_TREE* tree, /**< branch and bound tree */
    8166 SCIP_SET* set /**< global SCIP settings */
    8167 )
    8168{
    8169 SCIP_NODESEL* nodesel;
    8170 SCIP_NODE* bestnode;
    8171 int i;
    8172
    8173 assert(tree != NULL);
    8174
    8175 nodesel = SCIPnodepqGetNodesel(tree->leaves);
    8176 assert(nodesel != NULL);
    8177
    8178 bestnode = NULL;
    8179 for( i = 0; i < tree->nchildren; ++i )
    8180 {
    8181 if( bestnode == NULL || SCIPnodeselCompare(nodesel, set, tree->children[i], bestnode) < 0 )
    8182 {
    8183 bestnode = tree->children[i];
    8184 }
    8185 }
    8186
    8187 return bestnode;
    8188}
    8189
    8190/** gets the best sibling of the focus node w.r.t. the node selection strategy */
    8192 SCIP_TREE* tree, /**< branch and bound tree */
    8193 SCIP_SET* set /**< global SCIP settings */
    8194 )
    8195{
    8196 SCIP_NODESEL* nodesel;
    8197 SCIP_NODE* bestnode;
    8198 int i;
    8199
    8200 assert(tree != NULL);
    8201
    8202 nodesel = SCIPnodepqGetNodesel(tree->leaves);
    8203 assert(nodesel != NULL);
    8204
    8205 bestnode = NULL;
    8206 for( i = 0; i < tree->nsiblings; ++i )
    8207 {
    8208 if( bestnode == NULL || SCIPnodeselCompare(nodesel, set, tree->siblings[i], bestnode) < 0 )
    8209 {
    8210 bestnode = tree->siblings[i];
    8211 }
    8212 }
    8213
    8214 return bestnode;
    8215}
    8216
    8217/** gets the best leaf from the node queue w.r.t. the node selection strategy */
    8219 SCIP_TREE* tree /**< branch and bound tree */
    8220 )
    8221{
    8222 assert(tree != NULL);
    8223
    8224 return SCIPnodepqFirst(tree->leaves);
    8225}
    8226
    8227/** gets the best node from the tree (child, sibling, or leaf) w.r.t. the node selection strategy */
    8229 SCIP_TREE* tree, /**< branch and bound tree */
    8230 SCIP_SET* set /**< global SCIP settings */
    8231 )
    8232{
    8233 SCIP_NODESEL* nodesel;
    8234 SCIP_NODE* bestchild;
    8235 SCIP_NODE* bestsibling;
    8236 SCIP_NODE* bestleaf;
    8237 SCIP_NODE* bestnode;
    8238
    8239 assert(tree != NULL);
    8240
    8241 nodesel = SCIPnodepqGetNodesel(tree->leaves);
    8242 assert(nodesel != NULL);
    8243
    8244 /* get the best child, sibling, and leaf */
    8245 bestchild = SCIPtreeGetBestChild(tree, set);
    8246 bestsibling = SCIPtreeGetBestSibling(tree, set);
    8247 bestleaf = SCIPtreeGetBestLeaf(tree);
    8248
    8249 /* return the best of the three */
    8250 bestnode = bestchild;
    8251 if( bestsibling != NULL && (bestnode == NULL || SCIPnodeselCompare(nodesel, set, bestsibling, bestnode) < 0) )
    8252 bestnode = bestsibling;
    8253 if( bestleaf != NULL && (bestnode == NULL || SCIPnodeselCompare(nodesel, set, bestleaf, bestnode) < 0) )
    8254 bestnode = bestleaf;
    8255
    8256 assert(SCIPtreeGetNLeaves(tree) == 0 || bestnode != NULL);
    8257
    8258 return bestnode;
    8259}
    8260
    8261/** gets the minimal lower bound of all nodes in the tree */
    8263 SCIP_TREE* tree, /**< branch and bound tree */
    8264 SCIP_SET* set /**< global SCIP settings */
    8265 )
    8266{
    8267 SCIP_Real lowerbound;
    8268 int i;
    8269
    8270 assert(tree != NULL);
    8271 assert(set != NULL);
    8272
    8273 /* get the lower bound from the queue */
    8274 lowerbound = SCIPnodepqGetLowerbound(tree->leaves, set);
    8275
    8276 /* compare lower bound with children */
    8277 for( i = 0; i < tree->nchildren; ++i )
    8278 {
    8279 assert(tree->children[i] != NULL);
    8280 lowerbound = MIN(lowerbound, tree->children[i]->lowerbound);
    8281 }
    8282
    8283 /* compare lower bound with siblings */
    8284 for( i = 0; i < tree->nsiblings; ++i )
    8285 {
    8286 assert(tree->siblings[i] != NULL);
    8287 lowerbound = MIN(lowerbound, tree->siblings[i]->lowerbound);
    8288 }
    8289
    8290 /* compare lower bound with focus node */
    8291 if( tree->focusnode != NULL )
    8292 {
    8293 lowerbound = MIN(lowerbound, tree->focusnode->lowerbound);
    8294 }
    8295
    8296 return lowerbound;
    8297}
    8298
    8299/** gets the minimal exact lower bound of all nodes in the tree or NULL if empty
    8300 *
    8301 * @note The user must not modify the return value.
    8302 */
    8304 SCIP_TREE* tree, /**< branch and bound tree */
    8305 SCIP_SET* set /**< global SCIP settings */
    8306 )
    8307{
    8308 SCIP_RATIONAL* lowerbound;
    8309 int i;
    8310
    8311 assert(tree != NULL);
    8312 assert(set != NULL);
    8313
    8314 /* get the lower bound from the queue */
    8315 lowerbound = SCIPnodepqGetLowerboundExact(tree->leaves, set);
    8316
    8317 /* compare lower bound with children */
    8318 for( i = 0; i < tree->nchildren; ++i )
    8319 {
    8320 assert(tree->children[i] != NULL);
    8321 if( lowerbound == NULL || SCIPrationalIsGT(lowerbound, tree->children[i]->lowerboundexact) )
    8322 lowerbound = tree->children[i]->lowerboundexact;
    8323 }
    8324
    8325 /* compare lower bound with siblings */
    8326 for( i = 0; i < tree->nsiblings; ++i )
    8327 {
    8328 assert(tree->siblings[i] != NULL);
    8329 if( lowerbound == NULL || SCIPrationalIsGT(lowerbound, tree->siblings[i]->lowerboundexact) )
    8330 lowerbound = tree->siblings[i]->lowerboundexact;
    8331 }
    8332
    8333 /* compare lower bound with focus node */
    8334 if( tree->focusnode != NULL
    8335 && ( lowerbound == NULL || SCIPrationalIsGT(lowerbound, tree->focusnode->lowerboundexact) ) )
    8336 {
    8337 lowerbound = tree->focusnode->lowerboundexact;
    8338 }
    8339
    8340 return lowerbound;
    8341}
    8342
    8343/** gets the node with minimal lower bound of all nodes in the tree (child, sibling, or leaf) */
    8345 SCIP_TREE* tree, /**< branch and bound tree */
    8346 SCIP_SET* set /**< global SCIP settings */
    8347 )
    8348{
    8349 SCIP_NODE* lowerboundnode;
    8350 SCIP_Real bestprio;
    8351 int i;
    8352
    8353 assert(tree != NULL);
    8354 assert(set != NULL);
    8355
    8356 /* get the lower bound from the queue */
    8357 lowerboundnode = SCIPnodepqGetLowerboundNode(tree->leaves, set);
    8358 bestprio = -SCIPsetInfinity(set);
    8359
    8360 if( set->exact_enable )
    8361 {
    8362 SCIP_RATIONAL* lowerbound = lowerboundnode != NULL ? lowerboundnode->lowerboundexact : NULL;
    8363
    8364 /* compare lower bound with children */
    8365 for( i = 0; i < tree->nchildren; ++i )
    8366 {
    8367 assert(tree->children[i] != NULL);
    8368 if( lowerbound == NULL || ( SCIPrationalIsLE(tree->children[i]->lowerboundexact, lowerbound)
    8369 && ( !SCIPrationalIsEQ(tree->children[i]->lowerboundexact, lowerbound) || tree->childrenprio[i] > bestprio ) ) )
    8370 {
    8371 lowerboundnode = tree->children[i];
    8372 bestprio = tree->childrenprio[i];
    8373 lowerbound = lowerboundnode->lowerboundexact;
    8374 }
    8375 }
    8376
    8377 /* compare lower bound with siblings */
    8378 for( i = 0; i < tree->nsiblings; ++i )
    8379 {
    8380 assert(tree->siblings[i] != NULL);
    8381 if( lowerbound == NULL || ( SCIPrationalIsLE(tree->siblings[i]->lowerboundexact, lowerbound)
    8382 && ( !SCIPrationalIsEQ(tree->siblings[i]->lowerboundexact, lowerbound) || tree->siblingsprio[i] > bestprio ) ) )
    8383 {
    8384 lowerboundnode = tree->siblings[i];
    8385 bestprio = tree->siblingsprio[i];
    8386 lowerbound = lowerboundnode->lowerboundexact;
    8387 }
    8388 }
    8389 }
    8390 else
    8391 {
    8392 SCIP_Real lowerbound = lowerboundnode != NULL ? lowerboundnode->lowerbound : SCIPsetInfinity(set);
    8393
    8394 /* compare lower bound with children */
    8395 for( i = 0; i < tree->nchildren; ++i )
    8396 {
    8397 assert(tree->children[i] != NULL);
    8398 if( SCIPsetIsLE(set, tree->children[i]->lowerbound, lowerbound)
    8399 && ( SCIPsetIsLT(set, tree->children[i]->lowerbound, lowerbound) || tree->childrenprio[i] > bestprio ) )
    8400 {
    8401 lowerboundnode = tree->children[i];
    8402 bestprio = tree->childrenprio[i];
    8403 lowerbound = lowerboundnode->lowerbound;
    8404 }
    8405 }
    8406
    8407 /* compare lower bound with siblings */
    8408 for( i = 0; i < tree->nsiblings; ++i )
    8409 {
    8410 assert(tree->siblings[i] != NULL);
    8411 if( SCIPsetIsLE(set, tree->siblings[i]->lowerbound, lowerbound)
    8412 && ( SCIPsetIsLT(set, tree->siblings[i]->lowerbound, lowerbound) || tree->siblingsprio[i] > bestprio ) )
    8413 {
    8414 lowerboundnode = tree->siblings[i];
    8415 bestprio = tree->siblingsprio[i];
    8416 lowerbound = lowerboundnode->lowerbound;
    8417 }
    8418 }
    8419 }
    8420
    8421 return lowerboundnode;
    8422}
    8423
    8424/** gets the average lower bound of all nodes in the tree */
    8426 SCIP_TREE* tree, /**< branch and bound tree */
    8427 SCIP_Real cutoffbound /**< global cutoff bound */
    8428 )
    8429{
    8430 SCIP_Real lowerboundsum;
    8431 int nnodes;
    8432 int i;
    8433
    8434 assert(tree != NULL);
    8435
    8436 /* get sum of lower bounds from nodes in the queue */
    8437 lowerboundsum = SCIPnodepqGetLowerboundSum(tree->leaves);
    8438 nnodes = SCIPtreeGetNLeaves(tree);
    8439
    8440 /* add lower bound of focus node */
    8441 if( tree->focusnode != NULL && tree->focusnode->lowerbound < cutoffbound )
    8442 {
    8443 lowerboundsum += tree->focusnode->lowerbound;
    8444 nnodes++;
    8445 }
    8446
    8447 /* add lower bounds of siblings */
    8448 for( i = 0; i < tree->nsiblings; ++i )
    8449 {
    8450 assert(tree->siblings[i] != NULL);
    8451 lowerboundsum += tree->siblings[i]->lowerbound;
    8452 }
    8453 nnodes += tree->nsiblings;
    8454
    8455 /* add lower bounds of children */
    8456 for( i = 0; i < tree->nchildren; ++i )
    8457 {
    8458 assert(tree->children[i] != NULL);
    8459 lowerboundsum += tree->children[i]->lowerbound;
    8460 }
    8461 nnodes += tree->nchildren;
    8462
    8463 return nnodes == 0 ? 0.0 : lowerboundsum/nnodes;
    8464}
    8465
    8466
    8467
    8468
    8469/*
    8470 * simple functions implemented as defines
    8471 */
    8472
    8473/* In debug mode, the following methods are implemented as function calls to ensure
    8474 * type validity.
    8475 * In optimized mode, the methods are implemented as defines to improve performance.
    8476 * However, we want to have them in the library anyways, so we have to undef the defines.
    8477 */
    8478
    8479#undef SCIPnodeGetType
    8480#undef SCIPnodeGetNumber
    8481#undef SCIPnodeGetDepth
    8482#undef SCIPnodeGetLowerbound
    8483#undef SCIPnodeGetEstimate
    8484#undef SCIPnodeGetDomchg
    8485#undef SCIPnodeGetParent
    8486#undef SCIPnodeGetConssetchg
    8487#undef SCIPnodeIsActive
    8488#undef SCIPnodeIsPropagatedAgain
    8489#undef SCIPtreeGetNLeaves
    8490#undef SCIPtreeGetNChildren
    8491#undef SCIPtreeGetNSiblings
    8492#undef SCIPtreeGetNNodes
    8493#undef SCIPtreeIsPathComplete
    8494#undef SCIPtreeProbing
    8495#undef SCIPtreeGetProbingRoot
    8496#undef SCIPtreeGetProbingDepth
    8497#undef SCIPtreeGetFocusNode
    8498#undef SCIPtreeGetFocusDepth
    8499#undef SCIPtreeHasFocusNodeLP
    8500#undef SCIPtreeSetFocusNodeLP
    8501#undef SCIPtreeIsFocusNodeLPConstructed
    8502#undef SCIPtreeInRepropagation
    8503#undef SCIPtreeGetCurrentNode
    8504#undef SCIPtreeGetCurrentDepth
    8505#undef SCIPtreeHasCurrentNodeLP
    8506#undef SCIPtreeGetEffectiveRootDepth
    8507#undef SCIPtreeGetRootNode
    8508#undef SCIPtreeProbingObjChanged
    8509#undef SCIPtreeMarkProbingObjChanged
    8510
    8511/** gets the type of the node */
    8513 SCIP_NODE* node /**< node */
    8514 )
    8515{
    8516 assert(node != NULL);
    8517
    8518 return (SCIP_NODETYPE)(node->nodetype);
    8519}
    8520
    8521/** gets successively assigned number of the node */
    8523 SCIP_NODE* node /**< node */
    8524 )
    8525{
    8526 assert(node != NULL);
    8527
    8528 return node->number;
    8529}
    8530
    8531/** gets the depth of the node */
    8533 SCIP_NODE* node /**< node */
    8534 )
    8535{
    8536 assert(node != NULL);
    8537
    8538 return (int) node->depth;
    8539}
    8540
    8541/** gets the lower bound of the node */
    8543 SCIP_NODE* node /**< node */
    8544 )
    8545{
    8546 assert(node != NULL);
    8547
    8548 return node->lowerbound;
    8549}
    8550
    8551/** gets the lower bound of the node */
    8553 SCIP_NODE* node /**< node */
    8554 )
    8555{
    8556 assert(node != NULL);
    8557
    8558 return node->lowerboundexact;
    8559}
    8560
    8561/** gets the estimated value of the best feasible solution in subtree of the node */
    8563 SCIP_NODE* node /**< node */
    8564 )
    8565{
    8566 assert(node != NULL);
    8567
    8568 return node->estimate;
    8569}
    8570
    8571/** gets the reoptimization type of this node */
    8573 SCIP_NODE* node /**< node */
    8574 )
    8575{
    8576 assert(node != NULL);
    8577
    8578 return (SCIP_REOPTTYPE)node->reopttype;
    8579}
    8580
    8581/** sets the reoptimization type of this node */
    8583 SCIP_NODE* node, /**< node */
    8584 SCIP_REOPTTYPE reopttype /**< reoptimization type */
    8585 )
    8586{
    8587 assert(node != NULL);
    8588 assert(reopttype == SCIP_REOPTTYPE_NONE
    8589 || reopttype == SCIP_REOPTTYPE_TRANSIT
    8590 || reopttype == SCIP_REOPTTYPE_INFSUBTREE
    8591 || reopttype == SCIP_REOPTTYPE_STRBRANCHED
    8592 || reopttype == SCIP_REOPTTYPE_LOGICORNODE
    8593 || reopttype == SCIP_REOPTTYPE_LEAF
    8594 || reopttype == SCIP_REOPTTYPE_PRUNED
    8595 || reopttype == SCIP_REOPTTYPE_FEASIBLE);
    8596
    8597 node->reopttype = (unsigned int) reopttype;
    8598}
    8599
    8600/** gets the unique id to identify the node during reoptimization; the id is 0 if the node is the root or not part of
    8601 * the reoptimization tree
    8602 */
    8604 SCIP_NODE* node /**< node */
    8605 )
    8606{
    8607 assert(node != NULL);
    8608
    8609 return node->reoptid; /*lint !e732*/
    8610}
    8611
    8612/** set a unique id to identify the node during reoptimization */
    8614 SCIP_NODE* node, /**< node */
    8615 unsigned int id /**< unique id */
    8616 )
    8617{
    8618 assert(node != NULL);
    8619 assert(id <= 536870911); /* id has only 29 bits and needs to be smaller than 2^29 */
    8620
    8621 node->reoptid = id;
    8622}
    8623
    8624/** gets the domain change information of the node, i.e., the information about the differences in the
    8625 * variables domains to the parent node
    8626 */
    8628 SCIP_NODE* node /**< node */
    8629 )
    8630{
    8631 assert(node != NULL);
    8632
    8633 return node->domchg;
    8634}
    8635
    8636/** counts the number of bound changes due to branching, constraint propagation, and propagation */
    8638 SCIP_NODE* node, /**< node */
    8639 int* nbranchings, /**< pointer to store number of branchings (or NULL if not needed) */
    8640 int* nconsprop, /**< pointer to store number of constraint propagations (or NULL if not needed) */
    8641 int* nprop /**< pointer to store number of propagations (or NULL if not needed) */
    8642 )
    8643{ /*lint --e{641}*/
    8644 SCIP_Bool count_branchings;
    8645 SCIP_Bool count_consprop;
    8646 SCIP_Bool count_prop;
    8647 int i;
    8648
    8649 assert(node != NULL);
    8650
    8651 count_branchings = (nbranchings != NULL);
    8652 count_consprop = (nconsprop != NULL);
    8653 count_prop = (nprop != NULL);
    8654
    8655 /* set counter to zero */
    8656 if( count_branchings )
    8657 *nbranchings = 0;
    8658 if( count_consprop )
    8659 *nconsprop = 0; /* cppcheck-suppress nullPointer */
    8660 if( count_prop )
    8661 *nprop = 0; /* cppcheck-suppress nullPointer */
    8662
    8663 if( node->domchg == NULL )
    8664 return;
    8665
    8666 /* branching bound changes are always at beginning, count them in i */
    8667 for( i = 0; i < (int) node->domchg->domchgbound.nboundchgs; ++i )
    8669 break;
    8670 if( count_branchings )
    8671 *nbranchings = i;
    8672
    8673 if( !count_consprop && !count_prop )
    8674 return;
    8675
    8676 for( ; i < (int) node->domchg->domchgbound.nboundchgs; ++i )
    8677 {
    8680 {
    8681 if( count_consprop )
    8682 ++(*nconsprop);
    8683 }
    8684 else
    8685 {
    8686 if( count_prop )
    8687 ++(*nprop);
    8688 }
    8689 }
    8690}
    8691
    8692/* return the number of bound changes based on dual information.
    8693 *
    8694 * currently, this methods works only for bound changes made by strong branching on binary variables. we need this
    8695 * method to ensure optimality within reoptimization.
    8696 *
    8697 * since the bound changes made by strong branching are stored as SCIP_BOUNDCHGTYPE_CONSINFER or SCIP_BOUNDCHGTYPE_PROPINFER
    8698 * with no constraint or propagator, resp., we are are interested in bound changes with these attributes.
    8699 *
    8700 * all bound changes of type SCIP_BOUNDCHGTYPE_BRANCHING are stored in the beginning of the bound change array, afterwards,
    8701 * we can find the other two types. thus, we start the search at the end of the list and stop when reaching the first
    8702 * bound change of type SCIP_BOUNDCHGTYPE_BRANCHING.
    8703 */
    8705 SCIP_NODE* node /**< node */
    8706 )
    8707{ /*lint --e{641}*/
    8708 SCIP_BOUNDCHG* boundchgs;
    8709 int i;
    8710 int nboundchgs;
    8711 int npseudobranchvars;
    8712
    8713 assert(node != NULL);
    8714
    8715 if( node->domchg == NULL )
    8716 return 0;
    8717
    8718 nboundchgs = (int)node->domchg->domchgbound.nboundchgs;
    8719 boundchgs = node->domchg->domchgbound.boundchgs;
    8720
    8721 npseudobranchvars = 0;
    8722
    8723 assert(boundchgs != NULL);
    8724 assert(nboundchgs >= 0);
    8725
    8726 /* count the number of pseudo-branching decisions; pseudo-branching decisions have to be in the ending of the bound change
    8727 * array
    8728 */
    8729 for( i = nboundchgs-1; i >= 0; i--)
    8730 {
    8731 if( SCIPvarIsIntegral(boundchgs[i].var)
    8732 && ( ( boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER
    8733 && boundchgs[i].data.inferencedata.reason.cons == NULL )
    8734 || ( boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER
    8735 && boundchgs[i].data.inferencedata.reason.prop == NULL ) ) )
    8736 npseudobranchvars++;
    8737 else if( boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
    8738 break;
    8739 }
    8740
    8741 return npseudobranchvars;
    8742}
    8743
    8744/** returns the set of variable branchings that were performed in the parent node to create this node */
    8746 SCIP_NODE* node, /**< node data */
    8747 SCIP_VAR** vars, /**< array of variables on which the bound change is based on dual information */
    8748 SCIP_Real* bounds, /**< array of bounds which are based on dual information */
    8749 SCIP_BOUNDTYPE* boundtypes, /**< array of boundtypes which are based on dual information */
    8750 int* nvars, /**< number of variables on which the bound change is based on dual information
    8751 * if this is larger than the array size, arrays should be reallocated and method
    8752 * should be called again */
    8753 int varssize /**< available slots in arrays */
    8754 )
    8755{ /*lint --e{641}*/
    8756 SCIP_BOUNDCHG* boundchgs;
    8757 int nboundchgs;
    8758 int i;
    8759
    8760 assert(node != NULL);
    8761 assert(vars != NULL);
    8762 assert(bounds != NULL);
    8763 assert(boundtypes != NULL);
    8764 assert(nvars != NULL);
    8765 assert(varssize >= 0);
    8766
    8767 (*nvars) = 0;
    8768
    8769 if( SCIPnodeGetDepth(node) == 0 || node->domchg == NULL )
    8770 return;
    8771
    8772 nboundchgs = (int)node->domchg->domchgbound.nboundchgs;
    8773 boundchgs = node->domchg->domchgbound.boundchgs;
    8774
    8775 assert(boundchgs != NULL);
    8776 assert(nboundchgs >= 0);
    8777
    8778 /* count the number of pseudo-branching decisions; pseudo-branching decisions have to be in the ending of the bound change
    8779 * array
    8780 */
    8781 for( i = nboundchgs-1; i >= 0; i--)
    8782 {
    8783 if( SCIPvarIsIntegral(boundchgs[i].var) )
    8784 {
    8785 if( (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER
    8786 && boundchgs[i].data.inferencedata.reason.cons == NULL)
    8787 || (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER
    8788 && boundchgs[i].data.inferencedata.reason.prop == NULL) )
    8789 (*nvars)++;
    8790 else if( boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
    8791 break;
    8792 }
    8793 }
    8794
    8795 /* if the arrays have enough space store the branching decisions */
    8796 if( varssize >= *nvars )
    8797 {
    8798 int j;
    8799 j = 0;
    8800 for( i = i+1; i < nboundchgs; i++)
    8801 {
    8802 if( SCIPvarIsIntegral(boundchgs[i].var) )
    8803 {
    8804 assert( boundchgs[i].boundchgtype != SCIP_BOUNDCHGTYPE_BRANCHING );
    8805 if( (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER
    8806 && boundchgs[i].data.inferencedata.reason.cons == NULL)
    8807 || (boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER
    8808 && boundchgs[i].data.inferencedata.reason.prop == NULL) )
    8809 {
    8810 vars[j] = boundchgs[i].var;
    8811 bounds[j] = boundchgs[i].newbound;
    8812 boundtypes[j] = (SCIP_BOUNDTYPE) boundchgs[i].boundtype;
    8813 j++;
    8814 }
    8815 }
    8816 }
    8817 }
    8818}
    8819
    8820/** gets the parent node of a node in the branch-and-bound tree, if any */
    8822 SCIP_NODE* node /**< node */
    8823 )
    8824{
    8825 assert(node != NULL);
    8826
    8827 return node->parent;
    8828}
    8829
    8830/** returns the set of variable branchings that were performed in the parent node to create this node */
    8832 SCIP_NODE* node, /**< node data */
    8833 SCIP_VAR** branchvars, /**< array of variables on which the branching has been performed in the parent node */
    8834 SCIP_Real* branchbounds, /**< array of bounds which the branching in the parent node set */
    8835 SCIP_BOUNDTYPE* boundtypes, /**< array of boundtypes which the branching in the parent node set */
    8836 int* nbranchvars, /**< number of variables on which branching has been performed in the parent node
    8837 * if this is larger than the array size, arrays should be reallocated and method
    8838 * should be called again */
    8839 int branchvarssize /**< available slots in arrays */
    8840 )
    8841{
    8842 SCIP_BOUNDCHG* boundchgs;
    8843 int nboundchgs;
    8844 int i;
    8845
    8846 assert(node != NULL);
    8847 assert(branchvars != NULL);
    8848 assert(branchbounds != NULL);
    8849 assert(boundtypes != NULL);
    8850 assert(nbranchvars != NULL);
    8851 assert(branchvarssize >= 0);
    8852
    8853 (*nbranchvars) = 0;
    8854
    8855 if( SCIPnodeGetDepth(node) == 0 || node->domchg == NULL )
    8856 return;
    8857
    8858 nboundchgs = (int)node->domchg->domchgbound.nboundchgs;
    8859 boundchgs = node->domchg->domchgbound.boundchgs;
    8860
    8861 assert(boundchgs != NULL);
    8862 assert(nboundchgs >= 0);
    8863
    8864 /* count the number of branching decisions; branching decisions have to be in the beginning of the bound change
    8865 * array
    8866 */
    8867 for( i = 0; i < nboundchgs; i++)
    8868 {
    8869 if( boundchgs[i].boundchgtype != SCIP_BOUNDCHGTYPE_BRANCHING ) /*lint !e641*/
    8870 break;
    8871
    8872 (*nbranchvars)++;
    8873 }
    8874
    8875#ifndef NDEBUG
    8876 /* check that the remaining bound change are no branching decisions */
    8877 for( ; i < nboundchgs; i++)
    8878 assert(boundchgs[i].boundchgtype != SCIP_BOUNDCHGTYPE_BRANCHING); /*lint !e641*/
    8879#endif
    8880
    8881 /* if the arrays have enough space store the branching decisions */
    8882 if( branchvarssize >= *nbranchvars )
    8883 {
    8884 for( i = 0; i < *nbranchvars; i++)
    8885 {
    8886 assert( boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ); /*lint !e641*/
    8887 branchvars[i] = boundchgs[i].var;
    8888 boundtypes[i] = (SCIP_BOUNDTYPE) boundchgs[i].boundtype;
    8889 branchbounds[i] = boundchgs[i].newbound;
    8890 }
    8891 }
    8892}
    8893
    8894/** returns the set of variable branchings that were performed in all ancestor nodes (nodes on the path to the root) to create this node */
    8896 SCIP_NODE* node, /**< node data */
    8897 SCIP_VAR** branchvars, /**< array of variables on which the branchings has been performed in all ancestors */
    8898 SCIP_Real* branchbounds, /**< array of bounds which the branchings in all ancestors set */
    8899 SCIP_BOUNDTYPE* boundtypes, /**< array of boundtypes which the branchings in all ancestors set */
    8900 int* nbranchvars, /**< number of variables on which branchings have been performed in all ancestors
    8901 * if this is larger than the array size, arrays should be reallocated and method
    8902 * should be called again */
    8903 int branchvarssize /**< available slots in arrays */
    8904 )
    8905{
    8906 assert(node != NULL);
    8907 assert(branchvars != NULL);
    8908 assert(branchbounds != NULL);
    8909 assert(boundtypes != NULL);
    8910 assert(nbranchvars != NULL);
    8911 assert(branchvarssize >= 0);
    8912
    8913 (*nbranchvars) = 0;
    8914
    8915 while( SCIPnodeGetDepth(node) != 0 )
    8916 {
    8917 int nodenbranchvars;
    8918 int start;
    8919 int size;
    8920
    8921 start = *nbranchvars < branchvarssize - 1 ? *nbranchvars : branchvarssize - 1;
    8922 size = *nbranchvars > branchvarssize ? 0 : branchvarssize-(*nbranchvars);
    8923
    8924 SCIPnodeGetParentBranchings(node, &branchvars[start], &branchbounds[start], &boundtypes[start], &nodenbranchvars, size);
    8925 *nbranchvars += nodenbranchvars;
    8926
    8927 node = node->parent;
    8928 }
    8929}
    8930
    8931/** returns the set of variable branchings that were performed between the given @p node and the given @p parent node. */
    8933 SCIP_NODE* node, /**< node data */
    8934 SCIP_NODE* parent, /**< node data of the last ancestor node */
    8935 SCIP_VAR** branchvars, /**< array of variables on which the branchings has been performed in all ancestors */
    8936 SCIP_Real* branchbounds, /**< array of bounds which the branchings in all ancestors set */
    8937 SCIP_BOUNDTYPE* boundtypes, /**< array of boundtypes which the branchings in all ancestors set */
    8938 int* nbranchvars, /**< number of variables on which branchings have been performed in all ancestors
    8939 * if this is larger than the array size, arrays should be reallocated and method
    8940 * should be called again */
    8941 int branchvarssize /**< available slots in arrays */
    8942 )
    8943{
    8944 assert(node != NULL);
    8945 assert(parent != NULL);
    8946 assert(branchvars != NULL);
    8947 assert(branchbounds != NULL);
    8948 assert(boundtypes != NULL);
    8949 assert(nbranchvars != NULL);
    8950 assert(branchvarssize >= 0);
    8951
    8952 (*nbranchvars) = 0;
    8953
    8954 while( node != parent )
    8955 {
    8956 int nodenbranchvars;
    8957 int start;
    8958 int size;
    8959
    8960 start = *nbranchvars < branchvarssize - 1 ? *nbranchvars : branchvarssize - 1;
    8961 size = *nbranchvars > branchvarssize ? 0 : branchvarssize-(*nbranchvars);
    8962
    8963 SCIPnodeGetParentBranchings(node, &branchvars[start], &branchbounds[start], &boundtypes[start], &nodenbranchvars, size);
    8964 *nbranchvars += nodenbranchvars;
    8965
    8966 node = node->parent;
    8967 }
    8968}
    8969
    8970/** return all bound changes on non-continuous variables based on constraint and propagator propagation
    8971 *
    8972 * Stop saving the bound changes when a propagation based on a dual information is reached.
    8973 */
    8975 SCIP_NODE* node, /**< node */
    8976 SCIP_VAR** vars, /**< array of variables on which propagation triggers a bound change */
    8977 SCIP_Real* varbounds, /**< array of bounds set by propagation */
    8978 SCIP_BOUNDTYPE* varboundtypes, /**< array of boundtypes set by propagation */
    8979 int* npropvars, /**< number of variables on which propagation triggers a bound change
    8980 * if this is larger than the array size, arrays should be reallocated and method
    8981 * should be called again */
    8982 int propvarssize /**< available slots in arrays */
    8983 )
    8984{ /*lint --e{641}*/
    8985 SCIP_BOUNDCHG* boundchgs;
    8986 int nboundchgs;
    8987 int nbranchings;
    8988 int i;
    8989 int pos;
    8990
    8991 assert(node != NULL);
    8992 assert(vars != NULL);
    8993 assert(varbounds != NULL);
    8994 assert(varboundtypes != NULL);
    8995 assert(npropvars != NULL);
    8996 assert(propvarssize >= 0);
    8997
    8998 *npropvars = 0;
    8999
    9000 if( SCIPnodeGetDepth(node) == 0 || node->domchg == NULL )
    9001 return;
    9002
    9003 nboundchgs = (int)node->domchg->domchgbound.nboundchgs;
    9004 boundchgs = node->domchg->domchgbound.boundchgs;
    9005
    9006 assert(boundchgs != NULL);
    9007 assert(nboundchgs >= 0);
    9008
    9009 /* get index of first bound change, after the branching decisions, that is not from a known constraint or propagator (CONSINFER or PROPINFER without reason)
    9010 * count the number of bound changes because of constraint propagation
    9011 */
    9012 SCIPnodeGetNDomchg(node, &nbranchings, NULL, NULL);
    9013 for( i = nbranchings; i < nboundchgs; ++i )
    9014 {
    9015 /* as we start at nbranchings, there should be no BRANCHING boundchanges anymore */
    9016 assert(boundchgs[i].boundchgtype != SCIP_BOUNDCHGTYPE_BRANCHING);
    9017
    9018 if( boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER )
    9019 {
    9020 if( boundchgs[i].data.inferencedata.reason.cons == NULL )
    9021 break;
    9022 }
    9023 else
    9024 {
    9025 assert(boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER);
    9026 if( boundchgs[i].data.inferencedata.reason.prop == NULL )
    9027 break;
    9028 }
    9029 if( SCIPvarIsIntegral(boundchgs[i].var) )
    9030 (*npropvars)++;
    9031 }
    9032
    9033 /* return if the arrays do not have enough space to store the propagations */
    9034 if( propvarssize < *npropvars )
    9035 return;
    9036
    9037 for( i = nbranchings, pos = 0; pos < *npropvars; ++i ) /*lint !e440*/
    9038 {
    9039 assert(i < nboundchgs);
    9040 if( SCIPvarIsIntegral(boundchgs[i].var) )
    9041 {
    9042 vars[pos] = boundchgs[i].var;
    9043 varboundtypes[pos] = (SCIP_BOUNDTYPE) boundchgs[i].boundtype;
    9044 varbounds[pos] = boundchgs[i].newbound;
    9045 pos++;
    9046 }
    9047 }
    9048}
    9049
    9050/** return bound changes on non-continuous variables based on constraint and propagator propagation
    9051 *
    9052 * Start saving the bound changes when a propagation based on a dual information is reached.
    9053 *
    9054 * @note Currently, we can only detect bound changes based in dual information if they arise from strong branching.
    9055 */
    9057 SCIP_NODE* node, /**< node */
    9058 SCIP_VAR** vars, /**< array where to store variables with bound changes */
    9059 SCIP_Real* varbounds, /**< array where to store changed bounds */
    9060 SCIP_BOUNDTYPE* varboundtypes, /**< array where to store type of changed bound*/
    9061 int* nvars, /**< buffer to store number of bound changes;
    9062 * if this is larger than varssize, arrays should be reallocated and method
    9063 * should be called again */
    9064 int varssize /**< available slots in provided arrays */
    9065 )
    9066{ /*lint --e{641}*/
    9067 SCIP_BOUNDCHG* boundchgs;
    9068 int nboundchgs;
    9069 int i;
    9070 int first_dual;
    9071 int pos;
    9072
    9073 assert(node != NULL);
    9074 assert(vars != NULL);
    9075 assert(varbounds != NULL);
    9076 assert(varboundtypes != NULL);
    9077 assert(nvars != NULL);
    9078 assert(varssize >= 0);
    9079
    9080 *nvars = 0;
    9081
    9082 if( SCIPnodeGetDepth(node) == 0 || node->domchg == NULL )
    9083 return;
    9084
    9085 nboundchgs = (int)node->domchg->domchgbound.nboundchgs;
    9086 boundchgs = node->domchg->domchgbound.boundchgs;
    9087
    9088 assert(boundchgs != NULL);
    9089 assert(nboundchgs >= 0);
    9090
    9091 /* get index of first bound change, after the branching decisions, that is not from a known constraint or propagator (CONSINFER or PROPINFER without reason) */
    9092 for( i = 0; i < nboundchgs; ++i )
    9093 {
    9094 if( boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING )
    9095 continue;
    9096 if( boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER )
    9097 {
    9098 if( boundchgs[i].data.inferencedata.reason.cons == NULL )
    9099 break;
    9100 }
    9101 else
    9102 {
    9103 assert(boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER);
    9104 if( boundchgs[i].data.inferencedata.reason.prop == NULL )
    9105 break;
    9106 }
    9107 }
    9108 first_dual = i;
    9109 /* count following bound changes on non-continuous variables from known constraint or propagator */
    9110 for( ; i < nboundchgs; ++i )
    9111 {
    9112 if( boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER )
    9113 {
    9114 if( boundchgs[i].data.inferencedata.reason.cons == NULL )
    9115 continue;
    9116 }
    9117 else
    9118 {
    9119 assert(boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER);
    9120 if( boundchgs[i].data.inferencedata.reason.prop == NULL )
    9121 continue;
    9122 }
    9123 if( SCIPvarIsIntegral(boundchgs[i].var) )
    9124 ++(*nvars);
    9125 }
    9126
    9127 /* return if the arrays do not have enough space to store the propagations */
    9128 if( varssize < *nvars )
    9129 return;
    9130
    9131 /* store bound changes in given arrays */
    9132 for( i = first_dual, pos = 0; pos < *nvars; ++i ) /*lint !e440*/
    9133 {
    9134 assert(i < nboundchgs);
    9135 if( boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER )
    9136 {
    9137 if( boundchgs[i].data.inferencedata.reason.cons == NULL )
    9138 continue;
    9139 }
    9140 else
    9141 {
    9142 assert(boundchgs[i].boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER);
    9143 if( boundchgs[i].data.inferencedata.reason.prop == NULL )
    9144 continue;
    9145 }
    9146 if( SCIPvarIsIntegral(boundchgs[i].var) )
    9147 {
    9148 vars[pos] = boundchgs[i].var;
    9149 varboundtypes[pos] = (SCIP_BOUNDTYPE) boundchgs[i].boundtype;
    9150 varbounds[pos] = boundchgs[i].newbound;
    9151 pos++;
    9152 }
    9153 }
    9154}
    9155
    9156/** outputs the path into given file stream in GML format */
    9158 SCIP_NODE* node, /**< node data */
    9159 FILE* file /**< file to output the path */
    9160 )
    9161{
    9162 int nbranchings;
    9163
    9164 nbranchings = 0;
    9165
    9166 /* print opening in GML format */
    9168
    9169 while( SCIPnodeGetDepth(node) != 0 )
    9170 {
    9171 SCIP_BOUNDCHG* boundchgs;
    9172 char label[SCIP_MAXSTRLEN];
    9173 int nboundchgs;
    9174 int i;
    9175
    9176 nboundchgs = (int)node->domchg->domchgbound.nboundchgs;
    9177 boundchgs = node->domchg->domchgbound.boundchgs;
    9178
    9179 for( i = 0; i < nboundchgs; i++)
    9180 {
    9181 if( boundchgs[i].boundchgtype != SCIP_BOUNDCHGTYPE_BRANCHING ) /*lint !e641*/
    9182 break;
    9183
    9184 (void) SCIPsnprintf(label, SCIP_MAXSTRLEN, "%s %s %g", SCIPvarGetName(boundchgs[i].var),
    9185 (SCIP_BOUNDTYPE) boundchgs[i].boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", boundchgs[i].newbound);
    9186
    9187 SCIPgmlWriteNode(file, (unsigned int)nbranchings, label, "circle", NULL, NULL);
    9188
    9189 if( nbranchings > 0 )
    9190 {
    9191 SCIPgmlWriteArc(file, (unsigned int)nbranchings, (unsigned int)(nbranchings-1), NULL, NULL);
    9192 }
    9193
    9194 nbranchings++;
    9195 }
    9196
    9197 node = node->parent;
    9198 }
    9199
    9200 /* print closing in GML format */
    9201 SCIPgmlWriteClosing(file);
    9202
    9203 return SCIP_OKAY;
    9204}
    9205
    9206/** returns the set of variable branchings that were performed in all ancestor nodes (nodes on the path to the root) to create this node
    9207 * sorted by the nodes, starting from the current node going up to the root
    9208 */
    9210 SCIP_NODE* node, /**< node data */
    9211 SCIP_VAR** branchvars, /**< array of variables on which the branchings has been performed in all ancestors */
    9212 SCIP_Real* branchbounds, /**< array of bounds which the branchings in all ancestors set */
    9213 SCIP_BOUNDTYPE* boundtypes, /**< array of boundtypes which the branchings in all ancestors set */
    9214 int* nbranchvars, /**< number of variables on which branchings have been performed in all ancestors
    9215 * if this is larger than the array size, arrays should be reallocated and method
    9216 * should be called again */
    9217 int branchvarssize, /**< available slots in arrays */
    9218 int* nodeswitches, /**< marks, where in the arrays the branching decisions of the next node on the path
    9219 * start branchings performed at the parent of node always start at position 0.
    9220 * For single variable branching, nodeswitches[i] = i holds */
    9221 int* nnodes, /**< number of nodes in the nodeswitch array */
    9222 int nodeswitchsize /**< available slots in node switch array */
    9223 )
    9224{
    9225 assert(node != NULL);
    9226 assert(branchvars != NULL);
    9227 assert(branchbounds != NULL);
    9228 assert(boundtypes != NULL);
    9229 assert(nbranchvars != NULL);
    9230 assert(branchvarssize >= 0);
    9231
    9232 (*nbranchvars) = 0;
    9233 (*nnodes) = 0;
    9234
    9235 /* go up to the root, in the root no domains were changed due to branching */
    9236 while( SCIPnodeGetDepth(node) != 0 )
    9237 {
    9238 int nodenbranchvars;
    9239 int start;
    9240 int size;
    9241
    9242 /* calculate the start position for the current node and the maximum remaining slots in the arrays */
    9243 start = *nbranchvars < branchvarssize - 1 ? *nbranchvars : branchvarssize - 1;
    9244 size = *nbranchvars > branchvarssize ? 0 : branchvarssize-(*nbranchvars);
    9245 if( *nnodes < nodeswitchsize )
    9246 nodeswitches[*nnodes] = start;
    9247
    9248 /* get branchings for a single node */
    9249 SCIPnodeGetParentBranchings(node, &branchvars[start], &branchbounds[start], &boundtypes[start], &nodenbranchvars, size);
    9250 *nbranchvars += nodenbranchvars;
    9251 (*nnodes)++;
    9252
    9253 node = node->parent;
    9254 }
    9255}
    9256
    9257/** checks for two nodes whether they share the same root path, i.e., whether one is an ancestor of the other */
    9259 SCIP_NODE* node1, /**< node data */
    9260 SCIP_NODE* node2 /**< node data */
    9261 )
    9262{
    9263 assert(node1 != NULL);
    9264 assert(node2 != NULL);
    9265 assert(SCIPnodeGetDepth(node1) >= 0);
    9266 assert(SCIPnodeGetDepth(node2) >= 0);
    9267
    9268 /* if node2 is deeper than node1, follow the path until the level of node2 */
    9269 while( SCIPnodeGetDepth(node1) < SCIPnodeGetDepth(node2) )
    9270 node2 = node2->parent;
    9271
    9272 /* if node1 is deeper than node2, follow the path until the level of node1 */
    9273 while( SCIPnodeGetDepth(node2) < SCIPnodeGetDepth(node1) )
    9274 node1 = node1->parent;
    9275
    9276 assert(SCIPnodeGetDepth(node2) == SCIPnodeGetDepth(node1));
    9277
    9278 return (node1 == node2);
    9279}
    9280
    9281/** finds the common ancestor node of two given nodes */
    9283 SCIP_NODE* node1, /**< node data */
    9284 SCIP_NODE* node2 /**< node data */
    9285 )
    9286{
    9287 assert(node1 != NULL);
    9288 assert(node2 != NULL);
    9289 assert(SCIPnodeGetDepth(node1) >= 0);
    9290 assert(SCIPnodeGetDepth(node2) >= 0);
    9291
    9292 /* if node2 is deeper than node1, follow the path until the level of node2 */
    9293 while( SCIPnodeGetDepth(node1) < SCIPnodeGetDepth(node2) )
    9294 node2 = node2->parent;
    9295
    9296 /* if node1 is deeper than node2, follow the path until the level of node1 */
    9297 while( SCIPnodeGetDepth(node2) < SCIPnodeGetDepth(node1) )
    9298 node1 = node1->parent;
    9299
    9300 /* move up level by level until you found a common ancestor */
    9301 while( node1 != node2 )
    9302 {
    9303 node1 = node1->parent;
    9304 node2 = node2->parent;
    9305 assert(SCIPnodeGetDepth(node1) == SCIPnodeGetDepth(node2));
    9306 }
    9307 assert(SCIPnodeGetDepth(node1) >= 0);
    9308
    9309 return node1;
    9310}
    9311
    9312/** returns whether node is in the path to the current node */
    9314 SCIP_NODE* node /**< node */
    9315 )
    9316{
    9317 assert(node != NULL);
    9318
    9319 return node->active;
    9320}
    9321
    9322/** returns whether the node is marked to be propagated again */
    9324 SCIP_NODE* node /**< node data */
    9325 )
    9326{
    9327 assert(node != NULL);
    9328
    9329 return node->reprop;
    9330}
    9331
    9332/* returns the set of changed constraints for a particular node */
    9334 SCIP_NODE* node /**< node data */
    9335 )
    9336{
    9337 assert(node != NULL);
    9338
    9339 return node->conssetchg;
    9340}
    9341
    9342/** gets number of children of the focus node */
    9344 SCIP_TREE* tree /**< branch and bound tree */
    9345 )
    9346{
    9347 assert(tree != NULL);
    9348
    9349 return tree->nchildren;
    9350}
    9351
    9352/** gets number of siblings of the focus node */
    9354 SCIP_TREE* tree /**< branch and bound tree */
    9355 )
    9356{
    9357 assert(tree != NULL);
    9358
    9359 return tree->nsiblings;
    9360}
    9361
    9362/** gets number of leaves in the tree (excluding children and siblings of focus nodes) */
    9364 SCIP_TREE* tree /**< branch and bound tree */
    9365 )
    9366{
    9367 assert(tree != NULL);
    9368
    9369 return SCIPnodepqLen(tree->leaves);
    9370}
    9371
    9372/** gets number of open nodes in the tree (children + siblings + leaves) */
    9374 SCIP_TREE* tree /**< branch and bound tree */
    9375 )
    9376{
    9377 assert(tree != NULL);
    9378
    9379 return tree->nchildren + tree->nsiblings + SCIPtreeGetNLeaves(tree);
    9380}
    9381
    9382/** returns whether the active path goes completely down to the focus node */
    9384 SCIP_TREE* tree /**< branch and bound tree */
    9385 )
    9386{
    9387 assert(tree != NULL);
    9388 assert(tree->focusnode != NULL || !SCIPtreeProbing(tree));
    9389 assert(tree->pathlen == 0 || tree->focusnode != NULL);
    9390 assert(tree->pathlen >= 2 || !SCIPtreeProbing(tree));
    9391 assert(tree->pathlen == 0 || tree->path[tree->pathlen-1] != NULL);
    9392 assert(tree->pathlen == 0 || tree->path[tree->pathlen-1]->depth == tree->pathlen-1);
    9393 assert(tree->focusnode == NULL || (int)tree->focusnode->depth >= tree->pathlen
    9394 || tree->path[tree->focusnode->depth] == tree->focusnode);
    9395
    9396 return (tree->focusnode == NULL || (int)tree->focusnode->depth < tree->pathlen);
    9397}
    9398
    9399/** returns whether the current node is a temporary probing node */
    9401 SCIP_TREE* tree /**< branch and bound tree */
    9402 )
    9403{
    9404 assert(tree != NULL);
    9406 assert(tree->probingroot == NULL || tree->pathlen > SCIPnodeGetDepth(tree->probingroot));
    9407 assert(tree->probingroot == NULL || tree->path[SCIPnodeGetDepth(tree->probingroot)] == tree->probingroot);
    9408
    9409 return (tree->probingroot != NULL);
    9410}
    9411
    9412/** returns the temporary probing root node, or NULL if the we are not in probing mode */
    9414 SCIP_TREE* tree /**< branch and bound tree */
    9415 )
    9416{
    9417 assert(tree != NULL);
    9419 assert(tree->probingroot == NULL || tree->pathlen > SCIPnodeGetDepth(tree->probingroot));
    9420 assert(tree->probingroot == NULL || tree->path[SCIPnodeGetDepth(tree->probingroot)] == tree->probingroot);
    9421
    9422 return tree->probingroot;
    9423}
    9424
    9425/** gets focus node of the tree */
    9427 SCIP_TREE* tree /**< branch and bound tree */
    9428 )
    9429{
    9430 assert(tree != NULL);
    9431 assert(tree->focusnode != NULL || !SCIPtreeProbing(tree));
    9432 assert(tree->pathlen == 0 || tree->focusnode != NULL);
    9433 assert(tree->pathlen >= 2 || !SCIPtreeProbing(tree));
    9434 assert(tree->pathlen == 0 || tree->path[tree->pathlen-1] != NULL);
    9435 assert(tree->pathlen == 0 || tree->path[tree->pathlen-1]->depth == tree->pathlen-1);
    9436 assert(tree->focusnode == NULL || (int)tree->focusnode->depth >= tree->pathlen
    9437 || tree->path[tree->focusnode->depth] == tree->focusnode);
    9438
    9439 return tree->focusnode;
    9440}
    9441
    9442/** gets depth of focus node in the tree */
    9444 SCIP_TREE* tree /**< branch and bound tree */
    9445 )
    9446{
    9447 assert(tree != NULL);
    9448 assert(tree->focusnode != NULL || !SCIPtreeProbing(tree));
    9449 assert(tree->pathlen == 0 || tree->focusnode != NULL);
    9450 assert(tree->pathlen >= 2 || !SCIPtreeProbing(tree));
    9451 assert(tree->pathlen == 0 || tree->path[tree->pathlen-1] != NULL);
    9452 assert(tree->pathlen == 0 || tree->path[tree->pathlen-1]->depth == tree->pathlen-1);
    9453 assert(tree->focusnode == NULL || (int)tree->focusnode->depth >= tree->pathlen
    9454 || tree->path[tree->focusnode->depth] == tree->focusnode);
    9455
    9456 return tree->focusnode != NULL ? (int)tree->focusnode->depth : -1;
    9457}
    9458
    9459/** returns whether the LP was or is to be solved in the focus node */
    9461 SCIP_TREE* tree /**< branch and bound tree */
    9462 )
    9463{
    9464 assert(tree != NULL);
    9465
    9466 return tree->focusnodehaslp;
    9467}
    9468
    9469/** sets mark to solve or to ignore the LP while processing the focus node */
    9471 SCIP_TREE* tree, /**< branch and bound tree */
    9472 SCIP_Bool solvelp /**< should the LP be solved in focus node? */
    9473 )
    9474{
    9475 assert(tree != NULL);
    9476
    9477 tree->focusnodehaslp = solvelp;
    9478}
    9479
    9480/** returns whether the LP of the focus node is already constructed */
    9482 SCIP_TREE* tree /**< branch and bound tree */
    9483 )
    9484{
    9485 assert(tree != NULL);
    9486
    9487 return tree->focuslpconstructed;
    9488}
    9489
    9490/** returns whether the focus node is already solved and only propagated again */
    9492 SCIP_TREE* tree /**< branch and bound tree */
    9493 )
    9494{
    9495 assert(tree != NULL);
    9496
    9497 return (tree->focusnode != NULL && SCIPnodeGetType(tree->focusnode) == SCIP_NODETYPE_REFOCUSNODE);
    9498}
    9499
    9500/** gets current node of the tree, i.e. the last node in the active path, or NULL if no current node exists */
    9502 SCIP_TREE* tree /**< branch and bound tree */
    9503 )
    9504{
    9505 assert(tree != NULL);
    9506 assert(tree->focusnode != NULL || !SCIPtreeProbing(tree));
    9507 assert(tree->pathlen == 0 || tree->focusnode != NULL);
    9508 assert(tree->pathlen >= 2 || !SCIPtreeProbing(tree));
    9509 assert(tree->pathlen == 0 || tree->path[tree->pathlen-1] != NULL);
    9510 assert(tree->pathlen == 0 || tree->path[tree->pathlen-1]->depth == tree->pathlen-1);
    9511 assert(tree->focusnode == NULL || (int)tree->focusnode->depth >= tree->pathlen
    9512 || tree->path[tree->focusnode->depth] == tree->focusnode);
    9513
    9514 return (tree->pathlen > 0 ? tree->path[tree->pathlen-1] : NULL);
    9515}
    9516
    9517/** 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 */
    9519 SCIP_TREE* tree /**< branch and bound tree */
    9520 )
    9521{
    9522 assert(tree != NULL);
    9523 assert(tree->focusnode != NULL || !SCIPtreeProbing(tree));
    9524 assert(tree->pathlen == 0 || tree->focusnode != NULL);
    9525 assert(tree->pathlen >= 2 || !SCIPtreeProbing(tree));
    9526 assert(tree->pathlen == 0 || tree->path[tree->pathlen-1] != NULL);
    9527 assert(tree->pathlen == 0 || tree->path[tree->pathlen-1]->depth == tree->pathlen-1);
    9528 assert(tree->focusnode == NULL || (int)tree->focusnode->depth >= tree->pathlen
    9529 || tree->path[tree->focusnode->depth] == tree->focusnode);
    9530
    9531 return tree->pathlen-1;
    9532}
    9533
    9534/** returns whether the LP was or is to be solved in the current node */
    9536 SCIP_TREE* tree /**< branch and bound tree */
    9537 )
    9538{
    9539 assert(tree != NULL);
    9540 assert(SCIPtreeIsPathComplete(tree));
    9541
    9542 return SCIPtreeProbing(tree) ? tree->probingnodehaslp : SCIPtreeHasFocusNodeLP(tree);
    9543}
    9544
    9545/** returns the current probing depth, i.e. the number of probing sub nodes existing in the probing path */
    9547 SCIP_TREE* tree /**< branch and bound tree */
    9548 )
    9549{
    9550 assert(tree != NULL);
    9551 assert(SCIPtreeProbing(tree));
    9552
    9554}
    9555
    9556/** returns the depth of the effective root node (i.e. the first depth level of a node with at least two children) */
    9558 SCIP_TREE* tree /**< branch and bound tree */
    9559 )
    9560{
    9561 assert(tree != NULL);
    9562 assert(tree->effectiverootdepth >= 0);
    9563
    9564 return tree->effectiverootdepth;
    9565}
    9566
    9567/** gets the root node of the tree */
    9569 SCIP_TREE* tree /**< branch and bound tree */
    9570 )
    9571{
    9572 assert(tree != NULL);
    9573
    9574 return tree->root;
    9575}
    9576
    9577/** returns whether we are in probing and the objective value of at least one column was changed */
    9578
    9580 SCIP_TREE* tree /**< branch and bound tree */
    9581 )
    9582{
    9583 assert(tree != NULL);
    9584 assert(SCIPtreeProbing(tree) || !tree->probingobjchanged);
    9585
    9586 return tree->probingobjchanged;
    9587}
    9588
    9589/** marks the current probing node to have a changed objective function */
    9591 SCIP_TREE* tree /**< branch and bound tree */
    9592 )
    9593{
    9594 assert(tree != NULL);
    9595 assert(SCIPtreeProbing(tree));
    9596
    9597 tree->probingobjchanged = TRUE;
    9598}
    static long bound
    SCIP_RETCODE SCIPcertificatePrintDualboundPseudo(SCIP_CERTIFICATE *certificate, SCIP_LPEXACT *lpexact, SCIP_NODE *node, SCIP_SET *set, SCIP_PROB *prob, SCIP_Bool lowerchanged, int modifiedvarindex, SCIP_Longint boundchangeindex, SCIP_Real psval)
    SCIP_RETCODE SCIPcertificateNewNodeData(SCIP_CERTIFICATE *certificate, SCIP_STAT *stat, SCIP_NODE *node)
    SCIP_RETCODE SCIPcertificatePrintDualboundExactLP(SCIP_CERTIFICATE *certificate, SCIP_LPEXACT *lpexact, SCIP_SET *set, SCIP_NODE *node, SCIP_PROB *prob, SCIP_Bool usefarkas)
    SCIP_RETCODE SCIPcertificatePrintGlobalBound(SCIP *scip, SCIP_CERTIFICATE *certificate, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_RATIONAL *value, SCIP_Longint certificateindex)
    SCIP_Longint SCIPcertificateGetCurrentIndex(SCIP_CERTIFICATE *certificate)
    SCIP_RETCODE SCIPcertificatePrintUnsplitting(SCIP_SET *set, SCIP_CERTIFICATE *certificate, SCIP_NODE *node)
    SCIP_RETCODE SCIPcertificateUpdateBranchingData(SCIP_SET *set, SCIP_CERTIFICATE *certificate, SCIP_STAT *stat, SCIP_LP *lp, SCIP_NODE *node, SCIP_VAR *branchvar, SCIP_BOUNDTYPE boundtype, SCIP_Real newbound)
    methods for certificate output
    SCIP_Real * r
    Definition: circlepacking.c:59
    void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
    Definition: clock.c:360
    SCIP_Bool SCIPclockIsRunning(SCIP_CLOCK *clck)
    Definition: clock.c:427
    void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
    Definition: clock.c:290
    internal methods for clocks and timing issues
    internal methods for storing conflicts
    SCIP_RETCODE SCIPconshdlrsStorePropagationStatus(SCIP_SET *set, SCIP_CONSHDLR **conshdlrs, int nconshdlrs)
    Definition: cons.c:8126
    SCIP_RETCODE SCIPconssetchgUndo(SCIP_CONSSETCHG *conssetchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
    Definition: cons.c:5847
    SCIP_RETCODE SCIPconsDisable(SCIP_CONS *cons, SCIP_SET *set, SCIP_STAT *stat)
    Definition: cons.c:7141
    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:5596
    SCIP_RETCODE SCIPconssetchgFree(SCIP_CONSSETCHG **conssetchg, BMS_BLKMEM *blkmem, SCIP_SET *set)
    Definition: cons.c:5522
    SCIP_RETCODE SCIPconssetchgAddDisabledCons(SCIP_CONSSETCHG **conssetchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CONS *cons)
    Definition: cons.c:5642
    SCIP_RETCODE SCIPconshdlrsResetPropagationStatus(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_CONSHDLR **conshdlrs, int nconshdlrs)
    Definition: cons.c:8166
    SCIP_RETCODE SCIPconssetchgApply(SCIP_CONSSETCHG *conssetchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, int depth, SCIP_Bool focusnode)
    Definition: cons.c:5760
    SCIP_RETCODE SCIPconssetchgMakeGlobal(SCIP_CONSSETCHG **conssetchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_REOPT *reopt)
    Definition: cons.c:5933
    internal methods for constraints and constraint handlers
    methods for debugging
    #define SCIPdebugCheckLbGlobal(scip, var, lb)
    Definition: debug.h:298
    #define SCIPdebugCheckUbGlobal(scip, var, ub)
    Definition: debug.h:299
    #define SCIPdebugCheckGlobalLowerbound(blkmem, set)
    Definition: debug.h:302
    #define SCIPdebugCheckLocalLowerbound(blkmem, set, node)
    Definition: debug.h:303
    #define SCIPdebugRemoveNode(blkmem, set, node)
    Definition: debug.h:301
    #define SCIPdebugCheckInference(blkmem, set, node, var, newbound, boundtype)
    Definition: debug.h:300
    common defines and data types used in all packages of SCIP
    #define NULL
    Definition: def.h:255
    #define SCIP_MAXSTRLEN
    Definition: def.h:276
    #define SCIP_Longint
    Definition: def.h:148
    #define SCIP_MAXTREEDEPTH
    Definition: def.h:304
    #define EPSISINT(x, eps)
    Definition: def.h:202
    #define SCIP_REAL_MAX
    Definition: def.h:165
    #define SCIP_INVALID
    Definition: def.h:185
    #define SCIP_Bool
    Definition: def.h:98
    #define MIN(x, y)
    Definition: def.h:231
    #define SCIP_ALLOC(x)
    Definition: def.h:373
    #define SCIP_Real
    Definition: def.h:163
    #define TRUE
    Definition: def.h:100
    #define FALSE
    Definition: def.h:101
    #define MAX(x, y)
    Definition: def.h:227
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:155
    #define SCIPABORT()
    Definition: def.h:334
    #define SCIP_REAL_MIN
    Definition: def.h:166
    #define SCIP_CALL(x)
    Definition: def.h:362
    SCIP_RETCODE SCIPeventChgNode(SCIP_EVENT *event, SCIP_NODE *node)
    Definition: event.c:1547
    SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
    Definition: event.c:2933
    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:2861
    SCIP_RETCODE SCIPeventProcess(SCIP_EVENT *event, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter)
    Definition: event.c:1804
    SCIP_RETCODE SCIPeventChgType(SCIP_EVENT *event, SCIP_EVENTTYPE eventtype)
    Definition: event.c:1204
    SCIP_RETCODE SCIPeventqueueDelay(SCIP_EVENTQUEUE *eventqueue)
    Definition: event.c:2846
    internal methods for managing events
    #define nnodes
    Definition: gastrans.c:74
    void SCIPgmlWriteNode(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
    Definition: misc.c:501
    void SCIPgmlWriteClosing(FILE *file)
    Definition: misc.c:703
    void SCIPgmlWriteOpening(FILE *file, SCIP_Bool directed)
    Definition: misc.c:687
    void SCIPgmlWriteArc(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
    Definition: misc.c:643
    SCIP_RETCODE SCIPlpiClearState(SCIP_LPI *lpi)
    Definition: lpi_clp.cpp:3515
    SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
    Definition: misc.c:11162
    SCIP_Bool SCIPisCertified(SCIP *scip)
    SCIP_Bool SCIPconsIsGlobal(SCIP_CONS *cons)
    Definition: cons.c:8618
    SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
    Definition: cons.c:8450
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8389
    BMS_BUFMEM * SCIPbuffer(SCIP *scip)
    Definition: scip_mem.c:72
    void SCIPnodeGetAncestorBranchings(SCIP_NODE *node, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
    Definition: tree.c:8895
    void SCIPnodeSetReopttype(SCIP_NODE *node, SCIP_REOPTTYPE reopttype)
    Definition: tree.c:8582
    void SCIPnodeSetReoptID(SCIP_NODE *node, unsigned int id)
    Definition: tree.c:8613
    void SCIPnodeGetAncestorBranchingsPart(SCIP_NODE *node, SCIP_NODE *parent, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
    Definition: tree.c:8932
    void SCIPnodeGetParentBranchings(SCIP_NODE *node, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
    Definition: tree.c:8831
    SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
    Definition: tree.c:8512
    SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
    Definition: tree.c:8542
    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:9209
    void SCIPnodeGetNDomchg(SCIP_NODE *node, int *nbranchings, int *nconsprop, int *nprop)
    Definition: tree.c:8637
    SCIP_NODE * SCIPnodesGetCommonAncestor(SCIP_NODE *node1, SCIP_NODE *node2)
    Definition: tree.c:9282
    SCIP_Bool SCIPnodeIsActive(SCIP_NODE *node)
    Definition: tree.c:9313
    SCIP_DOMCHG * SCIPnodeGetDomchg(SCIP_NODE *node)
    Definition: tree.c:8627
    SCIP_RATIONAL * SCIPnodeGetLowerboundExact(SCIP_NODE *node)
    Definition: tree.c:8552
    SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
    Definition: tree.c:8522
    SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
    Definition: tree.c:8821
    SCIP_Bool SCIPnodesSharePath(SCIP_NODE *node1, SCIP_NODE *node2)
    Definition: tree.c:9258
    int SCIPnodeGetNAddedConss(SCIP_NODE *node)
    Definition: tree.c:1799
    SCIP_Real SCIPnodeGetEstimate(SCIP_NODE *node)
    Definition: tree.c:8562
    void SCIPnodeGetAddedConss(SCIP_NODE *node, SCIP_CONS **addedconss, int *naddedconss, int addedconsssize)
    Definition: tree.c:1769
    int SCIPnodeGetDepth(SCIP_NODE *node)
    Definition: tree.c:8532
    SCIP_REOPTTYPE SCIPnodeGetReopttype(SCIP_NODE *node)
    Definition: tree.c:8572
    unsigned int SCIPnodeGetReoptID(SCIP_NODE *node)
    Definition: tree.c:8603
    SCIP_Bool SCIPnodeIsPropagatedAgain(SCIP_NODE *node)
    Definition: tree.c:9323
    SCIP_RETCODE SCIPnodePrintAncestorBranchings(SCIP_NODE *node, FILE *file)
    Definition: tree.c:9157
    SCIP_DECL_SORTPTRCOMP(SCIPnodeCompLowerbound)
    Definition: tree.c:157
    SCIP_CONSSETCHG * SCIPnodeGetConssetchg(SCIP_NODE *node)
    Definition: tree.c:9333
    const char * SCIPnodeselGetName(SCIP_NODESEL *nodesel)
    Definition: nodesel.c:1195
    const char * SCIPpropGetName(SCIP_PROP *prop)
    Definition: prop.c:951
    void SCIPrationalMin(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
    Definition: rational.cpp:1343
    SCIP_RETCODE SCIPrationalCreateBlock(BMS_BLKMEM *blkmem, SCIP_RATIONAL **rational)
    Definition: rational.cpp:109
    SCIP_RETCODE SCIPrationalCreate(SCIP_RATIONAL **rational)
    Definition: rational.cpp:95
    void SCIPrationalSetInfinity(SCIP_RATIONAL *res)
    Definition: rational.cpp:619
    SCIP_Real SCIPrationalGetReal(SCIP_RATIONAL *rational)
    Definition: rational.cpp:2084
    void SCIPrationalFreeBlock(BMS_BLKMEM *mem, SCIP_RATIONAL **rational)
    Definition: rational.cpp:462
    #define SCIPrationalDebugMessage
    Definition: rational.h:641
    SCIP_Bool SCIPrationalIsLT(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
    Definition: rational.cpp:1504
    void SCIPrationalSetReal(SCIP_RATIONAL *res, SCIP_Real real)
    Definition: rational.cpp:604
    SCIP_Bool SCIPrationalIsGT(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
    Definition: rational.cpp:1475
    void SCIPrationalFreeBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
    Definition: rational.cpp:474
    SCIP_Real SCIPrationalGetInfinity(void)
    Definition: rational.cpp:2862
    SCIP_RETCODE SCIPrationalCreateBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
    Definition: rational.cpp:124
    void SCIPrationalSetRational(SCIP_RATIONAL *res, SCIP_RATIONAL *src)
    Definition: rational.cpp:570
    SCIP_Bool SCIPrationalIsGEReal(SCIP_RATIONAL *rat, SCIP_Real real)
    Definition: rational.cpp:1607
    SCIP_Bool SCIPrationalIsIntegral(SCIP_RATIONAL *rational)
    Definition: rational.cpp:1692
    void SCIPrationalMax(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
    Definition: rational.cpp:1374
    SCIP_Bool SCIPrationalIsGE(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
    Definition: rational.cpp:1513
    void SCIPrationalSetNegInfinity(SCIP_RATIONAL *res)
    Definition: rational.cpp:631
    SCIP_Bool SCIPrationalIsInfinity(SCIP_RATIONAL *rational)
    Definition: rational.cpp:1661
    SCIP_Real SCIPrationalRoundReal(SCIP_RATIONAL *rational, SCIP_ROUNDMODE_RAT roundmode)
    Definition: rational.cpp:2109
    SCIP_Bool SCIPrationalIsNegInfinity(SCIP_RATIONAL *rational)
    Definition: rational.cpp:1671
    SCIP_Bool SCIPrationalIsEQ(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
    Definition: rational.cpp:1405
    SCIP_Bool SCIPrationalIsLE(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
    Definition: rational.cpp:1522
    SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
    Definition: var.c:17801
    SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
    Definition: var.c:19007
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23478
    SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
    Definition: var.c:23194
    SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
    Definition: var.c:23174
    SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
    Definition: var.c:23222
    int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24568
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    int SCIPvarGetCertificateIndex(SCIP_VAR *var)
    Definition: var.c:25098
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
    Definition: var.c:17550
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24585
    SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
    Definition: var.c:24342
    int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
    Definition: var.c:23214
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_RETCODE SCIPvarGetProbvarBoundExact(SCIP_VAR **var, SCIP_RATIONAL *bound, SCIP_BOUNDTYPE *boundtype)
    Definition: var.c:17894
    SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
    Definition: var.c:19115
    SCIP_RATIONAL * SCIPvarGetUbLocalExact(SCIP_VAR *var)
    Definition: var.c:24278
    SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
    Definition: var.c:23632
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
    Definition: var.c:24472
    SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24614
    SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
    Definition: var.c:24664
    int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24642
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_RATIONAL * SCIPvarGetLbGlobalExact(SCIP_VAR *var)
    Definition: var.c:24130
    SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
    Definition: var.c:23204
    SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
    Definition: var.c:17990
    int SCIPvarGetBranchPriority(SCIP_VAR *var)
    Definition: var.c:24462
    SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24653
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    void SCIPvarMarkNotDeletable(SCIP_VAR *var)
    Definition: var.c:23557
    SCIP_RATIONAL * SCIPvarGetLbLocalExact(SCIP_VAR *var)
    Definition: var.c:24244
    SCIP_RATIONAL * SCIPvarGetObjExact(SCIP_VAR *var)
    Definition: var.c:23910
    SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24600
    SCIP_RATIONAL * SCIPvarGetUbGlobalExact(SCIP_VAR *var)
    Definition: var.c:24152
    SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
    Definition: var.c:23706
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
    Definition: implics.c:3384
    int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
    Definition: implics.c:3374
    SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
    Definition: implics.c:3396
    methods for implications, variable bounds, and cliques
    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:16231
    void SCIProwCapture(SCIP_ROW *row)
    Definition: lp.c:5554
    SCIP_RETCODE SCIPlpFreeState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
    Definition: lp.c:10350
    SCIP_RETCODE SCIPlpGetNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
    Definition: lp.c:10383
    void SCIPlpMarkSize(SCIP_LP *lp)
    Definition: lp.c:10040
    SCIP_RETCODE SCIPlpGetState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
    Definition: lp.c:10283
    int SCIPlpGetNNewcols(SCIP_LP *lp)
    Definition: lp.c:18047
    SCIP_RETCODE SCIPlpAddCol(SCIP_LP *lp, SCIP_SET *set, SCIP_COL *col, int depth)
    Definition: lp.c:9699
    SCIP_RETCODE SCIPlpSetState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_EVENTQUEUE *eventqueue, SCIP_LPISTATE *lpistate, SCIP_Bool wasprimfeas, SCIP_Bool wasprimchecked, SCIP_Bool wasdualfeas, SCIP_Bool wasdualchecked)
    Definition: lp.c:10307
    SCIP_Bool SCIPlpDivingObjChanged(SCIP_LP *lp)
    Definition: lp.c:18261
    SCIP_RETCODE SCIPlpFlush(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_EVENTQUEUE *eventqueue)
    Definition: lp.c:8917
    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:13711
    SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
    Definition: lp.c:13420
    SCIP_RETCODE SCIPlpShrinkCols(SCIP_LP *lp, SCIP_SET *set, int newncols)
    Definition: lp.c:9883
    SCIP_ROW ** SCIPlpGetNewrows(SCIP_LP *lp)
    Definition: lp.c:18058
    void SCIPlpRecomputeLocalAndGlobalPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
    Definition: lp.c:13519
    SCIP_RETCODE SCIPlpClear(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
    Definition: lp.c:10021
    void SCIPlpSetIsRelax(SCIP_LP *lp, SCIP_Bool relax)
    Definition: lp.c:18188
    SCIP_Bool SCIPlpIsRelax(SCIP_LP *lp)
    Definition: lp.c:18201
    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 forcedlpsolve, SCIP_Bool *lperror)
    Definition: lp.c:12680
    SCIP_Real SCIPlpGetObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
    Definition: lp.c:13436
    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:16270
    SCIP_COL ** SCIPlpGetNewcols(SCIP_LP *lp)
    Definition: lp.c:18036
    SCIP_RETCODE SCIPlpFreeNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
    Definition: lp.c:10427
    SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
    Definition: lp.c:18251
    void SCIPlpUnmarkDivingObjChanged(SCIP_LP *lp)
    Definition: lp.c:18282
    SCIP_RETCODE SCIPlpSetNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS *lpinorms)
    Definition: lp.c:10407
    SCIP_RETCODE SCIPlpSetCutoffbound(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_Real cutoffbound)
    Definition: lp.c:10451
    SCIP_RETCODE SCIPlpShrinkRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int newnrows)
    Definition: lp.c:9955
    SCIP_RETCODE SCIPlpStartProbing(SCIP_LP *lp)
    Definition: lp.c:16699
    SCIP_RETCODE SCIPlpRemoveAllObsoletes(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
    Definition: lp.c:16062
    SCIP_RETCODE SCIPlpEndProbing(SCIP_LP *lp)
    Definition: lp.c:16714
    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:9759
    SCIP_COL ** SCIPlpGetCols(SCIP_LP *lp)
    Definition: lp.c:17969
    int SCIPlpGetNCols(SCIP_LP *lp)
    Definition: lp.c:17979
    SCIP_ROW ** SCIPlpGetRows(SCIP_LP *lp)
    Definition: lp.c:18016
    int SCIPlpGetNNewrows(SCIP_LP *lp)
    Definition: lp.c:18069
    int SCIPlpGetNRows(SCIP_LP *lp)
    Definition: lp.c:18026
    void SCIPlpSetSizeMark(SCIP_LP *lp, int nrows, int ncols)
    Definition: lp.c:10052
    SCIP_RETCODE SCIProwRelease(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
    Definition: lp.c:5567
    internal methods for LP management
    SCIP_LPSOLSTAT SCIPlpExactGetSolstat(SCIP_LPEXACT *lpexact)
    Definition: lpexact.c:8084
    void SCIPlpExactGetObjval(SCIP_LPEXACT *lpexact, SCIP_SET *set, SCIP_RATIONAL *res)
    Definition: lpexact.c:7416
    void SCIPlpExactForceSafeBound(SCIP_LPEXACT *lpexact, SCIP_SET *set)
    Definition: lpexact.c:7614
    internal methods for exact LP management
    interface methods for specific LP solvers
    #define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
    Definition: memory.h:462
    #define BMSfreeMemory(ptr)
    Definition: memory.h:145
    #define BMSfreeBlockMemory(mem, ptr)
    Definition: memory.h:465
    #define BMSallocBlockMemory(mem, ptr)
    Definition: memory.h:451
    #define BMSreallocMemoryArray(ptr, num)
    Definition: memory.h:127
    #define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
    Definition: memory.h:468
    #define BMSallocMemoryArray(ptr, num)
    Definition: memory.h:123
    #define BMSfreeMemoryArray(ptr)
    Definition: memory.h:147
    #define BMSallocBlockMemoryArray(mem, ptr, num)
    Definition: memory.h:454
    #define BMSfreeBlockMemoryArray(mem, ptr, num)
    Definition: memory.h:467
    #define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
    Definition: memory.h:458
    struct BMS_BlkMem BMS_BLKMEM
    Definition: memory.h:437
    #define BMSfreeMemoryArrayNull(ptr)
    Definition: memory.h:148
    #define BMSallocMemory(ptr)
    Definition: memory.h:118
    void SCIPmessageFPrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
    Definition: message.c:451
    void SCIPmessagePrintVerbInfo(SCIP_MESSAGEHDLR *messagehdlr, SCIP_VERBLEVEL verblevel, SCIP_VERBLEVEL msgverblevel, const char *formatstr,...)
    Definition: message.c:678
    SCIP_Real SCIPnodepqGetLowerbound(SCIP_NODEPQ *nodepq, SCIP_SET *set)
    Definition: nodesel.c:639
    int SCIPnodepqLen(const SCIP_NODEPQ *nodepq)
    Definition: nodesel.c:628
    SCIP_RETCODE SCIPnodepqRemove(SCIP_NODEPQ *nodepq, SCIP_SET *set, SCIP_NODE *node)
    Definition: nodesel.c:581
    int SCIPnodeselCompare(SCIP_NODESEL *nodesel, SCIP_SET *set, SCIP_NODE *node1, SCIP_NODE *node2)
    Definition: nodesel.c:1178
    SCIP_RATIONAL * SCIPnodepqGetLowerboundExact(SCIP_NODEPQ *nodepq, SCIP_SET *set)
    Definition: nodesel.c:662
    SCIP_RETCODE SCIPnodepqSetNodesel(SCIP_NODEPQ **nodepq, SCIP_SET *set, SCIP_NODESEL *nodesel)
    Definition: nodesel.c:219
    SCIP_RETCODE SCIPnodepqFree(SCIP_NODEPQ **nodepq, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_LP *lp)
    Definition: nodesel.c:144
    SCIP_NODESEL * SCIPnodepqGetNodesel(SCIP_NODEPQ *nodepq)
    Definition: nodesel.c:209
    SCIP_RETCODE SCIPnodepqInsert(SCIP_NODEPQ *nodepq, SCIP_SET *set, SCIP_NODE *node)
    Definition: nodesel.c:283
    SCIP_NODE * SCIPnodepqFirst(const SCIP_NODEPQ *nodepq)
    Definition: nodesel.c:602
    SCIP_RETCODE SCIPnodepqBound(SCIP_NODEPQ *nodepq, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_Real cutoffbound)
    Definition: nodesel.c:719
    int SCIPnodepqCompare(SCIP_NODEPQ *nodepq, SCIP_SET *set, SCIP_NODE *node1, SCIP_NODE *node2)
    Definition: nodesel.c:267
    SCIP_RETCODE SCIPnodepqCreate(SCIP_NODEPQ **nodepq, SCIP_SET *set, SCIP_NODESEL *nodesel)
    Definition: nodesel.c:108
    SCIP_Real SCIPnodepqGetLowerboundSum(SCIP_NODEPQ *nodepq)
    Definition: nodesel.c:709
    SCIP_NODE * SCIPnodepqGetLowerboundNode(SCIP_NODEPQ *nodepq, SCIP_SET *set)
    Definition: nodesel.c:685
    SCIP_RETCODE SCIPnodepqClear(SCIP_NODEPQ *nodepq, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_LP *lp)
    Definition: nodesel.c:168
    internal methods for node selectors and node priority queues
    internal methods for collecting primal CIP solutions and primal informations
    SCIP_RETCODE SCIPprobPerformVarDeletions(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand)
    Definition: prob.c:1233
    SCIP_RETCODE SCIPprobDelVar(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *var, SCIP_Bool *deleted)
    Definition: prob.c:1171
    int SCIPprobGetNVars(SCIP_PROB *prob)
    Definition: prob.c:2868
    SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
    Definition: prob.c:2913
    SCIP_Bool SCIPprobAllColsInLP(SCIP_PROB *prob, SCIP_SET *set, SCIP_LP *lp)
    Definition: prob.c:2825
    internal methods for storing and manipulating the main problem
    internal methods for propagators
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    void SCIPrelaxationSetSolValid(SCIP_RELAXATION *relaxation, SCIP_Bool isvalid, SCIP_Bool includeslp)
    Definition: relax.c:810
    SCIP_Bool SCIPrelaxationIsLpIncludedForSol(SCIP_RELAXATION *relaxation)
    Definition: relax.c:833
    SCIP_Bool SCIPrelaxationIsSolValid(SCIP_RELAXATION *relaxation)
    Definition: relax.c:823
    internal methods for relaxators
    SCIP_RETCODE SCIPreoptCheckCutoff(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, SCIP_EVENTTYPE eventtype, SCIP_LP *lp, SCIP_LPSOLSTAT lpsolstat, SCIP_Bool isrootnode, SCIP_Bool isfocusnode, SCIP_Real lowerbound, int effectiverootdepth)
    Definition: reopt.c:5962
    data structures and methods for collecting reoptimization information
    SCIP callable library.
    SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6716
    SCIP_Bool SCIPsetIsRelLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:7487
    SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:7076
    SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6617
    SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:7136
    SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:7087
    SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6728
    SCIP_Bool SCIPsetIsRelEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:7463
    SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:7017
    SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6993
    SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6945
    SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6648
    SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6577
    SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:7124
    SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
    Definition: set.c:6402
    SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6537
    SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:7065
    SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6969
    SCIP_Real SCIPsetInfinity(SCIP_SET *set)
    Definition: set.c:6380
    SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6557
    SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6515
    SCIP_Bool SCIPsetIsRelGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:7559
    int SCIPsetCalcPathGrowSize(SCIP_SET *set, int num)
    Definition: set.c:6098
    SCIP_Bool SCIPsetIsRelGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:7535
    SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6597
    SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6637
    SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:7041
    int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
    Definition: set.c:6080
    SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:7098
    internal methods for global SCIP settings
    #define SCIPsetDebugMsg
    Definition: set.h:1811
    SCIP_RETCODE SCIPpropagateDomains(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CONFLICT *conflict, SCIP_CLIQUETABLE *cliquetable, int depth, int maxrounds, SCIP_PROPTIMING timingmask, SCIP_Bool *cutoff)
    Definition: solve.c:658
    internal methods for main solving loop and node processing
    void SCIPstatUpdatePrimalDualIntegrals(SCIP_STAT *stat, SCIP_SET *set, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_Real upperbound, SCIP_Real lowerbound)
    Definition: stat.c:513
    internal methods for problem statistics
    #define SCIPstatIncrement(stat, set, field)
    Definition: stat.h:260
    union SCIP_BoundChg::@23 data
    SCIP_Real newbound
    Definition: struct_var.h:96
    SCIP_INFERENCEDATA inferencedata
    Definition: struct_var.h:101
    SCIP_VAR * var
    Definition: struct_var.h:104
    unsigned int boundchgtype
    Definition: struct_var.h:105
    int arraypos
    Definition: struct_tree.h:81
    SCIP_CONS ** addedconss
    Definition: struct_cons.h:118
    SCIP_CONS ** disabledconss
    Definition: struct_cons.h:119
    int validdepth
    Definition: struct_cons.h:67
    unsigned int enabled
    Definition: struct_cons.h:91
    char * name
    Definition: struct_cons.h:49
    SCIP * scip
    Definition: struct_cons.h:111
    unsigned int updatedisable
    Definition: struct_cons.h:100
    SCIP_BOUNDCHG * boundchgs
    Definition: struct_var.h:140
    unsigned int nboundchgs
    Definition: struct_var.h:138
    SCIP_BOUNDCHG * boundchgs
    Definition: struct_var.h:158
    unsigned int nboundchgs
    Definition: struct_var.h:156
    unsigned int domchgtype
    Definition: struct_var.h:157
    unsigned int lpwasprimfeas
    Definition: struct_tree.h:117
    SCIP_COL ** addedcols
    Definition: struct_tree.h:109
    unsigned int nchildren
    Definition: struct_tree.h:116
    unsigned int lpwasprimchecked
    Definition: struct_tree.h:118
    unsigned int lpwasdualfeas
    Definition: struct_tree.h:119
    int nlpistateref
    Definition: struct_tree.h:115
    int naddedrows
    Definition: struct_tree.h:114
    int naddedcols
    Definition: struct_tree.h:113
    SCIP_LPISTATE * lpistate
    Definition: struct_tree.h:111
    SCIP_ROW ** addedrows
    Definition: struct_tree.h:110
    unsigned int lpwasdualchecked
    Definition: struct_tree.h:120
    SCIP_LP * fplp
    SCIP_Bool glbpseudoobjvalid
    Definition: struct_lp.h:365
    SCIP_Bool isrelax
    Definition: struct_lp.h:380
    SCIP_Bool primalfeasible
    Definition: struct_lp.h:374
    int ncols
    Definition: struct_lp.h:334
    SCIP_Real cutoffbound
    Definition: struct_lp.h:289
    SCIP_LPEXACT * lpexact
    Definition: struct_lp.h:309
    SCIP_Bool dualfeasible
    Definition: struct_lp.h:376
    int firstnewcol
    Definition: struct_lp.h:338
    SCIP_Bool solisbasic
    Definition: struct_lp.h:378
    int nrows
    Definition: struct_lp.h:340
    SCIP_Bool primalchecked
    Definition: struct_lp.h:375
    SCIP_Bool divingobjchg
    Definition: struct_lp.h:387
    int firstnewrow
    Definition: struct_lp.h:342
    SCIP_LPSOLSTAT lpsolstat
    Definition: struct_lp.h:359
    int nlpicols
    Definition: struct_lp.h:323
    SCIP_Real lpobjval
    Definition: struct_lp.h:276
    int nlpirows
    Definition: struct_lp.h:326
    SCIP_Bool solved
    Definition: struct_lp.h:373
    SCIP_Bool resolvelperror
    Definition: struct_lp.h:389
    SCIP_Bool dualchecked
    Definition: struct_lp.h:377
    SCIP_Bool pseudoobjvalid
    Definition: struct_lp.h:366
    SCIP_Bool hasprovedbound
    Definition: struct_lp.h:409
    SCIP_LPI * lpi
    Definition: struct_lp.h:301
    SCIP_Bool flushed
    Definition: struct_lp.h:372
    unsigned int reoptid
    Definition: struct_tree.h:162
    union SCIP_Node::@21 data
    unsigned int repropsubtreemark
    Definition: struct_tree.h:164
    unsigned int reprop
    Definition: struct_tree.h:167
    SCIP_DOMCHG * domchg
    Definition: struct_tree.h:160
    SCIP_PROBINGNODE * probingnode
    Definition: struct_tree.h:149
    SCIP_PSEUDOFORK * pseudofork
    Definition: struct_tree.h:154
    SCIP_Longint number
    Definition: struct_tree.h:143
    SCIP_JUNCTION junction
    Definition: struct_tree.h:153
    unsigned int nodetype
    Definition: struct_tree.h:168
    unsigned int cutoff
    Definition: struct_tree.h:166
    unsigned int reopttype
    Definition: struct_tree.h:163
    SCIP_SUBROOT * subroot
    Definition: struct_tree.h:156
    SCIP_FORK * fork
    Definition: struct_tree.h:155
    SCIP_CHILD child
    Definition: struct_tree.h:151
    SCIP_SIBLING sibling
    Definition: struct_tree.h:150
    SCIP_Real lowerbound
    Definition: struct_tree.h:144
    SCIP_RATIONAL * lowerboundexact
    Definition: struct_tree.h:145
    SCIP_Real estimate
    Definition: struct_tree.h:146
    SCIP_CONSSETCHG * conssetchg
    Definition: struct_tree.h:159
    unsigned int depth
    Definition: struct_tree.h:161
    SCIP_NODE * parent
    Definition: struct_tree.h:158
    unsigned int active
    Definition: struct_tree.h:165
    SCIP_NODE * node
    Definition: struct_tree.h:174
    SCIP_Real newbound
    Definition: struct_tree.h:176
    SCIP_Bool probingchange
    Definition: struct_tree.h:182
    SCIP_PROP * inferprop
    Definition: struct_tree.h:180
    SCIP_RATIONAL * newboundexact
    Definition: struct_tree.h:177
    SCIP_CONS * infercons
    Definition: struct_tree.h:179
    SCIP_VAR * var
    Definition: struct_tree.h:175
    SCIP_BOUNDTYPE boundtype
    Definition: struct_tree.h:178
    SCIP_RATIONAL * upperboundexact
    Definition: struct_primal.h:56
    SCIP_Real cutoffbound
    Definition: struct_primal.h:57
    SCIP_Real upperbound
    Definition: struct_primal.h:55
    SCIP_Bool lpwasdualchecked
    Definition: struct_tree.h:69
    SCIP_Bool lpwasprimfeas
    Definition: struct_tree.h:66
    SCIP_VAR ** origobjvars
    Definition: struct_tree.h:63
    SCIP_Bool lpwasdualfeas
    Definition: struct_tree.h:68
    SCIP_LPISTATE * lpistate
    Definition: struct_tree.h:57
    SCIP_Real * origobjvals
    Definition: struct_tree.h:64
    SCIP_LPINORMS * lpinorms
    Definition: struct_tree.h:58
    SCIP_Bool lpwasprimchecked
    Definition: struct_tree.h:67
    SCIP_ROW ** addedrows
    Definition: struct_tree.h:100
    SCIP_COL ** addedcols
    Definition: struct_tree.h:99
    SCIP_Longint nearlybacktracks
    Definition: struct_stat.h:96
    SCIP_Real rootlowerbound
    Definition: struct_stat.h:133
    SCIP_Bool inrestart
    Definition: struct_stat.h:316
    SCIP_Longint nactiveconssadded
    Definition: struct_stat.h:126
    SCIP_Longint nreprops
    Definition: struct_stat.h:100
    SCIP_Longint nnodes
    Definition: struct_stat.h:84
    SCIP_Longint nrepropcutoffs
    Definition: struct_stat.h:102
    SCIP_RATIONAL * lastlowerboundexact
    Definition: struct_stat.h:156
    SCIP_Longint ncreatednodesrun
    Definition: struct_stat.h:93
    SCIP_CLOCK * nodeactivationtime
    Definition: struct_stat.h:190
    SCIP_Longint nlps
    Definition: struct_stat.h:207
    SCIP_Real lastlowerbound
    Definition: struct_stat.h:155
    SCIP_Longint lpcount
    Definition: struct_stat.h:205
    SCIP_Longint nprobholechgs
    Definition: struct_stat.h:120
    SCIP_Longint nbacktracks
    Definition: struct_stat.h:98
    SCIP_Longint ndeactivatednodes
    Definition: struct_stat.h:95
    SCIP_Longint nrepropboundchgs
    Definition: struct_stat.h:101
    SCIP_VISUAL * visual
    Definition: struct_stat.h:198
    SCIP_Real referencebound
    Definition: struct_stat.h:159
    SCIP_Longint nboundchgs
    Definition: struct_stat.h:117
    SCIP_Longint nholechgs
    Definition: struct_stat.h:118
    SCIP_CERTIFICATE * certificate
    Definition: struct_stat.h:199
    SCIP_Longint nactivatednodes
    Definition: struct_stat.h:94
    int plungedepth
    Definition: struct_stat.h:274
    SCIP_Longint ncreatednodes
    Definition: struct_stat.h:92
    SCIP_LPISTATE * lpistate
    Definition: struct_tree.h:128
    unsigned int lpwasdualchecked
    Definition: struct_tree.h:137
    SCIP_COL ** cols
    Definition: struct_tree.h:126
    unsigned int nchildren
    Definition: struct_tree.h:133
    SCIP_ROW ** rows
    Definition: struct_tree.h:127
    unsigned int lpwasdualfeas
    Definition: struct_tree.h:136
    unsigned int lpwasprimchecked
    Definition: struct_tree.h:135
    unsigned int lpwasprimfeas
    Definition: struct_tree.h:134
    int repropsubtreecount
    Definition: struct_tree.h:236
    SCIP_Bool focuslpconstructed
    Definition: struct_tree.h:240
    int correctlpdepth
    Definition: struct_tree.h:233
    SCIP_NODE * root
    Definition: struct_tree.h:188
    SCIP_LPISTATE * probinglpistate
    Definition: struct_tree.h:212
    SCIP_Real * siblingsprio
    Definition: struct_tree.h:204
    SCIP_Bool cutoffdelayed
    Definition: struct_tree.h:241
    SCIP_PENDINGBDCHG * pendingbdchgs
    Definition: struct_tree.h:215
    SCIP_Bool probinglpwasdualchecked
    Definition: struct_tree.h:253
    SCIP_NODE * focuslpstatefork
    Definition: struct_tree.h:198
    SCIP_Bool probinglpwasprimfeas
    Definition: struct_tree.h:250
    int cutoffdepth
    Definition: struct_tree.h:234
    int * pathnlprows
    Definition: struct_tree.h:210
    SCIP_NODE ** path
    Definition: struct_tree.h:190
    SCIP_BRANCHDIR * divebdchgdirs[2]
    Definition: struct_tree.h:206
    SCIP_Bool probinglpwassolved
    Definition: struct_tree.h:243
    SCIP_Bool probinglpwasrelax
    Definition: struct_tree.h:245
    SCIP_Bool sbprobing
    Definition: struct_tree.h:249
    SCIP_NODE * focusnode
    Definition: struct_tree.h:193
    int pathsize
    Definition: struct_tree.h:230
    SCIP_Bool probingnodehaslp
    Definition: struct_tree.h:239
    SCIP_Bool probingobjchanged
    Definition: struct_tree.h:248
    SCIP_Real probinglpobjval
    Definition: struct_tree.h:217
    int nsiblings
    Definition: struct_tree.h:228
    SCIP_Bool focusnodehaslp
    Definition: struct_tree.h:238
    int npendingbdchgs
    Definition: struct_tree.h:224
    SCIP_Real * divebdchgvals[2]
    Definition: struct_tree.h:207
    int divebdchgsize[2]
    Definition: struct_tree.h:221
    int nprobdiverelaxsol
    Definition: struct_tree.h:218
    int updatedeffectiverootdepth
    Definition: struct_tree.h:232
    SCIP_NODE ** siblings
    Definition: struct_tree.h:202
    SCIP_Bool probdiverelaxincludeslp
    Definition: struct_tree.h:256
    int repropdepth
    Definition: struct_tree.h:235
    int nchildren
    Definition: struct_tree.h:226
    int childrensize
    Definition: struct_tree.h:225
    SCIP_VAR ** divebdchgvars[2]
    Definition: struct_tree.h:205
    int siblingssize
    Definition: struct_tree.h:227
    int ndivebdchanges[2]
    Definition: struct_tree.h:222
    SCIP_Bool probingsolvedlp
    Definition: struct_tree.h:246
    int effectiverootdepth
    Definition: struct_tree.h:231
    SCIP_Bool probinglpwasprimchecked
    Definition: struct_tree.h:251
    SCIP_LPINORMS * probinglpinorms
    Definition: struct_tree.h:214
    SCIP_Bool probinglpwasflushed
    Definition: struct_tree.h:242
    int probingsumchgdobjs
    Definition: struct_tree.h:237
    SCIP_Longint lastbranchparentid
    Definition: struct_tree.h:220
    int * pathnlpcols
    Definition: struct_tree.h:208
    SCIP_Real * childrenprio
    Definition: struct_tree.h:203
    SCIP_NODE * focussubroot
    Definition: struct_tree.h:199
    SCIP_Bool probdiverelaxstored
    Definition: struct_tree.h:255
    SCIP_NODE ** children
    Definition: struct_tree.h:201
    SCIP_Real * probdiverelaxsol
    Definition: struct_tree.h:216
    SCIP_NODE * probingroot
    Definition: struct_tree.h:200
    SCIP_Bool probingloadlpistate
    Definition: struct_tree.h:244
    SCIP_Longint focuslpstateforklpcount
    Definition: struct_tree.h:219
    SCIP_NODE * focuslpfork
    Definition: struct_tree.h:197
    int pendingbdchgssize
    Definition: struct_tree.h:223
    SCIP_NODEPQ * leaves
    Definition: struct_tree.h:189
    SCIP_Bool probinglphadsafebound
    Definition: struct_tree.h:254
    SCIP_Bool probinglpwasdualfeas
    Definition: struct_tree.h:252
    datastructures for managing events
    data structures for exact LP management
    datastructures for block memory pools and memory buffers
    SCIP main data structure.
    Definition: heur_padm.c:135
    SCIP_Bool SCIPtreeIsFocusNodeLPConstructed(SCIP_TREE *tree)
    Definition: tree.c:9481
    SCIP_NODE * SCIPtreeGetProbingRoot(SCIP_TREE *tree)
    Definition: tree.c:9413
    SCIP_RETCODE SCIPnodeReleaseLPIState(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_LP *lp)
    Definition: tree.c:278
    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:2598
    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:529
    static void treeCheckPath(SCIP_TREE *tree)
    Definition: tree.c:4037
    static void subrootCaptureLPIState(SCIP_SUBROOT *subroot, int nuses)
    Definition: tree.c:211
    void SCIPnodeGetDualBoundchgs(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *bounds, SCIP_BOUNDTYPE *boundtypes, int *nvars, int varssize)
    Definition: tree.c:8745
    SCIP_NODE * SCIPtreeGetBestSibling(SCIP_TREE *tree, SCIP_SET *set)
    Definition: tree.c:8191
    SCIP_RETCODE SCIPtreeFree(SCIP_TREE **tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp)
    Definition: tree.c:5618
    static SCIP_RETCODE focusnodeToFork(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable)
    Definition: tree.c:4702
    static SCIP_RETCODE treeUpdatePathLPSize(SCIP_TREE *tree, int startdepth)
    Definition: tree.c:3288
    SCIP_RETCODE SCIPnodeAddBoundchgExact(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_RATIONAL *newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
    Definition: tree.c:2568
    static SCIP_RETCODE focusnodeToPseudofork(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable)
    Definition: tree.c:4650
    static SCIP_RETCODE focusnodeToLeaf(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_NODE *lpstatefork, SCIP_Real cutoffbound)
    Definition: tree.c:4583
    SCIP_NODE * SCIPtreeGetFocusNode(SCIP_TREE *tree)
    Definition: tree.c:9426
    SCIP_Bool SCIPtreeProbing(SCIP_TREE *tree)
    Definition: tree.c:9400
    int SCIPtreeGetFocusDepth(SCIP_TREE *tree)
    Definition: tree.c:9443
    SCIP_Real SCIPtreeGetAvgLowerbound(SCIP_TREE *tree, SCIP_Real cutoffbound)
    Definition: tree.c:8425
    static SCIP_RETCODE pseudoforkFree(SCIP_PSEUDOFORK **pseudofork, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
    Definition: tree.c:499
    SCIP_Bool SCIPtreeIsPathComplete(SCIP_TREE *tree)
    Definition: tree.c:9383
    static SCIP_RETCODE junctionInit(SCIP_JUNCTION *junction, SCIP_TREE *tree)
    Definition: tree.c:422
    SCIP_Bool SCIPtreeProbingObjChanged(SCIP_TREE *tree)
    Definition: tree.c:9579
    SCIP_RETCODE SCIPnodeAddBoundchg(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
    Definition: tree.c:2539
    int SCIPtreeGetProbingDepth(SCIP_TREE *tree)
    Definition: tree.c:9546
    SCIP_RETCODE SCIPtreeSetNodesel(SCIP_TREE *tree, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_NODESEL *nodesel)
    Definition: tree.c:5868
    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:1660
    SCIP_RETCODE SCIPnodeDelCons(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_CONS *cons)
    Definition: tree.c:1739
    void SCIPnodeSetEstimate(SCIP_NODE *node, SCIP_SET *set, SCIP_Real newestimate)
    Definition: tree.c:3084
    void SCIPnodePropagateAgain(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree)
    Definition: tree.c:1368
    static SCIP_RETCODE nodeToLeaf(SCIP_NODE **node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_NODE *lpstatefork, SCIP_Real cutoffbound)
    Definition: tree.c:4358
    SCIP_RETCODE SCIPnodeCaptureLPIState(SCIP_NODE *node, int nuses)
    Definition: tree.c:250
    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:3946
    static SCIP_RETCODE treeCreateProbingNode(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
    Definition: tree.c:7324
    static void treeNextRepropsubtreecount(SCIP_TREE *tree)
    Definition: tree.c:1424
    #define MAXREPROPMARK
    Definition: tree.c:67
    void SCIPnodeGetPropsAfterDual(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *varbounds, SCIP_BOUNDTYPE *varboundtypes, int *nvars, int varssize)
    Definition: tree.c:9056
    SCIP_RETCODE SCIPtreeStartProbing(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_PROB *transprob, SCIP_Bool strongbranching)
    Definition: tree.c:7415
    static SCIP_RETCODE treeEnsureChildrenMem(SCIP_TREE *tree, SCIP_SET *set, int num)
    Definition: tree.c:76
    SCIP_RATIONAL * SCIPtreeGetLowerboundExact(SCIP_TREE *tree, SCIP_SET *set)
    Definition: tree.c:8303
    int SCIPtreeGetNChildren(SCIP_TREE *tree)
    Definition: tree.c:9343
    SCIP_RETCODE SCIPtreeSetProbingLPState(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_LP *lp, SCIP_LPISTATE **lpistate, SCIP_LPINORMS **lpinorms, SCIP_Bool primalfeas, SCIP_Bool dualfeas)
    Definition: tree.c:7508
    SCIP_RETCODE SCIPnodeCutoff(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_REOPT *reopt, SCIP_LP *lp, BMS_BLKMEM *blkmem)
    Definition: tree.c:1259
    SCIP_RETCODE SCIPtreeBranchVar(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *var, SCIP_Real val, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
    Definition: tree.c:6173
    static SCIP_RETCODE treeNodesToQueue(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_NODE **nodes, int *nnodes, SCIP_NODE *lpstatefork, SCIP_Real cutoffbound)
    Definition: tree.c:4933
    SCIP_NODE * SCIPtreeGetCurrentNode(SCIP_TREE *tree)
    Definition: tree.c:9501
    void SCIPnodeMarkPropagated(SCIP_NODE *node, SCIP_TREE *tree)
    Definition: tree.c:1394
    int SCIPtreeGetNLeaves(SCIP_TREE *tree)
    Definition: tree.c:9363
    SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
    Definition: tree.c:9568
    SCIP_RETCODE SCIPtreeStoreRelaxSol(SCIP_TREE *tree, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_PROB *transprob)
    Definition: tree.c:8035
    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:1050
    static SCIP_RETCODE nodeActivate(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
    Definition: tree.c:1587
    static SCIP_RETCODE treeSwitchPath(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_NODE *fork, SCIP_NODE *focusnode, SCIP_Bool *cutoff)
    Definition: tree.c:3694
    SCIP_RETCODE SCIPtreeBranchVarExact(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *var, SCIP_NODE **downchild, SCIP_NODE **upchild)
    Definition: tree.c:6587
    static void treeRemoveChild(SCIP_TREE *tree, SCIP_NODE *child)
    Definition: tree.c:768
    void SCIPtreeMarkProbingObjChanged(SCIP_TREE *tree)
    Definition: tree.c:9590
    static void treeChildrenToSiblings(SCIP_TREE *tree)
    Definition: tree.c:4970
    SCIP_RETCODE SCIPtreeAddDiveBoundChange(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Bool preferred)
    Definition: tree.c:7254
    SCIP_RETCODE SCIPnodeFree(SCIP_NODE **node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_LP *lp)
    Definition: tree.c:1115
    static SCIP_RETCODE focusnodeToDeadend(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable)
    Definition: tree.c:4539
    SCIP_Bool SCIPtreeHasCurrentNodeLP(SCIP_TREE *tree)
    Definition: tree.c:9535
    SCIP_Real SCIPtreeGetLowerbound(SCIP_TREE *tree, SCIP_SET *set)
    Definition: tree.c:8262
    SCIP_RETCODE SCIPtreeRestoreRelaxSol(SCIP_TREE *tree, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_PROB *transprob)
    Definition: tree.c:8079
    static SCIP_RETCODE probingnodeCreate(SCIP_PROBINGNODE **probingnode, BMS_BLKMEM *blkmem, SCIP_LP *lp)
    Definition: tree.c:303
    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:2711
    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:3396
    SCIP_RETCODE SCIPnodeAddBoundinferExact(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_RATIONAL *newbound, SCIP_BOUNDTYPE boundtype, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_Bool probingchange)
    Definition: tree.c:2229
    SCIP_RETCODE SCIPtreeCreatePresolvingRoot(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable)
    Definition: tree.c:5774
    static SCIP_RETCODE focusnodeCleanupVars(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool inlp)
    Definition: tree.c:4437
    SCIP_NODE * SCIPtreeGetBestChild(SCIP_TREE *tree, SCIP_SET *set)
    Definition: tree.c:8164
    SCIP_RETCODE SCIPtreeLoadProbingLPState(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
    Definition: tree.c:7562
    int SCIPtreeGetEffectiveRootDepth(SCIP_TREE *tree)
    Definition: tree.c:9557
    static void treeRemoveSibling(SCIP_TREE *tree, SCIP_NODE *sibling)
    Definition: tree.c:719
    SCIP_RETCODE SCIPtreeCreateRoot(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp)
    Definition: tree.c:5728
    static SCIP_RETCODE subrootReleaseLPIState(SCIP_SUBROOT *subroot, BMS_BLKMEM *blkmem, SCIP_LP *lp)
    Definition: tree.c:227
    SCIP_NODE * SCIPtreeGetPrioSibling(SCIP_TREE *tree)
    Definition: tree.c:8138
    static SCIP_RETCODE nodeRepropagate(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
    Definition: tree.c:1436
    void SCIPtreeSetFocusNodeLP(SCIP_TREE *tree, SCIP_Bool solvelp)
    Definition: tree.c:9470
    int SCIPnodeGetNDualBndchgs(SCIP_NODE *node)
    Definition: tree.c:8704
    SCIP_RETCODE SCIPnodeAddCons(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_CONS *cons)
    Definition: tree.c:1696
    static SCIP_RETCODE treeApplyPendingBdchgs(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable)
    Definition: tree.c:2744
    int SCIPtreeGetNNodes(SCIP_TREE *tree)
    Definition: tree.c:9373
    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:3901
    static SCIP_RETCODE treeAddChild(SCIP_TREE *tree, SCIP_SET *set, SCIP_NODE *child, SCIP_Real nodeselprio)
    Definition: tree.c:745
    static SCIP_RETCODE pseudoforkCreate(SCIP_PSEUDOFORK **pseudofork, BMS_BLKMEM *blkmem, SCIP_TREE *tree, SCIP_LP *lp)
    Definition: tree.c:446
    static SCIP_RETCODE probingnodeFree(SCIP_PROBINGNODE **probingnode, BMS_BLKMEM *blkmem, SCIP_LP *lp)
    Definition: tree.c:385
    SCIP_Real SCIPtreeCalcNodeselPriority(SCIP_TREE *tree, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_BRANCHDIR branchdir, SCIP_Real targetvalue)
    Definition: tree.c:5964
    static SCIP_RETCODE forkReleaseLPIState(SCIP_FORK *fork, BMS_BLKMEM *blkmem, SCIP_LP *lp)
    Definition: tree.c:187
    static SCIP_RETCODE probingnodeUpdate(SCIP_PROBINGNODE *probingnode, BMS_BLKMEM *blkmem, SCIP_TREE *tree, SCIP_LP *lp)
    Definition: tree.c:330
    SCIP_RETCODE SCIPnodePropagateImplics(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
    Definition: tree.c:3100
    int SCIPtreeGetNSiblings(SCIP_TREE *tree)
    Definition: tree.c:9353
    SCIP_RETCODE SCIPtreeClear(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp)
    Definition: tree.c:5667
    SCIP_NODE * SCIPtreeGetBestNode(SCIP_TREE *tree, SCIP_SET *set)
    Definition: tree.c:8228
    static SCIP_RETCODE treeEnsurePendingbdchgsMem(SCIP_TREE *tree, SCIP_SET *set, int num)
    Definition: tree.c:127
    SCIP_NODE * SCIPtreeGetBestLeaf(SCIP_TREE *tree)
    Definition: tree.c:8218
    SCIP_RETCODE SCIPtreeEndProbing(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_RELAXATION *relaxation, SCIP_PRIMAL *primal, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable)
    Definition: tree.c:7852
    SCIP_RETCODE SCIPtreeCutoff(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_Real cutoffbound)
    Definition: tree.c:5896
    SCIP_Bool SCIPtreeHasFocusNodeLP(SCIP_TREE *tree)
    Definition: tree.c:9460
    void SCIPtreeGetDiveBoundChangeData(SCIP_TREE *tree, SCIP_VAR ***variables, SCIP_BRANCHDIR **directions, SCIP_Real **values, int *ndivebdchgs, SCIP_Bool preferred)
    Definition: tree.c:7286
    SCIP_RETCODE SCIPtreeFreePresolvingRoot(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable)
    Definition: tree.c:5815
    static SCIP_RETCODE nodeReleaseParent(SCIP_NODE **node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_TREE *tree)
    Definition: tree.c:854
    SCIP_RETCODE SCIPtreeCreate(SCIP_TREE **tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_NODESEL *nodesel)
    Definition: tree.c:5537
    void SCIPchildChgNodeselPrio(SCIP_TREE *tree, SCIP_NODE *child, SCIP_Real priority)
    Definition: tree.c:3066
    int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
    Definition: tree.c:9518
    SCIP_NODE * SCIPtreeGetPrioChild(SCIP_TREE *tree)
    Definition: tree.c:8112
    static SCIP_RETCODE treeEnsurePathMem(SCIP_TREE *tree, SCIP_SET *set, int num)
    Definition: tree.c:101
    SCIP_RETCODE SCIPtreeBranchVarHole(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *var, SCIP_Real left, SCIP_Real right, SCIP_NODE **downchild, SCIP_NODE **upchild)
    Definition: tree.c:6738
    static SCIP_RETCODE subrootFree(SCIP_SUBROOT **subroot, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
    Definition: tree.c:686
    SCIP_Bool SCIPtreeWasNodeLastBranchParent(SCIP_TREE *tree, SCIP_NODE *node)
    Definition: tree.c:1102
    SCIP_RETCODE SCIPtreeCreateProbingNode(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
    Definition: tree.c:7483
    SCIP_RETCODE SCIPnodeUpdateLowerboundLP(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_MESSAGEHDLR *messagehdlr, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp)
    Definition: tree.c:2973
    static SCIP_RETCODE forkFree(SCIP_FORK **fork, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
    Definition: tree.c:592
    SCIP_RETCODE SCIPtreeMarkProbingNodeHasLP(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_LP *lp)
    Definition: tree.c:7644
    SCIP_RETCODE SCIPtreeBranchVarNary(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *var, SCIP_Real val, int n, SCIP_Real minwidth, SCIP_Real widthfactor, int *nchildren)
    Definition: tree.c:6881
    SCIP_RETCODE SCIPnodeAddBoundinfer(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_Bool probingchange)
    Definition: tree.c:1909
    static SCIP_RETCODE treeBacktrackProbing(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_PRIMAL *primal, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, int probingdepth)
    Definition: tree.c:7672
    SCIP_RETCODE SCIPtreeLoadLPState(SCIP_TREE *tree, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
    Definition: tree.c:4238
    SCIP_RETCODE SCIPnodeFocus(SCIP_NODE **node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_CONFLICT *conflict, SCIP_CONFLICTSTORE *conflictstore, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff, SCIP_Bool postponed, SCIP_Bool exitsolve)
    Definition: tree.c:5007
    SCIP_Bool SCIPtreeInRepropagation(SCIP_TREE *tree)
    Definition: tree.c:9491
    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:796
    static void forkCaptureLPIState(SCIP_FORK *fork, int nuses)
    Definition: tree.c:172
    SCIP_NODESEL * SCIPtreeGetNodesel(SCIP_TREE *tree)
    Definition: tree.c:5858
    SCIP_Real SCIPtreeCalcChildEstimate(SCIP_TREE *tree, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_Real targetvalue)
    Definition: tree.c:6114
    SCIP_NODE * SCIPtreeGetLowerboundNode(SCIP_TREE *tree, SCIP_SET *set)
    Definition: tree.c:8344
    SCIP_RETCODE SCIPtreeBacktrackProbing(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_PRIMAL *primal, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, int probingdepth)
    Definition: tree.c:7818
    SCIP_RETCODE SCIPnodeUpdateLowerbound(SCIP_NODE *node, SCIP_STAT *stat, SCIP_SET *set, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_Real newbound, SCIP_RATIONAL *newboundexact)
    Definition: tree.c:2851
    static SCIP_RETCODE focusnodeToJunction(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_TREE *tree, SCIP_LP *lp)
    Definition: tree.c:4613
    static SCIP_RETCODE treeAddPendingBdchg(SCIP_TREE *tree, SCIP_SET *set, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound, SCIP_RATIONAL *newboundexact, SCIP_BOUNDTYPE boundtype, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_Bool probingchange)
    Definition: tree.c:1813
    void SCIPnodeGetPropsBeforeDual(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *varbounds, SCIP_BOUNDTYPE *varboundtypes, int *npropvars, int propvarssize)
    Definition: tree.c:8974
    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:4109
    static SCIP_RETCODE nodeCreate(SCIP_NODE **node, BMS_BLKMEM *blkmem, SCIP_SET *set)
    Definition: tree.c:1016
    void SCIPtreeClearDiveBoundChanges(SCIP_TREE *tree)
    Definition: tree.c:7309
    #define ARRAYGROWTH
    Definition: tree.c:7253
    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:3991
    internal methods for branch and bound tree
    #define SCIP_EVENTTYPE_NODEINFEASIBLE
    Definition: type_event.h:95
    #define SCIP_EVENTTYPE_DUALBOUNDIMPROVED
    Definition: type_event.h:98
    #define SCIP_EVENTTYPE_NODEDELETE
    Definition: type_event.h:97
    @ SCIP_BRANCHDIR_DOWNWARDS
    Definition: type_history.h:43
    @ SCIP_BRANCHDIR_FIXED
    Definition: type_history.h:45
    @ SCIP_BRANCHDIR_AUTO
    Definition: type_history.h:46
    @ SCIP_BRANCHDIR_UPWARDS
    Definition: type_history.h:44
    enum SCIP_BranchDir SCIP_BRANCHDIR
    Definition: type_history.h:48
    enum SCIP_LPSolStat SCIP_LPSOLSTAT
    Definition: type_lp.h:52
    @ SCIP_BOUNDTYPE_UPPER
    Definition: type_lp.h:58
    @ SCIP_BOUNDTYPE_LOWER
    Definition: type_lp.h:57
    enum SCIP_BoundType SCIP_BOUNDTYPE
    Definition: type_lp.h:60
    @ SCIP_LPSOLSTAT_NOTSOLVED
    Definition: type_lp.h:43
    @ SCIP_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    @ SCIP_LPSOLSTAT_TIMELIMIT
    Definition: type_lp.h:49
    @ SCIP_LPSOLSTAT_UNBOUNDEDRAY
    Definition: type_lp.h:46
    @ SCIP_LPSOLSTAT_INFEASIBLE
    Definition: type_lp.h:45
    @ SCIP_LPSOLSTAT_OBJLIMIT
    Definition: type_lp.h:47
    @ SCIP_LPSOLSTAT_ITERLIMIT
    Definition: type_lp.h:48
    @ SCIP_VERBLEVEL_FULL
    Definition: type_message.h:62
    @ SCIP_R_ROUND_UPWARDS
    Definition: type_rational.h:58
    @ SCIP_R_ROUND_DOWNWARDS
    Definition: type_rational.h:57
    @ SCIP_REOPTTYPE_INFSUBTREE
    Definition: type_reopt.h:60
    @ SCIP_REOPTTYPE_LOGICORNODE
    Definition: type_reopt.h:62
    @ SCIP_REOPTTYPE_PRUNED
    Definition: type_reopt.h:64
    @ SCIP_REOPTTYPE_FEASIBLE
    Definition: type_reopt.h:65
    @ SCIP_REOPTTYPE_LEAF
    Definition: type_reopt.h:63
    @ SCIP_REOPTTYPE_TRANSIT
    Definition: type_reopt.h:59
    @ SCIP_REOPTTYPE_STRBRANCHED
    Definition: type_reopt.h:61
    @ SCIP_REOPTTYPE_NONE
    Definition: type_reopt.h:58
    enum SCIP_ReoptType SCIP_REOPTTYPE
    Definition: type_reopt.h:67
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_MAXDEPTHLEVEL
    Definition: type_retcode.h:59
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_PRESOLVING
    Definition: type_set.h:49
    @ SCIP_STAGE_INITSOLVE
    Definition: type_set.h:52
    @ SCIP_STAGE_SOLVING
    Definition: type_set.h:53
    #define SCIP_PROPTIMING_ALWAYS
    Definition: type_timing.h:73
    enum SCIP_NodeType SCIP_NODETYPE
    Definition: type_tree.h:53
    @ SCIP_NODETYPE_REFOCUSNODE
    Definition: type_tree.h:51
    @ SCIP_NODETYPE_FORK
    Definition: type_tree.h:49
    @ SCIP_NODETYPE_CHILD
    Definition: type_tree.h:44
    @ SCIP_NODETYPE_PROBINGNODE
    Definition: type_tree.h:42
    @ SCIP_NODETYPE_JUNCTION
    Definition: type_tree.h:47
    @ SCIP_NODETYPE_PSEUDOFORK
    Definition: type_tree.h:48
    @ SCIP_NODETYPE_DEADEND
    Definition: type_tree.h:46
    @ SCIP_NODETYPE_SIBLING
    Definition: type_tree.h:43
    @ SCIP_NODETYPE_LEAF
    Definition: type_tree.h:45
    @ SCIP_NODETYPE_SUBROOT
    Definition: type_tree.h:50
    @ SCIP_NODETYPE_FOCUSNODE
    Definition: type_tree.h:41
    @ SCIP_DOMCHGTYPE_DYNAMIC
    Definition: type_var.h:122
    @ SCIP_BOUNDCHGTYPE_PROPINFER
    Definition: type_var.h:133
    @ SCIP_BOUNDCHGTYPE_BRANCHING
    Definition: type_var.h:131
    @ SCIP_BOUNDCHGTYPE_CONSINFER
    Definition: type_var.h:132
    @ SCIP_VARSTATUS_FIXED
    Definition: type_var.h:54
    @ SCIP_VARSTATUS_COLUMN
    Definition: type_var.h:53
    @ SCIP_VARSTATUS_MULTAGGR
    Definition: type_var.h:56
    @ SCIP_VARSTATUS_LOOSE
    Definition: type_var.h:52
    SCIP_DOMCHGBOUND domchgbound
    Definition: struct_var.h:168
    SCIP_DOMCHGDYN domchgdyn
    Definition: struct_var.h:170
    SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
    Definition: var.c:20437
    SCIP_RETCODE SCIPdomchgAddBoundchg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Real newbound, SCIP_RATIONAL *newboundexact, 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:1734
    SCIP_RETCODE SCIPvarChgObj(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newobj)
    Definition: var.c:9419
    SCIP_RETCODE SCIPvarChgBdGlobalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *newbound, SCIP_BOUNDTYPE boundtype)
    Definition: var.c:11848
    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:1640
    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:845
    SCIP_RETCODE SCIPdomchgMakeStatic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
    Definition: var.c:1451
    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:14178
    SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
    Definition: var.c:3787
    void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
    Definition: var.c:9910
    void SCIPvarAdjustLbExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *lb)
    Definition: var.c:9927
    void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
    Definition: var.c:10012
    SCIP_RETCODE SCIPdomchgFree(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
    Definition: var.c:1348
    void SCIPvarCapture(SCIP_VAR *var)
    Definition: var.c:3762
    void SCIPvarAdjustUbExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *ub)
    Definition: var.c:9978
    SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
    Definition: var.c:22119
    int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
    Definition: var.c:22816
    SCIP_RETCODE SCIPdomchgApplyGlobal(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
    Definition: var.c:1675
    void SCIPdomchgAddCurrentCertificateIndex(SCIP_DOMCHG *domchg, SCIP_CERTIFICATE *certificate)
    Definition: var.c:1714
    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:1591
    SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
    Definition: var.c:19688
    SCIP_RETCODE SCIPvarChgBdGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
    Definition: var.c:11819
    SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
    Definition: var.c:18075
    void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
    Definition: var.c:9961
    SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
    Definition: var.c:19627
    internal methods for problem variables
    SCIP_RETCODE SCIPvisualUpdateChild(SCIP_VISUAL *visual, SCIP_SET *set, SCIP_STAT *stat, SCIP_NODE *node)
    Definition: visual.c:341
    void SCIPvisualLowerbound(SCIP_VISUAL *visual, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real lowerbound)
    Definition: visual.c:768
    void SCIPvisualMarkedRepropagateNode(SCIP_VISUAL *visual, SCIP_STAT *stat, SCIP_NODE *node)
    Definition: visual.c:630
    SCIP_RETCODE SCIPvisualNewChild(SCIP_VISUAL *visual, SCIP_SET *set, SCIP_STAT *stat, SCIP_NODE *node)
    Definition: visual.c:266
    void SCIPvisualCutoffNode(SCIP_VISUAL *visual, SCIP_SET *set, SCIP_STAT *stat, SCIP_NODE *node, SCIP_Bool infeasible)
    Definition: visual.c:533
    void SCIPvisualRepropagatedNode(SCIP_VISUAL *visual, SCIP_STAT *stat, SCIP_NODE *node)
    Definition: visual.c:651
    methods for creating output for visualization tools (VBC, BAK)