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-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file 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
    33#include "scip/def.h"
    34#include "scip/mem.h"
    35#include "scip/event.h"
    36#include "scip/scip.h"
    37#include "scip/set.h"
    38#include "scip/sol.h"
    39#include "scip/var.h"
    40#include "scip/lp.h"
    41#include "scip/misc.h"
    42#include "scip/reopt.h"
    43#include "scip/tree.h"
    44#include "scip/primal.h"
    45#include "scip/sepastore.h"
    46#include "scip/cutpool.h"
    47#include "scip/prob.h"
    48#include "scip/cons.h"
    50#include "scip/cons_linear.h"
    51#include "scip/cons_logicor.h"
    52#include "scip/cons_setppc.h"
    53#include "scip/cons_linear.h"
    54#include "scip/clock.h"
    55#include "scip/history.h"
    57
    58#define DEFAULT_MEM_VARAFTERDUAL 10
    59#define DEFAULT_MEM_VAR 10
    60#define DEFAULT_MEM_NODES 1000
    61#define DEFAULT_MEM_RUN 200
    62#define DEFAULT_MEM_DUALCONS 10
    63
    64#define DEFAULT_RANDSEED 67
    65
    66/* event handler properties */
    67#define EVENTHDLR_NAME "Reopt"
    68#define EVENTHDLR_DESC "node event handler for reoptimization"
    69
    70/* ---------------- Callback methods of event handler ---------------- */
    71
    72/** exec the event handler */
    73static
    74SCIP_DECL_EVENTEXEC(eventExecReopt)
    75{ /*lint --e{715}*/
    76 SCIP_NODE* eventnode;
    77 SCIP_Real oldbound;
    78 SCIP_Real newbound;
    79
    80 assert(scip != NULL);
    81 assert(eventhdlr != NULL);
    82 assert(SCIPvarIsIntegral(SCIPeventGetVar(event)));
    83
    85
    87 return SCIP_OKAY;
    88
    89 eventnode = SCIPgetCurrentNode(scip);
    90 oldbound = SCIPeventGetOldbound(event);
    91 newbound = SCIPeventGetNewbound(event);
    92
    93 /* 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 */
    94 if( eventnode == NULL )
    95 return SCIP_OKAY;
    96
    97 /* skip if the node is not the focus node */
    99 return SCIP_OKAY;
    100
    101 SCIPdebugMsg(scip, "catch event for node %lld: <%s>: %g -> %g\n", SCIPnodeGetNumber(eventnode),
    103
    104 assert(SCIPisFeasLT(scip, newbound, oldbound) || SCIPisFeasGT(scip, newbound, oldbound));
    105
    106 SCIP_CALL( SCIPaddReoptDualBndchg(scip, eventnode, SCIPeventGetVar(event), newbound, oldbound) );
    107
    108 return SCIP_OKAY;
    109}
    110
    111/** solving process initialization method of event handler (called when branch and bound process is about to begin) */
    112static
    113SCIP_DECL_EVENTINITSOL(eventInitsolReopt)
    114{
    115 SCIP_VAR** vars;
    116
    117 assert(scip != NULL);
    118 assert(eventhdlr != NULL);
    119
    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 assert(eventhdlr != NULL);
    145
    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_BOUNDTYPE* boundtypes;
    2324 SCIP_Real* bounds;
    2325
    2326 assert(reoptconsdata != NULL);
    2327 assert(cons != NULL);
    2328
    2329 *success = FALSE;
    2330 reoptconsdata->linear = FALSE;
    2331
    2333
    2334 SCIP_CALL( SCIPconsGetNVars(cons, set, &reoptconsdata->nvars, success) );
    2335 assert(*success);
    2336
    2337 /* allocate memory for variables and values; boundtypes are not needed */
    2338 vars = SCIPgetVarsBounddisjunction(NULL, cons);
    2339 bounds = SCIPgetBoundsBounddisjunction(NULL, cons);
    2340 boundtypes = SCIPgetBoundtypesBounddisjunction(NULL, cons);
    2341 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptconsdata->vars, vars, reoptconsdata->nvars) );
    2342 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptconsdata->vals, bounds, reoptconsdata->nvars) );
    2343 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, boundtypes, reoptconsdata->nvars) );
    2344 reoptconsdata->varssize = reoptconsdata->nvars;
    2345 reoptconsdata->lhs = SCIP_UNKNOWN;
    2346 reoptconsdata->rhs = SCIP_UNKNOWN;
    2347
    2348 /* transform all variables into the original space */
    2349 for( int v = 0; v < reoptconsdata->nvars; ++v )
    2350 {
    2351 SCIP_Real constant = 0.0;
    2352 SCIP_Real scalar = 1.0;
    2353
    2354 assert(reoptconsdata->vars[v] != NULL);
    2355
    2356 SCIP_CALL( SCIPvarGetOrigvarSum(&reoptconsdata->vars[v], &scalar, &constant) );
    2357 assert(!SCIPsetIsZero(set, scalar));
    2358
    2359 assert(!SCIPsetIsInfinity(set, REALABS(reoptconsdata->vals[v])));
    2360 reoptconsdata->vals[v] -= constant;
    2361 reoptconsdata->vals[v] *= scalar;
    2362
    2363 /* due to multipling with a negative scalar the relation need to be changed */
    2364 if( SCIPsetIsNegative(set, scalar) )
    2365 reoptconsdata->boundtypes[v] = (SCIP_BOUNDTYPE)(SCIP_BOUNDTYPE_UPPER - reoptconsdata->boundtypes[v]); /*lint !e656*/
    2366 }
    2367
    2368 return SCIP_OKAY;
    2369}
    2370
    2371/** save additional all constraints that were additionally added to @p node */
    2372static
    2374 SCIP_REOPTTREE* reopttree, /**< reopttree */
    2375 SCIP_SET* set, /**< global SCIP settings */
    2376 BMS_BLKMEM* blkmem, /**< block memory */
    2377 SCIP_NODE* node, /**< node of the branch and bound tree */
    2378 unsigned int id /**< id of the node*/
    2379 )
    2380{
    2381 SCIP_CONS** addedcons;
    2382 int naddedconss;
    2383 int addedconsssize;
    2384 int nconss;
    2385
    2386 assert(node != NULL );
    2387 assert(reopttree != NULL);
    2388 assert(id < reopttree->reoptnodessize);
    2389
    2390 /* save the added pseudo-constraint */
    2391 if( SCIPnodeGetNAddedConss(node) > 0 )
    2392 {
    2393 addedconsssize = SCIPnodeGetNAddedConss(node);
    2394
    2395 SCIPsetDebugMsg(set, " -> save %d locally added constraints\n", addedconsssize);
    2396
    2397 /* get memory */
    2398 SCIP_CALL( SCIPsetAllocBufferArray(set, &addedcons, addedconsssize) );
    2399 SCIPnodeGetAddedConss(node, addedcons, &naddedconss, addedconsssize);
    2400
    2401 nconss = reopttree->reoptnodes[id]->nconss;
    2402
    2403 /* check memory for added constraints */
    2404 SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], set, blkmem, 0, 0, naddedconss) );
    2405
    2406 /* since the first nconss are already stored in the data structure, we skip them */
    2407 for( int c = nconss; c < naddedconss; ++c )
    2408 {
    2409 SCIP_CONSHDLR* conshdlr;
    2410 SCIP_Bool islinear;
    2411 SCIP_Bool success;
    2412
    2413 conshdlr = SCIPconsGetHdlr(addedcons[c]);
    2414
    2415 /* check whether the constraint has a linear representation */
    2416 islinear = (strcmp(SCIPconshdlrGetName(conshdlr), "linear") == 0
    2417 || strcmp(SCIPconshdlrGetName(conshdlr), "logicor") == 0
    2418 || strcmp(SCIPconshdlrGetName(conshdlr), "setppc") == 0);
    2419
    2420 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopttree->reoptnodes[id]->conss[c]) ); /*lint !e866*/
    2421
    2422 success = FALSE;
    2423
    2424 /* the constraint has a linear representation */
    2425 if( islinear )
    2426 {
    2427 SCIP_CALL( saveConsLinear(reopttree->reoptnodes[id]->conss[c], set, blkmem, addedcons[c], &success) );
    2428 assert(success);
    2429
    2430 /* increase the counter for added constraints */
    2431 ++reopttree->reoptnodes[id]->nconss;
    2432 }
    2433 else
    2434 {
    2435 SCIP_STRINGEQ( SCIPconshdlrGetName(conshdlr), "bounddisjunction", SCIP_INVALIDCALL );
    2436
    2437 SCIP_CALL( saveConsBounddisjuction(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 assert(reopttree->reoptnodes[id]->conss[c]->nvars > 0);
    2444
    2445 if( strcmp("reopt_inf", SCIPconsGetName(addedcons[c])) == 0 )
    2446 reopttree->reoptnodes[id]->conss[c]->constype = REOPT_CONSTYPE_INFSUBTREE;
    2447 else if( strcmp("reopt_dual", SCIPconsGetName(addedcons[c])) == 0 )
    2448 reopttree->reoptnodes[id]->conss[c]->constype = REOPT_CONSTYPE_DUALREDS;
    2449 else
    2450 reopttree->reoptnodes[id]->conss[c]->constype = REOPT_CONSTYPE_UNKNOWN;
    2451 }
    2452
    2453 assert(reopttree->reoptnodes[id]->nconss == naddedconss);
    2454 SCIPsetFreeBufferArray(set, &addedcons);
    2455 }
    2456
    2457 return SCIP_OKAY;
    2458}
    2459
    2460/** collect all bound changes based on dual information
    2461 *
    2462 * If the bound changes are global, all information are already stored because they were caught by the event handler.
    2463 * otherwise, we have to use SCIPnodeGetDualBoundchgs.
    2464 *
    2465 * Afterwards, we check if the constraint will be added in the next iteration or after splitting the node.
    2466 */
    2467static
    2469 SCIP_REOPT* reopt, /**< reoptimization data structure */
    2470 SCIP_SET* set, /**< global SCIP settings */
    2471 BMS_BLKMEM* blkmem, /**< block memory */
    2472 SCIP_NODE* node, /**< node of the search tree */
    2473 unsigned int id, /**< id of the node */
    2474 SCIP_REOPTTYPE reopttype /**< reopttype */
    2475 )
    2476{
    2477 SCIP_Bool cons_is_next = TRUE;
    2478 int nbndchgs;
    2479
    2480 assert(reopt != NULL);
    2481 assert(reopt->reopttree != NULL);
    2482 assert(id < reopt->reopttree->reoptnodessize);
    2483 assert(reopt->reopttree->reoptnodes[id]->dualreds);
    2484 assert(node != NULL);
    2485 assert(blkmem != NULL);
    2486
    2487 /* first case, all bound changes were global */
    2488 if( reopt->currentnode == SCIPnodeGetNumber(node) && reopt->dualreds != NULL && reopt->dualreds->nvars > 0 )
    2489 {
    2490 nbndchgs = reopt->dualreds->nvars;
    2491 }
    2492 else
    2493 {
    2494 assert(reopt->currentnode == SCIPnodeGetNumber(node));
    2495
    2496 /* get the number of bound changes based on dual information */
    2497 nbndchgs = SCIPnodeGetNDualBndchgs(node);
    2498
    2499 /* ensure that enough memory is allocated */
    2500 SCIP_CALL( checkMemDualCons(reopt, set, blkmem, nbndchgs) );
    2501
    2502 /* collect the bound changes */
    2503 SCIPnodeGetDualBoundchgs(node, reopt->dualreds->vars, reopt->dualreds->vals, reopt->dualreds->boundtypes,
    2504 &nbndchgs, reopt->dualreds->varssize);
    2505 assert(nbndchgs <= reopt->dualreds->varssize);
    2506
    2507 reopt->dualreds->nvars = nbndchgs;
    2508 reopt->dualreds->linear = FALSE;
    2509
    2510 /* transform the variables into the original space */
    2511 for( int v = 0; v < nbndchgs; ++v )
    2512 {
    2513 SCIP_Real constant = 0.0;
    2514 SCIP_Real scalar = 1.0;
    2515
    2516 SCIP_CALL( SCIPvarGetOrigvarSum(&reopt->dualreds->vars[v], &scalar, &constant) );
    2517 reopt->dualreds->vals[v] = (reopt->dualreds->vals[v] - constant) / scalar;
    2518
    2519 assert(SCIPvarIsOriginal(reopt->dualreds->vars[v]));
    2520 }
    2521 }
    2522
    2523 assert(nbndchgs > 0);
    2524
    2525 /* due to the strong branching initialization it can be possible that two
    2526 * constraints handling dual information are stored at the same time.
    2527 * During reoptimizing a node we add the constraint stored at dualredscur only,
    2528 * i.e, if dualredscur is not NULL, we need to store the constraint for the next
    2529 * iteration at dualredsnex because the constraint stored at dualredscur is needed
    2530 * to split the constraint in the current iteration.
    2531 */
    2532 if( reopt->reopttree->reoptnodes[id]->dualredscur != NULL )
    2533 {
    2534 assert(reopt->reopttree->reoptnodes[id]->dualredsnex == NULL);
    2535 cons_is_next = FALSE;
    2536 }
    2537 assert((cons_is_next && reopt->reopttree->reoptnodes[id]->dualredscur == NULL)
    2538 || (!cons_is_next && reopt->reopttree->reoptnodes[id]->dualredsnex == NULL));
    2539
    2540 /* the constraint will be added next */
    2541 if( cons_is_next )
    2542 {
    2543 assert(reopt->reopttree->reoptnodes[id]->dualredscur == NULL);
    2546 reopt->dualreds->vars, nbndchgs) );
    2548 reopt->dualreds->vals, nbndchgs) );
    2549 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopt->reopttree->reoptnodes[id]->dualredscur->boundtypes, \
    2550 reopt->dualreds->boundtypes, nbndchgs) );
    2551
    2552 reopt->reopttree->reoptnodes[id]->dualredscur->nvars = nbndchgs;
    2553 reopt->reopttree->reoptnodes[id]->dualredscur->varssize = nbndchgs;
    2554 reopt->reopttree->reoptnodes[id]->dualredscur->lhs = 1.0;
    2555 reopt->reopttree->reoptnodes[id]->dualredscur->rhs = SCIPsetInfinity(set);
    2556 reopt->reopttree->reoptnodes[id]->dualredscur->constype = (reopttype == SCIP_REOPTTYPE_STRBRANCHED ?
    2558 reopt->reopttree->reoptnodes[id]->dualredscur->linear = FALSE;
    2559
    2560 SCIPsetDebugMsg(set, " -> save dual information of type 1: node %lld, nvars %d, constype %d\n",
    2561 SCIPnodeGetNumber(node), reopt->reopttree->reoptnodes[id]->dualredscur->nvars,
    2562 reopt->reopttree->reoptnodes[id]->dualredscur->constype);
    2563 }
    2564 /* the constraint will be added after next */
    2565 else
    2566 {
    2567 assert(reopt->reopttree->reoptnodes[id]->dualredsnex == NULL);
    2569 reopt->reopttree->reoptnodes[id]->dualredsnex->nvars = -1;
    2570
    2572 reopt->dualreds->vars, nbndchgs) );
    2574 reopt->dualreds->vals, nbndchgs) );
    2575 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reopt->reopttree->reoptnodes[id]->dualredsnex->boundtypes, \
    2576 reopt->dualreds->boundtypes, nbndchgs) );
    2577 reopt->reopttree->reoptnodes[id]->dualredsnex->nvars = nbndchgs;
    2578 reopt->reopttree->reoptnodes[id]->dualredsnex->varssize = nbndchgs;
    2579 reopt->reopttree->reoptnodes[id]->dualredsnex->lhs = 1.0;
    2580 reopt->reopttree->reoptnodes[id]->dualredsnex->rhs = SCIPsetInfinity(set);
    2581 reopt->reopttree->reoptnodes[id]->dualredsnex->constype = (reopttype == SCIP_REOPTTYPE_STRBRANCHED ?
    2583
    2584 SCIPsetDebugMsg(set, " -> save dual information of type 2: node %lld, nvars %d, constype %d\n",
    2585 SCIPnodeGetNumber(node), reopt->reopttree->reoptnodes[id]->dualredsnex->nvars,
    2586 reopt->reopttree->reoptnodes[id]->dualredsnex->constype);
    2587 }
    2588
    2589 return SCIP_OKAY;
    2590}
    2591
    2592/** adds a node of the branch and bound tree to the reoptimization tree */
    2593static
    2595 SCIP_REOPT* reopt, /**< reoptimization data structure */
    2596 SCIP_SET* set, /**< global SCIP settings */
    2597 SCIP_LP* lp, /**< current LP */
    2598 BMS_BLKMEM* blkmem, /**< block memory */
    2599 SCIP_NODE* node, /**< current node */
    2600 SCIP_REOPTTYPE reopttype, /**< reason for storing the node*/
    2601 SCIP_Bool saveafterdual, /**< save branching decisions after the first dual */
    2602 SCIP_Bool isrootnode, /**< node is the root node */
    2603 SCIP_Real lowerbound /**< lower bound of the node */
    2604 )
    2605{
    2606 SCIP_NODE* parent = NULL;
    2607 SCIP_Bool shrank = FALSE;
    2608 unsigned int id;
    2609 unsigned int parentid = 0;
    2610
    2611 assert(reopt != NULL);
    2612 assert(set != NULL);
    2613 assert(blkmem != NULL);
    2614 assert(node != NULL);
    2615
    2616 if( set->reopt_maxsavednodes == 0 )
    2617 return SCIP_OKAY;
    2618
    2619 assert(reopttype == SCIP_REOPTTYPE_TRANSIT
    2620 || reopttype == SCIP_REOPTTYPE_INFSUBTREE
    2621 || reopttype == SCIP_REOPTTYPE_STRBRANCHED
    2622 || reopttype == SCIP_REOPTTYPE_LOGICORNODE
    2623 || reopttype == SCIP_REOPTTYPE_LEAF
    2624 || reopttype == SCIP_REOPTTYPE_PRUNED
    2625 || reopttype == SCIP_REOPTTYPE_FEASIBLE);
    2626
    2627 /* start clock */
    2628 SCIPclockStart(reopt->savingtime, set);
    2629
    2630 /* the node was created by reoptimization, i.e., we need to update the
    2631 * stored data */
    2632 if( SCIPnodeGetReoptID(node) >= 1 )
    2633 {
    2634 SCIP_Bool transintoorig;
    2635
    2636 assert(reopttype != SCIP_REOPTTYPE_LEAF);
    2637 assert(!isrootnode);
    2638
    2639 id = SCIPnodeGetReoptID(node);
    2640 assert(id < reopt->reopttree->reoptnodessize);
    2641
    2642 /* this is a special case:
    2643 * due to re-propagation of the an anchester node it can happen that we try to update a node that was created by
    2644 * reoptimization and already removed by deleteChildrenBelow. In this case we do not want to save the current
    2645 * node
    2646 */
    2647 if( reopt->reopttree->reoptnodes[id] == NULL )
    2648 {
    2649 parent = SCIPnodeGetParent(node);
    2650 assert(parent != NULL);
    2651
    2652 parentid = SCIPnodeGetReoptID(parent);
    2653
    2654 /* traverse along the branching path until reaching a node that is part of the reoptimization tree or the root node */
    2655 while( SCIPnodeGetDepth(parent) > 0 && reopt->reopttree->reoptnodes[parentid] == NULL )
    2656 {
    2657 /* the parent node is not part of the reoptimization, reset the reoptid and reopttype of the parent node */
    2658 SCIPnodeSetReoptID(parent, 0);
    2660
    2661 parent = SCIPnodeGetParent(parent);
    2662 assert(parent != NULL);
    2663
    2664 parentid = SCIPnodeGetReoptID(parent);
    2665 }
    2666
    2667 /* the anchestor node has to be part of the reoptimization tree. either the parent is the root itself or
    2668 * marked to be a leaf, pruned or feasible
    2669 */
    2670 assert(reopt->reopttree->reoptnodes[parentid] != NULL);
    2671 assert(parentid == 0
    2672 || reopt->reopttree->reoptnodes[parentid]->reopttype == SCIP_REOPTTYPE_FEASIBLE
    2674 || reopt->reopttree->reoptnodes[parentid]->reopttype == SCIP_REOPTTYPE_LEAF
    2675 || reopt->reopttree->reoptnodes[parentid]->reopttype == SCIP_REOPTTYPE_PRUNED); /*lint !e641*/
    2676
    2677 SCIPsetDebugMsg(set, " -> skip saving\n");
    2678 SCIPnodeSetReoptID(node, 0);
    2680
    2681 /* stop clock */
    2682 SCIPclockStop(reopt->savingtime, set);
    2683
    2684 return SCIP_OKAY;
    2685 }
    2686
    2687 SCIPsetDebugMsg(set, "update node %lld at ID %u:\n", SCIPnodeGetNumber(node), id);
    2688
    2689 transintoorig = FALSE;
    2690
    2691 /* store separated cuts */
    2692 if( set->reopt_usecuts )
    2693 {
    2694 SCIP_CALL( storeCuts(reopt, set, blkmem, lp, id) );
    2695 }
    2696
    2697 /* save primal bound changes made after the first dual bound change */
    2698 if( saveafterdual )
    2699 {
    2700 assert(reopttype == SCIP_REOPTTYPE_STRBRANCHED);
    2701 SCIP_CALL( saveAfterDualBranchings(reopt, set, blkmem, node, id, &transintoorig) );
    2702 }
    2703
    2704 /* update propagations */
    2705 if( set->reopt_saveprop )
    2706 {
    2707 SCIP_CALL( updatePropagation(reopt, set, blkmem, node, id, &transintoorig) );
    2708 }
    2709
    2710 /* ensure that all variables describing the branching path are original */
    2711 if( transintoorig )
    2712 {
    2713 SCIP_CALL( transformIntoOrig(reopt, id) );
    2714 }
    2715
    2716 /* update the lowerbound if the new lower bound is finite */
    2717 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
    2718 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
    2719 SCIPsetDebugMsg(set, " -> reopttype: %d, lowerbound: %g\n", reopttype, reopt->reopttree->reoptnodes[id]->lowerbound);
    2720
    2721#ifdef SCIP_MORE_DEBUG
    2722 SCIPsetDebugMsg(set, " -> saved variables:\n");
    2723 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; ++varnr )
    2724 {
    2725 SCIPsetDebugMsg(set, " <%s> %s %g\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->vars[varnr]),
    2727 "=>" : "<=", reopt->reopttree->reoptnodes[id]->varbounds[varnr]);
    2728 }
    2729 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nafterdualvars; ++varnr )
    2730 {
    2731 SCIPsetDebugMsg(set, " <%s> %s %g (after dual red.)\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]),
    2733 "=>" : "<=", reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr]);
    2734 }
    2735#endif
    2736
    2737 /* update LPI state */
    2738 switch( reopttype )
    2739 {
    2741 if( set->reopt_shrinkinner )
    2742 {
    2743 SCIP_CALL( shrinkNode(reopt, set, node, id, &shrank, blkmem) );
    2744 }
    2745 goto TRANSIT;
    2746
    2749 goto TRANSIT;
    2750
    2752 /* delete the whole subtree induced be the current node */
    2753 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
    2754 goto PSEUDO;
    2755
    2757 goto PSEUDO;
    2758
    2760 /* delete the subtree */
    2761 if( set->reopt_reducetofrontier )
    2762 {
    2763 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
    2764 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    2765 }
    2766 /* dive through all children and change the reopttype to PRUNED */
    2767 else
    2768 {
    2770 }
    2771 goto FEASIBLE;
    2772
    2774 /* delete the subtree */
    2775 if( set->reopt_reducetofrontier )
    2776 {
    2777 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, id, FALSE, FALSE) );
    2778 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    2779 }
    2780 /* dive through all children and change the reopttype to LEAF */
    2781 else
    2782 {
    2784 }
    2785
    2786 /* increase number of reoptimized nodes that could be pruned */
    2787 ++reopt->reopttree->ncutoffreoptnodes;
    2789
    2790 goto PRUNED;
    2791
    2792 default:
    2793 break;
    2794 } /*lint !e788*/
    2795
    2796 /* stop clock */
    2797 SCIPclockStart(reopt->savingtime, set);
    2798
    2799 return SCIP_OKAY;
    2800 }
    2801
    2802 /* get new IDs */
    2803 SCIP_CALL( reopttreeCheckMemory(reopt->reopttree, set, blkmem) );
    2804
    2805 /* the current node is the root node */
    2806 if( isrootnode )
    2807 {
    2808 id = 0;
    2809
    2810 /* save local constraints
    2811 * note: currently, there will be no constraint to save because all global constraints are added by calling
    2812 * SCIPprobAddCons.
    2813 */
    2814 if (SCIPnodeGetNAddedConss(node) >= 1)
    2815 {
    2816 assert(reopt->reopttree->reoptnodes[id]->nconss == 0);
    2817
    2818 SCIP_CALL( saveLocalConssData(reopt->reopttree, set, blkmem, node, id) );
    2819 }
    2820
    2821 /* store separated cuts
    2822 * note: we need to call this after saveLocalConssData to be sure that the local conss array is ordered, first all
    2823 * local constraints, then cuts
    2824 */
    2825 if( set->reopt_usecuts )
    2826 {
    2827 SCIP_CALL( storeCuts(reopt, set, blkmem, lp, id) );
    2828 }
    2829
    2830 switch( reopttype )
    2831 {
    2833 /* ensure that no dual constraints are stored */
    2834 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    2835
    2836 /* update the lowerbound */
    2837 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
    2838 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
    2839
    2840 goto TRANSIT;
    2841
    2844 reopt->reopttree->reoptnodes[0]->reopttype = (unsigned int)reopttype;
    2845 reopt->reopttree->reoptnodes[0]->dualreds = TRUE;
    2846 reopt->reopttree->reoptnodes[0]->nvars = 0;
    2847
    2848 if( reopttype == SCIP_REOPTTYPE_INFSUBTREE )
    2849 {
    2850 /* delete the whole subtree induced be the current node */
    2851 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, 0, FALSE, FALSE) );
    2852 }
    2853
    2854 /* update the lowerbound */
    2855 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
    2856 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
    2857
    2858 SCIPsetDebugMsg(set, "update node %d at ID %d:\n", 1, 0);
    2859 SCIPsetDebugMsg(set, " -> nvars: 0, ncons: 0, parentID: -, reopttype: %d, lowerbound: %g\n", reopttype,
    2860 reopt->reopttree->reoptnodes[id]->lowerbound);
    2861
    2862 goto PSEUDO;
    2863
    2865 ++reopt->reopttree->ntotalfeasnodes;
    2866 ++reopt->reopttree->nfeasnodes;
    2867 reopt->reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_FEASIBLE;
    2868 reopt->reopttree->reoptnodes[0]->dualreds = FALSE;
    2869
    2870 if( reopt->reopttree->reoptnodes[0]->childids != NULL && reopt->reopttree->reoptnodes[0]->nchilds > 0 )
    2871 {
    2872 /* delete the subtree */
    2873 if( set->reopt_reducetofrontier )
    2874 {
    2875 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, 0, FALSE, FALSE) );
    2876 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    2877 }
    2878 /* dive through all children and change the reopttype to LEAF */
    2879 else
    2880 {
    2882 }
    2883 }
    2884 else
    2885 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    2886
    2887 /* update the lowerbound */
    2888 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
    2889 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
    2890
    2891 SCIPsetDebugMsg(set, "update node %d at ID %d:\n", 1, 0);
    2892 SCIPsetDebugMsg(set, " -> nvars: 0, ncons: 0, parentID: -, reopttype: %d, lowerbound: %g\n", reopttype,
    2893 reopt->reopttree->reoptnodes[id]->lowerbound);
    2894
    2895 break;
    2896
    2898 ++reopt->reopttree->nprunednodes;
    2899 ++reopt->reopttree->ntotalprunednodes;
    2900 reopt->reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_PRUNED;
    2901 reopt->reopttree->reoptnodes[0]->dualreds = FALSE;
    2902
    2903 if( reopt->reopttree->reoptnodes[0]->childids != NULL && reopt->reopttree->reoptnodes[0]->nchilds > 0 )
    2904 {
    2905 /* delete the subtree */
    2906 if( set->reopt_reducetofrontier )
    2907 {
    2908 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, 0, FALSE, FALSE) );
    2909 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    2910 }
    2911 /* dive through all children and change the reopttype to LEAF */
    2912 else
    2913 {
    2915 }
    2916 }
    2917 else
    2918 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    2919
    2920 /* update the lowerbound if it was not set */
    2921 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
    2922 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
    2923
    2924 SCIPsetDebugMsg(set, "update node %d at ID %d:\n", 1, 0);
    2925 SCIPsetDebugMsg(set, " -> nvars: 0, ncons: 0, parentID: -, reopttype: %d, lowerbound:%g \n", reopttype,
    2926 reopt->reopttree->reoptnodes[id]->lowerbound);
    2927
    2928 break;
    2929
    2930 default:
    2931 assert(reopttype == SCIP_REOPTTYPE_TRANSIT
    2932 || reopttype == SCIP_REOPTTYPE_INFSUBTREE
    2933 || reopttype == SCIP_REOPTTYPE_STRBRANCHED
    2934 || reopttype == SCIP_REOPTTYPE_PRUNED
    2935 || reopttype == SCIP_REOPTTYPE_FEASIBLE);
    2936 break;
    2937 }/*lint !e788*/
    2938
    2939 /* reset the information of dual bound changes */
    2940 reopt->currentnode = -1;
    2941 if( reopt->dualreds != NULL )
    2942 reopt->dualreds->nvars = 0;
    2943
    2944 /* stop clock */
    2945 SCIPclockStop(reopt->savingtime, set);
    2946
    2947 return SCIP_OKAY;
    2948 }
    2949 else
    2950 {
    2951 int nbndchgdiff;
    2952 SCIP_Bool transintoorig;
    2953
    2954 SCIPsetDebugMsg(set, "try to add node #%lld to the reopttree\n", SCIPnodeGetNumber(node));
    2955 SCIPsetDebugMsg(set, " -> reopttype = %d\n", reopttype);
    2956
    2957 /* check if we really want to save this node:
    2958 * 1. save the node if reopttype is at least SCIP_REOPTTYPE_INFSUBTREE
    2959 * 2. save the node if the number of bound changes of this node
    2960 * and the last saved node is at least a given number n
    2961 */
    2962
    2963 /* get the ID of the last saved node or 0 for the root */
    2964 SCIP_CALL( getLastSavedNode(reopt, set, node, &parent, &parentid, &nbndchgdiff) );
    2965
    2966 if( (reopttype < SCIP_REOPTTYPE_INFSUBTREE && nbndchgdiff <= set->reopt_maxdiffofnodes)
    2967 || reopt->reopttree->reoptnodes[parentid]->reopttype >= SCIP_REOPTTYPE_LEAF ) /*lint !e641*/
    2968 {
    2969 SCIPsetDebugMsg(set, " -> skip saving\n");
    2970
    2971 /* stop clock */
    2972 SCIPclockStop(reopt->savingtime, set);
    2973
    2974 return SCIP_OKAY;
    2975 }
    2976
    2977 /* check if there are free slots to store the node */
    2978 SCIP_CALL( reopttreeCheckMemory(reopt->reopttree, set, blkmem) );
    2979
    2981
    2982 SCIPsetDebugMsg(set, " -> save at ID %u\n", id);
    2983
    2984 assert(reopt->reopttree->reoptnodes[id] == NULL
    2985 || (reopt->reopttree->reoptnodes[id]->nvars == 0 && reopt->reopttree->reoptnodes[id]->nconss == 0));
    2986 assert(id >= 1 && id < reopt->reopttree->reoptnodessize);
    2987 assert(!isrootnode);
    2988
    2989 /* get memory for nodedata */
    2990 assert(reopt->reopttree->reoptnodes[id] == NULL || reopt->reopttree->reoptnodes[id]->nvars == 0);
    2991 SCIP_CALL( createReoptnode(reopt->reopttree, set, blkmem, id) );
    2992 reopt->reopttree->reoptnodes[id]->parentID = parentid;
    2993
    2994 assert(parent != NULL );
    2995 assert((SCIPnodeGetDepth(parent) == 0 && parentid == 0) || (SCIPnodeGetDepth(parent) >= 1 && parentid > 0));
    2996 assert(id >= 1);
    2997
    2998 /* create the array of "child nodes" if they not exist */
    2999 if( reopt->reopttree->reoptnodes[parentid]->childids == NULL
    3000 || reopt->reopttree->reoptnodes[parentid]->allocchildmem == 0 )
    3001 {
    3002 SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[parentid], set, blkmem, 0, 2, 0) );
    3003 }
    3004
    3005 /* add the new node as a "child node" of the last saved reoptminization node */
    3006 SCIP_CALL( reoptAddChild(reopt->reopttree, set, blkmem, parentid, id) );
    3007
    3008 /* save branching path */
    3009 SCIP_CALL( saveAncestorBranchings(reopt->reopttree, set, blkmem, node, parent, id, parentid) );
    3010
    3011 /* save bound changes after some dual reduction */
    3012 if( saveafterdual )
    3013 {
    3014 assert(reopttype == SCIP_REOPTTYPE_STRBRANCHED);
    3015 SCIP_CALL( saveAfterDualBranchings(reopt, set, blkmem, node, id, &transintoorig) );
    3016 }
    3017 else
    3018 {
    3019 SCIPsetDebugMsg(set, " -> skip saving bound changes after dual reductions.\n");
    3020 }
    3021
    3022 /* transform all bounds of branched variables and ensure that they are original. */
    3023 SCIP_CALL( transformIntoOrig(reopt, id) );
    3024
    3025 /* save pseudo-constraints (if one exists) */
    3026 if (SCIPnodeGetNAddedConss(node) >= 1)
    3027 {
    3028 assert(reopt->reopttree->reoptnodes[id]->nconss == 0);
    3029
    3030 SCIP_CALL( saveLocalConssData(reopt->reopttree, set, blkmem, node, id) );
    3031 }
    3032
    3033 /* store separated cuts
    3034 * note: we need to call this after saveLocalConssData to be sure that the local conss array is ordered, first all
    3035 * local constraints, then cuts
    3036 */
    3037 if( set->reopt_usecuts )
    3038 {
    3039 SCIP_CALL( storeCuts(reopt, set, blkmem, lp, id) );
    3040 }
    3041
    3042 /* update the lowerbound if it was not set */
    3043 if( !SCIPsetIsInfinity(set, REALABS(lowerbound)) )
    3044 reopt->reopttree->reoptnodes[id]->lowerbound = lowerbound;
    3045
    3046 /* set ID */
    3047 SCIPnodeSetReoptID(node, id);
    3048
    3049 /* set the REOPTTYPE */
    3050 SCIPnodeSetReopttype(node, reopttype);
    3051
    3052 SCIPsetDebugMsg(set, "save node #%lld successful\n", SCIPnodeGetNumber(node));
    3053 SCIPsetDebugMsg(set, " -> nvars: %d, ncons: %d, parentID: %u, reopttype: %d, lowerbound: %g\n",
    3054 reopt->reopttree->reoptnodes[id]->nvars + reopt->reopttree->reoptnodes[id]->nafterdualvars,
    3055 reopt->reopttree->reoptnodes[id]->nconss, reopt->reopttree->reoptnodes[id]->parentID,
    3056 reopttype, reopt->reopttree->reoptnodes[id]->lowerbound);
    3057#ifdef SCIP_MORE_DEBUG
    3058 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nvars; ++varnr )
    3059 {
    3060 SCIPsetDebugMsg(set, " <%s> %s %g\n", SCIPvarGetName(reopt->reopttree->reoptnodes[id]->vars[varnr]),
    3062 "=>" : "<=", reopt->reopttree->reoptnodes[id]->varbounds[varnr]);
    3063 }
    3064 for( int varnr = 0; varnr < reopt->reopttree->reoptnodes[id]->nafterdualvars; ++varnr )
    3065 {
    3066 SCIPsetDebugMsg(set, " <%s> %s %g (after dual red.)\n",
    3067 SCIPvarGetName(reopt->reopttree->reoptnodes[id]->afterdualvars[varnr]),
    3069 "=>" : "<=", reopt->reopttree->reoptnodes[id]->afterdualvarbounds[varnr]);
    3070 }
    3071#endif
    3072 } /*lint !e438*/
    3073
    3074 switch( reopttype )
    3075 {
    3079 TRANSIT:
    3080 if( !shrank )
    3081 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)reopttype;
    3082 else
    3083 {
    3084 SCIPnodeSetReoptID(node, 0);
    3086 }
    3087 break;
    3088
    3091 PSEUDO:
    3092 assert(reopt->currentnode == SCIPnodeGetNumber(node));
    3093
    3094 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)reopttype;
    3095 reopt->reopttree->reoptnodes[id]->dualreds = TRUE;
    3096
    3097 /* get all the dual information and decide if the constraint need
    3098 * to be added next or after next */
    3099 SCIP_CALL( collectDualInformation(reopt, set, blkmem, node, id, reopttype) );
    3100
    3101 break;
    3102
    3104 FEASIBLE:
    3105 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_FEASIBLE;
    3106 reopt->reopttree->reoptnodes[id]->dualreds = FALSE;
    3107 ++reopt->reopttree->nfeasnodes;
    3108 ++reopt->reopttree->ntotalfeasnodes;
    3109
    3110 break;
    3111
    3113 PRUNED:
    3114 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_PRUNED;
    3115 reopt->reopttree->reoptnodes[id]->dualreds = FALSE;
    3116 ++reopt->reopttree->nprunednodes;
    3117 ++reopt->reopttree->ntotalprunednodes;
    3118
    3119 break;
    3120
    3121 default:
    3122 assert(reopttype == SCIP_REOPTTYPE_TRANSIT
    3123 || reopttype == SCIP_REOPTTYPE_LOGICORNODE
    3124 || reopttype == SCIP_REOPTTYPE_LEAF
    3125 || reopttype == SCIP_REOPTTYPE_INFSUBTREE
    3126 || reopttype == SCIP_REOPTTYPE_STRBRANCHED
    3127 || reopttype == SCIP_REOPTTYPE_FEASIBLE
    3128 || reopttype == SCIP_REOPTTYPE_PRUNED);
    3129 break;
    3130 } /*lint !e788*/
    3131
    3132 /* stop clock */
    3133 SCIPclockStop(reopt->savingtime, set);
    3134
    3135 /* reset the information of dual bound changes */
    3136 reopt->currentnode = -1;
    3137 if( reopt->dualreds != NULL )
    3138 reopt->dualreds->nvars = 0;
    3139
    3140 return SCIP_OKAY;
    3141}
    3142
    3143/** delete the stored information about dual bound changes of the last focused node */
    3144static
    3146 SCIP_REOPT* reopt /**< reoptimization data structure */
    3147 )
    3148{
    3149 assert(reopt != NULL);
    3150
    3151 if( reopt->dualreds != NULL && reopt->dualreds->nvars > 0 )
    3152 {
    3153 SCIPdebugMessage("delete %d dual variable information about node %lld\n", reopt->dualreds->nvars,
    3154 reopt->currentnode);
    3155 reopt->dualreds->nvars = 0;
    3156 reopt->currentnode = -1;
    3157 }
    3158}
    3159
    3160/** delete the stored constraints that dual information at the given reoptimization node */
    3161static
    3163 SCIP_REOPTNODE* reoptnode, /**< reoptimization node */
    3164 BMS_BLKMEM* blkmem /**< block memory */
    3165 )
    3166{
    3167 assert(reoptnode != NULL);
    3168 assert(blkmem != NULL);
    3169
    3170 if( reoptnode->dualredscur != NULL )
    3171 {
    3172 SCIP_REOPTCONSDATA* reoptconsdata;
    3173
    3174 SCIPdebugMessage("reset dual information (current run)\n");
    3175
    3176 reoptconsdata = reoptnode->dualredscur;
    3177
    3178 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, reoptconsdata->varssize);
    3179 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vals, reoptconsdata->varssize);
    3180 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vars, reoptconsdata->varssize);
    3181 BMSfreeBlockMemory(blkmem, &reoptnode->dualredscur);
    3182 reoptnode->dualredscur = NULL;
    3183 }
    3184
    3185 if( reoptnode->dualredsnex != NULL )
    3186 {
    3187 SCIP_REOPTCONSDATA* reoptconsdata;
    3188
    3189 SCIPdebugMessage("reset dual information (next run)\n");
    3190
    3191 reoptconsdata = reoptnode->dualredsnex;
    3192
    3193 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, reoptconsdata->varssize);
    3194 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vals, reoptconsdata->varssize);
    3195 BMSfreeBlockMemoryArray(blkmem, &reoptconsdata->vars, reoptconsdata->varssize);
    3196 BMSfreeBlockMemory(blkmem, &reoptnode->dualredsnex);
    3197 reoptnode->dualredsnex = NULL;
    3198 }
    3199
    3200 reoptnode->dualreds = FALSE;
    3201
    3202 return SCIP_OKAY;
    3203}
    3204
    3205
    3206/** transform given set of variables, bounds and boundtypes into a global cut.
    3207 *
    3208 * @note: boundtypes can be NULL if all variables are binary or a MIP solution should be separated.
    3209 * @note: continuous variables will be skiped if boundtypes is NULL
    3210 */
    3211static
    3213 SCIP_REOPT* reopt, /**< reoptimization data structure */
    3214 BMS_BLKMEM* blkmem, /**< block memory */
    3215 SCIP_SET* set, /**< global SCIP settings */
    3216 SCIP_VAR** vars, /**< variables of the cut */
    3217 SCIP_Real* vals, /**< values of the cut */
    3218 SCIP_BOUNDTYPE* boundtypes, /**< bounds of the cut */
    3219 int nvars, /**< number of variables in the cut */
    3220 int nbinvars, /**< number of binary variables */
    3221 int nintvars /**< number of integer variables */
    3222 )
    3223{
    3224 SCIP_REOPTCONSDATA* reoptconsdata;
    3225 int nglbconss;
    3226 int nvarsadded;
    3227
    3228 assert(reopt != NULL);
    3229 assert(blkmem != NULL);
    3230 assert(set != NULL);
    3231 assert(vars != NULL);
    3232 assert(vals != NULL);
    3233 assert(nbinvars + nintvars == nvars);
    3234
    3235 nvarsadded = 0;
    3236
    3237 /* check whether we have enough memory allocated */
    3238 SCIP_CALL( checkMemGlbCons(reopt, set, blkmem, 10) );
    3239 nglbconss = reopt->nglbconss;
    3240 reoptconsdata = NULL;
    3241
    3242 if( reopt->glbconss[nglbconss] == NULL )
    3243 {
    3244 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reopt->glbconss[nglbconss]) ); /*lint !e866*/
    3245 reoptconsdata = reopt->glbconss[nglbconss];
    3246
    3247 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->vars, (int)(nbinvars+2*nintvars)) );
    3248 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->vals, (int)(nbinvars+2*nintvars)) );
    3249 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, (int)(nbinvars+2*nintvars)) );
    3250 reoptconsdata->varssize = (int)(nbinvars+2*nintvars);
    3251 reoptconsdata->nvars = 0;
    3252 }
    3253 else
    3254 {
    3255 assert(reopt->glbconss[nglbconss]->nvars == 0);
    3256 assert(reopt->glbconss[nglbconss]->varssize > 0);
    3257
    3258 reoptconsdata = reopt->glbconss[nglbconss];
    3259
    3260 if( reoptconsdata->varssize < nbinvars+2*nintvars )
    3261 {
    3262 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptconsdata->vars, reoptconsdata->varssize, \
    3263 (int)(nbinvars+2*nintvars)) );
    3264 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptconsdata->vals, reoptconsdata->varssize, \
    3265 (int)(nbinvars+2*nintvars)) );
    3266 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reoptconsdata->boundtypes, reoptconsdata->varssize, \
    3267 (int)(nbinvars+2*nintvars)) );
    3268 reoptconsdata->varssize = (int)(nbinvars+2*nintvars);
    3269 }
    3270 }
    3271 assert(reoptconsdata != NULL);
    3272
    3273 reoptconsdata->lhs = 1.0;
    3274 reoptconsdata->rhs = SCIPsetInfinity(set);
    3275 reoptconsdata->linear = FALSE;
    3276 reoptconsdata->constype = REOPT_CONSTYPE_CUT;
    3277
    3278 for( int v = 0; v < nvars; ++v )
    3279 {
    3280 assert(nvarsadded < reoptconsdata->varssize);
    3281 assert(vars[v] != NULL);
    3282 assert(SCIPvarIsOriginal(vars[v]));
    3283 assert(!SCIPvarIsIntegral(vars[v]) || SCIPsetIsIntegral(set, vals[v]));
    3284
    3285 /* if no boundtypes are given we skip continuous variables, otherwise we would add trivial clauses:
    3286 * a) x <= ub
    3287 * b) lb <= x
    3288 * c) (x <= val) or (x >= val)
    3289 */
    3290 if( boundtypes == NULL && !SCIPvarIsIntegral(vars[v]) )
    3291 continue;
    3292
    3293 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(vars[v]) )
    3294 {
    3295 reoptconsdata->vars[nvarsadded] = vars[v];
    3296
    3297 if( SCIPsetIsEQ(set, vals[v], 1.0) )
    3298 {
    3299 assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
    3300 reoptconsdata->vals[nvarsadded] = 0.0;
    3301 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
    3302 }
    3303 else
    3304 {
    3305 assert(SCIPsetIsEQ(set, vals[v], 0.0));
    3306 assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
    3307 reoptconsdata->vals[nvarsadded] = 1.0;
    3308 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
    3309 }
    3310 ++nvarsadded;
    3311 }
    3312 else if( !SCIPvarIsIntegral(vars[v]) )
    3313 {
    3314 assert(boundtypes != NULL);
    3315
    3316 reoptconsdata->vals[nvarsadded] = vals[v];
    3317 reoptconsdata->boundtypes[nvarsadded] = (boundtypes[v] == SCIP_BOUNDTYPE_LOWER ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER);
    3318 ++nvarsadded;
    3319 }
    3320 else
    3321 {
    3322 SCIP_Real roundedval;
    3323 SCIP_Real ubglb;
    3324 SCIP_Real lbglb;
    3325
    3326 assert(SCIPvarGetType(vars[v]) == SCIP_VARTYPE_INTEGER || SCIPvarIsImpliedIntegral(vars[v]));
    3327
    3328 reoptconsdata->vars[nvarsadded] = vars[v];
    3329
    3330 ubglb = SCIPvarGetUbGlobal(vars[v]);
    3331 lbglb = SCIPvarGetLbGlobal(vars[v]);
    3332
    3333 /* case 1 : x == val == ub -> x <= ub-1
    3334 * case 2 : x == val == lb -> x >= lb+1
    3335 * case 3.1: x <= val < ub -> x >= y+1
    3336 * case 3.2: x >= val > lb -> x <= y-1
    3337 * case 4 : lb < x == val < ub -> (x <= y-1) or (x >= y+1)
    3338 */
    3339
    3340 /* case 1 */
    3341 if( SCIPsetIsEQ(set, vals[v], ubglb) )
    3342 {
    3343 assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
    3344 reoptconsdata->vals[nvarsadded] = ubglb - 1.0;
    3345 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
    3346 ++nvarsadded;
    3347 }
    3348 /* case 2 */
    3349 else if( SCIPsetIsEQ(set, vals[v], lbglb) )
    3350 {
    3351 assert(boundtypes == NULL || boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
    3352 reoptconsdata->vals[nvarsadded] = lbglb + 1.0;
    3353 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
    3354 ++nvarsadded;
    3355 }
    3356 else if( boundtypes != NULL )
    3357 {
    3358 /* we round the solution value to get a 'clean' bound */
    3359 assert(SCIPsetIsIntegral(set, vals[v]));
    3360 roundedval = SCIPsetRound(set, vals[v]);
    3361
    3362 /* case 3.1 */
    3363 if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER )
    3364 {
    3365 reoptconsdata->vals[nvarsadded] = roundedval + 1.0;
    3366 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
    3367 ++nvarsadded;
    3368 }
    3369 /* case 3.2 */
    3370 else
    3371 {
    3372 assert(boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
    3373 reoptconsdata->vals[nvarsadded] = roundedval - 1.0;
    3374 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
    3375 ++nvarsadded;
    3376 }
    3377 }
    3378 /* case 4: in this case we have to add two clauses: (x <= val-1) and (x >= val+1) */
    3379 else
    3380 {
    3381 /* we round the solution value to get a 'clean' bound */
    3382 assert(SCIPsetIsIntegral(set, vals[v]));
    3383 roundedval = SCIPsetRound(set, vals[v]);
    3384
    3385 /* first clause: x <= val-1 */
    3386 reoptconsdata->vals[nvarsadded] = roundedval - 1.0;
    3387 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_UPPER;
    3388 ++nvarsadded;
    3389
    3390 /* second clause: x >= val+1 */
    3391 reoptconsdata->vars[nvarsadded] = vars[v];
    3392 reoptconsdata->vals[nvarsadded] = roundedval + 1.0;
    3393 reoptconsdata->boundtypes[nvarsadded] = SCIP_BOUNDTYPE_LOWER;
    3394 ++nvarsadded;
    3395 }
    3396 }
    3397 }
    3398 assert(nvars <= nvarsadded);
    3399 assert(nvarsadded == nbinvars + 2 * nintvars);
    3400
    3401 reoptconsdata->nvars = nvarsadded;
    3402 ++reopt->nglbconss;
    3403
    3404 return SCIP_OKAY;
    3405}
    3406
    3407/** generate a global constraint to separate an infeasible subtree */
    3408static
    3410 SCIP_REOPT* reopt, /**< reoptimization data structure */
    3411 SCIP_SET* set, /**< global SCIP settings */
    3412 BMS_BLKMEM* blkmem, /**< block memory */
    3413 SCIP_NODE* node, /**< node of the search tree */
    3414 REOPT_CONSTYPE consttype /**< reopttype of the constraint */
    3415 )
    3416{
    3417 assert(reopt != NULL);
    3418 assert(node != NULL);
    3419
    3420 if( consttype == REOPT_CONSTYPE_INFSUBTREE )
    3421 {
    3422 SCIP_VAR** vars;
    3423 SCIP_Real* vals;
    3424 SCIP_BOUNDTYPE* boundtypes;
    3425 int allocmem;
    3426 int nbranchvars;
    3427 int nbinvars;
    3428 int nintvars;
    3429
    3430 /* allocate memory to store the infeasible path */
    3431 allocmem = SCIPnodeGetDepth(node);
    3432 SCIP_CALL( SCIPsetAllocBufferArray(set, &vars, allocmem) );
    3433 SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, allocmem) );
    3434 SCIP_CALL( SCIPsetAllocBufferArray(set, &boundtypes, allocmem) );
    3435
    3436 /* get the branching path */
    3437 SCIPnodeGetAncestorBranchings(node, vars, vals, boundtypes, &nbranchvars, allocmem);
    3438
    3439 if( allocmem < nbranchvars )
    3440 {
    3441 SCIP_CALL( SCIPsetReallocBufferArray(set, &vars, nbranchvars) );
    3442 SCIP_CALL( SCIPsetReallocBufferArray(set, &vals, nbranchvars) );
    3443 SCIP_CALL( SCIPsetReallocBufferArray(set, &boundtypes, nbranchvars) );
    3444 allocmem = nbranchvars;
    3445
    3446 SCIPnodeGetAncestorBranchings(node, vars, vals, boundtypes, &nbranchvars, allocmem);
    3447 }
    3448
    3449 /* we count the number of binary and (impl) integer variables */
    3450 nbinvars = 0;
    3451 nintvars = 0;
    3452 for( int v = 0; v < nbranchvars; ++v )
    3453 {
    3454 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(vars[v]) )
    3455 ++nbinvars;
    3457 ++nintvars;
    3458 }
    3459 assert(nbinvars + nintvars == nbranchvars);
    3460
    3461 SCIP_CALL( addGlobalCut(reopt, blkmem, set, vars, vals, boundtypes, nbranchvars, nbinvars, nintvars) );
    3462 assert(!reopt->glbconss[reopt->nglbconss - 1]->linear);
    3463
    3464 /* free buffer */
    3465 SCIPsetFreeBufferArray(set, &boundtypes);
    3468 }
    3469
    3470 return SCIP_OKAY;
    3471}
    3472
    3473
    3474/** move all id of child nodes from reoptimization node stored at @p id1 to the node stored at @p id2 */
    3475static
    3477 SCIP_REOPTTREE* reopttree, /**< reopttree */
    3478 SCIP_SET* set, /**< global SCIP settings */
    3479 BMS_BLKMEM* blkmem, /**< block memory */
    3480 unsigned int id1, /**< source id */
    3481 unsigned int id2 /**< target id */
    3482 )
    3483{
    3484 int nchilds_id1;
    3485 int nchilds_id2;
    3486
    3487 assert(reopttree != NULL);
    3488 assert(blkmem != NULL);
    3489 assert(id1 < reopttree->reoptnodessize);
    3490 assert(id2 < reopttree->reoptnodessize);
    3491 assert(reopttree->reoptnodes[id1] != NULL);
    3492 assert(reopttree->reoptnodes[id2] != NULL);
    3493
    3494 nchilds_id1 = reopttree->reoptnodes[id1]->nchilds;
    3495 nchilds_id2 = reopttree->reoptnodes[id2]->nchilds;
    3496
    3497 /* ensure that the array storing the child id's is large enough */
    3498 SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id2], set, blkmem, 0, nchilds_id1+nchilds_id2, 0) );
    3499 assert(reopttree->reoptnodes[id2]->allocchildmem >= nchilds_id1+nchilds_id2);
    3500
    3501 SCIPsetDebugMsg(set, "move %d IDs: %u -> %u\n", nchilds_id1, id1, id2);
    3502
    3503 /* move the ids */
    3504 for( int c = 0; c < nchilds_id1; ++c )
    3505 {
    3506#ifdef SCIP_DEBUG
    3507 {
    3508 /* check that no id is added twice */
    3509 for( int k = 0; k < nchilds_id2; ++k )
    3510 assert(reopttree->reoptnodes[id2]->childids[k] != reopttree->reoptnodes[id1]->childids[c]);
    3511 }
    3512#endif
    3513
    3514 reopttree->reoptnodes[id2]->childids[nchilds_id2+c] = reopttree->reoptnodes[id1]->childids[c];
    3515 }
    3516
    3517 /* update the number of childs */
    3518 reopttree->reoptnodes[id1]->nchilds = 0;
    3519 reopttree->reoptnodes[id2]->nchilds += nchilds_id1;
    3520
    3521 return SCIP_OKAY;
    3522}
    3523
    3524/** change all bound changes along the root path */
    3525static
    3527 SCIP_REOPT* reopt, /**< reoptimization data structure */
    3528 SCIP_SET* set, /**< global SCIP settings */
    3529 SCIP_STAT* stat, /**< dynamic problem statistics */
    3530 SCIP_PROB* transprob, /**< transformed problem */
    3531 SCIP_PROB* origprob, /**< original problem */
    3532 SCIP_TREE* tree, /**< search tree */
    3533 SCIP_LP* lp, /**< current LP */
    3534 SCIP_BRANCHCAND* branchcand, /**< branching candidates */
    3535 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    3536 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    3537 SCIP_CLIQUETABLE* cliquetable, /**< clique table */
    3538 BMS_BLKMEM* blkmem, /**< block memory */
    3539 SCIP_NODE* node, /**< node of the branch and bound tree */
    3540 unsigned int id, /**< id of stored node */
    3541 SCIP_Bool afterdualbranching /**< convert all bound changes made directly after the first bound
    3542 * changes based on dual information into normal branchings */
    3543 )
    3544{
    3545 SCIP_REOPTTREE* reopttree;
    3546 SCIP_REOPTNODE* reoptnode;
    3547
    3548 assert(reopt != NULL);
    3549 assert(set != NULL);
    3550 assert(stat != NULL);
    3551 assert(transprob != NULL);
    3552 assert(tree != NULL);
    3553 assert(lp != NULL);
    3554 assert(branchcand != NULL);
    3555 assert(eventqueue != NULL);
    3556 assert(cliquetable != NULL);
    3557 assert(node != NULL);
    3558 assert(blkmem != NULL);
    3559
    3560 reopttree = reopt->reopttree;
    3561 assert(reopttree != NULL);
    3562 assert(id < reopttree->reoptnodessize);
    3563
    3564 reoptnode = reopttree->reoptnodes[id];
    3565 assert(reoptnode != NULL);
    3566
    3567 /* copy memory to ensure that only original variables are saved */
    3568 if( reoptnode->nvars == 0 && reoptnode->nafterdualvars == 0)
    3569 return SCIP_OKAY;
    3570
    3571 /* change the bounds along the branching path */
    3572 for( int v = 0; v < reoptnode->nvars; ++v )
    3573 {
    3574 SCIP_VAR* var;
    3575 SCIP_Real val;
    3576 SCIP_BOUNDTYPE boundtype;
    3577 SCIP_Real oldlb;
    3578 SCIP_Real oldub;
    3579 SCIP_Real newbound;
    3580
    3581 var = reoptnode->vars[v];
    3582 val = reoptnode->varbounds[v];
    3583 boundtype = reoptnode->varboundtypes[v];
    3584
    3585 assert(SCIPvarIsOriginal(var));
    3586 SCIP_CALL( SCIPvarGetProbvarBound(&var, &val, &boundtype) );
    3587 assert(SCIPvarIsTransformed(var));
    3589
    3590 oldlb = SCIPvarGetLbLocal(var);
    3591 oldub = SCIPvarGetUbLocal(var);
    3592 newbound = val;
    3593
    3594 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
    3595
    3596 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, oldlb) && SCIPsetIsFeasLE(set, newbound, oldub) )
    3597 {
    3598 SCIPvarAdjustLb(var, set, &newbound);
    3599
    3600 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    3601 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
    3602 }
    3603 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, oldub) && SCIPsetIsFeasGE(set, newbound, oldlb) )
    3604 {
    3605 SCIPvarAdjustUb(var, set, &newbound);
    3606
    3607 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    3608 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
    3609 }
    3610#ifdef SCIP_MORE_DEBUG
    3611 SCIPsetDebugMsg(set, " (path) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=", newbound);
    3612#endif
    3613 }
    3614
    3615 if( afterdualbranching && reoptnode->nafterdualvars > 0 )
    3616 {
    3617 /* check the memory to convert this bound changes into 'normal' */
    3618 SCIP_CALL( reoptnodeCheckMemory(reopttree->reoptnodes[id], set, blkmem,
    3619 reoptnode->nvars + reoptnode->nafterdualvars, 0, 0) );
    3620
    3621 /* change the bounds */
    3622 for( int v = 0; v < reoptnode->nafterdualvars; ++v )
    3623 {
    3624 SCIP_VAR* var;
    3625 SCIP_Real val;
    3626 SCIP_BOUNDTYPE boundtype;
    3627 SCIP_Bool bndchgd;
    3628 SCIP_Real oldlb;
    3629 SCIP_Real oldub;
    3630 SCIP_Real newbound;
    3631
    3632 var = reoptnode->afterdualvars[v];
    3633 val = reoptnode->afterdualvarbounds[v];
    3634 boundtype = reoptnode->afterdualvarboundtypes[v];
    3635
    3636 assert(SCIPvarIsOriginal(var));
    3637 SCIP_CALL( SCIPvarGetProbvarBound(&var, &val, &boundtype) );
    3638 assert(SCIPvarIsTransformed(var));
    3640
    3641 bndchgd = FALSE;
    3642
    3643 oldlb = SCIPvarGetLbLocal(var);
    3644 oldub = SCIPvarGetUbLocal(var);
    3645 newbound = val;
    3646
    3647 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, oldlb) && SCIPsetIsFeasLE(set, newbound, oldub) )
    3648 {
    3649 SCIPvarAdjustLb(var, set, &newbound);
    3650 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    3651 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
    3652
    3653 bndchgd = TRUE;
    3654 }
    3655 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, oldub) && SCIPsetIsFeasGE(set, newbound, oldlb) )
    3656 {
    3657 SCIPvarAdjustUb(var, set, &newbound);
    3658 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    3659 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
    3660
    3661 bndchgd = TRUE;
    3662 }
    3663
    3664 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
    3665
    3666#ifdef SCIP_MORE_DEBUG
    3667 SCIPsetDebugMsg(set, " (prop) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=", newbound);
    3668#endif
    3669 if( bndchgd )
    3670 {
    3671 int nvars;
    3672
    3673 nvars = reoptnode->nvars;
    3674 reoptnode->vars[nvars] = reoptnode->afterdualvars[v];
    3675 reoptnode->varbounds[nvars] = reoptnode->afterdualvarbounds[v];
    3676 reoptnode->varboundtypes[nvars] = reoptnode->afterdualvarboundtypes[v];
    3677 ++reoptnode->nvars;
    3678 }
    3679 }
    3680
    3681 /* free the afterdualvars, -bounds, and -boundtypes */
    3682 BMSfreeBlockMemoryArray(blkmem, &reoptnode->afterdualvarboundtypes, reoptnode->afterdualvarssize);
    3683 reoptnode->afterdualvarboundtypes = NULL;
    3684
    3685 BMSfreeBlockMemoryArray(blkmem, &reoptnode->afterdualvarbounds, reoptnode->afterdualvarssize);
    3686 reoptnode->afterdualvarbounds = NULL;
    3687
    3688 BMSfreeBlockMemoryArray(blkmem, &reoptnode->afterdualvars, reoptnode->afterdualvarssize);
    3689 reoptnode->afterdualvars = NULL;
    3690
    3691 reoptnode->nafterdualvars = 0;
    3692 reoptnode->afterdualvarssize = 0;
    3693 }
    3694
    3695 return SCIP_OKAY;
    3696}
    3697
    3698
    3699/** add a constraint to ensure that at least one variable bound gets different */
    3700static
    3702 SCIP_REOPT* reopt, /**< reoptimization data structure */
    3703 SCIP* scip, /**< SCIP data structure */
    3704 SCIP_SET* set, /**< global SCIP settings */
    3705 SCIP_STAT* stat, /**< dynamic problem statistics */
    3706 BMS_BLKMEM* blkmem, /**< block memory */
    3707 SCIP_PROB* transprob, /**< transformed problem */
    3708 SCIP_PROB* origprob, /**< original problem */
    3709 SCIP_TREE* tree, /**< search tree */
    3710 SCIP_LP* lp, /**< current LP */
    3711 SCIP_BRANCHCAND* branchcand, /**< branching candidates */
    3712 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    3713 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    3714 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    3715 SCIP_NODE* node, /**< node corresponding to the pruned part */
    3716 unsigned int id /**< id of stored node */
    3717 )
    3718{
    3719 SCIP_CONS* cons;
    3720 char name[SCIP_MAXSTRLEN];
    3721
    3722 assert(reopt != NULL);
    3723 assert(reopt->reopttree != NULL);
    3724 assert(id < reopt->reopttree->reoptnodessize);
    3725 assert(reopt->reopttree->reoptnodes[id] != NULL);
    3726 assert(reopt->reopttree->reoptnodes[id]->dualreds);
    3727 assert(reopt->reopttree->reoptnodes[id]->dualredscur != NULL);
    3728 assert(scip != NULL);
    3729 assert(set != NULL);
    3730 assert(stat != NULL);
    3731 assert(blkmem != NULL);
    3732 assert(transprob != NULL);
    3733 assert(origprob != NULL);
    3734 assert(tree != NULL);
    3735 assert(lp != NULL);
    3736 assert(branchcand != NULL);
    3737 assert(eventqueue != NULL);
    3738 assert(node != NULL);
    3739
    3740 assert(reopt->reopttree->reoptnodes[id]->dualredscur->constype == REOPT_CONSTYPE_DUALREDS
    3741 || reopt->reopttree->reoptnodes[id]->dualredscur->constype == REOPT_CONSTYPE_INFSUBTREE);
    3742
    3743#ifndef NDEBUG
    3744 if( reopt->reopttree->reoptnodes[id]->dualredscur->constype == REOPT_CONSTYPE_DUALREDS )
    3745 SCIPsetDebugMsg(set, " create a split-node #%lld\n", SCIPnodeGetNumber(node));
    3746 else
    3747 SCIPsetDebugMsg(set, " separate an infeasible subtree\n");
    3748#endif
    3749
    3750 /* if the constraint consists of exactly one variable it can be interpreted
    3751 * as a normal branching step, i.e., we can fix the variable to the negated bound */
    3752 if( reopt->reopttree->reoptnodes[id]->dualredscur->nvars == 1 )
    3753 {
    3754 SCIP_REOPTCONSDATA* reoptconsdata;
    3755 SCIP_VAR* var;
    3756 SCIP_BOUNDTYPE boundtype;
    3757 SCIP_Real oldlb;
    3758 SCIP_Real oldub;
    3759 SCIP_Real newbound;
    3760
    3761 reoptconsdata = reopt->reopttree->reoptnodes[id]->dualredscur;
    3762 assert(!reoptconsdata->linear);
    3763 assert(reoptconsdata->vars != NULL);
    3764 assert(reoptconsdata->vals != NULL);
    3765 assert(reoptconsdata->boundtypes != NULL);
    3766
    3767 var = reoptconsdata->vars[0];
    3768 newbound = reoptconsdata->vals[0];
    3769 boundtype = reoptconsdata->boundtypes[0];
    3770
    3771 assert(SCIPvarIsOriginal(var));
    3772 SCIP_CALL( SCIPvarGetProbvarBound(&var, &newbound, &boundtype) );
    3773 assert(SCIPvarIsTransformed(var));
    3774
    3775 oldlb = SCIPvarGetLbLocal(var);
    3776 oldub = SCIPvarGetUbLocal(var);
    3777
    3778 if( boundtype == SCIP_BOUNDTYPE_LOWER )
    3779 {
    3780 newbound = reoptconsdata->vals[0] - 1.0;
    3781 /* if newbound > local upper bound, the variable cannot take the old value and we exit */
    3782 if( SCIPisGT(scip, newbound, oldub) )
    3783 return SCIP_OKAY;
    3784 assert(SCIPisLE(scip, newbound, oldub));
    3785 }
    3786 else
    3787 {
    3788 newbound = reoptconsdata->vals[0] + 1.0;
    3789 /* if newbound < local lower bound, the variable cannot take the old value and we exit */
    3790 if( SCIPisLT(scip, newbound, oldlb) )
    3791 return SCIP_OKAY;
    3792 assert(SCIPisGE(scip, newbound, oldlb));
    3793 }
    3794 boundtype = (SCIP_BOUNDTYPE) (1 - (int)boundtype);
    3795 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
    3796
    3797 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, newbound, oldlb) && SCIPsetIsFeasLE(set, newbound, oldub) )
    3798 {
    3799 SCIPvarAdjustLb(var, set, &newbound);
    3800 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    3801 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
    3802 }
    3803 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, newbound, oldub) && SCIPsetIsFeasGE(set, newbound, oldlb) )
    3804 {
    3805 SCIPvarAdjustUb(var, set, &newbound);
    3806 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    3807 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
    3808 }
    3809
    3810 SCIPsetDebugMsg(set, " -> constraint consists of only one variable: <%s> %s %g\n", SCIPvarGetName(var),
    3811 boundtype == SCIP_BOUNDTYPE_LOWER ? "=>" : "<=", newbound);
    3812 }
    3813 else
    3814 {
    3815 SCIP_REOPTCONSDATA* reoptconsdata;
    3816 SCIP_VAR** consvars;
    3817 SCIP_Real consval;
    3818 SCIP_BOUNDTYPE consboundtype;
    3819 int nbinvars = 0;
    3820#ifndef NDEBUG
    3821 int nintvars = 0;
    3822 int ncontvars = 0;
    3823#endif
    3824
    3825 reoptconsdata = reopt->reopttree->reoptnodes[id]->dualredscur;
    3826 assert(!reoptconsdata->linear);
    3827 assert(reoptconsdata->vars != NULL);
    3828 assert(reoptconsdata->vals != NULL);
    3829 assert(reoptconsdata->boundtypes != NULL);
    3830
    3831 /* allocate buffer */
    3832 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, reoptconsdata->nvars) );
    3833
    3834 /* count number of binary, integer, and continuous variables */
    3835 for( int v = 0; v < reoptconsdata->nvars; ++v )
    3836 {
    3837 if( SCIPvarIsIntegral(reoptconsdata->vars[v]) )
    3838 {
    3839 if( SCIPisEQ(scip, SCIPvarGetLbLocal(reoptconsdata->vars[v]), 0.0)
    3840 && SCIPisEQ(scip, SCIPvarGetUbLocal(reoptconsdata->vars[v]), 1.0) )
    3841 ++nbinvars;
    3842#ifndef NDEBUG
    3843 else
    3844 ++nintvars;
    3845#endif
    3846 }
    3847#ifndef NDEBUG
    3848 else
    3849 ++ncontvars;
    3850#endif
    3851 }
    3852
    3853 if( reoptconsdata->constype == REOPT_CONSTYPE_INFSUBTREE )
    3854 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_inf");
    3855 else
    3856 {
    3857 assert(reoptconsdata->constype == REOPT_CONSTYPE_DUALREDS);
    3858 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_dual");
    3859 }
    3860
    3861 /* case 1: all variables are binary, we use a logic-or constraint. */
    3862 if( reoptconsdata->nvars == nbinvars )
    3863 {
    3864 for( int v = 0; v < reoptconsdata->nvars; ++v )
    3865 {
    3866 consvars[v] = reoptconsdata->vars[v];
    3867 consval = reoptconsdata->vals[v];
    3868 consboundtype = SCIPsetIsFeasEQ(set, consval, 1.0) ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER;
    3869
    3870 assert(SCIPvarIsOriginal(consvars[v]));
    3871 SCIP_CALL( SCIPvarGetProbvarBound(&consvars[v], &consval, &consboundtype) );
    3872 assert(SCIPvarIsTransformed(consvars[v]));
    3873 assert(SCIPvarGetStatus(consvars[v]) != SCIP_VARSTATUS_MULTAGGR);
    3874
    3875 if ( SCIPsetIsFeasEQ(set, consval, 1.0) )
    3876 {
    3877 SCIP_CALL( SCIPvarNegate(consvars[v], blkmem, set, stat, &consvars[v]) );
    3878 assert(SCIPvarIsNegated(consvars[v]));
    3879 }
    3880 }
    3881
    3882 SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, reoptconsdata->nvars, consvars,
    3884 }
    3885 /* case 2: at least one variable is integer or continuous. we use a bounddisjunction constraint. */
    3886 else
    3887 {
    3888 SCIP_Real* consvals;
    3889 SCIP_BOUNDTYPE* consboundtypes;
    3890
    3891 assert(nintvars > 0 || ncontvars > 0);
    3892
    3893 /* alloc buffer memory */
    3894 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, reoptconsdata->nvars) );
    3895 SCIP_CALL( SCIPallocBufferArray(scip, &consboundtypes, reoptconsdata->nvars) );
    3896
    3897 /* iterate over all variables and transform them */
    3898 for( int v = 0; v < reoptconsdata->nvars; ++v )
    3899 {
    3900 consvars[v] = reoptconsdata->vars[v];
    3901 consvals[v] = reoptconsdata->vals[v];
    3902 consboundtypes[v] = reoptconsdata->boundtypes[v];
    3903
    3904 /* we have to switch the bounds.
    3905 * case 1: integer variable with bound x <= u is transformed to u+1 <= x
    3906 * and l <= x is transformed to x <= l-1
    3907 * case 2: continuous variable with bound x <= u is transformed to u <= x
    3908 * and l <= x is transformed to x <= l
    3909 */
    3910 if( SCIPvarIsIntegral(consvars[v]) )
    3911 {
    3912 if( consboundtypes[v] == SCIP_BOUNDTYPE_UPPER )
    3913 {
    3914 consvals[v] += 1.0;
    3915 assert(SCIPsetIsLE(set, consvals[v], SCIPvarGetUbGlobal(consvars[v])));
    3916 }
    3917 else
    3918 {
    3919 consvals[v] -= 1.0;
    3920 assert(SCIPsetIsGE(set, consvals[v], SCIPvarGetLbGlobal(consvars[v])));
    3921 }
    3922 }
    3923
    3924 consboundtypes[v] = (SCIP_BOUNDTYPE)(1 - consboundtypes[v]); /*lint !e641*/
    3925
    3926 assert(SCIPvarIsOriginal(consvars[v]));
    3927 SCIP_CALL( SCIPvarGetProbvarBound(&consvars[v], &consvals[v], &consboundtypes[v]) );
    3928 assert(SCIPvarIsTransformed(consvars[v]));
    3929 assert(SCIPvarGetStatus(consvars[v]) != SCIP_VARSTATUS_MULTAGGR);
    3930 }
    3931
    3932 /* create the constraints and add them to the corresponding nodes */
    3933 SCIP_CALL( SCIPcreateConsBounddisjunctionRedundant(scip, &cons, name, reoptconsdata->nvars, consvars, consboundtypes,
    3934 consvals, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
    3935
    3936 /* free buffer memory */
    3937 SCIPfreeBufferArray(scip, &consboundtypes);
    3938 SCIPfreeBufferArray(scip, &consvals);
    3939 }
    3940
    3941 SCIPsetDebugMsg(set, " -> add constraint in node #%lld:\n", SCIPnodeGetNumber(node));
    3942#ifdef SCIP_DEBUG_CONSS
    3944#endif
    3945
    3946 SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
    3947 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    3948
    3949 /* free buffer */
    3950 SCIPfreeBufferArray(scip, &consvars);
    3951 }
    3952
    3953 return SCIP_OKAY;
    3954}
    3955
    3956/** fix all bounds ad stored in dualredscur at the given node @p node_fix */
    3957static
    3959 SCIP_REOPT* reopt, /**< reoptimization data structure */
    3960 SCIP_SET* set, /**< global SCIP settings */
    3961 SCIP_STAT* stat, /**< dynamic problem statistics */
    3962 SCIP_PROB* transprob, /**< transformed problem */
    3963 SCIP_PROB* origprob, /**< original problem */
    3964 SCIP_TREE* tree, /**< search tree */
    3965 SCIP_LP* lp, /**< current LP */
    3966 SCIP_BRANCHCAND* branchcand, /**< branching candidates */
    3967 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    3968 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    3969 SCIP_CLIQUETABLE* cliquetable, /**< clique table */
    3970 BMS_BLKMEM* blkmem, /**< block memory */
    3971 SCIP_NODE* node, /**< node corresponding to the fixed part */
    3972 unsigned int id, /**< id of stored node */
    3973 SCIP_Bool updatedualconss /**< update constraint representing dual bound changes */
    3974 )
    3975{
    3976 SCIP_REOPTTREE* reopttree;
    3977 SCIP_REOPTNODE* reoptnode;
    3978
    3979 assert(reopt != NULL);
    3980 assert(set != NULL);
    3981 assert(stat != NULL);
    3982 assert(transprob != NULL);
    3983 assert(origprob != NULL);
    3984 assert(tree != NULL);
    3985 assert(lp != NULL);
    3986 assert(branchcand != NULL);
    3987 assert(eventqueue != NULL);
    3988 assert(cliquetable != NULL);
    3989 assert(node != NULL);
    3990 assert(blkmem != NULL);
    3991
    3992 reopttree = reopt->reopttree;
    3993 assert(reopttree != NULL);
    3994 assert(0 < id && id < reopttree->reoptnodessize);
    3995
    3996 reoptnode = reopttree->reoptnodes[id];
    3997 assert(reoptnode != NULL);
    3998 assert(reoptnode->dualreds);
    3999 assert(reoptnode->dualredscur != NULL);
    4000
    4001 /* ensure that the arrays to store the bound changes are large enough */
    4002 SCIP_CALL( reoptnodeCheckMemory(reoptnode, set, blkmem, reoptnode->nvars + reoptnode->dualredscur->nvars, 0, 0) );
    4003
    4004 for( int v = 0; v < reoptnode->dualredscur->nvars; ++v )
    4005 {
    4006 SCIP_VAR* var;
    4007 SCIP_Real val;
    4008 SCIP_BOUNDTYPE boundtype;
    4009 SCIP_Bool bndchgd;
    4010
    4011 var = reoptnode->dualredscur->vars[v];
    4012 val = reoptnode->dualredscur->vals[v];
    4013 boundtype = reoptnode->dualredscur->boundtypes[v];
    4014
    4015 SCIP_CALL( SCIPvarGetProbvarBound(&var, &val, &boundtype) );
    4016 assert(SCIPvarIsTransformedOrigvar(var));
    4017
    4018 bndchgd = FALSE;
    4019
    4020 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, val, SCIPvarGetLbLocal(var))
    4021 && SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)) )
    4022 {
    4023 SCIPvarAdjustLb(var, set, &val);
    4024 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    4025 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, val, SCIP_BOUNDTYPE_LOWER, FALSE) );
    4026
    4027 bndchgd = TRUE;
    4028 }
    4029 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var))
    4030 && SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)) )
    4031 {
    4032 SCIPvarAdjustUb(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_UPPER, FALSE) );
    4035
    4036 bndchgd = TRUE;
    4037 }
    4038 else if( boundtype != SCIP_BOUNDTYPE_LOWER && boundtype != SCIP_BOUNDTYPE_UPPER )
    4039 {
    4040 SCIPerrorMessage("** Unknown boundtype: %d **\n", boundtype);
    4041 return SCIP_INVALIDDATA;
    4042 }
    4043#ifdef SCIP_MORE_DEBUG
    4044 SCIPsetDebugMsg(set, " (dual) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", val);
    4045#endif
    4046 /* add variable and bound to branching path information, because we don't want to delete this data */
    4047 if( bndchgd )
    4048 {
    4049 int pos;
    4050 SCIP_Real constant;
    4051 SCIP_Real scalar;
    4052
    4053 pos = reoptnode->nvars;
    4054
    4055 reoptnode->vars[pos] = var;
    4056 scalar = 1.0;
    4057 constant = 0.0;
    4058 SCIP_CALL( SCIPvarGetOrigvarSum(&reoptnode->vars[pos], &scalar, &constant) );
    4059 assert(SCIPvarIsOriginal(reoptnode->vars[pos]));
    4060
    4061 reoptnode->varbounds[pos] = reoptnode->dualredscur->vals[v];
    4062 reoptnode->varboundtypes[pos] = (SCIPsetIsFeasEQ(set, reoptnode->varbounds[pos], 0.0) ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER);
    4063 ++reoptnode->nvars;
    4064 }
    4065 }
    4066
    4067 if( updatedualconss )
    4068 {
    4069 /* delete dualredscur and move dualredsnex -> dualredscur */
    4070 SCIP_CALL( reoptnodeUpdateDualConss(reoptnode, blkmem) );
    4071 }
    4072
    4073 return SCIP_OKAY;
    4074}
    4075
    4076/** fix all bounds corresponding to dual bound changes in a previous iteration in the fashion of interdiction branching;
    4077 * keep the first negbndchg-1 bound changes as stored in dualredscur and negate the negbndchg-th bound.
    4078 */
    4079static
    4081 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4082 SCIP_SET* set, /**< global SCIP settings */
    4083 SCIP_STAT* stat, /**< dynamic problem statistics */
    4084 SCIP_PROB* transprob, /**< transformed problem */
    4085 SCIP_PROB* origprob, /**< original problem */
    4086 SCIP_TREE* tree, /**< search tree */
    4087 SCIP_LP* lp, /**< current LP */
    4088 SCIP_BRANCHCAND* branchcand, /**< branching candidates */
    4089 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    4090 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    4091 SCIP_CLIQUETABLE* cliquetable, /**< clique table */
    4092 BMS_BLKMEM* blkmem, /**< block memory */
    4093 SCIP_NODE* node, /**< child node */
    4094 unsigned int id, /**< id of the node */
    4095 int* perm, /**< array of permuted indices */
    4096 SCIP_VAR** vars, /**< variables */
    4097 SCIP_Real* vals, /**< bounds */
    4098 SCIP_BOUNDTYPE* boundtypes, /**< boundtypes */
    4099 int nvars, /**< number of variables */
    4100 int negbndchg /**< index of the variable that should negated */
    4101 )
    4102{
    4103 SCIP_VAR* var;
    4104 SCIP_Real val;
    4105 SCIP_BOUNDTYPE boundtype;
    4106 int nbndchgs;
    4107
    4108 assert(reopt != NULL);
    4109 assert(set != NULL);
    4110 assert(stat != NULL);
    4111 assert(transprob != NULL);
    4112 assert(origprob != NULL);
    4113 assert(tree != NULL);
    4114 assert(lp != NULL);
    4115 assert(branchcand != NULL);
    4116 assert(eventqueue != NULL);
    4117 assert(cliquetable != NULL);
    4118 assert(node != NULL);
    4119 assert(perm != NULL);
    4120 assert(vars != NULL);
    4121 assert(vals != NULL);
    4122 assert(boundtypes != NULL);
    4123 assert(nvars >= 0);
    4124 assert(blkmem != NULL);
    4125 assert(0 < id && id < reopt->reopttree->reoptnodessize);
    4126
    4127#ifndef NDEBUG
    4128 {
    4129 SCIP_REOPTTREE* reopttree;
    4130 SCIP_REOPTNODE* reoptnode;
    4131
    4132 reopttree = reopt->reopttree;
    4133 assert(reopttree != NULL);
    4134
    4135 reoptnode = reopttree->reoptnodes[id];
    4136 assert(reoptnode != NULL);
    4137 assert(reoptnode->dualreds);
    4138 }
    4139#endif
    4140
    4141 nbndchgs = MIN(negbndchg, nvars);
    4142
    4143 /* change the first nbndchg-1 bounds as stored in dualredscur and negate the negbndchg-th bound */
    4144 for( int v = 0; v < nbndchgs; ++v )
    4145 {
    4146 var = vars[perm[v]];
    4147 val = vals[perm[v]];
    4148 boundtype = boundtypes[perm[v]];
    4149
    4150 SCIP_CALL( SCIPvarGetProbvarBound(&var, &val, &boundtype) );
    4151 assert(SCIPvarIsTransformedOrigvar(var));
    4152
    4153 /* negate the last bound change */
    4154 if( v == nbndchgs-1 )
    4155 {
    4156 boundtype = (SCIP_BOUNDTYPE)(SCIP_BOUNDTYPE_UPPER - boundtype); /*lint !e656*/
    4157 if( SCIPvarIsIntegral(var) && boundtype == SCIP_BOUNDTYPE_UPPER )
    4158 val = val - 1.0;
    4159 else if( SCIPvarIsIntegral(var) && boundtype == SCIP_BOUNDTYPE_LOWER )
    4160 val = val + 1.0;
    4161 }
    4162
    4163 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, val, SCIPvarGetLbLocal(var))
    4164 && SCIPsetIsFeasLE(set, val, SCIPvarGetUbLocal(var)) )
    4165 {
    4166 SCIPvarAdjustLb(var, set, &val);
    4167 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    4168 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, val, SCIP_BOUNDTYPE_LOWER, FALSE) );
    4169 }
    4170 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var))
    4171 && SCIPsetIsFeasGE(set, val, SCIPvarGetLbLocal(var)) )
    4172 {
    4173 SCIPvarAdjustUb(var, set, &val);
    4174 SCIP_CALL( SCIPnodeAddBoundchg(node, blkmem, set, stat, transprob, origprob,
    4175 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, val, SCIP_BOUNDTYPE_UPPER, FALSE) );
    4176 }
    4177 else if( boundtype != SCIP_BOUNDTYPE_LOWER && boundtype != SCIP_BOUNDTYPE_UPPER )
    4178 {
    4179 SCIPerrorMessage("** Unknown boundtype: %d **\n", boundtype);
    4180 return SCIP_INVALIDDATA;
    4181 }
    4182#ifdef SCIP_MORE_DEBUG
    4183 SCIPsetDebugMsg(set, " (dual) <%s> %s %g\n", SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", val);
    4184#endif
    4185 }
    4186
    4187 return SCIP_OKAY;
    4188}
    4189
    4190/** add all constraints stored at @p id to the given nodes @p node_fix and @p node_cons */
    4191static
    4193 SCIP* scip, /**< SCIP data structure */
    4194 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4195 SCIP_SET* set, /**< global SCIP settings */
    4196 SCIP_STAT* stat, /**< dynamic problem statistics */
    4197 BMS_BLKMEM* blkmem, /**< block memory */
    4198 SCIP_NODE* node, /**< node of the branch and bound tree*/
    4199 unsigned int id /**< id of stored node */
    4200 )
    4201{
    4202 char name[SCIP_MAXSTRLEN];
    4203
    4204 assert(scip != NULL);
    4205 assert(reopt != NULL);
    4206 assert(reopt->reopttree != NULL);
    4207 assert(set != NULL);
    4208 assert(stat != NULL);
    4209 assert(blkmem != NULL);
    4210 assert(node != NULL);
    4211 assert(0 < id && id < reopt->reopttree->reoptnodessize);
    4212
    4213 if( reopt->reopttree->reoptnodes[id]->nconss == 0 )
    4214 return SCIP_OKAY;
    4215
    4216 SCIPsetDebugMsg(set, " -> add %d constraint(s) to node #%lld:\n", reopt->reopttree->reoptnodes[id]->nconss,
    4217 SCIPnodeGetNumber(node));
    4218
    4219 for( int c = 0; c < reopt->reopttree->reoptnodes[id]->nconss; ++c )
    4220 {
    4221 SCIP_CONS* cons;
    4222 SCIP_REOPTCONSDATA* reoptconsdata;
    4223
    4224 reoptconsdata = reopt->reopttree->reoptnodes[id]->conss[c];
    4225 assert(reoptconsdata != NULL);
    4226 assert(reoptconsdata->nvars > 0);
    4227 assert(reoptconsdata->varssize >= reoptconsdata->nvars);
    4228
    4229 if( reoptconsdata->constype == REOPT_CONSTYPE_CUT )
    4230 continue;
    4231
    4232 if( reoptconsdata->constype == REOPT_CONSTYPE_INFSUBTREE )
    4233 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_inf");
    4234 else if( reoptconsdata->constype == REOPT_CONSTYPE_DUALREDS )
    4235 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_dual");
    4236 else
    4237 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "reopt_unkn");
    4238
    4239 if( reoptconsdata->linear )
    4240 {
    4241 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, name, reoptconsdata->nvars, reoptconsdata->vars, reoptconsdata->vals,
    4242 reoptconsdata->lhs, reoptconsdata->rhs, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
    4243 }
    4244 else
    4245 {
    4246 assert(reoptconsdata->boundtypes != NULL);
    4247 SCIP_CALL( SCIPcreateConsBounddisjunctionRedundant(scip, &cons, name, reoptconsdata->nvars, reoptconsdata->vars, reoptconsdata->boundtypes,
    4248 reoptconsdata->vals, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
    4249 }
    4250#ifdef SCIP_DEBUG_CONSS
    4252#endif
    4253 SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
    4254 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    4255 }
    4256
    4257 return SCIP_OKAY;
    4258}
    4259
    4260/** reset the internal statistics at the beginning of a new iteration */
    4261static
    4263 SCIP_REOPT* reopt /**< reoptimization data structure */
    4264 )
    4265{
    4266 assert(reopt != NULL);
    4267
    4268 reopt->lastbranched = -1;
    4269 reopt->currentnode = -1;
    4270 reopt->lastseennode = -1;
    4271 reopt->reopttree->nfeasnodes = 0;
    4272 reopt->reopttree->ninfnodes = 0;
    4273 reopt->reopttree->nprunednodes = 0;
    4274 reopt->reopttree->ncutoffreoptnodes = 0;
    4275
    4276 if( reopt->dualreds != NULL )
    4277 reopt->dualreds->nvars = 0;
    4278}
    4279
    4280/** check the stored bound changes of all child nodes for redundancy and infeasibility
    4281 *
    4282 * Due to strongbranching initialization at node stored at @p id it can happen, that some bound changes stored in the
    4283 * child nodes of the reoptimization node stored at @p id become redundant or make the subproblem infeasible. in this
    4284 * method we remove all redundant bound changes and delete infeasible child nodes.
    4285 */
    4286static
    4288 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4289 SCIP_SET* set, /**< global SCIP settings */
    4290 BMS_BLKMEM* blkmem, /**< block memory */
    4291 SCIP_Bool* runagain, /**< pointer to store of this method should run again */
    4292 unsigned int id /**< id of stored node */
    4293 )
    4294{
    4295 SCIP_REOPTNODE* reoptnode;
    4296 unsigned int* cutoffchilds;
    4297 int ncutoffchilds = 0;
    4298 unsigned int* redchilds;
    4299 int nredchilds = 0;
    4300 int c;
    4301
    4302 assert(reopt != NULL);
    4303 assert(reopt->reopttree != NULL);
    4304 assert(id < reopt->reopttree->reoptnodessize);
    4305 assert(reopt->reopttree->reoptnodes != NULL);
    4306 assert(reopt->reopttree->reoptnodes[id] != NULL);
    4307
    4308 reoptnode = reopt->reopttree->reoptnodes[id];
    4309
    4310 *runagain = FALSE;
    4311
    4312 SCIPsetDebugMsg(set, "start dry branching of node at ID %u\n", id);
    4313
    4314 /* allocate buffer arrays */
    4315 SCIP_CALL( SCIPsetAllocBufferArray(set, &cutoffchilds, reoptnode->nchilds) );
    4316 SCIP_CALL( SCIPsetAllocBufferArray(set, &redchilds, reoptnode->nchilds) );
    4317
    4318 /* iterate over all child nodes and check each bound changes
    4319 * for redundancy and conflict */
    4320 for( c = 0; c < reoptnode->nchilds; ++c )
    4321 {
    4322 SCIP_REOPTNODE* child;
    4323 SCIP_Bool cutoff;
    4324 SCIP_Bool redundant;
    4325 int* redundantvars;
    4326 int nredundantvars;
    4327 unsigned int childid;
    4328
    4329 cutoff = FALSE;
    4330 redundant = FALSE;
    4331 nredundantvars = 0;
    4332
    4333 childid = reoptnode->childids[c];
    4334 assert(childid < reopt->reopttree->reoptnodessize);
    4335 child = reopt->reopttree->reoptnodes[childid];
    4336 assert(child != NULL);
    4337#ifdef SCIP_MORE_DEBUG
    4338 SCIPsetDebugMsg(set, "-> check child at ID %d (%d vars, %d conss):\n", childid, child->nvars, child->nconss);
    4339#endif
    4340 if( child->nvars > 0 )
    4341 {
    4342 /* allocate buffer memory to store the redundant variables */
    4343 SCIP_CALL( SCIPsetAllocBufferArray(set, &redundantvars, child->nvars) );
    4344
    4345 for( int v = 0; v < child->nvars && !cutoff; ++v )
    4346 {
    4347 SCIP_VAR* transvar;
    4348 SCIP_Real transval;
    4349 SCIP_BOUNDTYPE transbndtype;
    4350 SCIP_Real ub;
    4351 SCIP_Real lb;
    4352
    4353 transvar = child->vars[v];
    4354 transval = child->varbounds[v];
    4355 transbndtype = child->varboundtypes[v];
    4356
    4357 /* transform into the transformed space */
    4358 SCIP_CALL( SCIPvarGetProbvarBound(&transvar, &transval, &transbndtype) );
    4359
    4360 lb = SCIPvarGetLbLocal(transvar);
    4361 ub = SCIPvarGetUbLocal(transvar);
    4362
    4363 /* check for infeasibility */
    4364 if( SCIPsetIsFeasEQ(set, lb, ub) && !SCIPsetIsFeasEQ(set, lb, transval) )
    4365 {
    4366 SCIPsetDebugMsg(set, " -> <%s> is fixed to %g, can not change bound to %g -> cutoff\n",
    4367 SCIPvarGetName(transvar), lb, transval);
    4368
    4369 cutoff = TRUE;
    4370 break;
    4371 }
    4372
    4373 /* check for redundancy */
    4374 if( SCIPsetIsFeasEQ(set, lb, ub) && SCIPsetIsFeasEQ(set, lb, transval) )
    4375 {
    4376 SCIPsetDebugMsg(set, " -> <%s> is already fixed to %g -> redundant bound change\n",
    4377 SCIPvarGetName(transvar), lb);
    4378
    4379 redundantvars[nredundantvars] = v;
    4380 ++nredundantvars;
    4381 }
    4382 }
    4383
    4384 if( !cutoff && nredundantvars > 0 )
    4385 {
    4386 for( int v = 0; v < nredundantvars; ++v )
    4387 {
    4388 /* replace the redundant variable by the last stored variable */
    4389 child->vars[redundantvars[v]] = child->vars[child->nvars-1];
    4390 child->varbounds[redundantvars[v]] = child->varbounds[child->nvars-1];
    4391 child->varboundtypes[redundantvars[v]] = child->varboundtypes[child->nvars-1];
    4392 --child->nvars;
    4393 }
    4394 }
    4395
    4396 /* free buffer memory */
    4397 SCIPsetFreeBufferArray(set, &redundantvars);
    4398 }
    4399 else if( child->nconss == 0 )
    4400 {
    4401 redundant = TRUE;
    4402 SCIPsetDebugMsg(set, " -> redundant node found.\n");
    4403 }
    4404
    4405 if( cutoff )
    4406 {
    4407 cutoffchilds[ncutoffchilds] = childid;
    4408 ++ncutoffchilds;
    4409 }
    4410 else if( redundant )
    4411 {
    4412 redchilds[nredchilds] = childid;
    4413 ++nredchilds;
    4414 }
    4415 }
    4416
    4417 SCIPsetDebugMsg(set, "-> found %d redundant and %d infeasible nodes\n", nredchilds, ncutoffchilds);
    4418
    4419 /* delete all nodes that can be cut off */
    4420 while( ncutoffchilds > 0 )
    4421 {
    4422 /* delete the node and the induced subtree */
    4423 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, cutoffchilds[ncutoffchilds-1], TRUE, TRUE) );
    4424
    4425 /* find the position in the childid array */
    4426 c = 0;
    4427 while( c < reoptnode->nchilds && reoptnode->childids[c] != cutoffchilds[ncutoffchilds-1] )
    4428 ++c;
    4429 assert(reoptnode->childids[c] == cutoffchilds[ncutoffchilds-1]);
    4430
    4431 /* replace the ID at position c by the last ID */
    4432 reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
    4433 --reoptnode->nchilds;
    4434
    4435 /* decrease the number of nodes to cutoff */
    4436 --ncutoffchilds;
    4437 }
    4438
    4439 /* replace all redundant nodes their child nodes or cutoff the node if it is a leaf */
    4440 while( nredchilds > 0 )
    4441 {
    4442 /* find the position in the childid array */
    4443 c = 0;
    4444 while( c < reoptnode->nchilds && reoptnode->childids[c] != redchilds[nredchilds-1] )
    4445 ++c;
    4446 assert(reoptnode->childids[c] == redchilds[nredchilds-1]);
    4447
    4448 /* the node is a leaf and we can cutoff them */
    4449 if( reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->nchilds == 0 )
    4450 {
    4451 /* delete the node and the induced subtree */
    4452 SCIP_CALL( deleteChildrenBelow(reopt->reopttree, set, blkmem, redchilds[nredchilds-1], TRUE, TRUE) );
    4453
    4454 /* replace the ID at position c by the last ID */
    4455 reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
    4456 --reoptnode->nchilds;
    4457
    4458 /* decrease the number of redundant nodes */
    4459 --nredchilds;
    4460 }
    4461 else
    4462 {
    4463 int ncc;
    4464
    4465 /* replace the ID at position c by the last ID */
    4466 reoptnode->childids[c] = reoptnode->childids[reoptnode->nchilds-1];
    4467 --reoptnode->nchilds;
    4468
    4469 ncc = reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->nchilds;
    4470
    4471 /* check the memory */
    4472 SCIP_CALL( reoptnodeCheckMemory(reopt->reopttree->reoptnodes[id], set, blkmem, 0, reoptnode->nchilds+ncc, 0) );
    4473
    4474 /* add all IDs of child nodes to the current node */
    4475 for( int cc = 0; cc < ncc; ++cc )
    4476 {
    4477 reoptnode->childids[reoptnode->nchilds] = reopt->reopttree->reoptnodes[redchilds[nredchilds-1]]->childids[cc];
    4478 ++reoptnode->nchilds;
    4479 }
    4480
    4481 /* delete the redundant node */
    4482 SCIP_CALL( reopttreeDeleteNode(reopt->reopttree, set, blkmem, redchilds[nredchilds-1], TRUE) );
    4483 SCIP_CALL( SCIPqueueInsertUInt(reopt->reopttree->openids, redchilds[nredchilds-1]) );
    4484
    4485 /* decrease the number of redundant nodes */
    4486 --nredchilds;
    4487
    4488 /* update the flag to rerun this method */
    4489 *runagain = TRUE;
    4490 }
    4491 }
    4492
    4493 /* free buffer arrays */
    4494 SCIPsetFreeBufferArray(set, &redchilds);
    4495 SCIPsetFreeBufferArray(set, &cutoffchilds);
    4496
    4497 return SCIP_OKAY;
    4498}
    4499
    4500/** return the number of all nodes in the subtree induced by the reoptimization node stored at @p id */
    4501static
    4503 SCIP_REOPTTREE* reopttree, /**< reopttree */
    4504 unsigned int id /**< id of stored node */
    4505 )
    4506{
    4507 int nnodes = 0;
    4508
    4509 assert(reopttree != NULL);
    4510 assert(id < reopttree->reoptnodessize);
    4511
    4512 for( int i = 0; i < reopttree->reoptnodes[id]->nchilds; ++i )
    4513 nnodes += reopttreeGetNNodes(reopttree, reopttree->reoptnodes[id]->childids[i]);
    4514
    4515 return nnodes + 1;
    4516}
    4517
    4518/** returns the number of leaf nodes of the induced subtree */
    4519static
    4521 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4522 unsigned int id /**< id of stored node */
    4523 )
    4524{
    4525 int nleaves = 0;
    4526
    4527 assert(reopt != NULL);
    4528 assert(id < reopt->reopttree->reoptnodessize);
    4529 assert(reopt->reopttree->reoptnodes[id] != NULL);
    4530
    4531 /* iterate over all child nods and check whether they are leaves or not */
    4532 for( int i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
    4533 {
    4534 unsigned int childid;
    4535
    4536 childid = reopt->reopttree->reoptnodes[id]->childids[i];
    4537 assert(childid < reopt->reopttree->reoptnodessize);
    4538
    4539 if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
    4540 ++nleaves;
    4541 else
    4542 nleaves += reoptGetNLeaves(reopt, childid);
    4543 }
    4544
    4545 return nleaves;
    4546}
    4547
    4548/** returns all leaves of the subtree induced by the node stored at @p id*/
    4549static
    4551 SCIP_REOPT* reopt, /**< reoptimization data structure*/
    4552 unsigned int id, /**< id of stored node */
    4553 unsigned int* leaves, /**< array of leave nodes */
    4554 int leavessize, /**< size of leaves array */
    4555 int* nleaves /**< pointer to store the number of leave nodes */
    4556 )
    4557{
    4558 assert(reopt != NULL);
    4559 assert(leavessize > 0 && leaves != NULL);
    4560 assert((*nleaves) >= 0);
    4561 assert(id < reopt->reopttree->reoptnodessize);
    4562 assert(reopt->reopttree->reoptnodes[id] != NULL);
    4563
    4564 for( int i = 0, l = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
    4565 {
    4566 unsigned int childid;
    4567
    4568 assert(*nleaves <= leavessize);
    4569
    4570 childid = reopt->reopttree->reoptnodes[id]->childids[i];
    4571 assert(childid < reopt->reopttree->reoptnodessize);
    4572
    4573 if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
    4574 {
    4575 leaves[l] = reopt->reopttree->reoptnodes[id]->childids[i];
    4576 ++l;
    4577 ++(*nleaves);
    4578 }
    4579 else
    4580 {
    4581 int nleaves2 = 0;
    4582
    4583 SCIP_CALL( reoptGetLeaves(reopt, childid, &leaves[l], leavessize - l, &nleaves2) );
    4584 l += nleaves2;
    4585 (*nleaves) += nleaves2;
    4586 }
    4587 }
    4588
    4589 return SCIP_OKAY;
    4590}
    4591
    4592/** after restarting the reoptimization and an after compressing the search tree we have to delete all stored information */
    4593static
    4595 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4596 SCIP_SET* set, /**< global SCIP settings */
    4597 BMS_BLKMEM* blkmem, /**< block memory */
    4598 SCIP_Bool softreset /**< mark the nodes to overwriteable (TRUE) or delete them completely (FALSE) */
    4599 )
    4600{
    4601 assert(reopt != NULL);
    4602 assert(set != NULL);
    4603 assert(blkmem != NULL);
    4604
    4605 /* clear the tree */
    4606 SCIP_CALL( clearReoptnodes(reopt->reopttree, set, blkmem, softreset) );
    4607 assert(reopt->reopttree->nreoptnodes == 0);
    4608
    4609 /* reset the dual constraint */
    4610 if( reopt->dualreds != NULL )
    4611 reopt->dualreds->nvars = 0;
    4612
    4613 reopt->currentnode = -1;
    4614
    4615 return SCIP_OKAY;
    4616}
    4617
    4618/** restart the reoptimization by removing all stored information about nodes and increase the number of restarts */
    4619static
    4621 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4622 SCIP_SET* set, /**< global SCIP settings */
    4623 BMS_BLKMEM* blkmem /**< block memory */
    4624 )
    4625{
    4626 assert(reopt != NULL);
    4627 assert(reopt->reopttree != NULL);
    4628 assert(set != NULL);
    4629 assert(blkmem != NULL);
    4630
    4631 /* clear the tree */
    4632 SCIP_CALL( reoptResetTree(reopt, set, blkmem, FALSE) );
    4633 assert(reopt->reopttree->nreoptnodes == 0);
    4634
    4635 /* allocate memory for the root node */
    4636 SCIP_CALL( createReoptnode(reopt->reopttree, set, blkmem, 0) );
    4637
    4638 reopt->nglbrestarts += 1;
    4639
    4640 if( reopt->firstrestart == -1 )
    4641 reopt->firstrestart = reopt->run;
    4642
    4643 reopt->lastrestart = reopt->run;
    4644
    4645 return SCIP_OKAY;
    4646}
    4647
    4648/** save the new objective function */
    4649static
    4651 SCIP_REOPT* reopt, /**< reoptimization data */
    4652 SCIP_SET* set, /**< global SCIP settings */
    4653 BMS_BLKMEM* blkmem, /**< block memory */
    4654 SCIP_VAR** origvars, /**< original problem variables */
    4655 int norigvars /**< number of original problem variables */
    4656 )
    4657{
    4658 int probidx;
    4659
    4660 assert(reopt != NULL);
    4661 assert(set != NULL);
    4662 assert(blkmem != NULL);
    4663 assert(origvars != NULL);
    4664 assert(norigvars >= 0);
    4665
    4666 /* check memory */
    4667 SCIP_CALL( ensureRunSize(reopt, set, reopt->run, blkmem) );
    4668
    4669 /* get memory and check whether we have to resize all previous objectives */
    4670 if( reopt->nobjvars < norigvars )
    4671 {
    4672 for( int i = 0; i < reopt->run-1; ++i )
    4673 {
    4674 SCIP_ALLOC( BMSreallocMemoryArray(&reopt->objs[i], norigvars) ); /*lint !e866*/
    4675 for( int v = reopt->nobjvars-1; v < norigvars; ++v )
    4676 reopt->objs[i][v] = 0.0;
    4677 }
    4678 reopt->nobjvars = norigvars;
    4679 }
    4680 SCIP_ALLOC( BMSallocClearMemoryArray(&reopt->objs[reopt->run-1], reopt->nobjvars) ); /*lint !e866*/
    4681
    4682 /* save coefficients */
    4683 for( int v = 0; v < norigvars; ++v )
    4684 {
    4685 assert(SCIPvarIsOriginal(origvars[v]));
    4686
    4687 probidx = SCIPvarGetIndex(origvars[v]);
    4688
    4689 /* it can happen that the index is greater than the number of problem variables,
    4690 * i.e., not all created variables were added
    4691 */
    4692 if( probidx >= reopt->nobjvars )
    4693 {
    4694 int newsize = SCIPsetCalcMemGrowSize(set, probidx+1);
    4695 for( int i = 0; i < reopt->run; ++i )
    4696 {
    4697 SCIP_ALLOC( BMSreallocMemoryArray(&reopt->objs[i], newsize) ); /*lint !e866*/
    4698 for( int j = reopt->nobjvars; j < newsize; ++j )
    4699 reopt->objs[i][j] = 0.0;
    4700 }
    4701 reopt->nobjvars = newsize;
    4702 }
    4703 assert(0 <= probidx && probidx < reopt->nobjvars);
    4704
    4705 reopt->objs[reopt->run-1][probidx] = SCIPvarGetObj(origvars[v]);
    4706
    4707 /* update flag to remember if the objective function has changed */
    4708 if( !reopt->objhaschanged && reopt->run >= 2
    4709 && ! SCIPsetIsEQ(set, reopt->objs[reopt->run-2][probidx], reopt->objs[reopt->run-1][probidx]) )
    4710 reopt->objhaschanged = TRUE;
    4711
    4712 /* mark this objective as the first non empty */
    4713 if( reopt->firstobj == -1 && reopt->objs[reopt->run-1][probidx] != 0 )
    4714 reopt->firstobj = reopt->run-1;
    4715 }
    4716
    4717 /* calculate similarity to last objective */
    4718 if( reopt->run-1 >= 1 )
    4719 {
    4720 /* calculate similarity to last objective */
    4721 reopt->simtolastobj = reoptSimilarity(reopt, set, reopt->run-1, reopt->run-2, origvars, norigvars);
    4722
    4723 if( reopt->simtolastobj == SCIP_INVALID ) /*lint !e777*/
    4724 return SCIP_INVALIDRESULT;
    4725
    4726 SCIPverbMessage(set->scip, SCIP_VERBLEVEL_HIGH, NULL, "new objective has similarity of %g compared to previous.\n",
    4727 reopt->simtolastobj);
    4728 }
    4729
    4730 SCIPsetDebugMsg(set, "saved obj for run %d.\n", reopt->run);
    4731
    4732 return SCIP_OKAY;
    4733}
    4734
    4735/** orders the variable by inference score */
    4736static
    4738 SCIP_SET* set, /**< global SCIP settings */
    4739 SCIP_STAT* stat, /**< dynamic problem statistics */
    4740 int* perm, /**< array of indices that need to be permuted */
    4741 SCIP_VAR** vars, /**< variable array to permute */
    4742 SCIP_Real* bounds, /**< bound array to permute in the same order */
    4743 SCIP_BOUNDTYPE* boundtypes, /**< boundtype array to permute in the same order */
    4744 int nvars /**< number of variables */
    4745 )
    4746{
    4747 SCIP_Real* infscore;
    4748
    4749 assert(set != NULL);
    4750 assert(perm != NULL);
    4751 assert(vars != NULL);
    4752 assert(bounds != NULL);
    4753 assert(boundtypes != NULL);
    4754 assert(nvars >= 0);
    4755
    4756 /* allocate buffer for the scores */
    4757 SCIP_CALL( SCIPsetAllocBufferArray(set, &infscore, nvars) );
    4758
    4759 for( int v = 0; v < nvars; ++v )
    4760 {
    4761 if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER )
    4762 {
    4763 infscore[v] = 0.75 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_UPWARDS)
    4764 + 0.25 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_DOWNWARDS);
    4765 }
    4766 else
    4767 {
    4768 infscore[v] = 0.25 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_UPWARDS)
    4769 + 0.75 * SCIPvarGetAvgInferences(vars[v], stat, SCIP_BRANCHDIR_DOWNWARDS);
    4770 }
    4771 }
    4772
    4773 /* permute indices by inference score */
    4774 SCIPsortDownRealInt(infscore, perm, nvars);
    4775
    4776 /* free buffer */
    4777 SCIPsetFreeBufferArray(set, &infscore);
    4778
    4779 return SCIP_OKAY;
    4780}
    4781
    4782/** create a global constraint to separate the given solution */
    4783static
    4785 SCIP_REOPT* reopt, /**< reoptimization data structure */
    4786 BMS_BLKMEM* blkmem, /**< block memory */
    4787 SCIP_SET* set, /**< global SCIP settings */
    4788 SCIP_STAT* stat, /**< dynamic SCIP statistics */
    4789 SCIP_SOL* sol, /**< solution to separate */
    4790 SCIP_VAR** vars, /**< array of original problem variables */
    4791 int nvars /**< number of original problem variables */
    4792 )
    4793{
    4794 SCIP_VAR** origvars;
    4795 SCIP_Real* vals;
    4796 int nintvars;
    4797 int nbinvars;
    4798 int w;
    4799
    4800 assert(reopt != NULL);
    4801 assert(sol != NULL);
    4802 assert(blkmem != NULL);
    4803 assert(set != NULL);
    4804 assert(stat != NULL);
    4805 assert(vars != NULL);
    4806 assert(nvars != 0);
    4807 assert(SCIPsolIsOriginal(sol));
    4808
    4809 /* allocate buffer memory */
    4810 SCIP_CALL( SCIPsetAllocBufferArray(set, &origvars, nvars) );
    4811 SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, nvars) );
    4812
    4813 nbinvars = 0;
    4814 nintvars = 0;
    4815 w = 0;
    4816
    4817 /* get the solution values of the variables */
    4818 for( int v = 0; v < nvars; ++v )
    4819 {
    4820 assert(SCIPvarIsOriginal(vars[v]));
    4821 assert(nbinvars + nintvars == w);
    4822
    4823 /* we do not want to create cuts for continuous variables */
    4824 if( !SCIPvarIsIntegral(vars[v]) )
    4825 continue;
    4826
    4827 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(vars[v]) )
    4828 ++nbinvars;
    4829 else
    4830 ++nintvars;
    4831
    4832 origvars[v] = vars[v];
    4833 assert(origvars[v] != NULL);
    4834 assert(SCIPvarIsOriginal(origvars[v]));
    4835
    4836 vals[w] = SCIPsolGetVal(sol, set, stat, origvars[v]);
    4837 ++w;
    4838 }
    4839
    4840 SCIP_CALL( addGlobalCut(reopt, blkmem, set, origvars, vals, NULL, w, nbinvars, nintvars) );
    4841
    4842 /* free buffer memory */
    4844 SCIPsetFreeBufferArray(set, &origvars);
    4845
    4846 return SCIP_OKAY;
    4847}
    4848
    4849/*
    4850 * public methods
    4851 */
    4852
    4853/* ---------------- methods of general reoptimization ---------------- */
    4854
    4855/* In debug mode, the following methods are implemented as function calls to ensure
    4856 * type validity.
    4857 * In optimized mode, the methods are implemented as defines to improve performance.
    4858 * However, we want to have them in the library anyways, so we have to undef the defines.
    4859 */
    4860
    4861#undef SCIPreoptGetNRestartsGlobal
    4862#undef SCIPreoptGetNRestartsLocal
    4863#undef SCIPreoptGetNTotalRestartsLocal
    4864#undef SCIPreoptGetFirstRestarts
    4865#undef SCIPreoptGetLastRestarts
    4866#undef SCIPreoptGetNFeasNodes
    4867#undef SCIPreoptGetNTotalFeasNodes
    4868#undef SCIPreoptGetNPrunedNodes
    4869#undef SCIPreoptGetNTotalPrunedNodes
    4870#undef SCIPreoptGetNCutoffReoptnodes
    4871#undef SCIPreoptGetNTotalCutoffReoptnodes
    4872#undef SCIPreoptGetNInfNodes
    4873#undef SCIPreoptGetNTotalInfNodes
    4874#undef SCIPreoptGetNInfSubtrees
    4875
    4876
    4877/** returns the number of global restarts */
    4879 SCIP_REOPT* reopt /**< reoptimization data structure */
    4880 )
    4881{
    4882 assert(reopt != NULL);
    4883
    4884 return reopt->nglbrestarts;
    4885}
    4886
    4887/** returns the number of local restarts in the current run */
    4889 SCIP_REOPT* reopt /**< reoptimization data structure */
    4890 )
    4891{
    4892 assert(reopt != NULL);
    4893
    4894 return reopt->nlocrestarts;
    4895}
    4896
    4897/** returns the number of local restarts over all runs */
    4899 SCIP_REOPT* reopt /**< reoptimization data structure */
    4900 )
    4901{
    4902 assert(reopt != NULL);
    4903
    4904 return reopt->ntotallocrestarts;
    4905}
    4906
    4907/** returns the number of iteration with the first global restarts */
    4909 SCIP_REOPT* reopt /**< reoptimization data structure */
    4910 )
    4911{
    4912 assert(reopt != NULL);
    4913
    4914 return reopt->firstrestart;
    4915}
    4916
    4917/** returns the number of iteration with the last global restarts */
    4919 SCIP_REOPT* reopt /**< reoptimization data structure */
    4920 )
    4921{
    4922 assert(reopt != NULL);
    4923
    4924 return reopt->lastrestart;
    4925}
    4926
    4927/** returns the number of stored nodes providing an improving feasible LP solution in the current run */
    4929 SCIP_REOPT* reopt /**< reoptimization data structure */
    4930 )
    4931{
    4932 assert(reopt != NULL);
    4933
    4934 return reopt->reopttree->nfeasnodes;
    4935}
    4936
    4937/** returns the number of stored nodes providing an improving feasible LP solution over all runs */
    4939 SCIP_REOPT* reopt /**< reoptimization data structure */
    4940 )
    4941{
    4942 assert(reopt != NULL);
    4943
    4944 return reopt->reopttree->ntotalfeasnodes;
    4945}
    4946
    4947/** returns the number of stored nodes that exceeded the cutoff bound in the current run */
    4949 SCIP_REOPT* reopt /**< reoptimization data structure */
    4950 )
    4951{
    4952 assert(reopt != NULL);
    4953
    4954 return reopt->reopttree->nprunednodes;
    4955}
    4956
    4957/** returns the number of stored nodes that exceeded the cutoff bound over all runs */
    4959 SCIP_REOPT* reopt /**< reoptimization data structure */
    4960 )
    4961{
    4962 assert(reopt != NULL);
    4963
    4964 return reopt->reopttree->ntotalprunednodes;
    4965}
    4966
    4967/** rerturns the number of reoptimized nodes that were cutoff in the same iteration in the current run */
    4969 SCIP_REOPT* reopt /**< reoptimization data structure */
    4970 )
    4971{
    4972 assert(reopt != NULL);
    4973
    4974 return reopt->reopttree->ncutoffreoptnodes;
    4975}
    4976
    4977/** rerturns the number of reoptimized nodes that were cutoff in the same iteration over all runs */
    4979 SCIP_REOPT* reopt /**< reoptimization data structure */
    4980 )
    4981{
    4982 assert(reopt != NULL);
    4983
    4984 return reopt->reopttree->ntotalcutoffreoptnodes;
    4985}
    4986
    4987/** returns the number of stored nodes with an infeasible LP in the current run */
    4989 SCIP_REOPT* reopt /**< reoptimization data structure */
    4990 )
    4991{
    4992 assert(reopt != NULL);
    4993
    4994 return reopt->reopttree->ninfnodes;
    4995}
    4996
    4997/** returns the number of stored nodes with an infeasible LP over all runs */
    4999 SCIP_REOPT* reopt /**< reoptimization data structure */
    5000 )
    5001{
    5002 assert(reopt != NULL);
    5003
    5004 return reopt->reopttree->ntotalinfnodes;
    5005}
    5006
    5007/** constructor for the reoptimization data */
    5009 SCIP_REOPT** reopt, /**< pointer to reoptimization data structure */
    5010 SCIP_SET* set, /**< global SCIP settings */
    5011 BMS_BLKMEM* blkmem /**< block memory */
    5012 )
    5013{
    5014 SCIP_EVENTHDLR* eventhdlr;
    5015
    5016 assert(reopt != NULL);
    5017
    5018 SCIP_ALLOC( BMSallocMemory(reopt) );
    5019 (*reopt)->runsize = DEFAULT_MEM_RUN;
    5020 (*reopt)->run = 0;
    5021 (*reopt)->simtolastobj = -2.0;
    5022 (*reopt)->simtofirstobj = -2.0;
    5023 (*reopt)->firstobj = -1;
    5024 (*reopt)->currentnode = -1;
    5025 (*reopt)->lastbranched = -1;
    5026 (*reopt)->dualreds = NULL;
    5027 (*reopt)->glbconss = NULL;
    5028 (*reopt)->nglbconss = 0;
    5029 (*reopt)->allocmemglbconss = 0;
    5030 (*reopt)->ncheckedsols = 0;
    5031 (*reopt)->nimprovingsols = 0;
    5032 (*reopt)->noptsolsbyreoptsol = 0;
    5033 (*reopt)->nglbrestarts = 0;
    5034 (*reopt)->nlocrestarts = 0;
    5035 (*reopt)->ntotallocrestarts = 0;
    5036 (*reopt)->firstrestart = -1;
    5037 (*reopt)->lastrestart = 0;
    5038 (*reopt)->nobjvars = 0;
    5039 (*reopt)->objhaschanged = FALSE;
    5040 (*reopt)->consadded = FALSE;
    5041 (*reopt)->addedconss = NULL;
    5042 (*reopt)->naddedconss = 0;
    5043 (*reopt)->addedconsssize = 0;
    5044 (*reopt)->glblb = NULL;
    5045 (*reopt)->glbub = NULL;
    5046 (*reopt)->nactiveconss = 0;
    5047 (*reopt)->nmaxactiveconss = 0;
    5048 (*reopt)->activeconss = NULL;
    5049 (*reopt)->activeconssset = NULL;
    5050
    5051 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*reopt)->varhistory, (*reopt)->runsize) );
    5052 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*reopt)->prevbestsols, (*reopt)->runsize) );
    5053 SCIP_ALLOC( BMSallocMemoryArray(&(*reopt)->objs, (*reopt)->runsize) );
    5054
    5055 for( int i = 0; i < (*reopt)->runsize; ++i )
    5056 {
    5057 (*reopt)->objs[i] = NULL;
    5058 (*reopt)->prevbestsols[i] = NULL;
    5059 (*reopt)->varhistory[i] = NULL;
    5060 }
    5061
    5062 /* clocks */
    5063 SCIP_CALL( SCIPclockCreate(&(*reopt)->savingtime, SCIP_CLOCKTYPE_DEFAULT) );
    5064
    5065 /* create and initialize SCIP_SOLTREE */
    5066 SCIP_ALLOC( BMSallocMemory(&(*reopt)->soltree) );
    5067 SCIP_CALL( createSolTree((*reopt)->soltree, blkmem) );
    5068
    5069 /* create and initialize SCIP_REOPTTREE */
    5070 SCIP_ALLOC( BMSallocMemory(&(*reopt)->reopttree) );
    5071 SCIP_CALL( createReopttree((*reopt)->reopttree, set, blkmem) );
    5072
    5073 /* create a random number generator */
    5074 SCIP_CALL( SCIPrandomCreate(&(*reopt)->randnumgen, blkmem, SCIPsetInitializeRandomSeed(set, DEFAULT_RANDSEED)) );
    5075
    5076 /* create event handler for node events */
    5077 eventhdlr = NULL;
    5078
    5079 /* include event handler into SCIP */
    5081 eventInitsolReopt, eventExitsolReopt, NULL, eventExecReopt, NULL) );
    5082 SCIP_CALL( SCIPsetIncludeEventhdlr(set, eventhdlr) );
    5083 assert(eventhdlr != NULL);
    5084
    5085 return SCIP_OKAY;
    5086}
    5087
    5088/* release all variables and constraints captured during reoptimization */
    5090 SCIP_REOPT* reopt, /**< pointer to reoptimization data structure */
    5091 SCIP_SET* set, /**< global SCIP settings */
    5092 BMS_BLKMEM* blkmem /**< block memory */
    5093 )
    5094{
    5095 /* release all added constraints and free the data */
    5096 if( reopt->addedconss != NULL )
    5097 {
    5098 for( int c = 0; c < reopt->naddedconss; ++c )
    5099 {
    5100 assert(reopt->addedconss[c] != NULL);
    5101
    5102 SCIP_CALL( SCIPconsRelease(&reopt->addedconss[c], blkmem, set) );
    5103 }
    5104
    5105 BMSfreeBlockMemoryArray(blkmem, &reopt->addedconss, reopt->addedconsssize);
    5106 reopt->naddedconss = 0;
    5107 reopt->addedconsssize = 0;
    5108 }
    5109
    5110 SCIP_CALL( cleanActiveConss(reopt, set, blkmem) );
    5111
    5112 return SCIP_OKAY;
    5113}
    5114
    5115/** frees reoptimization data */
    5117 SCIP_REOPT** reopt, /**< reoptimization data structure */
    5118 SCIP_SET* set, /**< global SCIP settings */
    5119 SCIP_PRIMAL* origprimal, /**< original primal */
    5120 BMS_BLKMEM* blkmem /**< block memory */
    5121 )
    5122{
    5123 assert(reopt != NULL);
    5124 assert(*reopt != NULL);
    5125 assert(set != NULL);
    5126 assert(origprimal != NULL || set->stage == SCIP_STAGE_INIT);
    5127 assert(blkmem != NULL);
    5128
    5129 /* free random number generator */
    5130 SCIPrandomFree(&(*reopt)->randnumgen, blkmem);
    5131
    5132 /* free reopttree */
    5133 SCIP_CALL( freeReoptTree((*reopt)->reopttree, set, blkmem) );
    5134
    5135 /* free solutions and variable histories */
    5136 if( set->stage >= SCIP_STAGE_PROBLEM )
    5137 {
    5138 for( int p = (*reopt)->run-1; p >= 0; --p )
    5139 {
    5140 if( (*reopt)->soltree->sols[p] != NULL )
    5141 {
    5142 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->soltree->sols[p], (*reopt)->soltree->solssize[p]); /*lint !e866*/
    5143 (*reopt)->soltree->sols[p] = NULL;
    5144 }
    5145
    5146 if( set->reopt_storevarhistory && (*reopt)->varhistory[p] != NULL )
    5147 {
    5148 for( int v = SCIPgetNOrigVars(set->scip)-1; v >= 0; --v )
    5149 {
    5150 SCIPhistoryFree(&(*reopt)->varhistory[p][v], blkmem);
    5151 }
    5152
    5153 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->varhistory[p], SCIPgetNOrigVars(set->scip));
    5154 (*reopt)->varhistory[p] = NULL;
    5155 }
    5156
    5157 /* we have to free all optimal solution separatly, because those solutions are not stored in the
    5158 * solution reopt_sepabestsol = TRUE
    5159 */
    5160 if( set->reopt_sepabestsol && (*reopt)->prevbestsols[p] != NULL )
    5161 {
    5162 SCIP_CALL( SCIPsolFree(&(*reopt)->prevbestsols[p], blkmem, origprimal) );
    5163 }
    5164
    5165 if( (*reopt)->objs[p] != NULL )
    5166 {
    5167 BMSfreeMemoryArray(&(*reopt)->objs[p]);
    5168 }
    5169 }
    5170 }
    5171
    5172 /* free solution tree */
    5173 SCIP_CALL( freeSolTree((*reopt), set, origprimal, blkmem) );
    5174
    5175 if( (*reopt)->dualreds != NULL )
    5176 {
    5177 if( (*reopt)->dualreds->varssize > 0 )
    5178 {
    5179 assert(!(*reopt)->dualreds->linear);
    5180
    5181 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualreds->boundtypes, (*reopt)->dualreds->varssize);
    5182 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualreds->vals, (*reopt)->dualreds->varssize);
    5183 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->dualreds->vars, (*reopt)->dualreds->varssize);
    5184 BMSfreeBlockMemory(blkmem, &(*reopt)->dualreds);
    5185 (*reopt)->dualreds = NULL;
    5186 }
    5187 }
    5188
    5189 if( (*reopt)->glbconss != NULL && (*reopt)->allocmemglbconss > 0 )
    5190 {
    5191 /* free all constraint */
    5192 for( int c = 0; c < (*reopt)->allocmemglbconss; ++c )
    5193 {
    5194 if( (*reopt)->glbconss[c] != NULL )
    5195 {
    5196 if( (*reopt)->glbconss[c]->varssize > 0 )
    5197 {
    5198 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->boundtypes, (*reopt)->glbconss[c]->varssize);
    5199 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->vals, (*reopt)->glbconss[c]->varssize);
    5200 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss[c]->vars, (*reopt)->glbconss[c]->varssize);
    5201 (*reopt)->glbconss[c]->varssize = 0;
    5202 }
    5203 BMSfreeBlockMemory(blkmem, &(*reopt)->glbconss[c]); /*lint !e866*/
    5204 --(*reopt)->nglbconss;
    5205 }
    5206 }
    5207 assert((*reopt)->nglbconss == 0);
    5208
    5209 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->glbconss, (*reopt)->allocmemglbconss);
    5210 (*reopt)->allocmemglbconss = 0;
    5211 }
    5212
    5213 /* clocks */
    5214 SCIPclockFree(&(*reopt)->savingtime);
    5215
    5216 /* the hashmap need not to be exist, e.g., if the problem was solved during presolving */
    5217 if( (*reopt)->activeconssset != NULL )
    5218 {
    5219 SCIPhashsetFree(&(*reopt)->activeconssset, blkmem);
    5220 }
    5221 BMSfreeBlockMemoryArrayNull(blkmem, &(*reopt)->activeconss, (*reopt)->nmaxactiveconss);
    5222
    5223 if( (*reopt)->glblb != NULL )
    5224 {
    5225 SCIPhashmapFree(&(*reopt)->glblb);
    5226 SCIPhashmapFree(&(*reopt)->glbub);
    5227 (*reopt)->glblb = NULL;
    5228 (*reopt)->glbub = NULL;
    5229 }
    5230 else
    5231 assert((*reopt)->glbub == NULL);
    5232
    5233 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->varhistory, (*reopt)->runsize);
    5234 BMSfreeBlockMemoryArray(blkmem, &(*reopt)->prevbestsols, (*reopt)->runsize);
    5235 BMSfreeMemoryArray(&(*reopt)->objs);
    5236 BMSfreeMemory(reopt);
    5237
    5238 return SCIP_OKAY;
    5239}
    5240
    5241/** returns the number of constraints added by the reoptimization plug-in */
    5243 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5244 SCIP_NODE* node /**< node of the search tree */
    5245 )
    5246{
    5247 unsigned int id;
    5248
    5249 assert(reopt != NULL);
    5250 assert(node != NULL);
    5251
    5252 id = SCIPnodeGetReoptID(node);
    5253 assert(id < reopt->reopttree->reoptnodessize);
    5254
    5255 /* set the id to -1 if the node is not part of the reoptimization tree */
    5256 if( SCIPnodeGetDepth(node) > 0 && id == 0 )
    5257 return SCIPnodeGetNAddedConss(node);
    5258
    5259 if( id >= 1 && reopt->reopttree->reoptnodes[id]->nconss > 0 )
    5260 return MAX(SCIPnodeGetNAddedConss(node), reopt->reopttree->reoptnodes[id]->nconss); /*lint !e666*/
    5261 else
    5262 return SCIPnodeGetNAddedConss(node);
    5263}
    5264
    5265/** add a solution to the solution tree */
    5267 SCIP_REOPT* reopt, /**< reoptimization data */
    5268 SCIP_SET* set, /**< global SCIP settings */
    5269 SCIP_STAT* stat, /**< dynamic problem statistics */
    5270 SCIP_PRIMAL* origprimal, /**< original primal */
    5271 BMS_BLKMEM* blkmem, /**< block memory */
    5272 SCIP_SOL* sol, /**< solution to add */
    5273 SCIP_Bool bestsol, /**< is the current solution an optimal solution? */
    5274 SCIP_Bool* added, /**< pointer to store the information if the soltion was added */
    5275 SCIP_VAR** vars, /**< variable array */
    5276 int nvars, /**< number of variables */
    5277 int run /**< number of the current run (1,2,...) */
    5278 )
    5279{
    5280 SCIP_SOLNODE* solnode = NULL;
    5281 SCIP_HEUR* heur;
    5282 int insertpos;
    5283
    5284 assert(reopt != NULL);
    5285 assert(set != NULL);
    5286 assert(sol != NULL);
    5287 assert(run > 0);
    5288
    5289 assert(reopt->soltree->sols[run-1] != NULL);
    5290
    5291 /* if the solution was found by reoptsols the solutions is already stored */
    5292 heur = SCIPsolGetHeur(sol);
    5293 if( heur != NULL && strcmp(SCIPheurGetName(heur), "reoptsols") == 0 && bestsol )
    5294 ++reopt->noptsolsbyreoptsol;
    5295 else if( bestsol )
    5296 reopt->noptsolsbyreoptsol = 0;
    5297
    5298 /* check memory */
    5299 SCIP_CALL( ensureSolsSize(reopt, set, blkmem, reopt->soltree->nsols[run-1]+1, run-1) );
    5300
    5301 /* add solution to solution tree */
    5302 SCIP_CALL( soltreeAddSol(reopt, set, stat, origprimal, blkmem, vars, sol, &solnode, nvars, bestsol, added) );
    5303
    5304 if( (*added) )
    5305 {
    5306 assert(solnode != NULL);
    5307
    5308 /* add solution */
    5309 insertpos = reopt->soltree->nsols[run-1];
    5310 reopt->soltree->sols[run-1][insertpos] = solnode;
    5311 ++reopt->soltree->nsols[run-1];
    5312 assert(reopt->soltree->nsols[run-1] <= set->reopt_savesols);
    5313 }
    5314
    5315 return SCIP_OKAY;
    5316}
    5317
    5318/** we want to store the optimal solution of each run in a separate array */
    5320 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5321 SCIP_SOL* sol, /**< solution to add */
    5322 BMS_BLKMEM* blkmem, /**< block memory */
    5323 SCIP_SET* set, /**< global SCIP settings */
    5324 SCIP_STAT* stat, /**< dynamic problem statistics */
    5325 SCIP_PRIMAL* origprimal, /**< original primal */
    5326 SCIP_VAR** vars, /**< original problem variables */
    5327 int nvars /**< number of original problem variables */
    5328 )
    5329{
    5330 SCIP_SOL* solcopy;
    5331
    5332 assert(reopt != NULL);
    5333 assert(reopt->run-1 >= 0);
    5334 assert(sol != NULL);
    5335 assert(blkmem != NULL);
    5336 assert(set != NULL);
    5337 assert(stat != NULL);
    5338 assert(origprimal != NULL);
    5339
    5340 SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, origprimal, sol) );
    5341 reopt->prevbestsols[reopt->run-1] = solcopy;
    5342
    5343 /* store a global constraint that cutsoff the solution */
    5344 if( set->reopt_sepabestsol )
    5345 {
    5346 SCIP_CALL( separateSolution(reopt, blkmem, set, stat, sol, vars, nvars) );
    5347 }
    5348
    5349 return SCIP_OKAY;
    5350}
    5351
    5352/** add a new iteration after changing the objective function */
    5354 SCIP_REOPT* reopt, /**< reoptimization data sturcture */
    5355 SCIP_SET* set, /**< global SCIP settings */
    5356 BMS_BLKMEM* blkmem, /**< block memory */
    5357 SCIP_VAR** origvars, /**< original problem variables */
    5358 int norigvars, /**< number of original variables */
    5359 int size /**< number of expected solutions */
    5360 )
    5361{
    5362 assert(reopt != NULL);
    5363 assert(set != NULL);
    5364 assert(blkmem != NULL);
    5365 assert(origvars != NULL);
    5366
    5367 /* increase number of runs */
    5368 ++reopt->run;
    5369
    5370 /* check memory */
    5371 SCIP_CALL( ensureRunSize(reopt, set, reopt->run, blkmem) );
    5372
    5373 /* allocate memory */
    5374 reopt->soltree->solssize[reopt->run-1] = size;
    5375 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->soltree->sols[reopt->run-1], size) ); /*lint !e866*/
    5376
    5377 /* reset flag */
    5378 reopt->objhaschanged = FALSE;
    5379
    5380 /* save the objective function */
    5381 SCIP_CALL( reoptSaveNewObj(reopt, set, blkmem, origvars, norigvars) );
    5382
    5383 resetStats(reopt);
    5384
    5385 return SCIP_OKAY;
    5386}
    5387
    5388/** get the number of checked solutions during the reoptimization process */
    5390 SCIP_REOPT* reopt /**< reoptimization data structure */
    5391 )
    5392{
    5393 assert(reopt != NULL);
    5394
    5395 return reopt->ncheckedsols;
    5396}
    5397
    5398/** update the number of checked solutions during the reoptimization process */
    5400 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5401 int ncheckedsols /**< number of updated solutions */
    5402 )
    5403{
    5404 assert(reopt != NULL);
    5405
    5406 reopt->ncheckedsols += ncheckedsols;
    5407}
    5408
    5409/** get the number of checked solutions during the reoptimization process */
    5411 SCIP_REOPT* reopt /**< reoptimization data structure */
    5412 )
    5413{
    5414 assert(reopt != NULL);
    5415
    5416 return reopt->nimprovingsols;
    5417}
    5418
    5419/** update the number of checked solutions during the reoptimization process */
    5421 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5422 int nimprovingsols /**< number of improving solutions */
    5423 )
    5424{
    5425 assert(reopt != NULL);
    5426
    5427 reopt->nimprovingsols += nimprovingsols;
    5428}
    5429
    5430/** returns number of solutions stored in the solution tree of a given run */
    5432 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5433 int run /**< number of the run (1,2,..) */
    5434 )
    5435{
    5436 assert(reopt != NULL);
    5437 assert(0 < run && run <= reopt->runsize);
    5438
    5439 if( reopt->soltree->sols[run-1] == NULL )
    5440 return 0;
    5441 else
    5442 return reopt->soltree->nsols[run-1];
    5443}
    5444
    5445/** returns number of all solutions of all runs */
    5447 SCIP_REOPT* reopt /**< reoptimization data structure */
    5448 )
    5449{
    5450 int nsols = 0;
    5451
    5452 assert(reopt != NULL);
    5453
    5454 for( int r = 0; r < reopt->run; ++r )
    5455 nsols += reopt->soltree->nsols[r];
    5456
    5457 return nsols;
    5458}
    5459
    5460/** return the stored solutions of a given run */
    5462 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5463 int run, /**< number of the run (1,2,...) */
    5464 SCIP_SOL** sols, /**< array of solutions to fill */
    5465 int solssize, /**< length of the array */
    5466 int* nsols /**< pointer to store the number of added solutions */
    5467 )
    5468{
    5469 assert(reopt != NULL);
    5470 assert(run > 0 && run <= reopt->run);
    5471 assert(sols != NULL);
    5472
    5473 assert(solssize > 0);
    5474 assert(nsols != NULL);
    5475 *nsols = 0;
    5476
    5477 for( int s = 0; s < reopt->soltree->nsols[run-1]; ++s )
    5478 {
    5479 if( !reopt->soltree->sols[run-1][s]->updated )
    5480 ++(*nsols);
    5481 }
    5482
    5483 if( solssize < (*nsols) )
    5484 return SCIP_OKAY;
    5485
    5486 (*nsols) = 0;
    5487 for( int s = 0; s < reopt->soltree->nsols[run-1]; ++s )
    5488 {
    5489 if( !reopt->soltree->sols[run-1][s]->updated )
    5490 {
    5491 sols[*nsols] = reopt->soltree->sols[run-1][s]->sol;
    5492 reopt->soltree->sols[run-1][s]->updated = TRUE;
    5493 ++(*nsols);
    5494 }
    5495 }
    5496
    5497 return SCIP_OKAY;
    5498}
    5499
    5500/** returns the number of saved solutions overall runs */
    5502 SCIP_REOPT* reopt /**< reoptimization data structure */
    5503 )
    5504{
    5505 int nsavedsols = 0;
    5506
    5507 assert(reopt != NULL);
    5508 assert(reopt->soltree->root != NULL);
    5509
    5510 if( reopt->soltree->root->child != NULL )
    5511 nsavedsols = soltreeNInducedSols(reopt->soltree->root);
    5512
    5513 return nsavedsols;
    5514}
    5515
    5516/** check if the reoptimization process should be (locally) restarted.
    5517 *
    5518 * First, we check whether the current node is the root node, e.g., node == NULL. in this case, we do not need to calculate
    5519 * the similarity again. we trigger a restart if
    5520 * 1. the objective function has changed too much
    5521 * 2. the number of stored nodes is exceeded
    5522 * 3. the last n optimal solutions were found by heur_reoptsols (in this case, the stored tree was only needed to
    5523 * prove the optimality and this can be probably faster by solving from scratch)
    5524 *
    5525 * If the current node is different to the root node we calculate the local similarity, i.e., exclude all variable
    5526 * that are already fixed by bounding.
    5527 */
    5529 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5530 SCIP_SET* set, /**< global SCIP settings */
    5531 BMS_BLKMEM* blkmem, /**< block memory */
    5532 SCIP_NODE* node, /**< current node of the branch and bound tree (or NULL) */
    5533 SCIP_VAR** transvars, /**< transformed problem variables */
    5534 int ntransvars, /**< number of transformed problem variables */
    5535 SCIP_Bool* restart /**< pointer to store if the reoptimization process should be restarted */
    5536 )
    5537{
    5538 SCIP_Real sim = 1.0;
    5539
    5540 assert(reopt != NULL);
    5541 assert(set != NULL);
    5542 assert(blkmem != NULL);
    5543 assert(transvars != NULL);
    5544 assert(ntransvars >= 0);
    5545 assert(restart != NULL);
    5546
    5547 *restart = FALSE;
    5548
    5549 /* check if the whole reoptimization process should start from scratch */
    5550 if( node == NULL )
    5551 {
    5552 /* compute the similarity to the objective function of the first run after restarting */
    5553 if( reopt->run > 1 && set->reopt_objsimdelay > -1.0 )
    5554 {
    5555 sim = reoptSimilarity(reopt, set, reopt->run-1, MAX(0, reopt->lastrestart-1), transvars, ntransvars);
    5556
    5557 if( sim == SCIP_INVALID ) /*lint !e777*/
    5558 return SCIP_INVALIDRESULT;
    5559 }
    5560
    5561 /* check similarity */
    5562 if( SCIPsetIsFeasLT(set, sim, set->reopt_objsimdelay) )
    5563 {
    5564 SCIPsetDebugMsg(set, "-> restart reoptimization (objective functions are not similar enough)\n");
    5565 *restart = TRUE;
    5566 }
    5567 /* check size of the reoptimization tree */
    5568 else if( reopt->reopttree->nreoptnodes > set->reopt_maxsavednodes )
    5569 {
    5570 SCIPsetDebugMsg(set, "-> restart reoptimization (node limit reached)\n");
    5571 *restart = TRUE;
    5572 }
    5573 /* check if the tree was only needed to prove optimality */
    5574 else if( reopt->noptsolsbyreoptsol >= set->reopt_forceheurrestart )
    5575 {
    5576 SCIPsetDebugMsg(set, "-> restart reoptimization (found last %d optimal solutions by <reoptsols>)\n",
    5577 reopt->noptsolsbyreoptsol);
    5578 reopt->noptsolsbyreoptsol = 0;
    5579 *restart = TRUE;
    5580 }
    5581
    5582 if( *restart )
    5583 {
    5584 /* trigger a restart */
    5585 SCIP_CALL( reoptRestart(reopt, set, blkmem) );
    5586 }
    5587 }
    5588 /* check for a local restart, ie, start the solving process of an inner node from scatch */
    5589 else
    5590 {
    5591 SCIP_CALL( reoptCheckLocalRestart(reopt, set, blkmem, node, transvars, ntransvars, restart) );
    5592 }
    5593 return SCIP_OKAY;
    5594}
    5595
    5596/** returns the similarity to the previous objective function, if no exist return -2.0 */
    5598 SCIP_REOPT* reopt /**< reoptimization data structure */
    5599 )
    5600{
    5601 assert(reopt != NULL);
    5602 return reopt->simtolastobj;
    5603}
    5604
    5605/** returns the similarity to the first objective different to the zero-function function, if no exist return -2.0 */
    5607 SCIP_REOPT* reopt /**< reoptimization data structure */
    5608 )
    5609{
    5610 assert(reopt != NULL);
    5611 return reopt->simtofirstobj;
    5612}
    5613
    5614/** return the similarity between two of objective functions of two given runs */
    5616 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5617 SCIP_SET* set, /**< global SCIP settings */
    5618 int run1, /**< number of the first run */
    5619 int run2, /**< number of the second run */
    5620 SCIP_VAR** origvars, /**< original problem variables */
    5621 int norigvars /**< number of original problem variables */
    5622 )
    5623{
    5624 assert(reopt != NULL);
    5625 assert(run1 > 0 && run1 <= reopt->run);
    5626 assert(run2 > 0 && run2 <= reopt->run);
    5627 assert(origvars != NULL);
    5628 assert(norigvars >= 0);
    5629
    5630 return reoptSimilarity(reopt, set, run1-1, run2-1, origvars, norigvars);
    5631}
    5632
    5633/** returns the best solution of the last run */
    5635 SCIP_REOPT* reopt /**< reoptimization data structure */
    5636 )
    5637{
    5638 assert(reopt != NULL);
    5639 assert(reopt->prevbestsols != NULL);
    5640
    5641 if( reopt->run-2 < 0 )
    5642 return NULL;
    5643 else
    5644 return reopt->prevbestsols[reopt->run-2];
    5645}
    5646
    5647/** returns the node of the reoptimization tree corresponding to the unique @p id */
    5649 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5650 unsigned int id /**< unique id */
    5651 )
    5652{
    5653 assert(reopt != NULL);
    5654 assert(reopt->reopttree != NULL);
    5655 assert(id < reopt->reopttree->reoptnodessize);
    5656 assert(reopt->reopttree->reoptnodes[id] != NULL);
    5657
    5658 return reopt->reopttree->reoptnodes[id];
    5659}
    5660
    5661/** returns the coefficient of variable with index @p idx in run @p run */
    5663 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5664 int run, /**< number of the run (1,2,...) */
    5665 int idx /**< index of original variable */
    5666 )
    5667{
    5668 assert(reopt != NULL);
    5669 assert(0 < run && run <= reopt->runsize);
    5670
    5671 return reopt->objs[run-1][idx];
    5672}
    5673
    5674/** return the best solution of a given run.
    5675 *
    5676 * @note the returned solution is part of the original space.
    5677 */
    5679 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5680 int run /**< number of the run (1,2,...) */
    5681 )
    5682{
    5683 assert(reopt != NULL);
    5684 assert(0 < run && run <= reopt->run);
    5685
    5686 return reopt->prevbestsols[run-1];
    5687}
    5688
    5689/** reset solving specific parameters */
    5691 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5692 SCIP_SET* set, /**< global SCIP settings */
    5693 BMS_BLKMEM* blkmem /**< block memory */
    5694 )
    5695{
    5696 assert(reopt != NULL);
    5697 assert(set != NULL);
    5698 assert(blkmem != NULL);
    5699
    5700 /* clean addedconss array */
    5701 for( int c = 0; c < reopt->naddedconss; ++c )
    5702 {
    5703 SCIP_CONS* cons;
    5704
    5705 cons = reopt->addedconss[c];
    5706 assert(cons != NULL);
    5707
    5708#ifdef SCIP_MORE_DEBUG
    5709 SCIPsetDebugMsg(set, "release cons <%s> from reoptimization data\n", SCIPconsGetName(cons));
    5710#endif
    5711
    5712 SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
    5713 reopt->addedconss[c] = NULL;
    5714 }
    5715
    5716 reopt->naddedconss = 0;
    5717 reopt->consadded = FALSE;
    5718 reopt->objhaschanged = FALSE;
    5719
    5720 return SCIP_OKAY;
    5721}
    5722
    5723/** reset marks of stored solutions to not updated */
    5725 SCIP_REOPT* reopt /**< reoptimization data structure */
    5726 )
    5727{
    5728 SCIP_SOLNODE* child;
    5729
    5730 assert(reopt != NULL);
    5731 assert(reopt->soltree != NULL);
    5732 assert(reopt->soltree->root != NULL);
    5733
    5734 child = reopt->soltree->root->child;
    5735
    5736 /* traverse through the list */
    5737 while( child != NULL )
    5738 {
    5739 soltreeResetMarks(child);
    5740 child = child->sibling;
    5741 }
    5742}
    5743
    5744/** returns the number of stored nodes in the subtree induced by @p node */
    5746 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5747 SCIP_NODE* node /**< node of the search tree */
    5748 )
    5749{
    5750 unsigned int id;
    5751
    5752 assert(reopt != NULL);
    5753
    5754 if( node == NULL || SCIPnodeGetDepth(node) == 0 )
    5755 return reopt->reopttree->nreoptnodes;
    5756
    5757 id = SCIPnodeGetReoptID(node);
    5758 assert(id < reopt->reopttree->reoptnodessize);
    5759
    5760 /* set the id to -1 if the node is not part of the reoptimization tree */
    5761 if( SCIPnodeGetDepth(node) > 0 && id == 0 )
    5762 return 0;
    5763
    5764 assert(0 < id && id < reopt->reopttree->reoptnodessize);
    5765
    5766 return reopttreeGetNNodes(reopt->reopttree, id);
    5767}
    5768
    5769/* ---------------- methods of general reoptimization nodes ---------------- */
    5770
    5771/** In debug mode, the following methods are implemented as function calls to ensure
    5772 * type validity.
    5773 * In optimized mode, the methods are implemented as defines to improve performance.
    5774 * However, we want to have them in the library anyways, so we have to undef the defines.
    5775 */
    5776
    5777#undef SCIPreoptnodeGetNVars
    5778#undef SCIPreoptnodeGetNConss
    5779#undef SCIPreoptnodeGetNDualBoundChgs
    5780#undef SCIPreoptnodeGetNChildren
    5781#undef SCIPreoptnodeGetLowerbound
    5782#undef SCIPreoptnodeGetType
    5783
    5784/** returns the number of bound changes stored in the reopttree at ID id */
    5786 SCIP_REOPTNODE* reoptnode /**< node of the reopttree */
    5787 )
    5788{
    5789 assert(reoptnode != NULL);
    5790
    5791 return reoptnode->nvars + reoptnode->nafterdualvars;
    5792}
    5793
    5794/** returns the number of bound changes at the node stored at ID id */
    5796 SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
    5797 )
    5798{
    5799 assert(reoptnode != NULL);
    5800
    5801 return reoptnode->nconss;
    5802}
    5803
    5804/** returns the number of stored bound changes based on dual information in the reopttree at ID id */
    5806 SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
    5807 )
    5808{
    5809 assert(reoptnode != NULL);
    5810
    5811 if( reoptnode->dualredscur == NULL )
    5812 return 0;
    5813 else
    5814 return reoptnode->dualredscur->nvars;
    5815}
    5816
    5817/** returns the number of child nodes of @p reoptnode */
    5819 SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
    5820 )
    5821{
    5822 assert(reoptnode != NULL);
    5823
    5824 return reoptnode->nchilds;
    5825}
    5826
    5827/** return the lower bound stored at @p ID id */
    5829 SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
    5830 )
    5831{
    5832 assert(reoptnode != NULL);
    5833
    5834 return reoptnode->lowerbound;
    5835}
    5836
    5837/** returns the type of the @p reoptnode */
    5839 SCIP_REOPTNODE* reoptnode /**< node of the reoptimization tree */
    5840 )
    5841{
    5842 assert(reoptnode != NULL);
    5843
    5844 return (SCIP_REOPTTYPE)reoptnode->reopttype;
    5845}
    5846
    5847/** returns all added constraints at ID id */
    5849 SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
    5850 SCIP_VAR*** vars, /**< 2-dim array of variables */
    5851 SCIP_Real** bounds, /**< 2-dim array of bounds */
    5852 SCIP_BOUNDTYPE** boundtypes, /**< 2-dim array of boundtypes */
    5853 int mem, /**< allocated memory for constraints */
    5854 int* nconss, /**< pointer to store the number of constraints */
    5855 int* nvars /**< pointer to store the number of variables */
    5856 )
    5857{
    5858 assert(reoptnode != NULL);
    5859 assert(vars != NULL);
    5860 assert(bounds != NULL);
    5861 assert(boundtypes != NULL);
    5862 assert(nvars != NULL);
    5863 assert(nconss != NULL);
    5864
    5865 (*nconss) = reoptnode->nconss;
    5866
    5867 if( mem < *nconss )
    5868 return;
    5869
    5870 for( int c = 0; c < *nconss; ++c )
    5871 {
    5872 assert(vars[c] != NULL);
    5873 assert(bounds[c] != NULL);
    5874
    5875 vars[c] = reoptnode->conss[c]->vars;
    5876 bounds[c] = reoptnode->conss[c]->vals;
    5877 boundtypes[c] = reoptnode->conss[c]->boundtypes;
    5878 nvars[c] = reoptnode->conss[c]->nvars;
    5879 }
    5880}
    5881
    5882/** set the parent id */
    5884 SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
    5885 unsigned int parentid /**< id of the parent node */
    5886 )
    5887{
    5888 assert(reoptnode != NULL);
    5889 assert(parentid <= 536870911); /* id can be at most 2^29 - 1 */
    5890
    5891 reoptnode->parentID = parentid;
    5892}
    5893
    5894/** returns the number of leaf nodes of the subtree induced by @p node (of the whole tree if node == NULL) */
    5896 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5897 SCIP_NODE* node /**< node of the search tree (or NULL) */
    5898 )
    5899{
    5900 int nleaves = 0;
    5901 unsigned int id;
    5902
    5903 assert(reopt != NULL);
    5904
    5905 id = (node == NULL) ? 0 : SCIPnodeGetReoptID(node);
    5906 assert(id < reopt->reopttree->reoptnodessize);
    5907
    5908 /* return if the node is not part of the reoptimization tree */
    5909 if( node != NULL && SCIPnodeGetDepth(node) > 0 && id == 0 )
    5910 return nleaves;
    5911
    5912 for( int i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
    5913 {
    5914 unsigned int childid;
    5915
    5916 childid = reopt->reopttree->reoptnodes[id]->childids[i]; /*lint !e713*/
    5917 assert(childid < reopt->reopttree->reoptnodessize);
    5918
    5919 if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
    5920 ++nleaves;
    5921 else
    5922 nleaves += reoptGetNLeaves(reopt, childid);
    5923 }
    5924
    5925 return nleaves;
    5926}
    5927
    5928/** save information that given node is infeasible */
    5930 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5931 SCIP_SET* set, /**< global SCIP settings */
    5932 BMS_BLKMEM* blkmem, /**< block memory */
    5933 SCIP_NODE* node /**< node of the search tree */
    5934 )
    5935{
    5936 assert(reopt != NULL);
    5937 assert(set != NULL);
    5938 assert(blkmem != NULL);
    5939 assert(node != NULL);
    5940
    5941 if( set->reopt_sepaglbinfsubtrees )
    5942 {
    5943 SCIP_CALL( saveGlobalCons(reopt, set, blkmem, node, REOPT_CONSTYPE_CUT) );
    5944 }
    5945
    5946 ++reopt->reopttree->ninfnodes;
    5947 ++reopt->reopttree->ntotalinfnodes;
    5948
    5949 return SCIP_OKAY;
    5950}
    5951
    5952/** check the reason for cut off a node and if necessary store the node */
    5954 SCIP_REOPT* reopt, /**< reoptimization data structure */
    5955 SCIP_SET* set, /**< global SCIP settings */
    5956 BMS_BLKMEM* blkmem, /**< block memory */
    5957 SCIP_NODE* node, /**< node of the search tree */
    5958 SCIP_EVENTTYPE eventtype, /**< eventtype */
    5959 SCIP_LP* lp, /**< LP data */
    5960 SCIP_LPSOLSTAT lpsolstat, /**< solution status of the LP */
    5961 SCIP_Bool isrootnode, /**< the node is the root */
    5962 SCIP_Bool isfocusnode, /**< the node is the current focus node */
    5963 SCIP_Real lowerbound, /**< lower bound of the node */
    5964 int effectiverootdepth /**< effective root depth */
    5965 )
    5966{
    5967 SCIP_Bool strongbranched;
    5968
    5969 assert(reopt != NULL);
    5970 assert(set != NULL);
    5971 assert(blkmem != NULL);
    5972 assert(lp != NULL);
    5973 assert(node != NULL);
    5974 assert(eventtype == SCIP_EVENTTYPE_NODEBRANCHED || eventtype == SCIP_EVENTTYPE_NODEFEASIBLE || eventtype == SCIP_EVENTTYPE_NODEINFEASIBLE);
    5975
    5976 if( reopt->lastseennode == SCIPnodeGetNumber(node) )
    5977 return SCIP_OKAY;
    5978
    5979 /* we do not want to store probing node */
    5981 return SCIP_OKAY;
    5982
    5983 reopt->lastseennode = SCIPnodeGetNumber(node);
    5984
    5985 SCIPsetDebugMsg(set, "catch event %" SCIP_EVENTTYPE_FORMAT " for node %lld (type:%d)\n", eventtype, SCIPnodeGetNumber(node), SCIPnodeGetType(node));
    5986
    5987 /* case 1: the current node is the root node
    5988 * we can skip if the root is (in)feasible or branched w/o bound
    5989 * changes based on dual information.
    5990 *
    5991 * case 2: we need to store the current node if it contains
    5992 * bound changes based on dual information or is a leave node
    5993 */
    5994 if( isrootnode )
    5995 {
    5996 if( SCIPreoptGetNDualBndchgs(reopt, node) > 0 )
    5997 {
    5998 goto CHECK;
    5999 }
    6000 else if( eventtype == SCIP_EVENTTYPE_NODEBRANCHED )
    6001 {
    6002 /* store or update the information */
    6003 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_TRANSIT, FALSE, isrootnode, lowerbound) );
    6004 }
    6005 else if( eventtype == SCIP_EVENTTYPE_NODEFEASIBLE )
    6006 {
    6007 /* delete saved dual information which would lead to split the node in a further iteration */
    6008 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    6009
    6010 /* store or update the information */
    6011 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_FEASIBLE, FALSE, isrootnode, lowerbound) );
    6012 }
    6013 else if( eventtype == SCIP_EVENTTYPE_NODEINFEASIBLE )
    6014 {
    6015 /* delete saved dual information which would lead to split the node in a further iteration */
    6016 SCIP_CALL( SCIPreoptResetDualBndchgs(reopt, node, blkmem) );
    6017
    6019 {
    6020 SCIP_Real cutoffbound = SCIPlpGetCutoffbound(lp);
    6021 lowerbound = MIN(lowerbound, cutoffbound);
    6022 }
    6023
    6024 /* store or update the information */
    6025 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, reopt->currentnode == 1 ? SCIP_REOPTTYPE_INFSUBTREE : SCIP_REOPTTYPE_PRUNED, FALSE,
    6026 isrootnode, lowerbound) );
    6027 }
    6028
    6029 assert(reopt->currentnode == -1);
    6030 assert(reopt->dualreds == NULL || reopt->dualreds->nvars == 0);
    6031
    6032 return SCIP_OKAY;
    6033 }
    6034
    6035 CHECK:
    6036
    6037 if( effectiverootdepth == SCIPnodeGetDepth(node) )
    6038 strongbranched = SCIPreoptGetNDualBndchgs(reopt, node) > 0 ? TRUE : FALSE;
    6039 else
    6040 strongbranched = SCIPnodeGetNDualBndchgs(node) > 0 ? TRUE : FALSE;
    6041
    6042 SCIPsetDebugMsg(set, "check the reason of cutoff for node %lld:\n", SCIPnodeGetNumber(node));
    6043 SCIPsetDebugMsg(set, " -> focusnode : %s\n", isfocusnode ? "yes" : "no");
    6044 SCIPsetDebugMsg(set, " -> depth : %d (eff. %d)\n", SCIPnodeGetDepth(node), effectiverootdepth);
    6045 SCIPsetDebugMsg(set, " -> strong branched : %s\n", strongbranched ? "yes" : "no");
    6046 SCIPsetDebugMsg(set, " -> LP lpsolstat : %d\n", lpsolstat);
    6047
    6048 switch( eventtype )
    6049 {
    6051 /* current node has to be the eventnode */
    6052 assert(isfocusnode);
    6053
    6054 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_FEASIBLE);
    6055
    6056 /* delete strong branching information of some exists */
    6057 deleteLastDualBndchgs(reopt);
    6058
    6059 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_FEASIBLE, FALSE, isrootnode, lowerbound) );
    6060 break;
    6061
    6063 /* We have to check if the current node is the event node.
    6064 * if the current node is not the event node, we have to save this node, else we have to
    6065 * look at LP lpsolstat and decide.
    6066 */
    6067 if( isfocusnode )
    6068 {
    6069 /* An after-branch heuristic says NODEINFEASIBLE, maybe the cutoff bound is reached.
    6070 * because the node is already branched we have all children and can delete this node.
    6071 */
    6072 if( SCIPnodeGetNumber(node) == reopt->lastbranched )
    6073 {
    6074 deleteLastDualBndchgs(reopt);
    6075 break;
    6076 }
    6077
    6078 /* If the node is strong branched, we possibly detect an infeasible subtree;
    6079 * otherwise, the whole node is either infeasible or exceeds the cutoff bound.
    6080 */
    6081 if( strongbranched )
    6082 {
    6083 /* 1. the LP is infeasible: the (sub-)node is infeasible and can be discarded
    6084 * because the LP proves infeasibility. We have to store an infeasible subtree separated by a constraint.
    6085 * 2. the LP exceeds the objective limit or was not solved, we have to store the node and can delete the
    6086 * strong branching information
    6087 */
    6088 if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
    6089 {
    6090 /* add a dummy variable, because the bound changes were not global in the sense of effective root depth */
    6091 if( SCIPnodeGetDepth(node) > effectiverootdepth )
    6092 {
    6093 SCIP_CALL( SCIPreoptAddDualBndchg(reopt, set, blkmem, node, NULL, 0.0, 1.0) );
    6094 }
    6095
    6096 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_INFSUBTREE);
    6097 SCIPsetDebugMsg(set, " -> new constype : %d\n", REOPT_CONSTYPE_INFSUBTREE);
    6098
    6099 /* save the node as a strong branched node */
    6100 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_INFSUBTREE, FALSE, isrootnode, lowerbound) );
    6101 }
    6102 else
    6103 {
    6104 assert( lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT || lpsolstat == SCIP_LPSOLSTAT_OPTIMAL || lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED);
    6105
    6106 /* delete strong branching information if some exists */
    6107 deleteLastDualBndchgs(reopt);
    6108
    6109 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_PRUNED);
    6110 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
    6111 }
    6112 }
    6113 else
    6114 {
    6115 /* 1. the LP is infeasible: the whole node is infeasible and can be discarded
    6116 * 2. the LP was not solved or exceeds the objective limit, we have to store the node
    6117 */
    6118 if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE )
    6119 {
    6120 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_INFSUBTREE);
    6121 SCIP_CALL( SCIPreoptAddInfNode(reopt, set, blkmem, node) );
    6122 }
    6123 else
    6124 {
    6125 assert(lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED || lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT
    6126 || lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
    6127
    6128 if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
    6129 {
    6130 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
    6131 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, FALSE, isrootnode, lowerbound) );
    6132 }
    6133 else
    6134 {
    6135 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_PRUNED);
    6136 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
    6137 }
    6138 }
    6139 }
    6140 }
    6141 else
    6142 {
    6143 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_PRUNED);
    6144
    6145 /* if the node was created by branch_nodereopt, nothing happens */
    6146 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_PRUNED, FALSE, isrootnode, lowerbound) );
    6147 }
    6148 break;
    6149
    6151 /* current node has to be the eventnode */
    6152 assert(isfocusnode);
    6153
    6154 reopt->lastbranched = SCIPnodeGetNumber(node);
    6155
    6156 /* we have to check the depth of the current node. if the depth is equal to the effective
    6157 * root depth, then all information about bound changes based on dual information already exists,
    6158 * else we have to look at the domchg-data-structure.
    6159 */
    6160 if (SCIPnodeGetDepth(node) == effectiverootdepth)
    6161 {
    6162 /* Save the node if there are added constraints, because this means the node is a copy create by the
    6163 * reoptimization plug-in and contains at least one logic-or-constraint */
    6164 if( strongbranched )
    6165 {
    6166 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_STRBRANCHED);
    6167 SCIPsetDebugMsg(set, " -> new constype : %d\n", REOPT_CONSTYPE_DUALREDS);
    6168 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_STRBRANCHED, FALSE, isrootnode, lowerbound) );
    6169 }
    6170 else if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
    6171 {
    6172 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
    6173 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, FALSE, isrootnode, lowerbound) );
    6174 }
    6175 else
    6176 {
    6177 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_TRANSIT);
    6178 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_TRANSIT, FALSE, isrootnode, lowerbound) );
    6179 }
    6180 }
    6181 else
    6182 {
    6183 /* we only branch on binary variables and var == NULL indicates memory allocation w/o saving information.
    6184 *
    6185 * we have to do this in the following order:
    6186 * 1) all bound-changes are local, thats way we have to mark the node to include bound changes based
    6187 * on dual information.
    6188 * 2) save or update the node.
    6189 */
    6190 if( strongbranched )
    6191 {
    6192 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_STRBRANCHED);
    6193 SCIPsetDebugMsg(set, " -> new constype : %d\n", REOPT_CONSTYPE_DUALREDS);
    6194 SCIP_CALL( SCIPreoptAddDualBndchg(reopt, set, blkmem, node, NULL, 0.0, 1.0) );
    6195 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_STRBRANCHED, FALSE, isrootnode, lowerbound) );
    6196 }
    6197 else if( SCIPreoptGetNAddedConss(reopt, node) > 0 )
    6198 {
    6199 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_LOGICORNODE);
    6200 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_LOGICORNODE, FALSE, isrootnode, lowerbound) );
    6201 }
    6202 else
    6203 {
    6204 SCIPsetDebugMsg(set, " -> new reopttype : %d\n", SCIP_REOPTTYPE_TRANSIT);
    6205 SCIP_CALL( addNode(reopt, set, lp, blkmem, node, SCIP_REOPTTYPE_TRANSIT, FALSE, isrootnode, lowerbound) );
    6206 }
    6207 }
    6208 break;
    6209
    6210 default:
    6211 break;
    6212 }
    6213
    6214 assert(reopt->currentnode == -1);
    6215 assert(reopt->dualreds == NULL || reopt->dualreds->nvars == 0);
    6216
    6217 return SCIP_OKAY; /*lint !e438*/
    6218}
    6219
    6220/** store bound change based on dual information */
    6222 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6223 SCIP_SET* set, /**< global SCIP settings */
    6224 BMS_BLKMEM* blkmem, /**< block memory */
    6225 SCIP_NODE* node, /**< node of the search tree */
    6226 SCIP_VAR* var, /**< variable */
    6227 SCIP_Real newval, /**< new bound */
    6228 SCIP_Real oldval /**< old bound */
    6229 )
    6230{
    6231 SCIP_Real constant = 0.0;
    6232 SCIP_Real scalar = 1.0;
    6233
    6234 assert(reopt != NULL);
    6235 assert(node != NULL);
    6236
    6237 /* If var == NULL, we save all information by calling SCIPreoptNodeFinished().
    6238 * In that case, all bound changes were not global and we can find them within the
    6239 * domchg data structure.
    6240 * Otherwise, we allocate memory and store the information.
    6241 */
    6242 if( var != NULL )
    6243 {
    6244 SCIP_BOUNDTYPE boundtype;
    6245 int resizelength;
    6246 int allocmem;
    6247
    6248 if( SCIPsetFindBranchrule(set, "relpscost") != NULL )
    6249 {
    6250 SCIP_CALL( SCIPsetGetIntParam(set, "branching/relpscost/maxlookahead", &resizelength) );
    6251 }
    6252 else
    6253 resizelength = 1;
    6254
    6255 if( reopt->dualreds == NULL || reopt->dualreds->varssize == 0 )
    6256 allocmem = DEFAULT_MEM_DUALCONS;
    6257 else
    6258 allocmem = reopt->dualreds->nvars + resizelength;
    6259
    6260 /* allocate memory of necessary */
    6261 SCIP_CALL( checkMemDualCons(reopt, set, blkmem, allocmem) );
    6262
    6263 assert(reopt->dualreds->varssize > 0);
    6264 assert(reopt->dualreds->nvars >= 0);
    6265 assert(reopt->currentnode == -1 || reopt->dualreds->nvars > 0);
    6266 assert((reopt->dualreds->nvars > 0 && reopt->currentnode == SCIPnodeGetNumber(node))
    6267 || reopt->dualreds->nvars == 0);
    6268
    6269 reopt->currentnode = SCIPnodeGetNumber(node);
    6270
    6271 /* transform into the original space and then save the bound change */
    6272 SCIP_CALL( SCIPvarGetOrigvarSum(&var, &scalar, &constant) );
    6273 newval = (newval - constant) / scalar;
    6274 oldval = (oldval - constant) / scalar;
    6275
    6276 assert(SCIPvarIsOriginal(var));
    6277
    6278 if( SCIPsetIsEQ(set, oldval, newval) )
    6279 {
    6280 SCIPerrorMessage("cannot store equal bounds: old = %g, new = %g\n", oldval, newval);
    6281 return SCIP_INVALIDDATA;
    6282 }
    6283
    6284 if( SCIPsetIsLT(set, newval, oldval) )
    6285 boundtype = SCIP_BOUNDTYPE_UPPER;
    6286 else
    6287 boundtype = SCIP_BOUNDTYPE_LOWER;
    6288
    6289 reopt->dualreds->vars[reopt->dualreds->nvars] = var;
    6290 reopt->dualreds->vals[reopt->dualreds->nvars] = newval;
    6291 reopt->dualreds->boundtypes[reopt->dualreds->nvars] = boundtype;
    6292 ++reopt->dualreds->nvars;
    6293
    6294 SCIPsetDebugMsg(set, ">> store %s bound change of <%s>: %g -> %g\n",
    6295 (boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper"), SCIPvarGetName(var), oldval, newval);
    6296
    6297 reopt->dualreds->linear = FALSE;
    6298 }
    6299 else
    6300 {
    6301 assert(reopt->currentnode == -1);
    6302 assert(reopt->dualreds == NULL || reopt->dualreds->nvars == 0);
    6303
    6304 reopt->currentnode = SCIPnodeGetNumber(node);
    6305 }
    6306
    6307 return SCIP_OKAY;
    6308}
    6309
    6310/** returns the number of bound changes based on dual information */
    6312 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6313 SCIP_NODE* node /**< node of the search tree */
    6314 )
    6315{
    6316 int ndualbndchgs = 0;
    6317
    6318 assert(reopt != NULL);
    6319 assert(node != NULL);
    6320
    6321 if( SCIPnodeGetNumber(node) == reopt->currentnode )
    6322 {
    6323 assert(reopt->dualreds != NULL);
    6324 ndualbndchgs = reopt->dualreds->nvars;
    6325 }
    6326
    6327 return ndualbndchgs;
    6328}
    6329
    6330/** returns the child nodes of @p node that need to be reoptimized next or NULL if @p node is a leaf */
    6332 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6333 SCIP_SET* set, /**< global SCIP settings */
    6334 BMS_BLKMEM* blkmem, /**< block memory */
    6335 SCIP_NODE* node, /**< node of the search tree */
    6336 unsigned int* childs, /**< array to store the child ids */
    6337 int childssize, /**< size of the childs array */
    6338 int* nchilds /**< pointer to store the number of child nodes */
    6339 )
    6340{
    6341 SCIP_Bool runagain;
    6342 unsigned int id;
    6343
    6344 assert(reopt != NULL);
    6345 assert(childssize > 0 && childs != NULL);
    6346 assert(nchilds != NULL);
    6347
    6348 (*nchilds) = 0;
    6349
    6350 if( node == NULL )
    6351 id = 0;
    6352 else
    6353 {
    6354 id = SCIPnodeGetReoptID(node);
    6355 assert(id >= 1 || SCIPnodeGetDepth(node) == 0);
    6356 }
    6357
    6358 assert(id < reopt->reopttree->reoptnodessize);
    6359 assert(reopt->reopttree->reoptnodes[id] != NULL);
    6360
    6361 /* check if there are redundant bound changes or infeasible nodes */
    6362 runagain = TRUE;
    6363 while( runagain && reopt->reopttree->reoptnodes[id]->nchilds > 0 )
    6364 {
    6365 SCIP_CALL( dryBranch(reopt, set, blkmem, &runagain, id) );
    6366 }
    6367
    6368 /* return the list of child nodes if some exists; otherwise return NULL */
    6369 if( reopt->reopttree->reoptnodes[id]->childids != NULL && reopt->reopttree->reoptnodes[id]->nchilds > 0 )
    6370 {
    6371 (*nchilds) = reopt->reopttree->reoptnodes[id]->nchilds;
    6372
    6373 if( childssize < *nchilds )
    6374 return SCIP_OKAY;
    6375
    6376 for( int c = 0; c < *nchilds; ++c )
    6377 childs[c] = reopt->reopttree->reoptnodes[id]->childids[c];
    6378 }
    6379
    6380 return SCIP_OKAY;
    6381}
    6382
    6383/** returns all leaves of the subtree induced by @p node */
    6385 SCIP_REOPT* reopt, /**< reoptimization data */
    6386 SCIP_NODE* node, /**< node of the search tree */
    6387 unsigned int* leaves, /**< array to the the ids */
    6388 int leavessize, /**< size of leaves array */
    6389 int* nleaves /**< pointer to store the number of leave node */
    6390 )
    6391{
    6392 unsigned int id;
    6393
    6394 assert(reopt != NULL);
    6395 assert(leavessize > 0 && leaves != NULL);
    6396 assert((*nleaves) >= 0);
    6397
    6398 /* if the given node is we start from the root */
    6399 if( node == NULL )
    6400 id = 0;
    6401 else
    6402 id = SCIPnodeGetReoptID(node);
    6403
    6404 /* return if the node is not part of the reoptimization tree */
    6405 if( id == 0 && node != NULL )
    6406 {
    6407 (*nleaves) = 0;
    6408 return SCIP_OKAY;
    6409 }
    6410
    6411 assert(id < reopt->reopttree->reoptnodessize);
    6412 assert(reopt->reopttree->reoptnodes[id] != NULL);
    6413
    6414 for( int i = 0; i < leavessize; ++i )
    6415 leaves[i] = 0;
    6416
    6417 /* we traverse through all child nodes of the given node an collect all leave nodes of the subtrees induced by them */
    6418 for( int i = 0; i < reopt->reopttree->reoptnodes[id]->nchilds; ++i )
    6419 {
    6420 unsigned int childid;
    6421
    6422 assert(*nleaves + 1 <= leavessize);
    6423
    6424 childid = reopt->reopttree->reoptnodes[id]->childids[i];
    6425 assert(childid < reopt->reopttree->reoptnodessize);
    6426
    6427 /* the node is already a leave */
    6428 if( reopt->reopttree->reoptnodes[childid]->nchilds == 0 )
    6429 {
    6430 leaves[(*nleaves)] = reopt->reopttree->reoptnodes[id]->childids[i];
    6431 ++(*nleaves);
    6432 }
    6433 /* go into the tree induced by the current child node */
    6434 else
    6435 {
    6436 int nleaves2 = 0;
    6437
    6438 SCIP_CALL( reoptGetLeaves(reopt, childid, &leaves[*nleaves], leavessize - (*nleaves), &nleaves2) );
    6439 (*nleaves) += nleaves2;
    6440 }
    6441 }
    6442
    6443 return SCIP_OKAY;
    6444}
    6445
    6446/** add all unprocessed nodes to the reoptimization tree */
    6448 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6449 SCIP_SET* set, /**< global SCIP settings */
    6450 SCIP_LP* lp, /**< current LP */
    6451 BMS_BLKMEM* blkmem, /**< block memory */
    6452 SCIP_NODE** leaves, /**< array of open leave nodes */
    6453 int nleaves, /**< number of open leave nodes */
    6454 SCIP_NODE** childs, /**< array of open children nodes */
    6455 int nchilds, /**< number of open leave nodes */
    6456 SCIP_NODE** siblings, /**< array of open sibling nodes */
    6457 int nsiblings /**< number of open leave nodes */
    6458 )
    6459{
    6460 assert(reopt != NULL);
    6461 assert(set != NULL);
    6462 assert(blkmem != NULL);
    6463 assert(nleaves >= 0);
    6464 assert(nleaves == 0 || leaves != NULL);
    6465 assert(nchilds >= 0);
    6466 assert(nchilds == 0 || childs != NULL);
    6467 assert(nsiblings >= 0);
    6468 assert(nsiblings == 0 || siblings != NULL);
    6469
    6470 SCIPsetDebugMsg(set, "save unprocessed nodes (%d leaves, %d children, %d siblings)\n", nleaves, nchilds, nsiblings);
    6471
    6472 /* save open leaves */
    6473 for( int n = 0; n < nleaves; ++n )
    6474 {
    6475 SCIP_CALL( addNode(reopt, set, lp, blkmem, leaves[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
    6476 SCIPnodeGetLowerbound(leaves[n])) );
    6477 }
    6478
    6479 /* save open children */
    6480 for( int n = 0; n < nchilds; ++n )
    6481 {
    6482 SCIP_CALL( addNode(reopt, set, lp, blkmem, childs[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
    6483 SCIPnodeGetLowerbound(childs[n])) );
    6484 }
    6485
    6486 /* save open siblings */
    6487 for( int n = 0; n < nsiblings; ++n )
    6488 {
    6489 SCIP_CALL( addNode(reopt, set, lp, blkmem, siblings[n], SCIP_REOPTTYPE_PRUNED, FALSE, FALSE,
    6490 SCIPnodeGetLowerbound(siblings[n])) );
    6491 }
    6492
    6493 return SCIP_OKAY;
    6494}
    6495
    6496/** merges the variable history of the current run with the stored history */
    6498 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6499 SCIP_SET* set, /**< global SCIP settings */
    6500 SCIP_STAT* stat, /**< dynamic problem statistics */
    6501 SCIP_VAR** vars, /**< original problem variables */
    6502 int nvars /**< number of original problem variables */
    6503 )
    6504{
    6505 SCIP_VAR* transvar;
    6506 SCIP_Real avginference[2];
    6507 SCIP_Real avgcutoff[2];
    6508 SCIP_Real bestsim;
    6509 int bestrun;
    6510 int idx;
    6511
    6512 assert(reopt != NULL);
    6513 assert(stat != NULL);
    6514 assert(nvars >= 0);
    6515
    6516 if( !set->reopt_storevarhistory )
    6517 return SCIP_OKAY;
    6518
    6519 SCIPsetDebugMsg(set, "start merging variable histories:\n");
    6520
    6521 bestrun = reopt->run-2;
    6522 bestsim = reopt->simtolastobj;
    6523
    6524 /* find the run with the most similar objective */
    6525 for( int r = reopt->run-3; r >= 0 && reopt->objhaschanged && set->reopt_usepscost; --r )
    6526 {
    6527 SCIP_Real sim;
    6528 sim = reoptSimilarity(reopt, set, r, reopt->run-1, vars, nvars);
    6529
    6530 if( sim == SCIP_INVALID ) /*lint !e777*/
    6531 return SCIP_INVALIDRESULT;
    6532
    6533 if( SCIPsetIsGT(set, sim, bestsim) )
    6534 {
    6535 bestsim = sim;
    6536 bestrun = r;
    6537 }
    6538 }
    6539 SCIPverbMessage(set->scip, SCIP_VERBLEVEL_NORMAL, NULL, "run %d has best similarity=%g\n", bestrun, bestsim);
    6540
    6541 /* iterate through all variables and scale the histories */
    6542 for( int v = 0; v < nvars; ++v )
    6543 {
    6544 assert(SCIPvarIsOriginal(vars[v]));
    6545
    6546 transvar = SCIPvarGetTransVar(vars[v]);
    6547 assert(transvar != NULL);
    6548
    6549 /* skip variable that are not active */
    6550 if( !SCIPvarIsActive(transvar) )
    6551 continue;
    6552
    6553 idx = SCIPvarGetIndex(vars[v]);
    6554 assert(0 <= idx && idx <= nvars);
    6555
    6556 /* set the updated history for both directions */
    6557 for( int d = 0; d <= 1; ++d )
    6558 {
    6559 if( set->reopt_usepscost && !SCIPsetIsZero(set, reopt->varhistory[bestrun][idx]->pscostcount[d])
    6560 && SCIPsetIsGT(set, bestsim, 0.985) ) /* 0.985 is a magic number determined in some experiments */
    6561 {
    6562 transvar->history->pscostcount[d] = 1.0;
    6563 transvar->history->pscostweightedmean[d] = reopt->varhistory[bestrun][idx]->pscostweightedmean[d];
    6564 transvar->history->pscostvariance[d] = 0.0;
    6565 SCIPsetDebugMsg(set, "-> <%s> pscosts %4s: count=%g weightedmean=%g variance=%g\n", SCIPvarGetName(transvar),
    6566 (d == 0 ? "down" : "up"), transvar->history->pscostcount[d], transvar->history->pscostweightedmean[d],
    6567 transvar->history->pscostvariance[d]);
    6568 }
    6569
    6571
    6572 /* inference score */
    6573 avginference[d] = SCIPhistoryGetAvgInferences(reopt->varhistory[reopt->run-2][idx], (SCIP_BRANCHDIR)d);
    6574 SCIPhistoryIncInferenceSum(transvar->history, (SCIP_BRANCHDIR)d, avginference[d]);
    6575
    6576 /* cutoff score */
    6577 avgcutoff[d] = SCIPhistoryGetAvgCutoffs(reopt->varhistory[reopt->run-2][idx], (SCIP_BRANCHDIR)d);
    6578 SCIPhistoryIncCutoffSum(transvar->history, (SCIP_BRANCHDIR)d, avgcutoff[d]);
    6579
    6580 SCIPsetDebugMsg(set, "-> <%s> %4s scores: inf=%g cutoff=%g\n", SCIPvarGetName(transvar),
    6581 (d == 0 ? "down" : "up"), avginference[d], avgcutoff[d]);
    6582 }
    6583 }
    6584
    6585 return SCIP_OKAY;
    6586}
    6587
    6588/** updates the variable history */
    6590 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6591 SCIP_SET* set, /**< global SCIP settings */
    6592 SCIP_STAT* stat, /**< dynamic problem statistics */
    6593 BMS_BLKMEM* blkmem, /**< block memory */
    6594 SCIP_VAR** vars, /**< original variable array */
    6595 int nvars /**< number of original variables */
    6596 )
    6597{
    6598 assert(reopt != NULL);
    6599 assert(stat != NULL);
    6600 assert(blkmem != NULL);
    6601 assert(nvars >= 0);
    6602
    6603 if( !set->reopt_storevarhistory )
    6604 return SCIP_OKAY;
    6605
    6606 SCIPsetDebugMsg(set, "updating variable history\n");
    6607
    6608 if( reopt->varhistory[reopt->run-1] == NULL )
    6609 {
    6610 /* allocate memory */
    6611 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &reopt->varhistory[reopt->run-1], nvars) );
    6612
    6613 for( int v = 0; v < nvars; ++v )
    6614 {
    6615 SCIP_CALL( SCIPhistoryCreate(&(reopt->varhistory[reopt->run-1][v]), blkmem) );
    6616 }
    6617 }
    6618
    6619 /* update the history and scale them */
    6620 for( int v = 0; v < nvars; ++v )
    6621 {
    6622 SCIP_VAR* transvar;
    6623 int idx;
    6624
    6625 assert(SCIPvarIsOriginal(vars[v]));
    6626 idx = SCIPvarGetIndex(vars[v]);
    6627 assert(idx >= 0 && idx < nvars);
    6628
    6629 transvar = SCIPvarGetTransVar(vars[v]);
    6630 assert(transvar != NULL);
    6631
    6632 if( !SCIPvarIsActive(transvar) )
    6633 continue;
    6634
    6635 /* we store the complete history */
    6636 SCIPhistoryReset(reopt->varhistory[reopt->run-1][idx]);
    6637 SCIPhistoryUnite(reopt->varhistory[reopt->run-1][idx], transvar->history, FALSE);
    6638 }
    6639
    6640 return SCIP_OKAY;
    6641}
    6642
    6643/** reset the complete tree and set the given search frontier */
    6645 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6646 SCIP_SET* set, /**< global SCIP settings */
    6647 BMS_BLKMEM* blkmem, /**< block memory */
    6648 SCIP_REOPTNODE** representatives, /**< array of representatives */
    6649 int nrepresentatives, /**< number of representatives */
    6650 SCIP_Bool* success /**< pointer to store if the method was successful */
    6651 )
    6652{
    6653 SCIP_REOPTTREE* reopttree;
    6654 unsigned int id;
    6655
    6656 assert(reopt != NULL);
    6657 assert(set != NULL);
    6658 assert(blkmem != NULL);
    6659 assert(representatives != NULL);
    6660 assert(nrepresentatives > 0);
    6661
    6662 reopttree = reopt->reopttree;
    6663
    6664 /* reset the current search tree */
    6665 SCIP_CALL( reoptResetTree(reopt, set, blkmem, FALSE) );
    6666 assert(reopttree->nreoptnodes == 0);
    6667
    6668 /* create a new root node */
    6669 id = 0;
    6670 SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
    6671
    6672 /* set the reopttype */
    6673 reopttree->reoptnodes[0]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
    6674
    6675 /* add all representatives */
    6676 for( int r = 0; r < nrepresentatives; ++r )
    6677 {
    6678 /* get an empty slot*/
    6679 id = SCIPqueueRemoveUInt(reopttree->openids);
    6680 assert(1 <= id && id < reopttree->reoptnodessize);
    6681 assert(reopttree->reoptnodes[id] == NULL);
    6682
    6683 SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
    6684 assert(reopttree->reoptnodes[id] != NULL);
    6685
    6686 /* set the new node
    6687 * 1. copy all variables, bounds, and boundtypes
    6688 * 2. copy all constraints
    6689 * 3. set the parent relation
    6690 */
    6691 if( representatives[r]->nvars > 0 )
    6692 {
    6693 assert(representatives[r]->nvars <= representatives[r]->varssize);
    6694
    6695 for( int v = 0; v < representatives[r]->nvars; ++v )
    6696 {
    6697 SCIP_CALL( SCIPreoptnodeAddBndchg(reopttree->reoptnodes[id], set, blkmem, representatives[r]->vars[v],
    6698 representatives[r]->varbounds[v], representatives[r]->varboundtypes[v]) );
    6699 }
    6700 }
    6701
    6702 if( representatives[r]->nconss > 0 )
    6703 {
    6704 assert(representatives[r]->nconss <= representatives[r]->consssize);
    6705
    6706 for( int c = 0; c < representatives[r]->nconss; ++c )
    6707 {
    6708 SCIP_CALL( SCIPreoptnodeAddCons(reopttree->reoptnodes[id], set, blkmem, representatives[r]->conss[c]->vars,
    6709 representatives[r]->conss[c]->vals, representatives[r]->conss[c]->boundtypes,
    6710 representatives[r]->conss[c]->lhs, representatives[r]->conss[c]->rhs,
    6711 representatives[r]->conss[c]->nvars, representatives[r]->conss[c]->constype,
    6712 representatives[r]->conss[c]->linear) );
    6713 }
    6714 }
    6715
    6716 reopttree->reoptnodes[id]->parentID = representatives[r]->parentID; /*lint !e732*/
    6717
    6718 assert(reopttree->reoptnodes[id]->parentID == 0);
    6719 assert(reopttree->reoptnodes[id]->nvars >= 0);
    6720 assert(reopttree->reoptnodes[id]->nvars <= reopttree->reoptnodes[id]->varssize);
    6721 assert(reopttree->reoptnodes[id]->nconss >= 0);
    6722
    6723 /* set the reopttype */
    6724 if( reopttree->reoptnodes[id]->nconss == 0 )
    6725 reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LEAF;
    6726 else
    6727 reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LOGICORNODE;
    6728
    6729 /* add the representative as a child of the root */
    6730 SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
    6731 }
    6732
    6733 SCIPsetDebugMsg(set, "-> new tree consists of %d nodes, the root has %d child nodes.\n",
    6734 reopttree->nreoptnodes, reopttree->reoptnodes[0]->nchilds);
    6735
    6736 (*success) = TRUE;
    6737
    6738 return SCIP_OKAY;
    6739}
    6740
    6741/** transforms a set of dual reductions into a linear constraint */
    6742static
    6744 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6745 SCIP_SET* set, /**< global SCIP settings */
    6746 BMS_BLKMEM* blkmem, /**< block memory */
    6747 SCIP_REOPTCONSDATA* consdata, /**< reoptimization constraint data that should represent to set of solutions
    6748 * pruned by the dual reductions */
    6749 SCIP_REOPTCONSDATA* dualreds /**< set of dual reductions */
    6750 )
    6751{
    6752 assert(reopt != NULL);
    6753 assert(set != NULL);
    6754 assert(blkmem != NULL);
    6755 assert(consdata != NULL);
    6756 assert(dualreds != NULL);
    6757
    6758 /* we have to transform the set of bound changes into a linear constraint */
    6759 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vars, dualreds->vars, dualreds->nvars) );
    6760 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &consdata->vals, dualreds->nvars) );
    6761 consdata->boundtypes = NULL;
    6762
    6763 consdata->varssize = dualreds->nvars;
    6764 consdata->nvars = dualreds->nvars;
    6765 consdata->constype = REOPT_CONSTYPE_DUALREDS;
    6766 consdata->linear = TRUE;
    6767
    6768 /* set lhs and rhs */
    6769 consdata->lhs = 1.0;
    6770 consdata->rhs = SCIPsetInfinity(set);
    6771
    6772 for( int v = 0; v < consdata->nvars; ++v )
    6773 {
    6774 assert(consdata->vars[v] != NULL);
    6775
    6776 /* the bound is 0.0, the variable has to appear with a coefficient +1.0 in the constraint, sides do not change */
    6777 if( SCIPsetIsEQ(set, dualreds->vals[v], 0.0) )
    6778 {
    6779 assert(dualreds->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
    6780 consdata->vals[v] = 1.0;
    6781 }
    6782 /* the bound is 1.0, the variable has to appear with a coefficient -1.0 in the constraint, we subtract -1.0 from lhs
    6783 * logicor: sum x_i + ~y_i >= 1
    6784 * <==> sum x_i + (1-y_i) >= 1
    6785 * <==> sum x_i - y_i >= 0
    6786 */
    6787 else
    6788 {
    6789 assert(SCIPsetIsEQ(set, dualreds->vals[v], 1.0));
    6790 assert(dualreds->boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
    6791
    6792 consdata->vals[v] = -1.0;
    6793 consdata->lhs -= 1.0;
    6794 }
    6795 }
    6796
    6797 return SCIP_OKAY;
    6798}
    6799
    6800
    6801/** transforms a set of dual reductions into a bounddisjuction constraint */
    6802static
    6804 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6805 SCIP_SET* set, /**< global SCIP settings */
    6806 BMS_BLKMEM* blkmem, /**< block memory */
    6807 SCIP_REOPTCONSDATA* consdata, /**< reoptimization constraint data that should represent to set of solutions
    6808 * pruned by the dual reductions */
    6809 SCIP_REOPTCONSDATA* dualreds /**< set of dual reductions */
    6810 )
    6811{
    6812 assert(reopt != NULL);
    6813 assert(set != NULL);
    6814 assert(blkmem != NULL);
    6815 assert(consdata != NULL);
    6816 assert(dualreds != NULL);
    6817
    6818 /* we have to transform the set of bound changes into a linear constraint */
    6819 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vars, dualreds->vars, dualreds->nvars) );
    6820 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->vals, dualreds->vals, dualreds->nvars) );
    6821 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &consdata->boundtypes, dualreds->boundtypes, dualreds->nvars) );
    6822
    6823 consdata->varssize = dualreds->nvars;
    6824 consdata->nvars = dualreds->nvars;
    6825 consdata->constype = REOPT_CONSTYPE_DUALREDS;
    6826 consdata->linear = FALSE;
    6827
    6828 /* set lhs and rhs */
    6829 consdata->lhs = SCIP_UNKNOWN;
    6830 consdata->rhs = SCIP_UNKNOWN;
    6831
    6832 for( int v = 0; v < consdata->nvars; ++v )
    6833 {
    6834 SCIP_Real glbbd;
    6835
    6836 assert(consdata->vars[v] != NULL);
    6837
    6838 /* we do the followung to transformations:
    6839 * (a) x <= val ==> (x >= val+1)
    6840 * (b) x >= val ==> (x <= val-1)
    6841 */
    6842 if( consdata->boundtypes[v] == SCIP_BOUNDTYPE_UPPER )
    6843 {
    6844 glbbd = SCIPvarGetUbGlobal(consdata->vars[v]);
    6845 consdata->vals[v] = MIN(consdata->vals[v]+1.0, glbbd);
    6846 }
    6847 else
    6848 {
    6849 assert(dualreds->boundtypes[v] == SCIP_BOUNDTYPE_LOWER);
    6850 glbbd = SCIPvarGetLbGlobal(consdata->vars[v]);
    6851 consdata->vals[v] = MAX(glbbd, consdata->vals[v]-1.0);
    6852 }
    6853 consdata->boundtypes[v] = (SCIP_BOUNDTYPE)(SCIP_BOUNDTYPE_UPPER - consdata->boundtypes[v]); /*lint !e656*/
    6854 }
    6855
    6856 return SCIP_OKAY;
    6857}
    6858
    6859/** splits the root into several nodes and moves the child nodes of the root to one of the created nodes */
    6861 SCIP_REOPT* reopt, /**< reoptimization data structure */
    6862 SCIP_TREE* tree, /**< branch and bound tree */
    6863 SCIP_SET* set, /**< global SCIP settings */
    6864 SCIP_STAT* stat, /**< dynamic SCIP statistics */
    6865 BMS_BLKMEM* blkmem, /**< block memory */
    6866 int* ncreatedchilds, /**< pointer to store the number of created nodes */
    6867 int* naddedconss /**< pointer to store the number added constraints */
    6868 )
    6869{
    6870 SCIP_REOPTTREE* reopttree;
    6871 SCIP_REOPTNODE** reoptnodes;
    6872 SCIP_REOPTCONSDATA* consdata;
    6873 SCIP_VAR** vars;
    6874 SCIP_Real* bounds;
    6875 SCIP_BOUNDTYPE* boundtypes;
    6876 int* perm = NULL;
    6877 unsigned int id;
    6878 int nbndchgs;
    6879 int nchilds;
    6880 int v;
    6881
    6882 assert(reopt != NULL);
    6883 assert(set != NULL);
    6884 assert(stat != NULL);
    6885 assert(blkmem != NULL);
    6886
    6887 reopttree = reopt->reopttree;
    6888 assert(reopttree != NULL);
    6889
    6890 reoptnodes = reopttree->reoptnodes;
    6891 assert(reoptnodes != NULL);
    6892 assert(reoptnodes[0] != NULL);
    6893 assert(reoptnodes[0]->dualreds);
    6894 assert(reoptnodes[0]->reopttype == (unsigned int)SCIP_REOPTTYPE_STRBRANCHED);
    6895
    6896 nchilds = reoptnodes[0]->nchilds;
    6897
    6898 assert(reoptnodes[0]->dualredscur != NULL);
    6899 nbndchgs = reoptnodes[0]->dualredscur->nvars;
    6900
    6901 (*ncreatedchilds) = 0;
    6902 (*naddedconss) = 0;
    6903
    6904 /* create a node with all variables fixed, i.e., reconstruct the root of the last iteration */
    6905
    6906 /* ensure that two free slots are available */
    6907 SCIP_CALL( reopttreeCheckMemory(reopttree, set, blkmem) );
    6908 id = SCIPqueueRemoveUInt(reopttree->openids);
    6909
    6910 assert(0 < id && id < reopt->reopttree->reoptnodessize);
    6911 assert(reoptnodes[id] == NULL || reoptnodes[id]->nvars == 0);
    6912
    6913 /* 1. create the node
    6914 * 2. add all bound changes
    6915 * 3. move all child nodes to id
    6916 * 4. add id as a child of the root node
    6917 */
    6918 SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
    6919 reoptnodes[id]->parentID = 0;
    6920 reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
    6921
    6922 /* check memory */
    6923 SCIP_CALL( reoptnodeCheckMemory(reoptnodes[id], set, blkmem, nbndchgs, nchilds, 0) );
    6924 assert(reoptnodes[id]->varssize >= nbndchgs);
    6925 assert(reoptnodes[id]->nvars == 0);
    6926 assert(reoptnodes[id]->vars != NULL);
    6927 assert(reoptnodes[id]->varbounds != NULL);
    6928 assert(reoptnodes[id]->varboundtypes != NULL);
    6929
    6930 /* create a permutation array */
    6931 if( !set->reopt_usesplitcons )
    6932 {
    6933 assert(perm == NULL);
    6934 SCIP_CALL( SCIPsetAllocBufferArray(set, &perm, nbndchgs) );
    6935 }
    6936
    6937 /* copy bounds */
    6938 for( v = 0; v < nbndchgs; ++v )
    6939 {
    6940 reoptnodes[id]->vars[v] = reoptnodes[0]->dualredscur->vars[v];
    6941 reoptnodes[id]->varbounds[v] = reoptnodes[0]->dualredscur->vals[v];
    6942 reoptnodes[id]->varboundtypes[v] = reoptnodes[0]->dualredscur->boundtypes[v];
    6943 ++reoptnodes[id]->nvars;
    6944
    6945 /* fill a permutation array */
    6946 if( !set->reopt_usesplitcons )
    6947 perm[v] = v; /*lint !e613*/
    6948 }
    6949 assert(reoptnodes[id]->nvars == reoptnodes[0]->dualredscur->nvars);
    6950
    6951 /* move the children */
    6952 SCIP_CALL( reoptMoveIDs(reopttree, set, blkmem, 0, id) );
    6953 assert(reoptnodes[0]->nchilds == 0);
    6954
    6955 /* add the new reoptimization node as a child of the root node */
    6956 SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
    6957
    6958 ++(*ncreatedchilds);
    6959
    6960 if( set->reopt_usesplitcons )
    6961 {
    6962 int nbinvars = 0;
    6963#ifndef NDEBUG
    6964 int nintvars = 0;
    6965 int ncontvars = 0;
    6966#endif
    6967
    6968 assert(*ncreatedchilds == 1);
    6969
    6970 /* ensure that there is a free slots */
    6971 SCIP_CALL( reopttreeCheckMemory(reopttree, set, blkmem) );
    6972 id = SCIPqueueRemoveUInt(reopttree->openids);
    6973 assert(0 < id && id < reopt->reopttree->reoptnodessize);
    6974
    6975 /* 1. create the node
    6976 * 2. add the constraint to ensure that at least one
    6977 * variable gets different
    6978 * 3. add id as a child of the root node
    6979 */
    6980 SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
    6981 reoptnodes[id]->parentID = 0;
    6982 reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_LOGICORNODE;
    6983
    6984 /* check memory for added constraints */
    6985 SCIP_CALL( reoptnodeCheckMemory(reoptnodes[id], set, blkmem, 0, 0, 1) );
    6986
    6987 /* create the constraint */
    6988 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reoptnodes[id]->conss[0]) );
    6989 consdata = reoptnodes[id]->conss[0];
    6990
    6991 /* count number of binary, integer, and continuous varibales */
    6992 for( v = 0; v < nbndchgs; ++v )
    6993 {
    6994 if( SCIPvarGetType(reoptnodes[0]->dualredscur->vars[v]) == SCIP_VARTYPE_BINARY
    6995 && !SCIPvarIsImpliedIntegral(reoptnodes[0]->dualredscur->vars[v]) )
    6996 ++nbinvars;
    6997#ifndef NDEBUG
    6998 else if( SCIPvarIsIntegral(reoptnodes[0]->dualredscur->vars[v]) )
    6999 ++nintvars;
    7000 else
    7001 ++ncontvars;
    7002#endif
    7003 }
    7004
    7005 /* we create a linear constraint, since all variables are binary */
    7006 if( nbinvars == nbndchgs )
    7007 {
    7008 SCIP_CALL( transformDualredsToLinear(reopt, set, blkmem, consdata, reoptnodes[0]->dualredscur) );
    7009 }
    7010 /* we create a bounddisjunction constraint, since at least one variable is (implicit) integer or continuous */
    7011 else
    7012 {
    7013 assert(nintvars > 0 || ncontvars > 0);
    7014 SCIP_CALL( transformDualredsToBounddisjunction(reopt, set, blkmem, consdata, reoptnodes[0]->dualredscur) );
    7015 }
    7016 ++reoptnodes[id]->nconss;
    7017
    7018 /* add id as a child of the root node */
    7019 SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
    7020 ++(*ncreatedchilds);
    7021
    7022 ++(*naddedconss);
    7023 }
    7024 else
    7025 {
    7026 int nvars;
    7027
    7028 assert(*ncreatedchilds == 1);
    7029 assert(perm != NULL);
    7030
    7031 vars = reoptnodes[0]->dualredscur->vars;
    7032 bounds = reoptnodes[0]->dualredscur->vals;
    7033 boundtypes = reoptnodes[0]->dualredscur->boundtypes;
    7034 nvars = reoptnodes[0]->dualredscur->nvars;
    7035 assert(perm[0] == 0 && perm[nvars-1] == nvars-1);
    7036
    7037 /* calculate the order of the variables */
    7038 switch (set->reopt_varorderinterdiction)
    7039 {
    7040 /* default order */
    7041 case 'd':
    7042 break;
    7043
    7044 /* inference order */
    7045 case 'i':
    7046 SCIP_CALL( getInferenceOrder(set, stat, perm, vars, bounds, boundtypes, nvars) );
    7047 break;
    7048
    7049 /* random order */
    7050 case 'r':
    7051 SCIPrandomPermuteIntArray(reopt->randnumgen, perm, 0, nvars-1);
    7052 break;
    7053
    7054 default:
    7055 return SCIP_INVALIDDATA;
    7056 }
    7057
    7058 /* create nvars nodes in the fashion of interdiction branching */
    7059 for( int c = 0; c < nvars; ++c )
    7060 {
    7061 /* ensure that two free slots are available */
    7062 SCIP_CALL( reopttreeCheckMemory(reopttree, set, blkmem) );
    7063 id = SCIPqueueRemoveUInt(reopttree->openids);
    7064
    7065 assert(0 < id && id < reopt->reopttree->reoptnodessize);
    7066 assert(reoptnodes[id] == NULL || reoptnodes[id]->nvars == 0);
    7067
    7068 /* 1. create the node
    7069 * 2. fix the first v bound changes to vals[v] and v+1 to vals[v] +/- 1 (depending on the bound- and vartype)
    7070 * 4. add the ID id as a child of the root node
    7071 */
    7072 SCIP_CALL( createReoptnode(reopttree, set, blkmem, id) );
    7073 reoptnodes[id]->parentID = 0;
    7074 reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
    7075
    7076 /* check memory */
    7077 SCIP_CALL( reoptnodeCheckMemory(reoptnodes[id], set, blkmem, c+1, 0, 0) );
    7078 assert(reoptnodes[id]->varssize >= perm[c]+1);
    7079 assert(reoptnodes[id]->nvars == 0);
    7080 assert(reoptnodes[id]->vars != NULL);
    7081 assert(reoptnodes[id]->varbounds != NULL);
    7082 assert(reoptnodes[id]->varboundtypes != NULL);
    7083
    7084 /* the permutation is the identity */
    7085 if( set->reopt_varorderinterdiction == 'd' )
    7086 {
    7087 /* copy first c bound changes */
    7088 for( v = 0; v < c; ++v )
    7089 {
    7090 reoptnodes[id]->vars[v] = vars[v];
    7091 reoptnodes[id]->varbounds[v] = bounds[v];
    7092 reoptnodes[id]->varboundtypes[v] = boundtypes[v];
    7093 }
    7094 }
    7095 else
    7096 {
    7097 /* copy first c bound changes */
    7098 for( v = 0; v < c; ++v )
    7099 {
    7100 reoptnodes[id]->vars[v] = vars[perm[v]];
    7101 reoptnodes[id]->varbounds[v] = bounds[perm[v]];
    7102 reoptnodes[id]->varboundtypes[v] = boundtypes[perm[v]];
    7103 }
    7104 }
    7105 reoptnodes[id]->nvars += c;
    7106
    7107 /* set bound change v+1 (= c) to vals[v] +/- 1 (depending on the bound- and vartype) */
    7108 assert(v == c);
    7109 reoptnodes[id]->vars[c] = vars[perm[c]];
    7110 reoptnodes[id]->varbounds[c] = bounds[perm[c]];
    7111 if( SCIPvarIsIntegral(vars[perm[c]]) )
    7112 {
    7113 if( boundtypes[perm[c]] == SCIP_BOUNDTYPE_LOWER )
    7114 reoptnodes[id]->varbounds[c] -= 1.0;
    7115 else
    7116 reoptnodes[id]->varbounds[c] += 1.0;
    7117 }
    7118 reoptnodes[id]->varboundtypes[c] = (boundtypes[perm[c]] == SCIP_BOUNDTYPE_UPPER ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
    7119 ++reoptnodes[id]->nvars;
    7120
    7121 /* add dummy1 as a child of the root node */
    7122 SCIP_CALL( reoptAddChild(reopttree, set, blkmem, 0, id) );
    7123
    7124 ++(*ncreatedchilds);
    7125 }
    7126
    7127 assert(*ncreatedchilds == nvars+1);
    7128
    7130 perm = NULL;
    7131 }
    7132 assert(perm == NULL);
    7133
    7134 /* free the current dualredscur and assign dualredsnex */
    7135 assert(reoptnodes[0]->dualredscur->vars != NULL);
    7136 assert(reoptnodes[0]->dualredscur->vals != NULL);
    7137 assert(reoptnodes[0]->dualredscur->boundtypes != NULL);
    7138
    7139 /* free the current dualredscur and assign dualredsnex */
    7140 SCIP_CALL( reoptnodeUpdateDualConss(reoptnodes[0], blkmem) );
    7141
    7142 /* change the reopttype of the root node */
    7144
    7145 return SCIP_OKAY;
    7146}
    7147
    7148/** reset the stored information abound bound changes based on dual information */
    7150 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7151 SCIP_NODE* node, /**< node of the search tree */
    7152 BMS_BLKMEM* blkmem /**< block memory */
    7153 )
    7154{
    7155 unsigned int id;
    7156
    7157 assert(reopt != NULL);
    7158 assert(node != NULL);
    7159
    7160 id = SCIPnodeGetReoptID(node);
    7161 assert(id < reopt->reopttree->reoptnodessize);
    7162
    7163 /* return if the node is not part of the reoptimization tree */
    7164 if( SCIPnodeGetDepth(node) > 0 && id == 0 )
    7165 return SCIP_OKAY;
    7166
    7167 /* reset the dual constraint */
    7168 SCIP_CALL( reoptnodeResetDualConss(reopt->reopttree->reoptnodes[id], blkmem) );
    7169
    7170 return SCIP_OKAY;
    7171}
    7172
    7173/** return the branching path stored of the given node in the reoptimization tree */
    7175 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7176 SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree */
    7177 SCIP_VAR** vars, /**< array for variables */
    7178 SCIP_Real* vals, /**< array for values */
    7179 SCIP_BOUNDTYPE* boundtypes, /**< array for bound types */
    7180 int varssize, /**< size of arrays vars, vals, and boundtypes */
    7181 int* nbndchgs, /**< pointer to store the number of bound changes */
    7182 int* nbndchgsafterdual /**< pointer to store the number of bound changes applied after
    7183 * the first dual reduction at the given node */
    7184 )
    7185{
    7186 int v;
    7187 int nvars2;
    7188 int nafterdualvars2;
    7189
    7190 assert(reopt != NULL);
    7191 assert(reoptnode != NULL);
    7192 assert(vars != NULL);
    7193 assert(vals != NULL);
    7194 assert(boundtypes != NULL);
    7195
    7196 (*nbndchgs) = reoptnode->nvars;
    7197 (*nbndchgsafterdual) = reoptnode->nafterdualvars;
    7198
    7199 /* return if the size of the given array is not large enough */
    7200 if( varssize == 0 || varssize < *nbndchgs + *nbndchgsafterdual )
    7201 return;
    7202
    7203 /* add all bound changes made by branching (including dual reductions) */
    7204 for( v = 0; v < *nbndchgs; ++v )
    7205 {
    7206 vars[v] = reoptnode->vars[v];
    7207 vals[v] = reoptnode->varbounds[v];
    7208 boundtypes[v] = reoptnode->varboundtypes[v];
    7209 }
    7210
    7211 /* add all bound changes made applied after a dual reduction */
    7212 for( ; v < *nbndchgs + *nbndchgsafterdual; ++v )
    7213 {
    7214 vars[v] = reoptnode->afterdualvars[v-(*nbndchgs)];
    7215 vals[v] = reoptnode->afterdualvarbounds[v-(*nbndchgs)];
    7216 boundtypes[v] = reoptnode->afterdualvarboundtypes[v-(*nbndchgs)];
    7217 }
    7218
    7219 /* go along the root path within the reoptimization tree */
    7220 if( reoptnode->parentID != 0 )
    7221 {
    7222 SCIP_REOPTNODE* parent;
    7223
    7224 parent = reopt->reopttree->reoptnodes[reoptnode->parentID];
    7225 SCIPreoptnodeGetPath(reopt, parent, &vars[v], &vals[v], &boundtypes[v], varssize, &nvars2, &nafterdualvars2);
    7226
    7227 (*nbndchgs) += nvars2;
    7228 (*nbndchgsafterdual) += nafterdualvars2;
    7229 }
    7230}
    7231
    7232/** delete a node stored in the reoptimization tree */
    7234 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7235 SCIP_SET* set, /**< global SCIP settings */
    7236 unsigned int id, /**< id of a stored node */
    7237 BMS_BLKMEM* blkmem /**< block memory */
    7238 )
    7239{
    7240 assert(reopt != NULL);
    7241 assert(reopt->reopttree != NULL);
    7242 assert(id < reopt->reopttree->reoptnodessize);
    7243 assert(reopt->reopttree->reoptnodes[id] != NULL);
    7244 assert(blkmem != NULL);
    7245
    7246 SCIP_CALL( reopttreeDeleteNode(reopt->reopttree, set, blkmem, id, TRUE) );
    7248
    7249 return SCIP_OKAY;
    7250}
    7251
    7252/** reactivate the given @p reoptnode and split them into several nodes if necessary */
    7254 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7255 SCIP* scip, /**< SCIP data structure */
    7256 SCIP_SET* set, /**< global SCIP settings */
    7257 SCIP_STAT* stat, /**< dynamic problem statistics */
    7258 SCIP_PROB* transprob, /**< transformed problem */
    7259 SCIP_PROB* origprob, /**< original problem */
    7260 SCIP_TREE* tree, /**< branching tree */
    7261 SCIP_LP* lp, /**< current LP */
    7262 SCIP_BRANCHCAND* branchcand, /**< branching candidate */
    7263 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    7264 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    7265 SCIP_CLIQUETABLE* cliquetable, /**< clique table */
    7266 BMS_BLKMEM* blkmem, /**< block memory */
    7267 SCIP_REOPTNODE* reoptnode, /**< node of the reoptimization tree to reactivate */
    7268 unsigned int id, /**< id of the node to reactivate */
    7269 SCIP_Real estimate, /**< estimate of the child nodes that should be created */
    7270 SCIP_NODE** childnodes, /**< array to store the created child nodes */
    7271 int* ncreatedchilds, /**< pointer to store number of created child nodes */
    7272 int* naddedconss, /**< pointer to store number of generated constraints */
    7273 int childnodessize, /**< available size of childnodes array */
    7274 SCIP_Bool* success /**< pointer store the result */
    7275 )
    7276{
    7277 assert(reopt != NULL);
    7278 assert(scip != NULL);
    7279 assert(set != NULL);
    7280 assert(stat != NULL);
    7281 assert(transprob != NULL);
    7282 assert(origprob != NULL);
    7283 assert(tree != NULL);
    7284 assert(lp != NULL);
    7285 assert(branchcand != NULL);
    7286 assert(eventqueue != NULL);
    7287 assert(cliquetable != NULL);
    7288 assert(blkmem != NULL);
    7289 assert(reoptnode != NULL);
    7290 assert(childnodes != NULL);
    7291 assert(reopt->reopttree != NULL);
    7292 assert(id < reopt->reopttree->reoptnodessize);
    7293 assert(success != NULL);
    7294
    7295 SCIPsetDebugMsg(set, "reactivating node at id %u:\n", id);
    7296
    7297 *success = FALSE;
    7298
    7299 /* check if we need to split the node */
    7300 if( reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_STRBRANCHED
    7301 || reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_INFSUBTREE )
    7302 {
    7303 assert(reoptnode->dualreds);
    7304
    7305 /* we want use a constraint to split the node into two disjoint node */
    7306 if( set->reopt_usesplitcons )
    7307 {
    7308 if( reoptnode->reopttype == (unsigned int)SCIP_REOPTTYPE_INFSUBTREE )
    7309 {
    7310 assert(reoptnode->dualredscur != NULL);
    7311 assert(reoptnode->dualredscur->constype == REOPT_CONSTYPE_INFSUBTREE);
    7312 (*ncreatedchilds) = 1;
    7313 }
    7314 else
    7315 {
    7316 assert(reoptnode->dualredscur != NULL);
    7317 assert(reoptnode->dualredscur->constype == REOPT_CONSTYPE_DUALREDS);
    7318 (*ncreatedchilds) = 2;
    7319 }
    7320
    7321 /* in both cases we add exactly one constraint */
    7322 (*naddedconss) = 1;
    7323
    7324 if( childnodessize < *ncreatedchilds )
    7325 return SCIP_OKAY;
    7326
    7327 /* generate the nodes */
    7328 for( int c = 0; c < *ncreatedchilds; ++c )
    7329 {
    7330 /* create the child node */
    7331 SCIP_CALL( SCIPnodeCreateChild(&childnodes[c], blkmem, set, stat, tree, 1.0, estimate) );
    7332
    7333 /* change all bounds; convert the bound changes after the first based on dual reductions into branching
    7334 * for second node only. if we generate only one node, i.e., the pruned part, we do not need this
    7335 * changes anyway.
    7336 */
    7337 SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
    7338 eventfilter, cliquetable, blkmem, childnodes[c], id, c == 1) );
    7339
    7340 /* add all local constraints */
    7341 SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[c], id) );
    7342
    7343 /* we can use the old lowerbound if the objective function has not changed */
    7344 if( !reopt->objhaschanged && SCIPsetIsGT(set, reopt->reopttree->reoptnodes[id]->lowerbound, estimate) )
    7345 SCIPnodeSetEstimate(childnodes[c], set, reopt->reopttree->reoptnodes[id]->lowerbound);
    7346
    7347 if( c == 0 )
    7348 {
    7349 /* in both cases the node generated first represents the pruned is currently not part of the reoptimization tree */
    7351
    7352 /* add the constraint to the node */
    7353 assert(reopt->reopttree->reoptnodes[id]->dualredscur != NULL);
    7354 SCIP_CALL( addSplitcons(reopt, scip, set, stat, blkmem, transprob, origprob, tree, lp, branchcand,
    7355 eventqueue, eventfilter, cliquetable, childnodes[c], id) );
    7356
    7357 /* fixBounds() does the same, but in this case we go not into it */
    7358 if( reoptnode->dualredscur->constype == REOPT_CONSTYPE_INFSUBTREE )
    7359 {
    7360 assert(reoptnode->dualredscur->nvars > 0);
    7361 assert(reoptnode->dualredscur->varssize > 0);
    7362
    7363 /* delete dualredscur and move dualredsnex -> dualredscur */
    7364 SCIP_CALL( reoptnodeUpdateDualConss(reoptnode, blkmem) );
    7365 }
    7366
    7367 /* the added constraint could be deleted due to propagation, thus, we store the node in the reoptimization
    7368 * tree. the node has to stored anyway, because of the constraint representing the dual reductions
    7369 */
    7370 SCIP_CALL( addNode(reopt, set, lp, blkmem, childnodes[c], SCIP_REOPTTYPE_LOGICORNODE, FALSE, FALSE,
    7371 -SCIPsetInfinity(set)) );
    7372 }
    7373 else
    7374 {
    7375 /* if we reach this lines of code, the current node represents the original node including all bound
    7376 * changes based in dual information.
    7377 */
    7378 assert(reoptnode->dualredscur->constype == REOPT_CONSTYPE_DUALREDS);
    7379 if( reoptnode->nconss == 0 )
    7381 else
    7383
    7384 /* fix all bound changes based on dual information and convert them into branchings */
    7385 assert(reopt->reopttree->reoptnodes[id]->dualredscur != NULL);
    7386 SCIP_CALL( fixBounds(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, eventfilter,
    7387 cliquetable, blkmem, childnodes[c], id, TRUE) );
    7388
    7389 /* set the unique id the id of the original node */
    7390 SCIPnodeSetReoptID(childnodes[c], id);
    7391 }
    7392 }
    7393
    7394 /* reset the stored dual constraints */
    7396
    7397 /* set the reoptimization type */
    7398 if( reopt->reopttree->reoptnodes[id]->dualreds )
    7399 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_STRBRANCHED;
    7400 else
    7401 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
    7402
    7403 *success = TRUE;
    7404 }
    7405 else
    7406 {
    7407 SCIP_VAR** vars;
    7408 SCIP_Real* bounds;
    7409 SCIP_BOUNDTYPE* boundtypes;
    7410 int* perm = NULL;
    7411 int nvars;
    7412
    7413 vars = reoptnode->dualredscur->vars;
    7414 bounds = reoptnode->dualredscur->vals;
    7415 boundtypes = reoptnode->dualredscur->boundtypes;
    7416 nvars = reoptnode->dualredscur->nvars;
    7417
    7418 *ncreatedchilds = nvars+1;
    7419 *naddedconss = 0;
    7420
    7421 /* check if there is enough memory allocated */
    7422 if( childnodessize < *ncreatedchilds )
    7423 return SCIP_OKAY;
    7424
    7425 /* create and fill permutation array */
    7426 SCIP_CALL( SCIPsetAllocBufferArray(set, &perm, nvars) );
    7427 for( int c = 0; c < nvars; ++c )
    7428 perm[c] = c;
    7429
    7430 /* calculate the order of the variables */
    7431 switch (set->reopt_varorderinterdiction)
    7432 {
    7433 /* default order */
    7434 case 'd':
    7435 break;
    7436
    7437 /* inference order */
    7438 case 'i':
    7439 SCIP_CALL( getInferenceOrder(set, stat, perm, vars, bounds, boundtypes, nvars) );
    7440 break;
    7441
    7442 /* random order */
    7443 case 'r':
    7444 SCIPrandomPermuteIntArray(reopt->randnumgen, perm, 0, nvars-1);
    7445 break;
    7446
    7447 default:
    7448 return SCIP_INVALIDDATA;
    7449 }
    7450
    7451 assert(reopt->reopttree->reoptnodes[id] != NULL);
    7452 reoptnode = reopt->reopttree->reoptnodes[id];
    7453
    7454 /* enough that the node need to split */
    7455 assert(reoptnode->dualreds);
    7456
    7457 /* iterate over all nodes and change the necessary bounds (nodes[0] corresponds to the original one)
    7458 * we need to do this in the reverse order because we want to transform the bound changes based on dual information
    7459 * into branching decisions at nodes[0].
    7460 */
    7461 for( int c = nvars; c >= 0; --c )
    7462 {
    7463 /* create the child node */
    7464 SCIP_CALL( SCIPnodeCreateChild(&childnodes[c], blkmem, set, stat, tree, 1.0, estimate) );
    7465
    7466#ifdef SCIP_MORE_DEBUG
    7467 SCIPsetDebugMsg(set, " change bounds at node %lld\n", SCIPnodeGetNumber(childnodes[c]));
    7468#endif
    7469
    7470 /* change all bounds */
    7471 SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
    7472 eventfilter, cliquetable, blkmem, childnodes[c], id, FALSE) );
    7473
    7474 /* reconstruct the original node and the pruned part, respectively */
    7475 if( c == 0 )
    7476 {
    7477 /* fix bound changes based on dual information and convert all these bound changes to normal bound changes */
    7478 SCIP_CALL( fixBounds(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, eventfilter,
    7479 cliquetable, blkmem, childnodes[c], id, TRUE) );
    7480
    7481 /* set the reopttype of the node */
    7483
    7484 /* set the unique id */
    7485 SCIPnodeSetReoptID(childnodes[c], id);
    7486 }
    7487 else
    7488 {
    7489 /* fix the first c bound changes and negate the (c+1)th */
    7490 SCIP_CALL( fixInterdiction(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, eventfilter,
    7491 cliquetable, blkmem, childnodes[c], id, perm, vars, bounds, boundtypes, nvars, c) );
    7492 }
    7493
    7494 /* add all local constraints */
    7495 SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[c], id) );
    7496
    7497 /* we can use the old lowerbound if the objective function has not changed */
    7498 if( !reopt->objhaschanged && SCIPsetIsGT(set, reopt->reopttree->reoptnodes[id]->lowerbound, estimate) )
    7499 SCIPnodeSetEstimate(childnodes[c], set, reopt->reopttree->reoptnodes[id]->lowerbound);
    7500 }
    7501
    7502 /* free buffer array */
    7504
    7505 /* reset the stored dual constraints */
    7507
    7508 /* set the reoptimization type to transit */
    7509 if( reopt->reopttree->reoptnodes[id]->dualreds )
    7510 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_STRBRANCHED;
    7511 else
    7512 reopt->reopttree->reoptnodes[id]->reopttype = (unsigned int)SCIP_REOPTTYPE_TRANSIT;
    7513
    7514 *success = TRUE;
    7515 }
    7516 }
    7517 else
    7518 {
    7519 /* we need the create exactly one node to reconstruct the node itself and no additional constraint */
    7520 (*ncreatedchilds) = 1;
    7521 (*naddedconss) = 0;
    7522
    7523 if( childnodessize < *ncreatedchilds )
    7524 return SCIP_OKAY;
    7525
    7526 /* create the child node */
    7527 SCIP_CALL( SCIPnodeCreateChild(&childnodes[0], blkmem, set, stat, tree, 1.0, estimate) );
    7528
    7529 /* change all bounds */
    7530 assert(reoptnode->nafterdualvars == 0);
    7531 SCIP_CALL( changeAncestorBranchings(reopt, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
    7532 eventfilter, cliquetable, blkmem, childnodes[0], id, FALSE) );
    7533
    7534 /* add all local constraints */
    7535 SCIP_CALL( addLocalConss(scip, reopt, set, stat, blkmem, childnodes[0], id) );
    7536
    7537 /* we can use the old lowerbound if the objective function has not changed */
    7538 if( !reopt->objhaschanged && SCIPsetIsGT(set, reopt->reopttree->reoptnodes[id]->lowerbound, estimate) )
    7539 SCIPnodeSetEstimate(childnodes[0], set, reopt->reopttree->reoptnodes[id]->lowerbound);
    7540
    7541 /* set the reopttype */
    7542 assert(reoptnode->reopttype != (unsigned int)SCIP_REOPTTYPE_INFSUBTREE
    7543 && reoptnode->reopttype != (unsigned int)SCIP_REOPTTYPE_STRBRANCHED);
    7544 SCIPnodeSetReopttype(childnodes[0], (SCIP_REOPTTYPE)reoptnode->reopttype);
    7545
    7546 /* set the unique id */
    7547 SCIPnodeSetReoptID(childnodes[0], id);
    7548
    7549 *success = TRUE;
    7550 }
    7551
    7552 return SCIP_OKAY;
    7553}
    7554
    7555/** returns the time needed to store the nodes for reoptimization */
    7557 SCIP_REOPT* reopt /**< reoptimization data structure */
    7558 )
    7559{
    7560 assert(reopt != NULL);
    7561
    7562 return SCIPclockGetTime(reopt->savingtime);
    7563}
    7564
    7565/** add the stored constraints globally to the problem */
    7567 SCIP* scip, /**< SCIP data structure */
    7568 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7569 SCIP_SET* set, /**< global SCIP settings */
    7570 SCIP_STAT* stat, /**< dynamic problem statistics */
    7571 BMS_BLKMEM* blkmem /**< block memory */
    7572 )
    7573{
    7574 char name[SCIP_MAXSTRLEN];
    7575
    7576 assert(scip != NULL);
    7577 assert(reopt != NULL);
    7578 assert(set != NULL);
    7579 assert(stat != NULL);
    7580 assert(blkmem != NULL);
    7581
    7582 if( reopt->glbconss == NULL || reopt->nglbconss == 0 )
    7583 return SCIP_OKAY;
    7584
    7585 for( int c = reopt->nglbconss-1; c >= 0; --c )
    7586 {
    7587 SCIP_CONS* cons;
    7588 SCIP_VAR** consvars;
    7589 int nbinvars;
    7590 int nintvars;
    7591
    7592 assert(reopt->glbconss[c] != NULL);
    7593 assert(reopt->glbconss[c]->nvars > 0);
    7594
    7595 cons = NULL;
    7596 consvars = NULL;
    7597 nbinvars = 0;
    7598 nintvars = 0;
    7599
    7600 /* check if we can use a logic-or or if we have to use a bounddisjuction constraint */
    7601 for( int v = 0; v < reopt->glbconss[c]->nvars; ++v )
    7602 {
    7603 if( SCIPvarGetType(reopt->glbconss[c]->vars[v]) == SCIP_VARTYPE_BINARY
    7604 && !SCIPvarIsImpliedIntegral(reopt->glbconss[c]->vars[v]) )
    7605 ++nbinvars;
    7606 else if( SCIPvarIsIntegral(reopt->glbconss[c]->vars[v]) )
    7607 ++nintvars;
    7608 else
    7609 {
    7610 SCIPerrorMessage("Expected variable type binary or (impl.) integer for variable <%s> in global constraint at pos. %d.\n",
    7611 SCIPvarGetName(reopt->glbconss[c]->vars[v]), c);
    7612 return SCIP_INVALIDDATA;
    7613 }
    7614 }
    7615
    7616 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "glb_%s_%d_%d", reopt->glbconss[c]->constype == REOPT_CONSTYPE_CUT ? "cut" : "inf", reopt->run, c);
    7617
    7618 /* @todo use active representatives */
    7619
    7620 /* all variables are binary, we can create a logic-or constraint */
    7621 if( nbinvars == reopt->glbconss[c]->nvars )
    7622 {
    7623 SCIPsetDebugMsg(set, "-> add logic-or constraints with %d binvars\n", nbinvars);
    7624
    7625 /* allocate buffer */
    7626 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, reopt->glbconss[c]->nvars) );
    7627
    7628 for( int v = 0; v < reopt->glbconss[c]->nvars; ++v )
    7629 {
    7630 consvars[v] = reopt->glbconss[c]->vars[v];
    7631 assert(SCIPvarIsOriginal(consvars[v]));
    7632
    7633 /* negate the variable if it was fixed to 1 */
    7634 if( SCIPsetIsFeasEQ(set, reopt->glbconss[c]->vals[v], 0.0) )
    7635 {
    7636 assert(reopt->glbconss[c]->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
    7637 SCIP_CALL( SCIPvarNegate(consvars[v], blkmem, set, stat, &consvars[v]) );
    7638 }
    7639 }
    7640
    7641 /* create the logic-or constraint */
    7642 SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, reopt->glbconss[c]->nvars,
    7643 consvars, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
    7644
    7645 /* free buffer */
    7646 SCIPfreeBufferArray(scip, &consvars);
    7647 }
    7648 /* not all variables are binary, we need a bounddisjunction constraint */
    7649 else
    7650 {
    7651 assert(reopt->glbconss[c]->nvars == nbinvars + 2*nintvars);
    7652
    7653 SCIPsetDebugMsg(set, "-> add bounddisjuction constraints with %d binvars, %d intvars\n", nbinvars, (int) (2*nintvars));
    7654
    7655 /* create the bounddisjuction constraint */
    7656 SCIP_CALL( SCIPcreateConsBasicBounddisjunction(scip, &cons, name, reopt->glbconss[c]->nvars, reopt->glbconss[c]->vars,
    7657 reopt->glbconss[c]->boundtypes, reopt->glbconss[c]->vals) );
    7658 }
    7659
    7660#ifdef SCIP_DEBUG_CONSS
    7662#endif
    7663
    7664 SCIP_CALL( SCIPaddCons(scip, cons) );
    7665
    7666 /* remember the constraint for re-activation */
    7667 assert(!SCIPhashsetExists(reopt->activeconssset, (void*)cons));
    7668 SCIP_CALL( SCIPhashsetInsert(reopt->activeconssset, blkmem, (void*)cons) );
    7669 SCIP_CALL( ensureActiveconssSize(reopt, set, blkmem, reopt->nactiveconss + 1) );
    7670 assert(reopt->nactiveconss < reopt->nmaxactiveconss);
    7671 reopt->activeconss[reopt->nactiveconss++] = cons;
    7672
    7673 /* don't release the constraint because we would need to capture the constraint anyway */
    7674
    7675 /* mark the constraint as empty */
    7676 reopt->glbconss[c]->nvars = 0;
    7677 }
    7678
    7679 SCIPsetDebugMsg(set, "added %d gobal constraints\n", reopt->nglbconss);
    7680
    7681 /* reset number of global constraints */
    7682 reopt->nglbconss = 0;
    7683
    7684 return SCIP_OKAY;
    7685}
    7686
    7687/** add the stored cuts to the separation storage */
    7689 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7690 SCIP_NODE* node, /**< current focus node */
    7691 SCIP_SEPASTORE* sepastore, /**< separation storage */
    7692 SCIP_CUTPOOL* cutpool, /**< global cutpool */
    7693 BMS_BLKMEM* blkmem, /**< block memory */
    7694 SCIP_SET* set, /**< global SCIP settings */
    7695 SCIP_STAT* stat, /**< dynamic problem statistics */
    7696 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    7697 SCIP_EVENTFILTER* eventfilter, /**< event filter */
    7698 SCIP_LP* lp, /**< current LP */
    7699 SCIP_Bool root /**< bool whether the current node is the root */
    7700 )
    7701{
    7702 SCIP_REOPTNODE* reoptnode;
    7703 SCIP_Bool infeasible;
    7704 unsigned int id;
    7705 int ncuts;
    7706
    7707 assert(reopt != NULL);
    7708 assert(node != NULL);
    7709 assert(sepastore != NULL);
    7710 assert(blkmem != NULL);
    7711 assert(set != NULL);
    7712 assert(stat != NULL);
    7713 assert(eventqueue != NULL);
    7714 assert(eventfilter != NULL);
    7715 assert(lp != NULL);
    7716
    7717 id = SCIPnodeGetReoptID(node);
    7718 assert(id < reopt->reopttree->reoptnodessize);
    7719
    7720 /* skip nodes that are node part of the reoptimization tree */
    7721 if( id == 0 && SCIPnodeGetDepth(node) > 0 )
    7722 return SCIP_OKAY;
    7723
    7724 reoptnode = reopt->reopttree->reoptnodes[id];
    7725 assert(reoptnode != NULL);
    7726
    7727 ncuts = 0;
    7728 for( int c = reoptnode->nconss-1; c >= 0; --c )
    7729 {
    7730 SCIP_REOPTCONSDATA* cons;
    7731
    7732 cons = reoptnode->conss[c];
    7733 assert(cons != NULL);
    7734
    7735 if( cons->constype == REOPT_CONSTYPE_CUT )
    7736 {
    7737 SCIP_ROW* cut;
    7738 SCIP_COL** cols;
    7739 SCIP_Real* vals;
    7740 char cutname[SCIP_MAXSTRLEN];
    7741 int ncols;
    7742
    7743 SCIP_CALL( SCIPsetAllocBufferArray(set, &cols, cons->nvars) );
    7744 SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, cons->nvars) );
    7745
    7746 ncols = 0;
    7747 for( int v = 0; v < cons->nvars; ++v )
    7748 {
    7749 SCIP_VAR* transvar;
    7750
    7751 assert(SCIPvarIsOriginal(cons->vars[v]));
    7752
    7753 transvar = SCIPvarGetTransVar(cons->vars[v]);
    7754 assert(transvar != NULL);
    7755 assert(SCIPvarGetStatus(transvar) == SCIP_VARSTATUS_COLUMN);
    7756
    7757 vals[ncols] = cons->vals[v];
    7758 cols[ncols] = SCIPvarGetCol(transvar);
    7759 assert(cols[ncols] != NULL);
    7760
    7761 ++ncols;
    7762 }
    7763 assert(ncols == cons->nvars);
    7764
    7765 (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "reoptcut_%d_%d", id, ncuts);
    7766 infeasible = FALSE;
    7767
    7768 if( id == 0 )
    7769 {
    7770 SCIP_CALL( SCIProwCreate(&cut, blkmem, set, stat, cutname, ncols, cols, vals, cons->lhs, cons->rhs,
    7772 SCIP_CALL( SCIPcutpoolAddRow(cutpool, blkmem, set, stat, lp, cut) );
    7773
    7774 SCIPsetDebugMsg(set, "add cut <%s> of size %d to cutpool, [lhs, rhs] = [%g,%g] to node %lld\n", cutname,
    7775 ncols, cons->lhs, cons->rhs, SCIPnodeGetNumber(node));
    7776 }
    7777 else
    7778 {
    7779 SCIP_CALL( SCIProwCreate(&cut, blkmem, set, stat, cutname, ncols, cols, vals, cons->lhs, cons->rhs,
    7781 SCIP_CALL( SCIPsepastoreAddCut(sepastore, blkmem, set, stat, eventqueue, eventfilter, lp, cut, FALSE, root,
    7782 &infeasible) );
    7783
    7784 SCIPsetDebugMsg(set, "add cut <%s> of size %d to sepastore, [lhs, rhs] = [%g,%g] to node %lld\n", cutname,
    7785 ncols, cons->lhs, cons->rhs, SCIPnodeGetNumber(node));
    7786 }
    7787
    7788 SCIP_CALL( SCIProwRelease(&cut, blkmem, set, lp) );
    7789
    7790 if( infeasible )
    7791 SCIPsetDebugMsg(set, "cut %d stored at node %" SCIP_LONGINT_FORMAT " (id: %u) is infeasible.\n", c, SCIPnodeGetNumber(node), id);
    7792 else
    7793 ++ncuts;
    7794
    7797
    7798 BMSfreeBlockMemoryArrayNull(blkmem, &reoptnode->conss[c]->boundtypes, reoptnode->conss[c]->varssize);
    7799 BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vals, reoptnode->conss[c]->varssize);
    7800 BMSfreeBlockMemoryArray(blkmem, &reoptnode->conss[c]->vars, reoptnode->conss[c]->varssize);
    7801 BMSfreeBlockMemory(blkmem, &reoptnode->conss[c]); /*lint !e866*/
    7802 --reoptnode->nconss;
    7803 }
    7804 else
    7805 {
    7806#ifndef NDEBUG
    7807 for( int i = c-1; i >= 0; --i )
    7808 assert(reoptnode->conss[i]->constype != REOPT_CONSTYPE_CUT);
    7809#endif
    7810 break;
    7811 }
    7812 }
    7813
    7814 return SCIP_OKAY;
    7815}
    7816
    7817/** check if the LP of the given node should be solved or not */
    7819 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7820 SCIP_SET* set, /**< global SCIP settings */
    7821 SCIP_NODE* node /**< node of the current search tree */
    7822 )
    7823{
    7824 unsigned int id;
    7825
    7826 assert(reopt != NULL);
    7827 assert(node != NULL);
    7828
    7829 /* get the ID */
    7830 id = SCIPnodeGetReoptID(node);
    7831 assert(id < reopt->reopttree->reoptnodessize);
    7832
    7833 /* return if the node is not part of the reoptimization tree */
    7834 if( SCIPnodeGetDepth(node) > 0 && id == 0 )
    7835 return TRUE;
    7836
    7837 /* return always true if the parameter is set to 1.0 */
    7838 if( SCIPsetIsGE(set, set->reopt_objsimrootlp, 1.0) )
    7839 return TRUE;
    7840
    7841 /* current node is the root */
    7842 if( id == 0 )
    7843 {
    7844 if( reopt->reopttree->reoptnodes[0]->nchilds > 0 )
    7845 {
    7846 /* the objective function has changed only slightly */
    7847 if( SCIPsetIsGE(set, reopt->simtolastobj, set->reopt_objsimrootlp) )
    7848 return FALSE;
    7849 }
    7850 }
    7851 else
    7852 {
    7853 /* solve node LP if the node type is greater or equal to solvelp or there were too many bound changes at the current node */
    7854 if( reopt->reopttree->reoptnodes[id]->nvars < set->reopt_solvelpdiff && (int) SCIPnodeGetReopttype(node) < set->reopt_solvelp )
    7855 {
    7856 assert(reopt->reopttree->reoptnodes[id]->nchilds > 0);
    7857 return FALSE;
    7858 }
    7859 }
    7860
    7861 return TRUE;
    7862}
    7863
    7864/** initialize an empty node */
    7866 SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
    7867 SCIP_SET* set /**< global SCIP settings */
    7868 )
    7869{
    7870 assert(reoptnode != NULL);
    7871 assert(set != NULL);
    7872
    7873 reoptnode->conss = NULL;
    7874 reoptnode->nconss = 0;
    7875 reoptnode->consssize = 0;
    7876 reoptnode->childids = NULL;
    7877 reoptnode->allocchildmem = 0;
    7878 reoptnode->nchilds = 0;
    7879 reoptnode->nvars = 0;
    7880 reoptnode->nafterdualvars = 0;
    7881 reoptnode->parentID = 0;
    7882 reoptnode->dualreds = FALSE;
    7883 reoptnode->reopttype = (unsigned int)SCIP_REOPTTYPE_NONE;
    7884 reoptnode->varssize = 0;
    7885 reoptnode->afterdualvarssize = 0;
    7886 reoptnode->vars = NULL;
    7887 reoptnode->varbounds = NULL;
    7888 reoptnode->varboundtypes = NULL;
    7889 reoptnode->afterdualvars = NULL;
    7890 reoptnode->afterdualvarbounds = NULL;
    7891 reoptnode->afterdualvarboundtypes = NULL;
    7892 reoptnode->dualredscur = NULL;
    7893 reoptnode->dualredsnex = NULL;
    7894 reoptnode->lowerbound = -SCIPsetInfinity(set);
    7895}
    7896
    7897/** reset the given reoptimization node */
    7899 SCIP_REOPT* reopt, /**< reoptimization data structure */
    7900 SCIP_SET* set, /**< global SCIP settings */
    7901 BMS_BLKMEM* blkmem, /**< block memory */
    7902 SCIP_REOPTNODE* reoptnode /**< reoptimization node */
    7903 )
    7904{
    7905 assert(reopt != NULL);
    7906 assert(set != NULL);
    7907 assert(blkmem != NULL);
    7908 assert(reoptnode != NULL);
    7909
    7910 SCIP_CALL( reoptnodeReset(reoptnode, set, blkmem) );
    7911
    7912 return SCIP_OKAY;
    7913}
    7914
    7915/** delete the given reoptimization node */
    7917 SCIP_REOPTNODE** reoptnode, /**< pointer of reoptnode */
    7918 BMS_BLKMEM* blkmem /**< block memory */
    7919 )
    7920{
    7921 assert(reoptnode != NULL);
    7922 assert(blkmem != NULL);
    7923
    7924 SCIP_CALL( reoptnodeDelete(reoptnode, blkmem) );
    7925
    7926 return SCIP_OKAY;
    7927}
    7928
    7929/** add a variable to a given reoptnode */
    7931 SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
    7932 SCIP_SET* set, /**< global SCIP settings */
    7933 BMS_BLKMEM* blkmem, /**< block memory */
    7934 SCIP_VAR* var, /**< variable to add */
    7935 SCIP_Real val, /**< value of the variable */
    7936 SCIP_BOUNDTYPE boundtype /**< boundtype of the variable */
    7937 )
    7938{
    7939 int nvars;
    7940
    7941 assert(reoptnode != NULL);
    7942 assert(var != NULL);
    7943 assert(blkmem != NULL);
    7944
    7945 nvars = reoptnode->nvars;
    7946
    7947 SCIP_CALL( reoptnodeCheckMemory(reoptnode, set, blkmem, nvars + 1, 0, 0) );
    7948
    7949 reoptnode->vars[nvars] = var;
    7950 reoptnode->varbounds[nvars] = val;
    7951 reoptnode->varboundtypes[nvars] = boundtype;
    7952 ++reoptnode->nvars;
    7953
    7954 return SCIP_OKAY;
    7955}
    7956
    7957/** add a constraint to a given reoptnode */
    7959 SCIP_REOPTNODE* reoptnode, /**< node of the reopttree */
    7960 SCIP_SET* set, /**< global SCIP settings */
    7961 BMS_BLKMEM* blkmem, /**< block memory */
    7962 SCIP_VAR** vars, /**< variables which are part of the constraint */
    7963 SCIP_Real* bounds, /**< bounds of the variables */
    7964 SCIP_BOUNDTYPE* boundtypes, /**< boundtypes of the variables (or NULL is the constraint is a cut) */
    7965 SCIP_Real lhs, /**< lhs of the constraint */
    7966 SCIP_Real rhs, /**< rhs of the constraint */
    7967 int nvars, /**< number of variables */
    7968 REOPT_CONSTYPE constype, /**< type of the constraint */
    7969 SCIP_Bool linear /**< the given constraint has a linear representation */
    7970 )
    7971{
    7972 int nconss;
    7973
    7974 assert(reoptnode != NULL);
    7975 assert(set != NULL);
    7976 assert(vars != NULL);
    7977 assert(bounds != NULL);
    7978 assert(constype == REOPT_CONSTYPE_CUT || boundtypes != NULL);
    7979 assert(nvars > 0);
    7980 assert(blkmem != NULL);
    7981
    7982 /* the constraint can be interpreted as a normal bound change */
    7983 if( nvars == 1 && constype != REOPT_CONSTYPE_CUT )
    7984 {
    7985 assert(constype == REOPT_CONSTYPE_DUALREDS || constype == REOPT_CONSTYPE_INFSUBTREE);
    7986
    7987 SCIPsetDebugMsg(set, "-> constraint has size 1 -> save as normal bound change.\n");
    7988
    7989 assert(!SCIPvarIsImpliedIntegral(vars[0]));
    7990 if( SCIPvarGetType(vars[0]) == SCIP_VARTYPE_BINARY )
    7991 {
    7992 SCIP_CALL( SCIPreoptnodeAddBndchg(reoptnode, set, blkmem, vars[0], 1-bounds[0],
    7993 1-bounds[0] == 1 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER) );
    7994 }
    7995 else
    7996 {
    7997 SCIP_Real newbound;
    7998 SCIP_BOUNDTYPE newboundtype;
    7999
    8000 assert(SCIPvarGetType(vars[0]) == SCIP_VARTYPE_INTEGER);
    8001 assert(boundtypes != NULL);
    8002
    8003 if( boundtypes[0] == SCIP_BOUNDTYPE_UPPER )
    8004 {
    8005 newbound = bounds[0] + 1.0;
    8006 assert(SCIPsetIsLE(set, newbound, SCIPvarGetUbLocal(vars[0])));
    8007
    8008 newboundtype = SCIP_BOUNDTYPE_LOWER;
    8009 }
    8010 else
    8011 {
    8012 newbound = bounds[0] - 1.0;
    8013 assert(SCIPsetIsGE(set, newbound, SCIPvarGetLbLocal(vars[0])));
    8014
    8015 newboundtype = SCIP_BOUNDTYPE_UPPER;
    8016 }
    8017
    8018 SCIP_CALL( SCIPreoptnodeAddBndchg(reoptnode, set, blkmem, vars[0], newbound, newboundtype) );
    8019 }
    8020 }
    8021 else
    8022 {
    8023 nconss = reoptnode->nconss;
    8024
    8025 SCIP_CALL( reoptnodeCheckMemory(reoptnode, set, blkmem, 0, 0, nconss+1) );
    8026
    8027 /* create the constraint */
    8028 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &reoptnode->conss[nconss]) ); /*lint !e866*/
    8029 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->vars, vars, nvars) );
    8030 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->vals, bounds, nvars) );
    8031 if( boundtypes != NULL )
    8032 {
    8033 assert(!linear);
    8034 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &reoptnode->conss[nconss]->boundtypes, boundtypes, nvars) );
    8035 }
    8036 else
    8037 reoptnode->conss[nconss]->boundtypes = NULL;
    8038
    8039 reoptnode->conss[nconss]->varssize = nvars;
    8040 reoptnode->conss[nconss]->nvars = nvars;
    8041 reoptnode->conss[nconss]->lhs = lhs;
    8042 reoptnode->conss[nconss]->rhs = rhs;
    8043 reoptnode->conss[nconss]->constype = constype;
    8044 reoptnode->conss[nconss]->linear = linear;
    8045 ++reoptnode->nconss;
    8046 }
    8047 return SCIP_OKAY;
    8048}
    8049
    8050/** add a constraint to the reoptimization data structure */
    8052 SCIP_REOPT* reopt, /**< reoptimization data structure */
    8053 SCIP_SET* set, /**< global SCIP settings */
    8054 BMS_BLKMEM* blkmem, /**< block memory */
    8055 SCIP_CONS* cons /**< constraint to add */
    8056 )
    8057{
    8058 assert(reopt != NULL);
    8059 assert(set != NULL);
    8060 assert(blkmem != NULL);
    8061 assert(cons != NULL);
    8062
    8063#ifdef SCIP_MORE_DEBUG
    8064 SCIPsetDebugMsg(set, "add cons <%s> to reoptimization data\n", SCIPconsGetName(cons));
    8065#endif
    8066
    8067 /* check memory */
    8068 if( reopt->addedconsssize == 0 )
    8069 {
    8070 assert(reopt->addedconss == NULL);
    8071
    8072 reopt->addedconsssize = 10;
    8074 }
    8075 else if( reopt->naddedconss == reopt->addedconsssize )
    8076 {
    8077 int newsize = SCIPsetCalcMemGrowSize(set, reopt->addedconsssize+1);
    8078 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &reopt->addedconss, reopt->addedconsssize, newsize) );
    8079
    8080 /* clear the array */
    8081 BMSclearMemoryArray(&reopt->addedconss[reopt->addedconsssize], newsize - reopt->addedconsssize); /*lint !e866 */
    8082
    8083 reopt->addedconsssize = newsize;
    8084 }
    8085 assert(reopt->naddedconss < reopt->addedconsssize);
    8086 assert(reopt->addedconss[reopt->naddedconss] == NULL);
    8087
    8088 reopt->addedconss[reopt->naddedconss] = cons;
    8089 reopt->consadded = TRUE;
    8090 ++reopt->naddedconss;
    8091
    8092 /* capture the constraint */
    8093 SCIPconsCapture(cons);
    8094
    8095 return SCIP_OKAY;
    8096}
    8097
    8098/** save global lower and upper bounds
    8099 *
    8100 * @note this method should only be called once, i.e., after fishing presolving of the first problem
    8101 */
    8103 SCIP_REOPT* reopt, /**< reoptimization data structure */
    8104 SCIP_PROB* transprob, /**< transformed problem data */
    8105 BMS_BLKMEM* blkmem /**< block memory */
    8106 )
    8107{
    8108 SCIP_VAR** vars;
    8109 int nvars;
    8110
    8111 assert(reopt != NULL);
    8112 assert(transprob != NULL);
    8113 assert(reopt->glblb == NULL && reopt->glbub == NULL);
    8114
    8115 nvars = SCIPprobGetNVars(transprob);
    8116 vars = SCIPprobGetVars(transprob);
    8117
    8118 /* create hashmaps */
    8119 SCIP_CALL( SCIPhashmapCreate(&reopt->glbub, blkmem, nvars) );
    8120 SCIP_CALL( SCIPhashmapCreate(&reopt->glblb, blkmem, nvars) );
    8121
    8122 /* store the global bounds */
    8123 for( int i = 0; i < nvars; ++i )
    8124 {
    8125 if( SCIPvarIsRelaxationOnly(vars[i]) )
    8126 continue;
    8127
    8128 assert(!SCIPhashmapExists(reopt->glblb, (void*)vars[i]));
    8129 assert(!SCIPhashmapExists(reopt->glbub, (void*)vars[i]));
    8130
    8131 SCIP_CALL( SCIPhashmapInsertReal(reopt->glblb, (void*)vars[i], SCIPvarGetLbGlobal(vars[i])) );
    8132 SCIP_CALL( SCIPhashmapInsertReal(reopt->glbub, (void*)vars[i], SCIPvarGetUbGlobal(vars[i])) );
    8133 }
    8134
    8135 return SCIP_OKAY;
    8136}
    8137
    8138/** save active constraints
    8139 *
    8140 * @note this method can only called once, i.e., after fishing presolving of the first problem
    8141 */
    8143 SCIP_REOPT* reopt, /**< reoptimization data structure */
    8144 SCIP_SET* set, /**< global SCIP settings */
    8145 SCIP_PROB* transprob, /**< transformed problem data */
    8146 BMS_BLKMEM* blkmem /**< block memory */
    8147 )
    8148{
    8149 SCIP_CONS** conss;
    8150 int nconss;
    8151
    8152 assert(reopt != NULL);
    8153 assert(transprob != NULL);
    8154 assert(reopt->activeconss == NULL);
    8155 assert(reopt->activeconssset == NULL);
    8156 assert(reopt->nactiveconss == 0);
    8157 assert(reopt->nmaxactiveconss == 0);
    8158
    8159 conss = SCIPprobGetConss(transprob);
    8160 nconss = SCIPprobGetNConss(transprob);
    8161
    8162 SCIPsetDebugMsg(set, "save %d active conss\n", nconss);
    8163
    8164 /* create hashset and array */
    8165 SCIP_CALL( SCIPhashsetCreate(&reopt->activeconssset, blkmem, nconss) );
    8166 SCIP_CALL( ensureActiveconssSize(reopt, set, blkmem, nconss) );
    8167
    8168 for( int i = 0; i < nconss; ++i )
    8169 {
    8170 assert(SCIPconsIsActive(conss[i]));
    8171 assert(!SCIPhashsetExists(reopt->activeconssset, (void*)conss[i]));
    8172
    8173 SCIPconsCapture(conss[i]);
    8174 SCIP_CALL( SCIPhashsetInsert(reopt->activeconssset, blkmem, (void*)conss[i]) );
    8175 reopt->activeconss[reopt->nactiveconss++] = conss[i];
    8176 }
    8177
    8178 return SCIP_OKAY;
    8179}
    8180
    8181/** installs global lower and upper bounds */
    8183 SCIP_REOPT* reopt, /**< reoptimization data structure */
    8184 SCIP_SET* set, /**< global SCIP settings */
    8185 SCIP_STAT* stat, /**< dynamic SCIP statistics */
    8186 SCIP_PROB* transprob, /**< transformed problem data */
    8187 SCIP_LP* lp, /**< current LP data */
    8188 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    8189 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    8190 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    8191 BMS_BLKMEM* blkmem /**< block memory */
    8192 )
    8193{
    8194 SCIP_VAR** vars;
    8195 int nvars;
    8196
    8197 assert(reopt != NULL);
    8198 assert(transprob != NULL);
    8199 assert(reopt->glblb != NULL && reopt->glbub != NULL);
    8200 assert(SCIPprobIsTransformed(transprob));
    8201
    8202 nvars = SCIPprobGetNVars(transprob);
    8203 vars = SCIPprobGetVars(transprob);
    8204
    8205 /* install global lower and upper bounds */
    8206 for( int i = 0; i < nvars; ++i )
    8207 {
    8208 SCIP_Real lb;
    8209 SCIP_Real ub;
    8210
    8211 if( SCIPvarIsRelaxationOnly(vars[i]) )
    8212 continue;
    8213
    8214 assert(SCIPhashmapExists(reopt->glblb, (void*)vars[i]));
    8215 assert(SCIPhashmapExists(reopt->glbub, (void*)vars[i]));
    8216
    8217 lb = SCIPhashmapGetImageReal(reopt->glblb, (void*)vars[i]);
    8218 ub = SCIPhashmapGetImageReal(reopt->glbub, (void*)vars[i]);
    8219 assert(lb < SCIP_INVALID && ub < SCIP_INVALID);
    8220
    8221 /* reset the global bounds back */
    8222 SCIP_CALL( SCIPvarChgLbGlobal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, lb) );
    8223 SCIP_CALL( SCIPvarChgUbGlobal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, ub) );
    8224
    8225 /* reset the local bounds back */
    8226 SCIP_CALL( SCIPvarChgLbLocal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, lb) );
    8227 SCIP_CALL( SCIPvarChgUbLocal(vars[i], blkmem, set, stat, lp, branchcand, eventqueue, ub) );
    8228 }
    8229
    8230 return SCIP_OKAY;
    8231}
    8232
    8233/** reactivate globally valid constraints that were deactivated and necessary to ensure correctness */
    8235 SCIP_REOPT* reopt, /**< reoptimization data structure */
    8236 SCIP_SET* set, /**< global SCIP settings */
    8237 SCIP_STAT* stat /**< dynamic SCIP statistics */
    8238 )
    8239{
    8240 assert(reopt != NULL);
    8241 assert(reopt->activeconss != NULL || reopt->nmaxactiveconss == 0);
    8242 assert(reopt->activeconssset != NULL || reopt->nmaxactiveconss == 0);
    8243 assert(reopt->nmaxactiveconss >= 0);
    8244
    8245 SCIPsetDebugMsg(set, "Reset %d active conss.\n", reopt->nactiveconss);
    8246
    8247 /* loop over all storeed active constraints and reactivate deactivated constraints */
    8248 for( int i = 0; i < reopt->nactiveconss; ++i )
    8249 {
    8250 SCIP_CONS* cons;
    8251
    8252 assert(reopt->activeconss != NULL);
    8253 cons = reopt->activeconss[i];
    8254 assert(cons != NULL);
    8255 assert(SCIPhashsetExists(reopt->activeconssset, cons));
    8256
    8257 /* it can happen that the constraint got globally deleted */
    8258 if( SCIPconsIsDeleted(cons) )
    8259 cons->deleted = FALSE;
    8260
    8261 /* to ensure that the constraint will be added to all the data structures we need to deactivate the
    8262 * constraint first.
    8263 */
    8264 if( SCIPconsIsActive(cons) )
    8265 {
    8266 SCIP_CALL( SCIPconsDeactivate(cons, set, stat) );
    8267 }
    8268 SCIP_CALL( SCIPconsActivate(cons, set, stat, -1, TRUE) );
    8269 }
    8270
    8271 return SCIP_OKAY;
    8272}
    8273
    8274/** returns whether a constraint is necessary to ensure correctness and cannot be deleted */
    8276 SCIP_REOPT* reopt, /**< reoptimization data structure */
    8277 SCIP_CONS* cons /**< problem constraint */
    8278 )
    8279{
    8280 assert(reopt != NULL);
    8281 assert(cons != NULL);
    8282
    8283 /* the hashset is not initialized, we can delete all constraints */
    8284 if( reopt->activeconss == NULL )
    8285 return TRUE;
    8286
    8287 return !SCIPhashsetExists(reopt->activeconssset, (void*)cons);
    8288}
    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:6431
    SCIP_RETCODE SCIPconsDeactivate(SCIP_CONS *cons, SCIP_SET *set, SCIP_STAT *stat)
    Definition: cons.c:7077
    SCIP_RETCODE SCIPconsGetNVars(SCIP_CONS *cons, SCIP_SET *set, int *nvars, SCIP_Bool *success)
    Definition: cons.c:6558
    SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
    Definition: cons.c:6443
    SCIP_RETCODE SCIPconsActivate(SCIP_CONS *cons, SCIP_SET *set, SCIP_STAT *stat, int depth, SCIP_Bool focusnode)
    Definition: cons.c:7035
    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:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_INVALID
    Definition: def.h:187
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_ALLOC(x)
    Definition: def.h:375
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define SCIP_UNKNOWN
    Definition: def.h:188
    #define SQR(x)
    Definition: def.h:208
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:157
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_CALL(x)
    Definition: def.h:364
    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:9701
    SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_setppc.c:9719
    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:4320
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8413
    SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
    Definition: cons.c:8522
    SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
    Definition: cons.c:8454
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8393
    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:8886
    void SCIPnodeSetReopttype(SCIP_NODE *node, SCIP_REOPTTYPE reopttype)
    Definition: tree.c:8573
    void SCIPnodeSetReoptID(SCIP_NODE *node, unsigned int id)
    Definition: tree.c:8604
    void SCIPnodeGetAncestorBranchingsPart(SCIP_NODE *node, SCIP_NODE *parent, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
    Definition: tree.c:8923
    SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
    Definition: tree.c:8503
    SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
    Definition: tree.c:8533
    void SCIPnodeGetNDomchg(SCIP_NODE *node, int *nbranchings, int *nconsprop, int *nprop)
    Definition: tree.c:8628
    SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
    Definition: tree.c:8513
    SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
    Definition: tree.c:8812
    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:8523
    SCIP_REOPTTYPE SCIPnodeGetReopttype(SCIP_NODE *node)
    Definition: tree.c:8563
    unsigned int SCIPnodeGetReoptID(SCIP_NODE *node)
    Definition: tree.c:8594
    SCIP_RETCODE SCIPaddReoptDualBndchg(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound, SCIP_Real oldbound)
    Definition: scip_solve.c:3243
    SCIP_Bool SCIPisReoptEnabled(SCIP *scip)
    Definition: scip_solve.c:3629
    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:4274
    SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
    Definition: sol.c:4155
    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:18365
    SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
    Definition: var.c:17846
    SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
    Definition: var.c:23715
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23674
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23418
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23530
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
    Definition: var.c:23462
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23932
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23485
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24174
    int SCIPvarGetIndex(SCIP_VAR *var)
    Definition: var.c:23684
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23694
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23522
    SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
    Definition: var.c:18532
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
    Definition: var.c:23475
    SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
    Definition: var.c:23632
    SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
    Definition: var.c:23449
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
    Definition: var.c:23704
    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:793
    SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:819
    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:735
    void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
    Definition: history.c:751
    void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
    Definition: history.c:719
    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:2955
    int SCIPprobGetNConss(SCIP_PROB *prob)
    Definition: prob.c:2946
    int SCIPprobGetNVars(SCIP_PROB *prob)
    Definition: prob.c:2865
    SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
    Definition: prob.c:2910
    SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
    Definition: prob.c:2800
    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:3476
    SCIP_RETCODE SCIPreoptUpdateVarHistory(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem, SCIP_VAR **vars, int nvars)
    Definition: reopt.c:6589
    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:6311
    SCIP_RETCODE SCIPreoptSaveActiveConss(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_PROB *transprob, BMS_BLKMEM *blkmem)
    Definition: reopt.c:8142
    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:7253
    int SCIPreoptGetNTotalPrunedNodes(SCIP_REOPT *reopt)
    Definition: reopt.c:4958
    SCIP_RETCODE SCIPreoptnodeReset(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_REOPTNODE *reoptnode)
    Definition: reopt.c:7898
    SCIP_RETCODE SCIPreoptAddRun(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR **origvars, int norigvars, int size)
    Definition: reopt.c:5353
    SCIP_RETCODE SCIPreoptAddCons(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_CONS *cons)
    Definition: reopt.c:8051
    int SCIPreoptGetNTotalFeasNodes(SCIP_REOPT *reopt)
    Definition: reopt.c:4938
    void SCIPreoptAddNCheckedSols(SCIP_REOPT *reopt, int ncheckedsols)
    Definition: reopt.c:5399
    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:4908
    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:5266
    int SCIPreoptGetNTotalRestartsLocal(SCIP_REOPT *reopt)
    Definition: reopt.c:4898
    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:5953
    static SCIP_RETCODE transformDualredsToBounddisjunction(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_REOPTCONSDATA *consdata, SCIP_REOPTCONSDATA *dualreds)
    Definition: reopt.c:6803
    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:2373
    int SCIPreoptGetNImprovingSols(SCIP_REOPT *reopt)
    Definition: reopt.c:5410
    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:3212
    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:2594
    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:3145
    SCIP_RETCODE SCIPreoptAddInfNode(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node)
    Definition: reopt.c:5929
    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:4080
    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:3526
    static SCIP_RETCODE reoptResetTree(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_Bool softreset)
    Definition: reopt.c:4594
    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:7688
    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:5634
    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:4784
    SCIP_RETCODE SCIPreoptnodeAddBndchg(SCIP_REOPTNODE *reoptnode, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real val, SCIP_BOUNDTYPE boundtype)
    Definition: reopt.c:7930
    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:7958
    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:6860
    #define DEFAULT_MEM_DUALCONS
    Definition: reopt.c:62
    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:5461
    static SCIP_DECL_EVENTEXITSOL(eventExitsolReopt)
    Definition: reopt.c:139
    static void resetStats(SCIP_REOPT *reopt)
    Definition: reopt.c:4262
    static SCIP_RETCODE reoptRestart(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
    Definition: reopt.c:4620
    SCIP_Bool SCIPreoptConsCanBeDeleted(SCIP_REOPT *reopt, SCIP_CONS *cons)
    Definition: reopt.c:8275
    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:4948
    int SCIPreoptGetNFeasNodes(SCIP_REOPT *reopt)
    Definition: reopt.c:4928
    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:4520
    static SCIP_RETCODE saveGlobalCons(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_NODE *node, REOPT_CONSTYPE consttype)
    Definition: reopt.c:3409
    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:7233
    SCIP_Real SCIPreoptnodeGetLowerbound(SCIP_REOPTNODE *reoptnode)
    Definition: reopt.c:5828
    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:4888
    SCIP_RETCODE SCIPreoptReleaseData(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
    Definition: reopt.c:5089
    #define DEFAULT_MEM_VAR
    Definition: reopt.c:59
    SCIP_RETCODE SCIPreoptResetDualBndchgs(SCIP_REOPT *reopt, SCIP_NODE *node, BMS_BLKMEM *blkmem)
    Definition: reopt.c:7149
    void SCIPreoptResetSolMarks(SCIP_REOPT *reopt)
    Definition: reopt.c:5724
    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:4737
    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:5446
    int SCIPreoptGetNSolsRun(SCIP_REOPT *reopt, int run)
    Definition: reopt.c:5431
    void SCIPreoptnodeSetParentID(SCIP_REOPTNODE *reoptnode, unsigned int parentid)
    Definition: reopt.c:5883
    SCIP_Real SCIPreoptGetSimToFirst(SCIP_REOPT *reopt)
    Definition: reopt.c:5606
    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:58
    int SCIPreoptGetNSavedSols(SCIP_REOPT *reopt)
    Definition: reopt.c:5501
    #define DEFAULT_MEM_NODES
    Definition: reopt.c:60
    SCIP_Real SCIPreoptGetOldObjCoef(SCIP_REOPT *reopt, int run, int idx)
    Definition: reopt.c:5662
    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:74
    int SCIPreoptGetNCheckedSols(SCIP_REOPT *reopt)
    Definition: reopt.c:5389
    static SCIP_RETCODE reoptGetLeaves(SCIP_REOPT *reopt, unsigned int id, unsigned int *leaves, int leavessize, int *nleaves)
    Definition: reopt.c:4550
    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:6743
    SCIP_RETCODE SCIPreoptFree(SCIP_REOPT **reopt, SCIP_SET *set, SCIP_PRIMAL *origprimal, BMS_BLKMEM *blkmem)
    Definition: reopt.c:5116
    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:4192
    int SCIPreoptnodeGetNConss(SCIP_REOPTNODE *reoptnode)
    Definition: reopt.c:5795
    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:5848
    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:4918
    static SCIP_RETCODE reoptnodeResetDualConss(SCIP_REOPTNODE *reoptnode, BMS_BLKMEM *blkmem)
    Definition: reopt.c:3162
    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:5785
    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:4978
    static int reopttreeGetNNodes(SCIP_REOPTTREE *reopttree, unsigned int id)
    Definition: reopt.c:4502
    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:7174
    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:5319
    SCIP_REOPTTYPE SCIPreoptnodeGetType(SCIP_REOPTNODE *reoptnode)
    Definition: reopt.c:5838
    int SCIPreoptGetNNodes(SCIP_REOPT *reopt, SCIP_NODE *node)
    Definition: reopt.c:5745
    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:7556
    SCIP_RETCODE SCIPreoptResetActiveConss(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat)
    Definition: reopt.c:8234
    SCIP_RETCODE SCIPreoptnodeDelete(SCIP_REOPTNODE **reoptnode, BMS_BLKMEM *blkmem)
    Definition: reopt.c:7916
    SCIP_RETCODE SCIPreoptCreate(SCIP_REOPT **reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
    Definition: reopt.c:5008
    int SCIPreoptGetNTotalInfNodes(SCIP_REOPT *reopt)
    Definition: reopt.c:4998
    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:6221
    #define DEFAULT_RANDSEED
    Definition: reopt.c:64
    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:2468
    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:3701
    SCIP_Real SCIPreoptGetSimilarity(SCIP_REOPT *reopt, SCIP_SET *set, int run1, int run2, SCIP_VAR **origvars, int norigvars)
    Definition: reopt.c:5615
    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:4287
    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:6384
    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:5242
    SCIP_RETCODE SCIPreoptMergeVarHistory(SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **vars, int nvars)
    Definition: reopt.c:6497
    static SCIP_DECL_EVENTINITSOL(eventInitsolReopt)
    Definition: reopt.c:113
    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:68
    SCIP_RETCODE SCIPreoptSaveGlobalBounds(SCIP_REOPT *reopt, SCIP_PROB *transprob, BMS_BLKMEM *blkmem)
    Definition: reopt.c:8102
    SCIP_REOPTNODE * SCIPreoptGetReoptnode(SCIP_REOPT *reopt, unsigned int id)
    Definition: reopt.c:5648
    void SCIPreoptAddNImprovingSols(SCIP_REOPT *reopt, int nimprovingsols)
    Definition: reopt.c:5420
    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:7818
    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:5528
    int SCIPreoptGetNCutoffReoptnodes(SCIP_REOPT *reopt)
    Definition: reopt.c:4968
    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:8182
    static SCIP_RETCODE reoptSaveNewObj(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_VAR **origvars, int norigvars)
    Definition: reopt.c:4650
    int SCIPreoptnodeGetNChildren(SCIP_REOPTNODE *reoptnode)
    Definition: reopt.c:5818
    SCIP_RETCODE SCIPreoptApplyGlbConss(SCIP *scip, SCIP_REOPT *reopt, SCIP_SET *set, SCIP_STAT *stat, BMS_BLKMEM *blkmem)
    Definition: reopt.c:7566
    SCIP_RETCODE SCIPreoptApplyCompression(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_REOPTNODE **representatives, int nrepresentatives, SCIP_Bool *success)
    Definition: reopt.c:6644
    #define DEFAULT_MEM_RUN
    Definition: reopt.c:61
    int SCIPreoptnodeGetNDualBoundChgs(SCIP_REOPTNODE *reoptnode)
    Definition: reopt.c:5805
    SCIP_Real SCIPreoptGetSimToPrevious(SCIP_REOPT *reopt)
    Definition: reopt.c:5597
    SCIP_RETCODE SCIPreoptReset(SCIP_REOPT *reopt, SCIP_SET *set, BMS_BLKMEM *blkmem)
    Definition: reopt.c:5690
    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:6331
    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:67
    int SCIPreoptGetNRestartsGlobal(SCIP_REOPT *reopt)
    Definition: reopt.c:4878
    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:6447
    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:5678
    void SCIPreoptnodeInit(SCIP_REOPTNODE *reoptnode, SCIP_SET *set)
    Definition: reopt.c:7865
    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:3958
    int SCIPreoptGetNLeaves(SCIP_REOPT *reopt, SCIP_NODE *node)
    Definition: reopt.c:5895
    int SCIPreoptGetNInfNodes(SCIP_REOPT *reopt)
    Definition: reopt.c:4988
    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:6623
    SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6999
    SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6951
    SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6583
    SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6543
    SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6975
    SCIP_Real SCIPsetInfinity(SCIP_SET *set)
    Definition: set.c:6386
    SCIP_RETCODE SCIPsetGetIntParam(SCIP_SET *set, const char *name, int *value)
    Definition: set.c:3388
    SCIP_RETCODE SCIPsetIncludeEventhdlr(SCIP_SET *set, SCIP_EVENTHDLR *eventhdlr)
    Definition: set.c:4994
    SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6563
    SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6521
    SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6603
    SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6676
    SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6643
    SCIP_BRANCHRULE * SCIPsetFindBranchrule(SCIP_SET *set, const char *name)
    Definition: set.c:5150
    SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:7047
    SCIP_Real SCIPsetRound(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6746
    int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
    Definition: set.c:6086
    SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6665
    unsigned int SCIPsetInitializeRandomSeed(SCIP_SET *set, unsigned int initialseedvalue)
    Definition: set.c:7806
    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:1912
    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:132
    void SCIPnodeGetDualBoundchgs(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *bounds, SCIP_BOUNDTYPE *boundtypes, int *nvars, int varssize)
    Definition: tree.c:8736
    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:9047
    SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
    Definition: tree.c:9559
    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:8695
    void SCIPnodeGetPropsBeforeDual(SCIP_NODE *node, SCIP_VAR **vars, SCIP_Real *varbounds, SCIP_BOUNDTYPE *varboundtypes, int *npropvars, int propvarssize)
    Definition: tree.c:8965
    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
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    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:9906
    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:11186
    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:11488
    SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
    Definition: var.c:22148
    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:12746
    SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
    Definition: var.c:8976
    void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
    Definition: var.c:9957
    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:13019
    internal methods for problem variables