Scippy

    SCIP

    Solving Constraint Integer Programs

    reopt.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-2025 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 reopt.c
    26 * @ingroup OTHER_CFILES
    27 * @brief data structures and methods for collecting reoptimization information
    28 * @author Jakob Witzig
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32#include <assert.h>
    33#include <string.h>
    34
    35#include "scip/def.h"
    36#include "scip/mem.h"
    37#include "scip/event.h"
    38#include "scip/scip.h"
    39#include "scip/set.h"
    40#include "scip/sol.h"
    41#include "scip/var.h"
    42#include "scip/lp.h"
    43#include "scip/misc.h"
    44#include "scip/reopt.h"
    45#include "scip/tree.h"
    46#include "scip/primal.h"
    47#include "scip/sepastore.h"
    48#include "scip/cutpool.h"
    49#include "scip/prob.h"
    50#include "scip/cons.h"
    52#include "scip/cons_linear.h"
    53#include "scip/cons_logicor.h"
    54#include "scip/cons_setppc.h"
    55#include "scip/cons_linear.h"
    56#include "scip/clock.h"
    57#include "scip/history.h"
    59
    60#define DEFAULT_MEM_VARAFTERDUAL 10
    61#define DEFAULT_MEM_VAR 10
    62#define DEFAULT_MEM_NODES 1000
    63#define DEFAULT_MEM_RUN 200
    64#define DEFAULT_MEM_DUALCONS 10
    65
    66#define DEFAULT_RANDSEED 67
    67
    68/* event handler properties */
    69#define EVENTHDLR_NAME "Reopt"
    70#define EVENTHDLR_DESC "node event handler for reoptimization"
    71
    72/* ---------------- Callback methods of event handler ---------------- */
    73
    74/** exec the event handler */
    75static
    76SCIP_DECL_EVENTEXEC(eventExecReopt)
    77{ /*lint --e{715}*/
    78 SCIP_NODE* eventnode;
    79 SCIP_Real oldbound;
    80 SCIP_Real newbound;
    81
    82 assert(scip != NULL);
    83 assert(eventhdlr != NULL);
    84 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
    85 assert(SCIPvarIsIntegral(SCIPeventGetVar(event)));
    86
    88 return SCIP_OKAY;
    89
    90 eventnode = SCIPgetCurrentNode(scip);
    91 oldbound = SCIPeventGetOldbound(event);
    92 newbound = SCIPeventGetNewbound(event);
    93
    94 /* if we are called from the last node in the tree that is cut off, eventnode will be NULL and we do not have to store the bound changes */
    95 if( eventnode == NULL )
    96 return SCIP_OKAY;
    97
    98 /* skip if the node is not the focus node */
    100 return SCIP_OKAY;
    101
    102 SCIPdebugMsg(scip, "catch event for node %lld: <%s>: %g -> %g\n", SCIPnodeGetNumber(eventnode),
    104
    105 assert(SCIPisFeasLT(scip, newbound, oldbound) || SCIPisFeasGT(scip, newbound, oldbound));
    106
    107 SCIP_CALL( SCIPaddReoptDualBndchg(scip, eventnode, SCIPeventGetVar(event), newbound, oldbound) );
    108
    109 return SCIP_OKAY;
    110}
    111
    112/** solving process initialization method of event handler (called when branch and bound process is about to begin) */
    113static
    114SCIP_DECL_EVENTINITSOL(eventInitsolReopt)
    115{
    116 SCIP_VAR** vars;
    117
    118 assert(scip != NULL);
    119 assert(eventhdlr != NULL);
    120 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
    121
    123 return SCIP_OKAY;
    124
    125 vars = SCIPgetVars(scip);
    126 for( int varnr = 0; varnr < SCIPgetNVars(scip); ++varnr )
    127 {
    128 if( SCIPvarIsIntegral(vars[varnr]) )
    129 {
    130 SCIP_CALL( SCIPcatchVarEvent(scip, vars[varnr], SCIP_EVENTTYPE_GBDCHANGED, eventhdlr, NULL, NULL) );
    131 }
    132 }
    133
    134 return SCIP_OKAY;
    135}
    136
    137/** solving process deinitialization method of event handler (called before branch and bound process data is freed) */
    138static
    139SCIP_DECL_EVENTEXITSOL(eventExitsolReopt)
    140{
    141 SCIP_VAR** vars;
    142
    143 assert(scip != NULL);
    144
    145 assert(eventhdlr != NULL);
    146 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
    147
    149 return SCIP_OKAY;
    150
    151 vars = SCIPgetVars(scip);
    152
    153 for( int varnr = 0; varnr < SCIPgetNVars(scip); ++varnr )
    154 {
    155 if( SCIPvarGetType(vars[varnr]) == SCIP_VARTYPE_BINARY )
    156 {
    157 SCIP_CALL( SCIPdropVarEvent(scip, vars[varnr], SCIP_EVENTTYPE_GBDCHANGED , eventhdlr, NULL, -1) );
    158 }
    159 }
    160 return SCIP_OKAY;
    161}
    162
    163/* ---------------- Callback methods of reoptimization methods ---------------- */
    164
    165/*
    166 * memory growing methods for dynamically allocated arrays
    167 */
    168
    169/** ensures size for activeconss */
    170static
    172 SCIP_REOPT* reopt, /**< reoptimization data structure */
    173 SCIP_SET* set, /**< global SCIP settings */
    174 BMS_BLKMEM* blkmem, /**< block memory */
    175 int num /**< minimum number of entries to store */
    176 )
    177{
    178 if( reopt->nmaxactiveconss < num )
    179 {
    180 int newsize = SCIPsetCalcMemGrowSize(set, num + 1);
    181
    182 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->activeconss, reopt->nmaxactiveconss, newsize) );
    183 reopt->nmaxactiveconss = newsize;
    184 }
    185 assert(num <= reopt->nmaxactiveconss);
    186
    187 return SCIP_OKAY;
    188}
    189
    190/** ensures, that sols[pos] array can store at least num entries */
    191static
    193 SCIP_REOPT* reopt, /**< reoptimization data structure */
    194 SCIP_SET* set, /**< global SCIP settings */
    195 BMS_BLKMEM* blkmem, /**< block memory */
    196 int num, /**< minimum number of entries to store */
    197 int runidx /**< run index for which the memory should checked */
    198 )
    199{
    200 assert(runidx >= 0);
    201 assert(runidx <= reopt->runsize);
    202
    203 if( num > reopt->soltree->solssize[runidx] )
    204 {
    205 int newsize = SCIPsetCalcMemGrowSize(set, num + 1);
    206
    207 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->soltree->sols[runidx],
    208 reopt->soltree->solssize[runidx], newsize) ); /*lint !e866 */
    209
    210 reopt->soltree->solssize[runidx] = newsize;
    211 }
    212 assert(num <= reopt->soltree->solssize[runidx]);
    213
    214 return SCIP_OKAY;
    215}
    216
    217/** ensures, that sols array can store at least num entries */
    218static
    220 SCIP_REOPT* reopt, /**< reoptimization data structure */
    221 SCIP_SET* set, /**< gloabl SCIP settings */
    222 int num, /**< minimum number of entries to store */
    223 BMS_BLKMEM* blkmem /**< block memory */
    224 )
    225{
    226 if( num >= reopt->runsize )
    227 {
    228 int newsize = SCIPsetCalcMemGrowSize(set, num+1);
    229 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->soltree->sols, reopt->runsize, newsize) );
    230 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->soltree->nsols, reopt->runsize, newsize) );
    231 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->soltree->solssize, reopt->runsize, newsize) );
    232 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->prevbestsols, reopt->runsize, newsize) );
    233 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->varhistory, reopt->runsize, newsize) );
    234 SCIP_ALLOC( BMSreallocMemoryArray(&reopt->objs, newsize) );
    235
    236 for( int s = reopt->runsize; s < newsize; ++s )
    237 {
    238 reopt->varhistory[s] = NULL;
    239 reopt->prevbestsols[s] = NULL;
    240 reopt->objs[s] = NULL;
    241 reopt->soltree->solssize[s] = 0;
    242 reopt->soltree->nsols[s] = 0;
    243 reopt->soltree->sols[s] = NULL;
    244 }
    245
    246 reopt->runsize = newsize;
    247 }
    248 assert(num < reopt->runsize);
    249
    250 return SCIP_OKAY;
    251}
    252
    253/** check the memory of the reoptimization tree and if necessary reallocate */
    254static
    256 SCIP_REOPTTREE* reopttree, /**< reoptimization tree */
    257 SCIP_SET* set, /**< global SCIP settings */
    258 BMS_BLKMEM* blkmem /**< block memory */
    259 )
    260{
    261 assert(reopttree != NULL);
    262 assert(blkmem != NULL);
    263
    264 if( SCIPqueueIsEmpty(reopttree->openids) )
    265 {
    266 int newsize;
    267
    268 assert(reopttree->nreoptnodes == (int)(reopttree->reoptnodessize));
    269
    270 newsize = SCIPsetCalcMemGrowSize(set, (int)reopttree->reoptnodessize+1);
    271 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopttree->reoptnodes, reopttree->reoptnodessize, newsize) ); /*lint !e647*/
    272
    273 for( unsigned int id = reopttree->reoptnodessize; id < (unsigned int)newsize; ++id )
    274 {
    275 SCIP_CALL( SCIPqueueInsertUInt(reopttree->openids, id) );
    276 reopttree->reoptnodes[id] = NULL;
    277 }
    278
    279 reopttree->reoptnodessize = (unsigned int)newsize;
    280 }
    281
    282 return SCIP_OKAY;
    283}
    284
    285/** check allocated memory of a node within the reoptimization tree and if necessary reallocate */
    286static
    288 SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
    289 SCIP_SET* set, /**< global SCIP settings */
    290 BMS_BLKMEM* blkmem, /**< block memory */
    291 int var_mem, /**< memory for variables */
    292 int child_mem, /**< memory for child nodes */
    293 int conss_mem /**< memory for constraints */
    294 )
    295{
    296 int newsize;
    297
    298 assert(reoptnode != NULL);
    299 assert(blkmem != NULL);
    300 assert(var_mem >= 0);
    301 assert(child_mem >= 0);
    302 assert(conss_mem >= 0);
    303
    304 /* check allocated memory for variable and bound information */
    305 if( var_mem > 0 )
    306 {
    307 if( reoptnode->varssize == 0 )
    308 {
    309 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptnode->vars, var_mem) );
    310 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptnode->varbounds, var_mem) );
    311 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptnode->varboundtypes, var_mem) );
    312 reoptnode->varssize = var_mem;
    313 }
    314 else if( reoptnode->varssize < var_mem )
    315 {
    316 newsize = SCIPsetCalcMemGrowSize(set, var_mem+1);
    317 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptnode->vars, reoptnode->varssize, newsize) );
    318 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptnode->varbounds, reoptnode->varssize, newsize) );
    319 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptnode->varboundtypes, reoptnode->varssize, newsize) );
    320 reoptnode->varssize = newsize;
    321 }
    322 }
    323
    324 /* check allocated memory for child node information */
    325 if( child_mem > 0 )
    326 {
    327 if( reoptnode->allocchildmem == 0 )
    328 {
    329 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptnode->childids, child_mem) );
    330 reoptnode->nchilds = 0;
    331 reoptnode->allocchildmem = child_mem;
    332 }
    333 else if( reoptnode->allocchildmem < child_mem )
    334 {
    335 newsize = SCIPsetCalcMemGrowSize(set, child_mem+1);
    336 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptnode->childids, reoptnode->allocchildmem, newsize) );
    337 reoptnode->allocchildmem = newsize;
    338 }
    339 }
    340
    341 /* check allocated memory for add constraints */
    342 if( conss_mem > 0 )
    343 {
    344 if( reoptnode->consssize == 0 )
    345 {
    346 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptnode->conss, conss_mem) );
    347 reoptnode->nconss = 0;
    348 reoptnode->consssize = conss_mem;
    349 }
    350 else if( reoptnode->consssize < conss_mem )
    351 {
    352 newsize = SCIPsetCalcMemGrowSize(set, conss_mem);
    353 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptnode->conss, reoptnode->consssize, newsize) );
    354 reoptnode->consssize = newsize;
    355 }
    356 }
    357
    358 return SCIP_OKAY;
    359}
    360
    361/*
    362 * local methods
    363 */
    364
    365/** returns the number of stored solutions in the subtree induced by @p solnode */
    366static
    368 SCIP_SOLNODE* solnode /**< node within the solution tree */
    369 )
    370{
    371 SCIP_SOLNODE* sibling;
    372 int nsols;
    373
    374 assert(solnode != NULL);
    375
    376 if( solnode->child == NULL && solnode->sol == NULL )
    377 return 0;
    378 if( solnode->child == NULL && solnode->sol != NULL )
    379 return 1;
    380
    381 nsols = 0;
    382 sibling = solnode->child;
    383
    384 /* traverse through the list */
    385 while( sibling != NULL )
    386 {
    387 nsols += soltreeNInducedSols(sibling);
    388 sibling = sibling->sibling;
    389 }
    390
    391 return nsols;
    392}
    393
    394/** returns the similarity of the objective functions of two given iterations */
    395static
    397 SCIP_REOPT* reopt, /**< reoptimization data */
    398 SCIP_SET* set, /**< global SCIP settings */
    399 int obj1_id, /**< id of one objective function */
    400 int obj2_id, /**< id of the other objective function */
    401 SCIP_VAR** vars, /**< problem variables */
    402 int nvars /**< number of problem variables */
    403 )
    404{
    405 SCIP_Real similarity;
    406 SCIP_Real norm_obj1;
    407 SCIP_Real norm_obj2;
    408
    409 assert(reopt != NULL);
    410 assert(vars != NULL);
    411 assert(nvars >= 0);
    412
    413 similarity = 0.0;
    414 norm_obj1 = 0.0;
    415 norm_obj2 = 0.0;
    416
    417 /* calculate similarity */
    418 for( int v = 0; v < nvars; ++v )
    419 {
    420 SCIP_VAR* origvar;
    421 SCIP_VAR* transvar;
    422 SCIP_Real c1;
    423 SCIP_Real c2;
    424 SCIP_Real lb;
    425 SCIP_Real ub;
    426
    427 origvar = vars[v];
    428
    429 /* get the original variable */
    430 if( !SCIPvarIsOriginal(origvar) )
    431 {
    432 SCIP_RETCODE retcode;
    433 SCIP_Real constant = 0.0;
    434 SCIP_Real scalar = 1.0;
    435
    436 retcode = SCIPvarGetOrigvarSum(&origvar, &scalar, &constant);
    437
    438 if( retcode != SCIP_OKAY )
    439 return SCIP_INVALID;
    440 }
    441 assert(origvar != NULL && SCIPvarIsOriginal(origvar));
    442
    443 /* get the transformed variable, we skip globally fixed variables */
    444 transvar = SCIPvarGetTransVar(origvar);
    445 assert(transvar != NULL);
    446
    447 lb = SCIPvarGetLbLocal(transvar);
    448 ub = SCIPvarGetUbLocal(transvar);
    449
    450 if( SCIPsetIsFeasLT(set, lb, ub) )
    451 {
    452 int probidx;
    453
    454 probidx = SCIPvarGetIndex(origvar);
    455 assert(0 <= probidx && probidx < reopt->nobjvars);
    456
    457 c1 = reopt->objs[obj1_id][probidx];
    458 c2 = reopt->objs[obj2_id][probidx];
    459
    460 /* vector product */
    461 similarity += c1*c2;
    462 norm_obj1 += SQR(c1);
    463 norm_obj2 += SQR(c2);
    464 }
    465 }
    466
    467 /* divide similarity by norms of the objective vectors */
    468 norm_obj1 = sqrt(norm_obj1);
    469 norm_obj2 = sqrt(norm_obj2);
    470
    471 if( !SCIPsetIsZero(set, norm_obj1) && !SCIPsetIsZero(set, norm_obj2) )
    472 similarity /= (norm_obj1 * norm_obj2);
    473
    474 /* make sure that we are between -1.0 und +1.0 */
    475 similarity = MAX(similarity, -1.0);
    476 similarity = MIN(similarity, 1.0);
    477
    478 return similarity;
    479}
    480
    481/** delete the given reoptimization node */
    482static
    484 SCIP_REOPTNODE** reoptnode, /**< node of the reoptimization tree */
    485 BMS_BLKMEM* blkmem /**< block memory */
    486 )
    487{
    488 assert((*reoptnode) != NULL );
    489 assert(blkmem != NULL );
    490
    491 /* delete data for constraints */
    492 if( (*reoptnode)->consssize > 0 )
    493 {
    494 assert((*reoptnode)->conss != NULL);
    495
    496 for( int c = 0; c < (*reoptnode)->nconss; ++c )
    497 {
    498 assert((*reoptnode)->conss[c] != NULL);
    499 assert((*reoptnode)->conss[c]->vals != NULL);
    500 assert((*reoptnode)->conss[c]->vars != NULL);
    501
    502 BMSfreeBlockMemoryArrayNull(blkmem, &(*reoptnode)->conss[c]->boundtypes, (*reoptnode)->conss[c]->varssize);
    503 BMSfreeBlockMemoryArrayNull(blkmem, &(*reoptnode)->conss[c]->vals, (*reoptnode)->conss[c]->varssize);
    504 BMSfreeBlockMemoryArrayNull(blkmem, &(*reoptnode)->conss[c]->vars, (*reoptnode)->conss[c]->varssize);
    505 BMSfreeBlockMemory(blkmem, &(*reoptnode)->conss[c]); /*lint !e866*/
    506 }
    507 BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->conss, (*reoptnode)->consssize);
    508 (*reoptnode)->nconss = 0;
    509 (*reoptnode)->consssize = 0;
    510 (*reoptnode)->conss = NULL;
    511 }
    512
    513 /* free list of children */
    514 if( (*reoptnode)->childids != NULL )
    515 {
    516 BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->childids, (*reoptnode)->allocchildmem);
    517 (*reoptnode)->nchilds = 0;
    518 (*reoptnode)->allocchildmem = 0;
    519 (*reoptnode)->childids = NULL;
    520 }
    521
    522 /* delete dual constraint */
    523 if( (*reoptnode)->dualredscur != NULL )
    524 {
    525 assert((*reoptnode)->dualredscur->varssize > 0);
    526 BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualredscur->boundtypes, (*reoptnode)->dualredscur->varssize);
    527 BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualredscur->vals, (*reoptnode)->dualredscur->varssize);
    528 BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualredscur->vars, (*reoptnode)->dualredscur->varssize);
    529 BMSfreeBlockMemory(blkmem, &(*reoptnode)->dualredscur);
    530 (*reoptnode)->dualredscur = NULL;
    531 }
    532
    533 /* delete dual constraint */
    534 if( (*reoptnode)->dualredsnex != NULL )
    535 {
    536 assert((*reoptnode)->dualredsnex->varssize > 0);
    537 BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualredsnex->boundtypes, (*reoptnode)->dualredsnex->varssize);
    538 BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualredsnex->vals, (*reoptnode)->dualredsnex->varssize);
    539 BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->dualredsnex->vars, (*reoptnode)->dualredsnex->varssize);
    540 BMSfreeBlockMemory(blkmem, &(*reoptnode)->dualredsnex);
    541 (*reoptnode)->dualredsnex = NULL;
    542 }
    543
    544 /* free boundtypes */
    545 if ((*reoptnode)->varboundtypes != NULL )
    546 {
    547 assert((*reoptnode)->varssize > 0);
    548 BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->varboundtypes, (*reoptnode)->varssize);
    549 (*reoptnode)->varboundtypes = NULL;
    550 }
    551
    552 /* free bounds */
    553 if ((*reoptnode)->varbounds != NULL )
    554 {
    555 assert((*reoptnode)->varssize > 0);
    556 BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->varbounds, (*reoptnode)->varssize);
    557 (*reoptnode)->varbounds = NULL;
    558 }
    559
    560 /* free variables */
    561 if ((*reoptnode)->vars != NULL )
    562 {
    563 assert((*reoptnode)->varssize > 0);
    564 BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->vars, (*reoptnode)->varssize);
    565 (*reoptnode)->vars = NULL;
    566 }
    567
    568 (*reoptnode)->varssize = 0;
    569
    570 /* free afterdual-boundtypes */
    571 if ((*reoptnode)->afterdualvarboundtypes != NULL )
    572 {
    573 assert((*reoptnode)->afterdualvarssize > 0);
    574 BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->afterdualvarboundtypes, (*reoptnode)->afterdualvarssize);
    575 (*reoptnode)->afterdualvarboundtypes = NULL;
    576 }
    577
    578 /* free afterdual-bounds */
    579 if ((*reoptnode)->afterdualvarbounds != NULL )
    580 {
    581 assert((*reoptnode)->afterdualvarssize > 0);
    582 BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->afterdualvarbounds, (*reoptnode)->afterdualvarssize);
    583 (*reoptnode)->afterdualvarbounds = NULL;
    584 }
    585
    586 /* free afterdual-variables */
    587 if ((*reoptnode)->afterdualvars != NULL )
    588 {
    589 assert((*reoptnode)->afterdualvarssize > 0);
    590 BMSfreeBlockMemoryArray(blkmem, &(*reoptnode)->afterdualvars, (*reoptnode)->afterdualvarssize);
    591 (*reoptnode)->afterdualvars = NULL;
    592 }
    593
    594 (*reoptnode)->afterdualvarssize = 0;
    595
    596 BMSfreeBlockMemory(blkmem, reoptnode);
    597 (*reoptnode) = NULL;
    598
    599 return SCIP_OKAY;
    600}
    601
    602/** reset the given reoptimization node */
    603static
    605 SCIP_REOPTNODE* reoptnode, /**< reoptimization node */
    606 SCIP_SET* set, /**< global SCIP settings */
    607 BMS_BLKMEM* blkmem /**< block memory */
    608 )
    609{
    610 assert(reoptnode != NULL);
    611 assert(set != NULL);
    612 assert(blkmem != NULL);
    613
    614 /* remove and delete all constraints */
    615 if( reoptnode->nconss > 0 )
    616 {
    617 assert(reoptnode->conss != NULL);
    618 assert(reoptnode->consssize > 0);
    619
    620 for( int c = 0; c < reoptnode->nconss; ++c )
    621 {
    622 if( !reoptnode->conss[c]->linear )
    623 {
    624 assert(reoptnode->conss[c]->boundtypes != NULL);
    625 BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->boundtypes, reoptnode->conss[c]->varssize);
    626 }
    627 BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vals, reoptnode->conss[c]->varssize);
    628 BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vars, reoptnode->conss[c]->varssize);
    629 BMSfreeBlockMemory(blkmem, &reoptnode->conss[c]); /*lint !e866 */
    630 }
    631 reoptnode->nconss = 0;
    632 }
    633
    634 /* remove all children */
    635 if( reoptnode->childids != NULL )
    636 reoptnode->nchilds = 0;
    637
    638 /* delete dual constraint */
    639 if( reoptnode->dualredscur != NULL )
    640 {
    641 assert(reoptnode->dualredscur->varssize > 0);
    642 if( !reoptnode->dualredscur->linear )
    643 {
    644 assert(reoptnode->dualredscur->boundtypes != NULL);
    645 BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredscur->boundtypes, reoptnode->dualredscur->varssize);
    646 }
    647 BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredscur->vals, reoptnode->dualredscur->varssize);
    648 BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredscur->vars, reoptnode->dualredscur->varssize);
    649 BMSfreeBlockMemory(blkmem, &reoptnode->dualredscur);
    650 reoptnode->dualredscur = NULL;
    651 }
    652
    653 /* delete dual constraint */
    654 if( reoptnode->dualredsnex != NULL )
    655 {
    656 assert(reoptnode->dualredsnex->varssize > 0);
    657 if( !reoptnode->dualredsnex->linear )
    658 {
    659 assert(reoptnode->dualredsnex->boundtypes != NULL);
    660 BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredsnex->boundtypes, reoptnode->dualredsnex->varssize);
    661 }
    662 BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredsnex->vals, reoptnode->dualredsnex->varssize);
    663 BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredsnex->vars, reoptnode->dualredsnex->varssize);
    664 BMSfreeBlockMemory(blkmem, &reoptnode->dualredsnex);
    665 reoptnode->dualredsnex = NULL;
    666 }
    667
    668 reoptnode->parentID = 0;
    669 reoptnode->nvars = 0;
    670 reoptnode->nafterdualvars = 0;
    671 reoptnode->dualreds = FALSE;
    672 reoptnode->reopttype = (unsigned int)SCIP_REOPTTYPE_NONE;
    673 reoptnode->lowerbound = -SCIPsetInfinity(set);
    674
    675 return SCIP_OKAY;
    676}
    677
    678/** delete the node stored at position @p nodeID of the reoptimization tree */
    679static
    681 SCIP_REOPTTREE* reopttree, /**< reoptimization tree */
    682 SCIP_SET* set, /**< global SCIP settings */
    683 BMS_BLKMEM* blkmem, /**< block memory */
    684 unsigned int id, /**< id of a node */
    685 SCIP_Bool softreset /**< delete at the end of the solving process */
    686 )
    687{
    688 assert(reopttree != NULL );
    689 assert(id < reopttree->reoptnodessize);
    690 assert(reopttree->reoptnodes[id] != NULL );
    691
    692 if( softreset )
    693 {
    694 SCIP_CALL( reoptnodeReset(reopttree->reoptnodes[id], set, blkmem) );
    695 }
    696 else
    697 {
    698 SCIP_CALL( reoptnodeDelete(&reopttree->reoptnodes[id], blkmem) );
    699 }
    700
    701 assert(softreset || reopttree->reoptnodes[id] == NULL);
    702 assert(reopttree->reoptnodes[id] == NULL || reopttree->reoptnodes[id]->conss == NULL || reopttree->reoptnodes[id]->nconss == 0);
    703 assert(reopttree->reoptnodes[id] == NULL || reopttree->reoptnodes[id]->childids == NULL || reopttree->reoptnodes[id]->nchilds == 0);
    704
    705 --reopttree->nreoptnodes;
    706
    707 return SCIP_OKAY;
    708}
    709
    710/** constructor of the solution tree */
    711static
    713 SCIP_SOLTREE* soltree, /**< solution tree */
    714 BMS_BLKMEM* blkmem /**< block memory */
    715 )
    716{
    717 assert(soltree != NULL);
    718
    722
    723 for( int s = 0; s < DEFAULT_MEM_RUN; ++s )
    724 {
    725 soltree->nsols[s] = 0;
    726 soltree->solssize[s] = 0;
    727 soltree->sols[s] = NULL;
    728 }
    729
    730 /* allocate the root node */
    731 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &soltree->root) );
    732 soltree->root->sol = NULL;
    733 soltree->root->value = SCIP_INVALID;
    734 soltree->root->updated = FALSE;
    735 soltree->root->father = NULL;
    736 soltree->root->child = NULL;
    737 soltree->root->sibling = NULL;
    738
    739 return SCIP_OKAY;
    740}
    741
    742/** free the given solution node */
    743static
    745 SCIP_REOPT* reopt, /**< reoptimization data */
    746 SCIP_SET* set, /**< global SCIP settings */
    747 SCIP_PRIMAL* primal, /**< the primal */
    748 BMS_BLKMEM* blkmem, /**< block memory */
    749 SCIP_SOLNODE** solnode /**< node within the solution tree */
    750 )
    751{
    752 SCIP_SOLNODE* child;
    753 SCIP_SOLNODE* sibling;
    754
    755 assert(reopt != NULL);
    756 assert(set != NULL);
    757 assert(primal != NULL || set->stage == SCIP_STAGE_INIT);
    758 assert(solnode != NULL);
    759 assert(blkmem != NULL);
    760
    761 child = (*solnode)->child;
    762
    763 /* traverse through the list and free recursive all subtree */
    764 while( child != NULL )
    765 {
    766 SCIP_CALL( soltreefreeNode(reopt, set, primal, blkmem, &child) );
    767 assert(child != NULL);
    768
    769 sibling = child->sibling;
    770 BMSfreeBlockMemoryNull(blkmem, &child);
    771 child = sibling;
    772 }
    773
    774 if( (*solnode)->sol != NULL )
    775 {
    776 assert(set->stage == SCIP_STAGE_PROBLEM);
    777
    778 SCIP_CALL( SCIPsolFree(&(*solnode)->sol, blkmem, primal) );
    779 }
    780
    781 return SCIP_OKAY;
    782}
    783
    784/** free the solution tree */
    785static
    787 SCIP_REOPT* reopt, /**< reoptimization data */
    788 SCIP_SET* set, /**< global SCIP settings */
    789 SCIP_PRIMAL* origprimal, /**< the origprimal */
    790 BMS_BLKMEM* blkmem /**< block memory */
    791 )
    792{
    793 assert(reopt != NULL);
    794 assert(reopt->soltree != NULL);
    795 assert(reopt->soltree->root != NULL);
    796 assert(set != NULL);
    797 assert(blkmem != NULL);
    798
    799 /* free all nodes recursive */
    800 SCIP_CALL( soltreefreeNode(reopt, set, origprimal, blkmem, &reopt->soltree->root) );
    801 BMSfreeBlockMemoryNull(blkmem, &reopt->soltree->root);
    802
    803 BMSfreeBlockMemoryArray(blkmem, &reopt->soltree->sols, reopt->runsize);
    804 BMSfreeBlockMemoryArray(blkmem, &reopt->soltree->nsols, reopt->runsize);
    805 BMSfreeBlockMemoryArray(blkmem, &reopt->soltree->solssize, reopt->runsize);
    806
    807 BMSfreeMemory(&reopt->soltree);
    808
    809 return SCIP_OKAY;
    810}
    811
    812/** creates and adds a solution node to the solution tree */
    813static
    815 SCIP_SET* set, /**< global SCIP settings */
    816 BMS_BLKMEM* blkmem, /**< block memory */
    817 SCIP_SOLNODE* curnode, /**< current node in the solution tree */
    818 SCIP_SOLNODE** child, /**< pointer to store the node representing the solution value */
    819 SCIP_VAR* var, /**< variable represented by this node */
    820 SCIP_Real val, /**< value the child shell represent */
    821 SCIP_Bool* added /**< TRUE iff we created a new node, i.e, we have not seen this solution so far */
    822 )
    823{
    824 SCIP_SOLNODE* solnode;
    825
    826 assert(set != NULL);
    827 assert(blkmem != NULL);
    828 assert(curnode != NULL);
    829 assert(child != NULL && *child == NULL);
    830 assert(!SCIPsetIsInfinity(set, -val) && !SCIPsetIsInfinity(set, val));
    831
    832 /* get the first node of the child node list */
    833 *child = curnode->child;
    834
    835 /* this is the first solution in the subtree induced by the current node */
    836 if( *child == NULL )
    837 {
    838 assert(soltreeNInducedSols(curnode) == 0);
    839
    840 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &solnode) );
    841 solnode->sol = NULL;
    842 solnode->updated = FALSE;
    843 solnode->father = curnode;
    844 solnode->child = NULL;
    845 solnode->sibling = NULL;
    846 solnode->value = val;
    847#ifndef NDEBUG
    848 assert(var != NULL);
    849 solnode->var = var;
    850#endif
    851
    852 *added = TRUE;
    853 *child = solnode;
    854
    855 curnode->child = *child;
    856
    857#ifdef SCIP_MORE_DEBUG
    858 SCIPsetDebugMsg(set, "-> create new node %p: value=%g, sibling=%p\n", (void*) solnode, solnode->value,
    859 (void*) solnode->sibling);
    860#endif
    861 }
    862 else
    863 {
    864 /* we traverse through all children */
    865 while( *child != NULL )
    866 {
    867#ifdef SCIP_MORE_DEBUG
    868 SCIPsetDebugMsg(set, "-> check %p: father=%p, value=%g, sibling=%p\n", (void*) *child, (void*) (*child)->father,
    869 (*child)->value, (void*) (*child)->sibling);
    870#endif
    871 /* we found a node repesenting this solution value */
    872 if( SCIPsetIsEQ(set, val, (*child)->value) )
    873 break;
    874
    875 /* we are at the end of the list */
    876 if( (*child)->sibling == NULL )
    877 {
    878 /* create a new solnode */
    879 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &solnode) );
    880 solnode->sol = NULL;
    881 solnode->updated = FALSE;
    882 solnode->father = curnode;
    883 solnode->child = NULL;
    884 solnode->value = val;
    885#ifndef NDEBUG
    886 assert(var != NULL);
    887 solnode->var = var;
    888#endif
    889 *added = TRUE;
    890
    891 /* we have to append the new node at the end of the list. but we have to check whether the insertion before
    892 * the current node would be correct. in that case, we switch the values, the child pointer, and the
    893 * solution
    894 */
    895 solnode->sibling = NULL;
    896 (*child)->sibling = solnode;
    897
    898#ifdef SCIP_MORE_DEBUG
    899 SCIPsetDebugMsg(set, "-> create new node %p: value=%g, sibling=%p\n", (void*) solnode, solnode->value,
    900 (void*) solnode->sibling);
    901#endif
    902 /* the given value is lower than the current, insertion before the current node would be correct
    903 * in this case we do not have to change the child pointer
    904 */
    905 if( SCIPsetIsLT(set, val, (*child)->value) )
    906 {
    907#ifdef SCIP_MORE_DEBUG
    908 SCIPsetDebugMsg(set, "-> need to switch:\n");
    909 SCIPsetDebugMsg(set, " before switching: node %p witch child=%p, sibling=%p, sol=%p, value=%g\n",
    910 (void*) (*child), (void*) (*child)->child, (void*) (*child)->sibling, (void*) (*child)->sol,
    911 (*child)->value);
    912 SCIPsetDebugMsg(set, " node %p witch child=%p, sibling=%p, sol=%p, value=%g\n",
    913 (void*) solnode, (void*) solnode->child, (void*) solnode->sibling, (void*) solnode->sol,
    914 solnode->value);
    915#endif
    916 /* switch child pointer */
    917 solnode->child = (*child)->child;
    918 (*child)->child = NULL;
    919
    920 /* switch solution values */
    921 solnode->value = (*child)->value;
    922 (*child)->value = val;
    923 assert(SCIPsetIsLT(set, (*child)->value, solnode->value));
    924
    925 /* switch solution pointer */
    926 solnode->sol = (*child)->sol;
    927 (*child)->sol = NULL;
    928#ifdef SCIP_MORE_DEBUG
    929 SCIPsetDebugMsg(set, " after switching: node %p witch child=%p, sibling=%p, sol=%p, value=%g\n",
    930 (void*) (*child), (void*) (*child)->child, (void*) (*child)->sibling, (void*) (*child)->sol,
    931 (*child)->value);
    932 SCIPsetDebugMsg(set, " node %p witch child=%p, sibling=%p, sol=%p, value=%g\n",
    933 (void*) solnode, (void*) solnode->child, (void*) solnode->sibling, (void*) solnode->sol,
    934 solnode->value);
    935#endif
    936 }
    937 /* set the child pointer to the new created solnode */
    938 else
    939 (*child) = solnode;
    940
    941 break;
    942 }
    943
    944 /* the next sibling represents a solution value of larger size.
    945 * we insert a new node between the current child and the next sibling.
    946 */
    947 if( SCIPsetIsLT(set, val, (*child)->sibling->value) )
    948 {
    949 /* create a new solnode that points to the sibling of the current child */
    950 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &solnode) );
    951 solnode->sol = NULL;
    952 solnode->updated = FALSE;
    953 solnode->father = curnode;
    954 solnode->child = NULL;
    955 solnode->sibling = (*child)->sibling;
    956 solnode->value = val;
    957#ifndef NDEBUG
    958 assert(var != NULL);
    959 solnode->var = var;
    960#endif
    961 *added = TRUE;
    962
    963 /* change the poiter of the next sibling to the new node */
    964 (*child)->sibling = solnode;
    965
    966 *child = solnode;
    967#ifdef SCIP_MORE_DEBUG
    968 SCIPsetDebugMsg(set, "-> create new node %p: value=%g, sibling=%p\n", (void*) solnode, solnode->value,
    969 (void*) solnode->sibling);
    970#endif
    971 break;
    972 }
    973
    974 /* go to the next sibling */
    975 *child = (*child)->sibling;
    976 }
    977
    978#ifdef SCIP_DEBUG
    979 /* check whether the insert was correct and the list is increasing */
    980 solnode = curnode->child;
    981 assert(solnode != NULL);
    982
    983 while( solnode->sibling != NULL )
    984 {
    985 assert(SCIPsetIsLT(set, solnode->value, solnode->sibling->value));
    986 solnode = solnode->sibling;
    987 }
    988#endif
    989 }
    990 return SCIP_OKAY;
    991}
    992
    993/** add a solution to the solution tree */
    994static
    996 SCIP_REOPT* reopt, /**< reoptimization data */
    997 SCIP_SET* set, /**< global SCIP settings */
    998 SCIP_STAT* stat, /**< dynamic problem statistics */
    999 SCIP_PRIMAL* origprimal, /**< orig primal */
    1000 BMS_BLKMEM* blkmem, /**< block memory */
    1001 SCIP_VAR** vars, /**< array of original variables */
    1002 SCIP_SOL* sol, /**< solution to add */
    1003 SCIP_SOLNODE** solnode, /**< current solution node */
    1004 int nvars, /**< number of variables */
    1005 SCIP_Bool bestsol, /**< is the solution an optimal (best found) solution */
    1006 SCIP_Bool* added /**< pointer to store the result */
    1007 )
    1008{
    1009 SCIP_SOLNODE* cursolnode;
    1010 SCIP_Bool purelp;
    1011
    1012 assert(reopt != NULL);
    1013 assert(set != NULL);
    1014 assert(stat != NULL);
    1015 assert(origprimal != NULL);
    1016 assert(blkmem != NULL);
    1017 assert(vars != NULL);
    1018 assert(sol != NULL);
    1019 assert(solnode != NULL);
    1020
    1021 cursolnode = reopt->soltree->root;
    1022 *added = FALSE;
    1023 purelp = TRUE;
    1024
    1025 if( set->reopt_savesols > 0 )
    1026 {
    1027#ifdef MORE_DEBUG
    1028 SCIPsetDebugMsg(set, "try to add solution found by <%s>\n", (SCIPsolGetHeur(sol) == NULL ?
    1029 "relaxation" : SCIPheurGetName(SCIPsolGetHeur(sol))));
    1030#endif
    1031
    1032 for( int varid = 0; varid < nvars; ++varid )
    1033 {
    1034 if( SCIPvarIsIntegral(vars[varid]) )
    1035 {
    1036 SCIP_SOLNODE* child;
    1037
    1038 purelp = FALSE;
    1039 child = NULL;
    1040 SCIP_CALL( solnodeAddChild(set, blkmem, cursolnode, &child, vars[varid],
    1041 SCIPsolGetVal(sol, set, stat, vars[varid]), added) );
    1042 assert(child != NULL);
    1043 cursolnode = child;
    1044 }
    1045 }
    1046
    1047 /* the solution was added or is an optimal solution */
    1048 if( (*added || bestsol) && !purelp )
    1049 {
    1050 SCIP_SOL* copysol;
    1051
    1052 assert(cursolnode->child == NULL);
    1053
    1054 if( *added )
    1055 {
    1056 SCIP_CALL( SCIPsolCopy(&copysol, blkmem, set, stat, origprimal, sol) );
    1057 cursolnode->sol = copysol;
    1058 }
    1059 else
    1060 /* this is a pseudo add; we do not want to save this solution more than once, but we will link this solution
    1061 * to the solution storage of this round
    1062 */
    1063 (*added) = TRUE;
    1064
    1065 if( bestsol )
    1066 {
    1067 assert(reopt->prevbestsols != NULL);
    1068 assert(cursolnode->sol != NULL);
    1069
    1070 reopt->prevbestsols[reopt->run-1] = cursolnode->sol;
    1071 }
    1072
    1073 (*solnode) = cursolnode;
    1074 }
    1075 }
    1076
    1077 return SCIP_OKAY;
    1078}
    1079
    1080/** reset all marks 'updated' to FALSE */
    1081static
    1083 SCIP_SOLNODE* node /**< node within the solution tree */
    1084 )
    1085{
    1086 assert(node != NULL);
    1087
    1088 if( node->child != NULL )
    1089 {
    1090 SCIP_SOLNODE* child;
    1091
    1092 /* the node is no leaf */
    1093 assert(node->sol == NULL);
    1094 assert(!node->updated);
    1095
    1096 child = node->child;
    1097
    1098 /* traverse through the list of siblings */
    1099 while( child != NULL )
    1100 {
    1101 soltreeResetMarks(child);
    1102 child = child->sibling;
    1103 }
    1104 }
    1105 else
    1106 {
    1107 /* the node is a leaf */
    1108 assert(node->father != NULL);
    1109 assert(node->sol != NULL);
    1110 node->updated = FALSE;
    1111 }
    1112}
    1113
    1114/** allocate memory for a node within the reoptimization tree */
    1115static
    1117 SCIP_REOPTTREE* reopttree, /**< reoptimization tree */
    1118 SCIP_SET* set, /**< global SCIP settings */
    1119 BMS_BLKMEM* blkmem, /**< block memory */
    1120 unsigned int id /**< id of the node to create */
    1121 )
    1122{
    1123 assert(reopttree != NULL );
    1124 assert(id < reopttree->reoptnodessize);
    1125
    1126 SCIPsetDebugMsg(set, "create a reoptnode at ID %u\n", id);
    1127
    1128 if( reopttree->reoptnodes[id] == NULL )
    1129 {
    1130 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopttree->reoptnodes[id]) ); /*lint !e866*/
    1131
    1132 reopttree->reoptnodes[id]->conss = NULL;
    1133 reopttree->reoptnodes[id]->nconss = 0;
    1134 reopttree->reoptnodes[id]->consssize = 0;
    1135 reopttree->reoptnodes[id]->childids = NULL;
    1136 reopttree->reoptnodes[id]->allocchildmem = 0;
    1137 reopttree->reoptnodes[id]->nchilds = 0;
    1138 reopttree->reoptnodes[id]->nvars = 0;
    1139 reopttree->reoptnodes[id]->nafterdualvars = 0;
    1140 reopttree->reoptnodes[id]->parentID = 0;
    1141 reopttree->reoptnodes[id]->dualreds = FALSE;
    1142 reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_NONE;
    1143 reopttree->reoptnodes[id]->varssize = 0;
    1144 reopttree->reoptnodes[id]->afterdualvarssize = 0;
    1145 reopttree->reoptnodes[id]->vars = NULL;
    1146 reopttree->reoptnodes[id]->varbounds = NULL;
    1147 reopttree->reoptnodes[id]->varboundtypes = NULL;
    1148 reopttree->reoptnodes[id]->afterdualvars = NULL;
    1149 reopttree->reoptnodes[id]->afterdualvarbounds = NULL;
    1150 reopttree->reoptnodes[id]->afterdualvarboundtypes = NULL;
    1151 reopttree->reoptnodes[id]->dualredscur = NULL;
    1152 reopttree->reoptnodes[id]->dualredsnex = NULL;
    1153 reopttree->reoptnodes[id]->lowerbound = -SCIPsetInfinity(set);
    1154 }
    1155 else
    1156 {
    1157 assert(reopttree->reoptnodes[id]->nvars == 0);
    1158 assert(reopttree->reoptnodes[id]->nafterdualvars == 0);
    1159 reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_NONE;
    1160 reopttree->reoptnodes[id]->lowerbound = -SCIPsetInfinity(set);
    1161 }
    1162
    1163 /* increase the counter */
    1164 ++reopttree->nreoptnodes;
    1165
    1166 assert(reopttree->nreoptnodes + SCIPqueueNElems(reopttree->openids) == (int)reopttree->reoptnodessize);
    1167
    1168 return SCIP_OKAY;
    1169}
    1170
    1171/** constructor of the reoptimization tree */
    1172static
    1174 SCIP_REOPTTREE* reopttree, /**< pointer to the reoptimization tree */
    1175 SCIP_SET* set, /**< global SCIP settings */
    1176 BMS_BLKMEM* blkmem /**< block memory */
    1177 )
    1178{
    1179 assert(reopttree != NULL);
    1180 assert(set != NULL);
    1181 assert(blkmem != NULL);
    1182
    1183 /* allocate memory */
    1184 reopttree->reoptnodessize = DEFAULT_MEM_NODES;
    1185 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopttree->reoptnodes, reopttree->reoptnodessize) );
    1186
    1187 /* initialize the queue of open IDs */
    1188 SCIP_CALL( SCIPqueueCreate(&reopttree->openids, (int)reopttree->reoptnodessize, 2.0) );
    1189
    1190 /* fill the queue, but reserve the 0 for the root */
    1191 for( unsigned int id = 1; id < reopttree->reoptnodessize; ++id )
    1192 {
    1193 reopttree->reoptnodes[id] = NULL;
    1194 SCIP_CALL( SCIPqueueInsertUInt(reopttree->openids, id) );
    1195 }
    1196 assert(SCIPqueueNElems(reopttree->openids) == (int)(reopttree->reoptnodessize)-1);
    1197
    1198 reopttree->nreoptnodes = 0;
    1199 reopttree->ntotalfeasnodes = 0;
    1200 reopttree->nfeasnodes = 0;
    1201 reopttree->ninfnodes = 0;
    1202 reopttree->ntotalinfnodes= 0;
    1203 reopttree->nprunednodes = 0;
    1204 reopttree->ntotalprunednodes= 0;
    1205 reopttree->ncutoffreoptnodes = 0;
    1206 reopttree->ntotalcutoffreoptnodes = 0;
    1207
    1208 /* initialize the root node */
    1209 reopttree->reoptnodes[0] = NULL;
    1210 SCIP_CALL( createReoptnode(reopttree, set, blkmem, 0) );
    1211
    1212 return SCIP_OKAY;
    1213}
    1214
    1215/** clears the reopttree, e.g., to restart and solve the next problem from scratch */
    1216static
    1218 SCIP_REOPTTREE* reopttree, /**< reoptimization tree */
    1219 SCIP_SET* set, /**< global SCIP settings */
    1220 BMS_BLKMEM* blkmem, /**< block memory */
    1221 SCIP_Bool softreset /**< delete nodes before exit the solving process */
    1222 )
    1223{
    1224 assert(reopttree != NULL );
    1225
    1226 /* clear queue with open IDs */
    1227 SCIPqueueClear(reopttree->openids);
    1228 assert(SCIPqueueNElems(reopttree->openids) == 0);
    1229
    1230 /* delete all data about nodes */
    1231 for( unsigned int id = 0; id < reopttree->reoptnodessize; ++id )
    1232 {
    1233 if( reopttree->reoptnodes[id] != NULL )
    1234 {
    1235 SCIP_CALL( reopttreeDeleteNode(reopttree, set, blkmem, id, softreset) );
    1236 assert(reopttree->reoptnodes[id] == NULL || reopttree->reoptnodes[id]->nvars == 0);
    1237 }
    1238
    1239 if( id > 0 )
    1240 {
    1241 SCIP_CALL( SCIPqueueInsertUInt(reopttree->openids, id) );
    1242 }
    1243 }
    1244 assert(SCIPqueueNElems(reopttree->openids) == (int)(reopttree->reoptnodessize)-1);
    1245
    1246 reopttree->nreoptnodes = 0;
    1247
    1248 return SCIP_OKAY;
    1249}
    1250
    1251/** free the reoptimization tree */
    1252static
    1254 SCIP_REOPTTREE* reopttree, /**< reoptimization tree data */
    1255 SCIP_SET* set, /**< global SCIP settings */
    1256 BMS_BLKMEM* blkmem /**< block memory */
    1257 )
    1258{
    1259 assert(reopttree != NULL);
    1260 assert(blkmem != NULL);
    1261
    1262 /* free nodes */
    1263 SCIP_CALL( clearReoptnodes(reopttree, set, blkmem, FALSE) );
    1264
    1265 /* free the data */
    1266 BMSfreeBlockMemoryArray(blkmem, &reopttree->reoptnodes, reopttree->reoptnodessize);
    1267 SCIPqueueFree(&reopttree->openids);
    1268
    1269 /* free the tree itself */
    1270 BMSfreeMemory(&reopttree);
    1271
    1272 return SCIP_OKAY;
    1273}
    1274
    1275/** check memory for the constraint to handle bound changes based on dual information */
    1276static
    1278 SCIP_REOPT* reopt, /**< reoptimization data structure */
    1279 SCIP_SET* set, /**< global SCIP settings */
    1280 BMS_BLKMEM* blkmem, /**< block memory */
    1281 int size /**< size which need to be allocated */
    1282 )
    1283{
    1284 assert(reopt != NULL);
    1285 assert(blkmem != NULL);
    1286 assert(size > 0);
    1287
    1288 if( reopt->dualreds == NULL )
    1289 {
    1290 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopt->dualreds) );
    1291 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->dualreds->vars, size) );
    1292 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->dualreds->vals, size) );
    1293 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->dualreds->boundtypes, size) );
    1294 reopt->dualreds->varssize = size;
    1295 reopt->dualreds->nvars = 0;
    1296 }
    1297 else if( reopt->dualreds->varssize < size )
    1298 {
    1299 int newsize = SCIPsetCalcMemGrowSize(set, size+1);
    1300 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->dualreds->vars, reopt->dualreds->varssize, newsize) );
    1301 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->dualreds->vals, reopt->dualreds->varssize, newsize) );
    1302 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->dualreds->boundtypes, reopt->dualreds->varssize, newsize) );
    1303 reopt->dualreds->varssize = newsize;
    1304 }
    1305
    1306 return SCIP_OKAY;
    1307}
    1308
    1309/** check the memory to store global constraints */
    1310static
    1312 SCIP_REOPT* reopt, /**< reoptimization data structure */
    1313 SCIP_SET* set, /**< global SCIP settings */
    1314 BMS_BLKMEM* blkmem, /**< block memory */
    1315 int mem /**< memory which has to be allocated */
    1316 )
    1317{
    1318 assert(reopt != NULL);
    1319 assert(blkmem != NULL);
    1320 assert(mem > 0);
    1321
    1322 if( mem > 0 ) /*lint !e774*/
    1323 {
    1324 if( reopt->glbconss == NULL )
    1325 {
    1326 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->glbconss, mem) );
    1327 reopt->nglbconss = 0;
    1328 reopt->allocmemglbconss = mem;
    1329
    1330 for( int c = 0; c < reopt->allocmemglbconss; ++c )
    1331 reopt->glbconss[c] = NULL;
    1332 }
    1333 else if( reopt->allocmemglbconss < mem )
    1334 {
    1335 int newsize = SCIPsetCalcMemGrowSize(set, mem+1);
    1336
    1337 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->glbconss, reopt->allocmemglbconss, newsize) );
    1338
    1339 for( int c = reopt->allocmemglbconss; c < newsize; ++c )
    1340 reopt->glbconss[c] = NULL;
    1341
    1342 reopt->allocmemglbconss = newsize;
    1343 }
    1344 }
    1345
    1346 return SCIP_OKAY;
    1347}
    1348
    1349/** reactivate globally valid constraints that were deactivated and necessary to ensure correctness */
    1350static
    1352 SCIP_REOPT* reopt, /**< reoptimization data structure */
    1353 SCIP_SET* set, /**< global SCIP settings */
    1354 BMS_BLKMEM* blkmem /**< block memory */
    1355 )
    1356{
    1357 assert(reopt != NULL);
    1358
    1359 /* exit if there are no active constraints */
    1360 if( reopt->nactiveconss == 0 )
    1361 return SCIP_OKAY;
    1362
    1363 SCIPsetDebugMsg(set, "Cleaning %d active conss.\n", reopt->nactiveconss);
    1364 assert(reopt->activeconss != NULL);
    1365 assert(reopt->activeconssset != NULL);
    1366 assert(reopt->nactiveconss <= reopt->nmaxactiveconss);
    1367
    1368 /* loop over all stored constraints and reactivate deactivated constraints */
    1369 for( int i = 0; i < reopt->nactiveconss; ++i )
    1370 {
    1371 assert(reopt->activeconss[i] != NULL);
    1372 assert(SCIPhashsetExists(reopt->activeconssset, reopt->activeconss[i]));
    1373 SCIP_CALL( SCIPconsRelease(&reopt->activeconss[i], blkmem, set) );
    1374 }
    1375
    1376 /* also clean up hashset */
    1378 reopt->nactiveconss = 0;
    1379
    1380 return SCIP_OKAY;
    1381}
    1382
    1383/** update the bound changes made by propagations during current iteration; stop saving the bound changes if
    1384 * we reach a branching decision based on a dual information
    1385 */
    1386static
    1388 SCIP_REOPT* reopt, /**< reoptimization data structure */
    1389 SCIP_SET* set, /**< global SCIP settings */
    1390 BMS_BLKMEM* blkmem, /**< block memory */
    1391 SCIP_NODE* node, /**< node of the search tree */
    1392 unsigned int id, /**< id of the node */
    1393 SCIP_Bool* transintoorig /**< transform variables into originals */
    1394 )
    1395{
    1396 int nvars;
    1397 int nconsprops;
    1398 int npropprops;
    1399 int naddedbndchgs;
    1400
    1401 assert(reopt != NULL);
    1402 assert(blkmem != NULL);
    1403 assert(node != NULL);
    1404 assert(0 < id && id < reopt->reopttree->reoptnodessize);
    1405 assert(reopt->reopttree->reoptnodes[id] != NULL );
    1406
    1407 /* get the number of all stored constraint and propagator propagations */
    1408 SCIPnodeGetNDomchg(node, NULL, &nconsprops, &npropprops);
    1409 nvars = reopt->reopttree->reoptnodes[id]->nvars;
    1410
    1411 if( nconsprops > 0 || npropprops > 0 )
    1412 {
    1413 /* check the memory */
    1414 SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[id], set, blkmem, nvars + nconsprops + npropprops, 0, 0) );
    1415
    1417 &reopt->reopttree->reoptnodes[id]->vars[nvars],
    1418 &reopt->reopttree->reoptnodes[id]->varbounds[nvars],
    1419 &reopt->reopttree->reoptnodes[id]->varboundtypes[nvars],
    1420 &naddedbndchgs,
    1421 reopt->reopttree->reoptnodes[id]->varssize-nvars);
    1422
    1423 assert(nvars + naddedbndchgs <= reopt->reopttree->reoptnodes[id]->varssize);
    1424
    1425 reopt->reopttree->reoptnodes[id]->nvars += naddedbndchgs;
    1426
    1427 *transintoorig = TRUE;
    1428 }
    1429
    1430 return SCIP_OKAY;
    1431}
    1432
    1433/** save bound changes made after the first bound change based on dual information, e.g., mode by strong branching
    1434 *
    1435 * This method can be used during reoptimization. If we want to reconstruct a node containing dual bound changes we
    1436 * have to split the node into the original one and at least one node representing the pruned part. All bound changes,
    1437 * i.e., (constraint) propagation, made after the first bound change based on dual information are still valid for
    1438 * the original node after changing the objective function. thus, we can store them for the following iterations.
    1439 *
    1440 * It should be noted, that these bound changes will be found by (constraint) propagation methods anyway after changing
    1441 * the objective function. do not saving these information and find them again might be useful for conflict analysis.
    1442 */
    1443static
    1445 SCIP_REOPT* reopt, /**< reoptimization data structure */
    1446 SCIP_SET* set, /**< global SCIP settings */
    1447 BMS_BLKMEM* blkmem, /**< block memory */
    1448 SCIP_NODE* node, /**< node of the search tree */
    1449 unsigned int id, /**< id of the node */
    1450 SCIP_Bool* transintoorig /**< transform variables into originals */
    1451 )
    1452{
    1453 int nbranchvars;
    1454
    1455 assert(reopt != NULL);
    1456 assert(blkmem != NULL);
    1457 assert(node != NULL);
    1458 assert(0 < id && id < reopt->reopttree->reoptnodessize);
    1459 assert(reopt->reopttree->reoptnodes[id] != NULL );
    1460
    1461 nbranchvars = 0;
    1462
    1463 /* allocate memory */
    1464 if (reopt->reopttree->reoptnodes[id]->afterdualvarssize == 0)
    1465 {
    1466 assert(reopt->reopttree->reoptnodes[id]->afterdualvars == NULL );
    1467 assert(reopt->reopttree->reoptnodes[id]->afterdualvarbounds == NULL );
    1468 assert(reopt->reopttree->reoptnodes[id]->afterdualvarboundtypes == NULL );
    1469
    1470 /* allocate block memory for node information */
    1473 reopt->reopttree->reoptnodes[id]->afterdualvarssize) );
    1475 reopt->reopttree->reoptnodes[id]->afterdualvarssize) );
    1477 reopt->reopttree->reoptnodes[id]->afterdualvarssize) );
    1478 }
    1479
    1480 assert(reopt->reopttree->reoptnodes[id]->afterdualvarssize > 0);
    1481 assert(reopt->reopttree->reoptnodes[id]->nafterdualvars >= 0);
    1482
    1487 &nbranchvars,
    1489
    1490 if( nbranchvars > reopt->reopttree->reoptnodes[id]->afterdualvarssize - reopt->reopttree->reoptnodes[id]->nafterdualvars )
    1491 {
    1492 int newsize = SCIPsetCalcMemGrowSize(set, reopt->reopttree->reoptnodes[id]->nafterdualvars + nbranchvars);
    1494 reopt->reopttree->reoptnodes[id]->afterdualvarssize, newsize) );
    1496 reopt->reopttree->reoptnodes[id]->afterdualvarssize, newsize) );
    1498 reopt->reopttree->reoptnodes[id]->afterdualvarssize, newsize) );
    1499 reopt->reopttree->reoptnodes[id]->afterdualvarssize = newsize;
    1500
    1505 &nbranchvars,
    1507 }
    1508
    1509 /* the stored variables of this node need to be transformed into the original space */
    1510 if( nbranchvars > 0 )
    1511 *transintoorig = TRUE;
    1512
    1513 SCIPsetDebugMsg(set, " -> save %d bound changes after dual reductions\n", nbranchvars);
    1514
    1515 assert(reopt->reopttree->reoptnodes[id]->nafterdualvars + nbranchvars <= reopt->reopttree->reoptnodes[id]->afterdualvarssize); /* this should be the case */
    1516
    1517 reopt->reopttree->reoptnodes[id]->nafterdualvars += nbranchvars;
    1518
    1519 return SCIP_OKAY;
    1520}
    1521
    1522/** store cuts that are active in the current LP */
    1523static
    1525 SCIP_REOPT* reopt, /**< reoptimization data structure */
    1526 SCIP_SET* set, /**< global SCIP settings */
    1527 BMS_BLKMEM* blkmem, /**< block memory */
    1528 SCIP_LP* lp, /**< current LP */
    1529 unsigned int id /**< id in the reopttree */
    1530 )
    1531{
    1532 SCIP_ROW** lprows;
    1533 int nlprows;
    1534
    1535 assert(reopt != NULL);
    1536 assert(set != NULL);
    1537 assert(lp != NULL);
    1538 assert(blkmem != NULL);
    1539
    1540 lprows = SCIPlpGetRows(lp);
    1541 nlprows = SCIPlpGetNRows(lp);
    1542
    1543 for( int r = 0; r < nlprows; ++r )
    1544 {
    1545 /* we can break if we reach the first row that is not part of the current LP */
    1546 if( SCIProwGetLPPos(lprows[r]) == -1 )
    1547 break;
    1548
    1549 /* currently we only want to store cuts generated by a seperator */
    1550 if( SCIProwGetOrigintype(lprows[r]) == SCIP_ROWORIGINTYPE_SEPA && SCIProwGetAge(lprows[r]) <= set->reopt_maxcutage )
    1551 {
    1552 SCIP_VAR** cutvars;
    1553 SCIP_COL** cols;
    1554 SCIP_Real* cutvals;
    1555 SCIP_Real lhs;
    1556 SCIP_Real rhs;
    1557 int ncutvars;
    1558 SCIP_Bool storecut;
    1559
    1560 ncutvars = SCIProwGetNLPNonz(lprows[r]);
    1561 lhs = SCIProwGetLhs(lprows[r]);
    1562 rhs = SCIProwGetRhs(lprows[r]);
    1563
    1564 /* subtract row constant */
    1565 if( !SCIPsetIsInfinity(set, -lhs) )
    1566 lhs -= SCIProwGetConstant(lprows[r]);
    1567 if( !SCIPsetIsInfinity(set, rhs) )
    1568 rhs -= SCIProwGetConstant(lprows[r]);
    1569
    1570 cutvals = SCIProwGetVals(lprows[r]);
    1571 cols = SCIProwGetCols(lprows[r]);
    1572 storecut = TRUE;
    1573
    1574 SCIP_CALL( SCIPsetAllocBufferArray(set, &cutvars, ncutvars) );
    1575
    1576 for( int c = 0; c < ncutvars; ++c )
    1577 {
    1578 SCIP_Real constant;
    1579 SCIP_Real scalar;
    1580
    1581 cutvars[c] = SCIPcolGetVar(cols[c]);
    1582 assert(cutvars[c] != NULL);
    1583
    1584 constant = 0.0;
    1585 scalar = 1.0;
    1586
    1587 SCIP_CALL( SCIPvarGetOrigvarSum(&cutvars[c], &scalar, &constant) );
    1588
    1589 /* the cut contains an artificial variable that might not be present after modifying the problem */
    1590 if( cutvars[c] != NULL )
    1591 {
    1592 storecut = FALSE;
    1593 break;
    1594 }
    1595
    1596 assert(cutvars[c] != NULL);
    1597 assert(!SCIPsetIsZero(set, scalar));
    1598
    1599 /* subtract constant from sides */
    1600 if( !SCIPsetIsZero(set, constant) && !SCIPsetIsInfinity(set, -lhs) )
    1601 lhs -= constant;
    1602 if( !SCIPsetIsZero(set, constant) && !SCIPsetIsInfinity(set, rhs) )
    1603 rhs -= constant;
    1604
    1605 cutvals[c] = cutvals[c]/scalar;
    1606 }
    1607
    1608 if( storecut )
    1609 {
    1610 /* add cut as a linear constraint */
    1611 SCIP_CALL( SCIPreoptnodeAddCons(reopt->reopttree->reoptnodes[id], set, blkmem, cutvars, cutvals, NULL,
    1612 lhs, rhs, ncutvars, REOPT_CONSTYPE_CUT, TRUE) );
    1613 }
    1614
    1615 SCIPsetFreeBufferArray(set, &cutvars);
    1616 }
    1617 }
    1618
    1619 return SCIP_OKAY;
    1620}
    1621
    1622/** transform variable and bounds back to the original space */
    1623static
    1625 SCIP_REOPT* reopt, /**< reoptimization data structure */
    1626 unsigned int id /**< id of the node */
    1627 )
    1628{
    1629 assert(reopt != NULL );
    1630 assert(0 < id && id < reopt->reopttree->reoptnodessize);
    1631 assert(reopt->reopttree->reoptnodes[id] != NULL );
    1632
    1633 /* transform branching variables and bound changes applied before the first dual reduction */
    1634 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; ++varnr )
    1635 {
    1636 SCIP_Real constant = 0.0;
    1637 SCIP_Real scalar = 1.0;
    1638
    1639 if( !SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->vars[varnr]) )
    1640 {
    1641 SCIP_CALL( SCIPvarGetOrigvarSum(&reopt->reopttree->reoptnodes[id]->vars[varnr], &scalar, &constant)) ;
    1642 reopt->reopttree->reoptnodes[id]->varbounds[varnr] = (reopt->reopttree->reoptnodes[id]->varbounds[varnr] - constant) / scalar;
    1643 }
    1644 assert(SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->vars[varnr]));
    1645 }
    1646
    1647 /* transform bound changes affected by dual reduction */
    1648 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nafterdualvars; ++varnr )
    1649 {
    1650 SCIP_Real constant = 0.0;
    1651 SCIP_Real scalar = 1.0;
    1652
    1653 if( !SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]) )
    1654 {
    1655 SCIP_CALL( SCIPvarGetOrigvarSum(&reopt->reopttree->reoptnodes[id]->afterdualvars[varnr], &scalar, &constant)) ;
    1656 reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr]
    1657 = (reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr] - constant) / scalar;
    1658 }
    1659 assert(SCIPvarIsOriginal(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]));
    1660 }
    1661
    1662 return SCIP_OKAY;
    1663}
    1664
    1665/** search the next node along the root path that was saved by reoptimization */
    1666static
    1668 SCIP_REOPT* reopt, /**< reoptimization data structure */
    1669 SCIP_SET* set, /**< global SCIP settings */
    1670 SCIP_NODE* node, /**< node of the search tree */
    1671 SCIP_NODE** parent, /**< parent node within the search tree */
    1672 unsigned int* parentid, /**< id of the parent node */
    1673 int* nbndchgs /**< number of bound changes */
    1674 )
    1675{
    1676 assert(reopt != NULL);
    1677 assert(reopt->reopttree != NULL);
    1678 assert(reopt->reopttree->reoptnodes != NULL);
    1679
    1680 (*nbndchgs) = 0;
    1681 (*parent) = node;
    1682
    1683 /* look for a saved parent along the root-path */
    1684 while( SCIPnodeGetDepth(*parent) != 0 )
    1685 {
    1686 int nbranchings = 0;
    1687 int nconsprop = 0;
    1688 int npropprops = 0;
    1689
    1690 if( set->reopt_saveprop )
    1691 SCIPnodeGetNDomchg((*parent), &nbranchings, &nconsprop, &npropprops);
    1692 else
    1693 SCIPnodeGetNDomchg((*parent), &nbranchings, NULL, NULL);
    1694
    1695 (*nbndchgs) = (*nbndchgs) + nbranchings + nconsprop + npropprops;
    1696 (*parent) = SCIPnodeGetParent(*parent);
    1697 (*parentid) = SCIPnodeGetReoptID(*parent);
    1698
    1699 if( SCIPnodeGetDepth(*parent) == 0)
    1700 {
    1701 (*parentid) = 0;
    1702 break;
    1703 }
    1704 else if( SCIPnodeGetReopttype((*parent)) >= SCIP_REOPTTYPE_TRANSIT )
    1705 {
    1706 /* this is a special case: due to re-propagation the node could be already deleted. We need to reset reoptid
    1707 * and reopttype and continue upto we have found the last stored node
    1708 */
    1709 if( reopt->reopttree->reoptnodes[*parentid] == NULL )
    1710 {
    1711 SCIPnodeSetReoptID(*parent, 0);
    1713 }
    1714 else
    1715 {
    1716 assert(reopt->reopttree->reoptnodes[*parentid] != NULL);
    1717 assert(SCIPnodeGetReoptID((*parent)) < reopt->reopttree->reoptnodessize);
    1718 assert((*parentid) && (*parentid) < reopt->reopttree->reoptnodessize);
    1719 break;
    1720 }
    1721 }
    1722 }
    1723
    1724 return SCIP_OKAY;
    1725}
    1726
    1727/** adds the id @p childid to the array of child nodes of @p parentid */
    1728static
    1730 SCIP_REOPTTREE* reopttree, /**< reoptimization tree */
    1731 SCIP_SET* set, /**< global SCIP settings */
    1732 BMS_BLKMEM* blkmem, /**< block memory */
    1733 unsigned int parentid, /**< id of the parent node */
    1734 unsigned int childid /**< id of the child node */
    1735 )
    1736{
    1737 int nchilds;
    1738
    1739 assert(reopttree != NULL);
    1740 assert(blkmem != NULL);
    1741 assert(parentid < (unsigned int)reopttree->reoptnodessize);
    1742 assert(childid < (unsigned int)reopttree->reoptnodessize);
    1743 assert(reopttree->reoptnodes[parentid] != NULL);
    1744
    1745 nchilds = reopttree->reoptnodes[parentid]->nchilds;
    1746
    1747 /* ensure that the array is large enough */
    1748 SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[parentid], set, blkmem, 0, nchilds+1, 0) );
    1749 assert(reopttree->reoptnodes[parentid]->allocchildmem > nchilds);
    1750
    1751 /* add the child */
    1752 reopttree->reoptnodes[parentid]->childids[nchilds] = childid;
    1753 ++reopttree->reoptnodes[parentid]->nchilds;
    1754
    1755 SCIPsetDebugMsg(set, "add ID %u as a child of ID %u.\n", childid, parentid);
    1756
    1757 return SCIP_OKAY;
    1758}
    1759
    1760/** move all children to the next node (along the root path) stored in the reoptimization tree */
    1761static
    1763 SCIP_REOPT* reopt, /**< reoptimization data structure */
    1764 SCIP_SET* set, /**< global SCIP settings */
    1765 BMS_BLKMEM* blkmem, /**< block memory */
    1766 unsigned int nodeid, /**< id of the node */
    1767 unsigned int parentid /**< id of the parent node */
    1768 )
    1769{
    1770 unsigned int childid;
    1771 int nvars;
    1772
    1773 assert(reopt != NULL);
    1774 assert(blkmem != NULL);
    1775 assert(0 < nodeid && nodeid < reopt->reopttree->reoptnodessize);
    1776 assert(parentid < reopt->reopttree->reoptnodessize);
    1777 assert(reopt->reopttree->reoptnodes[nodeid]->childids != NULL);
    1778
    1779 /* ensure that enough memory at the parentID is available */
    1780 SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[parentid], set, blkmem, 0,
    1781 reopt->reopttree->reoptnodes[parentid]->nchilds + reopt->reopttree->reoptnodes[nodeid]->nchilds, 0) );
    1782
    1783 while( reopt->reopttree->reoptnodes[nodeid]->nchilds > 0 )
    1784 {
    1785 int nchilds;
    1786
    1787 nchilds = reopt->reopttree->reoptnodes[nodeid]->nchilds;
    1788 childid = reopt->reopttree->reoptnodes[nodeid]->childids[nchilds-1];
    1789 assert(0 < childid && childid < reopt->reopttree->reoptnodessize);
    1790
    1791 /* check the memory */
    1792 SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[childid], set, blkmem,
    1793 reopt->reopttree->reoptnodes[childid]->nvars + reopt->reopttree->reoptnodes[nodeid]->nvars, 0, 0) );
    1794 assert(reopt->reopttree->reoptnodes[childid]->varssize >= reopt->reopttree->reoptnodes[childid]->nvars
    1795 + reopt->reopttree->reoptnodes[nodeid]->nvars);
    1796
    1797 /* save branching information */
    1798 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[nodeid]->nvars; ++varnr )
    1799 {
    1800 nvars = reopt->reopttree->reoptnodes[childid]->nvars;
    1801 reopt->reopttree->reoptnodes[childid]->vars[nvars] = reopt->reopttree->reoptnodes[nodeid]->vars[varnr];
    1802 reopt->reopttree->reoptnodes[childid]->varbounds[nvars] = reopt->reopttree->reoptnodes[nodeid]->varbounds[varnr];
    1803 reopt->reopttree->reoptnodes[childid]->varboundtypes[nvars] = reopt->reopttree->reoptnodes[nodeid]->varboundtypes[varnr];
    1804 ++reopt->reopttree->reoptnodes[childid]->nvars;
    1805 }
    1806
    1807 /* update the ID of the parent node */
    1808 reopt->reopttree->reoptnodes[childid]->parentID = parentid;
    1809
    1810 /* insert the node as a child */
    1811 SCIP_CALL( reoptAddChild(reopt->reopttree, set, blkmem, parentid, childid) );
    1812
    1813 /* reduce the number of child nodes by 1 */
    1814 --reopt->reopttree->reoptnodes[nodeid]->nchilds;
    1815 }
    1816
    1817 return SCIP_OKAY;
    1818}
    1819
    1820/** delete all nodes in the subtree induced by nodeID */
    1821static
    1823 SCIP_REOPTTREE* reopttree, /**< reoptimization tree */
    1824 SCIP_SET* set, /**< global SCIP settings */
    1825 BMS_BLKMEM* blkmem, /**< block memory */
    1826 unsigned int id, /**< id of the node */
    1827 SCIP_Bool delnodeitself, /**< should the node be deleted after deleting the induced subtree? */
    1828 SCIP_Bool exitsolve /**< will the solving process end after deletion */
    1829 )
    1830{
    1831 assert(reopttree != NULL );
    1832 assert(blkmem != NULL);
    1833 assert(id < reopttree->reoptnodessize);
    1834 assert(reopttree->reoptnodes[id] != NULL);
    1835
    1836 /* delete all children below */
    1837 if( reopttree->reoptnodes[id]->childids != NULL && reopttree->reoptnodes[id]->nchilds > 0 )
    1838 {
    1839 SCIPsetDebugMsg(set, "-> delete subtree induced by ID %u (hard remove = %u)\n", id, exitsolve);
    1840
    1841 while( reopttree->reoptnodes[id]->nchilds > 0 )
    1842 {
    1843 int nchilds;
    1844 unsigned int childid;
    1845
    1846 nchilds = reopttree->reoptnodes[id]->nchilds;
    1847 childid = reopttree->reoptnodes[id]->childids[nchilds-1];
    1848 assert(0 < childid && childid < reopttree->reoptnodessize);
    1849
    1850 SCIP_CALL( deleteChildrenBelow(reopttree, set, blkmem, childid, TRUE, exitsolve) );
    1851
    1852 --reopttree->reoptnodes[id]->nchilds;
    1853 }
    1854 }
    1855
    1856 /* delete node data*/
    1857 if( delnodeitself )
    1858 {
    1859 SCIP_CALL( reopttreeDeleteNode(reopttree, set, blkmem, id, exitsolve) );
    1860 SCIP_CALL( SCIPqueueInsertUInt(reopttree->openids, id) );
    1861 }
    1862
    1863 return SCIP_OKAY;
    1864}
    1865
    1866/** replaces a reoptimization nodes by its stored child nodes */
    1867static
    1869 SCIP_REOPT* reopt, /**< reoptimization data structure */
    1870 SCIP_SET* set, /**< global SCIP settings */
    1871 SCIP_NODE* node, /**< node of the search tree */
    1872 unsigned int id, /**< id of the node */
    1873 SCIP_Bool* shrank, /**< pointer to store if the node was shrank */
    1874 BMS_BLKMEM* blkmem /**< block memory */
    1875 )
    1876{
    1877 SCIP_REOPTNODE** reoptnodes;
    1878
    1879 assert(reopt != NULL);
    1880 assert(node != NULL);
    1881 assert(id < reopt->reopttree->reoptnodessize);
    1882
    1883 reoptnodes = reopt->reopttree->reoptnodes;
    1884 assert(reoptnodes != NULL);
    1885 assert(reoptnodes[id] != NULL);
    1886
    1887 if( reoptnodes[id]->childids != NULL && reoptnodes[id]->nchilds > 0 )
    1888 {
    1889 int ndomchgs = 0;
    1890 unsigned int parentid = 0;
    1891 SCIP_NODE* parent = NULL;
    1892
    1893 SCIP_CALL( getLastSavedNode(reopt, set, node, &parent, &parentid, &ndomchgs) );
    1894
    1895 assert(parentid != id);
    1896 assert(reoptnodes[parentid] != NULL );
    1897 assert(reoptnodes[parentid]->childids != NULL && reoptnodes[parentid]->nchilds);
    1898
    1899 /* check if we want move all children to the next saved node above
    1900 * we want to shrink the path if either
    1901 * - the maximal number of bound changes fix and the number of bound changes is
    1902 * less than the given threshold set->reopt_maxdiffofnodes
    1903 * or
    1904 * - the number is calculated dynamically and the number of bound changes
    1905 * is less than log2(SCIPgetNBinVars - (#vars of parent))
    1906 * */
    1907 if( ndomchgs <= set->reopt_maxdiffofnodes )
    1908 {
    1909 int c;
    1910
    1911 SCIPsetDebugMsg(set, " -> shrink node %lld at ID %u, replaced by %d child nodes.\n", SCIPnodeGetNumber(node),
    1912 id, reoptnodes[id]->nchilds);
    1913
    1914 /* copy the references of child nodes to the parent*/
    1915 SCIP_CALL( moveChildrenUp(reopt, set, blkmem, id, parentid) );
    1916
    1917 /* delete the current node */
    1918 c = 0;
    1919 while( reoptnodes[parentid]->childids[c] != id )
    1920 {
    1921 ++c;
    1922 assert(c < reoptnodes[parentid]->nchilds);
    1923 }
    1924
    1925 assert(reoptnodes[parentid]->childids[c] == id);
    1926
    1927 /* replace the childid at position c by the last one */
    1928 reoptnodes[parentid]->childids[c] = reoptnodes[parentid]->childids[reoptnodes[parentid]->nchilds-1];
    1929 --reoptnodes[parentid]->nchilds;
    1930
    1931 SCIP_CALL( reopttreeDeleteNode(reopt->reopttree, set, blkmem, id, TRUE) );
    1933
    1934 *shrank = TRUE;
    1935
    1936 /* set the reopttype to none */
    1938 }
    1939 }
    1940
    1941 return SCIP_OKAY;
    1942}
    1943
    1944/** change all reopttypes in the subtree induced by @p nodeID */
    1945static
    1947 SCIP_REOPTTREE* reopttree, /**< reopttree */
    1948 unsigned int id, /**< id of the node */
    1949 SCIP_REOPTTYPE reopttype /**< reopttype */
    1950 )
    1951{
    1952 assert(reopttree != NULL);
    1953 assert(id < reopttree->reoptnodessize);
    1954 assert(reopttree->reoptnodes[id] != NULL);
    1955
    1956 if( reopttree->reoptnodes[id]->childids != NULL && reopttree->reoptnodes[id]->nchilds > 0 )
    1957 {
    1958 unsigned int childid;
    1959 int nchildids;
    1960 int seenids = 0;
    1961
    1962 nchildids = reopttree->reoptnodes[id]->nchilds;
    1963
    1964 while( seenids < nchildids )
    1965 {
    1966 /* get childID */
    1967 childid = reopttree->reoptnodes[id]->childids[seenids];
    1968 assert(childid < reopttree->reoptnodessize);
    1969 assert(reopttree->reoptnodes[childid] != NULL);
    1970
    1971 /* change the reopttype of the node iff the node is neither infeasible nor induces an
    1972 * infeasible subtree and if the node contains no bound changes based on dual decisions
    1973 */
    1974 if( reopttree->reoptnodes[childid]->reopttype != SCIP_REOPTTYPE_STRBRANCHED
    1975 && reopttree->reoptnodes[childid]->reopttype != SCIP_REOPTTYPE_INFSUBTREE ) /*lint !e641*/
    1976 reopttree->reoptnodes[childid]->reopttype = reopttype; /*lint !e641*/
    1977
    1978 /* change reopttype of subtree */
    1979 SCIP_CALL( changeReopttypeOfSubtree(reopttree, childid, reopttype) );
    1980
    1981 ++seenids;
    1982 }
    1983 }
    1984
    1985 return SCIP_OKAY;
    1986}
    1987
    1988/** delete the constraint handling dual information for the current iteration and replace it with the dual constraint
    1989 * for the next iteration
    1990 */
    1991static
    1993 SCIP_REOPTNODE* reoptnode, /**< reoptimization node */
    1994 BMS_BLKMEM* blkmem /**< block memory */
    1995 )
    1996{
    1997 assert(reoptnode != NULL);
    1998 assert(blkmem != NULL);
    1999
    2000 if( reoptnode->dualredscur != NULL )
    2001 {
    2002 SCIPdebugMessage("reset dual information (current run)\n");
    2003
    2004 BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredscur->boundtypes, reoptnode->dualredscur->varssize);
    2005 BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredscur->vals, reoptnode->dualredscur->varssize);
    2006 BMSfreeBlockMemoryArray(blkmem, &reoptnode->dualredscur->vars, reoptnode->dualredscur->varssize);
    2007 BMSfreeBlockMemory(blkmem, &reoptnode->dualredscur);
    2008 reoptnode->dualredscur = NULL;
    2009 }
    2010
    2011 if( reoptnode->dualredsnex != NULL )
    2012 {
    2013 SCIPdebugMessage("set dual information of next run to current run\n");
    2014 reoptnode->dualredscur = reoptnode->dualredsnex;
    2015 reoptnode->dualredsnex = NULL;
    2016 }
    2017
    2018 reoptnode->dualreds = (reoptnode->dualredscur != NULL ? TRUE : FALSE);
    2019
    2020 return SCIP_OKAY;
    2021}
    2022
    2023/** calculates a (local) similarity of a given node and returns if the subproblem should be solved from scratch */
    2024static
    2026 SCIP_REOPT* reopt, /**< reoptimization data structure */
    2027 SCIP_SET* set, /**< global SCIP settings */
    2028 BMS_BLKMEM* blkmem, /**< block memory */
    2029 SCIP_NODE* node, /**< node of the search tree */
    2030 SCIP_VAR** transvars, /**< transformed variables */
    2031 int ntransvars, /**< number of transformed variables */
    2032 SCIP_Bool* localrestart /**< pointer to store if we want to restart solving the (sub)problem */
    2033 )
    2034{
    2035 unsigned int id;
    2036
    2037 assert(reopt != NULL);
    2038 assert(reopt->reopttree != NULL);
    2039 assert(set != NULL);
    2040 assert(blkmem != NULL);
    2041 assert(node != NULL);
    2042 assert(transvars != NULL);
    2043
    2044 /* node == NULL is equivalent to node == root, this case should be handled by SCIPreoptCheckReopt */
    2045 assert(node != NULL);
    2046
    2047 *localrestart = FALSE;
    2048
    2049 id = SCIPnodeGetReoptID(node);
    2050 assert(id < reopt->reopttree->reoptnodessize);
    2051
    2052 /* set the id to -1 if the node is not part of the reoptimization tree */
    2053 if( SCIPnodeGetDepth(node) > 0 && id == 0 )
    2054 return SCIP_OKAY;
    2055
    2056 if( set->reopt_objsimdelay > -1 )
    2057 {
    2058 SCIP_Real sim = 0.0;
    2059 SCIP_Real lb;
    2060 SCIP_Real ub;
    2061 SCIP_Real oldcoef;
    2062 SCIP_Real newcoef;
    2063 int idx;
    2064
    2065 if( id == 0 )
    2066 reopt->nlocrestarts = 0;
    2067
    2068 /* since the stored objective functions are already normalize the dot-product is equivalent to the similarity */
    2069 for( int v = 0; v < ntransvars; ++v )
    2070 {
    2071 lb = SCIPvarGetLbLocal(transvars[v]);
    2072 ub = SCIPvarGetUbLocal(transvars[v]);
    2073
    2074 /* skip already fixed variables */
    2075 if( SCIPsetIsFeasLT(set, lb, ub) )
    2076 {
    2077 idx = SCIPvarGetProbindex(transvars[v]);
    2078 assert(0 <= idx && idx < ntransvars);
    2079
    2080 oldcoef = SCIPreoptGetOldObjCoef(reopt, reopt->run-1, idx);
    2081 newcoef = SCIPreoptGetOldObjCoef(reopt, reopt->run, idx);
    2082
    2083 sim += (oldcoef * newcoef);
    2084 }
    2085 }
    2086
    2087 /* delete the stored subtree and information about bound changes
    2088 * based on dual information */
    2089 if( SCIPsetIsLT(set, sim, set->reopt_objsimdelay) )
    2090 {
    2091 /* set the flag */
    2092 *localrestart = TRUE;
    2093
    2094 ++reopt->nlocrestarts;
    2095 ++reopt->ntotallocrestarts;
    2096
    2097 /* delete the stored subtree */
    2098 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
    2099
    2100 /* delete the stored constraints; we do this twice in a row because we want to delete both constraints */
    2103 }
    2104
    2105 SCIPsetDebugMsg(set, " -> local similarity: %.4f%s\n", sim, *localrestart ? " (solve subproblem from scratch)" : "");
    2106 }
    2107
    2108 return SCIP_OKAY;
    2109}
    2110
    2111/** save ancestor branching information up to the next stored node */
    2112static
    2114 SCIP_REOPTTREE* reopttree, /**< reoptimization tree */
    2115 SCIP_SET* set, /**< global SCIP settings */
    2116 BMS_BLKMEM* blkmem, /**< block memory */
    2117 SCIP_NODE* node, /**< node of the branch and bound tree */
    2118 SCIP_NODE* parent, /**< parent node */
    2119 unsigned int id, /**< id of the node */
    2120 unsigned int parentid /**< id of the parent node */
    2121 )
    2122{
    2123 int nbranchvars;
    2124
    2125 assert(reopttree != NULL );
    2126 assert(node != NULL );
    2127 assert(parent != NULL );
    2128 assert(1 <= id && id < reopttree->reoptnodessize);
    2129 assert(reopttree->reoptnodes[id] != NULL );
    2130 assert(parentid < reopttree->reoptnodessize);
    2131 assert(parentid == 0 || reopttree->reoptnodes[parentid] != NULL ); /* if the root is the next saved node, the nodedata can be NULL */
    2132
    2133 SCIPsetDebugMsg(set, " -> save ancestor branchings\n");
    2134
    2135 /* allocate memory */
    2136 if (reopttree->reoptnodes[id]->varssize == 0)
    2137 {
    2138 assert(reopttree->reoptnodes[id]->vars == NULL );
    2139 assert(reopttree->reoptnodes[id]->varbounds == NULL );
    2140 assert(reopttree->reoptnodes[id]->varboundtypes == NULL );
    2141
    2142 /* allocate memory for node information */
    2143 SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], set, blkmem, DEFAULT_MEM_VAR, 0, 0) );
    2144 }
    2145
    2146 assert(reopttree->reoptnodes[id]->varssize > 0);
    2147 assert(reopttree->reoptnodes[id]->nvars == 0);
    2148
    2150 reopttree->reoptnodes[id]->vars,
    2151 reopttree->reoptnodes[id]->varbounds,
    2152 reopttree->reoptnodes[id]->varboundtypes,
    2153 &nbranchvars,
    2154 reopttree->reoptnodes[id]->varssize);
    2155
    2156 if( nbranchvars > reopttree->reoptnodes[id]->varssize )
    2157 {
    2158 /* reallocate memory */
    2159 SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], set, blkmem, nbranchvars, 0, 0) );
    2160
    2162 reopttree->reoptnodes[id]->vars,
    2163 reopttree->reoptnodes[id]->varbounds,
    2164 reopttree->reoptnodes[id]->varboundtypes,
    2165 &nbranchvars,
    2166 reopttree->reoptnodes[id]->varssize);
    2167 }
    2168
    2169 assert(nbranchvars <= reopttree->reoptnodes[id]->varssize); /* this should be the case */
    2170
    2171 reopttree->reoptnodes[id]->nvars = nbranchvars;
    2172
    2173 assert(nbranchvars <= reopttree->reoptnodes[id]->varssize);
    2174 assert(reopttree->reoptnodes[id]->vars != NULL );
    2175
    2176 return SCIP_OKAY;
    2177}
    2178
    2179
    2180/** transform a constraint with linear representation into reoptimization constraint data */
    2181static
    2183 SCIP_REOPTCONSDATA* reoptconsdata, /**< reoptimization constraint data */
    2184 SCIP_SET* set, /**< global SCIP settings */
    2185 BMS_BLKMEM* blkmem, /**< block memory */
    2186 SCIP_CONS* cons, /**< linear constraint that should be stored */
    2187 SCIP_Bool* success /**< pointer to store the success */
    2188 )
    2189{
    2190 SCIP_VAR** vars;
    2191 SCIP_Real* vals;
    2192 SCIP_CONSHDLR* conshdlr;
    2193 SCIP_Bool allocbuffervals;
    2194
    2195 assert(reoptconsdata != NULL);
    2196 assert(cons != NULL);
    2197
    2198 *success = FALSE;
    2199 allocbuffervals = FALSE;
    2200 reoptconsdata->linear = TRUE;
    2201
    2202 vars = NULL;
    2203 vals = NULL;
    2204 SCIP_CALL( SCIPconsGetNVars(cons, set, &reoptconsdata->nvars, success) );
    2205 assert(*success);
    2206
    2207 /* allocate memory for variables and values; boundtypes are not needed */
    2208 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->vars, reoptconsdata->nvars) );
    2209 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->vals, reoptconsdata->nvars) );
    2210 reoptconsdata->varssize = reoptconsdata->nvars;
    2211
    2212 /* only needed for bounddisjuction constraints, thus we set them to NULL to avoid compiler warnings */
    2213 reoptconsdata->boundtypes = NULL;
    2214
    2215 conshdlr = SCIPconsGetHdlr(cons);
    2216 assert(conshdlr != NULL);
    2217
    2218 /* get all variables, values, and sides */
    2219 if( strcmp(SCIPconshdlrGetName(conshdlr), "linear") == 0 )
    2220 {
    2221 vars = SCIPgetVarsLinear(set->scip, cons);
    2222 vals = SCIPgetValsLinear(set->scip, cons);
    2223 reoptconsdata->lhs = SCIPgetLhsLinear(set->scip, cons);
    2224 reoptconsdata->rhs = SCIPgetRhsLinear(set->scip, cons);
    2225 }
    2226 else if( strcmp(SCIPconshdlrGetName(conshdlr), "logicor") == 0 )
    2227 {
    2228 vars = SCIPgetVarsLogicor(set->scip, cons);
    2229
    2230 /* initialize values to 1.0 */
    2231 SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, reoptconsdata->nvars) );
    2232 allocbuffervals = TRUE;
    2233
    2234 for( int v = 0; v < reoptconsdata->nvars; ++v )
    2235 vals[v] = 1.0;
    2236
    2237 reoptconsdata->lhs = 1.0;
    2238 reoptconsdata->rhs = SCIPsetInfinity(set);
    2239 }
    2240 else if( strcmp(SCIPconshdlrGetName(conshdlr), "setppc") == 0 )
    2241 {
    2242 vars = SCIPgetVarsSetppc(set->scip, cons);
    2243
    2244 /* initialize values to 1.0 */
    2245 SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, reoptconsdata->nvars) );
    2246 allocbuffervals = TRUE;
    2247
    2248 for( int v = 0; v < reoptconsdata->nvars; ++v )
    2249 vals[v] = 1.0;
    2250
    2251 switch( SCIPgetTypeSetppc(set->scip, cons) ) {
    2253 reoptconsdata->lhs = 1.0;
    2254 reoptconsdata->rhs = 1.0;
    2255 break;
    2257 reoptconsdata->lhs = -SCIPsetInfinity(set);
    2258 reoptconsdata->rhs = 1.0;
    2259 break;
    2261 reoptconsdata->lhs = 1.0;
    2262 reoptconsdata->rhs = SCIPsetInfinity(set);
    2263 break;
    2264 default:
    2265 *success = FALSE;
    2266 return SCIP_OKAY;
    2267 }
    2268 }
    2269 else
    2270 {
    2271 assert(strcmp(SCIPconshdlrGetName(conshdlr), "linear") == 0 || strcmp(SCIPconshdlrGetName(conshdlr), "logicor") == 0
    2272 || strcmp(SCIPconshdlrGetName(conshdlr), "setppc") == 0);
    2273
    2274 SCIPerrorMessage("Cannot handle constraints of type <%s> in saveConsLinear.\n", SCIPconshdlrGetName(conshdlr));
    2275 return SCIP_INVALIDDATA;
    2276 }
    2277 assert(vars != NULL);
    2278 assert(vals != NULL);
    2279
    2280 /* transform all variables into the original space */
    2281 for( int v = 0; v < reoptconsdata->nvars; ++v )
    2282 {
    2283 SCIP_Real constant = 0.0;
    2284 SCIP_Real scalar = 1.0;
    2285
    2286 assert(vars[v] != NULL);
    2287
    2288 reoptconsdata->vars[v] = vars[v];
    2289 reoptconsdata->vals[v] = vals[v];
    2290
    2291 SCIP_CALL( SCIPvarGetOrigvarSum(&reoptconsdata->vars[v], &scalar, &constant) );
    2292 assert(!SCIPsetIsZero(set, scalar));
    2293
    2294 assert(!SCIPsetIsInfinity(set, REALABS(reoptconsdata->vals[v])));
    2295 reoptconsdata->vals[v] *= scalar;
    2296
    2297 if( !SCIPsetIsZero(set, constant) && !SCIPsetIsInfinity(set, -reoptconsdata->lhs) )
    2298 reoptconsdata->lhs -= constant;
    2299 if( !SCIPsetIsZero(set, constant) && !SCIPsetIsInfinity(set, reoptconsdata->rhs) )
    2300 reoptconsdata->rhs -= constant;
    2301 }
    2302
    2303 /* free buffer if needed */
    2304 if( allocbuffervals )
    2305 {
    2307 }
    2308
    2309 return SCIP_OKAY;
    2310}
    2311
    2312/** transform a bounddisjunction constraint into reoptimization constraint data */
    2313static
    2315 SCIP_REOPTCONSDATA* reoptconsdata, /**< reoptimization constraint data */
    2316 SCIP_SET* set, /**< global SCIP settings */
    2317 BMS_BLKMEM* blkmem, /**< block memory */
    2318 SCIP_CONS* cons, /**< bounddisjuction constraint that should be stored */
    2319 SCIP_Bool* success /**< pointer to store the success */
    2320 )
    2321{
    2322 SCIP_VAR** vars;
    2323 SCIP_CONSHDLR* conshdlr;
    2324 SCIP_BOUNDTYPE* boundtypes;
    2325 SCIP_Real* bounds;
    2326
    2327 assert(reoptconsdata != NULL);
    2328 assert(cons != NULL);
    2329
    2330 *success = FALSE;
    2331 reoptconsdata->linear = FALSE;
    2332
    2333 conshdlr = SCIPconsGetHdlr(cons);
    2334 assert(conshdlr != NULL);
    2335 assert(strcmp(SCIPconshdlrGetName(conshdlr), "bounddisjunction") == 0);
    2336
    2337 if( strcmp(SCIPconshdlrGetName(conshdlr), "bounddisjunction") != 0 )
    2338 {
    2339 SCIPerrorMessage("Cannot handle constraints of type <%s> in saveConsBounddisjuction.\n",
    2340 SCIPconshdlrGetName(conshdlr));
    2341 return SCIP_INVALIDDATA;
    2342 }
    2343
    2344 SCIP_CALL( SCIPconsGetNVars(cons, set, &reoptconsdata->nvars, success) );
    2345 assert(*success);
    2346
    2347 /* allocate memory for variables and values; boundtypes are not needed */
    2348 vars = SCIPgetVarsBounddisjunction(NULL, cons);
    2349 bounds = SCIPgetBoundsBounddisjunction(NULL, cons);
    2350 boundtypes = SCIPgetBoundtypesBounddisjunction(NULL, cons);
    2351 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptconsdata->vars, vars, reoptconsdata->nvars) );
    2352 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptconsdata->vals, bounds, reoptconsdata->nvars) );
    2353 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, boundtypes, reoptconsdata->nvars) );
    2354 reoptconsdata->varssize = reoptconsdata->nvars;
    2355 reoptconsdata->lhs = SCIP_UNKNOWN;
    2356 reoptconsdata->rhs = SCIP_UNKNOWN;
    2357
    2358 /* transform all variables into the original space */
    2359 for( int v = 0; v < reoptconsdata->nvars; ++v )
    2360 {
    2361 SCIP_Real constant = 0.0;
    2362 SCIP_Real scalar = 1.0;
    2363
    2364 assert(reoptconsdata->vars[v] != NULL);
    2365
    2366 SCIP_CALL( SCIPvarGetOrigvarSum(&reoptconsdata->vars[v], &scalar, &constant) );
    2367 assert(!SCIPsetIsZero(set, scalar));
    2368
    2369 assert(!SCIPsetIsInfinity(set, REALABS(reoptconsdata->vals[v])));
    2370 reoptconsdata->vals[v] -= constant;
    2371 reoptconsdata->vals[v] *= scalar;
    2372
    2373 /* due to multipling with a negative scalar the relation need to be changed */
    2374 if( SCIPsetIsNegative(set, scalar) )
    2375 reoptconsdata->boundtypes[v] = (SCIP_BOUNDTYPE)(SCIP_BOUNDTYPE_UPPER - reoptconsdata->boundtypes[v]); /*lint !e656*/
    2376 }
    2377
    2378 return SCIP_OKAY;
    2379}
    2380
    2381/** save additional all constraints that were additionally added to @p node */
    2382static
    2384 SCIP_REOPTTREE* reopttree, /**< reopttree */
    2385 SCIP_SET* set, /**< global SCIP settings */
    2386 BMS_BLKMEM* blkmem, /**< block memory */
    2387 SCIP_NODE* node, /**< node of the branch and bound tree */
    2388 unsigned int id /**< id of the node*/
    2389 )
    2390{
    2391 SCIP_CONS** addedcons;
    2392 int naddedconss;
    2393 int addedconsssize;
    2394 int nconss;
    2395
    2396 assert(node != NULL );
    2397 assert(reopttree != NULL);
    2398 assert(id < reopttree->reoptnodessize);
    2399
    2400 /* save the added pseudo-constraint */
    2401 if( SCIPnodeGetNAddedConss(node) > 0 )
    2402 {
    2403 addedconsssize = SCIPnodeGetNAddedConss(node);
    2404
    2405 SCIPsetDebugMsg(set, " -> save %d locally added constraints\n", addedconsssize);
    2406
    2407 /* get memory */
    2408 SCIP_CALL( SCIPsetAllocBufferArray(set, &addedcons, addedconsssize) );
    2409 SCIPnodeGetAddedConss(node, addedcons, &naddedconss, addedconsssize);
    2410
    2411 nconss = reopttree->reoptnodes[id]->nconss;
    2412
    2413 /* check memory for added constraints */
    2414 SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], set, blkmem, 0, 0, naddedconss) );
    2415
    2416 /* since the first nconss are already stored in the data structure, we skip them */
    2417 for( int c = nconss; c < naddedconss; ++c )
    2418 {
    2419 SCIP_CONSHDLR* conshdlr;
    2420 SCIP_Bool islinear;
    2421 SCIP_Bool success;
    2422
    2423 conshdlr = SCIPconsGetHdlr(addedcons[c]);
    2424
    2425 /* check whether the constraint has a linear representation */
    2426 islinear = (strcmp(SCIPconshdlrGetName(conshdlr), "linear") == 0
    2427 || strcmp(SCIPconshdlrGetName(conshdlr), "logicor") == 0
    2428 || strcmp(SCIPconshdlrGetName(conshdlr), "setppc") == 0);
    2429
    2430 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopttree->reoptnodes[id]->conss[c]) ); /*lint !e866*/
    2431
    2432 success = FALSE;
    2433
    2434 /* the constraint has a linear representation */
    2435 if( islinear )
    2436 {
    2437 SCIP_CALL( saveConsLinear(reopttree->reoptnodes[id]->conss[c], set, blkmem, addedcons[c], &success) );
    2438 assert(success);
    2439
    2440 /* increase the counter for added constraints */
    2441 ++reopttree->reoptnodes[id]->nconss;
    2442 }
    2443 else
    2444 {
    2445 assert(strcmp(SCIPconshdlrGetName(conshdlr), "bounddisjunction") == 0);
    2446 SCIP_CALL( saveConsBounddisjuction(reopttree->reoptnodes[id]->conss[c], set, blkmem, addedcons[c], &success) );
    2447 assert(success);
    2448
    2449 /* increase the counter for added constraints */
    2450 ++reopttree->reoptnodes[id]->nconss;
    2451 }
    2452 assert(reopttree->reoptnodes[id]->conss[c]->nvars > 0);
    2453
    2454 if( strcmp("reopt_inf", SCIPconsGetName(addedcons[c])) == 0 )
    2455 reopttree->reoptnodes[id]->conss[c]->constype = REOPT_CONSTYPE_INFSUBTREE;
    2456 else if( strcmp("reopt_dual", SCIPconsGetName(addedcons[c])) == 0 )
    2457 reopttree->reoptnodes[id]->conss[c]->constype = REOPT_CONSTYPE_DUALREDS;
    2458 else
    2459 reopttree->reoptnodes[id]->conss[c]->constype = REOPT_CONSTYPE_UNKNOWN;
    2460 }
    2461
    2462 assert(reopttree->reoptnodes[id]->nconss == naddedconss);
    2463 SCIPsetFreeBufferArray(set, &addedcons);
    2464 }
    2465
    2466 return SCIP_OKAY;
    2467}
    2468
    2469/** collect all bound changes based on dual information
    2470 *
    2471 * If the bound changes are global, all information are already stored because they were caught by the event handler.
    2472 * otherwise, we have to use SCIPnodeGetDualBoundchgs.
    2473 *
    2474 * Afterwards, we check if the constraint will be added in the next iteration or after splitting the node.
    2475 */
    2476static
    2478 SCIP_REOPT* reopt, /**< reoptimization data structure */
    2479 SCIP_SET* set, /**< global SCIP settings */
    2480 BMS_BLKMEM* blkmem, /**< block memory */
    2481 SCIP_NODE* node, /**< node of the search tree */
    2482 unsigned int id, /**< id of the node */
    2483 SCIP_REOPTTYPE reopttype /**< reopttype */
    2484 )
    2485{
    2486 SCIP_Bool cons_is_next = TRUE;
    2487 int nbndchgs;
    2488
    2489 assert(reopt != NULL);
    2490 assert(reopt->reopttree != NULL);
    2491 assert(id < reopt->reopttree->reoptnodessize);
    2492 assert(reopt->reopttree->reoptnodes[id]->dualreds);
    2493 assert(node != NULL);
    2494 assert(blkmem != NULL);
    2495
    2496 /* first case, all bound changes were global */
    2497 if( reopt->currentnode == SCIPnodeGetNumber(node) && reopt->dualreds != NULL && reopt->dualreds->nvars > 0 )
    2498 {
    2499 nbndchgs = reopt->dualreds->nvars;
    2500 }
    2501 else
    2502 {
    2503 assert(reopt->currentnode == SCIPnodeGetNumber(node));
    2504
    2505 /* get the number of bound changes based on dual information */
    2506 nbndchgs = SCIPnodeGetNDualBndchgs(node);
    2507
    2508 /* ensure that enough memory is allocated */
    2509 SCIP_CALL( checkMemDualCons(reopt, set, blkmem, nbndchgs) );
    2510
    2511 /* collect the bound changes */
    2512 SCIPnodeGetDualBoundchgs(node, reopt->dualreds->vars, reopt->dualreds->vals, reopt->dualreds->boundtypes,
    2513 &nbndchgs, reopt->dualreds->varssize);
    2514 assert(nbndchgs <= reopt->dualreds->varssize);
    2515
    2516 reopt->dualreds->nvars = nbndchgs;
    2517 reopt->dualreds->linear = FALSE;
    2518
    2519 /* transform the variables into the original space */
    2520 for( int v = 0; v < nbndchgs; ++v )
    2521 {
    2522 SCIP_Real constant = 0.0;
    2523 SCIP_Real scalar = 1.0;
    2524
    2525 SCIP_CALL( SCIPvarGetOrigvarSum(&reopt->dualreds->vars[v], &scalar, &constant) );
    2526 reopt->dualreds->vals[v] = (reopt->dualreds->vals[v] - constant) / scalar;
    2527
    2528 assert(SCIPvarIsOriginal(reopt->dualreds->vars[v]));
    2529 }
    2530 }
    2531
    2532 assert(nbndchgs > 0);
    2533
    2534 /* due to the strong branching initialization it can be possible that two
    2535 * constraints handling dual information are stored at the same time.
    2536 * During reoptimizing a node we add the constraint stored at dualredscur only,
    2537 * i.e, if dualredscur is not NULL, we need to store the constraint for the next
    2538 * iteration at dualredsnex because the constraint stored at dualredscur is needed
    2539 * to split the constraint in the current iteration.
    2540 */
    2541 if( reopt->reopttree->reoptnodes[id]->dualredscur != NULL )
    2542 {
    2543 assert(reopt->reopttree->reoptnodes[id]->dualredsnex == NULL);
    2544 cons_is_next = FALSE;
    2545 }
    2546 assert((cons_is_next && reopt->reopttree->reoptnodes[id]->dualredscur == NULL)
    2547 || (!cons_is_next && reopt->reopttree->reoptnodes[id]->dualredsnex == NULL));
    2548
    2549 /* the constraint will be added next */
    2550 if( cons_is_next )
    2551 {
    2552 assert(reopt->reopttree->reoptnodes[id]->dualredscur == NULL);
    2555 reopt->dualreds->vars, nbndchgs) );
    2557 reopt->dualreds->vals, nbndchgs) );
    2558 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopt->reopttree->reoptnodes[id]->dualredscur->boundtypes, \
    2559 reopt->dualreds->boundtypes, nbndchgs) );
    2560
    2561 reopt->reopttree->reoptnodes[id]->dualredscur->nvars = nbndchgs;
    2562 reopt->reopttree->reoptnodes[id]->dualredscur->varssize = nbndchgs;
    2563 reopt->reopttree->reoptnodes[id]->dualredscur->lhs = 1.0;
    2564 reopt->reopttree->reoptnodes[id]->dualredscur->rhs = SCIPsetInfinity(set);
    2565 reopt->reopttree->reoptnodes[id]->dualredscur->constype = (reopttype == SCIP_REOPTTYPE_STRBRANCHED ?
    2567 reopt->reopttree->reoptnodes[id]->dualredscur->linear = FALSE;
    2568
    2569 SCIPsetDebugMsg(set, " -> save dual information of type 1: node %lld, nvars %d, constype %d\n",
    2570 SCIPnodeGetNumber(node), reopt->reopttree->reoptnodes[id]->dualredscur->nvars,
    2571 reopt->reopttree->reoptnodes[id]->dualredscur->constype);
    2572 }
    2573 /* the constraint will be added after next */
    2574 else
    2575 {
    2576 assert(reopt->reopttree->reoptnodes[id]->dualredsnex == NULL);
    2578 reopt->reopttree->reoptnodes[id]->dualredsnex->nvars = -1;
    2579
    2581 reopt->dualreds->vars, nbndchgs) );
    2583 reopt->dualreds->vals, nbndchgs) );
    2584 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopt->reopttree->reoptnodes[id]->dualredsnex->boundtypes, \
    2585 reopt->dualreds->boundtypes, nbndchgs) );
    2586 reopt->reopttree->reoptnodes[id]->dualredsnex->nvars = nbndchgs;
    2587 reopt->reopttree->reoptnodes[id]->dualredsnex->varssize = nbndchgs;
    2588 reopt->reopttree->reoptnodes[id]->dualredsnex->lhs = 1.0;
    2589 reopt->reopttree->reoptnodes[id]->dualredsnex->rhs = SCIPsetInfinity(set);
    2590 reopt->reopttree->reoptnodes[id]->dualredsnex->constype = (reopttype == SCIP_REOPTTYPE_STRBRANCHED ?
    2592
    2593 SCIPsetDebugMsg(set, " -> save dual information of type 2: node %lld, nvars %d, constype %d\n",
    2594 SCIPnodeGetNumber(node), reopt->reopttree->reoptnodes[id]->dualredsnex->nvars,
    2595 reopt->reopttree->reoptnodes[id]->dualredsnex->constype);
    2596 }
    2597
    2598 return SCIP_OKAY;
    2599}
    2600
    2601/** adds a node of the branch and bound tree to the reoptimization tree */
    2602static
    2604 SCIP_REOPT* reopt, /**< reoptimization data structure */
    2605 SCIP_SET* set, /**< global SCIP settings */
    2606 SCIP_LP* lp, /**< current LP */
    2607 BMS_BLKMEM* blkmem, /**< block memory */
    2608 SCIP_NODE* node, /**< current node */
    2609 SCIP_REOPTTYPE reopttype, /**< reason for storing the node*/
    2610 SCIP_Bool saveafterdual, /**< save branching decisions after the first dual */
    2611 SCIP_Bool isrootnode, /**< node is the root node */
    2612 SCIP_Real lowerbound /**< lower bound of the node */
    2613 )
    2614{
    2615 SCIP_NODE* parent = NULL;
    2616 SCIP_Bool shrank = FALSE;
    2617 unsigned int id;
    2618 unsigned int parentid = 0;
    2619
    2620 assert(reopt != NULL);
    2621 assert(set != NULL);
    2622 assert(blkmem != NULL);
    2623 assert(node != NULL);
    2624
    2625 if( set->reopt_maxsavednodes == 0 )
    2626 return SCIP_OKAY;
    2627
    2628 assert(reopttype == SCIP_REOPTTYPE_TRANSIT
    2629 || reopttype == SCIP_REOPTTYPE_INFSUBTREE
    2630 || reopttype == SCIP_REOPTTYPE_STRBRANCHED
    2631 || reopttype == SCIP_REOPTTYPE_LOGICORNODE
    2632 || reopttype == SCIP_REOPTTYPE_LEAF
    2633 || reopttype == SCIP_REOPTTYPE_PRUNED
    2634 || reopttype == SCIP_REOPTTYPE_FEASIBLE);
    2635
    2636 /* start clock */
    2637 SCIPclockStart(reopt->savingtime, set);
    2638
    2639 /* the node was created by reoptimization, i.e., we need to update the
    2640 * stored data */
    2641 if( SCIPnodeGetReoptID(node) >= 1 )
    2642 {
    2643 SCIP_Bool transintoorig;
    2644
    2645 assert(reopttype != SCIP_REOPTTYPE_LEAF);
    2646 assert(!isrootnode);
    2647
    2648 id = SCIPnodeGetReoptID(node);
    2649 assert(id < reopt->reopttree->reoptnodessize);
    2650
    2651 /* this is a special case:
    2652 * due to re-propagation of the an anchester node it can happen that we try to update a node that was created by
    2653 * reoptimization and already removed by deleteChildrenBelow. In this case we do not want to save the current
    2654 * node
    2655 */
    2656 if( reopt->reopttree->reoptnodes[id] == NULL )
    2657 {
    2658 parent = SCIPnodeGetParent(node);
    2659 assert(parent != NULL);
    2660
    2661 parentid = SCIPnodeGetReoptID(parent);
    2662
    2663 /* traverse along the branching path until reaching a node that is part of the reoptimization tree or the root node */
    2664 while( SCIPnodeGetDepth(parent) > 0 && reopt->reopttree->reoptnodes[parentid] == NULL )
    2665 {
    2666 /* the parent node is not part of the reoptimization, reset the reoptid and reopttype of the parent node */
    2667 SCIPnodeSetReoptID(parent, 0);
    2669
    2670 parent = SCIPnodeGetParent(parent);
    2671 assert(parent != NULL);
    2672
    2673 parentid = SCIPnodeGetReoptID(parent);
    2674 }
    2675
    2676 /* the anchestor node has to be part of the reoptimization tree. either the parent is the root itself or
    2677 * marked to be a leaf, pruned or feasible
    2678 */
    2679 assert(reopt->reopttree->reoptnodes[parentid] != NULL);
    2680 assert(parentid == 0
    2681 || reopt->reopttree->reoptnodes[parentid]->reopttype == SCIP_REOPTTYPE_FEASIBLE
    2683 || reopt->reopttree->reoptnodes[parentid]->reopttype == SCIP_REOPTTYPE_LEAF
    2684 || reopt->reopttree->reoptnodes[parentid]->reopttype == SCIP_REOPTTYPE_PRUNED); /*lint !e641*/
    2685
    2686 SCIPsetDebugMsg(set, " -> skip saving\n");
    2687 SCIPnodeSetReoptID(node, 0);
    2689
    2690 /* stop clock */
    2691 SCIPclockStop(reopt->savingtime, set);
    2692
    2693 return SCIP_OKAY;
    2694 }
    2695
    2696 SCIPsetDebugMsg(set, "update node %lld at ID %u:\n", SCIPnodeGetNumber(node), id);
    2697
    2698 transintoorig = FALSE;
    2699
    2700 /* store separated cuts */
    2701 if( set->reopt_usecuts )
    2702 {
    2703 SCIP_CALL( storeCuts(reopt, set, blkmem, lp, id) );
    2704 }
    2705
    2706 /* save primal bound changes made after the first dual bound change */
    2707 if( saveafterdual )
    2708 {
    2709 assert(reopttype == SCIP_REOPTTYPE_STRBRANCHED);
    2710 SCIP_CALL( saveAfterDualBranchings(reopt, set, blkmem, node, id, &transintoorig) );
    2711 }
    2712
    2713 /* update propagations */
    2714 if( set->reopt_saveprop )
    2715 {
    2716 SCIP_CALL( updatePropagation(reopt, set, blkmem, node, id, &transintoorig) );
    2717 }
    2718
    2719 /* ensure that all variables describing the branching path are original */
    2720 if( transintoorig )
    2721 {
    2722 SCIP_CALL( transformIntoOrig(reopt, id) );
    2723 }
    2724
    2725 /* update the lowerbound if the new lower bound is finite */
    2726 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
    2727 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
    2728 SCIPsetDebugMsg(set, " -> reopttype: %d, lowerbound: %g\n", reopttype, reopt->reopttree->reoptnodes[id]->lowerbound);
    2729
    2730#ifdef SCIP_MORE_DEBUG
    2731 SCIPsetDebugMsg(set, " -> saved variables:\n");
    2732 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; ++varnr )
    2733 {
    2734 SCIPsetDebugMsg(set, " <%s> %s %g\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->vars[varnr]),
    2736 "=>" : "<=", reopt->reopttree->reoptnodes[id]->varbounds[varnr]);
    2737 }
    2738 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nafterdualvars; ++varnr )
    2739 {
    2740 SCIPsetDebugMsg(set, " <%s> %s %g (after dual red.)\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]),
    2742 "=>" : "<=", reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr]);
    2743 }
    2744#endif
    2745
    2746 /* update LPI state */
    2747 switch( reopttype )
    2748 {
    2750 if( set->reopt_shrinkinner )
    2751 {
    2752 SCIP_CALL( shrinkNode(reopt, set, node, id, &shrank, blkmem) );
    2753 }
    2754 goto TRANSIT;
    2755
    2758 goto TRANSIT;
    2759
    2761 /* delete the whole subtree induced be the current node */
    2762 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
    2763 goto PSEUDO;
    2764
    2766 goto PSEUDO;
    2767
    2769 /* delete the subtree */
    2770 if( set->reopt_reducetofrontier )
    2771 {
    2772 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
    2773 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    2774 }
    2775 /* dive through all children and change the reopttype to PRUNED */
    2776 else
    2777 {
    2779 }
    2780 goto FEASIBLE;
    2781
    2783 /* delete the subtree */
    2784 if( set->reopt_reducetofrontier )
    2785 {
    2786 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
    2787 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    2788 }
    2789 /* dive through all children and change the reopttype to LEAF */
    2790 else
    2791 {
    2793 }
    2794
    2795 /* increase number of reoptimized nodes that could be pruned */
    2796 ++reopt->reopttree->ncutoffreoptnodes;
    2798
    2799 goto PRUNED;
    2800
    2801 default:
    2802 break;
    2803 } /*lint !e788*/
    2804
    2805 /* stop clock */
    2806 SCIPclockStart(reopt->savingtime, set);
    2807
    2808 return SCIP_OKAY;
    2809 }
    2810
    2811 /* get new IDs */
    2812 SCIP_CALL( reopttreeCheckMemory(reopt->reopttree, set, blkmem) );
    2813
    2814 /* the current node is the root node */
    2815 if( isrootnode )
    2816 {
    2817 id = 0;
    2818
    2819 /* save local constraints
    2820 * note: currently, there will be no constraint to save because all global constraints are added by calling
    2821 * SCIPprobAddCons.
    2822 */
    2823 if (SCIPnodeGetNAddedConss(node) >= 1)
    2824 {
    2825 assert(reopt->reopttree->reoptnodes[id]->nconss == 0);
    2826
    2827 SCIP_CALL( saveLocalConssData(reopt->reopttree, set, blkmem, node, id) );
    2828 }
    2829
    2830 /* store separated cuts
    2831 * note: we need to call this after saveLocalConssData to be sure that the local conss array is ordered, first all
    2832 * local constraints, then cuts
    2833 */
    2834 if( set->reopt_usecuts )
    2835 {
    2836 SCIP_CALL( storeCuts(reopt, set, blkmem, lp, id) );
    2837 }
    2838
    2839 switch( reopttype )
    2840 {
    2842 /* ensure that no dual constraints are stored */
    2843 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    2844
    2845 /* update the lowerbound */
    2846 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
    2847 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
    2848
    2849 goto TRANSIT;
    2850
    2853 reopt->reopttree->reoptnodes[0]->reopttype = (unsigned int)reopttype;
    2854 reopt->reopttree->reoptnodes[0]->dualreds = TRUE;
    2855 reopt->reopttree->reoptnodes[0]->nvars = 0;
    2856
    2857 if( reopttype == SCIP_REOPTTYPE_INFSUBTREE )
    2858 {
    2859 /* delete the whole subtree induced be the current node */
    2860 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, 0, FALSE, FALSE) );
    2861 }
    2862
    2863 /* update the lowerbound */
    2864 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
    2865 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
    2866
    2867 SCIPsetDebugMsg(set, "update node %d at ID %d:\n", 1, 0);
    2868 SCIPsetDebugMsg(set, " -> nvars: 0, ncons: 0, parentID: -, reopttype: %d, lowerbound: %g\n", reopttype,
    2869 reopt->reopttree->reoptnodes[id]->lowerbound);
    2870
    2871 goto PSEUDO;
    2872
    2874 ++reopt->reopttree->ntotalfeasnodes;
    2875 ++reopt->reopttree->nfeasnodes;
    2876 reopt->reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_FEASIBLE;
    2877 reopt->reopttree->reoptnodes[0]->dualreds = FALSE;
    2878
    2879 if( reopt->reopttree->reoptnodes[0]->childids != NULL && reopt->reopttree->reoptnodes[0]->nchilds > 0 )
    2880 {
    2881 /* delete the subtree */
    2882 if( set->reopt_reducetofrontier )
    2883 {
    2884 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, 0, FALSE, FALSE) );
    2885 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    2886 }
    2887 /* dive through all children and change the reopttype to LEAF */
    2888 else
    2889 {
    2891 }
    2892 }
    2893 else
    2894 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    2895
    2896 /* update the lowerbound */
    2897 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
    2898 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
    2899
    2900 SCIPsetDebugMsg(set, "update node %d at ID %d:\n", 1, 0);
    2901 SCIPsetDebugMsg(set, " -> nvars: 0, ncons: 0, parentID: -, reopttype: %d, lowerbound: %g\n", reopttype,
    2902 reopt->reopttree->reoptnodes[id]->lowerbound);
    2903
    2904 break;
    2905
    2907 ++reopt->reopttree->nprunednodes;
    2908 ++reopt->reopttree->ntotalprunednodes;
    2909 reopt->reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_PRUNED;
    2910 reopt->reopttree->reoptnodes[0]->dualreds = FALSE;
    2911
    2912 if( reopt->reopttree->reoptnodes[0]->childids != NULL && reopt->reopttree->reoptnodes[0]->nchilds > 0 )
    2913 {
    2914 /* delete the subtree */
    2915 if( set->reopt_reducetofrontier )
    2916 {
    2917 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, 0, FALSE, FALSE) );
    2918 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    2919 }
    2920 /* dive through all children and change the reopttype to LEAF */
    2921 else
    2922 {
    2924 }
    2925 }
    2926 else
    2927 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    2928
    2929 /* update the lowerbound if it was not set */
    2930 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
    2931 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
    2932
    2933 SCIPsetDebugMsg(set, "update node %d at ID %d:\n", 1, 0);
    2934 SCIPsetDebugMsg(set, " -> nvars: 0, ncons: 0, parentID: -, reopttype: %d, lowerbound:%g \n", reopttype,
    2935 reopt->reopttree->reoptnodes[id]->lowerbound);
    2936
    2937 break;
    2938
    2939 default:
    2940 assert(reopttype == SCIP_REOPTTYPE_TRANSIT
    2941 || reopttype == SCIP_REOPTTYPE_INFSUBTREE
    2942 || reopttype == SCIP_REOPTTYPE_STRBRANCHED
    2943 || reopttype == SCIP_REOPTTYPE_PRUNED
    2944 || reopttype == SCIP_REOPTTYPE_FEASIBLE);
    2945 break;
    2946 }/*lint !e788*/
    2947
    2948 /* reset the information of dual bound changes */
    2949 reopt->currentnode = -1;
    2950 if( reopt->dualreds != NULL )
    2951 reopt->dualreds->nvars = 0;
    2952
    2953 /* stop clock */
    2954 SCIPclockStop(reopt->savingtime, set);
    2955
    2956 return SCIP_OKAY;
    2957 }
    2958 else
    2959 {
    2960 int nbndchgdiff;
    2961 SCIP_Bool transintoorig;
    2962
    2963 SCIPsetDebugMsg(set, "try to add node #%lld to the reopttree\n", SCIPnodeGetNumber(node));
    2964 SCIPsetDebugMsg(set, " -> reopttype = %d\n", reopttype);
    2965
    2966 /* check if we really want to save this node:
    2967 * 1. save the node if reopttype is at least SCIP_REOPTTYPE_INFSUBTREE
    2968 * 2. save the node if the number of bound changes of this node
    2969 * and the last saved node is at least a given number n
    2970 */
    2971
    2972 /* get the ID of the last saved node or 0 for the root */
    2973 SCIP_CALL( getLastSavedNode(reopt, set, node, &parent, &parentid, &nbndchgdiff) );
    2974
    2975 if( (reopttype < SCIP_REOPTTYPE_INFSUBTREE && nbndchgdiff <= set->reopt_maxdiffofnodes)
    2976 || reopt->reopttree->reoptnodes[parentid]->reopttype >= SCIP_REOPTTYPE_LEAF ) /*lint !e641*/
    2977 {
    2978 SCIPsetDebugMsg(set, " -> skip saving\n");
    2979
    2980 /* stop clock */
    2981 SCIPclockStop(reopt->savingtime, set);
    2982
    2983 return SCIP_OKAY;
    2984 }
    2985
    2986 /* check if there are free slots to store the node */
    2987 SCIP_CALL( reopttreeCheckMemory(reopt->reopttree, set, blkmem) );
    2988
    2990
    2991 SCIPsetDebugMsg(set, " -> save at ID %u\n", id);
    2992
    2993 assert(reopt->reopttree->reoptnodes[id] == NULL
    2994 || (reopt->reopttree->reoptnodes[id]->nvars == 0 && reopt->reopttree->reoptnodes[id]->nconss == 0));
    2995 assert(id >= 1 && id < reopt->reopttree->reoptnodessize);
    2996 assert(!isrootnode);
    2997
    2998 /* get memory for nodedata */
    2999 assert(reopt->reopttree->reoptnodes[id] == NULL || reopt->reopttree->reoptnodes[id]->nvars == 0);
    3000 SCIP_CALL( createReoptnode(reopt->reopttree, set, blkmem, id) );
    3001 reopt->reopttree->reoptnodes[id]->parentID = parentid;
    3002
    3003 assert(parent != NULL );
    3004 assert((SCIPnodeGetDepth(parent) == 0 && parentid == 0) || (SCIPnodeGetDepth(parent) >= 1 && parentid > 0));
    3005 assert(id >= 1);
    3006
    3007 /* create the array of "child nodes" if they not exist */
    3008 if( reopt->reopttree->reoptnodes[parentid]->childids == NULL
    3009 || reopt->reopttree->reoptnodes[parentid]->allocchildmem == 0 )
    3010 {
    3011 SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[parentid], set, blkmem, 0, 2, 0) );
    3012 }
    3013
    3014 /* add the new node as a "child node" of the last saved reoptminization node */
    3015 SCIP_CALL( reoptAddChild(reopt->reopttree, set, blkmem, parentid, id) );
    3016
    3017 /* save branching path */
    3018 SCIP_CALL( saveAncestorBranchings(reopt->reopttree, set, blkmem, node, parent, id, parentid) );
    3019
    3020 /* save bound changes after some dual reduction */
    3021 if( saveafterdual )
    3022 {
    3023 assert(reopttype == SCIP_REOPTTYPE_STRBRANCHED);
    3024 SCIP_CALL( saveAfterDualBranchings(reopt, set, blkmem, node, id, &transintoorig) );
    3025 }
    3026 else
    3027 {
    3028 SCIPsetDebugMsg(set, " -> skip saving bound changes after dual reductions.\n");
    3029 }
    3030
    3031 /* transform all bounds of branched variables and ensure that they are original. */
    3032 SCIP_CALL( transformIntoOrig(reopt, id) );
    3033
    3034 /* save pseudo-constraints (if one exists) */
    3035 if (SCIPnodeGetNAddedConss(node) >= 1)
    3036 {
    3037 assert(reopt->reopttree->reoptnodes[id]->nconss == 0);
    3038
    3039 SCIP_CALL( saveLocalConssData(reopt->reopttree, set, blkmem, node, id) );
    3040 }
    3041
    3042 /* store separated cuts
    3043 * note: we need to call this after saveLocalConssData to be sure that the local conss array is ordered, first all
    3044 * local constraints, then cuts
    3045 */
    3046 if( set->reopt_usecuts )
    3047 {
    3048 SCIP_CALL( storeCuts(reopt, set, blkmem, lp, id) );
    3049 }
    3050
    3051 /* update the lowerbound if it was not set */
    3052 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
    3053 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
    3054
    3055 /* set ID */
    3056 SCIPnodeSetReoptID(node, id);
    3057
    3058 /* set the REOPTTYPE */
    3059 SCIPnodeSetReopttype(node, reopttype);
    3060
    3061 SCIPsetDebugMsg(set, "save node #%lld successful\n", SCIPnodeGetNumber(node));
    3062 SCIPsetDebugMsg(set, " -> nvars: %d, ncons: %d, parentID: %u, reopttype: %d, lowerbound: %g\n",
    3063 reopt->reopttree->reoptnodes[id]->nvars + reopt->reopttree->reoptnodes[id]->nafterdualvars,
    3064 reopt->reopttree->reoptnodes[id]->nconss, reopt->reopttree->reoptnodes[id]->parentID,
    3065 reopttype, reopt->reopttree->reoptnodes[id]->lowerbound);
    3066#ifdef SCIP_MORE_DEBUG
    3067 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; ++varnr )
    3068 {
    3069 SCIPsetDebugMsg(set, " <%s> %s %g\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->vars[varnr]),
    3071 "=>" : "<=", reopt->reopttree->reoptnodes[id]->varbounds[varnr]);
    3072 }
    3073 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nafterdualvars; ++varnr )
    3074 {
    3075 SCIPsetDebugMsg(set, " <%s> %s %g (after dual red.)\n",
    3076 SCIPvarGetName(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]),
    3078 "=>" : "<=", reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr]);
    3079 }
    3080#endif
    3081 } /*lint !e438*/
    3082
    3083 switch( reopttype )
    3084 {
    3088 TRANSIT:
    3089 if( !shrank )
    3090 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)reopttype;
    3091 else
    3092 {
    3093 SCIPnodeSetReoptID(node, 0);
    3095 }
    3096 break;
    3097
    3100 PSEUDO:
    3101 assert(reopt->currentnode == SCIPnodeGetNumber(node));
    3102
    3103 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)reopttype;
    3104 reopt->reopttree->reoptnodes[id]->dualreds = TRUE;
    3105
    3106 /* get all the dual information and decide if the constraint need
    3107 * to be added next or after next */
    3108 SCIP_CALL( collectDualInformation(reopt, set, blkmem, node, id, reopttype) );
    3109
    3110 break;
    3111
    3113 FEASIBLE:
    3114 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_FEASIBLE;
    3115 reopt->reopttree->reoptnodes[id]->dualreds = FALSE;
    3116 ++reopt->reopttree->nfeasnodes;
    3117 ++reopt->reopttree->ntotalfeasnodes;
    3118
    3119 break;
    3120
    3122 PRUNED:
    3123 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_PRUNED;
    3124 reopt->reopttree->reoptnodes[id]->dualreds = FALSE;
    3125 ++reopt->reopttree->nprunednodes;
    3126 ++reopt->reopttree->ntotalprunednodes;
    3127
    3128 break;
    3129
    3130 default:
    3131 assert(reopttype == SCIP_REOPTTYPE_TRANSIT
    3132 || reopttype == SCIP_REOPTTYPE_LOGICORNODE
    3133 || reopttype == SCIP_REOPTTYPE_LEAF
    3134 || reopttype == SCIP_REOPTTYPE_INFSUBTREE
    3135 || reopttype == SCIP_REOPTTYPE_STRBRANCHED
    3136 || reopttype == SCIP_REOPTTYPE_FEASIBLE
    3137 || reopttype == SCIP_REOPTTYPE_PRUNED);
    3138 break;
    3139 } /*lint !e788*/
    3140
    3141 /* stop clock */
    3142 SCIPclockStop(reopt->savingtime, set);
    3143
    3144 /* reset the information of dual bound changes */
    3145 reopt->currentnode = -1;
    3146 if( reopt->dualreds != NULL )
    3147 reopt->dualreds->nvars = 0;
    3148
    3149 return SCIP_OKAY;
    3150}
    3151
    3152/** delete the stored information about dual bound changes of the last focused node */
    3153static
    3155 SCIP_REOPT* reopt /**< reoptimization data structure */
    3156 )
    3157{
    3158 assert(reopt != NULL);
    3159
    3160 if( reopt->dualreds != NULL && reopt->dualreds->nvars > 0 )
    3161 {
    3162 SCIPdebugMessage("delete %d dual variable information about node %lld\n", reopt->dualreds->nvars,
    3163 reopt->currentnode);
    3164 reopt->dualreds->nvars = 0;
    3165 reopt->currentnode = -1;
    3166 }
    3167}
    3168
    3169/** delete the stored constraints that dual information at the given reoptimization node */
    3170static
    3172 SCIP_REOPTNODE* reoptnode, /**< reoptimization node */
    3173 BMS_BLKMEM* blkmem /**< block memory */
    3174 )
    3175{
    3176 assert(reoptnode != NULL);
    3177 assert(blkmem != NULL);
    3178
    3179 if( reoptnode->dualredscur != NULL )
    3180 {
    3181 SCIP_REOPTCONSDATA* reoptconsdata;
    3182
    3183 SCIPdebugMessage("reset dual information (current run)\n");
    3184
    3185 reoptconsdata = reoptnode->dualredscur;
    3186
    3187 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, reoptconsdata->varssize);
    3188 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vals, reoptconsdata->varssize);
    3189 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vars, reoptconsdata->varssize);
    3190 BMSfreeBlockMemory(blkmem, &reoptnode->dualredscur);
    3191 reoptnode->dualredscur = NULL;
    3192 }
    3193
    3194 if( reoptnode->dualredsnex != NULL )
    3195 {
    3196 SCIP_REOPTCONSDATA* reoptconsdata;
    3197
    3198 SCIPdebugMessage("reset dual information (next run)\n");
    3199
    3200 reoptconsdata = reoptnode->dualredsnex;
    3201
    3202 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, reoptconsdata->varssize);
    3203 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vals, reoptconsdata->varssize);
    3204 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vars, reoptconsdata->varssize);
    3205 BMSfreeBlockMemory(blkmem, &reoptnode->dualredsnex);
    3206 reoptnode->dualredsnex = NULL;
    3207 }
    3208
    3209 reoptnode->dualreds = FALSE;
    3210
    3211 return SCIP_OKAY;
    3212}
    3213
    3214
    3215/** transform given set of variables, bounds and boundtypes into a global cut.
    3216 *
    3217 * @note: boundtypes can be NULL if all variables are binary or a MIP solution should be separated.
    3218 * @note: continuous variables will be skiped if boundtypes is NULL
    3219 */
    3220static
    3222 SCIP_REOPT* reopt, /**< reoptimization data structure */
    3223 BMS_BLKMEM* blkmem, /**< block memory */
    3224 SCIP_SET* set, /**< global SCIP settings */
    3225 SCIP_VAR** vars, /**< variables of the cut */
    3226 SCIP_Real* vals, /**< values of the cut */
    3227 SCIP_BOUNDTYPE* boundtypes, /**< bounds of the cut */
    3228 int nvars, /**< number of variables in the cut */
    3229 int nbinvars, /**< number of binary variables */
    3230 int nintvars /**< number of integer variables */
    3231 )
    3232{
    3233 SCIP_REOPTCONSDATA* reoptconsdata;
    3234 int nglbconss;
    3235 int nvarsadded;
    3236
    3237 assert(reopt != NULL);
    3238 assert(blkmem != NULL);
    3239 assert(set != NULL);
    3240 assert(vars != NULL);
    3241 assert(vals != NULL);
    3242 assert(nbinvars + nintvars == nvars);
    3243
    3244 nvarsadded = 0;
    3245
    3246 /* check whether we have enough memory allocated */
    3247 SCIP_CALL( checkMemGlbCons(reopt, set, blkmem, 10) );
    3248 nglbconss = reopt->nglbconss;
    3249 reoptconsdata = NULL;
    3250
    3251 if( reopt->glbconss[nglbconss] == NULL )
    3252 {
    3253 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopt->glbconss[nglbconss]) ); /*lint !e866*/
    3254 reoptconsdata = reopt->glbconss[nglbconss];
    3255
    3256 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->vars, (int)(nbinvars+2*nintvars)) );
    3257 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->vals, (int)(nbinvars+2*nintvars)) );
    3258 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, (int)(nbinvars+2*nintvars)) );
    3259 reoptconsdata->varssize = (int)(nbinvars+2*nintvars);
    3260 reoptconsdata->nvars = 0;
    3261 }
    3262 else
    3263 {
    3264 assert(reopt->glbconss[nglbconss]->nvars == 0);
    3265 assert(reopt->glbconss[nglbconss]->varssize > 0);
    3266
    3267 reoptconsdata = reopt->glbconss[nglbconss];
    3268
    3269 if( reoptconsdata->varssize < nbinvars+2*nintvars )
    3270 {
    3271 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptconsdata->vars, reoptconsdata->varssize, \
    3272 (int)(nbinvars+2*nintvars)) );
    3273 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptconsdata->vals, reoptconsdata->varssize, \
    3274 (int)(nbinvars+2*nintvars)) );
    3275 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, reoptconsdata->varssize, \
    3276 (int)(nbinvars+2*nintvars)) );
    3277 reoptconsdata->varssize = (int)(nbinvars+2*nintvars);
    3278 }
    3279 }
    3280 assert(reoptconsdata != NULL);
    3281
    3282 reoptconsdata->lhs = 1.0;
    3283 reoptconsdata->rhs = SCIPsetInfinity(set);
    3284 reoptconsdata->linear = FALSE;
    3285 reoptconsdata->constype = REOPT_CONSTYPE_CUT;
    3286
    3287 for( int v = 0; v < nvars; ++v )
    3288 {
    3289 assert(nvarsadded < reoptconsdata->varssize);
    3290 assert(vars[v] != NULL);
    3291 assert(SCIPvarIsOriginal(vars[v]));
    3292 assert(!SCIPvarIsIntegral(vars[v]) || SCIPsetIsIntegral(set, vals[v]));
    3293
    3294 /* if no boundtypes are given we skip continuous variables, otherwise we would add trivial clauses:
    3295 * a) x <= ub
    3296 * b) lb <= x
    3297 * c) (x <= val) or (x >= val)
    3298 */
    3299 if( boundtypes == NULL && !SCIPvarIsIntegral(vars[v]) )
    3300 continue;
    3301
    3302 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(vars[v]) )
    3303 {
    3304 reoptconsdata->vars[nvarsadded] = vars[v];
    3305
    3306 if( SCIPsetIsEQ(set, vals[v], 1.0) )
    3307 {
    3308 assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
    3309 reoptconsdata->vals[nvarsadded] = 0.0;
    3310 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
    3311 }
    3312 else
    3313 {
    3314 assert(SCIPsetIsEQ(set, vals[v], 0.0));
    3315 assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
    3316 reoptconsdata->vals[nvarsadded] = 1.0;
    3317 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
    3318 }
    3319 ++nvarsadded;
    3320 }
    3321 else if( !SCIPvarIsIntegral(vars[v]) )
    3322 {
    3323 assert(boundtypes != NULL);
    3324
    3325 reoptconsdata->vals[nvarsadded] = vals[v];
    3326 reoptconsdata->boundtypes[nvarsadded] = (boundtypes[v] == SCIP_BOUNDTYPE_LOWER ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER);
    3327 ++nvarsadded;
    3328 }
    3329 else
    3330 {
    3331 SCIP_Real roundedval;
    3332 SCIP_Real ubglb;
    3333 SCIP_Real lbglb;
    3334
    3335 assert(SCIPvarGetType(vars[v]) == SCIP_VARTYPE_INTEGER || SCIPvarIsImpliedIntegral(vars[v]));
    3336
    3337 reoptconsdata->vars[nvarsadded] = vars[v];
    3338
    3339 ubglb = SCIPvarGetUbGlobal(vars[v]);
    3340 lbglb = SCIPvarGetLbGlobal(vars[v]);
    3341
    3342 /* case 1 : x == val == ub -> x <= ub-1
    3343 * case 2 : x == val == lb -> x >= lb+1
    3344 * case 3.1: x <= val < ub -> x >= y+1
    3345 * case 3.2: x >= val > lb -> x <= y-1
    3346 * case 4 : lb < x == val < ub -> (x <= y-1) or (x >= y+1)
    3347 */
    3348
    3349 /* case 1 */
    3350 if( SCIPsetIsEQ(set, vals[v], ubglb) )
    3351 {
    3352 assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
    3353 reoptconsdata->vals[nvarsadded] = ubglb - 1.0;
    3354 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
    3355 ++nvarsadded;
    3356 }
    3357 /* case 2 */
    3358 else if( SCIPsetIsEQ(set, vals[v], lbglb) )
    3359 {
    3360 assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
    3361 reoptconsdata->vals[nvarsadded] = lbglb + 1.0;
    3362 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
    3363 ++nvarsadded;
    3364 }
    3365 else if( boundtypes != NULL )
    3366 {
    3367 /* we round the solution value to get a 'clean' bound */
    3368 assert(SCIPsetIsIntegral(set, vals[v]));
    3369 roundedval = SCIPsetRound(set, vals[v]);
    3370
    3371 /* case 3.1 */
    3372 if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER )
    3373 {
    3374 reoptconsdata->vals[nvarsadded] = roundedval + 1.0;
    3375 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
    3376 ++nvarsadded;
    3377 }
    3378 /* case 3.2 */
    3379 else
    3380 {
    3381 assert(boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
    3382 reoptconsdata->vals[nvarsadded] = roundedval - 1.0;
    3383 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
    3384 ++nvarsadded;
    3385 }
    3386 }
    3387 /* case 4: in this case we have to add two clauses: (x <= val-1) and (x >= val+1) */
    3388 else
    3389 {
    3390 /* we round the solution value to get a 'clean' bound */
    3391 assert(SCIPsetIsIntegral(set, vals[v]));
    3392 roundedval = SCIPsetRound(set, vals[v]);
    3393
    3394 /* first clause: x <= val-1 */
    3395 reoptconsdata->vals[nvarsadded] = roundedval - 1.0;
    3396 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
    3397 ++nvarsadded;
    3398
    3399 /* second clause: x >= val+1 */
    3400 reoptconsdata->vars[nvarsadded] = vars[v];
    3401 reoptconsdata->vals[nvarsadded] = roundedval + 1.0;
    3402 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
    3403 ++nvarsadded;
    3404 }
    3405 }
    3406 }
    3407 assert(nvars <= nvarsadded);
    3408 assert(nvarsadded == nbinvars + 2 * nintvars);
    3409
    3410 reoptconsdata->nvars = nvarsadded;
    3411 ++reopt->nglbconss;
    3412
    3413 return SCIP_OKAY;
    3414}
    3415
    3416/** generate a global constraint to separate an infeasible subtree */
    3417static
    3419 SCIP_REOPT* reopt, /**< reoptimization data structure */
    3420 SCIP_SET* set, /**< global SCIP settings */
    3421 BMS_BLKMEM* blkmem, /**< block memory */
    3422 SCIP_NODE* node, /**< node of the search tree */
    3423 REOPT_CONSTYPE consttype /**< reopttype of the constraint */
    3424 )
    3425{
    3426 assert(reopt != NULL);
    3427 assert(node != NULL);
    3428
    3429 if( consttype == REOPT_CONSTYPE_INFSUBTREE )
    3430 {
    3431 SCIP_VAR** vars;
    3432 SCIP_Real* vals;
    3433 SCIP_BOUNDTYPE* boundtypes;
    3434 int allocmem;
    3435 int nbranchvars;
    3436 int nbinvars;
    3437 int nintvars;
    3438
    3439 /* allocate memory to store the infeasible path */
    3440 allocmem = SCIPnodeGetDepth(node);
    3441 SCIP_CALL( SCIPsetAllocBufferArray(set, &vars, allocmem) );
    3442 SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, allocmem) );
    3443 SCIP_CALL( SCIPsetAllocBufferArray(set, &boundtypes, allocmem) );
    3444
    3445 /* get the branching path */
    3446 SCIPnodeGetAncestorBranchings(node, vars, vals, boundtypes, &nbranchvars, allocmem);
    3447
    3448 if( allocmem < nbranchvars )
    3449 {
    3450 SCIP_CALL( SCIPsetReallocBufferArray(set, &vars, nbranchvars) );
    3451 SCIP_CALL( SCIPsetReallocBufferArray(set, &vals, nbranchvars) );
    3452 SCIP_CALL( SCIPsetReallocBufferArray(set, &boundtypes, nbranchvars) );
    3453 allocmem = nbranchvars;
    3454
    3455 SCIPnodeGetAncestorBranchings(node, vars, vals, boundtypes, &nbranchvars, allocmem);
    3456 }
    3457
    3458 /* we count the number of binary and (impl) integer variables */
    3459 nbinvars = 0;
    3460 nintvars = 0;
    3461 for( int v = 0; v < nbranchvars; ++v )
    3462 {
    3463 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(vars[v]) )
    3464 ++nbinvars;
    3466 ++nintvars;
    3467 }
    3468 assert(nbinvars + nintvars == nbranchvars);
    3469
    3470 SCIP_CALL( addGlobalCut(reopt, blkmem, set, vars, vals, boundtypes, nbranchvars, nbinvars, nintvars) );
    3471 assert(!reopt->glbconss[reopt->nglbconss - 1]->linear);
    3472
    3473 /* free buffer */
    3474 SCIPsetFreeBufferArray(set, &boundtypes);
    3477 }
    3478
    3479 return SCIP_OKAY;
    3480}
    3481
    3482
    3483/** move all id of child nodes from reoptimization node stored at @p id1 to the node stored at @p id2 */
    3484static
    3486 SCIP_REOPTTREE* reopttree, /**< reopttree */
    3487 SCIP_SET* set, /**< global SCIP settings */
    3488 BMS_BLKMEM* blkmem, /**< block memory */
    3489 unsigned int id1, /**< source id */
    3490 unsigned int id2 /**< target id */
    3491 )
    3492{
    3493 int nchilds_id1;
    3494 int nchilds_id2;
    3495
    3496 assert(reopttree != NULL);
    3497 assert(blkmem != NULL);
    3498 assert(id1 < reopttree->reoptnodessize);
    3499 assert(id2 < reopttree->reoptnodessize);
    3500 assert(reopttree->reoptnodes[id1] != NULL);
    3501 assert(reopttree->reoptnodes[id2] != NULL);
    3502
    3503 nchilds_id1 = reopttree->reoptnodes[id1]->nchilds;
    3504 nchilds_id2 = reopttree->reoptnodes[id2]->nchilds;
    3505
    3506 /* ensure that the array storing the child id's is large enough */
    3507 SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id2], set, blkmem, 0, nchilds_id1+nchilds_id2, 0) );
    3508 assert(reopttree->reoptnodes[id2]->allocchildmem >= nchilds_id1+nchilds_id2);
    3509
    3510 SCIPsetDebugMsg(set, "move %d IDs: %u -> %u\n", nchilds_id1, id1, id2);
    3511
    3512 /* move the ids */
    3513 for( int c = 0; c < nchilds_id1; ++c )
    3514 {
    3515#ifdef SCIP_DEBUG
    3516 {
    3517 /* check that no id is added twice */
    3518 for( int k = 0; k < nchilds_id2; ++k )
    3519 assert(reopttree->reoptnodes[id2]->childids[k] != reopttree->reoptnodes[id1]->childids[c]);
    3520 }
    3521#endif
    3522
    3523 reopttree->reoptnodes[id2]->childids[nchilds_id2+c] = reopttree->reoptnodes[id1]->childids[c];
    3524 }
    3525
    3526 /* update the number of childs */
    3527 reopttree->reoptnodes[id1]->nchilds = 0;
    3528 reopttree->reoptnodes[id2]->nchilds += nchilds_id1;
    3529
    3530 return SCIP_OKAY;
    3531}
    3532
    3533/** change all bound changes along the root path */
    3534static
    3536 SCIP_REOPT* reopt, /**< reoptimization data structure */
    3537 SCIP_SET* set, /**< global SCIP settings */
    3538 SCIP_STAT* stat, /**< dynamic problem statistics */
    3539 SCIP_PROB* transprob, /**< transformed problem */
    3540 SCIP_PROB* origprob, /**< original problem */
    3541 SCIP_TREE* tree, /**< search tree */
    3542 SCIP_LP* lp, /**< current LP */
    3543 SCIP_BRANCHCAND* branchcand, /**< branching candidates */
    3544 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    3545 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    3546 SCIP_CLIQUETABLE* cliquetable, /**< clique table */
    3547 BMS_BLKMEM* blkmem, /**< block memory */
    3548 SCIP_NODE* node, /**< node of the branch and bound tree */
    3549 unsigned int id, /**< id of stored node */
    3550 SCIP_Bool afterdualbranching /**< convert all bound changes made directly after the first bound
    3551 * changes based on dual information into normal branchings */
    3552 )
    3553{
    3554 SCIP_REOPTTREE* reopttree;
    3555 SCIP_REOPTNODE* reoptnode;
    3556
    3557 assert(reopt != NULL);
    3558 assert(set != NULL);
    3559 assert(stat != NULL);
    3560 assert(transprob != NULL);
    3561 assert(tree != NULL);
    3562 assert(lp != NULL);
    3563 assert(branchcand != NULL);
    3564 assert(eventqueue != NULL);
    3565 assert(cliquetable != NULL);
    3566 assert(node != NULL);
    3567 assert(blkmem != NULL);
    3568
    3569 reopttree = reopt->reopttree;
    3570 assert(reopttree != NULL);
    3571 assert(id < reopttree->reoptnodessize);
    3572
    3573 reoptnode = reopttree->reoptnodes[id];
    3574 assert(reoptnode != NULL);
    3575
    3576 /* copy memory to ensure that only original variables are saved */
    3577 if( reoptnode->nvars == 0 && reoptnode->nafterdualvars == 0)
    3578 return SCIP_OKAY;
    3579
    3580 /* change the bounds along the branching path */
    3581 for( int v = 0; v < reoptnode->nvars; ++v )
    3582 {
    3583 SCIP_VAR* var;
    3584 SCIP_Real val;
    3585 SCIP_BOUNDTYPE boundtype;
    3586 SCIP_Real oldlb;
    3587 SCIP_Real oldub;
    3588 SCIP_Real newbound;
    3589
    3590 var = reoptnode->vars[v];
    3591 val = reoptnode->varbounds[v];
    3592 boundtype = reoptnode->varboundtypes[v];
    3593
    3594 assert(SCIPvarIsOriginal(var));
    3595 SCIP_CALL( SCIPvarGetProbvarBound(&var, &val, &boundtype) );
    3596 assert(SCIPvarIsTransformed(var));
    3598
    3599 oldlb = SCIPvarGetLbLocal(var);
    3600 oldub = SCIPvarGetUbLocal(var);
    3601 newbound = val;
    3602
    3603 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
    3604
    3605 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, oldlb) && SCIPsetIsFeasLE(set, newbound, oldub) )
    3606 {
    3607 SCIPvarAdjustLb(var, set, &newbound);
    3608
    3609 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    3610 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
    3611 }
    3612 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, oldub) && SCIPsetIsFeasGE(set, newbound, oldlb) )
    3613 {
    3614 SCIPvarAdjustUb(var, set, &newbound);
    3615
    3616 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    3617 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
    3618 }
    3619#ifdef SCIP_MORE_DEBUG
    3620 SCIPsetDebugMsg(set, " (path) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=", newbound);
    3621#endif
    3622 }
    3623
    3624 if( afterdualbranching && reoptnode->nafterdualvars > 0 )
    3625 {
    3626 /* check the memory to convert this bound changes into 'normal' */
    3627 SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], set, blkmem,
    3628 reoptnode->nvars + reoptnode->nafterdualvars, 0, 0) );
    3629
    3630 /* change the bounds */
    3631 for( int v = 0; v < reoptnode->nafterdualvars; ++v )
    3632 {
    3633 SCIP_VAR* var;
    3634 SCIP_Real val;
    3635 SCIP_BOUNDTYPE boundtype;
    3636 SCIP_Bool bndchgd;
    3637 SCIP_Real oldlb;
    3638 SCIP_Real oldub;
    3639 SCIP_Real newbound;
    3640
    3641 var = reoptnode->afterdualvars[v];
    3642 val = reoptnode->afterdualvarbounds[v];
    3643 boundtype = reoptnode->afterdualvarboundtypes[v];
    3644
    3645 assert(SCIPvarIsOriginal(var));
    3646 SCIP_CALL( SCIPvarGetProbvarBound(&var, &val, &boundtype) );
    3647 assert(SCIPvarIsTransformed(var));
    3649
    3650 bndchgd = FALSE;
    3651
    3652 oldlb = SCIPvarGetLbLocal(var);
    3653 oldub = SCIPvarGetUbLocal(var);
    3654 newbound = val;
    3655
    3656 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, oldlb) && SCIPsetIsFeasLE(set, newbound, oldub) )
    3657 {
    3658 SCIPvarAdjustLb(var, set, &newbound);
    3659 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    3660 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
    3661
    3662 bndchgd = TRUE;
    3663 }
    3664 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, oldub) && SCIPsetIsFeasGE(set, newbound, oldlb) )
    3665 {
    3666 SCIPvarAdjustUb(var, set, &newbound);
    3667 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    3668 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
    3669
    3670 bndchgd = TRUE;
    3671 }
    3672
    3673 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
    3674
    3675#ifdef SCIP_MORE_DEBUG
    3676 SCIPsetDebugMsg(set, " (prop) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=", newbound);
    3677#endif
    3678 if( bndchgd )
    3679 {
    3680 int nvars;
    3681
    3682 nvars = reoptnode->nvars;
    3683 reoptnode->vars[nvars] = reoptnode->afterdualvars[v];
    3684 reoptnode->varbounds[nvars] = reoptnode->afterdualvarbounds[v];
    3685 reoptnode->varboundtypes[nvars] = reoptnode->afterdualvarboundtypes[v];
    3686 ++reoptnode->nvars;
    3687 }
    3688 }
    3689
    3690 /* free the afterdualvars, -bounds, and -boundtypes */
    3691 BMSfreeBlockMemoryArray(blkmem, &reoptnode->afterdualvarboundtypes, reoptnode->afterdualvarssize);
    3692 reoptnode->afterdualvarboundtypes = NULL;
    3693
    3694 BMSfreeBlockMemoryArray(blkmem, &reoptnode->afterdualvarbounds, reoptnode->afterdualvarssize);
    3695 reoptnode->afterdualvarbounds = NULL;
    3696
    3697 BMSfreeBlockMemoryArray(blkmem, &reoptnode->afterdualvars, reoptnode->afterdualvarssize);
    3698 reoptnode->afterdualvars = NULL;
    3699
    3700 reoptnode->nafterdualvars = 0;
    3701 reoptnode->afterdualvarssize = 0;
    3702 }
    3703
    3704 return SCIP_OKAY;
    3705}
    3706
    3707
    3708/** add a constraint to ensure that at least one variable bound gets different */
    3709static
    3711 SCIP_REOPT* reopt, /**< reoptimization data structure */
    3712 SCIP* scip, /**< SCIP data structure */
    3713 SCIP_SET* set, /**< global SCIP settings */
    3714 SCIP_STAT* stat, /**< dynamic problem statistics */
    3715 BMS_BLKMEM* blkmem, /**< block memory */
    3716 SCIP_PROB* transprob, /**< transformed problem */
    3717 SCIP_PROB* origprob, /**< original problem */
    3718 SCIP_TREE* tree, /**< search tree */
    3719 SCIP_LP* lp, /**< current LP */
    3720 SCIP_BRANCHCAND* branchcand, /**< branching candidates */
    3721 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    3722 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    3723 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    3724 SCIP_NODE* node, /**< node corresponding to the pruned part */
    3725 unsigned int id /**< id of stored node */
    3726 )
    3727{
    3728 SCIP_CONS* cons;
    3729 char name[SCIP_MAXSTRLEN];
    3730
    3731 assert(reopt != NULL);
    3732 assert(reopt->reopttree != NULL);
    3733 assert(id < reopt->reopttree->reoptnodessize);
    3734 assert(reopt->reopttree->reoptnodes[id] != NULL);
    3735 assert(reopt->reopttree->reoptnodes[id]->dualreds);
    3736 assert(reopt->reopttree->reoptnodes[id]->dualredscur != NULL);
    3737 assert(scip != NULL);
    3738 assert(set != NULL);
    3739 assert(stat != NULL);
    3740 assert(blkmem != NULL);
    3741 assert(transprob != NULL);
    3742 assert(origprob != NULL);
    3743 assert(tree != NULL);
    3744 assert(lp != NULL);
    3745 assert(branchcand != NULL);
    3746 assert(eventqueue != NULL);
    3747 assert(node != NULL);
    3748
    3749 assert(reopt->reopttree->reoptnodes[id]->dualredscur->constype == REOPT_CONSTYPE_DUALREDS
    3750 || reopt->reopttree->reoptnodes[id]->dualredscur->constype == REOPT_CONSTYPE_INFSUBTREE);
    3751
    3752#ifndef NDEBUG
    3753 if( reopt->reopttree->reoptnodes[id]->dualredscur->constype == REOPT_CONSTYPE_DUALREDS )
    3754 SCIPsetDebugMsg(set, " create a split-node #%lld\n", SCIPnodeGetNumber(node));
    3755 else
    3756 SCIPsetDebugMsg(set, " separate an infeasible subtree\n");
    3757#endif
    3758
    3759 /* if the constraint consists of exactly one variable it can be interpreted
    3760 * as a normal branching step, i.e., we can fix the variable to the negated bound */
    3761 if( reopt->reopttree->reoptnodes[id]->dualredscur->nvars == 1 )
    3762 {
    3763 SCIP_REOPTCONSDATA* reoptconsdata;
    3764 SCIP_VAR* var;
    3765 SCIP_BOUNDTYPE boundtype;
    3766 SCIP_Real oldlb;
    3767 SCIP_Real oldub;
    3768 SCIP_Real newbound;
    3769
    3770 reoptconsdata = reopt->reopttree->reoptnodes[id]->dualredscur;
    3771 assert(!reoptconsdata->linear);
    3772 assert(reoptconsdata->vars != NULL);
    3773 assert(reoptconsdata->vals != NULL);
    3774 assert(reoptconsdata->boundtypes != NULL);
    3775
    3776 var = reoptconsdata->vars[0];
    3777 newbound = reoptconsdata->vals[0];
    3778 boundtype = reoptconsdata->boundtypes[0];
    3779
    3780 assert(SCIPvarIsOriginal(var));
    3781 SCIP_CALL( SCIPvarGetProbvarBound(&var, &newbound, &boundtype) );
    3782 assert(SCIPvarIsTransformed(var));
    3783
    3784 oldlb = SCIPvarGetLbLocal(var);
    3785 oldub = SCIPvarGetUbLocal(var);
    3786
    3787 if( boundtype == SCIP_BOUNDTYPE_LOWER )
    3788 {
    3789 newbound = reoptconsdata->vals[0] - 1.0;
    3790 /* if newbound > local upper bound, the variable cannot take the old value and we exit */
    3791 if( SCIPisGT(scip, newbound, oldub) )
    3792 return SCIP_OKAY;
    3793 assert(SCIPisLE(scip, newbound, oldub));
    3794 }
    3795 else
    3796 {
    3797 newbound = reoptconsdata->vals[0] + 1.0;
    3798 /* if newbound < local lower bound, the variable cannot take the old value and we exit */
    3799 if( SCIPisLT(scip, newbound, oldlb) )
    3800 return SCIP_OKAY;
    3801 assert(SCIPisGE(scip, newbound, oldlb));
    3802 }
    3803 boundtype = (SCIP_BOUNDTYPE) (1 - (int)boundtype);
    3804 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
    3805
    3806 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, oldlb) && SCIPsetIsFeasLE(set, newbound, oldub) )
    3807 {
    3808 SCIPvarAdjustLb(var, set, &newbound);
    3809 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    3810 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
    3811 }
    3812 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, oldub) && SCIPsetIsFeasGE(set, newbound, oldlb) )
    3813 {
    3814 SCIPvarAdjustUb(var, set, &newbound);
    3815 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    3816 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
    3817 }
    3818
    3819 SCIPsetDebugMsg(set, " -> constraint consists of only one variable: <%s> %s %g\n", SCIPvarGetName(var),
    3820 boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=", newbound);
    3821 }
    3822 else
    3823 {
    3824 SCIP_REOPTCONSDATA* reoptconsdata;
    3825 SCIP_VAR** consvars;
    3826 SCIP_Real consval;
    3827 SCIP_BOUNDTYPE consboundtype;
    3828 int nbinvars = 0;
    3829#ifndef NDEBUG
    3830 int nintvars = 0;
    3831 int ncontvars = 0;
    3832#endif
    3833
    3834 reoptconsdata = reopt->reopttree->reoptnodes[id]->dualredscur;
    3835 assert(!reoptconsdata->linear);
    3836 assert(reoptconsdata->vars != NULL);
    3837 assert(reoptconsdata->vals != NULL);
    3838 assert(reoptconsdata->boundtypes != NULL);
    3839
    3840 /* allocate buffer */
    3841 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, reoptconsdata->nvars) );
    3842
    3843 /* count number of binary, integer, and continuous variables */
    3844 for( int v = 0; v < reoptconsdata->nvars; ++v )
    3845 {
    3846 if( SCIPvarIsIntegral(reoptconsdata->vars[v]) )
    3847 {
    3848 if( SCIPisEQ(scip, SCIPvarGetLbLocal(reoptconsdata->vars[v]), 0.0)
    3849 && SCIPisEQ(scip, SCIPvarGetUbLocal(reoptconsdata->vars[v]), 1.0) )
    3850 ++nbinvars;
    3851#ifndef NDEBUG
    3852 else
    3853 ++nintvars;
    3854#endif
    3855 }
    3856#ifndef NDEBUG
    3857 else
    3858 ++ncontvars;
    3859#endif
    3860 }
    3861
    3862 if( reoptconsdata->constype == REOPT_CONSTYPE_INFSUBTREE )
    3863 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_inf");
    3864 else
    3865 {
    3866 assert(reoptconsdata->constype == REOPT_CONSTYPE_DUALREDS);
    3867 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_dual");
    3868 }
    3869
    3870 /* case 1: all variables are binary, we use a logic-or constraint. */
    3871 if( reoptconsdata->nvars == nbinvars )
    3872 {
    3873 for( int v = 0; v < reoptconsdata->nvars; ++v )
    3874 {
    3875 consvars[v] = reoptconsdata->vars[v];
    3876 consval = reoptconsdata->vals[v];
    3877 consboundtype = SCIPsetIsFeasEQ(set, consval, 1.0) ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER;
    3878
    3879 assert(SCIPvarIsOriginal(consvars[v]));
    3880 SCIP_CALL( SCIPvarGetProbvarBound(&consvars[v], &consval, &consboundtype) );
    3881 assert(SCIPvarIsTransformed(consvars[v]));
    3882 assert(SCIPvarGetStatus(consvars[v]) != SCIP_VARSTATUS_MULTAGGR);
    3883
    3884 if ( SCIPsetIsFeasEQ(set, consval, 1.0) )
    3885 {
    3886 SCIP_CALL( SCIPvarNegate(consvars[v], blkmem, set, stat, &consvars[v]) );
    3887 assert(SCIPvarIsNegated(consvars[v]));
    3888 }
    3889 }
    3890
    3891 SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, reoptconsdata->nvars, consvars,
    3893 }
    3894 /* case 2: at least one variable is integer or continuous. we use a bounddisjunction constraint. */
    3895 else
    3896 {
    3897 SCIP_Real* consvals;
    3898 SCIP_BOUNDTYPE* consboundtypes;
    3899
    3900 assert(nintvars > 0 || ncontvars > 0);
    3901
    3902 /* alloc buffer memory */
    3903 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, reoptconsdata->nvars) );
    3904 SCIP_CALL( SCIPallocBufferArray(scip, &consboundtypes, reoptconsdata->nvars) );
    3905
    3906 /* iterate over all variables and transform them */
    3907 for( int v = 0; v < reoptconsdata->nvars; ++v )
    3908 {
    3909 consvars[v] = reoptconsdata->vars[v];
    3910 consvals[v] = reoptconsdata->vals[v];
    3911 consboundtypes[v] = reoptconsdata->boundtypes[v];
    3912
    3913 /* we have to switch the bounds.
    3914 * case 1: integer variable with bound x <= u is transformed to u+1 <= x
    3915 * and l <= x is transformed to x <= l-1
    3916 * case 2: continuous variable with bound x <= u is transformed to u <= x
    3917 * and l <= x is transformed to x <= l
    3918 */
    3919 if( SCIPvarIsIntegral(consvars[v]) )
    3920 {
    3921 if( consboundtypes[v] == SCIP_BOUNDTYPE_UPPER )
    3922 {
    3923 consvals[v] += 1.0;
    3924 assert(SCIPsetIsLE(set, consvals[v], SCIPvarGetUbGlobal(consvars[v])));
    3925 }
    3926 else
    3927 {
    3928 consvals[v] -= 1.0;
    3929 assert(SCIPsetIsGE(set, consvals[v], SCIPvarGetLbGlobal(consvars[v])));
    3930 }
    3931 }
    3932
    3933 consboundtypes[v] = (SCIP_BOUNDTYPE)(1 - consboundtypes[v]); /*lint !e641*/
    3934
    3935 assert(SCIPvarIsOriginal(consvars[v]));
    3936 SCIP_CALL( SCIPvarGetProbvarBound(&consvars[v], &consvals[v], &consboundtypes[v]) );
    3937 assert(SCIPvarIsTransformed(consvars[v]));
    3938 assert(SCIPvarGetStatus(consvars[v]) != SCIP_VARSTATUS_MULTAGGR);
    3939 }
    3940
    3941 /* create the constraints and add them to the corresponding nodes */
    3942 SCIP_CALL( SCIPcreateConsBounddisjunctionRedundant(scip, &cons, name, reoptconsdata->nvars, consvars, consboundtypes,
    3943 consvals, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
    3944
    3945 /* free buffer memory */
    3946 SCIPfreeBufferArray(scip, &consboundtypes);
    3947 SCIPfreeBufferArray(scip, &consvals);
    3948 }
    3949
    3950 SCIPsetDebugMsg(set, " -> add constraint in node #%lld:\n", SCIPnodeGetNumber(node));
    3951#ifdef SCIP_DEBUG_CONSS
    3953#endif
    3954
    3955 SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
    3956 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    3957
    3958 /* free buffer */
    3959 SCIPfreeBufferArray(scip, &consvars);
    3960 }
    3961
    3962 return SCIP_OKAY;
    3963}
    3964
    3965/** fix all bounds ad stored in dualredscur at the given node @p node_fix */
    3966static
    3968 SCIP_REOPT* reopt, /**< reoptimization data structure */
    3969 SCIP_SET* set, /**< global SCIP settings */
    3970 SCIP_STAT* stat, /**< dynamic problem statistics */
    3971 SCIP_PROB* transprob, /**< transformed problem */
    3972 SCIP_PROB* origprob, /**< original problem */
    3973 SCIP_TREE* tree, /**< search tree */
    3974 SCIP_LP* lp, /**< current LP */
    3975 SCIP_BRANCHCAND* branchcand, /**< branching candidates */
    3976 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    3977 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    3978 SCIP_CLIQUETABLE* cliquetable, /**< clique table */
    3979 BMS_BLKMEM* blkmem, /**< block memory */
    3980 SCIP_NODE* node, /**< node corresponding to the fixed part */
    3981 unsigned int id, /**< id of stored node */
    3982 SCIP_Bool updatedualconss /**< update constraint representing dual bound changes */
    3983 )
    3984{
    3985 SCIP_REOPTTREE* reopttree;
    3986 SCIP_REOPTNODE* reoptnode;
    3987
    3988 assert(reopt != NULL);
    3989 assert(set != NULL);
    3990 assert(stat != NULL);
    3991 assert(transprob != NULL);
    3992 assert(origprob != NULL);
    3993 assert(tree != NULL);
    3994 assert(lp != NULL);
    3995 assert(branchcand != NULL);
    3996 assert(eventqueue != NULL);
    3997 assert(cliquetable != NULL);
    3998 assert(node != NULL);
    3999 assert(blkmem != NULL);
    4000
    4001 reopttree = reopt->reopttree;
    4002 assert(reopttree != NULL);
    4003 assert(0 < id && id < reopttree->reoptnodessize);
    4004
    4005 reoptnode = reopttree->reoptnodes[id];
    4006 assert(reoptnode != NULL);
    4007 assert(reoptnode->dualreds);
    4008 assert(reoptnode->dualredscur != NULL);
    4009
    4010 /* ensure that the arrays to store the bound changes are large enough */
    4011 SCIP_CALL( reoptnodeCheckMemory(reoptnode, set, blkmem, reoptnode->nvars + reoptnode->dualredscur->nvars, 0, 0) );
    4012
    4013 for( int v = 0; v < reoptnode->dualredscur->nvars; ++v )
    4014 {
    4015 SCIP_VAR* var;
    4016 SCIP_Real val;
    4017 SCIP_BOUNDTYPE boundtype;
    4018 SCIP_Bool bndchgd;
    4019
    4020 var = reoptnode->dualredscur->vars[v];
    4021 val = reoptnode->dualredscur->vals[v];
    4022 boundtype = reoptnode->dualredscur->boundtypes[v];
    4023
    4024 SCIP_CALL( SCIPvarGetProbvarBound(&var, &val, &boundtype) );
    4025 assert(SCIPvarIsTransformedOrigvar(var));
    4026
    4027 bndchgd = FALSE;
    4028
    4029 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, val, SCIPvarGetLbLocal(var))
    4030 && SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)) )
    4031 {
    4032 SCIPvarAdjustLb(var, set, &val);
    4033 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    4034 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, val, SCIP_BOUNDTYPE_LOWER, FALSE) );
    4035
    4036 bndchgd = TRUE;
    4037 }
    4038 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var))
    4039 && SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)) )
    4040 {
    4041 SCIPvarAdjustUb(var, set, &val);
    4042 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    4043 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, val, SCIP_BOUNDTYPE_UPPER, FALSE) );
    4044
    4045 bndchgd = TRUE;
    4046 }
    4047 else if( boundtype != SCIP_BOUNDTYPE_LOWER && boundtype != SCIP_BOUNDTYPE_UPPER )
    4048 {
    4049 SCIPerrorMessage("** Unknown boundtype: %d **\n", boundtype);
    4050 return SCIP_INVALIDDATA;
    4051 }
    4052#ifdef SCIP_MORE_DEBUG
    4053 SCIPsetDebugMsg(set, " (dual) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", val);
    4054#endif
    4055 /* add variable and bound to branching path information, because we don't want to delete this data */
    4056 if( bndchgd )
    4057 {
    4058 int pos;
    4059 SCIP_Real constant;
    4060 SCIP_Real scalar;
    4061
    4062 pos = reoptnode->nvars;
    4063
    4064 reoptnode->vars[pos] = var;
    4065 scalar = 1.0;
    4066 constant = 0.0;
    4067 SCIP_CALL( SCIPvarGetOrigvarSum(&reoptnode->vars[pos], &scalar, &constant) );
    4068 assert(SCIPvarIsOriginal(reoptnode->vars[pos]));
    4069
    4070 reoptnode->varbounds[pos] = reoptnode->dualredscur->vals[v];
    4071 reoptnode->varboundtypes[pos] = (SCIPsetIsFeasEQ(set, reoptnode->varbounds[pos], 0.0) ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER);
    4072 ++reoptnode->nvars;
    4073 }
    4074 }
    4075
    4076 if( updatedualconss )
    4077 {
    4078 /* delete dualredscur and move dualredsnex -> dualredscur */
    4079 SCIP_CALL( reoptnodeUpdateDualConss(reoptnode, blkmem) );
    4080 }
    4081
    4082 return SCIP_OKAY;
    4083}
    4084
    4085/** fix all bounds corresponding to dual bound changes in a previous iteration in the fashion of interdiction branching;
    4086 * keep the first negbndchg-1 bound changes as stored in dualredscur and negate the negbndchg-th bound.
    4087 */
    4088static
    4090 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4091 SCIP_SET* set, /**< global SCIP settings */
    4092 SCIP_STAT* stat, /**< dynamic problem statistics */
    4093 SCIP_PROB* transprob, /**< transformed problem */
    4094 SCIP_PROB* origprob, /**< original problem */
    4095 SCIP_TREE* tree, /**< search tree */
    4096 SCIP_LP* lp, /**< current LP */
    4097 SCIP_BRANCHCAND* branchcand, /**< branching candidates */
    4098 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    4099 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    4100 SCIP_CLIQUETABLE* cliquetable, /**< clique table */
    4101 BMS_BLKMEM* blkmem, /**< block memory */
    4102 SCIP_NODE* node, /**< child node */
    4103 unsigned int id, /**< id of the node */
    4104 int* perm, /**< array of permuted indices */
    4105 SCIP_VAR** vars, /**< variables */
    4106 SCIP_Real* vals, /**< bounds */
    4107 SCIP_BOUNDTYPE* boundtypes, /**< boundtypes */
    4108 int nvars, /**< number of variables */
    4109 int negbndchg /**< index of the variable that should negated */
    4110 )
    4111{
    4112 SCIP_VAR* var;
    4113 SCIP_Real val;
    4114 SCIP_BOUNDTYPE boundtype;
    4115 int nbndchgs;
    4116
    4117 assert(reopt != NULL);
    4118 assert(set != NULL);
    4119 assert(stat != NULL);
    4120 assert(transprob != NULL);
    4121 assert(origprob != NULL);
    4122 assert(tree != NULL);
    4123 assert(lp != NULL);
    4124 assert(branchcand != NULL);
    4125 assert(eventqueue != NULL);
    4126 assert(cliquetable != NULL);
    4127 assert(node != NULL);
    4128 assert(perm != NULL);
    4129 assert(vars != NULL);
    4130 assert(vals != NULL);
    4131 assert(boundtypes != NULL);
    4132 assert(nvars >= 0);
    4133 assert(blkmem != NULL);
    4134 assert(0 < id && id < reopt->reopttree->reoptnodessize);
    4135
    4136#ifndef NDEBUG
    4137 {
    4138 SCIP_REOPTTREE* reopttree;
    4139 SCIP_REOPTNODE* reoptnode;
    4140
    4141 reopttree = reopt->reopttree;
    4142 assert(reopttree != NULL);
    4143
    4144 reoptnode = reopttree->reoptnodes[id];
    4145 assert(reoptnode != NULL);
    4146 assert(reoptnode->dualreds);
    4147 }
    4148#endif
    4149
    4150 nbndchgs = MIN(negbndchg, nvars);
    4151
    4152 /* change the first nbndchg-1 bounds as stored in dualredscur and negate the negbndchg-th bound */
    4153 for( int v = 0; v < nbndchgs; ++v )
    4154 {
    4155 var = vars[perm[v]];
    4156 val = vals[perm[v]];
    4157 boundtype = boundtypes[perm[v]];
    4158
    4159 SCIP_CALL( SCIPvarGetProbvarBound(&var, &val, &boundtype) );
    4160 assert(SCIPvarIsTransformedOrigvar(var));
    4161
    4162 /* negate the last bound change */
    4163 if( v == nbndchgs-1 )
    4164 {
    4165 boundtype = (SCIP_BOUNDTYPE)(SCIP_BOUNDTYPE_UPPER - boundtype); /*lint !e656*/
    4166 if( SCIPvarIsIntegral(var) && boundtype == SCIP_BOUNDTYPE_UPPER )
    4167 val = val - 1.0;
    4168 else if( SCIPvarIsIntegral(var) && boundtype == SCIP_BOUNDTYPE_LOWER )
    4169 val = val + 1.0;
    4170 }
    4171
    4172 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, val, SCIPvarGetLbLocal(var))
    4173 && SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)) )
    4174 {
    4175 SCIPvarAdjustLb(var, set, &val);
    4176 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    4177 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, val, SCIP_BOUNDTYPE_LOWER, FALSE) );
    4178 }
    4179 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var))
    4180 && SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)) )
    4181 {
    4182 SCIPvarAdjustUb(var, set, &val);
    4183 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    4184 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, val, SCIP_BOUNDTYPE_UPPER, FALSE) );
    4185 }
    4186 else if( boundtype != SCIP_BOUNDTYPE_LOWER && boundtype != SCIP_BOUNDTYPE_UPPER )
    4187 {
    4188 SCIPerrorMessage("** Unknown boundtype: %d **\n", boundtype);
    4189 return SCIP_INVALIDDATA;
    4190 }
    4191#ifdef SCIP_MORE_DEBUG
    4192 SCIPsetDebugMsg(set, " (dual) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", val);
    4193#endif
    4194 }
    4195
    4196 return SCIP_OKAY;
    4197}
    4198
    4199/** add all constraints stored at @p id to the given nodes @p node_fix and @p node_cons */
    4200static
    4202 SCIP* scip, /**< SCIP data structure */
    4203 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4204 SCIP_SET* set, /**< global SCIP settings */
    4205 SCIP_STAT* stat, /**< dynamic problem statistics */
    4206 BMS_BLKMEM* blkmem, /**< block memory */
    4207 SCIP_NODE* node, /**< node of the branch and bound tree*/
    4208 unsigned int id /**< id of stored node */
    4209 )
    4210{
    4211 char name[SCIP_MAXSTRLEN];
    4212
    4213 assert(scip != NULL);
    4214 assert(reopt != NULL);
    4215 assert(reopt->reopttree != NULL);
    4216 assert(set != NULL);
    4217 assert(stat != NULL);
    4218 assert(blkmem != NULL);
    4219 assert(node != NULL);
    4220 assert(0 < id && id < reopt->reopttree->reoptnodessize);
    4221
    4222 if( reopt->reopttree->reoptnodes[id]->nconss == 0 )
    4223 return SCIP_OKAY;
    4224
    4225 SCIPsetDebugMsg(set, " -> add %d constraint(s) to node #%lld:\n", reopt->reopttree->reoptnodes[id]->nconss,
    4226 SCIPnodeGetNumber(node));
    4227
    4228 for( int c = 0; c < reopt->reopttree->reoptnodes[id]->nconss; ++c )
    4229 {
    4230 SCIP_CONS* cons;
    4231 SCIP_REOPTCONSDATA* reoptconsdata;
    4232
    4233 reoptconsdata = reopt->reopttree->reoptnodes[id]->conss[c];
    4234 assert(reoptconsdata != NULL);
    4235 assert(reoptconsdata->nvars > 0);
    4236 assert(reoptconsdata->varssize >= reoptconsdata->nvars);
    4237
    4238 if( reoptconsdata->constype == REOPT_CONSTYPE_CUT )
    4239 continue;
    4240
    4241 if( reoptconsdata->constype == REOPT_CONSTYPE_INFSUBTREE )
    4242 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_inf");
    4243 else if( reoptconsdata->constype == REOPT_CONSTYPE_DUALREDS )
    4244 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_dual");
    4245 else
    4246 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_unkn");
    4247
    4248 if( reoptconsdata->linear )
    4249 {
    4250 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, name, reoptconsdata->nvars, reoptconsdata->vars, reoptconsdata->vals,
    4251 reoptconsdata->lhs, reoptconsdata->rhs, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
    4252 }
    4253 else
    4254 {
    4255 assert(reoptconsdata->boundtypes != NULL);
    4256 SCIP_CALL( SCIPcreateConsBounddisjunctionRedundant(scip, &cons, name, reoptconsdata->nvars, reoptconsdata->vars, reoptconsdata->boundtypes,
    4257 reoptconsdata->vals, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
    4258 }
    4259#ifdef SCIP_DEBUG_CONSS
    4261#endif
    4262 SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
    4263 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    4264 }
    4265
    4266 return SCIP_OKAY;
    4267}
    4268
    4269/** reset the internal statistics at the beginning of a new iteration */
    4270static
    4272 SCIP_REOPT* reopt /**< reoptimization data structure */
    4273 )
    4274{
    4275 assert(reopt != NULL);
    4276
    4277 reopt->lastbranched = -1;
    4278 reopt->currentnode = -1;
    4279 reopt->lastseennode = -1;
    4280 reopt->reopttree->nfeasnodes = 0;
    4281 reopt->reopttree->ninfnodes = 0;
    4282 reopt->reopttree->nprunednodes = 0;
    4283 reopt->reopttree->ncutoffreoptnodes = 0;
    4284
    4285 if( reopt->dualreds != NULL )
    4286 reopt->dualreds->nvars = 0;
    4287}
    4288
    4289/** check the stored bound changes of all child nodes for redundancy and infeasibility
    4290 *
    4291 * Due to strongbranching initialization at node stored at @p id it can happen, that some bound changes stored in the
    4292 * child nodes of the reoptimization node stored at @p id become redundant or make the subproblem infeasible. in this
    4293 * method we remove all redundant bound changes and delete infeasible child nodes.
    4294 */
    4295static
    4297 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4298 SCIP_SET* set, /**< global SCIP settings */
    4299 BMS_BLKMEM* blkmem, /**< block memory */
    4300 SCIP_Bool* runagain, /**< pointer to store of this method should run again */
    4301 unsigned int id /**< id of stored node */
    4302 )
    4303{
    4304 SCIP_REOPTNODE* reoptnode;
    4305 unsigned int* cutoffchilds;
    4306 int ncutoffchilds = 0;
    4307 unsigned int* redchilds;
    4308 int nredchilds = 0;
    4309 int c;
    4310
    4311 assert(reopt != NULL);
    4312 assert(reopt->reopttree != NULL);
    4313 assert(id < reopt->reopttree->reoptnodessize);
    4314 assert(reopt->reopttree->reoptnodes != NULL);
    4315 assert(reopt->reopttree->reoptnodes[id] != NULL);
    4316
    4317 reoptnode = reopt->reopttree->reoptnodes[id];
    4318
    4319 *runagain = FALSE;
    4320
    4321 SCIPsetDebugMsg(set, "start dry branching of node at ID %u\n", id);
    4322
    4323 /* allocate buffer arrays */
    4324 SCIP_CALL( SCIPsetAllocBufferArray(set, &cutoffchilds, reoptnode->nchilds) );
    4325 SCIP_CALL( SCIPsetAllocBufferArray(set, &redchilds, reoptnode->nchilds) );
    4326
    4327 /* iterate over all child nodes and check each bound changes
    4328 * for redundancy and conflict */
    4329 for( c = 0; c < reoptnode->nchilds; ++c )
    4330 {
    4331 SCIP_REOPTNODE* child;
    4332 SCIP_Bool cutoff;
    4333 SCIP_Bool redundant;
    4334 int* redundantvars;
    4335 int nredundantvars;
    4336 unsigned int childid;
    4337
    4338 cutoff = FALSE;
    4339 redundant = FALSE;
    4340 nredundantvars = 0;
    4341
    4342 childid = reoptnode->childids[c];
    4343 assert(childid < reopt->reopttree->reoptnodessize);
    4344 child = reopt->reopttree->reoptnodes[childid];
    4345 assert(child != NULL);
    4346#ifdef SCIP_MORE_DEBUG
    4347 SCIPsetDebugMsg(set, "-> check child at ID %d (%d vars, %d conss):\n", childid, child->nvars, child->nconss);
    4348#endif
    4349 if( child->nvars > 0 )
    4350 {
    4351 /* allocate buffer memory to store the redundant variables */
    4352 SCIP_CALL( SCIPsetAllocBufferArray(set, &redundantvars, child->nvars) );
    4353
    4354 for( int v = 0; v < child->nvars && !cutoff; ++v )
    4355 {
    4356 SCIP_VAR* transvar;
    4357 SCIP_Real transval;
    4358 SCIP_BOUNDTYPE transbndtype;
    4359 SCIP_Real ub;
    4360 SCIP_Real lb;
    4361
    4362 transvar = child->vars[v];
    4363 transval = child->varbounds[v];
    4364 transbndtype = child->varboundtypes[v];
    4365
    4366 /* transform into the transformed space */
    4367 SCIP_CALL( SCIPvarGetProbvarBound(&transvar, &transval, &transbndtype) );
    4368
    4369 lb = SCIPvarGetLbLocal(transvar);
    4370 ub = SCIPvarGetUbLocal(transvar);
    4371
    4372 /* check for infeasibility */
    4373 if( SCIPsetIsFeasEQ(set, lb, ub) && !SCIPsetIsFeasEQ(set, lb, transval) )
    4374 {
    4375 SCIPsetDebugMsg(set, " -> <%s> is fixed to %g, can not change bound to %g -> cutoff\n",
    4376 SCIPvarGetName(transvar), lb, transval);
    4377
    4378 cutoff = TRUE;
    4379 break;
    4380 }
    4381
    4382 /* check for redundancy */
    4383 if( SCIPsetIsFeasEQ(set, lb, ub) && SCIPsetIsFeasEQ(set, lb, transval) )
    4384 {
    4385 SCIPsetDebugMsg(set, " -> <%s> is already fixed to %g -> redundant bound change\n",
    4386 SCIPvarGetName(transvar), lb);
    4387
    4388 redundantvars[nredundantvars] = v;
    4389 ++nredundantvars;
    4390 }
    4391 }
    4392
    4393 if( !cutoff && nredundantvars > 0 )
    4394 {
    4395 for( int v = 0; v < nredundantvars; ++v )
    4396 {
    4397 /* replace the redundant variable by the last stored variable */
    4398 child->vars[redundantvars[v]] = child->vars[child->nvars-1];
    4399 child->varbounds[redundantvars[v]] = child->varbounds[child->nvars-1];
    4400 child->varboundtypes[redundantvars[v]] = child->varboundtypes[child->nvars-1];
    4401 --child->nvars;
    4402 }
    4403 }
    4404
    4405 /* free buffer memory */
    4406 SCIPsetFreeBufferArray(set, &redundantvars);
    4407 }
    4408 else if( child->nconss == 0 )
    4409 {
    4410 redundant = TRUE;
    4411 SCIPsetDebugMsg(set, " -> redundant node found.\n");
    4412 }
    4413
    4414 if( cutoff )
    4415 {
    4416 cutoffchilds[ncutoffchilds] = childid;
    4417 ++ncutoffchilds;
    4418 }
    4419 else if( redundant )
    4420 {
    4421 redchilds[nredchilds] = childid;
    4422 ++nredchilds;
    4423 }
    4424 }
    4425
    4426 SCIPsetDebugMsg(set, "-> found %d redundant and %d infeasible nodes\n", nredchilds, ncutoffchilds);
    4427
    4428 /* delete all nodes that can be cut off */
    4429 while( ncutoffchilds > 0 )
    4430 {
    4431 /* delete the node and the induced subtree */
    4432 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, cutoffchilds[ncutoffchilds-1], TRUE, TRUE) );
    4433
    4434 /* find the position in the childid array */
    4435 c = 0;
    4436 while( c < reoptnode->nchilds && reoptnode->childids[c] != cutoffchilds[ncutoffchilds-1] )
    4437 ++c;
    4438 assert(reoptnode->childids[c] == cutoffchilds[ncutoffchilds-1]);
    4439
    4440 /* replace the ID at position c by the last ID */
    4441 reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
    4442 --reoptnode->nchilds;
    4443
    4444 /* decrease the number of nodes to cutoff */
    4445 --ncutoffchilds;
    4446 }
    4447
    4448 /* replace all redundant nodes their child nodes or cutoff the node if it is a leaf */
    4449 while( nredchilds > 0 )
    4450 {
    4451 /* find the position in the childid array */
    4452 c = 0;
    4453 while( c < reoptnode->nchilds && reoptnode->childids[c] != redchilds[nredchilds-1] )
    4454 ++c;
    4455 assert(reoptnode->childids[c] == redchilds[nredchilds-1]);
    4456
    4457 /* the node is a leaf and we can cutoff them */
    4458 if( reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->nchilds == 0 )
    4459 {
    4460 /* delete the node and the induced subtree */
    4461 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, redchilds[nredchilds-1], TRUE, TRUE) );
    4462
    4463 /* replace the ID at position c by the last ID */
    4464 reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
    4465 --reoptnode->nchilds;
    4466
    4467 /* decrease the number of redundant nodes */
    4468 --nredchilds;
    4469 }
    4470 else
    4471 {
    4472 int ncc;
    4473
    4474 /* replace the ID at position c by the last ID */
    4475 reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
    4476 --reoptnode->nchilds;
    4477
    4478 ncc = reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->nchilds;
    4479
    4480 /* check the memory */
    4481 SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[id], set, blkmem, 0, reoptnode->nchilds+ncc, 0) );
    4482
    4483 /* add all IDs of child nodes to the current node */
    4484 for( int cc = 0; cc < ncc; ++cc )
    4485 {
    4486 reoptnode->childids[reoptnode->nchilds] = reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->childids[cc];
    4487 ++reoptnode->nchilds;
    4488 }
    4489
    4490 /* delete the redundant node */
    4491 SCIP_CALL( reopttreeDeleteNode(reopt->reopttree, set, blkmem, redchilds[nredchilds-1], TRUE) );
    4492 SCIP_CALL( SCIPqueueInsertUInt(reopt->reopttree->openids, redchilds[nredchilds-1]) );
    4493
    4494 /* decrease the number of redundant nodes */
    4495 --nredchilds;
    4496
    4497 /* update the flag to rerun this method */
    4498 *runagain = TRUE;
    4499 }
    4500 }
    4501
    4502 /* free buffer arrays */
    4503 SCIPsetFreeBufferArray(set, &redchilds);
    4504 SCIPsetFreeBufferArray(set, &cutoffchilds);
    4505
    4506 return SCIP_OKAY;
    4507}
    4508
    4509/** return the number of all nodes in the subtree induced by the reoptimization node stored at @p id */
    4510static
    4512 SCIP_REOPTTREE* reopttree, /**< reopttree */
    4513 unsigned int id /**< id of stored node */
    4514 )
    4515{
    4516 int nnodes = 0;
    4517
    4518 assert(reopttree != NULL);
    4519 assert(id < reopttree->reoptnodessize);
    4520
    4521 for( int i = 0; i < reopttree->reoptnodes[id]->nchilds; ++i )
    4522 nnodes += reopttreeGetNNodes(reopttree, reopttree->reoptnodes[id]->childids[i]);
    4523
    4524 return nnodes + 1;
    4525}
    4526
    4527/** returns the number of leaf nodes of the induced subtree */
    4528static
    4530 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4531 unsigned int id /**< id of stored node */
    4532 )
    4533{
    4534 int nleaves = 0;
    4535
    4536 assert(reopt != NULL);
    4537 assert(id < reopt->reopttree->reoptnodessize);
    4538 assert(reopt->reopttree->reoptnodes[id] != NULL);
    4539
    4540 /* iterate over all child nods and check whether they are leaves or not */
    4541 for( int i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
    4542 {
    4543 unsigned int childid;
    4544
    4545 childid = reopt->reopttree->reoptnodes[id]->childids[i];
    4546 assert(childid < reopt->reopttree->reoptnodessize);
    4547
    4548 if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
    4549 ++nleaves;
    4550 else
    4551 nleaves += reoptGetNLeaves(reopt, childid);
    4552 }
    4553
    4554 return nleaves;
    4555}
    4556
    4557/** returns all leaves of the subtree induced by the node stored at @p id*/
    4558static
    4560 SCIP_REOPT* reopt, /**< reoptimization data structure*/
    4561 unsigned int id, /**< id of stored node */
    4562 unsigned int* leaves, /**< array of leave nodes */
    4563 int leavessize, /**< size of leaves array */
    4564 int* nleaves /**< pointer to store the number of leave nodes */
    4565 )
    4566{
    4567 assert(reopt != NULL);
    4568 assert(leavessize > 0 && leaves != NULL);
    4569 assert((*nleaves) >= 0);
    4570 assert(id < reopt->reopttree->reoptnodessize);
    4571 assert(reopt->reopttree->reoptnodes[id] != NULL);
    4572
    4573 for( int i = 0, l = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
    4574 {
    4575 unsigned int childid;
    4576
    4577 assert(*nleaves <= leavessize);
    4578
    4579 childid = reopt->reopttree->reoptnodes[id]->childids[i];
    4580 assert(childid < reopt->reopttree->reoptnodessize);
    4581
    4582 if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
    4583 {
    4584 leaves[l] = reopt->reopttree->reoptnodes[id]->childids[i];
    4585 ++l;
    4586 ++(*nleaves);
    4587 }
    4588 else
    4589 {
    4590 int nleaves2 = 0;
    4591
    4592 SCIP_CALL( reoptGetLeaves(reopt, childid, &leaves[l], leavessize - l, &nleaves2) );
    4593 l += nleaves2;
    4594 (*nleaves) += nleaves2;
    4595 }
    4596 }
    4597
    4598 return SCIP_OKAY;
    4599}
    4600
    4601/** after restarting the reoptimization and an after compressing the search tree we have to delete all stored information */
    4602static
    4604 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4605 SCIP_SET* set, /**< global SCIP settings */
    4606 BMS_BLKMEM* blkmem, /**< block memory */
    4607 SCIP_Bool softreset /**< mark the nodes to overwriteable (TRUE) or delete them completely (FALSE) */
    4608 )
    4609{
    4610 assert(reopt != NULL);
    4611 assert(set != NULL);
    4612 assert(blkmem != NULL);
    4613
    4614 /* clear the tree */
    4615 SCIP_CALL( clearReoptnodes(reopt->reopttree, set, blkmem, softreset) );
    4616 assert(reopt->reopttree->nreoptnodes == 0);
    4617
    4618 /* reset the dual constraint */
    4619 if( reopt->dualreds != NULL )
    4620 reopt->dualreds->nvars = 0;
    4621
    4622 reopt->currentnode = -1;
    4623
    4624 return SCIP_OKAY;
    4625}
    4626
    4627/** restart the reoptimization by removing all stored information about nodes and increase the number of restarts */
    4628static
    4630 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4631 SCIP_SET* set, /**< global SCIP settings */
    4632 BMS_BLKMEM* blkmem /**< block memory */
    4633 )
    4634{
    4635 assert(reopt != NULL);
    4636 assert(reopt->reopttree != NULL);
    4637 assert(set != NULL);
    4638 assert(blkmem != NULL);
    4639
    4640 /* clear the tree */
    4641 SCIP_CALL( reoptResetTree(reopt, set, blkmem, FALSE) );
    4642 assert(reopt->reopttree->nreoptnodes == 0);
    4643
    4644 /* allocate memory for the root node */
    4645 SCIP_CALL( createReoptnode(reopt->reopttree, set, blkmem, 0) );
    4646
    4647 reopt->nglbrestarts += 1;
    4648
    4649 if( reopt->firstrestart == -1 )
    4650 reopt->firstrestart = reopt->run;
    4651
    4652 reopt->lastrestart = reopt->run;
    4653
    4654 return SCIP_OKAY;
    4655}
    4656
    4657/** save the new objective function */
    4658static
    4660 SCIP_REOPT* reopt, /**< reoptimization data */
    4661 SCIP_SET* set, /**< global SCIP settings */
    4662 BMS_BLKMEM* blkmem, /**< block memory */
    4663 SCIP_VAR** origvars, /**< original problem variables */
    4664 int norigvars /**< number of original problem variables */
    4665 )
    4666{
    4667 int probidx;
    4668
    4669 assert(reopt != NULL);
    4670 assert(set != NULL);
    4671 assert(blkmem != NULL);
    4672 assert(origvars != NULL);
    4673 assert(norigvars >= 0);
    4674
    4675 /* check memory */
    4676 SCIP_CALL( ensureRunSize(reopt, set, reopt->run, blkmem) );
    4677
    4678 /* get memory and check whether we have to resize all previous objectives */
    4679 if( reopt->nobjvars < norigvars )
    4680 {
    4681 for( int i = 0; i < reopt->run-1; ++i )
    4682 {
    4683 SCIP_ALLOC( BMSreallocMemoryArray(&reopt->objs[i], norigvars) ); /*lint !e866*/
    4684 for( int v = reopt->nobjvars-1; v < norigvars; ++v )
    4685 reopt->objs[i][v] = 0.0;
    4686 }
    4687 reopt->nobjvars = norigvars;
    4688 }
    4689 SCIP_ALLOC( BMSallocClearMemoryArray(&reopt->objs[reopt->run-1], reopt->nobjvars) ); /*lint !e866*/
    4690
    4691 /* save coefficients */
    4692 for( int v = 0; v < norigvars; ++v )
    4693 {
    4694 assert(SCIPvarIsOriginal(origvars[v]));
    4695
    4696 probidx = SCIPvarGetIndex(origvars[v]);
    4697
    4698 /* it can happen that the index is greater than the number of problem variables,
    4699 * i.e., not all created variables were added
    4700 */
    4701 if( probidx >= reopt->nobjvars )
    4702 {
    4703 int newsize = SCIPsetCalcMemGrowSize(set, probidx+1);
    4704 for( int i = 0; i < reopt->run; ++i )
    4705 {
    4706 SCIP_ALLOC( BMSreallocMemoryArray(&reopt->objs[i], newsize) ); /*lint !e866*/
    4707 for( int j = reopt->nobjvars; j < newsize; ++j )
    4708 reopt->objs[i][j] = 0.0;
    4709 }
    4710 reopt->nobjvars = newsize;
    4711 }
    4712 assert(0 <= probidx && probidx < reopt->nobjvars);
    4713
    4714 reopt->objs[reopt->run-1][probidx] = SCIPvarGetObj(origvars[v]);
    4715
    4716 /* update flag to remember if the objective function has changed */
    4717 if( !reopt->objhaschanged && reopt->run >= 2
    4718 && ! SCIPsetIsEQ(set, reopt->objs[reopt->run-2][probidx], reopt->objs[reopt->run-1][probidx]) )
    4719 reopt->objhaschanged = TRUE;
    4720
    4721 /* mark this objective as the first non empty */
    4722 if( reopt->firstobj == -1 && reopt->objs[reopt->run-1][probidx] != 0 )
    4723 reopt->firstobj = reopt->run-1;
    4724 }
    4725
    4726 /* calculate similarity to last objective */
    4727 if( reopt->run-1 >= 1 )
    4728 {
    4729 /* calculate similarity to last objective */
    4730 reopt->simtolastobj = reoptSimilarity(reopt, set, reopt->run-1, reopt->run-2, origvars, norigvars);
    4731
    4732 if( reopt->simtolastobj == SCIP_INVALID ) /*lint !e777*/
    4733 return SCIP_INVALIDRESULT;
    4734
    4735 SCIPverbMessage(set->scip, SCIP_VERBLEVEL_HIGH, NULL, "new objective has similarity of %g compared to previous.\n",
    4736 reopt->simtolastobj);
    4737 }
    4738
    4739 SCIPsetDebugMsg(set, "saved obj for run %d.\n", reopt->run);
    4740
    4741 return SCIP_OKAY;
    4742}
    4743
    4744/** orders the variable by inference score */
    4745static
    4747 SCIP_SET* set, /**< global SCIP settings */
    4748 SCIP_STAT* stat, /**< dynamic problem statistics */
    4749 int* perm, /**< array of indices that need to be permuted */
    4750 SCIP_VAR** vars, /**< variable array to permute */
    4751 SCIP_Real* bounds, /**< bound array to permute in the same order */
    4752 SCIP_BOUNDTYPE* boundtypes, /**< boundtype array to permute in the same order */
    4753 int nvars /**< number of variables */
    4754 )
    4755{
    4756 SCIP_Real* infscore;
    4757
    4758 assert(set != NULL);
    4759 assert(perm != NULL);
    4760 assert(vars != NULL);
    4761 assert(bounds != NULL);
    4762 assert(boundtypes != NULL);
    4763 assert(nvars >= 0);
    4764
    4765 /* allocate buffer for the scores */
    4766 SCIP_CALL( SCIPsetAllocBufferArray(set, &infscore, nvars) );
    4767
    4768 for( int v = 0; v < nvars; ++v )
    4769 {
    4770 if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER )
    4771 {
    4772 infscore[v] = 0.75 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_UPWARDS)
    4773 + 0.25 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_DOWNWARDS);
    4774 }
    4775 else
    4776 {
    4777 infscore[v] = 0.25 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_UPWARDS)
    4778 + 0.75 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_DOWNWARDS);
    4779 }
    4780 }
    4781
    4782 /* permute indices by inference score */
    4783 SCIPsortDownRealInt(infscore, perm, nvars);
    4784
    4785 /* free buffer */
    4786 SCIPsetFreeBufferArray(set, &infscore);
    4787
    4788 return SCIP_OKAY;
    4789}
    4790
    4791/** create a global constraint to separate the given solution */
    4792static
    4794 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4795 BMS_BLKMEM* blkmem, /**< block memory */
    4796 SCIP_SET* set, /**< global SCIP settings */
    4797 SCIP_STAT* stat, /**< dynamic SCIP statistics */
    4798 SCIP_SOL* sol, /**< solution to separate */
    4799 SCIP_VAR** vars, /**< array of original problem variables */
    4800 int nvars /**< number of original problem variables */
    4801 )
    4802{
    4803 SCIP_VAR** origvars;
    4804 SCIP_Real* vals;
    4805 int nintvars;
    4806 int nbinvars;
    4807 int w;
    4808
    4809 assert(reopt != NULL);
    4810 assert(sol != NULL);
    4811 assert(blkmem != NULL);
    4812 assert(set != NULL);
    4813 assert(stat != NULL);
    4814 assert(vars != NULL);
    4815 assert(nvars != 0);
    4816 assert(SCIPsolIsOriginal(sol));
    4817
    4818 /* allocate buffer memory */
    4819 SCIP_CALL( SCIPsetAllocBufferArray(set, &origvars, nvars) );
    4820 SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, nvars) );
    4821
    4822 nbinvars = 0;
    4823 nintvars = 0;
    4824 w = 0;
    4825
    4826 /* get the solution values of the variables */
    4827 for( int v = 0; v < nvars; ++v )
    4828 {
    4829 assert(SCIPvarIsOriginal(vars[v]));
    4830 assert(nbinvars + nintvars == w);
    4831
    4832 /* we do not want to create cuts for continuous variables */
    4833 if( !SCIPvarIsIntegral(vars[v]) )
    4834 continue;
    4835
    4836 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(vars[v]) )
    4837 ++nbinvars;
    4838 else
    4839 ++nintvars;
    4840
    4841 origvars[v] = vars[v];
    4842 assert(origvars[v] != NULL);
    4843 assert(SCIPvarIsOriginal(origvars[v]));
    4844
    4845 vals[w] = SCIPsolGetVal(sol, set, stat, origvars[v]);
    4846 ++w;
    4847 }
    4848
    4849 SCIP_CALL( addGlobalCut(reopt, blkmem, set, origvars, vals, NULL, w, nbinvars, nintvars) );
    4850
    4851 /* free buffer memory */
    4853 SCIPsetFreeBufferArray(set, &origvars);
    4854
    4855 return SCIP_OKAY;
    4856}
    4857
    4858/*
    4859 * public methods
    4860 */
    4861
    4862/* ---------------- methods of general reoptimization ---------------- */
    4863
    4864/* In debug mode, the following methods are implemented as function calls to ensure
    4865 * type validity.
    4866 * In optimized mode, the methods are implemented as defines to improve performance.
    4867 * However, we want to have them in the library anyways, so we have to undef the defines.
    4868 */
    4869
    4870#undef SCIPreoptGetNRestartsGlobal
    4871#undef SCIPreoptGetNRestartsLocal
    4872#undef SCIPreoptGetNTotalRestartsLocal
    4873#undef SCIPreoptGetFirstRestarts
    4874#undef SCIPreoptGetLastRestarts
    4875#undef SCIPreoptGetNFeasNodes
    4876#undef SCIPreoptGetNTotalFeasNodes
    4877#undef SCIPreoptGetNPrunedNodes
    4878#undef SCIPreoptGetNTotalPrunedNodes
    4879#undef SCIPreoptGetNCutoffReoptnodes
    4880#undef SCIPreoptGetNTotalCutoffReoptnodes
    4881#undef SCIPreoptGetNInfNodes
    4882#undef SCIPreoptGetNTotalInfNodes
    4883#undef SCIPreoptGetNInfSubtrees
    4884
    4885
    4886/** returns the number of global restarts */
    4888 SCIP_REOPT* reopt /**< reoptimization data structure */
    4889 )
    4890{
    4891 assert(reopt != NULL);
    4892
    4893 return reopt->nglbrestarts;
    4894}
    4895
    4896/** returns the number of local restarts in the current run */
    4898 SCIP_REOPT* reopt /**< reoptimization data structure */
    4899 )
    4900{
    4901 assert(reopt != NULL);
    4902
    4903 return reopt->nlocrestarts;
    4904}
    4905
    4906/** returns the number of local restarts over all runs */
    4908 SCIP_REOPT* reopt /**< reoptimization data structure */
    4909 )
    4910{
    4911 assert(reopt != NULL);
    4912
    4913 return reopt->ntotallocrestarts;
    4914}
    4915
    4916/** returns the number of iteration with the first global restarts */
    4918 SCIP_REOPT* reopt /**< reoptimization data structure */
    4919 )
    4920{
    4921 assert(reopt != NULL);
    4922
    4923 return reopt->firstrestart;
    4924}
    4925
    4926/** returns the number of iteration with the last global restarts */
    4928 SCIP_REOPT* reopt /**< reoptimization data structure */
    4929 )
    4930{
    4931 assert(reopt != NULL);
    4932
    4933 return reopt->lastrestart;
    4934}
    4935
    4936/** returns the number of stored nodes providing an improving feasible LP solution in the current run */
    4938 SCIP_REOPT* reopt /**< reoptimization data structure */
    4939 )
    4940{
    4941 assert(reopt != NULL);
    4942
    4943 return reopt->reopttree->nfeasnodes;
    4944}
    4945
    4946/** returns the number of stored nodes providing an improving feasible LP solution over all runs */
    4948 SCIP_REOPT* reopt /**< reoptimization data structure */
    4949 )
    4950{
    4951 assert(reopt != NULL);
    4952
    4953 return reopt->reopttree->ntotalfeasnodes;
    4954}
    4955
    4956/** returns the number of stored nodes that exceeded the cutoff bound in the current run */
    4958 SCIP_REOPT* reopt /**< reoptimization data structure */
    4959 )
    4960{
    4961 assert(reopt != NULL);
    4962
    4963 return reopt->reopttree->nprunednodes;
    4964}
    4965
    4966/** returns the number of stored nodes that exceeded the cutoff bound over all runs */
    4968 SCIP_REOPT* reopt /**< reoptimization data structure */
    4969 )
    4970{
    4971 assert(reopt != NULL);
    4972
    4973 return reopt->reopttree->ntotalprunednodes;
    4974}
    4975
    4976/** rerturns the number of reoptimized nodes that were cutoff in the same iteration in the current run */
    4978 SCIP_REOPT* reopt /**< reoptimization data structure */
    4979 )
    4980{
    4981 assert(reopt != NULL);
    4982
    4983 return reopt->reopttree->ncutoffreoptnodes;
    4984}
    4985
    4986/** rerturns the number of reoptimized nodes that were cutoff in the same iteration over all runs */
    4988 SCIP_REOPT* reopt /**< reoptimization data structure */
    4989 )
    4990{
    4991 assert(reopt != NULL);
    4992
    4993 return reopt->reopttree->ntotalcutoffreoptnodes;
    4994}
    4995
    4996/** returns the number of stored nodes with an infeasible LP in the current run */
    4998 SCIP_REOPT* reopt /**< reoptimization data structure */
    4999 )
    5000{
    5001 assert(reopt != NULL);
    5002
    5003 return reopt->reopttree->ninfnodes;
    5004}
    5005
    5006/** returns the number of stored nodes with an infeasible LP over all runs */
    5008 SCIP_REOPT* reopt /**< reoptimization data structure */
    5009 )
    5010{
    5011 assert(reopt != NULL);
    5012
    5013 return reopt->reopttree->ntotalinfnodes;
    5014}
    5015
    5016/** constructor for the reoptimization data */
    5018 SCIP_REOPT** reopt, /**< pointer to reoptimization data structure */
    5019 SCIP_SET* set, /**< global SCIP settings */
    5020 BMS_BLKMEM* blkmem /**< block memory */
    5021 )
    5022{
    5023 SCIP_EVENTHDLR* eventhdlr;
    5024
    5025 assert(reopt != NULL);
    5026
    5027 SCIP_ALLOC( BMSallocMemory(reopt) );
    5028 (*reopt)->runsize = DEFAULT_MEM_RUN;
    5029 (*reopt)->run = 0;
    5030 (*reopt)->simtolastobj = -2.0;
    5031 (*reopt)->simtofirstobj = -2.0;
    5032 (*reopt)->firstobj = -1;
    5033 (*reopt)->currentnode = -1;
    5034 (*reopt)->lastbranched = -1;
    5035 (*reopt)->dualreds = NULL;
    5036 (*reopt)->glbconss = NULL;
    5037 (*reopt)->nglbconss = 0;
    5038 (*reopt)->allocmemglbconss = 0;
    5039 (*reopt)->ncheckedsols = 0;
    5040 (*reopt)->nimprovingsols = 0;
    5041 (*reopt)->noptsolsbyreoptsol = 0;
    5042 (*reopt)->nglbrestarts = 0;
    5043 (*reopt)->nlocrestarts = 0;
    5044 (*reopt)->ntotallocrestarts = 0;
    5045 (*reopt)->firstrestart = -1;
    5046 (*reopt)->lastrestart = 0;
    5047 (*reopt)->nobjvars = 0;
    5048 (*reopt)->objhaschanged = FALSE;
    5049 (*reopt)->consadded = FALSE;
    5050 (*reopt)->addedconss = NULL;
    5051 (*reopt)->naddedconss = 0;
    5052 (*reopt)->addedconsssize = 0;
    5053 (*reopt)->glblb = NULL;
    5054 (*reopt)->glbub = NULL;
    5055 (*reopt)->nactiveconss = 0;
    5056 (*reopt)->nmaxactiveconss = 0;
    5057 (*reopt)->activeconss = NULL;
    5058 (*reopt)->activeconssset = NULL;
    5059
    5060 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*reopt)->varhistory, (*reopt)->runsize) );
    5061 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*reopt)->prevbestsols, (*reopt)->runsize) );
    5062 SCIP_ALLOC( BMSallocMemoryArray(&(*reopt)->objs, (*reopt)->runsize) );
    5063
    5064 for( int i = 0; i < (*reopt)->runsize; ++i )
    5065 {
    5066 (*reopt)->objs[i] = NULL;
    5067 (*reopt)->prevbestsols[i] = NULL;
    5068 (*reopt)->varhistory[i] = NULL;
    5069 }
    5070
    5071 /* clocks */
    5072 SCIP_CALL( SCIPclockCreate(&(*reopt)->savingtime, SCIP_CLOCKTYPE_DEFAULT) );
    5073
    5074 /* create and initialize SCIP_SOLTREE */
    5075 SCIP_ALLOC( BMSallocMemory(&(*reopt)->soltree) );
    5076 SCIP_CALL( createSolTree((*reopt)->soltree, blkmem) );
    5077
    5078 /* create and initialize SCIP_REOPTTREE */
    5079 SCIP_ALLOC( BMSallocMemory(&(*reopt)->reopttree) );
    5080 SCIP_CALL( createReopttree((*reopt)->reopttree, set, blkmem) );
    5081
    5082 /* create a random number generator */
    5083 SCIP_CALL( SCIPrandomCreate(&(*reopt)->randnumgen, blkmem, SCIPsetInitializeRandomSeed(set, DEFAULT_RANDSEED)) );
    5084
    5085 /* create event handler for node events */
    5086 eventhdlr = NULL;
    5087
    5088 /* include event handler into SCIP */
    5090 eventInitsolReopt, eventExitsolReopt, NULL, eventExecReopt, NULL) );
    5091 SCIP_CALL( SCIPsetIncludeEventhdlr(set, eventhdlr) );
    5092 assert(eventhdlr != NULL);
    5093
    5094 return SCIP_OKAY;
    5095}
    5096
    5097/* release all variables and constraints captured during reoptimization */
    5099 SCIP_REOPT* reopt, /**< pointer to reoptimization data structure */
    5100 SCIP_SET* set, /**< global SCIP settings */
    5101 BMS_BLKMEM* blkmem /**< block memory */
    5102 )
    5103{
    5104 /* release all added constraints and free the data */
    5105 if( reopt->addedconss != NULL )
    5106 {
    5107 for( int c = 0; c < reopt->naddedconss; ++c )
    5108 {
    5109 assert(reopt->addedconss[c] != NULL);
    5110
    5111 SCIP_CALL( SCIPconsRelease(&reopt->addedconss[c], blkmem, set) );
    5112 }
    5113
    5114 BMSfreeBlockMemoryArray(blkmem, &reopt->addedconss, reopt->addedconsssize);
    5115 reopt->naddedconss = 0;
    5116 reopt->addedconsssize = 0;
    5117 }
    5118
    5119 SCIP_CALL( cleanActiveConss(reopt, set, blkmem) );
    5120
    5121 return SCIP_OKAY;
    5122}
    5123
    5124/** frees reoptimization data */
    5126 SCIP_REOPT** reopt, /**< reoptimization data structure */
    5127 SCIP_SET* set, /**< global SCIP settings */
    5128 SCIP_PRIMAL* origprimal, /**< original primal */
    5129 BMS_BLKMEM* blkmem /**< block memory */
    5130 )
    5131{
    5132 assert(reopt != NULL);
    5133 assert(*reopt != NULL);
    5134 assert(set != NULL);
    5135 assert(origprimal != NULL || set->stage == SCIP_STAGE_INIT);
    5136 assert(blkmem != NULL);
    5137
    5138 /* free random number generator */
    5139 SCIPrandomFree(&(*reopt)->randnumgen, blkmem);
    5140
    5141 /* free reopttree */
    5142 SCIP_CALL( freeReoptTree((*reopt)->reopttree, set, blkmem) );
    5143
    5144 /* free solutions and variable histories */
    5145 if( set->stage >= SCIP_STAGE_PROBLEM )
    5146 {
    5147 for( int p = (*reopt)->run-1; p >= 0; --p )
    5148 {
    5149 if( (*reopt)->soltree->sols[p] != NULL )
    5150 {
    5151 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->soltree->sols[p], (*reopt)->soltree->solssize[p]); /*lint !e866*/
    5152 (*reopt)->soltree->sols[p] = NULL;
    5153 }
    5154
    5155 if( set->reopt_storevarhistory && (*reopt)->varhistory[p] != NULL )
    5156 {
    5157 for( int v = SCIPgetNOrigVars(set->scip)-1; v >= 0; --v )
    5158 {
    5159 SCIPhistoryFree(&(*reopt)->varhistory[p][v], blkmem);
    5160 }
    5161
    5162 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->varhistory[p], SCIPgetNOrigVars(set->scip));
    5163 (*reopt)->varhistory[p] = NULL;
    5164 }
    5165
    5166 /* we have to free all optimal solution separatly, because those solutions are not stored in the
    5167 * solution reopt_sepabestsol = TRUE
    5168 */
    5169 if( set->reopt_sepabestsol && (*reopt)->prevbestsols[p] != NULL )
    5170 {
    5171 SCIP_CALL( SCIPsolFree(&(*reopt)->prevbestsols[p], blkmem, origprimal) );
    5172 }
    5173
    5174 if( (*reopt)->objs[p] != NULL )
    5175 {
    5176 BMSfreeMemoryArray(&(*reopt)->objs[p]);
    5177 }
    5178 }
    5179 }
    5180
    5181 /* free solution tree */
    5182 SCIP_CALL( freeSolTree((*reopt), set, origprimal, blkmem) );
    5183
    5184 if( (*reopt)->dualreds != NULL )
    5185 {
    5186 if( (*reopt)->dualreds->varssize > 0 )
    5187 {
    5188 assert(!(*reopt)->dualreds->linear);
    5189
    5190 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualreds->boundtypes, (*reopt)->dualreds->varssize);
    5191 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualreds->vals, (*reopt)->dualreds->varssize);
    5192 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualreds->vars, (*reopt)->dualreds->varssize);
    5193 BMSfreeBlockMemory(blkmem, &(*reopt)->dualreds);
    5194 (*reopt)->dualreds = NULL;
    5195 }
    5196 }
    5197
    5198 if( (*reopt)->glbconss != NULL && (*reopt)->allocmemglbconss > 0 )
    5199 {
    5200 /* free all constraint */
    5201 for( int c = 0; c < (*reopt)->allocmemglbconss; ++c )
    5202 {
    5203 if( (*reopt)->glbconss[c] != NULL )
    5204 {
    5205 if( (*reopt)->glbconss[c]->varssize > 0 )
    5206 {
    5207 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->boundtypes, (*reopt)->glbconss[c]->varssize);
    5208 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->vals, (*reopt)->glbconss[c]->varssize);
    5209 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->vars, (*reopt)->glbconss[c]->varssize);
    5210 (*reopt)->glbconss[c]->varssize = 0;
    5211 }
    5212 BMSfreeBlockMemory(blkmem, &(*reopt)->glbconss[c]); /*lint !e866*/
    5213 --(*reopt)->nglbconss;
    5214 }
    5215 }
    5216 assert((*reopt)->nglbconss == 0);
    5217
    5218 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss, (*reopt)->allocmemglbconss);
    5219 (*reopt)->allocmemglbconss = 0;
    5220 }
    5221
    5222 /* clocks */
    5223 SCIPclockFree(&(*reopt)->savingtime);
    5224
    5225 /* the hashmap need not to be exist, e.g., if the problem was solved during presolving */
    5226 if( (*reopt)->activeconssset != NULL )
    5227 {
    5228 SCIPhashsetFree(&(*reopt)->activeconssset, blkmem);
    5229 }
    5230 BMSfreeBlockMemoryArrayNull(blkmem, &(*reopt)->activeconss, (*reopt)->nmaxactiveconss);
    5231
    5232 if( (*reopt)->glblb != NULL )
    5233 {
    5234 SCIPhashmapFree(&(*reopt)->glblb);
    5235 SCIPhashmapFree(&(*reopt)->glbub);
    5236 (*reopt)->glblb = NULL;
    5237 (*reopt)->glbub = NULL;
    5238 }
    5239 else
    5240 assert((*reopt)->glbub == NULL);
    5241
    5242 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->varhistory, (*reopt)->runsize);
    5243 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->prevbestsols, (*reopt)->runsize);
    5244 BMSfreeMemoryArray(&(*reopt)->objs);
    5245 BMSfreeMemory(reopt);
    5246
    5247 return SCIP_OKAY;
    5248}
    5249
    5250/** returns the number of constraints added by the reoptimization plug-in */
    5252 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5253 SCIP_NODE* node /**< node of the search tree */
    5254 )
    5255{
    5256 unsigned int id;
    5257
    5258 assert(reopt != NULL);
    5259 assert(node != NULL);
    5260
    5261 id = SCIPnodeGetReoptID(node);
    5262 assert(id < reopt->reopttree->reoptnodessize);
    5263
    5264 /* set the id to -1 if the node is not part of the reoptimization tree */
    5265 if( SCIPnodeGetDepth(node) > 0 && id == 0 )
    5266 return SCIPnodeGetNAddedConss(node);
    5267
    5268 if( id >= 1 && reopt->reopttree->reoptnodes[id]->nconss > 0 )
    5269 return MAX(SCIPnodeGetNAddedConss(node), reopt->reopttree->reoptnodes[id]->nconss); /*lint !e666*/
    5270 else
    5271 return SCIPnodeGetNAddedConss(node);
    5272}
    5273
    5274/** add a solution to the solution tree */
    5276 SCIP_REOPT* reopt, /**< reoptimization data */
    5277 SCIP_SET* set, /**< global SCIP settings */
    5278 SCIP_STAT* stat, /**< dynamic problem statistics */
    5279 SCIP_PRIMAL* origprimal, /**< original primal */
    5280 BMS_BLKMEM* blkmem, /**< block memory */
    5281 SCIP_SOL* sol, /**< solution to add */
    5282 SCIP_Bool bestsol, /**< is the current solution an optimal solution? */
    5283 SCIP_Bool* added, /**< pointer to store the information if the soltion was added */
    5284 SCIP_VAR** vars, /**< variable array */
    5285 int nvars, /**< number of variables */
    5286 int run /**< number of the current run (1,2,...) */
    5287 )
    5288{
    5289 SCIP_SOLNODE* solnode = NULL;
    5290 SCIP_HEUR* heur;
    5291 int insertpos;
    5292
    5293 assert(reopt != NULL);
    5294 assert(set != NULL);
    5295 assert(sol != NULL);
    5296 assert(run > 0);
    5297
    5298 assert(reopt->soltree->sols[run-1] != NULL);
    5299
    5300 /* if the solution was found by reoptsols the solutions is already stored */
    5301 heur = SCIPsolGetHeur(sol);
    5302 if( heur != NULL && strcmp(SCIPheurGetName(heur), "reoptsols") == 0 && bestsol )
    5303 ++reopt->noptsolsbyreoptsol;
    5304 else if( bestsol )
    5305 reopt->noptsolsbyreoptsol = 0;
    5306
    5307 /* check memory */
    5308 SCIP_CALL( ensureSolsSize(reopt, set, blkmem, reopt->soltree->nsols[run-1]+1, run-1) );
    5309
    5310 /* add solution to solution tree */
    5311 SCIP_CALL( soltreeAddSol(reopt, set, stat, origprimal, blkmem, vars, sol, &solnode, nvars, bestsol, added) );
    5312
    5313 if( (*added) )
    5314 {
    5315 assert(solnode != NULL);
    5316
    5317 /* add solution */
    5318 insertpos = reopt->soltree->nsols[run-1];
    5319 reopt->soltree->sols[run-1][insertpos] = solnode;
    5320 ++reopt->soltree->nsols[run-1];
    5321 assert(reopt->soltree->nsols[run-1] <= set->reopt_savesols);
    5322 }
    5323
    5324 return SCIP_OKAY;
    5325}
    5326
    5327/** we want to store the optimal solution of each run in a separate array */
    5329 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5330 SCIP_SOL* sol, /**< solution to add */
    5331 BMS_BLKMEM* blkmem, /**< block memory */
    5332 SCIP_SET* set, /**< global SCIP settings */
    5333 SCIP_STAT* stat, /**< dynamic problem statistics */
    5334 SCIP_PRIMAL* origprimal, /**< original primal */
    5335 SCIP_VAR** vars, /**< original problem variables */
    5336 int nvars /**< number of original problem variables */
    5337 )
    5338{
    5339 SCIP_SOL* solcopy;
    5340
    5341 assert(reopt != NULL);
    5342 assert(reopt->run-1 >= 0);
    5343 assert(sol != NULL);
    5344 assert(blkmem != NULL);
    5345 assert(set != NULL);
    5346 assert(stat != NULL);
    5347 assert(origprimal != NULL);
    5348
    5349 SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, origprimal, sol) );
    5350 reopt->prevbestsols[reopt->run-1] = solcopy;
    5351
    5352 /* store a global constraint that cutsoff the solution */
    5353 if( set->reopt_sepabestsol )
    5354 {
    5355 SCIP_CALL( separateSolution(reopt, blkmem, set, stat, sol, vars, nvars) );
    5356 }
    5357
    5358 return SCIP_OKAY;
    5359}
    5360
    5361/** add a new iteration after changing the objective function */
    5363 SCIP_REOPT* reopt, /**< reoptimization data sturcture */
    5364 SCIP_SET* set, /**< global SCIP settings */
    5365 BMS_BLKMEM* blkmem, /**< block memory */
    5366 SCIP_VAR** origvars, /**< original problem variables */
    5367 int norigvars, /**< number of original variables */
    5368 int size /**< number of expected solutions */
    5369 )
    5370{
    5371 assert(reopt != NULL);
    5372 assert(set != NULL);
    5373 assert(blkmem != NULL);
    5374 assert(origvars != NULL);
    5375
    5376 /* increase number of runs */
    5377 ++reopt->run;
    5378
    5379 /* check memory */
    5380 SCIP_CALL( ensureRunSize(reopt, set, reopt->run, blkmem) );
    5381
    5382 /* allocate memory */
    5383 reopt->soltree->solssize[reopt->run-1] = size;
    5384 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->soltree->sols[reopt->run-1], size) ); /*lint !e866*/
    5385
    5386 /* reset flag */
    5387 reopt->objhaschanged = FALSE;
    5388
    5389 /* save the objective function */
    5390 SCIP_CALL( reoptSaveNewObj(reopt, set, blkmem, origvars, norigvars) );
    5391
    5392 resetStats(reopt);
    5393
    5394 return SCIP_OKAY;
    5395}
    5396
    5397/** get the number of checked solutions during the reoptimization process */
    5399 SCIP_REOPT* reopt /**< reoptimization data structure */
    5400 )
    5401{
    5402 assert(reopt != NULL);
    5403
    5404 return reopt->ncheckedsols;
    5405}
    5406
    5407/** update the number of checked solutions during the reoptimization process */
    5409 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5410 int ncheckedsols /**< number of updated solutions */
    5411 )
    5412{
    5413 assert(reopt != NULL);
    5414
    5415 reopt->ncheckedsols += ncheckedsols;
    5416}
    5417
    5418/** get the number of checked solutions during the reoptimization process */
    5420 SCIP_REOPT* reopt /**< reoptimization data structure */
    5421 )
    5422{
    5423 assert(reopt != NULL);
    5424
    5425 return reopt->nimprovingsols;
    5426}
    5427
    5428/** update the number of checked solutions during the reoptimization process */
    5430 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5431 int nimprovingsols /**< number of improving solutions */
    5432 )
    5433{
    5434 assert(reopt != NULL);
    5435
    5436 reopt->nimprovingsols += nimprovingsols;
    5437}
    5438
    5439/** returns number of solutions stored in the solution tree of a given run */
    5441 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5442 int run /**< number of the run (1,2,..) */
    5443 )
    5444{
    5445 assert(reopt != NULL);
    5446 assert(0 < run && run <= reopt->runsize);
    5447
    5448 if( reopt->soltree->sols[run-1] == NULL )
    5449 return 0;
    5450 else
    5451 return reopt->soltree->nsols[run-1];
    5452}
    5453
    5454/** returns number of all solutions of all runs */
    5456 SCIP_REOPT* reopt /**< reoptimization data structure */
    5457 )
    5458{
    5459 int nsols = 0;
    5460
    5461 assert(reopt != NULL);
    5462
    5463 for( int r = 0; r < reopt->run; ++r )
    5464 nsols += reopt->soltree->nsols[r];
    5465
    5466 return nsols;
    5467}
    5468
    5469/** return the stored solutions of a given run */
    5471 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5472 int run, /**< number of the run (1,2,...) */
    5473 SCIP_SOL** sols, /**< array of solutions to fill */
    5474 int solssize, /**< length of the array */
    5475 int* nsols /**< pointer to store the number of added solutions */
    5476 )
    5477{
    5478 assert(reopt != NULL);
    5479 assert(run > 0 && run <= reopt->run);
    5480 assert(sols != NULL);
    5481
    5482 assert(solssize > 0);
    5483 assert(nsols != NULL);
    5484 *nsols = 0;
    5485
    5486 for( int s = 0; s < reopt->soltree->nsols[run-1]; ++s )
    5487 {
    5488 if( !reopt->soltree->sols[run-1][s]->updated )
    5489 ++(*nsols);
    5490 }
    5491
    5492 if( solssize < (*nsols) )
    5493 return SCIP_OKAY;
    5494
    5495 (*nsols) = 0;
    5496 for( int s = 0; s < reopt->soltree->nsols[run-1]; ++s )
    5497 {
    5498 if( !reopt->soltree->sols[run-1][s]->updated )
    5499 {
    5500 sols[*nsols] = reopt->soltree->sols[run-1][s]->sol;
    5501 reopt->soltree->sols[run-1][s]->updated = TRUE;
    5502 ++(*nsols);
    5503 }
    5504 }
    5505
    5506 return SCIP_OKAY;
    5507}
    5508
    5509/** returns the number of saved solutions overall runs */
    5511 SCIP_REOPT* reopt /**< reoptimization data structure */
    5512 )
    5513{
    5514 int nsavedsols = 0;
    5515
    5516 assert(reopt != NULL);
    5517 assert(reopt->soltree->root != NULL);
    5518
    5519 if( reopt->soltree->root->child != NULL )
    5520 nsavedsols = soltreeNInducedSols(reopt->soltree->root);
    5521
    5522 return nsavedsols;
    5523}
    5524
    5525/** check if the reoptimization process should be (locally) restarted.
    5526 *
    5527 * First, we check whether the current node is the root node, e.g., node == NULL. in this case, we do not need to calculate
    5528 * the similarity again. we trigger a restart if
    5529 * 1. the objective function has changed too much
    5530 * 2. the number of stored nodes is exceeded
    5531 * 3. the last n optimal solutions were found by heur_reoptsols (in this case, the stored tree was only needed to
    5532 * prove the optimality and this can be probably faster by solving from scratch)
    5533 *
    5534 * If the current node is different to the root node we calculate the local similarity, i.e., exclude all variable
    5535 * that are already fixed by bounding.
    5536 */
    5538 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5539 SCIP_SET* set, /**< global SCIP settings */
    5540 BMS_BLKMEM* blkmem, /**< block memory */
    5541 SCIP_NODE* node, /**< current node of the branch and bound tree (or NULL) */
    5542 SCIP_VAR** transvars, /**< transformed problem variables */
    5543 int ntransvars, /**< number of transformed problem variables */
    5544 SCIP_Bool* restart /**< pointer to store if the reoptimization process should be restarted */
    5545 )
    5546{
    5547 SCIP_Real sim = 1.0;
    5548
    5549 assert(reopt != NULL);
    5550 assert(set != NULL);
    5551 assert(blkmem != NULL);
    5552 assert(transvars != NULL);
    5553 assert(ntransvars >= 0);
    5554 assert(restart != NULL);
    5555
    5556 *restart = FALSE;
    5557
    5558 /* check if the whole reoptimization process should start from scratch */
    5559 if( node == NULL )
    5560 {
    5561 /* compute the similarity to the objective function of the first run after restarting */
    5562 if( reopt->run > 1 && set->reopt_objsimdelay > -1.0 )
    5563 {
    5564 sim = reoptSimilarity(reopt, set, reopt->run-1, MAX(0, reopt->lastrestart-1), transvars, ntransvars);
    5565
    5566 if( sim == SCIP_INVALID ) /*lint !e777*/
    5567 return SCIP_INVALIDRESULT;
    5568 }
    5569
    5570 /* check similarity */
    5571 if( SCIPsetIsFeasLT(set, sim, set->reopt_objsimdelay) )
    5572 {
    5573 SCIPsetDebugMsg(set, "-> restart reoptimization (objective functions are not similar enough)\n");
    5574 *restart = TRUE;
    5575 }
    5576 /* check size of the reoptimization tree */
    5577 else if( reopt->reopttree->nreoptnodes > set->reopt_maxsavednodes )
    5578 {
    5579 SCIPsetDebugMsg(set, "-> restart reoptimization (node limit reached)\n");
    5580 *restart = TRUE;
    5581 }
    5582 /* check if the tree was only needed to prove optimality */
    5583 else if( reopt->noptsolsbyreoptsol >= set->reopt_forceheurrestart )
    5584 {
    5585 SCIPsetDebugMsg(set, "-> restart reoptimization (found last %d optimal solutions by <reoptsols>)\n",
    5586 reopt->noptsolsbyreoptsol);
    5587 reopt->noptsolsbyreoptsol = 0;
    5588 *restart = TRUE;
    5589 }
    5590
    5591 if( *restart )
    5592 {
    5593 /* trigger a restart */
    5594 SCIP_CALL( reoptRestart(reopt, set, blkmem) );
    5595 }
    5596 }
    5597 /* check for a local restart, ie, start the solving process of an inner node from scatch */
    5598 else
    5599 {
    5600 SCIP_CALL( reoptCheckLocalRestart(reopt, set, blkmem, node, transvars, ntransvars, restart) );
    5601 }
    5602 return SCIP_OKAY;
    5603}
    5604
    5605/** returns the similarity to the previous objective function, if no exist return -2.0 */
    5607 SCIP_REOPT* reopt /**< reoptimization data structure */
    5608 )
    5609{
    5610 assert(reopt != NULL);
    5611 return reopt->simtolastobj;
    5612}
    5613
    5614/** returns the similarity to the first objective different to the zero-function function, if no exist return -2.0 */
    5616 SCIP_REOPT* reopt /**< reoptimization data structure */
    5617 )
    5618{
    5619 assert(reopt != NULL);
    5620 return reopt->simtofirstobj;
    5621}
    5622
    5623/** return the similarity between two of objective functions of two given runs */
    5625 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5626 SCIP_SET* set, /**< global SCIP settings */
    5627 int run1, /**< number of the first run */
    5628 int run2, /**< number of the second run */
    5629 SCIP_VAR** origvars, /**< original problem variables */
    5630 int norigvars /**< number of original problem variables */
    5631 )
    5632{
    5633 assert(reopt != NULL);
    5634 assert(run1 > 0 && run1 <= reopt->run);
    5635 assert(run2 > 0 && run2 <= reopt->run);
    5636 assert(origvars != NULL);
    5637 assert(norigvars >= 0);
    5638
    5639 return reoptSimilarity(reopt, set, run1-1, run2-1, origvars, norigvars);
    5640}
    5641
    5642/** returns the best solution of the last run */
    5644 SCIP_REOPT* reopt /**< reoptimization data structure */
    5645 )
    5646{
    5647 assert(reopt != NULL);
    5648 assert(reopt->prevbestsols != NULL);
    5649
    5650 if( reopt->run-2 < 0 )
    5651 return NULL;
    5652 else
    5653 return reopt->prevbestsols[reopt->run-2];
    5654}
    5655
    5656/** returns the node of the reoptimization tree corresponding to the unique @p id */
    5658 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5659 unsigned int id /**< unique id */
    5660 )
    5661{
    5662 assert(reopt != NULL);
    5663 assert(reopt->reopttree != NULL);
    5664 assert(id < reopt->reopttree->reoptnodessize);
    5665 assert(reopt->reopttree->reoptnodes[id] != NULL);
    5666
    5667 return reopt->reopttree->reoptnodes[id];
    5668}
    5669
    5670/** returns the coefficient of variable with index @p idx in run @p run */
    5672 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5673 int run, /**< number of the run (1,2,...) */
    5674 int idx /**< index of original variable */
    5675 )
    5676{
    5677 assert(reopt != NULL);
    5678 assert(0 < run && run <= reopt->runsize);
    5679
    5680 return reopt->objs[run-1][idx];
    5681}
    5682
    5683/** return the best solution of a given run.
    5684 *
    5685 * @note the returned solution is part of the original space.
    5686 */
    5688 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5689 int run /**< number of the run (1,2,...) */
    5690 )
    5691{
    5692 assert(reopt != NULL);
    5693 assert(0 < run && run <= reopt->run);
    5694
    5695 return reopt->prevbestsols[run-1];
    5696}
    5697
    5698/** reset solving specific parameters */
    5700 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5701 SCIP_SET* set, /**< global SCIP settings */
    5702 BMS_BLKMEM* blkmem /**< block memory */
    5703 )
    5704{
    5705 assert(reopt != NULL);
    5706 assert(set != NULL);
    5707 assert(blkmem != NULL);
    5708
    5709 /* clean addedconss array */
    5710 for( int c = 0; c < reopt->naddedconss; ++c )
    5711 {
    5712 SCIP_CONS* cons;
    5713
    5714 cons = reopt->addedconss[c];
    5715 assert(cons != NULL);
    5716
    5717#ifdef SCIP_MORE_DEBUG
    5718 SCIPsetDebugMsg(set, "release cons <%s> from reoptimization data\n", SCIPconsGetName(cons));
    5719#endif
    5720
    5721 SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
    5722 reopt->addedconss[c] = NULL;
    5723 }
    5724
    5725 reopt->naddedconss = 0;
    5726 reopt->consadded = FALSE;
    5727 reopt->objhaschanged = FALSE;
    5728
    5729 return SCIP_OKAY;
    5730}
    5731
    5732/** reset marks of stored solutions to not updated */
    5734 SCIP_REOPT* reopt /**< reoptimization data structure */
    5735 )
    5736{
    5737 SCIP_SOLNODE* child;
    5738
    5739 assert(reopt != NULL);
    5740 assert(reopt->soltree != NULL);
    5741 assert(reopt->soltree->root != NULL);
    5742
    5743 child = reopt->soltree->root->child;
    5744
    5745 /* traverse through the list */
    5746 while( child != NULL )
    5747 {
    5748 soltreeResetMarks(child);
    5749 child = child->sibling;
    5750 }
    5751}
    5752
    5753/** returns the number of stored nodes in the subtree induced by @p node */
    5755 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5756 SCIP_NODE* node /**< node of the search tree */
    5757 )
    5758{
    5759 unsigned int id;
    5760
    5761 assert(reopt != NULL);
    5762
    5763 if( node == NULL || SCIPnodeGetDepth(node) == 0 )
    5764 return reopt->reopttree->nreoptnodes;
    5765
    5766 id = SCIPnodeGetReoptID(node);
    5767 assert(id < reopt->reopttree->reoptnodessize);
    5768
    5769 /* set the id to -1 if the node is not part of the reoptimization tree */
    5770 if( SCIPnodeGetDepth(node) > 0 && id == 0 )
    5771 return 0;
    5772
    5773 assert(0 < id && id < reopt->reopttree->reoptnodessize);
    5774
    5775 return reopttreeGetNNodes(reopt->reopttree, id);
    5776}
    5777
    5778/* ---------------- methods of general reoptimization nodes ---------------- */
    5779
    5780/** In debug mode, the following methods are implemented as function calls to ensure
    5781 * type validity.
    5782 * In optimized mode, the methods are implemented as defines to improve performance.
    5783 * However, we want to have them in the library anyways, so we have to undef the defines.
    5784 */
    5785
    5786#undef SCIPreoptnodeGetNVars
    5787#undef SCIPreoptnodeGetNConss
    5788#undef SCIPreoptnodeGetNDualBoundChgs
    5789#undef SCIPreoptnodeGetNChildren
    5790#undef SCIPreoptnodeGetLowerbound
    5791#undef SCIPreoptnodeGetType
    5792
    5793/** returns the number of bound changes stored in the reopttree at ID id */
    5795 SCIP_REOPTNODE* reoptnode /**< node of the reopttree */
    5796 )
    5797{
    5798 assert(reoptnode != NULL);
    5799
    5800 return reoptnode->nvars + reoptnode->nafterdualvars;
    5801}
    5802
    5803/** returns the number of bound changes at the node stored at ID id */
    5805 SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
    5806 )
    5807{
    5808 assert(reoptnode != NULL);
    5809
    5810 return reoptnode->nconss;
    5811}
    5812
    5813/** returns the number of stored bound changes based on dual information in the reopttree at ID id */
    5815 SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
    5816 )
    5817{
    5818 assert(reoptnode != NULL);
    5819
    5820 if( reoptnode->dualredscur == NULL )
    5821 return 0;
    5822 else
    5823 return reoptnode->dualredscur->nvars;
    5824}
    5825
    5826/** returns the number of child nodes of @p reoptnode */
    5828 SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
    5829 )
    5830{
    5831 assert(reoptnode != NULL);
    5832
    5833 return reoptnode->nchilds;
    5834}
    5835
    5836/** return the lower bound stored at @p ID id */
    5838 SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
    5839 )
    5840{
    5841 assert(reoptnode != NULL);
    5842
    5843 return reoptnode->lowerbound;
    5844}
    5845
    5846/** returns the type of the @p reoptnode */
    5848 SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
    5849 )
    5850{
    5851 assert(reoptnode != NULL);
    5852
    5853 return (SCIP_REOPTTYPE)reoptnode->reopttype;
    5854}
    5855
    5856/** returns all added constraints at ID id */
    5858 SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
    5859 SCIP_VAR*** vars, /**< 2-dim array of variables */
    5860 SCIP_Real** bounds, /**< 2-dim array of bounds */
    5861 SCIP_BOUNDTYPE** boundtypes, /**< 2-dim array of boundtypes */
    5862 int mem, /**< allocated memory for constraints */
    5863 int* nconss, /**< pointer to store the number of constraints */
    5864 int* nvars /**< pointer to store the number of variables */
    5865 )
    5866{
    5867 assert(reoptnode != NULL);
    5868 assert(vars != NULL);
    5869 assert(bounds != NULL);
    5870 assert(boundtypes != NULL);
    5871 assert(nvars != NULL);
    5872 assert(nconss != NULL);
    5873
    5874 (*nconss) = reoptnode->nconss;
    5875
    5876 if( mem < *nconss )
    5877 return;
    5878
    5879 for( int c = 0; c < *nconss; ++c )
    5880 {
    5881 assert(vars[c] != NULL);
    5882 assert(bounds[c] != NULL);
    5883
    5884 vars[c] = reoptnode->conss[c]->vars;
    5885 bounds[c] = reoptnode->conss[c]->vals;
    5886 boundtypes[c] = reoptnode->conss[c]->boundtypes;
    5887 nvars[c] = reoptnode->conss[c]->nvars;
    5888 }
    5889}
    5890
    5891/** set the parent id */
    5893 SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
    5894 unsigned int parentid /**< id of the parent node */
    5895 )
    5896{
    5897 assert(reoptnode != NULL);
    5898 assert(parentid <= 536870911); /* id can be at most 2^29 - 1 */
    5899
    5900 reoptnode->parentID = parentid;
    5901}
    5902
    5903/** returns the number of leaf nodes of the subtree induced by @p node (of the whole tree if node == NULL) */
    5905 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5906 SCIP_NODE* node /**< node of the search tree (or NULL) */
    5907 )
    5908{
    5909 int nleaves = 0;
    5910 unsigned int id;
    5911
    5912 assert(reopt != NULL);
    5913
    5914 id = (node == NULL) ? 0 : SCIPnodeGetReoptID(node);
    5915 assert(id < reopt->reopttree->reoptnodessize);
    5916
    5917 /* return if the node is not part of the reoptimization tree */
    5918 if( node != NULL && SCIPnodeGetDepth(node) > 0 && id == 0 )
    5919 return nleaves;
    5920
    5921 for( int i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
    5922 {
    5923 unsigned int childid;
    5924
    5925 childid = reopt->reopttree->reoptnodes[id]->childids[i]; /*lint !e713*/
    5926 assert(childid < reopt->reopttree->reoptnodessize);
    5927
    5928 if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
    5929 ++nleaves;
    5930 else
    5931 nleaves += reoptGetNLeaves(reopt, childid);
    5932 }
    5933
    5934 return nleaves;
    5935}
    5936
    5937/** save information that given node is infeasible */
    5939 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5940 SCIP_SET* set, /**< global SCIP settings */
    5941 BMS_BLKMEM* blkmem, /**< block memory */
    5942 SCIP_NODE* node /**< node of the search tree */
    5943 )
    5944{
    5945 assert(reopt != NULL);
    5946 assert(set != NULL);
    5947 assert(blkmem != NULL);
    5948 assert(node != NULL);
    5949
    5950 if( set->reopt_sepaglbinfsubtrees )
    5951 {
    5952 SCIP_CALL( saveGlobalCons(reopt, set, blkmem, node, REOPT_CONSTYPE_CUT) );
    5953 }
    5954
    5955 ++reopt->reopttree->ninfnodes;
    5956 ++reopt->reopttree->ntotalinfnodes;
    5957
    5958 return SCIP_OKAY;
    5959}
    5960
    5961/** check the reason for cut off a node and if necessary store the node */
    5963 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5964 SCIP_SET* set, /**< global SCIP settings */
    5965 BMS_BLKMEM* blkmem, /**< block memory */
    5966 SCIP_NODE* node, /**< node of the search tree */
    5967 SCIP_EVENTTYPE eventtype, /**< eventtype */
    5968 SCIP_LP* lp, /**< LP data */
    5969 SCIP_LPSOLSTAT lpsolstat, /**< solution status of the LP */
    5970 SCIP_Bool isrootnode, /**< the node is the root */
    5971 SCIP_Bool isfocusnode, /**< the node is the current focus node */
    5972 SCIP_Real lowerbound, /**< lower bound of the node */
    5973 int effectiverootdepth /**< effective root depth */
    5974 )
    5975{
    5976 SCIP_Bool strongbranched;
    5977
    5978 assert(reopt != NULL);
    5979 assert(set != NULL);
    5980 assert(blkmem != NULL);
    5981 assert(lp != NULL);
    5982 assert(node != NULL);
    5983 assert(eventtype == SCIP_EVENTTYPE_NODEBRANCHED || eventtype == SCIP_EVENTTYPE_NODEFEASIBLE || eventtype == SCIP_EVENTTYPE_NODEINFEASIBLE);
    5984
    5985 if( reopt->lastseennode == SCIPnodeGetNumber(node) )
    5986 return SCIP_OKAY;
    5987
    5988 /* we do not want to store probing node */
    5990 return SCIP_OKAY;
    5991
    5992 reopt->lastseennode = SCIPnodeGetNumber(node);
    5993
    5994 SCIPsetDebugMsg(set, "catch event %" SCIP_EVENTTYPE_FORMAT " for node %lld (type:%d)\n", eventtype, SCIPnodeGetNumber(node), SCIPnodeGetType(node));
    5995
    5996 /* case 1: the current node is the root node
    5997 * we can skip if the root is (in)feasible or branched w/o bound
    5998 * changes based on dual information.
    5999 *
    6000 * case 2: we need to store the current node if it contains
    6001 * bound changes based on dual information or is a leave node
    6002 */
    6003 if( isrootnode )
    6004 {
    6005 if( SCIPreoptGetNDualBndchgs(reopt, node) > 0 )
    6006 {
    6007 goto CHECK;
    6008 }
    6009 else if( eventtype == SCIP_EVENTTYPE_NODEBRANCHED )
    6010 {
    6011 /* store or update the information */
    6012 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_TRANSIT, FALSE, isrootnode, lowerbound) );
    6013 }
    6014 else if( eventtype == SCIP_EVENTTYPE_NODEFEASIBLE )
    6015 {
    6016 /* delete saved dual information which would lead to split the node in a further iteration */
    6017 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    6018
    6019 /* store or update the information */
    6020 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_FEASIBLE, FALSE, isrootnode, lowerbound) );
    6021 }
    6022 else if( eventtype == SCIP_EVENTTYPE_NODEINFEASIBLE )
    6023 {
    6024 /* delete saved dual information which would lead to split the node in a further iteration */
    6025 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    6026
    6028 {
    6029 SCIP_Real cutoffbound = SCIPlpGetCutoffbound(lp);
    6030 lowerbound = MIN(lowerbound, cutoffbound);
    6031 }
    6032
    6033 /* store or update the information */
    6034 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, reopt->currentnode == 1 ? SCIP_REOPTTYPE_INFSUBTREE : SCIP_REOPTTYPE_PRUNED, FALSE,
    6035 isrootnode, lowerbound) );
    6036 }
    6037
    6038 assert(reopt->currentnode == -1);
    6039 assert(reopt->dualreds == NULL || reopt->dualreds->nvars == 0);
    6040
    6041 return SCIP_OKAY;
    6042 }
    6043
    6044 CHECK:
    6045
    6046 if( effectiverootdepth == SCIPnodeGetDepth(node) )
    6047 strongbranched = SCIPreoptGetNDualBndchgs(reopt, node) > 0 ? TRUE : FALSE;
    6048 else
    6049 strongbranched = SCIPnodeGetNDualBndchgs(node) > 0 ? TRUE : FALSE;
    6050
    6051 SCIPsetDebugMsg(set, "check the reason of cutoff for node %lld:\n", SCIPnodeGetNumber(node));
    6052 SCIPsetDebugMsg(set, " -> focusnode : %s\n", isfocusnode ? "yes" : "no");
    6053 SCIPsetDebugMsg(set, " -> depth : %d (eff. %d)\n", SCIPnodeGetDepth(node), effectiverootdepth);
    6054 SCIPsetDebugMsg(set, " -> strong branched : %s\n", strongbranched ? "yes" : "no");
    6055 SCIPsetDebugMsg(set, " -> LP lpsolstat : %d\n", lpsolstat);
    6056
    6057 switch( eventtype )
    6058 {
    6060 /* current node has to be the eventnode */
    6061 assert(isfocusnode);
    6062
    6063 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_FEASIBLE);
    6064
    6065 /* delete strong branching information of some exists */
    6066 deleteLastDualBndchgs(reopt);
    6067
    6068 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_FEASIBLE, FALSE, isrootnode, lowerbound) );
    6069 break;
    6070
    6072 /* We have to check if the current node is the event node.
    6073 * if the current node is not the event node, we have to save this node, else we have to
    6074 * look at LP lpsolstat and decide.
    6075 */
    6076 if( isfocusnode )
    6077 {
    6078 /* An after-branch heuristic says NODEINFEASIBLE, maybe the cutoff bound is reached.
    6079 * because the node is already branched we have all children and can delete this node.
    6080 */
    6081 if( SCIPnodeGetNumber(node) == reopt->lastbranched )
    6082 {
    6083 deleteLastDualBndchgs(reopt);
    6084 break;
    6085 }
    6086
    6087 /* If the node is strong branched, we possibly detect an infeasible subtree;
    6088 * otherwise, the whole node is either infeasible or exceeds the cutoff bound.
    6089 */
    6090 if( strongbranched )
    6091 {
    6092 /* 1. the LP is infeasible: the (sub-)node is infeasible and can be discarded
    6093 * because the LP proves infeasibility. We have to store an infeasible subtree separated by a constraint.
    6094 * 2. the LP exceeds the objective limit or was not solved, we have to store the node and can delete the
    6095 * strong branching information
    6096 */
    6097 if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
    6098 {
    6099 /* add a dummy variable, because the bound changes were not global in the sense of effective root depth */
    6100 if( SCIPnodeGetDepth(node) > effectiverootdepth )
    6101 {
    6102 SCIP_CALL( SCIPreoptAddDualBndchg(reopt, set, blkmem, node, NULL, 0.0, 1.0) );
    6103 }
    6104
    6105 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_INFSUBTREE);
    6106 SCIPsetDebugMsg(set, " -> new constype : %d\n", REOPT_CONSTYPE_INFSUBTREE);
    6107
    6108 /* save the node as a strong branched node */
    6109 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_INFSUBTREE, FALSE, isrootnode, lowerbound) );
    6110 }
    6111 else
    6112 {
    6113 assert( lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT || lpsolstat == SCIP_LPSOLSTAT_OPTIMAL || lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED);
    6114
    6115 /* delete strong branching information if some exists */
    6116 deleteLastDualBndchgs(reopt);
    6117
    6118 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_PRUNED);
    6119 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
    6120 }
    6121 }
    6122 else
    6123 {
    6124 /* 1. the LP is infeasible: the whole node is infeasible and can be discarded
    6125 * 2. the LP was not solved or exceeds the objective limit, we have to store the node
    6126 */
    6127 if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
    6128 {
    6129 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_INFSUBTREE);
    6130 SCIP_CALL( SCIPreoptAddInfNode(reopt, set, blkmem, node) );
    6131 }
    6132 else
    6133 {
    6134 assert(lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED || lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT
    6135 || lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
    6136
    6137 if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
    6138 {
    6139 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
    6140 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, FALSE, isrootnode, lowerbound) );
    6141 }
    6142 else
    6143 {
    6144 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_PRUNED);
    6145 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
    6146 }
    6147 }
    6148 }
    6149 }
    6150 else
    6151 {
    6152 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_PRUNED);
    6153
    6154 /* if the node was created by branch_nodereopt, nothing happens */
    6155 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
    6156 }
    6157 break;
    6158
    6160 /* current node has to be the eventnode */
    6161 assert(isfocusnode);
    6162
    6163 reopt->lastbranched = SCIPnodeGetNumber(node);
    6164
    6165 /* we have to check the depth of the current node. if the depth is equal to the effective
    6166 * root depth, then all information about bound changes based on dual information already exists,
    6167 * else we have to look at the domchg-data-structure.
    6168 */
    6169 if (SCIPnodeGetDepth(node) == effectiverootdepth)
    6170 {
    6171 /* Save the node if there are added constraints, because this means the node is a copy create by the
    6172 * reoptimization plug-in and contains at least one logic-or-constraint */
    6173 if( strongbranched )
    6174 {
    6175 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_STRBRANCHED);
    6176 SCIPsetDebugMsg(set, " -> new constype : %d\n", REOPT_CONSTYPE_DUALREDS);
    6177 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_STRBRANCHED, FALSE, isrootnode, lowerbound) );
    6178 }
    6179 else if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
    6180 {
    6181 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
    6182 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, FALSE, isrootnode, lowerbound) );
    6183 }
    6184 else
    6185 {
    6186 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_TRANSIT);
    6187 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_TRANSIT, FALSE, isrootnode, lowerbound) );
    6188 }
    6189 }
    6190 else
    6191 {
    6192 /* we only branch on binary variables and var == NULL indicates memory allocation w/o saving information.
    6193 *
    6194 * we have to do this in the following order:
    6195 * 1) all bound-changes are local, thats way we have to mark the node to include bound changes based
    6196 * on dual information.
    6197 * 2) save or update the node.
    6198 */
    6199 if( strongbranched )
    6200 {
    6201 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_STRBRANCHED);
    6202 SCIPsetDebugMsg(set, " -> new constype : %d\n", REOPT_CONSTYPE_DUALREDS);
    6203 SCIP_CALL( SCIPreoptAddDualBndchg(reopt, set, blkmem, node, NULL, 0.0, 1.0) );
    6204 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_STRBRANCHED, FALSE, isrootnode, lowerbound) );
    6205 }
    6206 else if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
    6207 {
    6208 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
    6209 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, FALSE, isrootnode, lowerbound) );
    6210 }
    6211 else
    6212 {
    6213 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_TRANSIT);
    6214 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_TRANSIT, FALSE, isrootnode, lowerbound) );
    6215 }
    6216 }
    6217 break;
    6218
    6219 default:
    6220 break;
    6221 }
    6222
    6223 assert(reopt->currentnode == -1);
    6224 assert(reopt->dualreds == NULL || reopt->dualreds->nvars == 0);
    6225
    6226 return SCIP_OKAY; /*lint !e438*/
    6227}
    6228
    6229/** store bound change based on dual information */
    6231 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6232 SCIP_SET* set, /**< global SCIP settings */
    6233 BMS_BLKMEM* blkmem, /**< block memory */
    6234 SCIP_NODE* node, /**< node of the search tree */
    6235 SCIP_VAR* var, /**< variable */
    6236 SCIP_Real newval, /**< new bound */
    6237 SCIP_Real oldval /**< old bound */
    6238 )
    6239{
    6240 SCIP_Real constant = 0.0;
    6241 SCIP_Real scalar = 1.0;
    6242
    6243 assert(reopt != NULL);
    6244 assert(node != NULL);
    6245
    6246 /* If var == NULL, we save all information by calling SCIPreoptNodeFinished().
    6247 * In that case, all bound changes were not global and we can find them within the
    6248 * domchg data structure.
    6249 * Otherwise, we allocate memory and store the information.
    6250 */
    6251 if( var != NULL )
    6252 {
    6253 SCIP_BOUNDTYPE boundtype;
    6254 int resizelength;
    6255 int allocmem;
    6256
    6257 if( SCIPsetFindBranchrule(set, "relpscost") != NULL )
    6258 {
    6259 SCIP_CALL( SCIPsetGetIntParam(set, "branching/relpscost/maxlookahead", &resizelength) );
    6260 }
    6261 else
    6262 resizelength = 1;
    6263
    6264 if( reopt->dualreds == NULL || reopt->dualreds->varssize == 0 )
    6265 allocmem = DEFAULT_MEM_DUALCONS;
    6266 else
    6267 allocmem = reopt->dualreds->nvars + resizelength;
    6268
    6269 /* allocate memory of necessary */
    6270 SCIP_CALL( checkMemDualCons(reopt, set, blkmem, allocmem) );
    6271
    6272 assert(reopt->dualreds->varssize > 0);
    6273 assert(reopt->dualreds->nvars >= 0);
    6274 assert(reopt->currentnode == -1 || reopt->dualreds->nvars > 0);
    6275 assert((reopt->dualreds->nvars > 0 && reopt->currentnode == SCIPnodeGetNumber(node))
    6276 || reopt->dualreds->nvars == 0);
    6277
    6278 reopt->currentnode = SCIPnodeGetNumber(node);
    6279
    6280 /* transform into the original space and then save the bound change */
    6281 SCIP_CALL( SCIPvarGetOrigvarSum(&var, &scalar, &constant) );
    6282 newval = (newval - constant) / scalar;
    6283 oldval = (oldval - constant) / scalar;
    6284
    6285 assert(SCIPvarIsOriginal(var));
    6286
    6287 if( SCIPsetIsEQ(set, oldval, newval) )
    6288 {
    6289 SCIPerrorMessage("cannot store equal bounds: old = %g, new = %g\n", oldval, newval);
    6290 return SCIP_INVALIDDATA;
    6291 }
    6292
    6293 if( SCIPsetIsLT(set, newval, oldval) )
    6294 boundtype = SCIP_BOUNDTYPE_UPPER;
    6295 else
    6296 boundtype = SCIP_BOUNDTYPE_LOWER;
    6297
    6298 reopt->dualreds->vars[reopt->dualreds->nvars] = var;
    6299 reopt->dualreds->vals[reopt->dualreds->nvars] = newval;
    6300 reopt->dualreds->boundtypes[reopt->dualreds->nvars] = boundtype;
    6301 ++reopt->dualreds->nvars;
    6302
    6303 SCIPsetDebugMsg(set, ">> store %s bound change of <%s>: %g -> %g\n",
    6304 (boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper"), SCIPvarGetName(var), oldval, newval);
    6305
    6306 reopt->dualreds->linear = FALSE;
    6307 }
    6308 else
    6309 {
    6310 assert(reopt->currentnode == -1);
    6311 assert(reopt->dualreds == NULL || reopt->dualreds->nvars == 0);
    6312
    6313 reopt->currentnode = SCIPnodeGetNumber(node);
    6314 }
    6315
    6316 return SCIP_OKAY;
    6317}
    6318
    6319/** returns the number of bound changes based on dual information */
    6321 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6322 SCIP_NODE* node /**< node of the search tree */
    6323 )
    6324{
    6325 int ndualbndchgs = 0;
    6326
    6327 assert(reopt != NULL);
    6328 assert(node != NULL);
    6329
    6330 if( SCIPnodeGetNumber(node) == reopt->currentnode )
    6331 {
    6332 assert(reopt->dualreds != NULL);
    6333 ndualbndchgs = reopt->dualreds->nvars;
    6334 }
    6335
    6336 return ndualbndchgs;
    6337}
    6338
    6339/** returns the child nodes of @p node that need to be reoptimized next or NULL if @p node is a leaf */
    6341 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6342 SCIP_SET* set, /**< global SCIP settings */
    6343 BMS_BLKMEM* blkmem, /**< block memory */
    6344 SCIP_NODE* node, /**< node of the search tree */
    6345 unsigned int* childs, /**< array to store the child ids */
    6346 int childssize, /**< size of the childs array */
    6347 int* nchilds /**< pointer to store the number of child nodes */
    6348 )
    6349{
    6350 SCIP_Bool runagain;
    6351 unsigned int id;
    6352
    6353 assert(reopt != NULL);
    6354 assert(childssize > 0 && childs != NULL);
    6355 assert(nchilds != NULL);
    6356
    6357 (*nchilds) = 0;
    6358
    6359 if( node == NULL )
    6360 id = 0;
    6361 else
    6362 {
    6363 id = SCIPnodeGetReoptID(node);
    6364 assert(id >= 1 || SCIPnodeGetDepth(node) == 0);
    6365 }
    6366
    6367 assert(id < reopt->reopttree->reoptnodessize);
    6368 assert(reopt->reopttree->reoptnodes[id] != NULL);
    6369
    6370 /* check if there are redundant bound changes or infeasible nodes */
    6371 runagain = TRUE;
    6372 while( runagain && reopt->reopttree->reoptnodes[id]->nchilds > 0 )
    6373 {
    6374 SCIP_CALL( dryBranch(reopt, set, blkmem, &runagain, id) );
    6375 }
    6376
    6377 /* return the list of child nodes if some exists; otherwise return NULL */
    6378 if( reopt->reopttree->reoptnodes[id]->childids != NULL && reopt->reopttree->reoptnodes[id]->nchilds > 0 )
    6379 {
    6380 (*nchilds) = reopt->reopttree->reoptnodes[id]->nchilds;
    6381
    6382 if( childssize < *nchilds )
    6383 return SCIP_OKAY;
    6384
    6385 for( int c = 0; c < *nchilds; ++c )
    6386 childs[c] = reopt->reopttree->reoptnodes[id]->childids[c];
    6387 }
    6388
    6389 return SCIP_OKAY;
    6390}
    6391
    6392/** returns all leaves of the subtree induced by @p node */
    6394 SCIP_REOPT* reopt, /**< reoptimization data */
    6395 SCIP_NODE* node, /**< node of the search tree */
    6396 unsigned int* leaves, /**< array to the the ids */
    6397 int leavessize, /**< size of leaves array */
    6398 int* nleaves /**< pointer to store the number of leave node */
    6399 )
    6400{
    6401 unsigned int id;
    6402
    6403 assert(reopt != NULL);
    6404 assert(leavessize > 0 && leaves != NULL);
    6405 assert((*nleaves) >= 0);
    6406
    6407 /* if the given node is we start from the root */
    6408 if( node == NULL )
    6409 id = 0;
    6410 else
    6411 id = SCIPnodeGetReoptID(node);
    6412
    6413 /* return if the node is not part of the reoptimization tree */
    6414 if( id == 0 && node != NULL )
    6415 {
    6416 (*nleaves) = 0;
    6417 return SCIP_OKAY;
    6418 }
    6419
    6420 assert(id < reopt->reopttree->reoptnodessize);
    6421 assert(reopt->reopttree->reoptnodes[id] != NULL);
    6422
    6423 for( int i = 0; i < leavessize; ++i )
    6424 leaves[i] = 0;
    6425
    6426 /* we traverse through all child nodes of the given node an collect all leave nodes of the subtrees induced by them */
    6427 for( int i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
    6428 {
    6429 unsigned int childid;
    6430
    6431 assert(*nleaves + 1 <= leavessize);
    6432
    6433 childid = reopt->reopttree->reoptnodes[id]->childids[i];
    6434 assert(childid < reopt->reopttree->reoptnodessize);
    6435
    6436 /* the node is already a leave */
    6437 if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
    6438 {
    6439 leaves[(*nleaves)] = reopt->reopttree->reoptnodes[id]->childids[i];
    6440 ++(*nleaves);
    6441 }
    6442 /* go into the tree induced by the current child node */
    6443 else
    6444 {
    6445 int nleaves2 = 0;
    6446
    6447 SCIP_CALL( reoptGetLeaves(reopt, childid, &leaves[*nleaves], leavessize - (*nleaves), &nleaves2) );
    6448 (*nleaves) += nleaves2;
    6449 }
    6450 }
    6451
    6452 return SCIP_OKAY;
    6453}
    6454
    6455/** add all unprocessed nodes to the reoptimization tree */
    6457 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6458 SCIP_SET* set, /**< global SCIP settings */
    6459 SCIP_LP* lp, /**< current LP */
    6460 BMS_BLKMEM* blkmem, /**< block memory */
    6461 SCIP_NODE** leaves, /**< array of open leave nodes */
    6462 int nleaves, /**< number of open leave nodes */
    6463 SCIP_NODE** childs, /**< array of open children nodes */
    6464 int nchilds, /**< number of open leave nodes */
    6465 SCIP_NODE** siblings, /**< array of open sibling nodes */
    6466 int nsiblings /**< number of open leave nodes */
    6467 )
    6468{
    6469 assert(reopt != NULL);
    6470 assert(set != NULL);
    6471 assert(blkmem != NULL);
    6472 assert(nleaves >= 0);
    6473 assert(nleaves == 0 || leaves != NULL);
    6474 assert(nchilds >= 0);
    6475 assert(nchilds == 0 || childs != NULL);
    6476 assert(nsiblings >= 0);
    6477 assert(nsiblings == 0 || siblings != NULL);
    6478
    6479 SCIPsetDebugMsg(set, "save unprocessed nodes (%d leaves, %d children, %d siblings)\n", nleaves, nchilds, nsiblings);
    6480
    6481 /* save open leaves */
    6482 for( int n = 0; n < nleaves; ++n )
    6483 {
    6484 SCIP_CALL( addNode(reopt, set, lp, blkmem, leaves[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
    6485 SCIPnodeGetLowerbound(leaves[n])) );
    6486 }
    6487
    6488 /* save open children */
    6489 for( int n = 0; n < nchilds; ++n )
    6490 {
    6491 SCIP_CALL( addNode(reopt, set, lp, blkmem, childs[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
    6492 SCIPnodeGetLowerbound(childs[n])) );
    6493 }
    6494
    6495 /* save open siblings */
    6496 for( int n = 0; n < nsiblings; ++n )
    6497 {
    6498 SCIP_CALL( addNode(reopt, set, lp, blkmem, siblings[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
    6499 SCIPnodeGetLowerbound(siblings[n])) );
    6500 }
    6501
    6502 return SCIP_OKAY;
    6503}
    6504
    6505/** merges the variable history of the current run with the stored history */
    6507 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6508 SCIP_SET* set, /**< global SCIP settings */
    6509 SCIP_STAT* stat, /**< dynamic problem statistics */
    6510 SCIP_VAR** vars, /**< original problem variables */
    6511 int nvars /**< number of original problem variables */
    6512 )
    6513{
    6514 SCIP_VAR* transvar;
    6515 SCIP_Real avginference[2];
    6516 SCIP_Real avgcutoff[2];
    6517 SCIP_Real bestsim;
    6518 int bestrun;
    6519 int idx;
    6520
    6521 assert(reopt != NULL);
    6522 assert(stat != NULL);
    6523 assert(nvars >= 0);
    6524
    6525 if( !set->reopt_storevarhistory )
    6526 return SCIP_OKAY;
    6527
    6528 SCIPsetDebugMsg(set, "start merging variable histories:\n");
    6529
    6530 bestrun = reopt->run-2;
    6531 bestsim = reopt->simtolastobj;
    6532
    6533 /* find the run with the most similar objective */
    6534 for( int r = reopt->run-3; r >= 0 && reopt->objhaschanged && set->reopt_usepscost; --r )
    6535 {
    6536 SCIP_Real sim;
    6537 sim = reoptSimilarity(reopt, set, r, reopt->run-1, vars, nvars);
    6538
    6539 if( sim == SCIP_INVALID ) /*lint !e777*/
    6540 return SCIP_INVALIDRESULT;
    6541
    6542 if( SCIPsetIsGT(set, sim, bestsim) )
    6543 {
    6544 bestsim = sim;
    6545 bestrun = r;
    6546 }
    6547 }
    6548 SCIPverbMessage(set->scip, SCIP_VERBLEVEL_NORMAL, NULL, "run %d has best similarity=%g\n", bestrun, bestsim);
    6549
    6550 /* iterate through all variables and scale the histories */
    6551 for( int v = 0; v < nvars; ++v )
    6552 {
    6553 assert(SCIPvarIsOriginal(vars[v]));
    6554
    6555 transvar = SCIPvarGetTransVar(vars[v]);
    6556 assert(transvar != NULL);
    6557
    6558 /* skip variable that are not active */
    6559 if( !SCIPvarIsActive(transvar) )
    6560 continue;
    6561
    6562 idx = SCIPvarGetIndex(vars[v]);
    6563 assert(0 <= idx && idx <= nvars);
    6564
    6565 /* set the updated history for both directions */
    6566 for( int d = 0; d <= 1; ++d )
    6567 {
    6568 if( set->reopt_usepscost && !SCIPsetIsZero(set, reopt->varhistory[bestrun][idx]->pscostcount[d])
    6569 && SCIPsetIsGT(set, bestsim, 0.985) ) /* 0.985 is a magic number determined in some experiments */
    6570 {
    6571 transvar->history->pscostcount[d] = 1.0;
    6572 transvar->history->pscostweightedmean[d] = reopt->varhistory[bestrun][idx]->pscostweightedmean[d];
    6573 transvar->history->pscostvariance[d] = 0.0;
    6574 SCIPsetDebugMsg(set, "-> <%s> pscosts %4s: count=%g weightedmean=%g variance=%g\n", SCIPvarGetName(transvar),
    6575 (d == 0 ? "down" : "up"), transvar->history->pscostcount[d], transvar->history->pscostweightedmean[d],
    6576 transvar->history->pscostvariance[d]);
    6577 }
    6578
    6580
    6581 /* inference score */
    6582 avginference[d] = SCIPhistoryGetAvgInferences(reopt->varhistory[reopt->run-2][idx], (SCIP_BRANCHDIR)d);
    6583 SCIPhistoryIncInferenceSum(transvar->history, (SCIP_BRANCHDIR)d, avginference[d]);
    6584
    6585 /* cutoff score */
    6586 avgcutoff[d] = SCIPhistoryGetAvgCutoffs(reopt->varhistory[reopt->run-2][idx], (SCIP_BRANCHDIR)d);
    6587 SCIPhistoryIncCutoffSum(transvar->history, (SCIP_BRANCHDIR)d, avgcutoff[d]);
    6588
    6589 SCIPsetDebugMsg(set, "-> <%s> %4s scores: inf=%g cutoff=%g\n", SCIPvarGetName(transvar),
    6590 (d == 0 ? "down" : "up"), avginference[d], avgcutoff[d]);
    6591 }
    6592 }
    6593
    6594 return SCIP_OKAY;
    6595}
    6596
    6597/** updates the variable history */
    6599 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6600 SCIP_SET* set, /**< global SCIP settings */
    6601 SCIP_STAT* stat, /**< dynamic problem statistics */
    6602 BMS_BLKMEM* blkmem, /**< block memory */
    6603 SCIP_VAR** vars, /**< original variable array */
    6604 int nvars /**< number of original variables */
    6605 )
    6606{
    6607 assert(reopt != NULL);
    6608 assert(stat != NULL);
    6609 assert(blkmem != NULL);
    6610 assert(nvars >= 0);
    6611
    6612 if( !set->reopt_storevarhistory )
    6613 return SCIP_OKAY;
    6614
    6615 SCIPsetDebugMsg(set, "updating variable history\n");
    6616
    6617 if( reopt->varhistory[reopt->run-1] == NULL )
    6618 {
    6619 /* allocate memory */
    6620 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->varhistory[reopt->run-1], nvars) );
    6621
    6622 for( int v = 0; v < nvars; ++v )
    6623 {
    6624 SCIP_CALL( SCIPhistoryCreate(&(reopt->varhistory[reopt->run-1][v]), blkmem) );
    6625 }
    6626 }
    6627
    6628 /* update the history and scale them */
    6629 for( int v = 0; v < nvars; ++v )
    6630 {
    6631 SCIP_VAR* transvar;
    6632 int idx;
    6633
    6634 assert(SCIPvarIsOriginal(vars[v]));
    6635 idx = SCIPvarGetIndex(vars[v]);
    6636 assert(idx >= 0 && idx < nvars);
    6637
    6638 transvar = SCIPvarGetTransVar(vars[v]);
    6639 assert(transvar != NULL);
    6640
    6641 if( !SCIPvarIsActive(transvar) )
    6642 continue;
    6643
    6644 /* we store the complete history */
    6645 SCIPhistoryReset(reopt->varhistory[reopt->run-1][idx]);
    6646 SCIPhistoryUnite(reopt->varhistory[reopt->run-1][idx], transvar->history, FALSE);
    6647 }
    6648
    6649 return SCIP_OKAY;
    6650}
    6651
    6652/** reset the complete tree and set the given search frontier */
    6654 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6655 SCIP_SET* set, /**< global SCIP settings */
    6656 BMS_BLKMEM* blkmem, /**< block memory */
    6657 SCIP_REOPTNODE** representatives, /**< array of representatives */
    6658 int nrepresentatives, /**< number of representatives */
    6659 SCIP_Bool* success /**< pointer to store if the method was successful */
    6660 )
    6661{
    6662 SCIP_REOPTTREE* reopttree;
    6663 unsigned int id;
    6664
    6665 assert(reopt != NULL);
    6666 assert(set != NULL);
    6667 assert(blkmem != NULL);
    6668 assert(representatives != NULL);
    6669 assert(nrepresentatives > 0);
    6670
    6671 reopttree = reopt->reopttree;
    6672
    6673 /* reset the current search tree */
    6674 SCIP_CALL( reoptResetTree(reopt, set, blkmem, FALSE) );
    6675 assert(reopttree->nreoptnodes == 0);
    6676
    6677 /* create a new root node */
    6678 id = 0;
    6679 SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
    6680
    6681 /* set the reopttype */
    6682 reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
    6683
    6684 /* add all representatives */
    6685 for( int r = 0; r < nrepresentatives; ++r )
    6686 {
    6687 /* get an empty slot*/
    6688 id = SCIPqueueRemoveUInt(reopttree->openids);
    6689 assert(1 <= id && id < reopttree->reoptnodessize);
    6690 assert(reopttree->reoptnodes[id] == NULL);
    6691
    6692 SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
    6693 assert(reopttree->reoptnodes[id] != NULL);
    6694
    6695 /* set the new node
    6696 * 1. copy all variables, bounds, and boundtypes
    6697 * 2. copy all constraints
    6698 * 3. set the parent relation
    6699 */
    6700 if( representatives[r]->nvars > 0 )
    6701 {
    6702 assert(representatives[r]->nvars <= representatives[r]->varssize);
    6703
    6704 for( int v = 0; v < representatives[r]->nvars; ++v )
    6705 {
    6706 SCIP_CALL( SCIPreoptnodeAddBndchg(reopttree->reoptnodes[id], set, blkmem, representatives[r]->vars[v],
    6707 representatives[r]->varbounds[v], representatives[r]->varboundtypes[v]) );
    6708 }
    6709 }
    6710
    6711 if( representatives[r]->nconss > 0 )
    6712 {
    6713 assert(representatives[r]->nconss <= representatives[r]->consssize);
    6714
    6715 for( int c = 0; c < representatives[r]->nconss; ++c )
    6716 {
    6717 SCIP_CALL( SCIPreoptnodeAddCons(reopttree->reoptnodes[id], set, blkmem, representatives[r]->conss[c]->vars,
    6718 representatives[r]->conss[c]->vals, representatives[r]->conss[c]->boundtypes,
    6719 representatives[r]->conss[c]->lhs, representatives[r]->conss[c]->rhs,
    6720 representatives[r]->conss[c]->nvars, representatives[r]->conss[c]->constype,
    6721 representatives[r]->conss[c]->linear) );
    6722 }
    6723 }
    6724
    6725 reopttree->reoptnodes[id]->parentID = representatives[r]->parentID; /*lint !e732*/
    6726
    6727 assert(reopttree->reoptnodes[id]->parentID == 0);
    6728 assert(reopttree->reoptnodes[id]->nvars >= 0);
    6729 assert(reopttree->reoptnodes[id]->nvars <= reopttree->reoptnodes[id]->varssize);
    6730 assert(reopttree->reoptnodes[id]->nconss >= 0);
    6731
    6732 /* set the reopttype */
    6733 if( reopttree->reoptnodes[id]->nconss == 0 )
    6734 reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LEAF;
    6735 else
    6736 reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LOGICORNODE;
    6737
    6738 /* add the representative as a child of the root */
    6739 SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
    6740 }
    6741
    6742 SCIPsetDebugMsg(set, "-> new tree consists of %d nodes, the root has %d child nodes.\n",
    6743 reopttree->nreoptnodes, reopttree->reoptnodes[0]->nchilds);
    6744
    6745 (*success) = TRUE;
    6746
    6747 return SCIP_OKAY;
    6748}
    6749
    6750/** transforms a set of dual reductions into a linear constraint */
    6751static
    6753 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6754 SCIP_SET* set, /**< global SCIP settings */
    6755 BMS_BLKMEM* blkmem, /**< block memory */
    6756 SCIP_REOPTCONSDATA* consdata, /**< reoptimization constraint data that should represent to set of solutions
    6757 * pruned by the dual reductions */
    6758 SCIP_REOPTCONSDATA* dualreds /**< set of dual reductions */
    6759 )
    6760{
    6761 assert(reopt != NULL);
    6762 assert(set != NULL);
    6763 assert(blkmem != NULL);
    6764 assert(consdata != NULL);
    6765 assert(dualreds != NULL);
    6766
    6767 /* we have to transform the set of bound changes into a linear constraint */
    6768 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vars, dualreds->vars, dualreds->nvars) );
    6769 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &consdata->vals, dualreds->nvars) );
    6770 consdata->boundtypes = NULL;
    6771
    6772 consdata->varssize = dualreds->nvars;
    6773 consdata->nvars = dualreds->nvars;
    6774 consdata->constype = REOPT_CONSTYPE_DUALREDS;
    6775 consdata->linear = TRUE;
    6776
    6777 /* set lhs and rhs */
    6778 consdata->lhs = 1.0;
    6779 consdata->rhs = SCIPsetInfinity(set);
    6780
    6781 for( int v = 0; v < consdata->nvars; ++v )
    6782 {
    6783 assert(consdata->vars[v] != NULL);
    6784
    6785 /* the bound is 0.0, the variable has to appear with a coefficient +1.0 in the constraint, sides do not change */
    6786 if( SCIPsetIsEQ(set, dualreds->vals[v], 0.0) )
    6787 {
    6788 assert(dualreds->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
    6789 consdata->vals[v] = 1.0;
    6790 }
    6791 /* the bound is 1.0, the variable has to appear with a coefficient -1.0 in the constraint, we subtract -1.0 from lhs
    6792 * logicor: sum x_i + ~y_i >= 1
    6793 * <==> sum x_i + (1-y_i) >= 1
    6794 * <==> sum x_i - y_i >= 0
    6795 */
    6796 else
    6797 {
    6798 assert(SCIPsetIsEQ(set, dualreds->vals[v], 1.0));
    6799 assert(dualreds->boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
    6800
    6801 consdata->vals[v] = -1.0;
    6802 consdata->lhs -= 1.0;
    6803 }
    6804 }
    6805
    6806 return SCIP_OKAY;
    6807}
    6808
    6809
    6810/** transforms a set of dual reductions into a bounddisjuction constraint */
    6811static
    6813 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6814 SCIP_SET* set, /**< global SCIP settings */
    6815 BMS_BLKMEM* blkmem, /**< block memory */
    6816 SCIP_REOPTCONSDATA* consdata, /**< reoptimization constraint data that should represent to set of solutions
    6817 * pruned by the dual reductions */
    6818 SCIP_REOPTCONSDATA* dualreds /**< set of dual reductions */
    6819 )
    6820{
    6821 assert(reopt != NULL);
    6822 assert(set != NULL);
    6823 assert(blkmem != NULL);
    6824 assert(consdata != NULL);
    6825 assert(dualreds != NULL);
    6826
    6827 /* we have to transform the set of bound changes into a linear constraint */
    6828 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vars, dualreds->vars, dualreds->nvars) );
    6829 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vals, dualreds->vals, dualreds->nvars) );
    6830 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->boundtypes, dualreds->boundtypes, dualreds->nvars) );
    6831
    6832 consdata->varssize = dualreds->nvars;
    6833 consdata->nvars = dualreds->nvars;
    6834 consdata->constype = REOPT_CONSTYPE_DUALREDS;
    6835 consdata->linear = FALSE;
    6836
    6837 /* set lhs and rhs */
    6838 consdata->lhs = SCIP_UNKNOWN;
    6839 consdata->rhs = SCIP_UNKNOWN;
    6840
    6841 for( int v = 0; v < consdata->nvars; ++v )
    6842 {
    6843 SCIP_Real glbbd;
    6844
    6845 assert(consdata->vars[v] != NULL);
    6846
    6847 /* we do the followung to transformations:
    6848 * (a) x <= val ==> (x >= val+1)
    6849 * (b) x >= val ==> (x <= val-1)
    6850 */
    6851 if( consdata->boundtypes[v] == SCIP_BOUNDTYPE_UPPER )
    6852 {
    6853 glbbd = SCIPvarGetUbGlobal(consdata->vars[v]);
    6854 consdata->vals[v] = MIN(consdata->vals[v]+1.0, glbbd);
    6855 }
    6856 else
    6857 {
    6858 assert(dualreds->boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
    6859 glbbd = SCIPvarGetLbGlobal(consdata->vars[v]);
    6860 consdata->vals[v] = MAX(glbbd, consdata->vals[v]-1.0);
    6861 }
    6862 consdata->boundtypes[v] = (SCIP_BOUNDTYPE)(SCIP_BOUNDTYPE_UPPER - consdata->boundtypes[v]); /*lint !e656*/
    6863 }
    6864
    6865 return SCIP_OKAY;
    6866}
    6867
    6868/** splits the root into several nodes and moves the child nodes of the root to one of the created nodes */
    6870 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6871 SCIP_TREE* tree, /**< branch and bound tree */
    6872 SCIP_SET* set, /**< global SCIP settings */
    6873 SCIP_STAT* stat, /**< dynamic SCIP statistics */
    6874 BMS_BLKMEM* blkmem, /**< block memory */
    6875 int* ncreatedchilds, /**< pointer to store the number of created nodes */
    6876 int* naddedconss /**< pointer to store the number added constraints */
    6877 )
    6878{
    6879 SCIP_REOPTTREE* reopttree;
    6880 SCIP_REOPTNODE** reoptnodes;
    6881 SCIP_REOPTCONSDATA* consdata;
    6882 SCIP_VAR** vars;
    6883 SCIP_Real* bounds;
    6884 SCIP_BOUNDTYPE* boundtypes;
    6885 int* perm = NULL;
    6886 unsigned int id;
    6887 int nbndchgs;
    6888 int nchilds;
    6889 int v;
    6890
    6891 assert(reopt != NULL);
    6892 assert(set != NULL);
    6893 assert(stat != NULL);
    6894 assert(blkmem != NULL);
    6895
    6896 reopttree = reopt->reopttree;
    6897 assert(reopttree != NULL);
    6898
    6899 reoptnodes = reopttree->reoptnodes;
    6900 assert(reoptnodes != NULL);
    6901 assert(reoptnodes[0] != NULL);
    6902 assert(reoptnodes[0]->dualreds);
    6903 assert(reoptnodes[0]->reopttype == (unsigned int)SCIP_REOPTTYPE_STRBRANCHED);
    6904
    6905 nchilds = reoptnodes[0]->nchilds;
    6906
    6907 assert(reoptnodes[0]->dualredscur != NULL);
    6908 nbndchgs = reoptnodes[0]->dualredscur->nvars;
    6909
    6910 (*ncreatedchilds) = 0;
    6911 (*naddedconss) = 0;
    6912
    6913 /* create a node with all variables fixed, i.e., reconstruct the root of the last iteration */
    6914
    6915 /* ensure that two free slots are available */
    6916 SCIP_CALL( reopttreeCheckMemory(reopttree, set, blkmem) );
    6917 id = SCIPqueueRemoveUInt(reopttree->openids);
    6918
    6919 assert(0 < id && id < reopt->reopttree->reoptnodessize);
    6920 assert(reoptnodes[id] == NULL || reoptnodes[id]->nvars == 0);
    6921
    6922 /* 1. create the node
    6923 * 2. add all bound changes
    6924 * 3. move all child nodes to id
    6925 * 4. add id as a child of the root node
    6926 */
    6927 SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
    6928 reoptnodes[id]->parentID = 0;
    6929 reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
    6930
    6931 /* check memory */
    6932 SCIP_CALL( reoptnodeCheckMemory(reoptnodes[id], set, blkmem, nbndchgs, nchilds, 0) );
    6933 assert(reoptnodes[id]->varssize >= nbndchgs);
    6934 assert(reoptnodes[id]->nvars == 0);
    6935 assert(reoptnodes[id]->vars != NULL);
    6936 assert(reoptnodes[id]->varbounds != NULL);
    6937 assert(reoptnodes[id]->varboundtypes != NULL);
    6938
    6939 /* create a permutation array */
    6940 if( !set->reopt_usesplitcons )
    6941 {
    6942 assert(perm == NULL);
    6943 SCIP_CALL( SCIPsetAllocBufferArray(set, &perm, nbndchgs) );
    6944 }
    6945
    6946 /* copy bounds */
    6947 for( v = 0; v < nbndchgs; ++v )
    6948 {
    6949 reoptnodes[id]->vars[v] = reoptnodes[0]->dualredscur->vars[v];
    6950 reoptnodes[id]->varbounds[v] = reoptnodes[0]->dualredscur->vals[v];
    6951 reoptnodes[id]->varboundtypes[v] = reoptnodes[0]->dualredscur->boundtypes[v];
    6952 ++reoptnodes[id]->nvars;
    6953
    6954 /* fill a permutation array */
    6955 if( !set->reopt_usesplitcons )
    6956 perm[v] = v; /*lint !e613*/
    6957 }
    6958 assert(reoptnodes[id]->nvars == reoptnodes[0]->dualredscur->nvars);
    6959
    6960 /* move the children */
    6961 SCIP_CALL( reoptMoveIDs(reopttree, set, blkmem, 0, id) );
    6962 assert(reoptnodes[0]->nchilds == 0);
    6963
    6964 /* add the new reoptimization node as a child of the root node */
    6965 SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
    6966
    6967 ++(*ncreatedchilds);
    6968
    6969 if( set->reopt_usesplitcons )
    6970 {
    6971 int nbinvars = 0;
    6972#ifndef NDEBUG
    6973 int nintvars = 0;
    6974 int ncontvars = 0;
    6975#endif
    6976
    6977 assert(*ncreatedchilds == 1);
    6978
    6979 /* ensure that there is a free slots */
    6980 SCIP_CALL( reopttreeCheckMemory(reopttree, set, blkmem) );
    6981 id = SCIPqueueRemoveUInt(reopttree->openids);
    6982 assert(0 < id && id < reopt->reopttree->reoptnodessize);
    6983
    6984 /* 1. create the node
    6985 * 2. add the constraint to ensure that at least one
    6986 * variable gets different
    6987 * 3. add id as a child of the root node
    6988 */
    6989 SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
    6990 reoptnodes[id]->parentID = 0;
    6991 reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LOGICORNODE;
    6992
    6993 /* check memory for added constraints */
    6994 SCIP_CALL( reoptnodeCheckMemory(reoptnodes[id], set, blkmem, 0, 0, 1) );
    6995
    6996 /* create the constraint */
    6997 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reoptnodes[id]->conss[0]) );
    6998 consdata = reoptnodes[id]->conss[0];
    6999
    7000 /* count number of binary, integer, and continuous varibales */
    7001 for( v = 0; v < nbndchgs; ++v )
    7002 {
    7003 if( SCIPvarGetType(reoptnodes[0]->dualredscur->vars[v]) == SCIP_VARTYPE_BINARY
    7004 && !SCIPvarIsImpliedIntegral(reoptnodes[0]->dualredscur->vars[v]) )
    7005 ++nbinvars;
    7006#ifndef NDEBUG
    7007 else if( SCIPvarIsIntegral(reoptnodes[0]->dualredscur->vars[v]) )
    7008 ++nintvars;
    7009 else
    7010 ++ncontvars;
    7011#endif
    7012 }
    7013
    7014 /* we create a linear constraint, since all variables are binary */
    7015 if( nbinvars == nbndchgs )
    7016 {
    7017 SCIP_CALL( transformDualredsToLinear(reopt, set, blkmem, consdata, reoptnodes[0]->dualredscur) );
    7018 }
    7019 /* we create a bounddisjunction constraint, since at least one variable is (implicit) integer or continuous */
    7020 else
    7021 {
    7022 assert(nintvars > 0 || ncontvars > 0);
    7023 SCIP_CALL( transformDualredsToBounddisjunction(reopt, set, blkmem, consdata, reoptnodes[0]->dualredscur) );
    7024 }
    7025 ++reoptnodes[id]->nconss;
    7026
    7027 /* add id as a child of the root node */
    7028 SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
    7029 ++(*ncreatedchilds);
    7030
    7031 ++(*naddedconss);
    7032 }
    7033 else
    7034 {
    7035 int nvars;
    7036
    7037 assert(*ncreatedchilds == 1);
    7038 assert(perm != NULL);
    7039
    7040 vars = reoptnodes[0]->dualredscur->vars;
    7041 bounds = reoptnodes[0]->dualredscur->vals;
    7042 boundtypes = reoptnodes[0]->dualredscur->boundtypes;
    7043 nvars = reoptnodes[0]->dualredscur->nvars;
    7044 assert(perm[0] == 0 && perm[nvars-1] == nvars-1);
    7045
    7046 /* calculate the order of the variables */
    7047 switch (set->reopt_varorderinterdiction)
    7048 {
    7049 /* default order */
    7050 case 'd':
    7051 break;
    7052
    7053 /* inference order */
    7054 case 'i':
    7055 SCIP_CALL( getInferenceOrder(set, stat, perm, vars, bounds, boundtypes, nvars) );
    7056 break;
    7057
    7058 /* random order */
    7059 case 'r':
    7060 SCIPrandomPermuteIntArray(reopt->randnumgen, perm, 0, nvars-1);
    7061 break;
    7062
    7063 default:
    7064 return SCIP_INVALIDDATA;
    7065 }
    7066
    7067 /* create nvars nodes in the fashion of interdiction branching */
    7068 for( int c = 0; c < nvars; ++c )
    7069 {
    7070 /* ensure that two free slots are available */
    7071 SCIP_CALL( reopttreeCheckMemory(reopttree, set, blkmem) );
    7072 id = SCIPqueueRemoveUInt(reopttree->openids);
    7073
    7074 assert(0 < id && id < reopt->reopttree->reoptnodessize);
    7075 assert(reoptnodes[id] == NULL || reoptnodes[id]->nvars == 0);
    7076
    7077 /* 1. create the node
    7078 * 2. fix the first v bound changes to vals[v] and v+1 to vals[v] +/- 1 (depending on the bound- and vartype)
    7079 * 4. add the ID id as a child of the root node
    7080 */
    7081 SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
    7082 reoptnodes[id]->parentID = 0;
    7083 reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
    7084
    7085 /* check memory */
    7086 SCIP_CALL( reoptnodeCheckMemory(reoptnodes[id], set, blkmem, c+1, 0, 0) );
    7087 assert(reoptnodes[id]->varssize >= perm[c]+1);
    7088 assert(reoptnodes[id]->nvars == 0);
    7089 assert(reoptnodes[id]->vars != NULL);
    7090 assert(reoptnodes[id]->varbounds != NULL);
    7091 assert(reoptnodes[id]->varboundtypes != NULL);
    7092
    7093 /* the permutation is the identity */
    7094 if( set->reopt_varorderinterdiction == 'd' )
    7095 {
    7096 /* copy first c bound changes */
    7097 for( v = 0; v < c; ++v )
    7098 {
    7099 reoptnodes[id]->vars[v] = vars[v];
    7100 reoptnodes[id]->varbounds[v] = bounds[v];
    7101 reoptnodes[id]->varboundtypes[v] = boundtypes[v];
    7102 }
    7103 }
    7104 else
    7105 {
    7106 /* copy first c bound changes */
    7107 for( v = 0; v < c; ++v )
    7108 {
    7109 reoptnodes[id]->vars[v] = vars[perm[v]];
    7110 reoptnodes[id]->varbounds[v] = bounds[perm[v]];
    7111 reoptnodes[id]->varboundtypes[v] = boundtypes[perm[v]];
    7112 }
    7113 }
    7114 reoptnodes[id]->nvars += c;
    7115
    7116 /* set bound change v+1 (= c) to vals[v] +/- 1 (depending on the bound- and vartype) */
    7117 assert(v == c);
    7118 reoptnodes[id]->vars[c] = vars[perm[c]];
    7119 reoptnodes[id]->varbounds[c] = bounds[perm[c]];
    7120 if( SCIPvarIsIntegral(vars[perm[c]]) )
    7121 {
    7122 if( boundtypes[perm[c]] == SCIP_BOUNDTYPE_LOWER )
    7123 reoptnodes[id]->varbounds[c] -= 1.0;
    7124 else
    7125 reoptnodes[id]->varbounds[c] += 1.0;
    7126 }
    7127 reoptnodes[id]->varboundtypes[c] = (boundtypes[perm[c]] == SCIP_BOUNDTYPE_UPPER ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
    7128 ++reoptnodes[id]->nvars;
    7129
    7130 /* add dummy1 as a child of the root node */
    7131 SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
    7132
    7133 ++(*ncreatedchilds);
    7134 }
    7135
    7136 assert(*ncreatedchilds == nvars+1);
    7137
    7139 perm = NULL;
    7140 }
    7141 assert(perm == NULL);
    7142
    7143 /* free the current dualredscur and assign dualredsnex */
    7144 assert(reoptnodes[0]->dualredscur->vars != NULL);
    7145 assert(reoptnodes[0]->dualredscur->vals != NULL);
    7146 assert(reoptnodes[0]->dualredscur->boundtypes != NULL);
    7147
    7148 /* free the current dualredscur and assign dualredsnex */
    7149 SCIP_CALL( reoptnodeUpdateDualConss(reoptnodes[0], blkmem) );
    7150
    7151 /* change the reopttype of the root node */
    7153
    7154 return SCIP_OKAY;
    7155}
    7156
    7157/** reset the stored information abound bound changes based on dual information */
    7159 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7160 SCIP_NODE* node, /**< node of the search tree */
    7161 BMS_BLKMEM* blkmem /**< block memory */
    7162 )
    7163{
    7164 unsigned int id;
    7165
    7166 assert(reopt != NULL);
    7167 assert(node != NULL);
    7168
    7169 id = SCIPnodeGetReoptID(node);
    7170 assert(id < reopt->reopttree->reoptnodessize);
    7171
    7172 /* return if the node is not part of the reoptimization tree */
    7173 if( SCIPnodeGetDepth(node) > 0 && id == 0 )
    7174 return SCIP_OKAY;
    7175
    7176 /* reset the dual constraint */
    7177 SCIP_CALL( reoptnodeResetDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
    7178
    7179 return SCIP_OKAY;
    7180}
    7181
    7182/** return the branching path stored of the given node in the reoptimization tree */
    7184 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7185 SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
    7186 SCIP_VAR** vars, /**< array for variables */
    7187 SCIP_Real* vals, /**< array for values */
    7188 SCIP_BOUNDTYPE* boundtypes, /**< array for bound types */
    7189 int varssize, /**< size of arrays vars, vals, and boundtypes */
    7190 int* nbndchgs, /**< pointer to store the number of bound changes */
    7191 int* nbndchgsafterdual /**< pointer to store the number of bound changes applied after
    7192 * the first dual reduction at the given node */
    7193 )
    7194{
    7195 int v;
    7196 int nvars2;
    7197 int nafterdualvars2;
    7198
    7199 assert(reopt != NULL);
    7200 assert(reoptnode != NULL);
    7201 assert(vars != NULL);
    7202 assert(vals != NULL);
    7203 assert(boundtypes != NULL);
    7204
    7205 (*nbndchgs) = reoptnode->nvars;
    7206 (*nbndchgsafterdual) = reoptnode->nafterdualvars;
    7207
    7208 /* return if the size of the given array is not large enough */
    7209 if( varssize == 0 || varssize < *nbndchgs + *nbndchgsafterdual )
    7210 return;
    7211
    7212 /* add all bound changes made by branching (including dual reductions) */
    7213 for( v = 0; v < *nbndchgs; ++v )
    7214 {
    7215 vars[v] = reoptnode->vars[v];
    7216 vals[v] = reoptnode->varbounds[v];
    7217 boundtypes[v] = reoptnode->varboundtypes[v];
    7218 }
    7219
    7220 /* add all bound changes made applied after a dual reduction */
    7221 for( ; v < *nbndchgs + *nbndchgsafterdual; ++v )
    7222 {
    7223 vars[v] = reoptnode->afterdualvars[v-(*nbndchgs)];
    7224 vals[v] = reoptnode->afterdualvarbounds[v-(*nbndchgs)];
    7225 boundtypes[v] = reoptnode->afterdualvarboundtypes[v-(*nbndchgs)];
    7226 }
    7227
    7228 /* go along the root path within the reoptimization tree */
    7229 if( reoptnode->parentID != 0 )
    7230 {
    7231 SCIP_REOPTNODE* parent;
    7232
    7233 parent = reopt->reopttree->reoptnodes[reoptnode->parentID];
    7234 SCIPreoptnodeGetPath(reopt, parent, &vars[v], &vals[v], &boundtypes[v], varssize, &nvars2, &nafterdualvars2);
    7235
    7236 (*nbndchgs) += nvars2;
    7237 (*nbndchgsafterdual) += nafterdualvars2;
    7238 }
    7239}
    7240
    7241/** delete a node stored in the reoptimization tree */
    7243 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7244 SCIP_SET* set, /**< global SCIP settings */
    7245 unsigned int id, /**< id of a stored node */
    7246 BMS_BLKMEM* blkmem /**< block memory */
    7247 )
    7248{
    7249 assert(reopt != NULL);
    7250 assert(reopt->reopttree != NULL);
    7251 assert(id < reopt->reopttree->reoptnodessize);
    7252 assert(reopt->reopttree->reoptnodes[id] != NULL);
    7253 assert(blkmem != NULL);
    7254
    7255 SCIP_CALL( reopttreeDeleteNode(reopt->reopttree, set, blkmem, id, TRUE) );
    7257
    7258 return SCIP_OKAY;
    7259}
    7260
    7261/** reactivate the given @p reoptnode and split them into several nodes if necessary */
    7263 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7264 SCIP* scip, /**< SCIP data structure */
    7265 SCIP_SET* set, /**< global SCIP settings */
    7266 SCIP_STAT* stat, /**< dynamic problem statistics */
    7267 SCIP_PROB* transprob, /**< transformed problem */
    7268 SCIP_PROB* origprob, /**< original problem */
    7269 SCIP_TREE* tree, /**< branching tree */
    7270 SCIP_LP* lp, /**< current LP */
    7271 SCIP_BRANCHCAND* branchcand, /**< branching candidate */
    7272 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    7273 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    7274 SCIP_CLIQUETABLE* cliquetable, /**< clique table */
    7275 BMS_BLKMEM* blkmem, /**< block memory */
    7276 SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree to reactivate */
    7277 unsigned int id, /**< id of the node to reactivate */
    7278 SCIP_Real estimate, /**< estimate of the child nodes that should be created */
    7279 SCIP_NODE** childnodes, /**< array to store the created child nodes */
    7280 int* ncreatedchilds, /**< pointer to store number of created child nodes */
    7281 int* naddedconss, /**< pointer to store number of generated constraints */
    7282 int childnodessize, /**< available size of childnodes array */
    7283 SCIP_Bool* success /**< pointer store the result */
    7284 )
    7285{
    7286 assert(reopt != NULL);
    7287 assert(scip != NULL);
    7288 assert(set != NULL);
    7289 assert(stat != NULL);
    7290 assert(transprob != NULL);
    7291 assert(origprob != NULL);
    7292 assert(tree != NULL);
    7293 assert(lp != NULL);
    7294 assert(branchcand != NULL);
    7295 assert(eventqueue != NULL);
    7296 assert(cliquetable != NULL);
    7297 assert(blkmem != NULL);
    7298 assert(reoptnode != NULL);
    7299 assert(childnodes != NULL);
    7300 assert(reopt->reopttree != NULL);
    7301 assert(id < reopt->reopttree->reoptnodessize);
    7302 assert(success != NULL);
    7303
    7304 SCIPsetDebugMsg(set, "reactivating node at id %u:\n", id);
    7305
    7306 *success = FALSE;
    7307
    7308 /* check if we need to split the node */
    7309 if( reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_STRBRANCHED
    7310 || reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_INFSUBTREE )
    7311 {
    7312 assert(reoptnode->dualreds);
    7313
    7314 /* we want use a constraint to split the node into two disjoint node */
    7315 if( set->reopt_usesplitcons )
    7316 {
    7317 if( reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_INFSUBTREE )
    7318 {
    7319 assert(reoptnode->dualredscur != NULL);
    7320 assert(reoptnode->dualredscur->constype == REOPT_CONSTYPE_INFSUBTREE);
    7321 (*ncreatedchilds) = 1;
    7322 }
    7323 else
    7324 {
    7325 assert(reoptnode->dualredscur != NULL);
    7326 assert(reoptnode->dualredscur->constype == REOPT_CONSTYPE_DUALREDS);
    7327 (*ncreatedchilds) = 2;
    7328 }
    7329
    7330 /* in both cases we add exactly one constraint */
    7331 (*naddedconss) = 1;
    7332
    7333 if( childnodessize < *ncreatedchilds )
    7334 return SCIP_OKAY;
    7335
    7336 /* generate the nodes */
    7337 for( int c = 0; c < *ncreatedchilds; ++c )
    7338 {
    7339 /* create the child node */
    7340 SCIP_CALL( SCIPnodeCreateChild(&childnodes[c], blkmem, set, stat, tree, 1.0, estimate) );
    7341
    7342 /* change all bounds; convert the bound changes after the first based on dual reductions into branching
    7343 * for second node only. if we generate only one node, i.e., the pruned part, we do not need this
    7344 * changes anyway.
    7345 */
    7346 SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
    7347 eventfilter, cliquetable, blkmem, childnodes[c], id, c == 1) );
    7348
    7349 /* add all local constraints */
    7350 SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[c], id) );
    7351
    7352 /* we can use the old lowerbound if the objective function has not changed */
    7353 if( !reopt->objhaschanged && SCIPsetIsGT(set, reopt->reopttree->reoptnodes[id]->lowerbound, estimate) )
    7354 SCIPnodeSetEstimate(childnodes[c], set, reopt->reopttree->reoptnodes[id]->lowerbound);
    7355
    7356 if( c == 0 )
    7357 {
    7358 /* in both cases the node generated first represents the pruned is currently not part of the reoptimization tree */
    7360
    7361 /* add the constraint to the node */
    7362 assert(reopt->reopttree->reoptnodes[id]->dualredscur != NULL);
    7363 SCIP_CALL( addSplitcons(reopt, scip, set, stat, blkmem, transprob, origprob, tree, lp, branchcand,
    7364 eventqueue, eventfilter, cliquetable, childnodes[c], id) );
    7365
    7366 /* fixBounds() does the same, but in this case we go not into it */
    7367 if( reoptnode->dualredscur->constype == REOPT_CONSTYPE_INFSUBTREE )
    7368 {
    7369 assert(reoptnode->dualredscur->nvars > 0);
    7370 assert(reoptnode->dualredscur->varssize > 0);
    7371
    7372 /* delete dualredscur and move dualredsnex -> dualredscur */
    7373 SCIP_CALL( reoptnodeUpdateDualConss(reoptnode, blkmem) );
    7374 }
    7375
    7376 /* the added constraint could be deleted due to propagation, thus, we store the node in the reoptimization
    7377 * tree. the node has to stored anyway, because of the constraint representing the dual reductions
    7378 */
    7379 SCIP_CALL( addNode(reopt, set, lp, blkmem, childnodes[c], SCIP_REOPTTYPE_LOGICORNODE, FALSE, FALSE,
    7380 -SCIPsetInfinity(set)) );
    7381 }
    7382 else
    7383 {
    7384 /* if we reach this lines of code, the current node represents the original node including all bound
    7385 * changes based in dual information.
    7386 */
    7387 assert(reoptnode->dualredscur->constype == REOPT_CONSTYPE_DUALREDS);
    7388 if( reoptnode->nconss == 0 )
    7390 else
    7392
    7393 /* fix all bound changes based on dual information and convert them into branchings */
    7394 assert(reopt->reopttree->reoptnodes[id]->dualredscur != NULL);
    7395 SCIP_CALL( fixBounds(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, eventfilter,
    7396 cliquetable, blkmem, childnodes[c], id, TRUE) );
    7397
    7398 /* set the unique id the id of the original node */
    7399 SCIPnodeSetReoptID(childnodes[c], id);
    7400 }
    7401 }
    7402
    7403 /* reset the stored dual constraints */
    7405
    7406 /* set the reoptimization type */
    7407 if( reopt->reopttree->reoptnodes[id]->dualreds )
    7408 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_STRBRANCHED;
    7409 else
    7410 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
    7411
    7412 *success = TRUE;
    7413 }
    7414 else
    7415 {
    7416 SCIP_VAR** vars;
    7417 SCIP_Real* bounds;
    7418 SCIP_BOUNDTYPE* boundtypes;
    7419 int* perm = NULL;
    7420 int nvars;
    7421
    7422 vars = reoptnode->dualredscur->vars;
    7423 bounds = reoptnode->dualredscur->vals;
    7424 boundtypes = reoptnode->dualredscur->boundtypes;
    7425 nvars = reoptnode->dualredscur->nvars;
    7426
    7427 *ncreatedchilds = nvars+1;
    7428 *naddedconss = 0;
    7429
    7430 /* check if there is enough memory allocated */
    7431 if( childnodessize < *ncreatedchilds )
    7432 return SCIP_OKAY;
    7433
    7434 /* create and fill permutation array */
    7435 SCIP_CALL( SCIPsetAllocBufferArray(set, &perm, nvars) );
    7436 for( int c = 0; c < nvars; ++c )
    7437 perm[c] = c;
    7438
    7439 /* calculate the order of the variables */
    7440 switch (set->reopt_varorderinterdiction)
    7441 {
    7442 /* default order */
    7443 case 'd':
    7444 break;
    7445
    7446 /* inference order */
    7447 case 'i':
    7448 SCIP_CALL( getInferenceOrder(set, stat, perm, vars, bounds, boundtypes, nvars) );
    7449 break;
    7450
    7451 /* random order */
    7452 case 'r':
    7453 SCIPrandomPermuteIntArray(reopt->randnumgen, perm, 0, nvars-1);
    7454 break;
    7455
    7456 default:
    7457 return SCIP_INVALIDDATA;
    7458 }
    7459
    7460 assert(reopt->reopttree->reoptnodes[id] != NULL);
    7461 reoptnode = reopt->reopttree->reoptnodes[id];
    7462
    7463 /* enough that the node need to split */
    7464 assert(reoptnode->dualreds);
    7465
    7466 /* iterate over all nodes and change the necessary bounds (nodes[0] corresponds to the original one)
    7467 * we need to do this in the reverse order because we want to transform the bound changes based on dual information
    7468 * into branching decisions at nodes[0].
    7469 */
    7470 for( int c = nvars; c >= 0; --c )
    7471 {
    7472 /* create the child node */
    7473 SCIP_CALL( SCIPnodeCreateChild(&childnodes[c], blkmem, set, stat, tree, 1.0, estimate) );
    7474
    7475#ifdef SCIP_MORE_DEBUG
    7476 SCIPsetDebugMsg(set, " change bounds at node %lld\n", SCIPnodeGetNumber(childnodes[c]));
    7477#endif
    7478
    7479 /* change all bounds */
    7480 SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
    7481 eventfilter, cliquetable, blkmem, childnodes[c], id, FALSE) );
    7482
    7483 /* reconstruct the original node and the pruned part, respectively */
    7484 if( c == 0 )
    7485 {
    7486 /* fix bound changes based on dual information and convert all these bound changes to normal bound changes */
    7487 SCIP_CALL( fixBounds(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, eventfilter,
    7488 cliquetable, blkmem, childnodes[c], id, TRUE) );
    7489
    7490 /* set the reopttype of the node */
    7492
    7493 /* set the unique id */
    7494 SCIPnodeSetReoptID(childnodes[c], id);
    7495 }
    7496 else
    7497 {
    7498 /* fix the first c bound changes and negate the (c+1)th */
    7499 SCIP_CALL( fixInterdiction(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, eventfilter,
    7500 cliquetable, blkmem, childnodes[c], id, perm, vars, bounds, boundtypes, nvars, c) );
    7501 }
    7502
    7503 /* add all local constraints */
    7504 SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[c], id) );
    7505
    7506 /* we can use the old lowerbound if the objective function has not changed */
    7507 if( !reopt->objhaschanged && SCIPsetIsGT(set, reopt->reopttree->reoptnodes[id]->lowerbound, estimate) )
    7508 SCIPnodeSetEstimate(childnodes[c], set, reopt->reopttree->reoptnodes[id]->lowerbound);
    7509 }
    7510
    7511 /* free buffer array */
    7513
    7514 /* reset the stored dual constraints */
    7516
    7517 /* set the reoptimization type to transit */
    7518 if( reopt->reopttree->reoptnodes[id]->dualreds )
    7519 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_STRBRANCHED;
    7520 else
    7521 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
    7522
    7523 *success = TRUE;
    7524 }
    7525 }
    7526 else
    7527 {
    7528 /* we need the create exactly one node to reconstruct the node itself and no additional constraint */
    7529 (*ncreatedchilds) = 1;
    7530 (*naddedconss) = 0;
    7531
    7532 if( childnodessize < *ncreatedchilds )
    7533 return SCIP_OKAY;
    7534
    7535 /* create the child node */
    7536 SCIP_CALL( SCIPnodeCreateChild(&childnodes[0], blkmem, set, stat, tree, 1.0, estimate) );
    7537
    7538 /* change all bounds */
    7539 assert(reoptnode->nafterdualvars == 0);
    7540 SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
    7541 eventfilter, cliquetable, blkmem, childnodes[0], id, FALSE) );
    7542
    7543 /* add all local constraints */
    7544 SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[0], id) );
    7545
    7546 /* we can use the old lowerbound if the objective function has not changed */
    7547 if( !reopt->objhaschanged && SCIPsetIsGT(set, reopt->reopttree->reoptnodes[id]->lowerbound, estimate) )
    7548 SCIPnodeSetEstimate(childnodes[0], set, reopt->reopttree->reoptnodes[id]->lowerbound);
    7549
    7550 /* set the reopttype */
    7551 assert(reoptnode->reopttype != (unsigned int)SCIP_REOPTTYPE_INFSUBTREE
    7552 && reoptnode->reopttype != (unsigned int)SCIP_REOPTTYPE_STRBRANCHED);
    7553 SCIPnodeSetReopttype(childnodes[0], (SCIP_REOPTTYPE)reoptnode->reopttype);
    7554
    7555 /* set the unique id */
    7556 SCIPnodeSetReoptID(childnodes[0], id);
    7557
    7558 *success = TRUE;
    7559 }
    7560
    7561 return SCIP_OKAY;
    7562}
    7563
    7564/** returns the time needed to store the nodes for reoptimization */
    7566 SCIP_REOPT* reopt /**< reoptimization data structure */
    7567 )
    7568{
    7569 assert(reopt != NULL);
    7570
    7571 return SCIPclockGetTime(reopt->savingtime);
    7572}
    7573
    7574/** add the stored constraints globally to the problem */
    7576 SCIP* scip, /**< SCIP data structure */
    7577 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7578 SCIP_SET* set, /**< global SCIP settings */
    7579 SCIP_STAT* stat, /**< dynamic problem statistics */
    7580 BMS_BLKMEM* blkmem /**< block memory */
    7581 )
    7582{
    7583 char name[SCIP_MAXSTRLEN];
    7584
    7585 assert(scip != NULL);
    7586 assert(reopt != NULL);
    7587 assert(set != NULL);
    7588 assert(stat != NULL);
    7589 assert(blkmem != NULL);
    7590
    7591 if( reopt->glbconss == NULL || reopt->nglbconss == 0 )
    7592 return SCIP_OKAY;
    7593
    7594 for( int c = reopt->nglbconss-1; c >= 0; --c )
    7595 {
    7596 SCIP_CONS* cons;
    7597 SCIP_VAR** consvars;
    7598 int nbinvars;
    7599 int nintvars;
    7600
    7601 assert(reopt->glbconss[c] != NULL);
    7602 assert(reopt->glbconss[c]->nvars > 0);
    7603
    7604 cons = NULL;
    7605 consvars = NULL;
    7606 nbinvars = 0;
    7607 nintvars = 0;
    7608
    7609 /* check if we can use a logic-or or if we have to use a bounddisjuction constraint */
    7610 for( int v = 0; v < reopt->glbconss[c]->nvars; ++v )
    7611 {
    7612 if( SCIPvarGetType(reopt->glbconss[c]->vars[v]) == SCIP_VARTYPE_BINARY
    7613 && !SCIPvarIsImpliedIntegral(reopt->glbconss[c]->vars[v]) )
    7614 ++nbinvars;
    7615 else if( SCIPvarIsIntegral(reopt->glbconss[c]->vars[v]) )
    7616 ++nintvars;
    7617 else
    7618 {
    7619 SCIPerrorMessage("Expected variable type binary or (impl.) integer for variable <%s> in global constraint at pos. %d.\n",
    7620 SCIPvarGetName(reopt->glbconss[c]->vars[v]), c);
    7621 return SCIP_INVALIDDATA;
    7622 }
    7623 }
    7624
    7625 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "glb_%s_%d_%d", reopt->glbconss[c]->constype == REOPT_CONSTYPE_CUT ? "cut" : "inf", reopt->run, c);
    7626
    7627 /* @todo use active representatives */
    7628
    7629 /* all variables are binary, we can create a logic-or constraint */
    7630 if( nbinvars == reopt->glbconss[c]->nvars )
    7631 {
    7632 SCIPsetDebugMsg(set, "-> add logic-or constraints with %d binvars\n", nbinvars);
    7633
    7634 /* allocate buffer */
    7635 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, reopt->glbconss[c]->nvars) );
    7636
    7637 for( int v = 0; v < reopt->glbconss[c]->nvars; ++v )
    7638 {
    7639 consvars[v] = reopt->glbconss[c]->vars[v];
    7640 assert(SCIPvarIsOriginal(consvars[v]));
    7641
    7642 /* negate the variable if it was fixed to 1 */
    7643 if( SCIPsetIsFeasEQ(set, reopt->glbconss[c]->vals[v], 0.0) )
    7644 {
    7645 assert(reopt->glbconss[c]->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
    7646 SCIP_CALL( SCIPvarNegate(consvars[v], blkmem, set, stat, &consvars[v]) );
    7647 }
    7648 }
    7649
    7650 /* create the logic-or constraint */
    7651 SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, reopt->glbconss[c]->nvars,
    7652 consvars, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
    7653
    7654 /* free buffer */
    7655 SCIPfreeBufferArray(scip, &consvars);
    7656 }
    7657 /* not all variables are binary, we need a bounddisjunction constraint */
    7658 else
    7659 {
    7660 assert(reopt->glbconss[c]->nvars == nbinvars + 2*nintvars);
    7661
    7662 SCIPsetDebugMsg(set, "-> add bounddisjuction constraints with %d binvars, %d intvars\n", nbinvars, (int) (2*nintvars));
    7663
    7664 /* create the bounddisjuction constraint */
    7665 SCIP_CALL( SCIPcreateConsBasicBounddisjunction(scip, &cons, name, reopt->glbconss[c]->nvars, reopt->glbconss[c]->vars,
    7666 reopt->glbconss[c]->boundtypes, reopt->glbconss[c]->vals) );
    7667 }
    7668
    7669#ifdef SCIP_DEBUG_CONSS
    7671#endif
    7672
    7673 SCIP_CALL( SCIPaddCons(scip, cons) );
    7674
    7675 /* remember the constraint for re-activation */
    7676 assert(!SCIPhashsetExists(reopt->activeconssset, (void*)cons));
    7677 SCIP_CALL( SCIPhashsetInsert(reopt->activeconssset, blkmem, (void*)cons) );
    7678 SCIP_CALL( ensureActiveconssSize(reopt, set, blkmem, reopt->nactiveconss + 1) );
    7679 assert(reopt->nactiveconss < reopt->nmaxactiveconss);
    7680 reopt->activeconss[reopt->nactiveconss++] = cons;
    7681
    7682 /* don't release the constraint because we would need to capture the constraint anyway */
    7683
    7684 /* mark the constraint as empty */
    7685 reopt->glbconss[c]->nvars = 0;
    7686 }
    7687
    7688 SCIPsetDebugMsg(set, "added %d gobal constraints\n", reopt->nglbconss);
    7689
    7690 /* reset number of global constraints */
    7691 reopt->nglbconss = 0;
    7692
    7693 return SCIP_OKAY;
    7694}
    7695
    7696/** add the stored cuts to the separation storage */
    7698 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7699 SCIP_NODE* node, /**< current focus node */
    7700 SCIP_SEPASTORE* sepastore, /**< separation storage */
    7701 SCIP_CUTPOOL* cutpool, /**< global cutpool */
    7702 BMS_BLKMEM* blkmem, /**< block memory */
    7703 SCIP_SET* set, /**< global SCIP settings */
    7704 SCIP_STAT* stat, /**< dynamic problem statistics */
    7705 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    7706 SCIP_EVENTFILTER* eventfilter, /**< event filter */
    7707 SCIP_LP* lp, /**< current LP */
    7708 SCIP_Bool root /**< bool whether the current node is the root */
    7709 )
    7710{
    7711 SCIP_REOPTNODE* reoptnode;
    7712 SCIP_Bool infeasible;
    7713 unsigned int id;
    7714 int ncuts;
    7715
    7716 assert(reopt != NULL);
    7717 assert(node != NULL);
    7718 assert(sepastore != NULL);
    7719 assert(blkmem != NULL);
    7720 assert(set != NULL);
    7721 assert(stat != NULL);
    7722 assert(eventqueue != NULL);
    7723 assert(eventfilter != NULL);
    7724 assert(lp != NULL);
    7725
    7726 id = SCIPnodeGetReoptID(node);
    7727 assert(id < reopt->reopttree->reoptnodessize);
    7728
    7729 /* skip nodes that are node part of the reoptimization tree */
    7730 if( id == 0 && SCIPnodeGetDepth(node) > 0 )
    7731 return SCIP_OKAY;
    7732
    7733 reoptnode = reopt->reopttree->reoptnodes[id];
    7734 assert(reoptnode != NULL);
    7735
    7736 ncuts = 0;
    7737 for( int c = reoptnode->nconss-1; c >= 0; --c )
    7738 {
    7739 SCIP_REOPTCONSDATA* cons;
    7740
    7741 cons = reoptnode->conss[c];
    7742 assert(cons != NULL);
    7743
    7744 if( cons->constype == REOPT_CONSTYPE_CUT )
    7745 {
    7746 SCIP_ROW* cut;
    7747 SCIP_COL** cols;
    7748 SCIP_Real* vals;
    7749 char cutname[SCIP_MAXSTRLEN];
    7750 int ncols;
    7751
    7752 SCIP_CALL( SCIPsetAllocBufferArray(set, &cols, cons->nvars) );
    7753 SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, cons->nvars) );
    7754
    7755 ncols = 0;
    7756 for( int v = 0; v < cons->nvars; ++v )
    7757 {
    7758 SCIP_VAR* transvar;
    7759
    7760 assert(SCIPvarIsOriginal(cons->vars[v]));
    7761
    7762 transvar = SCIPvarGetTransVar(cons->vars[v]);
    7763 assert(transvar != NULL);
    7764 assert(SCIPvarGetStatus(transvar) == SCIP_VARSTATUS_COLUMN);
    7765
    7766 vals[ncols] = cons->vals[v];
    7767 cols[ncols] = SCIPvarGetCol(transvar);
    7768 assert(cols[ncols] != NULL);
    7769
    7770 ++ncols;
    7771 }
    7772 assert(ncols == cons->nvars);
    7773
    7774 (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "reoptcut_%d_%d", id, ncuts);
    7775 infeasible = FALSE;
    7776
    7777 if( id == 0 )
    7778 {
    7779 SCIP_CALL( SCIProwCreate(&cut, blkmem, set, stat, cutname, ncols, cols, vals, cons->lhs, cons->rhs,
    7781 SCIP_CALL( SCIPcutpoolAddRow(cutpool, blkmem, set, stat, lp, cut) );
    7782
    7783 SCIPsetDebugMsg(set, "add cut <%s> of size %d to cutpool, [lhs, rhs] = [%g,%g] to node %lld\n", cutname,
    7784 ncols, cons->lhs, cons->rhs, SCIPnodeGetNumber(node));
    7785 }
    7786 else
    7787 {
    7788 SCIP_CALL( SCIProwCreate(&cut, blkmem, set, stat, cutname, ncols, cols, vals, cons->lhs, cons->rhs,
    7790 SCIP_CALL( SCIPsepastoreAddCut(sepastore, blkmem, set, stat, eventqueue, eventfilter, lp, cut, FALSE, root,
    7791 &infeasible) );
    7792
    7793 SCIPsetDebugMsg(set, "add cut <%s> of size %d to sepastore, [lhs, rhs] = [%g,%g] to node %lld\n", cutname,
    7794 ncols, cons->lhs, cons->rhs, SCIPnodeGetNumber(node));
    7795 }
    7796
    7797 SCIP_CALL( SCIProwRelease(&cut, blkmem, set, lp) );
    7798
    7799 if( infeasible )
    7800 SCIPsetDebugMsg(set, "cut %d stored at node %" SCIP_LONGINT_FORMAT " (id: %u) is infeasible.\n", c, SCIPnodeGetNumber(node), id);
    7801 else
    7802 ++ncuts;
    7803
    7806
    7807 BMSfreeBlockMemoryArrayNull(blkmem, &reoptnode->conss[c]->boundtypes, reoptnode->conss[c]->varssize);
    7808 BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vals, reoptnode->conss[c]->varssize);
    7809 BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vars, reoptnode->conss[c]->varssize);
    7810 BMSfreeBlockMemory(blkmem, &reoptnode->conss[c]); /*lint !e866*/
    7811 --reoptnode->nconss;
    7812 }
    7813 else
    7814 {
    7815#ifndef NDEBUG
    7816 for( int i = c-1; i >= 0; --i )
    7817 assert(reoptnode->conss[i]->constype != REOPT_CONSTYPE_CUT);
    7818#endif
    7819 break;
    7820 }
    7821 }
    7822
    7823 return SCIP_OKAY;
    7824}
    7825
    7826/** check if the LP of the given node should be solved or not */
    7828 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7829 SCIP_SET* set, /**< global SCIP settings */
    7830 SCIP_NODE* node /**< node of the current search tree */
    7831 )
    7832{
    7833 unsigned int id;
    7834
    7835 assert(reopt != NULL);
    7836 assert(node != NULL);
    7837
    7838 /* get the ID */
    7839 id = SCIPnodeGetReoptID(node);
    7840 assert(id < reopt->reopttree->reoptnodessize);
    7841
    7842 /* return if the node is not part of the reoptimization tree */
    7843 if( SCIPnodeGetDepth(node) > 0 && id == 0 )
    7844 return TRUE;
    7845
    7846 /* return always true if the parameter is set to 1.0 */
    7847 if( SCIPsetIsGE(set, set->reopt_objsimrootlp, 1.0) )
    7848 return TRUE;
    7849
    7850 /* current node is the root */
    7851 if( id == 0 )
    7852 {
    7853 if( reopt->reopttree->reoptnodes[0]->nchilds > 0 )
    7854 {
    7855 /* the objective function has changed only slightly */
    7856 if( SCIPsetIsGE(set, reopt->simtolastobj, set->reopt_objsimrootlp) )
    7857 return FALSE;
    7858 }
    7859 }
    7860 else
    7861 {
    7862 /* solve node LP if the node type is greater or equal to solvelp or there were too many bound changes at the current node */
    7863 if( reopt->reopttree->reoptnodes[id]->nvars < set->reopt_solvelpdiff && (int) SCIPnodeGetReopttype(node) < set->reopt_solvelp )
    7864 {
    7865 assert(reopt->reopttree->reoptnodes[id]->nchilds > 0);
    7866 return FALSE;
    7867 }
    7868 }
    7869
    7870 return TRUE;
    7871}
    7872
    7873/** initialize an empty node */
    7875 SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
    7876 SCIP_SET* set /**< global SCIP settings */
    7877 )
    7878{
    7879 assert(reoptnode != NULL);
    7880 assert(set != NULL);
    7881
    7882 reoptnode->conss = NULL;
    7883 reoptnode->nconss = 0;
    7884 reoptnode->consssize = 0;
    7885 reoptnode->childids = NULL;
    7886 reoptnode->allocchildmem = 0;
    7887 reoptnode->nchilds = 0;
    7888 reoptnode->nvars = 0;
    7889 reoptnode->nafterdualvars = 0;
    7890 reoptnode->parentID = 0;
    7891 reoptnode->dualreds = FALSE;
    7892 reoptnode->reopttype = (unsigned int)SCIP_REOPTTYPE_NONE;
    7893 reoptnode->varssize = 0;
    7894 reoptnode->afterdualvarssize = 0;
    7895 reoptnode->vars = NULL;
    7896 reoptnode->varbounds = NULL;
    7897 reoptnode->varboundtypes = NULL;
    7898 reoptnode->afterdualvars = NULL;
    7899 reoptnode->afterdualvarbounds = NULL;
    7900 reoptnode->afterdualvarboundtypes = NULL;
    7901 reoptnode->dualredscur = NULL;
    7902 reoptnode->dualredsnex = NULL;
    7903 reoptnode->lowerbound = -SCIPsetInfinity(set);
    7904}
    7905
    7906/** reset the given reoptimization node */
    7908 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7909 SCIP_SET* set, /**< global SCIP settings */
    7910 BMS_BLKMEM* blkmem, /**< block memory */
    7911 SCIP_REOPTNODE* reoptnode /**< reoptimization node */
    7912 )
    7913{
    7914 assert(reopt != NULL);
    7915 assert(set != NULL);
    7916 assert(blkmem != NULL);
    7917 assert(reoptnode != NULL);
    7918
    7919 SCIP_CALL( reoptnodeReset(reoptnode, set, blkmem) );
    7920
    7921 return SCIP_OKAY;
    7922}
    7923
    7924/** delete the given reoptimization node */
    7926 SCIP_REOPTNODE** reoptnode, /**< pointer of reoptnode */
    7927 BMS_BLKMEM* blkmem /**< block memory */
    7928 )
    7929{
    7930 assert(reoptnode != NULL);
    7931 assert(blkmem != NULL);
    7932
    7933 SCIP_CALL( reoptnodeDelete(reoptnode, blkmem) );
    7934
    7935 return SCIP_OKAY;
    7936}
    7937
    7938/** add a variable to a given reoptnode */
    7940 SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
    7941 SCIP_SET* set, /**< global SCIP settings */
    7942 BMS_BLKMEM* blkmem, /**< block memory */
    7943 SCIP_VAR* var, /**< variable to add */
    7944 SCIP_Real val, /**< value of the variable */
    7945 SCIP_BOUNDTYPE boundtype /**< boundtype of the variable */
    7946 )
    7947{
    7948 int nvars;
    7949
    7950 assert(reoptnode != NULL);
    7951 assert(var != NULL);
    7952 assert(blkmem != NULL);
    7953
    7954 nvars = reoptnode->nvars;
    7955
    7956 SCIP_CALL( reoptnodeCheckMemory(reoptnode, set, blkmem, nvars + 1, 0, 0) );
    7957
    7958 reoptnode->vars[nvars] = var;
    7959 reoptnode->varbounds[nvars] = val;
    7960 reoptnode->varboundtypes[nvars] = boundtype;
    7961 ++reoptnode->nvars;
    7962
    7963 return SCIP_OKAY;
    7964}
    7965
    7966/** add a constraint to a given reoptnode */
    7968 SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
    7969 SCIP_SET* set, /**< global SCIP settings */
    7970 BMS_BLKMEM* blkmem, /**< block memory */
    7971 SCIP_VAR** vars, /**< variables which are part of the constraint */
    7972 SCIP_Real* bounds, /**< bounds of the variables */
    7973 SCIP_BOUNDTYPE* boundtypes, /**< boundtypes of the variables (or NULL is the constraint is a cut) */
    7974 SCIP_Real lhs, /**< lhs of the constraint */
    7975 SCIP_Real rhs, /**< rhs of the constraint */
    7976 int nvars, /**< number of variables */
    7977 REOPT_CONSTYPE constype, /**< type of the constraint */
    7978 SCIP_Bool linear /**< the given constraint has a linear representation */
    7979 )
    7980{
    7981 int nconss;
    7982
    7983 assert(reoptnode != NULL);
    7984 assert(set != NULL);
    7985 assert(vars != NULL);
    7986 assert(bounds != NULL);
    7987 assert(constype == REOPT_CONSTYPE_CUT || boundtypes != NULL);
    7988 assert(nvars > 0);
    7989 assert(blkmem != NULL);
    7990
    7991 /* the constraint can be interpreted as a normal bound change */
    7992 if( nvars == 1 && constype != REOPT_CONSTYPE_CUT )
    7993 {
    7994 assert(constype == REOPT_CONSTYPE_DUALREDS || constype == REOPT_CONSTYPE_INFSUBTREE);
    7995
    7996 SCIPsetDebugMsg(set, "-> constraint has size 1 -> save as normal bound change.\n");
    7997
    7998 assert(!SCIPvarIsImpliedIntegral(vars[0]));
    7999 if( SCIPvarGetType(vars[0]) == SCIP_VARTYPE_BINARY )
    8000 {
    8001 SCIP_CALL( SCIPreoptnodeAddBndchg(reoptnode, set, blkmem, vars[0], 1-bounds[0],
    8002 1-bounds[0] == 1 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER) );
    8003 }
    8004 else
    8005 {
    8006 SCIP_Real newbound;
    8007 SCIP_BOUNDTYPE newboundtype;
    8008
    8009 assert(SCIPvarGetType(vars[0]) == SCIP_VARTYPE_INTEGER);
    8010 assert(boundtypes != NULL);
    8011
    8012 if( boundtypes[0] == SCIP_BOUNDTYPE_UPPER )
    8013 {
    8014 newbound = bounds[0] + 1.0;
    8015 assert(SCIPsetIsLE(set, newbound, SCIPvarGetUbLocal(vars[0])));
    8016
    8017 newboundtype = SCIP_BOUNDTYPE_LOWER;
    8018 }
    8019 else
    8020 {
    8021 newbound = bounds[0] - 1.0;
    8022 assert(SCIPsetIsGE(set, newbound, SCIPvarGetLbLocal(vars[0])));
    8023
    8024 newboundtype = SCIP_BOUNDTYPE_UPPER;
    8025 }
    8026
    8027 SCIP_CALL( SCIPreoptnodeAddBndchg(reoptnode, set, blkmem, vars[0], newbound, newboundtype) );
    8028 }
    8029 }
    8030 else
    8031 {
    8032 nconss = reoptnode->nconss;
    8033
    8034 SCIP_CALL( reoptnodeCheckMemory(reoptnode, set, blkmem, 0, 0, nconss+1) );
    8035
    8036 /* create the constraint */
    8037 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reoptnode->conss[nconss]) ); /*lint !e866*/
    8038 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->vars, vars, nvars) );
    8039 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->vals, bounds, nvars) );
    8040 if( boundtypes != NULL )
    8041 {
    8042 assert(!linear);
    8043 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->boundtypes, boundtypes, nvars) );
    8044 }
    8045 else
    8046 reoptnode->conss[nconss]->boundtypes = NULL;
    8047
    8048 reoptnode->conss[nconss]->varssize = nvars;
    8049 reoptnode->conss[nconss]->nvars = nvars;
    8050 reoptnode->conss[nconss]->lhs = lhs;
    8051 reoptnode->conss[nconss]->rhs = rhs;
    8052 reoptnode->conss[nconss]->constype = constype;
    8053 reoptnode->conss[nconss]->linear = linear;
    8054 ++reoptnode->nconss;
    8055 }
    8056 return SCIP_OKAY;
    8057}
    8058
    8059/** add a constraint to the reoptimization data structure */
    8061 SCIP_REOPT* reopt, /**< reoptimization data structure */
    8062 SCIP_SET* set, /**< global SCIP settings */
    8063 BMS_BLKMEM* blkmem, /**< block memory */
    8064 SCIP_CONS* cons /**< constraint to add */
    8065 )
    8066{
    8067 assert(reopt != NULL);
    8068 assert(set != NULL);
    8069 assert(blkmem != NULL);
    8070 assert(cons != NULL);
    8071
    8072#ifdef SCIP_MORE_DEBUG
    8073 SCIPsetDebugMsg(set, "add cons <%s> to reoptimization data\n", SCIPconsGetName(cons));
    8074#endif
    8075
    8076 /* check memory */
    8077 if( reopt->addedconsssize == 0 )
    8078 {
    8079 assert(reopt->addedconss == NULL);
    8080
    8081 reopt->addedconsssize = 10;
    8083 }
    8084 else if( reopt->naddedconss == reopt->addedconsssize )
    8085 {
    8086 int newsize = SCIPsetCalcMemGrowSize(set, reopt->addedconsssize+1);
    8087 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->addedconss, reopt->addedconsssize, newsize) );
    8088
    8089 /* clear the array */
    8090 BMSclearMemoryArray(&reopt->addedconss[reopt->addedconsssize], newsize - reopt->addedconsssize); /*lint !e866 */
    8091
    8092 reopt->addedconsssize = newsize;
    8093 }
    8094 assert(reopt->naddedconss < reopt->addedconsssize);
    8095 assert(reopt->addedconss[reopt->naddedconss] == NULL);
    8096
    8097 reopt->addedconss[reopt->naddedconss] = cons;
    8098 reopt->consadded = TRUE;
    8099 ++reopt->naddedconss;
    8100
    8101 /* capture the constraint */
    8102 SCIPconsCapture(cons);
    8103
    8104 return SCIP_OKAY;
    8105}
    8106
    8107/** save global lower and upper bounds
    8108 *
    8109 * @note this method should only be called once, i.e., after fishing presolving of the first problem
    8110 */
    8112 SCIP_REOPT* reopt, /**< reoptimization data structure */
    8113 SCIP_PROB* transprob, /**< transformed problem data */
    8114 BMS_BLKMEM* blkmem /**< block memory */
    8115 )
    8116{
    8117 SCIP_VAR** vars;
    8118 int nvars;
    8119
    8120 assert(reopt != NULL);
    8121 assert(transprob != NULL);
    8122 assert(reopt->glblb == NULL && reopt->glbub == NULL);
    8123
    8124 nvars = SCIPprobGetNVars(transprob);
    8125 vars = SCIPprobGetVars(transprob);
    8126
    8127 /* create hashmaps */
    8128 SCIP_CALL( SCIPhashmapCreate(&reopt->glbub, blkmem, nvars) );
    8129 SCIP_CALL( SCIPhashmapCreate(&reopt->glblb, blkmem, nvars) );
    8130
    8131 /* store the global bounds */
    8132 for( int i = 0; i < nvars; ++i )
    8133 {
    8134 if( SCIPvarIsRelaxationOnly(vars[i]) )
    8135 continue;
    8136
    8137 assert(!SCIPhashmapExists(reopt->glblb, (void*)vars[i]));
    8138 assert(!SCIPhashmapExists(reopt->glbub, (void*)vars[i]));
    8139
    8140 SCIP_CALL( SCIPhashmapInsertReal(reopt->glblb, (void*)vars[i], SCIPvarGetLbGlobal(vars[i])) );
    8141 SCIP_CALL( SCIPhashmapInsertReal(reopt->glbub, (void*)vars[i], SCIPvarGetUbGlobal(vars[i])) );
    8142 }
    8143
    8144 return SCIP_OKAY;
    8145}
    8146
    8147/** save active constraints
    8148 *
    8149 * @note this method can only called once, i.e., after fishing presolving of the first problem
    8150 */
    8152 SCIP_REOPT* reopt, /**< reoptimization data structure */
    8153 SCIP_SET* set, /**< global SCIP settings */
    8154 SCIP_PROB* transprob, /**< transformed problem data */
    8155 BMS_BLKMEM* blkmem /**< block memory */
    8156 )
    8157{
    8158 SCIP_CONS** conss;
    8159 int nconss;
    8160
    8161 assert(reopt != NULL);
    8162 assert(transprob != NULL);
    8163 assert(reopt->activeconss == NULL);
    8164 assert(reopt->activeconssset == NULL);
    8165 assert(reopt->nactiveconss == 0);
    8166 assert(reopt->nmaxactiveconss == 0);
    8167
    8168 conss = SCIPprobGetConss(transprob);
    8169 nconss = SCIPprobGetNConss(transprob);
    8170
    8171 SCIPsetDebugMsg(set, "save %d active conss\n", nconss);
    8172
    8173 /* create hashset and array */
    8174 SCIP_CALL( SCIPhashsetCreate(&reopt->activeconssset, blkmem, nconss) );
    8175 SCIP_CALL( ensureActiveconssSize(reopt, set, blkmem, nconss) );
    8176
    8177 for( int i = 0; i < nconss; ++i )
    8178 {
    8179 assert(SCIPconsIsActive(conss[i]));
    8180 assert(!SCIPhashsetExists(reopt->activeconssset, (void*)conss[i]));
    8181
    8182 SCIPconsCapture(conss[i]);
    8183 SCIP_CALL( SCIPhashsetInsert(reopt->activeconssset, blkmem, (void*)conss[i]) );
    8184 reopt->activeconss[reopt->nactiveconss++] = conss[i];
    8185 }
    8186
    8187 return SCIP_OKAY;
    8188}
    8189
    8190/** installs global lower and upper bounds */
    8192 SCIP_REOPT* reopt, /**< reoptimization data structure */
    8193 SCIP_SET* set, /**< global SCIP settings */
    8194 SCIP_STAT* stat, /**< dynamic SCIP statistics */
    8195 SCIP_PROB* transprob, /**< transformed problem data */
    8196 SCIP_LP* lp, /**< current LP data */
    8197 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    8198 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    8199 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    8200 BMS_BLKMEM* blkmem /**< block memory */
    8201 )
    8202{
    8203 SCIP_VAR** vars;
    8204 int nvars;
    8205
    8206 assert(reopt != NULL);
    8207 assert(transprob != NULL);
    8208 assert(reopt->glblb != NULL && reopt->glbub != NULL);
    8209 assert(SCIPprobIsTransformed(transprob));
    8210
    8211 nvars = SCIPprobGetNVars(transprob);
    8212 vars = SCIPprobGetVars(transprob);
    8213
    8214 /* install global lower and upper bounds */
    8215 for( int i = 0; i < nvars; ++i )
    8216 {
    8217 SCIP_Real lb;
    8218 SCIP_Real ub;
    8219
    8220 if( SCIPvarIsRelaxationOnly(vars[i]) )
    8221 continue;
    8222
    8223 assert(SCIPhashmapExists(reopt->glblb, (void*)vars[i]));
    8224 assert(SCIPhashmapExists(reopt->glbub, (void*)vars[i]));
    8225
    8226 lb = SCIPhashmapGetImageReal(reopt->glblb, (void*)vars[i]);
    8227 ub = SCIPhashmapGetImageReal(reopt->glbub, (void*)vars[i]);
    8228 assert(lb < SCIP_INVALID && ub < SCIP_INVALID);
    8229
    8230 /* reset the global bounds back */
    8231 SCIP_CALL( SCIPvarChgLbGlobal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, lb) );
    8232 SCIP_CALL( SCIPvarChgUbGlobal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, ub) );
    8233
    8234 /* reset the local bounds back */
    8235 SCIP_CALL( SCIPvarChgLbLocal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, lb) );
    8236 SCIP_CALL( SCIPvarChgUbLocal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, ub) );
    8237 }
    8238
    8239 return SCIP_OKAY;
    8240}
    8241
    8242/** reactivate globally valid constraints that were deactivated and necessary to ensure correctness */
    8244 SCIP_REOPT* reopt, /**< reoptimization data structure */
    8245 SCIP_SET* set, /**< global SCIP settings */
    8246 SCIP_STAT* stat /**< dynamic SCIP statistics */
    8247 )
    8248{
    8249 assert(reopt != NULL);
    8250 assert(reopt->activeconss != NULL || reopt->nmaxactiveconss == 0);
    8251 assert(reopt->activeconssset != NULL || reopt->nmaxactiveconss == 0);
    8252 assert(reopt->nmaxactiveconss >= 0);
    8253
    8254 SCIPsetDebugMsg(set, "Reset %d active conss.\n", reopt->nactiveconss);
    8255
    8256 /* loop over all storeed active constraints and reactivate deactivated constraints */
    8257 for( int i = 0; i < reopt->nactiveconss; ++i )
    8258 {
    8259 SCIP_CONS* cons;
    8260
    8261 assert(reopt->activeconss != NULL);
    8262 cons = reopt->activeconss[i];
    8263 assert(cons != NULL);
    8264 assert(SCIPhashsetExists(reopt->activeconssset, cons));
    8265
    8266 /* it can happen that the constraint got globally deleted */
    8267 if( SCIPconsIsDeleted(cons) )
    8268 cons->deleted = FALSE;
    8269
    8270 /* to ensure that the constraint will be added to all the data structures we need to deactivate the
    8271 * constraint first.
    8272 */
    8273 if( SCIPconsIsActive(cons) )
    8274 {
    8275 SCIP_CALL( SCIPconsDeactivate(cons, set, stat) );
    8276 }
    8277 SCIP_CALL( SCIPconsActivate(cons, set, stat, -1, TRUE) );
    8278 }
    8279
    8280 return SCIP_OKAY;
    8281}
    8282
    8283/** returns whether a constraint is necessary to ensure correctness and cannot be deleted */
    8285 SCIP_REOPT* reopt, /**< reoptimization data structure */
    8286 SCIP_CONS* cons /**< problem constraint */
    8287 )
    8288{
    8289 assert(reopt != NULL);
    8290 assert(cons != NULL);
    8291
    8292 /* the hashset is not initialized, we can delete all constraints */
    8293 if( reopt->activeconss == NULL )
    8294 return TRUE;
    8295
    8296 return !SCIPhashsetExists(reopt->activeconssset, (void*)cons);
    8297}
    SCIP_VAR * w
    Definition: circlepacking.c:67
    SCIP_Real * r
    Definition: circlepacking.c:59
    void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
    Definition: clock.c:360
    void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
    Definition: clock.c:290
    SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
    Definition: clock.c:438
    void SCIPclockFree(SCIP_CLOCK **clck)
    Definition: clock.c:185
    SCIP_RETCODE SCIPclockCreate(SCIP_CLOCK **clck, SCIP_CLOCKTYPE clocktype)
    Definition: clock.c:170
    internal methods for clocks and timing issues
    void SCIPconsCapture(SCIP_CONS *cons)
    Definition: cons.c:6427
    SCIP_RETCODE SCIPconsDeactivate(SCIP_CONS *cons, SCIP_SET *set, SCIP_STAT *stat)
    Definition: cons.c:7073
    SCIP_RETCODE SCIPconsGetNVars(SCIP_CONS *cons, SCIP_SET *set, int *nvars, SCIP_Bool *success)
    Definition: cons.c:6554
    SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
    Definition: cons.c:6439
    SCIP_RETCODE SCIPconsActivate(SCIP_CONS *cons, SCIP_SET *set, SCIP_STAT *stat, int depth, SCIP_Bool focusnode)
    Definition: cons.c:7031
    internal methods for constraints and constraint handlers
    constraint handler for bound disjunction constraints
    Constraint handler for linear constraints in their most general form, .
    Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
    Constraint handler for the set partitioning / packing / covering constraints .
    SCIP_RETCODE SCIPcutpoolAddRow(SCIP_CUTPOOL *cutpool, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_ROW *row)
    Definition: cutpool.c:656
    internal methods for storing cuts in a cut pool
    common defines and data types used in all packages of SCIP
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_ALLOC(x)
    Definition: def.h:366
    #define SCIP_Real
    Definition: def.h:156
    #define SCIP_UNKNOWN
    Definition: def.h:179
    #define SQR(x)
    Definition: def.h:199
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPeventhdlrCreate(SCIP_EVENTHDLR **eventhdlr, SCIP_SET *set, const char *name, const char *desc, SCIP_DECL_EVENTCOPY((*eventcopy)), SCIP_DECL_EVENTFREE((*eventfree)), SCIP_DECL_EVENTINIT((*eventinit)), SCIP_DECL_EVENTEXIT((*eventexit)), SCIP_DECL_EVENTINITSOL((*eventinitsol)), SCIP_DECL_EVENTEXITSOL((*eventexitsol)), SCIP_DECL_EVENTDELETE((*eventdelete)), SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: event.c:195
    internal methods for managing events
    #define nnodes
    Definition: gastrans.c:74
    SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_Real * SCIPgetBoundsBounddisjunction(SCIP *scip, SCIP_CONS *cons)
    SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcreateConsBasicBounddisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds)
    SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcreateConsBounddisjunctionRedundant(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_BOUNDTYPE * SCIPgetBoundtypesBounddisjunction(SCIP *scip, SCIP_CONS *cons)
    SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_setppc.c:9619
    SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_setppc.c:9642
    SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcreateConsLogicor(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_VAR ** SCIPgetVarsBounddisjunction(SCIP *scip, SCIP_CONS *cons)
    @ SCIP_SETPPCTYPE_PARTITIONING
    Definition: cons_setppc.h:87
    @ SCIP_SETPPCTYPE_COVERING
    Definition: cons_setppc.h:89
    @ SCIP_SETPPCTYPE_PACKING
    Definition: cons_setppc.h:88
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    int SCIPgetNOrigVars(SCIP *scip)
    Definition: scip_prob.c:2838
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    SCIP_Real SCIPhashmapGetImageReal(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3344
    SCIP_RETCODE SCIPhashmapInsertReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
    Definition: misc.c:3251
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3466
    void SCIPhashsetFree(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem)
    Definition: misc.c:3833
    SCIP_Bool SCIPhashsetExists(SCIP_HASHSET *hashset, void *element)
    Definition: misc.c:3860
    void SCIPhashsetRemoveAll(SCIP_HASHSET *hashset)
    Definition: misc.c:4059
    SCIP_RETCODE SCIPhashsetInsert(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem, void *element)
    Definition: misc.c:3843
    SCIP_RETCODE SCIPhashsetCreate(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem, int size)
    Definition: misc.c:3802
    SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
    Definition: scip_prob.c:3901
    void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:225
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPrandomPermuteIntArray(SCIP_RANDNUMGEN *randnumgen, int *array, int begin, int end)
    Definition: misc.c:10264
    SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
    Definition: lp.c:17425
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4316
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8409
    SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
    Definition: cons.c:8518
    SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
    Definition: cons.c:8450
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8389
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:396
    SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
    Definition: scip_event.c:367
    SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
    Definition: scip_event.c:413
    SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
    Definition: event.c:1391
    SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
    Definition: event.c:1217
    SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
    Definition: event.c:1415
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    void SCIPnodeGetAncestorBranchings(SCIP_NODE *node, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
    Definition: tree.c:8856
    void SCIPnodeSetReopttype(SCIP_NODE *node, SCIP_REOPTTYPE reopttype)
    Definition: tree.c:8543
    void SCIPnodeSetReoptID(SCIP_NODE *node, unsigned int id)
    Definition: tree.c:8574
    void SCIPnodeGetAncestorBranchingsPart(SCIP_NODE *node, SCIP_NODE *parent, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
    Definition: tree.c:8893
    SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
    Definition: tree.c:8473
    SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
    Definition: tree.c:8503
    void SCIPnodeGetNDomchg(SCIP_NODE *node, int *nbranchings, int *nconsprop, int *nprop)
    Definition: tree.c:8598
    SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
    Definition: tree.c:8483
    SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
    Definition: tree.c:8782
    int SCIPnodeGetNAddedConss(SCIP_NODE *node)
    Definition: tree.c:1799
    void SCIPnodeGetAddedConss(SCIP_NODE *node, SCIP_CONS **addedconss, int *naddedconss, int addedconsssize)
    Definition: tree.c:1769
    int SCIPnodeGetDepth(SCIP_NODE *node)
    Definition: tree.c:8493
    SCIP_REOPTTYPE SCIPnodeGetReopttype(SCIP_NODE *node)
    Definition: tree.c:8533
    unsigned int SCIPnodeGetReoptID(SCIP_NODE *node)
    Definition: tree.c:8564
    SCIP_RETCODE SCIPaddReoptDualBndchg(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound, SCIP_Real oldbound)
    Definition: scip_solve.c:3230
    SCIP_Bool SCIPisReoptEnabled(SCIP *scip)
    Definition: scip_solve.c:3616
    SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
    Definition: lp.c:17686
    SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
    Definition: lp.c:17632
    SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
    Definition: lp.c:17696
    int SCIProwGetAge(SCIP_ROW *row)
    Definition: lp.c:17765
    int SCIProwGetNLPNonz(SCIP_ROW *row)
    Definition: lp.c:17621
    int SCIProwGetLPPos(SCIP_ROW *row)
    Definition: lp.c:17895
    SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
    Definition: lp.c:17652
    SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
    Definition: lp.c:17642
    SCIP_ROWORIGINTYPE SCIProwGetOrigintype(SCIP_ROW *row)
    Definition: lp.c:17825
    SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
    Definition: sol.c:4259
    SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
    Definition: sol.c:4140
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    int SCIPgetEffectiveRootDepth(SCIP *scip)
    Definition: scip_tree.c:127
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
    Definition: var.c:18320
    SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
    Definition: var.c:17801
    SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
    Definition: var.c:23683
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23498
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
    Definition: var.c:23430
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    int SCIPvarGetIndex(SCIP_VAR *var)
    Definition: var.c:23652
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
    Definition: var.c:18497
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
    Definition: var.c:23443
    SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
    Definition: var.c:23600
    SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
    Definition: var.c:23417
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
    Definition: var.c:23672
    int SCIPqueueNElems(SCIP_QUEUE *queue)
    Definition: misc.c:1249
    unsigned int SCIPqueueRemoveUInt(SCIP_QUEUE *queue)
    Definition: misc.c:1166
    void SCIPqueueFree(SCIP_QUEUE **queue)
    Definition: misc.c:1019
    SCIP_RETCODE SCIPqueueInsertUInt(SCIP_QUEUE *queue, unsigned int elem)
    Definition: misc.c:1107
    SCIP_RETCODE SCIPqueueCreate(SCIP_QUEUE **queue, int initsize, SCIP_Real sizefac)
    Definition: misc.c:995
    void SCIPqueueClear(SCIP_QUEUE *queue)
    Definition: misc.c:1030
    SCIP_Bool SCIPqueueIsEmpty(SCIP_QUEUE *queue)
    Definition: misc.c:1236
    void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    void SCIPhistoryReset(SCIP_HISTORY *history)
    Definition: history.c:78
    SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:790
    SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:816
    SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
    Definition: history.c:51
    void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
    Definition: history.c:732
    void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
    Definition: history.c:748
    void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
    Definition: history.c:716
    void SCIPhistoryFree(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
    Definition: history.c:66
    void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
    Definition: history.c:117
    internal methods for branching and inference history
    SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
    Definition: lp.c:13420
    SCIP_RETCODE SCIProwCreate(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, int len, SCIP_COL **cols, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_ROWORIGINTYPE origintype, void *origin, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
    Definition: lp.c:5313
    SCIP_Real SCIPlpGetCutoffbound(SCIP_LP *lp)
    Definition: lp.c:10441
    SCIP_ROW ** SCIPlpGetRows(SCIP_LP *lp)
    Definition: lp.c:18016
    int SCIPlpGetNRows(SCIP_LP *lp)
    Definition: lp.c:18026
    SCIP_RETCODE SCIProwRelease(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
    Definition: lp.c:5567
    internal methods for LP management
    methods for block memory pools and memory buffers
    memory allocation routines
    #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 BMSfreeBlockMemoryNull(mem, ptr)
    Definition: memory.h:466
    #define BMSfreeBlockMemoryArray(mem, ptr, num)
    Definition: memory.h:467
    #define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
    Definition: memory.h:458
    #define BMSallocClearBlockMemoryArray(mem, ptr, num)
    Definition: memory.h:455
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    #define BMSallocClearMemoryArray(ptr, num)
    Definition: memory.h:125
    struct BMS_BlkMem BMS_BLKMEM
    Definition: memory.h:437
    #define BMSallocMemory(ptr)
    Definition: memory.h:118
    void SCIPrandomFree(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem)
    Definition: misc.c:10209
    SCIP_RETCODE SCIPrandomCreate(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem, unsigned int initialseed)
    Definition: misc.c:10193
    internal miscellaneous methods
    internal methods for collecting primal CIP solutions and primal informations
    SCIP_CONS ** SCIPprobGetConss(SCIP_PROB *prob)
    Definition: prob.c:2958
    int SCIPprobGetNConss(SCIP_PROB *prob)
    Definition: prob.c:2949
    int SCIPprobGetNVars(SCIP_PROB *prob)
    Definition: prob.c:2868
    SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
    Definition: prob.c:2913
    SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
    Definition: prob.c:2803
    internal methods for storing and manipulating the main problem
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebugPrintCons(x, y, z)
    Definition: pub_message.h:102
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    static SCIP_RETCODE reoptMoveIDs(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, unsigned int id1, unsigned int id2)
    Definition: reopt.c:3485
    SCIP_RETCODE SCIPreoptUpdateVarHistory(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem, SCIP_VAR **vars, int nvars)
    Definition: reopt.c:6598
    static SCIP_RETCODE changeReopttypeOfSubtree(SCIP_REOPTTREE *reopttree, unsigned int id, SCIP_REOPTTYPE reopttype)
    Definition: reopt.c:1946
    int SCIPreoptGetNDualBndchgs(SCIP_REOPT *reopt, SCIP_NODE *node)
    Definition: reopt.c:6320
    SCIP_RETCODE SCIPreoptSaveActiveConss(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_PROB *transprob, BMS_BLKMEM *blkmem)
    Definition: reopt.c:8151
    static int soltreeNInducedSols(SCIP_SOLNODE *solnode)
    Definition: reopt.c:367
    SCIP_RETCODE SCIPreoptApply(SCIP_REOPT *reopt, SCIP *scip, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, BMS_BLKMEM *blkmem, SCIP_REOPTNODE *reoptnode, unsigned int id, SCIP_Real estimate, SCIP_NODE **childnodes, int *ncreatedchilds, int *naddedconss, int childnodessize, SCIP_Bool *success)
    Definition: reopt.c:7262
    int SCIPreoptGetNTotalPrunedNodes(SCIP_REOPT *reopt)
    Definition: reopt.c:4967
    SCIP_RETCODE SCIPreoptnodeReset(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_REOPTNODE *reoptnode)
    Definition: reopt.c:7907
    SCIP_RETCODE SCIPreoptAddRun(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR **origvars, int norigvars, int size)
    Definition: reopt.c:5362
    SCIP_RETCODE SCIPreoptAddCons(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_CONS *cons)
    Definition: reopt.c:8060
    int SCIPreoptGetNTotalFeasNodes(SCIP_REOPT *reopt)
    Definition: reopt.c:4947
    void SCIPreoptAddNCheckedSols(SCIP_REOPT *reopt, int ncheckedsols)
    Definition: reopt.c:5408
    static SCIP_RETCODE ensureSolsSize(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, int num, int runidx)
    Definition: reopt.c:192
    static SCIP_RETCODE reopttreeDeleteNode(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, unsigned int id, SCIP_Bool softreset)
    Definition: reopt.c:680
    int SCIPreoptGetFirstRestarts(SCIP_REOPT *reopt)
    Definition: reopt.c:4917
    static SCIP_RETCODE saveAfterDualBranchings(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int id, SCIP_Bool *transintoorig)
    Definition: reopt.c:1444
    SCIP_RETCODE SCIPreoptAddSol(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *origprimal, BMS_BLKMEM *blkmem, SCIP_SOL *sol, SCIP_Bool bestsol, SCIP_Bool *added, SCIP_VAR **vars, int nvars, int run)
    Definition: reopt.c:5275
    int SCIPreoptGetNTotalRestartsLocal(SCIP_REOPT *reopt)
    Definition: reopt.c:4907
    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
    static SCIP_RETCODE transformDualredsToBounddisjunction(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_REOPTCONSDATA *consdata, SCIP_REOPTCONSDATA *dualreds)
    Definition: reopt.c:6812
    static SCIP_RETCODE transformIntoOrig(SCIP_REOPT *reopt, unsigned int id)
    Definition: reopt.c:1624
    static SCIP_RETCODE saveLocalConssData(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int id)
    Definition: reopt.c:2383
    int SCIPreoptGetNImprovingSols(SCIP_REOPT *reopt)
    Definition: reopt.c:5419
    static SCIP_RETCODE addGlobalCut(SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR **vars, SCIP_Real *vals, SCIP_BOUNDTYPE *boundtypes, int nvars, int nbinvars, int nintvars)
    Definition: reopt.c:3221
    static SCIP_RETCODE addNode(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_NODE *node, SCIP_REOPTTYPE reopttype, SCIP_Bool saveafterdual, SCIP_Bool isrootnode, SCIP_Real lowerbound)
    Definition: reopt.c:2603
    static SCIP_RETCODE shrinkNode(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_NODE *node, unsigned int id, SCIP_Bool *shrank, BMS_BLKMEM *blkmem)
    Definition: reopt.c:1868
    static void deleteLastDualBndchgs(SCIP_REOPT *reopt)
    Definition: reopt.c:3154
    SCIP_RETCODE SCIPreoptAddInfNode(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node)
    Definition: reopt.c:5938
    static SCIP_RETCODE clearReoptnodes(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_Bool softreset)
    Definition: reopt.c:1217
    static SCIP_RETCODE fixInterdiction(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int id, int *perm, SCIP_VAR **vars, SCIP_Real *vals, SCIP_BOUNDTYPE *boundtypes, int nvars, int negbndchg)
    Definition: reopt.c:4089
    static SCIP_RETCODE changeAncestorBranchings(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int id, SCIP_Bool afterdualbranching)
    Definition: reopt.c:3535
    static SCIP_RETCODE reoptResetTree(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_Bool softreset)
    Definition: reopt.c:4603
    SCIP_RETCODE SCIPreoptApplyCuts(SCIP_REOPT *reopt, SCIP_NODE *node, SCIP_SEPASTORE *sepastore, SCIP_CUTPOOL *cutpool, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_Bool root)
    Definition: reopt.c:7697
    static SCIP_RETCODE reopttreeCheckMemory(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem)
    Definition: reopt.c:255
    SCIP_SOL * SCIPreoptGetLastBestSol(SCIP_REOPT *reopt)
    Definition: reopt.c:5643
    static SCIP_RETCODE separateSolution(SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol, SCIP_VAR **vars, int nvars)
    Definition: reopt.c:4793
    SCIP_RETCODE SCIPreoptnodeAddBndchg(SCIP_REOPTNODE *reoptnode, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real val, SCIP_BOUNDTYPE boundtype)
    Definition: reopt.c:7939
    SCIP_RETCODE SCIPreoptnodeAddCons(SCIP_REOPTNODE *reoptnode, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR **vars, SCIP_Real *bounds, SCIP_BOUNDTYPE *boundtypes, SCIP_Real lhs, SCIP_Real rhs, int nvars, REOPT_CONSTYPE constype, SCIP_Bool linear)
    Definition: reopt.c:7967
    SCIP_RETCODE SCIPreoptSplitRoot(SCIP_REOPT *reopt, SCIP_TREE *tree, SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem, int *ncreatedchilds, int *naddedconss)
    Definition: reopt.c:6869
    #define DEFAULT_MEM_DUALCONS
    Definition: reopt.c:64
    static SCIP_RETCODE createSolTree(SCIP_SOLTREE *soltree, BMS_BLKMEM *blkmem)
    Definition: reopt.c:712
    SCIP_RETCODE SCIPreoptGetSolsRun(SCIP_REOPT *reopt, int run, SCIP_SOL **sols, int solssize, int *nsols)
    Definition: reopt.c:5470
    static SCIP_DECL_EVENTEXITSOL(eventExitsolReopt)
    Definition: reopt.c:139
    static void resetStats(SCIP_REOPT *reopt)
    Definition: reopt.c:4271
    static SCIP_RETCODE reoptRestart(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
    Definition: reopt.c:4629
    SCIP_Bool SCIPreoptConsCanBeDeleted(SCIP_REOPT *reopt, SCIP_CONS *cons)
    Definition: reopt.c:8284
    static SCIP_RETCODE freeReoptTree(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem)
    Definition: reopt.c:1253
    int SCIPreoptGetNPrunedNodes(SCIP_REOPT *reopt)
    Definition: reopt.c:4957
    int SCIPreoptGetNFeasNodes(SCIP_REOPT *reopt)
    Definition: reopt.c:4937
    static SCIP_RETCODE reoptnodeDelete(SCIP_REOPTNODE **reoptnode, BMS_BLKMEM *blkmem)
    Definition: reopt.c:483
    static int reoptGetNLeaves(SCIP_REOPT *reopt, unsigned int id)
    Definition: reopt.c:4529
    static SCIP_RETCODE saveGlobalCons(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, REOPT_CONSTYPE consttype)
    Definition: reopt.c:3418
    static SCIP_RETCODE deleteChildrenBelow(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, unsigned int id, SCIP_Bool delnodeitself, SCIP_Bool exitsolve)
    Definition: reopt.c:1822
    SCIP_RETCODE SCIPreoptDeleteNode(SCIP_REOPT *reopt, SCIP_SET *set, unsigned int id, BMS_BLKMEM *blkmem)
    Definition: reopt.c:7242
    SCIP_Real SCIPreoptnodeGetLowerbound(SCIP_REOPTNODE *reoptnode)
    Definition: reopt.c:5837
    static SCIP_RETCODE reoptnodeReset(SCIP_REOPTNODE *reoptnode, SCIP_SET *set, BMS_BLKMEM *blkmem)
    Definition: reopt.c:604
    int SCIPreoptGetNRestartsLocal(SCIP_REOPT *reopt)
    Definition: reopt.c:4897
    SCIP_RETCODE SCIPreoptReleaseData(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
    Definition: reopt.c:5098
    #define DEFAULT_MEM_VAR
    Definition: reopt.c:61
    SCIP_RETCODE SCIPreoptResetDualBndchgs(SCIP_REOPT *reopt, SCIP_NODE *node, BMS_BLKMEM *blkmem)
    Definition: reopt.c:7158
    void SCIPreoptResetSolMarks(SCIP_REOPT *reopt)
    Definition: reopt.c:5733
    static SCIP_RETCODE getInferenceOrder(SCIP_SET *set, SCIP_STAT *stat, int *perm, SCIP_VAR **vars, SCIP_Real *bounds, SCIP_BOUNDTYPE *boundtypes, int nvars)
    Definition: reopt.c:4746
    static SCIP_RETCODE freeSolTree(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_PRIMAL *origprimal, BMS_BLKMEM *blkmem)
    Definition: reopt.c:786
    int SCIPreoptGetNSols(SCIP_REOPT *reopt)
    Definition: reopt.c:5455
    int SCIPreoptGetNSolsRun(SCIP_REOPT *reopt, int run)
    Definition: reopt.c:5440
    void SCIPreoptnodeSetParentID(SCIP_REOPTNODE *reoptnode, unsigned int parentid)
    Definition: reopt.c:5892
    SCIP_Real SCIPreoptGetSimToFirst(SCIP_REOPT *reopt)
    Definition: reopt.c:5615
    static SCIP_RETCODE saveConsBounddisjuction(SCIP_REOPTCONSDATA *reoptconsdata, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_CONS *cons, SCIP_Bool *success)
    Definition: reopt.c:2314
    static SCIP_RETCODE reoptAddChild(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, unsigned int parentid, unsigned int childid)
    Definition: reopt.c:1729
    #define DEFAULT_MEM_VARAFTERDUAL
    Definition: reopt.c:60
    int SCIPreoptGetNSavedSols(SCIP_REOPT *reopt)
    Definition: reopt.c:5510
    #define DEFAULT_MEM_NODES
    Definition: reopt.c:62
    SCIP_Real SCIPreoptGetOldObjCoef(SCIP_REOPT *reopt, int run, int idx)
    Definition: reopt.c:5671
    static void soltreeResetMarks(SCIP_SOLNODE *node)
    Definition: reopt.c:1082
    static SCIP_RETCODE reoptnodeCheckMemory(SCIP_REOPTNODE *reoptnode, SCIP_SET *set, BMS_BLKMEM *blkmem, int var_mem, int child_mem, int conss_mem)
    Definition: reopt.c:287
    static SCIP_RETCODE cleanActiveConss(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
    Definition: reopt.c:1351
    static SCIP_DECL_EVENTEXEC(eventExecReopt)
    Definition: reopt.c:76
    int SCIPreoptGetNCheckedSols(SCIP_REOPT *reopt)
    Definition: reopt.c:5398
    static SCIP_RETCODE reoptGetLeaves(SCIP_REOPT *reopt, unsigned int id, unsigned int *leaves, int leavessize, int *nleaves)
    Definition: reopt.c:4559
    static SCIP_RETCODE getLastSavedNode(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_NODE *node, SCIP_NODE **parent, unsigned int *parentid, int *nbndchgs)
    Definition: reopt.c:1667
    static SCIP_RETCODE reoptCheckLocalRestart(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, SCIP_VAR **transvars, int ntransvars, SCIP_Bool *localrestart)
    Definition: reopt.c:2025
    static SCIP_RETCODE storeCuts(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_LP *lp, unsigned int id)
    Definition: reopt.c:1524
    static SCIP_RETCODE transformDualredsToLinear(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_REOPTCONSDATA *consdata, SCIP_REOPTCONSDATA *dualreds)
    Definition: reopt.c:6752
    SCIP_RETCODE SCIPreoptFree(SCIP_REOPT **reopt, SCIP_SET *set, SCIP_PRIMAL *origprimal, BMS_BLKMEM *blkmem)
    Definition: reopt.c:5125
    static SCIP_RETCODE addLocalConss(SCIP *scip, SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int id)
    Definition: reopt.c:4201
    int SCIPreoptnodeGetNConss(SCIP_REOPTNODE *reoptnode)
    Definition: reopt.c:5804
    static SCIP_RETCODE solnodeAddChild(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_SOLNODE *curnode, SCIP_SOLNODE **child, SCIP_VAR *var, SCIP_Real val, SCIP_Bool *added)
    Definition: reopt.c:814
    void SCIPreoptnodeGetConss(SCIP_REOPTNODE *reoptnode, SCIP_VAR ***vars, SCIP_Real **bounds, SCIP_BOUNDTYPE **boundtypes, int mem, int *nconss, int *nvars)
    Definition: reopt.c:5857
    static SCIP_RETCODE checkMemGlbCons(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, int mem)
    Definition: reopt.c:1311
    int SCIPreoptGetLastRestarts(SCIP_REOPT *reopt)
    Definition: reopt.c:4927
    static SCIP_RETCODE reoptnodeResetDualConss(SCIP_REOPTNODE *reoptnode, BMS_BLKMEM *blkmem)
    Definition: reopt.c:3171
    static SCIP_RETCODE createReopttree(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem)
    Definition: reopt.c:1173
    int SCIPreoptnodeGetNVars(SCIP_REOPTNODE *reoptnode)
    Definition: reopt.c:5794
    static SCIP_RETCODE ensureActiveconssSize(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, int num)
    Definition: reopt.c:171
    int SCIPreoptGetNTotalCutoffReoptnodes(SCIP_REOPT *reopt)
    Definition: reopt.c:4987
    static int reopttreeGetNNodes(SCIP_REOPTTREE *reopttree, unsigned int id)
    Definition: reopt.c:4511
    static SCIP_RETCODE createReoptnode(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, unsigned int id)
    Definition: reopt.c:1116
    void SCIPreoptnodeGetPath(SCIP_REOPT *reopt, SCIP_REOPTNODE *reoptnode, SCIP_VAR **vars, SCIP_Real *vals, SCIP_BOUNDTYPE *boundtypes, int varssize, int *nbndchgs, int *nbndchgsafterdual)
    Definition: reopt.c:7183
    SCIP_RETCODE SCIPreoptAddOptSol(SCIP_REOPT *reopt, SCIP_SOL *sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *origprimal, SCIP_VAR **vars, int nvars)
    Definition: reopt.c:5328
    SCIP_REOPTTYPE SCIPreoptnodeGetType(SCIP_REOPTNODE *reoptnode)
    Definition: reopt.c:5847
    int SCIPreoptGetNNodes(SCIP_REOPT *reopt, SCIP_NODE *node)
    Definition: reopt.c:5754
    static SCIP_RETCODE moveChildrenUp(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, unsigned int nodeid, unsigned int parentid)
    Definition: reopt.c:1762
    SCIP_Real SCIPreoptGetSavingtime(SCIP_REOPT *reopt)
    Definition: reopt.c:7565
    SCIP_RETCODE SCIPreoptResetActiveConss(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat)
    Definition: reopt.c:8243
    SCIP_RETCODE SCIPreoptnodeDelete(SCIP_REOPTNODE **reoptnode, BMS_BLKMEM *blkmem)
    Definition: reopt.c:7925
    SCIP_RETCODE SCIPreoptCreate(SCIP_REOPT **reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
    Definition: reopt.c:5017
    int SCIPreoptGetNTotalInfNodes(SCIP_REOPT *reopt)
    Definition: reopt.c:5007
    SCIP_RETCODE SCIPreoptAddDualBndchg(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newval, SCIP_Real oldval)
    Definition: reopt.c:6230
    #define DEFAULT_RANDSEED
    Definition: reopt.c:66
    static SCIP_Real reoptSimilarity(SCIP_REOPT *reopt, SCIP_SET *set, int obj1_id, int obj2_id, SCIP_VAR **vars, int nvars)
    Definition: reopt.c:396
    static SCIP_RETCODE collectDualInformation(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int id, SCIP_REOPTTYPE reopttype)
    Definition: reopt.c:2477
    static SCIP_RETCODE addSplitcons(SCIP_REOPT *reopt, SCIP *scip, SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_NODE *node, unsigned int id)
    Definition: reopt.c:3710
    SCIP_Real SCIPreoptGetSimilarity(SCIP_REOPT *reopt, SCIP_SET *set, int run1, int run2, SCIP_VAR **origvars, int norigvars)
    Definition: reopt.c:5624
    static SCIP_RETCODE ensureRunSize(SCIP_REOPT *reopt, SCIP_SET *set, int num, BMS_BLKMEM *blkmem)
    Definition: reopt.c:219
    static SCIP_RETCODE dryBranch(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_Bool *runagain, unsigned int id)
    Definition: reopt.c:4296
    static SCIP_RETCODE soltreefreeNode(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SOLNODE **solnode)
    Definition: reopt.c:744
    SCIP_RETCODE SCIPreoptGetLeaves(SCIP_REOPT *reopt, SCIP_NODE *node, unsigned int *leaves, int leavessize, int *nleaves)
    Definition: reopt.c:6393
    static SCIP_RETCODE updatePropagation(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int id, SCIP_Bool *transintoorig)
    Definition: reopt.c:1387
    static SCIP_RETCODE soltreeAddSol(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *origprimal, BMS_BLKMEM *blkmem, SCIP_VAR **vars, SCIP_SOL *sol, SCIP_SOLNODE **solnode, int nvars, SCIP_Bool bestsol, SCIP_Bool *added)
    Definition: reopt.c:995
    int SCIPreoptGetNAddedConss(SCIP_REOPT *reopt, SCIP_NODE *node)
    Definition: reopt.c:5251
    SCIP_RETCODE SCIPreoptMergeVarHistory(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **vars, int nvars)
    Definition: reopt.c:6506
    static SCIP_DECL_EVENTINITSOL(eventInitsolReopt)
    Definition: reopt.c:114
    static SCIP_RETCODE checkMemDualCons(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, int size)
    Definition: reopt.c:1277
    #define EVENTHDLR_DESC
    Definition: reopt.c:70
    SCIP_RETCODE SCIPreoptSaveGlobalBounds(SCIP_REOPT *reopt, SCIP_PROB *transprob, BMS_BLKMEM *blkmem)
    Definition: reopt.c:8111
    SCIP_REOPTNODE * SCIPreoptGetReoptnode(SCIP_REOPT *reopt, unsigned int id)
    Definition: reopt.c:5657
    void SCIPreoptAddNImprovingSols(SCIP_REOPT *reopt, int nimprovingsols)
    Definition: reopt.c:5429
    static SCIP_RETCODE reoptnodeUpdateDualConss(SCIP_REOPTNODE *reoptnode, BMS_BLKMEM *blkmem)
    Definition: reopt.c:1992
    SCIP_Bool SCIPreoptGetSolveLP(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_NODE *node)
    Definition: reopt.c:7827
    SCIP_RETCODE SCIPreoptCheckRestart(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, SCIP_VAR **transvars, int ntransvars, SCIP_Bool *restart)
    Definition: reopt.c:5537
    int SCIPreoptGetNCutoffReoptnodes(SCIP_REOPT *reopt)
    Definition: reopt.c:4977
    SCIP_RETCODE SCIPreoptInstallBounds(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, BMS_BLKMEM *blkmem)
    Definition: reopt.c:8191
    static SCIP_RETCODE reoptSaveNewObj(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR **origvars, int norigvars)
    Definition: reopt.c:4659
    int SCIPreoptnodeGetNChildren(SCIP_REOPTNODE *reoptnode)
    Definition: reopt.c:5827
    SCIP_RETCODE SCIPreoptApplyGlbConss(SCIP *scip, SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem)
    Definition: reopt.c:7575
    SCIP_RETCODE SCIPreoptApplyCompression(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_REOPTNODE **representatives, int nrepresentatives, SCIP_Bool *success)
    Definition: reopt.c:6653
    #define DEFAULT_MEM_RUN
    Definition: reopt.c:63
    int SCIPreoptnodeGetNDualBoundChgs(SCIP_REOPTNODE *reoptnode)
    Definition: reopt.c:5814
    SCIP_Real SCIPreoptGetSimToPrevious(SCIP_REOPT *reopt)
    Definition: reopt.c:5606
    SCIP_RETCODE SCIPreoptReset(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
    Definition: reopt.c:5699
    SCIP_RETCODE SCIPreoptGetChildIDs(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int *childs, int childssize, int *nchilds)
    Definition: reopt.c:6340
    static SCIP_RETCODE saveAncestorBranchings(SCIP_REOPTTREE *reopttree, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, SCIP_NODE *parent, unsigned int id, unsigned int parentid)
    Definition: reopt.c:2113
    #define EVENTHDLR_NAME
    Definition: reopt.c:69
    int SCIPreoptGetNRestartsGlobal(SCIP_REOPT *reopt)
    Definition: reopt.c:4887
    SCIP_RETCODE SCIPreoptSaveOpenNodes(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_NODE **leaves, int nleaves, SCIP_NODE **childs, int nchilds, SCIP_NODE **siblings, int nsiblings)
    Definition: reopt.c:6456
    static SCIP_RETCODE saveConsLinear(SCIP_REOPTCONSDATA *reoptconsdata, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_CONS *cons, SCIP_Bool *success)
    Definition: reopt.c:2182
    SCIP_SOL * SCIPreoptGetBestSolRun(SCIP_REOPT *reopt, int run)
    Definition: reopt.c:5687
    void SCIPreoptnodeInit(SCIP_REOPTNODE *reoptnode, SCIP_SET *set)
    Definition: reopt.c:7874
    static SCIP_RETCODE fixBounds(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, BMS_BLKMEM *blkmem, SCIP_NODE *node, unsigned int id, SCIP_Bool updatedualconss)
    Definition: reopt.c:3967
    int SCIPreoptGetNLeaves(SCIP_REOPT *reopt, SCIP_NODE *node)
    Definition: reopt.c:5904
    int SCIPreoptGetNInfNodes(SCIP_REOPT *reopt)
    Definition: reopt.c:4997
    data structures and methods for collecting reoptimization information
    SCIP callable library.
    SCIP_RETCODE SCIPsepastoreAddCut(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool root, SCIP_Bool *infeasible)
    Definition: sepastore.c:439
    internal methods for storing separated cuts
    SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6617
    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 SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6577
    SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6537
    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_RETCODE SCIPsetGetIntParam(SCIP_SET *set, const char *name, int *value)
    Definition: set.c:3382
    SCIP_RETCODE SCIPsetIncludeEventhdlr(SCIP_SET *set, SCIP_EVENTHDLR *eventhdlr)
    Definition: set.c:4988
    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 SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6597
    SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6670
    SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6637
    SCIP_BRANCHRULE * SCIPsetFindBranchrule(SCIP_SET *set, const char *name)
    Definition: set.c:5144
    SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:7041
    SCIP_Real SCIPsetRound(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6740
    int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
    Definition: set.c:6080
    SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6659
    unsigned int SCIPsetInitializeRandomSeed(SCIP_SET *set, unsigned int initialseedvalue)
    Definition: set.c:7800
    internal methods for global SCIP settings
    #define SCIPsetFreeBufferArray(set, ptr)
    Definition: set.h:1782
    #define SCIPsetAllocBufferArray(set, ptr, num)
    Definition: set.h:1775
    #define SCIPsetDebugMsg
    Definition: set.h:1811
    #define SCIPsetReallocBufferArray(set, ptr, num)
    Definition: set.h:1779
    SCIP_RETCODE SCIPsolFree(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_PRIMAL *primal)
    Definition: sol.c:1133
    SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
    Definition: sol.c:1908
    SCIP_RETCODE SCIPsolCopy(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *primal, SCIP_SOL *sourcesol)
    Definition: sol.c:583
    internal methods for storing primal CIP solutions
    unsigned int deleted
    Definition: struct_cons.h:94
    SCIP_Real pscostweightedmean[2]
    SCIP_Real pscostvariance[2]
    SCIP_Real pscostcount[2]
    SCIP_VAR ** afterdualvars
    Definition: struct_reopt.h:97
    SCIP_REOPTCONSDATA * dualredscur
    Definition: struct_reopt.h:98
    SCIP_REOPTCONSDATA * dualredsnex
    Definition: struct_reopt.h:99
    SCIP_BOUNDTYPE * afterdualvarboundtypes
    Definition: struct_reopt.h:101
    SCIP_BOUNDTYPE * varboundtypes
    Definition: struct_reopt.h:100
    unsigned int * childids
    Definition: struct_reopt.h:114
    SCIP_Bool dualreds
    Definition: struct_reopt.h:105
    SCIP_VAR ** vars
    Definition: struct_reopt.h:96
    SCIP_Real * afterdualvarbounds
    Definition: struct_reopt.h:103
    SCIP_REOPTCONSDATA ** conss
    Definition: struct_reopt.h:95
    SCIP_Real lowerbound
    Definition: struct_reopt.h:104
    unsigned int parentID
    Definition: struct_reopt.h:116
    unsigned int reopttype
    Definition: struct_reopt.h:117
    SCIP_Real * varbounds
    Definition: struct_reopt.h:102
    SCIP_QUEUE * openids
    Definition: struct_reopt.h:124
    unsigned int reoptnodessize
    Definition: struct_reopt.h:135
    SCIP_REOPTNODE ** reoptnodes
    Definition: struct_reopt.h:123
    int ntotalcutoffreoptnodes
    Definition: struct_reopt.h:133
    int firstrestart
    Definition: struct_reopt.h:182
    int nimprovingsols
    Definition: struct_reopt.h:178
    SCIP_REOPTCONSDATA ** glbconss
    Definition: struct_reopt.h:144
    SCIP_Bool consadded
    Definition: struct_reopt.h:159
    int nactiveconss
    Definition: struct_reopt.h:160
    SCIP_SOL ** prevbestsols
    Definition: struct_reopt.h:141
    SCIP_REOPTTREE * reopttree
    Definition: struct_reopt.h:146
    SCIP_REOPTCONSDATA * dualreds
    Definition: struct_reopt.h:145
    int nglbrestarts
    Definition: struct_reopt.h:179
    SCIP_SOLTREE * soltree
    Definition: struct_reopt.h:147
    SCIP_Longint lastbranched
    Definition: struct_reopt.h:153
    int nlocrestarts
    Definition: struct_reopt.h:181
    int ntotallocrestarts
    Definition: struct_reopt.h:180
    int noptsolsbyreoptsol
    Definition: struct_reopt.h:174
    int nmaxactiveconss
    Definition: struct_reopt.h:162
    SCIP_RANDNUMGEN * randnumgen
    Definition: struct_reopt.h:148
    SCIP_CLOCK * savingtime
    Definition: struct_reopt.h:149
    SCIP_HASHMAP * glblb
    Definition: struct_reopt.h:165
    SCIP_Longint lastseennode
    Definition: struct_reopt.h:154
    SCIP_CONS ** activeconss
    Definition: struct_reopt.h:161
    SCIP_Longint currentnode
    Definition: struct_reopt.h:170
    SCIP_HASHSET * activeconssset
    Definition: struct_reopt.h:167
    SCIP_HISTORY *** varhistory
    Definition: struct_reopt.h:143
    SCIP_Bool objhaschanged
    Definition: struct_reopt.h:158
    SCIP_Real simtofirstobj
    Definition: struct_reopt.h:152
    SCIP_Real ** objs
    Definition: struct_reopt.h:142
    int addedconsssize
    Definition: struct_reopt.h:156
    SCIP_CONS ** addedconss
    Definition: struct_reopt.h:150
    int ncheckedsols
    Definition: struct_reopt.h:177
    SCIP_HASHMAP * glbub
    Definition: struct_reopt.h:166
    int allocmemglbconss
    Definition: struct_reopt.h:176
    SCIP_Real simtolastobj
    Definition: struct_reopt.h:151
    SCIP_SOL * sol
    Definition: struct_reopt.h:53
    SCIP_VAR * var
    Definition: struct_reopt.h:63
    SCIP_Real value
    Definition: struct_reopt.h:59
    SCIP_SOLNODE * child
    Definition: struct_reopt.h:55
    SCIP_SOLNODE * father
    Definition: struct_reopt.h:54
    SCIP_SOLNODE * sibling
    Definition: struct_reopt.h:58
    SCIP_Bool updated
    Definition: struct_reopt.h:60
    SCIP_SOLNODE * root
    Definition: struct_reopt.h:71
    SCIP_SOLNODE *** sols
    Definition: struct_reopt.h:70
    int * solssize
    Definition: struct_reopt.h:72
    SCIP_HISTORY * history
    Definition: struct_var.h:306
    Definition: heur_padm.c:135
    void SCIPnodeGetDualBoundchgs(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *bounds, SCIP_BOUNDTYPE *boundtypes, int *nvars, int varssize)
    Definition: tree.c:8706
    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
    void SCIPnodeSetEstimate(SCIP_NODE *node, SCIP_SET *set, SCIP_Real newestimate)
    Definition: tree.c:3084
    void SCIPnodeGetPropsAfterDual(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *varbounds, SCIP_BOUNDTYPE *varboundtypes, int *nvars, int varssize)
    Definition: tree.c:9017
    SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
    Definition: tree.c:9529
    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
    int SCIPnodeGetNDualBndchgs(SCIP_NODE *node)
    Definition: tree.c:8665
    void SCIPnodeGetPropsBeforeDual(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *varbounds, SCIP_BOUNDTYPE *varboundtypes, int *npropvars, int propvarssize)
    Definition: tree.c:8935
    internal methods for branch and bound tree
    @ SCIP_CLOCKTYPE_DEFAULT
    Definition: type_clock.h:43
    #define SCIP_EVENTTYPE_NODEFEASIBLE
    Definition: type_event.h:94
    #define SCIP_EVENTTYPE_GBDCHANGED
    Definition: type_event.h:122
    #define SCIP_EVENTTYPE_NODEINFEASIBLE
    Definition: type_event.h:95
    #define SCIP_EVENTTYPE_NODEBRANCHED
    Definition: type_event.h:96
    #define SCIP_EVENTTYPE_FORMAT
    Definition: type_event.h:157
    uint64_t SCIP_EVENTTYPE
    Definition: type_event.h:156
    @ SCIP_BRANCHDIR_DOWNWARDS
    Definition: type_history.h:43
    @ 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_ROWORIGINTYPE_REOPT
    Definition: type_lp.h:77
    @ SCIP_ROWORIGINTYPE_SEPA
    Definition: type_lp.h:76
    @ 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_INFEASIBLE
    Definition: type_lp.h:45
    @ SCIP_LPSOLSTAT_OBJLIMIT
    Definition: type_lp.h:47
    @ SCIP_VERBLEVEL_HIGH
    Definition: type_message.h:61
    @ SCIP_VERBLEVEL_NORMAL
    Definition: type_message.h:60
    @ 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
    struct SCIP_ReoptConsData SCIP_REOPTCONSDATA
    Definition: type_reopt.h:51
    @ REOPT_CONSTYPE_DUALREDS
    Definition: type_reopt.h:72
    @ REOPT_CONSTYPE_INFSUBTREE
    Definition: type_reopt.h:71
    @ REOPT_CONSTYPE_CUT
    Definition: type_reopt.h:73
    @ REOPT_CONSTYPE_UNKNOWN
    Definition: type_reopt.h:74
    enum Reopt_ConsType REOPT_CONSTYPE
    Definition: type_reopt.h:76
    @ SCIP_INVALIDRESULT
    Definition: type_retcode.h:53
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_PROBLEM
    Definition: type_set.h:45
    @ SCIP_STAGE_INIT
    Definition: type_set.h:44
    @ SCIP_STAGE_SOLVING
    Definition: type_set.h:53
    @ SCIP_NODETYPE_PROBINGNODE
    Definition: type_tree.h:42
    @ SCIP_NODETYPE_FOCUSNODE
    Definition: type_tree.h:41
    @ SCIP_VARTYPE_INTEGER
    Definition: type_var.h:65
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64
    @ SCIP_VARSTATUS_COLUMN
    Definition: type_var.h:53
    @ SCIP_VARSTATUS_MULTAGGR
    Definition: type_var.h:56
    void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
    Definition: var.c:9910
    SCIP_RETCODE SCIPvarChgLbGlobal(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)
    Definition: var.c:11178
    SCIP_RETCODE SCIPvarChgUbGlobal(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)
    Definition: var.c:11475
    SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
    Definition: var.c:22119
    SCIP_RETCODE SCIPvarChgLbLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound)
    Definition: var.c:12715
    SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
    Definition: var.c:8979
    void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
    Definition: var.c:9961
    SCIP_RETCODE SCIPvarChgUbLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound)
    Definition: var.c:12983
    internal methods for problem variables