Scippy

    SCIP

    Solving Constraint Integer Programs

    sepastore.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file sepastore.c
    26 * @ingroup OTHER_CFILES
    27 * @brief methods for storing separated cuts
    28 * @author Tobias Achterberg
    29 * @author Marc Pfetsch
    30 * @author Leona Gottwald
    31 */
    32
    33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    34
    35#include <assert.h>
    36
    37#include "scip/def.h"
    38#include "scip/set.h"
    39#include "scip/stat.h"
    40#include "scip/lp.h"
    41#include "scip/lpexact.h"
    42#include "scip/var.h"
    43#include "scip/tree.h"
    44#include "scip/reopt.h"
    45#include "scip/sepastore.h"
    46#include "scip/event.h"
    47#include "scip/sepa.h"
    48#include "scip/cons.h"
    49#include "scip/debug.h"
    50#include "scip/scip.h"
    51#include "scip/cuts.h"
    52#include "scip/cutsel.h"
    53#include "scip/struct_event.h"
    55#include "scip/misc.h"
    56#include "scip/pub_lpexact.h"
    57#include "scip/scip_lpexact.h"
    58
    59
    60
    61/*
    62 * dynamic memory arrays
    63 */
    64
    65/** resizes cuts and score arrays to be able to store at least num entries */
    66static
    68 SCIP_SEPASTORE* sepastore, /**< separation storage */
    69 SCIP_SET* set, /**< global SCIP settings */
    70 int num /**< minimal number of slots in array */
    71 )
    72{
    73 assert(sepastore != NULL);
    74 assert(set != NULL);
    75
    76 if( num > sepastore->cutssize )
    77 {
    78 int newsize;
    79
    80 newsize = SCIPsetCalcMemGrowSize(set, num);
    81 SCIP_ALLOC( BMSreallocMemoryArray(&sepastore->cuts, newsize) );
    82 sepastore->cutssize = newsize;
    83 }
    84 assert(num <= sepastore->cutssize);
    85
    86 return SCIP_OKAY;
    87}
    88
    89/** creates separation storage */
    91 SCIP_SEPASTORE** sepastore, /**< pointer to store separation storage */
    92 BMS_BLKMEM* blkmem, /**< block memory */
    93 SCIP_SET* set /**< global SCIP settings */
    94 )
    95{
    96 assert(sepastore != NULL);
    97
    98 SCIP_ALLOC( BMSallocMemory(sepastore) );
    99
    100 (*sepastore)->cuts = NULL;
    101 (*sepastore)->cutssize = 0;
    102 (*sepastore)->ncuts = 0;
    103 (*sepastore)->nforcedcuts = 0;
    104 (*sepastore)->ncutsadded = 0;
    105 (*sepastore)->ncutsaddedviapool = 0;
    106 (*sepastore)->ncutsaddeddirect = 0;
    107 (*sepastore)->ncutsfoundround = 0;
    108 (*sepastore)->ncutsapplied = 0;
    109 (*sepastore)->initiallp = FALSE;
    110 (*sepastore)->forcecuts = FALSE;
    111
    112 SCIP_CALL( SCIPrandomCreate(&(*sepastore)->randnumgen, blkmem, SCIPsetInitializeRandomSeed(set, 0x5EED)) );
    113
    114 return SCIP_OKAY;
    115}
    116
    117/** frees separation storage */
    119 SCIP_SEPASTORE** sepastore, /**< pointer to store separation storage */
    120 BMS_BLKMEM* blkmem /**< block memory */
    121 )
    122{
    123 assert(sepastore != NULL);
    124 assert(*sepastore != NULL);
    125 assert((*sepastore)->ncuts == 0);
    126
    127 SCIPrandomFree(&(*sepastore)->randnumgen, blkmem);
    128 BMSfreeMemoryArrayNull(&(*sepastore)->cuts);
    129 BMSfreeMemory(sepastore);
    130
    131 return SCIP_OKAY;
    132}
    133
    134/** informs separation storage that the setup of the initial LP starts now */
    136 SCIP_SEPASTORE* sepastore /**< separation storage */
    137 )
    138{
    139 assert(sepastore != NULL);
    140 assert(!sepastore->initiallp);
    141 assert(sepastore->ncuts == 0);
    142
    143 sepastore->initiallp = TRUE;
    144}
    145
    146/** informs separation storage that the setup of the initial LP is now finished */
    148 SCIP_SEPASTORE* sepastore /**< separation storage */
    149 )
    150{
    151 assert(sepastore != NULL);
    152 assert(sepastore->initiallp);
    153 assert(sepastore->ncuts == 0);
    154
    155 sepastore->initiallp = FALSE;
    156}
    157
    158/** informs separation storage that the following cuts should be used in any case */
    160 SCIP_SEPASTORE* sepastore /**< separation storage */
    161 )
    162{
    163 assert(sepastore != NULL);
    164 assert(!sepastore->forcecuts);
    165
    166 sepastore->forcecuts = TRUE;
    167}
    168
    169/** informs separation storage that the following cuts should no longer be used in any case */
    171 SCIP_SEPASTORE* sepastore /**< separation storage */
    172 )
    173{
    174 assert(sepastore != NULL);
    175 assert(sepastore->forcecuts);
    176
    177 sepastore->forcecuts = FALSE;
    178}
    179
    180/** checks cut for redundancy due to activity bounds */
    181static
    183 SCIP_SEPASTORE* sepastore, /**< separation storage */
    184 SCIP_SET* set, /**< global SCIP settings */
    185 SCIP_STAT* stat, /**< problem statistics data */
    186 SCIP_ROW* cut /**< separated cut */
    187 )
    188{
    189 SCIP_Real minactivity;
    190 SCIP_Real maxactivity;
    191 SCIP_Real lhs;
    192 SCIP_Real rhs;
    193
    194 assert(sepastore != NULL);
    195 assert(cut != NULL);
    196
    197 /* modifiable cuts cannot be declared redundant, since we don't know all coefficients */
    198 if( SCIProwIsModifiable(cut) )
    199 return FALSE;
    200
    201 /** @todo implement a safe redundancy check for cuts in exact solving mode */
    202 if( set->exact_enable )
    203 return FALSE;
    204
    205 /* check for activity redundancy */
    206 lhs = SCIProwGetLhs(cut);
    207 rhs = SCIProwGetRhs(cut);
    208 minactivity = SCIProwGetMinActivity(cut, set, stat);
    209 maxactivity = SCIProwGetMaxActivity(cut, set, stat);
    210
    211 if( (SCIPsetIsInfinity(set, -lhs) || SCIPsetIsLE(set, lhs, minactivity)) &&
    212 (SCIPsetIsInfinity(set, rhs) || SCIPsetIsLE(set, maxactivity, rhs)) )
    213 {
    214 SCIPsetDebugMsg(set, "ignoring activity redundant cut <%s> (sides=[%g,%g], act=[%g,%g])\n",
    215 SCIProwGetName(cut), lhs, rhs, minactivity, maxactivity);
    216 /*SCIPdebug(SCIProwPrint(cut, set->scip->messagehdlr, NULL));*/
    217 return TRUE;
    218 }
    219
    220 return FALSE;
    221}
    222
    223/** checks cut for redundancy or infeasibility due to activity bounds */
    224static
    226 SCIP_SEPASTORE* sepastore, /**< separation storage */
    227 SCIP_SET* set, /**< global SCIP settings */
    228 SCIP_STAT* stat, /**< problem statistics data */
    229 SCIP_ROW* cut, /**< separated cut */
    230 SCIP_Bool* infeasible /**< pointer to store whether the cut has been detected to be infeasible */
    231 )
    232{
    233 SCIP_Real minactivity;
    234 SCIP_Real maxactivity;
    235 SCIP_Real lhs;
    236 SCIP_Real rhs;
    237
    238 assert(sepastore != NULL);
    239 assert(cut != NULL);
    240 assert(infeasible != NULL);
    241
    242 *infeasible = FALSE;
    243
    244 /** @todo implement a safe redundancy or infeasibility check for cuts in exact solving mode */
    245 if( set->exact_enable )
    246 return FALSE;
    247
    248 /* modifiable cuts cannot be declared redundant or infeasible, since we don't know all coefficients */
    249 if( SCIProwIsModifiable(cut) )
    250 return FALSE;
    251
    252 /* check for activity redundancy */
    253 lhs = SCIProwGetLhs(cut);
    254 rhs = SCIProwGetRhs(cut);
    255 minactivity = SCIProwGetMinActivity(cut, set, stat);
    256 maxactivity = SCIProwGetMaxActivity(cut, set, stat);
    257
    258 if( (SCIPsetIsInfinity(set, -lhs) || SCIPsetIsLE(set, lhs, minactivity)) &&
    259 (SCIPsetIsInfinity(set, rhs) || SCIPsetIsLE(set, maxactivity, rhs)) )
    260 {
    261 SCIPsetDebugMsg(set, "ignoring activity redundant cut <%s> (sides=[%g,%g], act=[%g,%g])\n",
    262 SCIProwGetName(cut), lhs, rhs, minactivity, maxactivity);
    263 /*SCIPdebug(SCIProwPrint(cut, set->scip->messagehdlr, NULL));*/
    264 return TRUE;
    265 }
    266
    267 if( (!SCIPsetIsInfinity(set, rhs) && SCIPsetIsFeasPositive(set, minactivity - rhs)) ||
    268 (!SCIPsetIsInfinity(set, -lhs) && SCIPsetIsFeasNegative(set, maxactivity - lhs)) )
    269 {
    270 SCIPsetDebugMsg(set, "cut <%s> is infeasible (sides=[%g,%g], act=[%g,%g])\n",
    271 SCIProwGetName(cut), lhs, rhs, minactivity, maxactivity);
    272 /*SCIPdebug(SCIProwPrint(cut, set->scip->messagehdlr, NULL));*/
    273 *infeasible = TRUE;
    274 return TRUE;
    275 }
    276
    277 return FALSE;
    278}
    279
    280/** checks whether a cut with only one variable can be applied as boundchange
    281 *
    282 * This is the case if the bound change would prove infeasibility (w.r.t feastol), or if the new bound is at least
    283 * epsilon better than the old bound. In the latter case, also the opposite bound has to be taken into account.
    284 */
    285static
    287 SCIP_SET* set, /**< global SCIP settings */
    288 SCIP_ROW* cut /**< cut with a single variable */
    289 )
    290{
    291 SCIP_COL** cols;
    292 SCIP_Real* vals;
    293 SCIP_VAR* var;
    294 SCIP_Real lhs;
    295 SCIP_Real rhs;
    296 SCIP_Bool local;
    297 SCIP_Real oldlb;
    298 SCIP_Real oldub;
    299
    300 assert(set != NULL);
    301 assert(cut != NULL);
    302 assert(!SCIProwIsModifiable(cut));
    303 assert(SCIProwGetNNonz(cut) == 1);
    304
    305 /* get the single variable and its coefficient of the cut */
    306 cols = SCIProwGetCols(cut);
    307 assert(cols != NULL);
    308
    309 var = SCIPcolGetVar(cols[0]);
    310 vals = SCIProwGetVals(cut);
    311 assert(vals != NULL);
    312 assert(!SCIPsetIsZero(set, vals[0]));
    313
    314 /* if the coefficient is nearly zero, we better ignore this cut for numerical reasons */
    315 if( SCIPsetIsFeasZero(set, vals[0]) )
    316 return FALSE;
    317
    318 local = SCIProwIsLocal(cut);
    319
    320 oldlb = local ? SCIPvarGetLbLocal(var) : SCIPvarGetLbGlobal(var);
    321 oldub = local ? SCIPvarGetUbLocal(var) : SCIPvarGetUbGlobal(var);
    322
    323 /* get the left hand side of the cut and convert it to a bound */
    324 lhs = SCIProwGetLhs(cut);
    325 if( !SCIPsetIsInfinity(set, -lhs) )
    326 {
    327 lhs -= SCIProwGetConstant(cut);
    328 if( vals[0] > 0.0 )
    329 {
    330 /* coefficient is positive -> lhs corresponds to lower bound */
    331 SCIP_Real newlb;
    332
    333 newlb = lhs/vals[0];
    334 SCIPvarAdjustLb(var, set, &newlb);
    335
    336 /* bound changes that improve the bound sufficiently are applicable */
    337 if( SCIPsetIsFeasGT(set, newlb, oldub) || SCIPsetIsGT(set, MIN(newlb, oldub), oldlb) )
    338 return TRUE;
    339 }
    340 else
    341 {
    342 /* coefficient is negative -> lhs corresponds to upper bound */
    343 SCIP_Real newub;
    344
    345 newub = lhs/vals[0];
    346 SCIPvarAdjustUb(var, set, &newub);
    347
    348 /* bound changes that improve the bound sufficiently are applicable */
    349 if( SCIPsetIsFeasLT(set, newub, oldlb) || SCIPsetIsLT(set, MAX(newub, oldlb), oldub) )
    350 return TRUE;
    351 }
    352 }
    353
    354 /* get the right hand side of the cut and convert it to a bound */
    355 rhs = SCIProwGetRhs(cut);
    356 if( !SCIPsetIsInfinity(set, rhs) )
    357 {
    358 rhs -= SCIProwGetConstant(cut);
    359 if( vals[0] > 0.0 )
    360 {
    361 /* coefficient is positive -> rhs corresponds to upper bound */
    362 SCIP_Real newub;
    363
    364 newub = rhs/vals[0];
    365 SCIPvarAdjustUb(var, set, &newub);
    366
    367 /* bound changes that improve the bound sufficiently are applicable */
    368 if( SCIPsetIsFeasLT(set, newub, oldlb) || SCIPsetIsLT(set, MAX(newub, oldlb), oldub) )
    369 return TRUE;
    370 }
    371 else
    372 {
    373 /* coefficient is negative -> rhs corresponds to lower bound */
    374 SCIP_Real newlb;
    375
    376 newlb = rhs/vals[0];
    377 SCIPvarAdjustLb(var, set, &newlb);
    378
    379 /* bound changes that improve the bound sufficiently are applicable */
    380 if( SCIPsetIsFeasGT(set, newlb, oldub) || SCIPsetIsGT(set, MIN(newlb, oldub), oldlb) )
    381 return TRUE;
    382 }
    383 }
    384
    385 return FALSE;
    386}
    387
    388/** removes a non-forced cut from the separation storage */
    389static
    391 SCIP_SEPASTORE* sepastore, /**< separation storage */
    392 BMS_BLKMEM* blkmem, /**< block memory */
    393 SCIP_SET* set, /**< global SCIP settings */
    394 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    395 SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
    396 SCIP_LP* lp, /**< LP data */
    397 int pos /**< position of cut to delete */
    398 )
    399{
    400 assert(sepastore != NULL);
    401 assert(sepastore->cuts != NULL);
    402 assert(sepastore->nforcedcuts <= pos && pos < sepastore->ncuts);
    403
    404 /* check, if the row deletions from separation storage events are tracked if so, issue ROWDELETEDSEPA event */
    405 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDSEPA) != 0 )
    406 {
    407 SCIP_EVENT* event;
    408
    409 SCIP_CALL( SCIPeventCreateRowDeletedSepa(&event, blkmem, sepastore->cuts[pos]) );
    410 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
    411 }
    412
    413 /* release the row */
    414 if( !sepastore->initiallp )
    415 {
    416 sepastore->ncutsadded--;
    417 if( sepastore->cuts[pos]->fromcutpool )
    418 sepastore->ncutsaddedviapool--;
    419 else
    420 sepastore->ncutsaddeddirect--;
    421
    423 {
    424 SCIP_SEPA* sepa;
    425 sepa = SCIProwGetOriginSepa(sepastore->cuts[pos]);
    426 SCIPsepaDecNCutsAdded(sepa, sepastore->cuts[pos]->fromcutpool);
    427 }
    428 }
    429 SCIP_CALL( SCIProwRelease(&sepastore->cuts[pos], blkmem, set, lp) );
    430
    431 /* move last cut to the empty position */
    432 sepastore->cuts[pos] = sepastore->cuts[sepastore->ncuts-1];
    433 sepastore->ncuts--;
    434
    435 return SCIP_OKAY;
    436}
    437
    438/** adds cut to separation storage and captures it */
    440 SCIP_SEPASTORE* sepastore, /**< separation storage */
    441 BMS_BLKMEM* blkmem, /**< block memory */
    442 SCIP_SET* set, /**< global SCIP settings */
    443 SCIP_STAT* stat, /**< problem statistics data */
    444 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    445 SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
    446 SCIP_LP* lp, /**< LP data */
    447 SCIP_ROW* cut, /**< separated cut */
    448 SCIP_Bool forcecut, /**< should the cut be forced to enter the LP? */
    449 SCIP_Bool root, /**< are we at the root node? */
    450 SCIP_Bool* infeasible /**< pointer to store whether the cut is infeasible */
    451 )
    452{
    453 SCIP_Bool redundant;
    454 int pos;
    455
    456 assert(sepastore != NULL);
    457 assert(sepastore->nforcedcuts <= sepastore->ncuts);
    458 assert(set != NULL);
    459 assert(cut != NULL);
    461 assert(eventqueue != NULL);
    462 assert(eventfilter != NULL);
    463
    464 /* debug: check cut for feasibility */
    465 SCIP_CALL( SCIPdebugCheckRow(set, cut) ); /*lint !e506 !e774*/
    466
    467 /* the cut will be forced to enter the LP if the dual must be collected and the initial LP is being constructed */
    468 forcecut = forcecut || (set->lp_alwaysgetduals && sepastore->initiallp);
    469
    470 /* in the root node, every local cut is a global cut, and global cuts are nicer in many ways ... */
    471 if( root && SCIProwIsLocal(cut) )
    472 {
    473 SCIPsetDebugMsg(set, "change local flag of cut <%s> to FALSE due to addition in root node\n", SCIProwGetName(cut));
    474
    476
    477 assert(!SCIProwIsLocal(cut));
    478 }
    479
    480 /* check cut for redundancy or infeasibility */
    481 redundant = sepastoreIsCutRedundantOrInfeasible(sepastore, set, stat, cut, infeasible);
    482 /* Note that we add infeasible rows in any case, since we cannot be sure whether the return values are handled
    483 * correctly. In this way, the LP becomes infeasible. */
    484
    485 /* in each separation round, make sure that at least one (even redundant) cut enters the LP to avoid cycling */
    486 if( !forcecut && sepastore->ncuts > 0 && redundant )
    487 return SCIP_OKAY;
    488
    489 /* if only one cut is currently present in sepastore, it could be redundant; in this case, it can now be removed
    490 * again, because now a non redundant cut enters the sepastore */
    491 if( sepastore->ncuts == 1 && sepastoreIsCutRedundant(sepastore, set, stat, sepastore->cuts[0]) )
    492 {
    493 /* check, if the row deletions from separation storage events are tracked if so, issue ROWDELETEDSEPA event */
    494 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDSEPA) != 0 )
    495 {
    496 SCIP_EVENT* event;
    497
    498 SCIP_CALL( SCIPeventCreateRowDeletedSepa(&event, blkmem, sepastore->cuts[0]) );
    499 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
    500 }
    501 /* update statistics of total number of found cuts */
    502 if( !sepastore->initiallp )
    503 {
    504 sepastore->ncutsadded--;
    505 if( sepastore->cuts[0]->fromcutpool )
    506 sepastore->ncutsaddedviapool--;
    507 else
    508 sepastore->ncutsaddeddirect--;
    509
    511 {
    512 SCIP_SEPA* sepa;
    513 sepa = SCIProwGetOriginSepa(sepastore->cuts[0]);
    514 SCIPsepaDecNCutsAdded(sepa, sepastore->cuts[0]->fromcutpool);
    515 }
    516 }
    517
    518 SCIP_CALL( SCIProwRelease(&sepastore->cuts[0], blkmem, set, lp) );
    519 sepastore->ncuts = 0;
    520 sepastore->nforcedcuts = 0;
    521 }
    522
    523 /* a cut is forced to enter the LP if
    524 * - we construct the initial LP, or
    525 * - it has infinite score factor, or
    526 * - it is a bound change that can be applied
    527 * if it is a non-forced cut and no cuts should be added, abort
    528 */
    529 forcecut = forcecut || sepastore->initiallp || sepastore->forcecuts || (!SCIProwIsModifiable(cut) && SCIProwGetNNonz(cut) == 1 && sepastoreIsBdchgApplicable(set, cut));
    530 if( !forcecut && SCIPsetGetSepaMaxcuts(set, root) == 0 )
    531 return SCIP_OKAY;
    532
    533 /* get enough memory to store the cut */
    534 SCIP_CALL( sepastoreEnsureCutsMem(sepastore, set, sepastore->ncuts+1) );
    535 assert(sepastore->ncuts < sepastore->cutssize);
    536
    537 SCIPsetDebugMsg(set, "adding cut <%s> to separation storage of size %d (forcecut=%u, len=%d)\n",
    538 SCIProwGetName(cut), sepastore->ncuts, forcecut, SCIProwGetNNonz(cut));
    539 /*SCIP_CALL( SCIPprintRow(set->scip, cut, NULL) );*/
    540
    541 /* capture the cut */
    542 SCIProwCapture(cut);
    543
    544 /* add cut to arrays */
    545 if( forcecut )
    546 {
    547 /* make room at the beginning of the array for forced cut */
    548 pos = sepastore->nforcedcuts;
    549 sepastore->cuts[sepastore->ncuts] = sepastore->cuts[pos];
    550 sepastore->nforcedcuts++;
    551 }
    552 else
    553 pos = sepastore->ncuts;
    554
    555 sepastore->cuts[pos] = cut;
    556
    557 /* update statistics of total number of found cuts */
    558 if( !sepastore->initiallp )
    559 {
    560 sepastore->ncutsadded++;
    561 sepastore->ncutsfoundround++;
    562 if( cut->fromcutpool )
    563 sepastore->ncutsaddedviapool++;
    564 else
    565 sepastore->ncutsaddeddirect++;
    566
    568 {
    569 SCIP_SEPA* sepa;
    570
    571 sepa = SCIProwGetOriginSepa(cut);
    573 }
    574 }
    575 sepastore->ncuts++;
    576
    577 /* check, if the row addition to separation storage events are tracked if so, issue ROWADDEDSEPA event */
    578 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWADDEDSEPA) != 0 )
    579 {
    580 SCIP_EVENT* event;
    581
    582 SCIP_CALL( SCIPeventCreateRowAddedSepa(&event, blkmem, cut) );
    583 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
    584 }
    585
    586 /* If the duals need to be collected, then the infeasible flag is set to FALSE. This ensures that the LP is solved */
    587 if( set->lp_alwaysgetduals && sepastore->initiallp )
    588 (*infeasible) = FALSE;
    589
    590 return SCIP_OKAY;
    591}
    592
    593/** applies a lower bound change */
    594static
    596 SCIP_SEPASTORE* sepastore, /**< separation storage */
    597 BMS_BLKMEM* blkmem, /**< block memory */
    598 SCIP_SET* set, /**< global SCIP settings */
    599 SCIP_STAT* stat, /**< problem statistics */
    600 SCIP_PROB* transprob, /**< transformed problem */
    601 SCIP_PROB* origprob, /**< original problem */
    602 SCIP_TREE* tree, /**< branch and bound tree */
    603 SCIP_REOPT* reopt, /**< reoptimization data structure */
    604 SCIP_LP* lp, /**< LP data */
    605 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    606 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    607 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    608 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    609 SCIP_VAR* var, /**< problem variable */
    610 SCIP_Real bound, /**< new lower bound of variable */
    611 SCIP_Bool local, /**< is it a local bound change? (otherwise global) */
    612 SCIP_Bool* applied, /**< pointer to store whether the domain change was applied */
    613 SCIP_Bool* cutoff /**< pointer to store TRUE, if an infeasibility has been detected */
    614 )
    615{
    616 assert(sepastore != NULL);
    617 assert(cutoff != NULL);
    618 assert(applied != NULL);
    619
    620 /* adjust bound to the one that would be applied, so the SCIPsetIsGT check below is more reliable */
    621 SCIPvarAdjustLb(var, set, &bound);
    622
    623 if( local )
    624 {
    625 /* apply the local bound change or detect a cutoff */
    627 {
    628 SCIPsetDebugMsg(set, " -> applying bound change: <%s>: [%.15g,%.15g] -> [%.15g,%.15g]\n",
    630
    631 /* changing the lower bound to a value >= SCIPinfinity should result in a cutoff,
    632 * since "infinite" values in solutions are reserved for another meaning
    633 */
    635 {
    636 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob, tree,
    637 reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, bound, SCIP_BOUNDTYPE_LOWER, FALSE) );
    638 }
    639 else
    640 *cutoff = TRUE;
    641
    642 *applied = TRUE;
    643 }
    644 else
    645 {
    646 SCIPsetDebugMsg(set, " -> ignoring bound change: <%s>: [%.15g,%.15g] -> [%.15g,%.15g]\n",
    648 }
    649 }
    650 else
    651 {
    652 /* apply the global bound change or detect a global cutoff which means we can cutoff the root node */
    654 {
    655 SCIPsetDebugMsg(set, " -> applying global bound change: <%s>: [%.15g,%.15g] -> [%.15g,%.15g]\n",
    657
    658 /* changing the lower bound to a value >= SCIPinfinity should result in a cutoff,
    659 * since "infinite" values in solutions are reserved for another meaning
    660 */
    662 {
    663 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob, tree, reopt,
    664 lp, branchcand, eventqueue, eventfilter, cliquetable, var, bound, SCIP_BOUNDTYPE_LOWER, FALSE) );
    665 }
    666 else
    667 {
    668 /* we are done with solving since a global bound change is infeasible */
    669 SCIP_CALL( SCIPnodeCutoff(SCIPtreeGetRootNode(tree), set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
    670 *cutoff = TRUE;
    671 }
    672
    673 *applied = TRUE;
    674 }
    675 else
    676 {
    677 SCIPsetDebugMsg(set, " -> ignoring global bound change: <%s>: [%.15g,%.15g] -> [%.15g,%.15g]\n",
    679 }
    680 }
    681
    682 return SCIP_OKAY;
    683}
    684
    685/** applies an upper bound change */
    686static
    688 SCIP_SEPASTORE* sepastore, /**< separation storage */
    689 BMS_BLKMEM* blkmem, /**< block memory */
    690 SCIP_SET* set, /**< global SCIP settings */
    691 SCIP_STAT* stat, /**< problem statistics */
    692 SCIP_PROB* transprob, /**< transformed problem */
    693 SCIP_PROB* origprob, /**< original problem */
    694 SCIP_TREE* tree, /**< branch and bound tree */
    695 SCIP_REOPT* reopt, /**< reoptimization data structure */
    696 SCIP_LP* lp, /**< LP data */
    697 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    698 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    699 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    700 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    701 SCIP_VAR* var, /**< problem variable */
    702 SCIP_Real bound, /**< new upper bound of variable */
    703 SCIP_Bool local, /**< is it a local bound change? (otherwise global) */
    704 SCIP_Bool* applied, /**< pointer to store whether the domain change was applied */
    705 SCIP_Bool* cutoff /**< pointer to store TRUE, if an infeasibility has been detected */
    706 )
    707{
    708 assert(sepastore != NULL);
    709 assert(cutoff != NULL);
    710 assert(applied != NULL);
    711
    712 /* adjust bound to the one that would be applied, so the SCIPsetIsGT check below is more reliable */
    713 SCIPvarAdjustUb(var, set, &bound);
    714
    715 if( local )
    716 {
    717 /* apply the local bound change or detect a cutoff */
    719 {
    720 SCIPsetDebugMsg(set, " -> applying bound change: <%s>: [%.15g,%.15g] -> [%.15g,%.15g]\n",
    722
    723 /* changing the upper bound to a value <= -SCIPinfinity should result in a cutoff,
    724 * since "infinite" values in solutions are reserved for another meaning
    725 */
    727 {
    728 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob, tree,
    729 reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, bound, SCIP_BOUNDTYPE_UPPER, FALSE) );
    730 }
    731 else
    732 *cutoff = TRUE;
    733
    734 *applied = TRUE;
    735 }
    736 else
    737 {
    738 SCIPsetDebugMsg(set, " -> ignoring bound change: <%s>: [%.15g,%.15g] -> [%.15g,%.15g]\n",
    740 }
    741 }
    742 else
    743 {
    744 /* apply the global bound change or detect a global cutoff which means we can cutoff the root node */
    746 {
    747 SCIPsetDebugMsg(set, " -> applying global bound change: <%s>: [%.15g,%.15g] -> [%.15g,%.15g]\n",
    749
    750 /* changing the upper bound to a value <= -SCIPinfinity should result in a cutoff,
    751 * since "infinite" values in solutions are reserved for another meaning
    752 */
    754 {
    755 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob, tree, reopt,
    756 lp, branchcand, eventqueue, eventfilter, cliquetable, var, bound, SCIP_BOUNDTYPE_UPPER, FALSE) );
    757 }
    758 else
    759 {
    760 /* we are done with solving since a global bound change is infeasible */
    761 SCIP_CALL( SCIPnodeCutoff(SCIPtreeGetRootNode(tree), set, stat, eventfilter, tree, transprob, origprob, reopt, lp, blkmem) );
    762 *cutoff = TRUE;
    763 }
    764
    765 *applied = TRUE;
    766 }
    767 else
    768 {
    769 SCIPsetDebugMsg(set, " -> ignoring global bound change: <%s>: [%.15g,%.15g] -> [%.15g,%.15g]\n",
    771 }
    772 }
    773
    774 return SCIP_OKAY;
    775}
    776
    777/** applies a cut that is a bound change directly as bound change instead of adding it as row to the LP */
    778static
    780 SCIP_SEPASTORE* sepastore, /**< separation storage */
    781 BMS_BLKMEM* blkmem, /**< block memory */
    782 SCIP_SET* set, /**< global SCIP settings */
    783 SCIP_STAT* stat, /**< problem statistics */
    784 SCIP_PROB* transprob, /**< transformed problem */
    785 SCIP_PROB* origprob, /**< original problem */
    786 SCIP_TREE* tree, /**< branch and bound tree */
    787 SCIP_REOPT* reopt, /**< reoptimization data structure */
    788 SCIP_LP* lp, /**< LP data */
    789 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    790 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    791 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    792 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    793 SCIP_ROW* cut, /**< cut with a single variable */
    794 SCIP_Bool* applied, /**< pointer to store whether the domain change was applied */
    795 SCIP_Bool* cutoff /**< pointer to store whether an empty domain was created */
    796 )
    797{
    798 SCIP_COL** cols;
    799 SCIP_Real* vals;
    800 SCIP_VAR* var;
    801 SCIP_Real lhs;
    802 SCIP_Real rhs;
    803 SCIP_Bool local;
    804
    805 assert(sepastore != NULL);
    806 assert(!SCIProwIsModifiable(cut));
    807 assert(SCIProwGetNNonz(cut) == 1);
    808 assert(cutoff != NULL);
    809 assert(applied != NULL);
    810
    811 *applied = FALSE;
    812 *cutoff = FALSE;
    813
    814 /* get the single variable and its coefficient of the cut */
    815 cols = SCIProwGetCols(cut);
    816 assert(cols != NULL);
    817
    818 var = SCIPcolGetVar(cols[0]);
    819 vals = SCIProwGetVals(cut);
    820 assert(vals != NULL);
    821 assert(!SCIPsetIsZero(set, vals[0]));
    822
    823 /* if the coefficient is nearly zero, we better ignore this cut for numerical reasons */
    824 if( SCIPsetIsFeasZero(set, vals[0]) )
    825 return SCIP_OKAY;
    826
    827 local = SCIProwIsLocal(cut);
    828
    829 /* get the left hand side of the cut and convert it to a bound */
    830 lhs = SCIProwGetLhs(cut);
    831 if( !SCIPsetIsInfinity(set, -lhs) )
    832 {
    833 lhs -= SCIProwGetConstant(cut);
    834 if( vals[0] > 0.0 )
    835 {
    836 /* coefficient is positive -> lhs corresponds to lower bound */
    837 SCIP_CALL( sepastoreApplyLb(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    838 eventfilter, cliquetable, var, lhs/vals[0], local, applied, cutoff) );
    839 }
    840 else
    841 {
    842 /* coefficient is negative -> lhs corresponds to upper bound */
    843 SCIP_CALL( sepastoreApplyUb(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    844 eventfilter, cliquetable, var, lhs/vals[0], local, applied, cutoff) );
    845 }
    846 }
    847
    848 /* get the right hand side of the cut and convert it to a bound */
    849 rhs = SCIProwGetRhs(cut);
    850 if( !SCIPsetIsInfinity(set, rhs) )
    851 {
    852 rhs -= SCIProwGetConstant(cut);
    853 if( vals[0] > 0.0 )
    854 {
    855 /* coefficient is positive -> rhs corresponds to upper bound */
    856 SCIP_CALL( sepastoreApplyUb(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    857 eventfilter, cliquetable, var, rhs/vals[0], local, applied, cutoff) );
    858 }
    859 else
    860 {
    861 /* coefficient is negative -> rhs corresponds to lower bound */
    862 SCIP_CALL( sepastoreApplyLb(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
    863 eventfilter, cliquetable, var, rhs/vals[0], local, applied, cutoff) );
    864 }
    865 }
    866
    867 /* count the bound change as applied cut */
    868 if( *applied && !sepastore->initiallp )
    869 sepastore->ncutsapplied++;
    870
    871 return SCIP_OKAY;
    872}
    873
    874/** applies the given cut to the LP and updates the orthogonalities and scores of remaining cuts */
    875static
    877 SCIP_SEPASTORE* sepastore, /**< separation storage */
    878 BMS_BLKMEM* blkmem, /**< block memory */
    879 SCIP_SET* set, /**< global SCIP settings */
    880 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    881 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    882 SCIP_LP* lp, /**< LP data */
    883 SCIP_ROW* cut, /**< cut to apply to the LP */
    884 int depth, /**< depth of current node */
    885 int* ncutsapplied /**< pointer to count the number of applied cuts */
    886 )
    887{
    888 assert(sepastore != NULL);
    889 assert(ncutsapplied != NULL);
    890
    891 /* a row could have been added twice to the separation store; add it only once! */
    892 if( !SCIProwIsInLP(cut) )
    893 {
    894 /* add cut to the LP and capture it */
    895 SCIP_CALL( SCIPlpAddRow(lp, blkmem, set, eventqueue, eventfilter, cut, depth) );
    896
    897 /* update statistics -> only if we are not in the initial lp (cuts are only counted if added during run) */
    898 if( !sepastore->initiallp )
    899 {
    900 sepastore->ncutsapplied++;
    901
    902 /* increase count of applied cuts for origins of row */
    903 /* TODO: adjust conshdlr statistics to mirror cut statistics */
    904 switch ( (SCIP_ROWORIGINTYPE) cut->origintype )
    905 {
    907 assert( cut->origin != NULL );
    909 break;
    911 assert( cut->origin != NULL );
    913 break;
    915 assert( cut->origin != NULL );
    917 break;
    920 /* do nothing - cannot update statistics */
    921 break;
    922 default:
    923 SCIPerrorMessage("unknown type of row origin.\n");
    924 return SCIP_INVALIDDATA;
    925 }
    926 }
    927
    928 (*ncutsapplied)++;
    929 }
    930
    931 return SCIP_OKAY;
    932}
    933
    934/** adds cuts to the LP and clears separation storage */
    936 SCIP_SEPASTORE* sepastore, /**< separation storage */
    937 BMS_BLKMEM* blkmem, /**< block memory */
    938 SCIP_SET* set, /**< global SCIP settings */
    939 SCIP_STAT* stat, /**< problem statistics */
    940 SCIP_PROB* transprob, /**< transformed problem */
    941 SCIP_PROB* origprob, /**< original problem */
    942 SCIP_TREE* tree, /**< branch and bound tree */
    943 SCIP_REOPT* reopt, /**< reoptimization data structure */
    944 SCIP_LP* lp, /**< LP data */
    945 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
    946 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    947 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
    948 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
    949 SCIP_Bool root, /**< are we at the root node? */
    950 SCIP_EFFICIACYCHOICE efficiacychoice, /**< type of solution to base efficiacy computation on */
    951 SCIP_Bool* cutoff /**< pointer to store whether an empty domain was created */
    952 )
    953{
    954 SCIP_NODE* node;
    955 int maxsepacuts;
    956 int ncutsapplied;
    957 int nselectedcuts;
    958 int depth;
    959 int i;
    960
    961 assert(sepastore != NULL);
    962 assert(set != NULL);
    963 assert(tree != NULL);
    964 assert(lp != NULL);
    965 assert(cutoff != NULL);
    966
    967 SCIP_UNUSED(efficiacychoice);
    968
    969 SCIPsetDebugMsg(set, "selecting from %d cuts\n", sepastore->ncuts);
    970
    971 /* get maximal number of cuts to add to the LP */
    972 maxsepacuts = SCIPsetGetSepaMaxcuts(set, root);
    973
    974 /* if all cuts are forced cuts, no selection is required */
    975 if( sepastore->nforcedcuts >= MIN(sepastore->ncuts, maxsepacuts) )
    976 {
    977 nselectedcuts = sepastore->nforcedcuts;
    978 }
    979 else
    980 {
    981 /* call cut selection algorithms */
    982 nselectedcuts = 0;
    983 SCIP_CALL( SCIPcutselsSelect(set, sepastore->cuts, sepastore->ncuts, sepastore->nforcedcuts, root, sepastore->initiallp, maxsepacuts,
    984 &nselectedcuts) );
    985 assert(nselectedcuts + sepastore->nforcedcuts <= maxsepacuts);
    986
    987 /* note that cut selector statistics are updated here also when in probing mode; this may lead to an offset with
    988 * separator/constraint handler statistics */
    989 /* @todo do not update cutselector statistics if SCIPtreeProbing(scip->tree) */
    990 nselectedcuts += sepastore->nforcedcuts;
    991 }
    992
    993 /*
    994 * apply all selected cuts
    995 */
    996 ncutsapplied = 0;
    997 *cutoff = FALSE;
    998
    999 node = SCIPtreeGetCurrentNode(tree);
    1000 assert(node != NULL);
    1001
    1002 /* get depth of current node */
    1003 depth = SCIPnodeGetDepth(node);
    1004
    1005 for( i = 0; i < nselectedcuts && !(*cutoff); i++ )
    1006 {
    1007 SCIP_ROW* cut;
    1008
    1009 cut = sepastore->cuts[i];
    1010
    1011 if( i < sepastore->nforcedcuts || SCIPsetIsFeasPositive(set, SCIProwGetLPEfficacy(cut, set, stat, lp)) )
    1012 {
    1013 SCIP_Bool applied = FALSE;
    1014
    1015 /* if the cut is a bound change (i.e. a row with only one variable), add it as bound change instead of LP row */
    1016 if( !SCIProwIsModifiable(cut) && SCIProwGetNNonz(cut) == 1 && !set->exact_enable )
    1017 {
    1018 SCIPsetDebugMsg(set, " -> applying forced cut <%s> as boundchange\n", SCIProwGetName(cut));
    1019 SCIP_CALL( sepastoreApplyBdchg(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
    1020 eventqueue, eventfilter, cliquetable, cut, &applied, cutoff) );
    1021 assert(applied || !sepastoreIsBdchgApplicable(set, cut));
    1022 }
    1023
    1024 if( !applied )
    1025 {
    1026 /* create rational representation of the cut; note that this may slightly change the floating-point
    1027 * coefficients
    1028 */
    1029 if( set->exact_enable && SCIProwGetRowExact(cut) == NULL )
    1030 {
    1031 SCIP_Bool poolcut = FALSE;
    1032 if( !SCIProwIsLocal(cut) && !(SCIPisCutNew(set->scip, cut)) )
    1033 {
    1034 poolcut = TRUE;
    1035 SCIP_CALL( SCIPdelPoolCut(set->scip, cut) );
    1036 }
    1037 SCIP_CALL( SCIProwExactCreateFromRow(cut, blkmem, set, stat, eventqueue, transprob, lp->lpexact) );
    1038 if( poolcut )
    1039 {
    1040 SCIP_CALL( SCIPaddPoolCut(set->scip, cut) );
    1041 }
    1042
    1043 SCIP_CALL( SCIPaddRowExact(set->scip, cut->rowexact) );
    1044 }
    1045
    1046 /* add cut to the LP and update orthogonalities */
    1047 SCIPsetDebugMsg(set, " -> applying%s cut <%s>\n", (i < sepastore->nforcedcuts) ? " forced" : "", SCIProwGetName(cut));
    1048 /*SCIPdebug( SCIProwPrint(cut, set->scip->messagehdlr, NULL));*/
    1049 SCIP_CALL( sepastoreApplyCut(sepastore, blkmem, set, eventqueue, eventfilter, lp, cut, depth, &ncutsapplied) );
    1050 }
    1051 }
    1052 }
    1053
    1054 /* clear the separation storage and reset statistics for separation round */
    1055 SCIP_CALL( SCIPsepastoreClearCuts(sepastore, blkmem, set, eventqueue, eventfilter, lp) );
    1056
    1057 return SCIP_OKAY;
    1058}
    1059
    1060/** clears the separation storage without adding the cuts to the LP */
    1062 SCIP_SEPASTORE* sepastore, /**< separation storage */
    1063 BMS_BLKMEM* blkmem, /**< block memory */
    1064 SCIP_SET* set, /**< global SCIP settings */
    1065 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    1066 SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
    1067 SCIP_LP* lp /**< LP data */
    1068 )
    1069{
    1070 int c;
    1071
    1072 assert(sepastore != NULL);
    1073
    1074 SCIPsetDebugMsg(set, "clearing %d cuts\n", sepastore->ncuts);
    1075
    1076 /* release cuts */
    1077 for( c = 0; c < sepastore->ncuts; ++c )
    1078 {
    1079 /* check, if the row deletions from separation storage events are tracked if so, issue ROWDELETEDSEPA event */
    1080 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDSEPA) != 0 )
    1081 {
    1082 SCIP_EVENT* event;
    1083
    1084 SCIP_CALL( SCIPeventCreateRowDeletedSepa(&event, blkmem, sepastore->cuts[c]) );
    1085 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
    1086 }
    1087
    1088 SCIP_CALL( SCIProwRelease(&sepastore->cuts[c], blkmem, set, lp) );
    1089 }
    1090
    1091 /* reset counters */
    1092 sepastore->ncuts = 0;
    1093 sepastore->nforcedcuts = 0;
    1094 sepastore->ncutsfoundround = 0;
    1095
    1096 /* if we have just finished the initial LP construction, free the (potentially large) cuts array */
    1097 if( sepastore->initiallp )
    1098 {
    1099 BMSfreeMemoryArrayNull(&sepastore->cuts);
    1100 sepastore->cutssize = 0;
    1101 }
    1102
    1103 return SCIP_OKAY;
    1104}
    1105
    1106/** removes cuts that are inefficacious w.r.t. the current LP solution from separation storage without adding the cuts to the LP */
    1108 SCIP_SEPASTORE* sepastore, /**< separation storage */
    1109 BMS_BLKMEM* blkmem, /**< block memory */
    1110 SCIP_SET* set, /**< global SCIP settings */
    1111 SCIP_STAT* stat, /**< problem statistics data */
    1112 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    1113 SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
    1114 SCIP_LP* lp, /**< LP data */
    1115 SCIP_Bool root, /**< are we at the root node? */
    1116 SCIP_EFFICIACYCHOICE efficiacychoice /**< type of solution to base efficiacy computation on */
    1117 )
    1118{
    1119 int cnt = 0;
    1120 int c;
    1121
    1122 assert( sepastore != NULL );
    1123
    1124 /* check non-forced cuts only */
    1125 c = sepastore->nforcedcuts;
    1126 while( c < sepastore->ncuts )
    1127 {
    1128 SCIP_Real cutefficacy;
    1129
    1130 /* calculate cut's efficacy */
    1131 switch ( efficiacychoice )
    1132 {
    1134 cutefficacy = SCIProwGetLPEfficacy(sepastore->cuts[c], set, stat, lp);
    1135 break;
    1137 cutefficacy = SCIProwGetRelaxEfficacy(sepastore->cuts[c], set, stat);
    1138 break;
    1140 cutefficacy = SCIProwGetNLPEfficacy(sepastore->cuts[c], set, stat);
    1141 break;
    1142 default:
    1143 SCIPerrorMessage("Invalid efficiacy choice.\n");
    1144 return SCIP_INVALIDCALL;
    1145 }
    1146
    1147 if( !SCIPsetIsEfficacious(set, root, cutefficacy) )
    1148 {
    1149 SCIP_CALL( sepastoreDelCut(sepastore, blkmem, set, eventqueue, eventfilter, lp, c) );
    1150 ++cnt;
    1151 }
    1152 else
    1153 ++c;
    1154 }
    1155 SCIPsetDebugMsg(set, "removed %d non-efficacious cuts\n", cnt);
    1156
    1157 return SCIP_OKAY;
    1158}
    1159
    1160/** indicates whether a cut is applicable
    1161 *
    1162 * A cut is applicable if it is modifiable, not a bound change, or a bound change that changes bounds by at least epsilon.
    1163 */
    1165 SCIP_SET* set, /**< global SCIP settings */
    1166 SCIP_ROW* cut /**< cut to check */
    1167 )
    1168{
    1169 return SCIProwIsModifiable(cut) || SCIProwGetNNonz(cut) != 1 || sepastoreIsBdchgApplicable(set, cut);
    1170}
    1171
    1172/** get cuts in the separation storage */
    1174 SCIP_SEPASTORE* sepastore /**< separation storage */
    1175 )
    1176{
    1177 assert(sepastore != NULL);
    1178
    1179 return sepastore->cuts;
    1180}
    1181
    1182/** get number of cuts in the separation storage */
    1184 SCIP_SEPASTORE* sepastore /**< separation storage */
    1185 )
    1186{
    1187 assert(sepastore != NULL);
    1188
    1189 return sepastore->ncuts;
    1190}
    1191
    1192/** gets the total number of cutting planes added to the separation storage;
    1193 * this is equal to the sum of added cuts directly and via the pool. */
    1195 SCIP_SEPASTORE* sepastore /**< separation storage */
    1196 )
    1197{
    1198 assert(sepastore != NULL);
    1199
    1200 return sepastore->ncutsadded;
    1201}
    1202
    1203/** gets the number of cutting planes added to the separation storage from the cut pool */
    1205 SCIP_SEPASTORE* sepastore /**< separation storage */
    1206 )
    1207{
    1208 assert(sepastore != NULL);
    1209
    1210 return sepastore->ncutsaddedviapool;
    1211}
    1212
    1213/** gets the number of cutting planes added to the separation storage directly */
    1215 SCIP_SEPASTORE* sepastore /**< separation storage */
    1216 )
    1217{
    1218 assert(sepastore != NULL);
    1219
    1220 return sepastore->ncutsaddeddirect;
    1221}
    1222
    1223/** get number of cuts found so far in current separation round */
    1225 SCIP_SEPASTORE* sepastore /**< separation storage */
    1226 )
    1227{
    1228 assert(sepastore != NULL);
    1229
    1230 return sepastore->ncutsfoundround;
    1231}
    1232
    1233/** gets the total number of cutting planes applied to the LP */
    1235 SCIP_SEPASTORE* sepastore /**< separation storage */
    1236 )
    1237{
    1238 assert(sepastore != NULL);
    1239
    1240 return sepastore->ncutsapplied;
    1241}
    static long bound
    void SCIPconshdlrIncNAppliedCuts(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:5062
    internal methods for constraints and constraint handlers
    methods for the aggregation rows
    SCIP_RETCODE SCIPcutselsSelect(SCIP_SET *set, SCIP_ROW **cuts, int ncuts, int nforcedcuts, SCIP_Bool root, SCIP_Bool initiallp, int maxnselectedcuts, int *nselectedcuts)
    Definition: cutsel.c:169
    internal methods for cut selectors
    methods for debugging
    #define SCIPdebugCheckRow(set, row)
    Definition: debug.h:297
    common defines and data types used in all packages of SCIP
    #define NULL
    Definition: def.h:248
    #define SCIP_UNUSED(x)
    Definition: def.h:409
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_ALLOC(x)
    Definition: def.h:366
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPeventqueueAdd(SCIP_EVENTQUEUE *eventqueue, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENT **event)
    Definition: event.c:2561
    SCIP_RETCODE SCIPeventCreateRowAddedSepa(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row)
    Definition: event.c:998
    SCIP_RETCODE SCIPeventCreateRowDeletedSepa(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row)
    Definition: event.c:1017
    internal methods for managing events
    SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
    Definition: lp.c:17425
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8409
    SCIP_RETCODE SCIPaddPoolCut(SCIP *scip, SCIP_ROW *row)
    Definition: scip_cut.c:336
    SCIP_Bool SCIPisCutNew(SCIP *scip, SCIP_ROW *row)
    Definition: scip_cut.c:318
    SCIP_RETCODE SCIPdelPoolCut(SCIP *scip, SCIP_ROW *row)
    Definition: scip_cut.c:356
    SCIP_RETCODE SCIPaddRowExact(SCIP *scip, SCIP_ROWEXACT *rowexact)
    Definition: scip_exact.c:257
    int SCIPnodeGetDepth(SCIP_NODE *node)
    Definition: tree.c:8493
    SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
    Definition: lp.c:17686
    SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
    Definition: lp.c:17805
    int SCIProwGetNNonz(SCIP_ROW *row)
    Definition: lp.c:17607
    SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
    Definition: lp.c:17632
    SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
    Definition: lp.c:17696
    SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
    Definition: lp.c:17795
    const char * SCIProwGetName(SCIP_ROW *row)
    Definition: lp.c:17745
    SCIP_SEPA * SCIProwGetOriginSepa(SCIP_ROW *row)
    Definition: lp.c:17870
    SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
    Definition: lp.c:17652
    SCIP_ROWEXACT * SCIProwGetRowExact(SCIP_ROW *row)
    Definition: lp.c:17959
    SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
    Definition: lp.c:17917
    SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
    Definition: lp.c:17642
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_Real SCIProwGetRelaxEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
    Definition: lp.c:7170
    void SCIProwCapture(SCIP_ROW *row)
    Definition: lp.c:5554
    SCIP_Real SCIProwGetMaxActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
    Definition: lp.c:6849
    SCIP_Real SCIProwGetNLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
    Definition: lp.c:7210
    SCIP_RETCODE SCIProwChgLocal(SCIP_ROW *row, SCIP_Bool local)
    Definition: lp.c:5946
    SCIP_Real SCIProwGetLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
    Definition: lp.c:7054
    SCIP_RETCODE SCIPlpAddRow(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_ROW *row, int depth)
    Definition: lp.c:9759
    SCIP_Real SCIProwGetMinActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
    Definition: lp.c:6828
    SCIP_RETCODE SCIProwRelease(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
    Definition: lp.c:5567
    internal methods for LP management
    SCIP_RETCODE SCIProwExactCreateFromRow(SCIP_ROW *fprow, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LPEXACT *lpexact)
    Definition: lpexact.c:3373
    internal methods for exact LP management
    #define BMSfreeMemory(ptr)
    Definition: memory.h:145
    #define BMSreallocMemoryArray(ptr, num)
    Definition: memory.h:127
    struct BMS_BlkMem BMS_BLKMEM
    Definition: memory.h:437
    #define BMSfreeMemoryArrayNull(ptr)
    Definition: memory.h:148
    #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
    public methods for LP management
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    data structures and methods for collecting reoptimization information
    SCIP callable library.
    public methods for the LP relaxation, rows and columns
    void SCIPsepaDecNCutsAdded(SCIP_SEPA *sepa, SCIP_Bool fromcutpool)
    Definition: sepa.c:1029
    void SCIPsepaIncNCutsApplied(SCIP_SEPA *sepa, SCIP_Bool fromcutpool)
    Definition: sepa.c:984
    void SCIPsepaIncNCutsAdded(SCIP_SEPA *sepa, SCIP_Bool fromcutpool)
    Definition: sepa.c:1006
    internal methods for separators
    static SCIP_Bool sepastoreIsBdchgApplicable(SCIP_SET *set, SCIP_ROW *cut)
    Definition: sepastore.c:286
    int SCIPsepastoreGetNCutsFoundRound(SCIP_SEPASTORE *sepastore)
    Definition: sepastore.c:1224
    void SCIPsepastoreEndInitialLP(SCIP_SEPASTORE *sepastore)
    Definition: sepastore.c:147
    static SCIP_RETCODE sepastoreApplyBdchg(SCIP_SEPASTORE *sepastore, 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_ROW *cut, SCIP_Bool *applied, SCIP_Bool *cutoff)
    Definition: sepastore.c:779
    SCIP_RETCODE SCIPsepastoreCreate(SCIP_SEPASTORE **sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set)
    Definition: sepastore.c:90
    SCIP_RETCODE SCIPsepastoreClearCuts(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp)
    Definition: sepastore.c:1061
    int SCIPsepastoreGetNCutsAddedViaPool(SCIP_SEPASTORE *sepastore)
    Definition: sepastore.c:1204
    int SCIPsepastoreGetNCuts(SCIP_SEPASTORE *sepastore)
    Definition: sepastore.c:1183
    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
    static SCIP_RETCODE sepastoreApplyUb(SCIP_SEPASTORE *sepastore, 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 bound, SCIP_Bool local, SCIP_Bool *applied, SCIP_Bool *cutoff)
    Definition: sepastore.c:687
    void SCIPsepastoreStartForceCuts(SCIP_SEPASTORE *sepastore)
    Definition: sepastore.c:159
    void SCIPsepastoreEndForceCuts(SCIP_SEPASTORE *sepastore)
    Definition: sepastore.c:170
    static SCIP_RETCODE sepastoreApplyLb(SCIP_SEPASTORE *sepastore, 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 bound, SCIP_Bool local, SCIP_Bool *applied, SCIP_Bool *cutoff)
    Definition: sepastore.c:595
    static SCIP_Bool sepastoreIsCutRedundant(SCIP_SEPASTORE *sepastore, SCIP_SET *set, SCIP_STAT *stat, SCIP_ROW *cut)
    Definition: sepastore.c:182
    SCIP_RETCODE SCIPsepastoreRemoveInefficaciousCuts(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_Bool root, SCIP_EFFICIACYCHOICE efficiacychoice)
    Definition: sepastore.c:1107
    void SCIPsepastoreStartInitialLP(SCIP_SEPASTORE *sepastore)
    Definition: sepastore.c:135
    static SCIP_RETCODE sepastoreApplyCut(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_ROW *cut, int depth, int *ncutsapplied)
    Definition: sepastore.c:876
    static SCIP_Bool sepastoreIsCutRedundantOrInfeasible(SCIP_SEPASTORE *sepastore, SCIP_SET *set, SCIP_STAT *stat, SCIP_ROW *cut, SCIP_Bool *infeasible)
    Definition: sepastore.c:225
    SCIP_RETCODE SCIPsepastoreFree(SCIP_SEPASTORE **sepastore, BMS_BLKMEM *blkmem)
    Definition: sepastore.c:118
    SCIP_RETCODE SCIPsepastoreApplyCuts(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool root, SCIP_EFFICIACYCHOICE efficiacychoice, SCIP_Bool *cutoff)
    Definition: sepastore.c:935
    static SCIP_RETCODE sepastoreDelCut(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, int pos)
    Definition: sepastore.c:390
    int SCIPsepastoreGetNCutsApplied(SCIP_SEPASTORE *sepastore)
    Definition: sepastore.c:1234
    SCIP_ROW ** SCIPsepastoreGetCuts(SCIP_SEPASTORE *sepastore)
    Definition: sepastore.c:1173
    int SCIPsepastoreGetNCutsAddedDirect(SCIP_SEPASTORE *sepastore)
    Definition: sepastore.c:1214
    static SCIP_RETCODE sepastoreEnsureCutsMem(SCIP_SEPASTORE *sepastore, SCIP_SET *set, int num)
    Definition: sepastore.c:67
    SCIP_Bool SCIPsepastoreIsCutApplicable(SCIP_SET *set, SCIP_ROW *cut)
    Definition: sepastore.c:1164
    int SCIPsepastoreGetNCutsAdded(SCIP_SEPASTORE *sepastore)
    Definition: sepastore.c:1194
    internal methods for storing separated cuts
    SCIP_Bool SCIPsetIsEfficacious(SCIP_SET *set, SCIP_Bool root, SCIP_Real efficacy)
    Definition: set.c:7447
    SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:7076
    SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:7087
    int SCIPsetGetSepaMaxcuts(SCIP_SET *set, SCIP_Bool root)
    Definition: set.c:6233
    SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:7017
    SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6993
    SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6577
    SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:7065
    SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6969
    SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6557
    SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6515
    SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6597
    SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6637
    SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:7041
    int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
    Definition: set.c:6080
    unsigned int SCIPsetInitializeRandomSeed(SCIP_SET *set, unsigned int initialseedvalue)
    Definition: set.c:7800
    internal methods for global SCIP settings
    #define SCIPsetDebugMsg
    Definition: set.h:1811
    internal methods for problem statistics
    SCIP_EVENTTYPE eventmask
    Definition: struct_event.h:211
    SCIP_LPEXACT * lpexact
    Definition: struct_lp.h:309
    unsigned int origintype
    Definition: struct_lp.h:270
    SCIP_ROWEXACT * rowexact
    Definition: struct_lp.h:235
    void * origin
    Definition: struct_lp.h:228
    unsigned int fromcutpool
    Definition: struct_lp.h:254
    SCIP_Bool initiallp
    SCIP_Bool forcecuts
    SCIP_ROW ** cuts
    datastructures for managing events
    datastructures for storing conflicts
    Definition: heur_padm.c:135
    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
    SCIP_RETCODE SCIPnodeCutoff(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_REOPT *reopt, SCIP_LP *lp, BMS_BLKMEM *blkmem)
    Definition: tree.c:1259
    SCIP_NODE * SCIPtreeGetCurrentNode(SCIP_TREE *tree)
    Definition: tree.c:9462
    SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
    Definition: tree.c:9529
    internal methods for branch and bound tree
    #define SCIP_EVENTTYPE_ROWDELETEDSEPA
    Definition: type_event.h:110
    #define SCIP_EVENTTYPE_ROWADDEDSEPA
    Definition: type_event.h:109
    enum SCIP_RowOriginType SCIP_ROWORIGINTYPE
    Definition: type_lp.h:79
    @ SCIP_ROWORIGINTYPE_CONSHDLR
    Definition: type_lp.h:74
    @ SCIP_ROWORIGINTYPE_REOPT
    Definition: type_lp.h:77
    @ SCIP_ROWORIGINTYPE_UNSPEC
    Definition: type_lp.h:73
    @ SCIP_ROWORIGINTYPE_SEPA
    Definition: type_lp.h:76
    @ SCIP_ROWORIGINTYPE_CONS
    Definition: type_lp.h:75
    @ SCIP_BOUNDTYPE_UPPER
    Definition: type_lp.h:58
    @ SCIP_BOUNDTYPE_LOWER
    Definition: type_lp.h:57
    @ 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_EFFICIACYCHOICE_LP
    @ SCIP_EFFICIACYCHOICE_RELAX
    @ SCIP_EFFICIACYCHOICE_NLP
    enum SCIP_Efficiacychoice SCIP_EFFICIACYCHOICE
    void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
    Definition: var.c:9910
    void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
    Definition: var.c:9961
    internal methods for problem variables