Scippy

    SCIP

    Solving Constraint Integer Programs

    prop_pseudoobj.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 prop_pseudoobj.c
    26 * @ingroup DEFPLUGINS_PROP
    27 * @brief Pseudo objective propagator
    28 * @author Tobias Achterberg
    29 * @author Stefan Heinz
    30 *
    31 * This propagator propagates the objective function using the cutoff bound and the pseudo objective value. The pseudo
    32 * objective value can be seen as minimum activity of the linear objective function. Using this, this propagator checks
    33 * if variables with non-zero objective coefficients can exceed the cutoff bound. If this is the case the corresponding
    34 * bound can be tightened.
    35 *
    36 * @todo use the complete implication to initialize the objective implication data structure
    37 */
    38
    39/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    40
    42#include "scip/prop_pseudoobj.h"
    43#include "scip/pub_event.h"
    44#include "scip/pub_implics.h"
    45#include "scip/pub_message.h"
    46#include "scip/pub_misc.h"
    47#include "scip/pub_misc_sort.h"
    48#include "scip/pub_prop.h"
    49#include "scip/pub_var.h"
    50#include "scip/scip_conflict.h"
    51#include "scip/scip_event.h"
    52#include "scip/scip_general.h"
    53#include "scip/scip_lp.h"
    54#include "scip/scip_mem.h"
    55#include "scip/scip_message.h"
    56#include "scip/scip_numerics.h"
    57#include "scip/scip_param.h"
    58#include "scip/scip_pricer.h"
    59#include "scip/scip_prob.h"
    60#include "scip/scip_probing.h"
    61#include "scip/scip_prop.h"
    63#include "scip/scip_tree.h"
    64#include "scip/scip_var.h"
    65#include "scip/dbldblarith.h"
    66#include <string.h>
    67
    68#define PROP_NAME "pseudoobj"
    69#define PROP_DESC "pseudo objective function propagator"
    70#define PROP_TIMING SCIP_PROPTIMING_BEFORELP | SCIP_PROPTIMING_DURINGLPLOOP | SCIP_PROPTIMING_AFTERLPLOOP
    71#define PROP_PRIORITY 3000000 /**< propagator priority */
    72#define PROP_FREQ 1 /**< propagator frequency */
    73#define PROP_DELAY FALSE /**< should propagation method be delayed, if other propagators found reductions? */
    74#define PROP_PRESOL_PRIORITY +6000000 /**< priority of the presolving method (>= 0: before, < 0: after constraint handlers); combined with presolvers */
    75#define PROP_PRESOL_MAXROUNDS -1 /**< maximal number of presolving rounds the presolver participates in (-1: no
    76 * limit) */
    77#define PROP_PRESOLTIMING SCIP_PRESOLTIMING_FAST /* timing of the presolving method (fast, medium, or exhaustive) */
    78
    79#define EVENTHDLR_NAME "pseudoobj"
    80#define EVENTHDLR_DESC "bound change event handler for pseudo objective function propagator"
    81
    82#define DEFAULT_MINUSELESS 100 /**< minimal number of successive non-binary variable propagator whithout a
    83 * bound reduction before aborted */
    84#define DEFAULT_MAXVARSFRAC 0.1 /**< maximal fraction of non-binary variables with non-zero objective
    85 * without a bound reduction before aborted */
    86#define DEFAULT_PROPFULLINROOT TRUE /**< do we want to propagate all non-binary variables if we are propagating the root node? */
    87#define DEFAULT_PROPCUTOFFBOUND TRUE /**< propagate new cutoff bound directly globally */
    88#define DEFAULT_FORCE FALSE /**< should the propagator be forced even if active pricer are present? Note that
    89 * can be done if it is known that the pseudo objective activity is given by
    90 * the zero bound for all variables which are currently not present in the
    91 * problem */
    92#define DEFAULT_MAXNEWVARS 1000 /**< number of variable added after the propagator is reinitialized? */
    93#define DEFAULT_PROPUSEIMPLICS TRUE /**< use implications to strengthen the propagation of binary variable (increasing the objective change)? */
    94#define DEFAULT_RESPROPUSEIMPLICS TRUE /**< use implications to strengthen the resolve propagation of binary variable (increasing the objective change)? */
    95#define DEFAULT_MAXIMPLVARS 50000 /**< maximum number of binary variables the implications are used if turned on (-1: unlimited)? */
    96
    97
    98/*
    99 * Data structures
    100 */
    101
    102/** implication data structure for objective contributions of a binary variable */
    104{
    105 SCIP_VAR** objvars; /**< variables y in implications y == 0 or y == 1, first we store the
    106 * implications by x == 0 and second the implications x == 1 */
    107 SCIP_Real maxobjchg; /**< maximum objective contribution if variables x is fixed to zero or one */
    108 int nlbimpls; /**< number of all implications result through for x == 0 */
    109 int nubimpls; /**< number of all implications result through for x == 1 */
    110 int size; /**< size of the objvars array */
    111};
    112typedef struct SCIP_ObjImplics SCIP_OBJIMPLICS; /**< implications in the form x == 0 or x == 1 ==> y == 0 or y == 1 for (x and y binary) */
    113
    114
    115/** propagator data */
    116struct SCIP_PropData
    117{
    118 SCIP_EVENTHDLR* eventhdlr; /**< event handler for global bound change events */
    119 SCIP_VAR** minactvars; /**< binary variables with non-zero objective contribution w.r.t. minimum activity of the objective function */
    120 SCIP_OBJIMPLICS** minactimpls; /**< implication data structure for the binary variables w.r.t. minimum activity */
    121 SCIP_VAR** maxactvars; /**< binary variables with non-zero objective contribution w.r.t. maximum activity of the objective function */
    122 SCIP_Real* maxactchgs; /**< the maximal potential change of the objective if the binary variable
    123 * is fixed to its best bound w.r.t. maximum activity of the objective function */
    124
    125 SCIP_VAR** objintvars; /**< non-binary variable with non-zero objective coefficient */
    126 SCIP_HASHTABLE* addedvars; /**< hash table used during resolving of a bound change (conflict analysis) */
    127 SCIP_Real lastlowerbound; /**< last lower bound which was propagated */
    128 SCIP_Real cutoffbound; /**< last cutoff bound used for propagation */
    129 SCIP_Real glbpseudoobjval; /**< last global pseudo objective used in presolving */
    130 SCIP_Real maxvarsfrac; /**< maximal fraction of non-binary variables with non-zero objective
    131 * without a bound reduction before aborted
    132 */
    133 SCIP_Real maxpseudoobjact; /**< maximal global pseudo objective activity */
    134 int maxpseudoobjactinf; /**< number of coefficients contributing with infinite value to maxpseudoobjact */
    135 int nminactvars; /**< number of binary variables with non-zero objective contribution w.r.t. minimum activity of the objective function */
    136 int nmaxactvars; /**< number of binary variables with non-zero objective contribution w.r.t. maximum activity of the objective function */
    137 int nobjintvars; /**< number of non-binary variables with non-zero objective */
    138 int minuseless; /**< minimal number of successive non-binary variable propagator whithout
    139 * a bound reduction before aborted
    140 */
    141 int lastvarnum; /**< last non-binary variable number that was looked at */
    142 int glbfirstnonfixed; /**< index of first globally non-fixed binary variable in minactvars array */
    143 int maxactfirstnonfixed;/**< index of first globally non-fixed binary variable in maxctvars array */
    144 int firstnonfixed; /**< index of first locally non-fixed binary variable in minactvars array */
    145 int nnewvars; /**< counter for counting number of new variables added */
    146 int maxnewvars; /**< number of variable added after the propagator is reinitialized? */
    147 int maximplvars; /**< maximum number of binary variables the implications are used if turned on (-1: unlimited)? */
    148 int minactsize; /**< size of minactvars and minactimpls array */
    149 int maxactsize; /**< size of maxactvars and maxactchgs array */
    150 int objintvarssize; /**< size of objintvars array*/
    151 SCIP_Bool glbpropagated; /**< are global domains propagated */
    152 SCIP_Bool propfullinroot; /**< do we want to propagate all non-binary variables if we are propagating the root node */
    153 SCIP_Bool propcutoffbound; /**< propagate new cutoff bound directly globally */
    154 SCIP_Bool force; /**< should the propagator be forced even if active pricer are present? */
    155 SCIP_Bool catchvaradded; /**< do we catch the variable added event? */
    156 SCIP_Bool propuseimplics; /**< use implications to strengthen the propagation of binary variable (increasing the objective change)? */
    157 SCIP_Bool respropuseimplics; /**< use implications to strengthen the resolve propagation of binary variable (increasing the objective change)? */
    158 SCIP_Bool initialized; /**< is propagator data structure initialized */
    159};
    160
    161/*
    162 * Debug methods
    163 */
    164
    165#ifndef NDEBUG
    166/** check that the implications are applied for a globally fixed variable */
    167static
    169 SCIP* scip, /**< SCIP data structure */
    170 SCIP_VAR* var /**< variable to check the implications */
    171 )
    172{
    173 SCIP_VAR** vars;
    174 SCIP_Real* bounds;
    175 SCIP_BOUNDTYPE* boundtypes;
    176 SCIP_Bool varfixing;
    177 int nvars;
    178 int v;
    179
    180 /* check that the given variable is locally or globally fixed */
    181 assert(SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5);
    182
    183 /* get fixed value */
    184 varfixing = SCIPvarGetLbGlobal(var) > 0.5;
    185
    186 vars = SCIPvarGetImplVars(var, varfixing);
    187 nvars = SCIPvarGetNImpls(var, varfixing);
    188 bounds = SCIPvarGetImplBounds(var, varfixing);
    189 boundtypes = SCIPvarGetImplTypes(var, varfixing);
    190
    191 /* check that each implication was applied */
    192 for( v = 0; v < nvars; ++v )
    193 {
    194 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
    195 {
    196 SCIP_Real lb;
    197
    198 lb = SCIPvarGetLbGlobal(vars[v]);
    199 assert(SCIPisLE(scip, lb, bounds[v]));
    200 }
    201 else
    202 {
    203 SCIP_Real ub;
    204
    205 assert(boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
    206
    207 ub = SCIPvarGetLbGlobal(vars[v]);
    208 assert(SCIPisGE(scip, ub, bounds[v]));
    209 }
    210 }
    211}
    212
    213/** check if the global fixed indices are correct */
    214static
    216 SCIP_PROPDATA* propdata /**< propagator data */
    217 )
    218{
    219 SCIP_VAR* var;
    220 int v;
    221
    222 for( v = 0; v < propdata->glbfirstnonfixed; ++v )
    223 {
    224 var = propdata->minactvars[v];
    225 assert(var != NULL);
    226
    227 assert(SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5);
    228 }
    229
    230 for( v = 0; v < propdata->maxactfirstnonfixed; ++v )
    231 {
    232 var = propdata->maxactvars[v];
    233 assert(var != NULL);
    234
    235 assert(SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5);
    236 }
    237}
    238#endif /* end of debug methods */
    239
    240/*
    241 * Comparer
    242 */
    243
    244/** compares objective implications w.r.t. their maximum contribution */
    245static
    247{
    248 SCIP_OBJIMPLICS* objimplics1;
    249 SCIP_OBJIMPLICS* objimplics2;
    250
    251 objimplics1 = (SCIP_OBJIMPLICS*)elem1;
    252 objimplics2 = (SCIP_OBJIMPLICS*)elem2;
    253
    254 if( objimplics1->maxobjchg > objimplics2->maxobjchg )
    255 return +1;
    256
    257 if( objimplics1->maxobjchg < objimplics2->maxobjchg )
    258 return -1;
    259
    260 return 0;
    261}
    262
    263/** compare variables w.r.t.
    264 * (i) the absolute value the objective coefficient;
    265 * (ii) the locks which indicate most effect -- for the variables with a positive (negative) objective coefficient the
    266 * down (up) lock is used since this lock indicates that tightened of the upper (lower) bound will triegger
    267 * further domain propagations;
    268 * (iii) the other locks;
    269 * (iv) variable problem index;
    270 */
    271static
    273{
    274 SCIP_VAR* var1;
    275 SCIP_VAR* var2;
    276 int locks1;
    277 int locks2;
    278
    279 var1 = (SCIP_VAR*)elem1;
    280 var2 = (SCIP_VAR*)elem2;
    281
    282 assert(SCIPvarGetObj(var1) != 0.0);
    283 assert(SCIPvarGetObj(var2) != 0.0);
    284
    285 /* first criterion is the absolute value of objective coefficient */
    286 if( REALABS(SCIPvarGetObj(var1)) < REALABS(SCIPvarGetObj(var2)) )
    287 return -1;
    288 else if( REALABS(SCIPvarGetObj(var1)) > REALABS(SCIPvarGetObj(var2)) )
    289 return +1;
    290
    291 /* second criterion the locks which indicate most effect */
    292 if( SCIPvarGetObj(var1) > 0.0 )
    294 else
    296
    297 if( SCIPvarGetObj(var2) > 0.0 )
    299 else
    301
    302 if( locks1 < locks2 )
    303 return -1;
    304 if( locks1 > locks2 )
    305 return 1;
    306
    307 /* third criterion the other locks */
    308 if( SCIPvarGetObj(var1) > 0.0 )
    310 else
    312
    313 if( SCIPvarGetObj(var2) > 0.0 )
    315 else
    317
    318 if( locks1 < locks2 )
    319 return -1;
    320 if( locks1 > locks2 )
    321 return 1;
    322
    323 /* forth criterion use the problem index */
    324 return SCIPvarCompare(var1, var2);
    325}
    326
    327/** hash key retrieval function for cliques*/
    328static
    329SCIP_DECL_HASHGETKEY(cliqueGetHashkey)
    330{ /*lint --e{715}*/
    331 return elem;
    332}
    333
    334/** returns TRUE iff the cliques are equal */
    335static
    336SCIP_DECL_HASHKEYEQ(cliqueIsHashkeyEq)
    337{ /*lint --e{715}*/
    338 if( key1 == key2 )
    339 return TRUE;
    340 return FALSE;
    341}
    342
    343/** returns the hash value of the key */
    344static
    345SCIP_DECL_HASHKEYVAL(cliqueGetHashkeyVal)
    346{ /*lint --e{715}*/
    347 return SCIPcliqueGetId((SCIP_CLIQUE*) key);
    348}
    349
    350/*
    351 * methods for SCIP_OBJIMPLICS data structure
    352 */
    353
    354/** creates an objective implication data structure, fixes (globally) variables which are implied by lower and upper
    355 * bound fixing, and clears the collected arrays for lower and upper bound
    356 */
    357static
    359 SCIP* scip, /**< SCIP data structure */
    360 SCIP_OBJIMPLICS** objimplics, /**< pointer to objective implication data structure */
    361 SCIP_VAR** objvars, /**< objective contributor variables, or NULL */
    362 SCIP_HASHMAP* binobjvarmap, /**< hash map mapping binary variables with none-zero objective to position in collected variables arrays, or NULL */
    363 SCIP_Bool* collectedlbvars, /**< temporary buffer to mark collected variables for lower bound fixing, or NULL */
    364 SCIP_Bool* collectedubvars, /**< temporary buffer to mark collected variables for upper bound fixing, or NULL */
    365 SCIP_Real maxlbobjchg, /**< maximum objective contributor if variables id fixed to zero */
    366 SCIP_Real maxubobjchg, /**< maximum objective contributor if variables id fixed to one */
    367 int nlbimpls, /**< number of variables contributing to to lower bound fix */
    368 int nubimpls /**< number of variables contributing to to upper bound fix */
    369 )
    370
    371{
    372 assert(scip != NULL);
    373 assert(objimplics != NULL);
    374 assert(!SCIPisNegative(scip, maxlbobjchg));
    375 assert(!SCIPisNegative(scip, maxubobjchg));
    376
    377 /* allocate block memory for the implication data structure */
    378 SCIP_CALL( SCIPallocBlockMemory(scip, objimplics) );
    379
    380 if( nlbimpls + nubimpls == 0 )
    381 {
    382 assert(nlbimpls == 0);
    383 assert(nubimpls == 0);
    384 (*objimplics)->objvars = NULL;
    385 (*objimplics)->maxobjchg = 0.0;
    386 (*objimplics)->nlbimpls = 0;
    387 (*objimplics)->nubimpls = 0;
    388 (*objimplics)->size = 0;
    389 }
    390 else
    391 {
    392 SCIP_VAR* var;
    393 int nvars;
    394 int pos;
    395 int v;
    396
    397 assert(objvars != NULL);
    398 assert(binobjvarmap != NULL);
    399 assert(collectedlbvars != NULL);
    400 assert(collectedubvars != NULL);
    401
    402 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*objimplics)->objvars, nlbimpls + nubimpls) );
    403 (*objimplics)->size = nlbimpls + nubimpls;
    404
    405 nvars = 0;
    406
    407 for( v = 0; v < nlbimpls; ++v )
    408 {
    409 var = objvars[v];
    410 assert(var != NULL);
    411 assert(!SCIPisZero(scip, SCIPvarGetObj(var)));
    412
    413 assert(SCIPhashmapExists(binobjvarmap, var));
    414 pos = SCIPhashmapGetImageInt(binobjvarmap, (void*)var);
    415 assert(pos > 0);
    416 assert(collectedlbvars[pos]);
    417
    418 if( collectedubvars[pos] )
    419 {
    420 SCIP_Bool infeasible;
    421 SCIP_Bool tightened;
    422
    424 {
    425 SCIPdebugMsg(scip, "fix variables <%s> to 1.0 due to implications\n", SCIPvarGetName(var));
    426
    427 SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, 1.0, FALSE, &infeasible, &tightened) );
    428 maxlbobjchg -= SCIPvarGetObj(var);
    429 }
    430 else
    431 {
    432 SCIPdebugMsg(scip, "fix variables <%s> to 0.0 due to implications\n", SCIPvarGetName(var));
    433
    434 SCIP_CALL( SCIPtightenVarUbGlobal(scip, var, 0.0, FALSE, &infeasible, &tightened) );
    435 maxlbobjchg += SCIPvarGetObj(var);
    436 }
    437 assert(!infeasible);
    438 assert(tightened);
    439 }
    440 else
    441 {
    442 (*objimplics)->objvars[nvars] = var;
    443 nvars++;
    444 }
    445 collectedlbvars[pos] = FALSE;
    446 }
    447 (*objimplics)->nlbimpls = nvars;
    448
    449 for( v = 0; v < nubimpls; ++v )
    450 {
    451 var = objvars[nlbimpls + v];
    452 assert(var != NULL);
    453 assert(!SCIPisZero(scip, SCIPvarGetObj(var)));
    454
    455 assert(SCIPhashmapExists(binobjvarmap, var));
    456 pos = SCIPhashmapGetImageInt(binobjvarmap, (void*)var);
    457 assert(pos > 0);
    458 assert(collectedubvars[pos]);
    459
    460 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
    461 {
    463 maxubobjchg -= SCIPvarGetObj(var);
    464 else
    465 maxubobjchg += SCIPvarGetObj(var);
    466 }
    467 else
    468 {
    469 (*objimplics)->objvars[nvars] = var;
    470 nvars++;
    471 }
    472 collectedubvars[pos] = FALSE;
    473 }
    474 (*objimplics)->nubimpls = nvars - (*objimplics)->nlbimpls;
    475
    476 /* capture the variables */
    477 for( v = 0; v < nvars; ++v )
    478 {
    479 assert(SCIPvarIsBinary((*objimplics)->objvars[v]));
    480 assert(!SCIPisZero(scip, SCIPvarGetObj((*objimplics)->objvars[v])));
    481 SCIP_CALL( SCIPcaptureVar(scip, (*objimplics)->objvars[v]) );
    482 }
    483 }
    484
    485 (*objimplics)->maxobjchg = MAX(maxlbobjchg, maxubobjchg);
    486
    487 return SCIP_OKAY;
    488}
    489
    490/** frees an objective implication data structure */
    491static
    493 SCIP* scip, /**< SCIP data structure */
    494 SCIP_OBJIMPLICS** objimplics /**< pointer to objective implication data structure */
    495 )
    496{
    497 int v;
    498
    499 assert(scip != NULL);
    500 assert(objimplics != NULL);
    501 assert(*objimplics != NULL);
    502
    503 /* release all variables */
    504 for( v = 0; v < (*objimplics)->nlbimpls + (*objimplics)->nubimpls; ++v )
    505 {
    506 SCIP_CALL( SCIPreleaseVar(scip, &(*objimplics)->objvars[v]) );
    507 }
    508
    509 /* free objective variable array */
    510 SCIPfreeBlockMemoryArrayNull(scip, &(*objimplics)->objvars, (*objimplics)->size);
    511
    512 /* frees block memory for the implication data structure */
    513 SCIPfreeBlockMemory(scip, objimplics);
    514
    515 return SCIP_OKAY;
    516}
    517
    518/** remove the given variable at the given pos from the objective implication data structure */
    519static
    521 SCIP* scip, /**< SCIP data structure */
    522 SCIP_OBJIMPLICS* objimplics, /**< objective implication data structure */
    523 int pos /**< position */
    524 )
    525{
    526 assert(0 <= pos);
    527 assert(pos < objimplics->nlbimpls + objimplics->nubimpls);
    528
    529 SCIPdebugMsg(scip, "variable <%s> ", SCIPvarGetName(objimplics->objvars[pos]));
    530
    531 /* release variable */
    532 SCIP_CALL( SCIPreleaseVar(scip, &objimplics->objvars[pos]) );
    533
    534 /* copy last lower bound variable to that position */
    535 if( pos < objimplics->nlbimpls )
    536 {
    537 objimplics->nlbimpls--;
    538 assert(objimplics->nlbimpls >= 0);
    539
    540 /* copy last lower bound variable to that position */
    541 objimplics->objvars[pos] = objimplics->objvars[objimplics->nlbimpls];
    542
    543 /* copy last upper bound variable to open slot */
    544 objimplics->objvars[objimplics->nlbimpls] = objimplics->objvars[objimplics->nlbimpls + objimplics->nubimpls];
    545
    546 SCIPdebugMsgPrint(scip, "remove lower bound implication\n");
    547 }
    548 else
    549 {
    550 objimplics->nubimpls--;
    551 assert(objimplics->nubimpls >= 0);
    552
    553 /* copy last upper bound variable to that position */
    554 objimplics->objvars[pos] = objimplics->objvars[objimplics->nlbimpls + objimplics->nubimpls];
    555
    556 SCIPdebugMsgPrint(scip, "remove upper bound implication\n");
    557 }
    558
    559 return SCIP_OKAY;
    560}
    561
    562/*
    563 * Local methods
    564 */
    565
    566
    567/** catch bound change events if the variable has a non-zero objective coefficient to check if the maximum activity of
    568 * the objective function changed
    569 */
    570static
    572 SCIP* scip, /**< SCIP data structure */
    573 SCIP_PROPDATA* propdata, /**< propagator data */
    574 SCIP_EVENTHDLR* eventhdlr, /**< event handler for global bound change events */
    575 SCIP_VAR* var /**< variable for which the event should be dropped */
    576 )
    577{
    578 SCIP_Real objval;
    579
    580 assert(propdata != NULL);
    581 assert(eventhdlr != NULL);
    582
    583 objval = SCIPvarGetObj(var);
    584
    585 if( !SCIPisZero(scip, objval) )
    586 {
    587 if( objval > 0.0 )
    588 {
    590 }
    591 else
    592 {
    594 }
    595 }
    596
    597 return SCIP_OKAY;
    598}
    599
    600/** drop variable event w.r.t. objective coefficient */
    601static
    603 SCIP* scip, /**< SCIP data structure */
    604 SCIP_PROPDATA* propdata, /**< propagator data */
    605 SCIP_EVENTHDLR* eventhdlr, /**< event handler for global bound change events */
    606 SCIP_VAR* var /**< variable for which the event should be dropped */
    607 )
    608{
    609 SCIP_Real objval;
    610
    611 assert(propdata != NULL);
    612 assert(eventhdlr != NULL);
    613
    614 objval = SCIPvarGetObj(var);
    615
    616 /* drop bound change event */
    617 if( !SCIPisZero(scip, objval) )
    618 {
    619 if( objval > 0.0 )
    620 {
    621 SCIP_CALL( SCIPdropVarEvent(scip, var, SCIP_EVENTTYPE_GUBCHANGED, eventhdlr, (SCIP_EVENTDATA*)propdata, -1) );
    622 }
    623 else
    624 {
    625 SCIP_CALL( SCIPdropVarEvent(scip, var, SCIP_EVENTTYPE_GLBCHANGED, eventhdlr, (SCIP_EVENTDATA*)propdata, -1) );
    626 }
    627 }
    628 return SCIP_OKAY;
    629}
    630
    631/** drop all variable events */
    632static
    634 SCIP* scip, /**< SCIP data structure */
    635 SCIP_PROPDATA* propdata /**< propagator data */
    636 )
    637{
    638 SCIP_EVENTHDLR* eventhdlr;
    639 SCIP_VAR* var;
    640 int k;
    641
    642 assert(scip != NULL);
    643 assert(propdata != NULL);
    644
    645 eventhdlr = propdata->eventhdlr;
    646 assert(eventhdlr != NULL);
    647
    648 /* drop all events and release variables */
    649 for( k = 0; k < propdata->nminactvars; ++k )
    650 {
    651 var = propdata->minactvars[k];
    652 assert(var != NULL);
    653 assert(SCIPvarIsBinary(var));
    654
    655 /* drop bound relax event which is caught for all binary variables which are used for propagation the objective
    656 * function via the minimum activity of the objective function
    657 */
    658 SCIP_CALL( SCIPdropVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDRELAXED, eventhdlr, (SCIP_EVENTDATA*)propdata, -1) );
    659
    660 /* release variable */
    661 SCIP_CALL( SCIPreleaseVar(scip, &var) );
    662 }
    663
    664 /* release variables */
    665 for( k = 0; k < propdata->nmaxactvars; ++k )
    666 {
    667 var = propdata->maxactvars[k];
    668 assert(var != NULL);
    669 assert(SCIPvarIsBinary(var));
    670
    671 /* drop events which are needed for evaluating the maximum activity of the objective function */
    672 SCIP_CALL( dropObjEvent(scip, propdata, eventhdlr, var) );
    673
    674 /* release variable */
    675 SCIP_CALL( SCIPreleaseVar(scip, &var) );
    676 }
    677
    678 /* drop all events and release variables */
    679 for( k = 0; k < propdata->nobjintvars; ++k )
    680 {
    681 var = propdata->objintvars[k];
    682 assert(var != NULL);
    683
    684 /* drop events which are needed for evaluating the maximum activity of the objective function */
    685 SCIP_CALL( dropObjEvent(scip, propdata, eventhdlr, var) );
    686
    687 /* release variable */
    688 SCIP_CALL( SCIPreleaseVar(scip, &var) );
    689 }
    690
    691 return SCIP_OKAY;
    692}
    693
    694/** reset propagatore data structure */
    695static
    697 SCIP_PROPDATA* propdata /**< propagator data */
    698 )
    699{
    700 propdata->minactvars = NULL;
    701 propdata->minactimpls = NULL;
    702 propdata->maxactvars = NULL;
    703 propdata->maxactchgs = NULL;
    704 propdata->objintvars = NULL;
    705 propdata->nminactvars = 0;
    706 propdata->nmaxactvars = 0;
    707 propdata->nobjintvars = 0;
    708 propdata->maxpseudoobjact = SCIP_INVALID;
    709 propdata->maxpseudoobjactinf = 0;
    710 propdata->lastvarnum = -1;
    711 propdata->glbpropagated = FALSE;
    712 propdata->cutoffbound = SCIP_INVALID;
    713 propdata->lastlowerbound = -SCIP_INVALID;
    714 propdata->glbpseudoobjval = -SCIP_INVALID;
    715 propdata->glbfirstnonfixed = 0;
    716 propdata->maxactfirstnonfixed = 0;
    717 propdata->firstnonfixed = 0;
    718 propdata->nnewvars = 0;
    719 propdata->minactsize = 0;
    720 propdata->maxactsize = 0;
    721 propdata->objintvarssize = 0;
    722 propdata->catchvaradded = FALSE;
    723 propdata->initialized = FALSE;
    724}
    725
    726/** free propagator data */
    727static
    729 SCIP* scip, /**< SCIP data structure */
    730 SCIP_PROPDATA* propdata /**< propagator data */
    731 )
    732{
    733 int v;
    734
    735 if( !propdata->initialized )
    736 return SCIP_OKAY;
    737
    738 if( propdata->addedvars != NULL )
    739 SCIPhashtableFree(&propdata->addedvars);
    740
    741 /* drop events for the variables */
    742 SCIP_CALL( dropVarEvents(scip, propdata) );
    743
    744 for( v = 0; v < propdata->nminactvars; ++v )
    745 {
    746 SCIP_CALL( objimplicsFree(scip, &(propdata->minactimpls[v])) );
    747 }
    748
    749 /* free memory for non-zero objective variables */
    750 SCIPfreeBlockMemoryArrayNull(scip, &propdata->minactvars, propdata->minactsize);
    751 SCIPfreeBlockMemoryArrayNull(scip, &propdata->minactimpls, propdata->minactsize);
    752 SCIPfreeBlockMemoryArrayNull(scip, &propdata->maxactvars, propdata->maxactsize);
    753 SCIPfreeBlockMemoryArrayNull(scip, &propdata->maxactchgs, propdata->maxactsize);
    754 SCIPfreeBlockMemoryArrayNull(scip, &propdata->objintvars, propdata->objintvarssize);
    755
    756 /* reset propagator data structure */
    757 propdataReset(propdata);
    758
    759 return SCIP_OKAY;
    760}
    761
    762/** returns the objective change for the given binary variable */
    763static
    765 SCIP_VAR* var, /**< variable to get objective change for */
    766 SCIP_BOUNDTYPE boundtype, /**< bound type to consider */
    767 SCIP_BOUNDTYPE bound /**< fixing bound */
    768 )
    769{
    770 assert(SCIPvarIsBinary(var));
    771 assert((int)SCIP_BOUNDTYPE_LOWER == 0); /*lint !e506*/
    772 assert((int)SCIP_BOUNDTYPE_UPPER == 1); /*lint !e506*/
    773
    774 /* collect contribution of variable itself */
    775 return (SCIP_Real)((int)bound - (int)(boundtype == SCIP_BOUNDTYPE_UPPER)) * SCIPvarGetObj(var);
    776}
    777
    778/** returns the objective change provided by the implication variable by fixing it to the given bound
    779 * w.r.t. minimum activity of the objective function; additionally it collects all contributors for that objective
    780 * change;
    781 */
    782static
    784 SCIP* scip, /**< SCIP data structure */
    785 SCIP_VAR* var, /**< variable to computes the objective contribution */
    786 SCIP_HASHMAP* binobjvarmap, /**< hash map mapping binary variables with none-zero objective to position in collected variables arrays */
    787 SCIP_Bool* collectedvars, /**< temporary buffer to mark collected variables */
    788 int nbinobjvars, /**< number of binary variables with non-zero objective coefficient */
    789 SCIP_VAR** contributors, /**< array to store the contributors */
    790 int* ncontributors /**< pointer to store number of contributor to the objective contribution */
    791 )
    792{
    793 SCIP_Real objval;
    794 int pos;
    795
    796 assert(scip != NULL);
    797 assert(var != NULL);
    798 assert(binobjvarmap != NULL);
    799 assert(collectedvars != NULL);
    800 assert(contributors != NULL);
    801 assert(ncontributors != NULL);
    802
    803 /* ignore global fixed variables */
    804 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
    805 return 0.0;
    806
    807 objval = SCIPvarGetObj(var);
    808
    809 /* ignore variables with zero objective coefficient */
    810 if( SCIPisZero(scip, objval) )
    811 return 0.0;
    812
    813 assert(SCIPhashmapExists(binobjvarmap, var));
    814 pos = SCIPhashmapGetImageInt(binobjvarmap, var);
    815 assert(pos > 0);
    816
    817 /* check if the variables was already collected through other cliques */
    818 if( collectedvars[pos] )
    819 return 0.0;
    820
    821 /* collect variable */
    822 assert(*ncontributors < nbinobjvars);
    823 contributors[*ncontributors] = var;
    824 (*ncontributors)++;
    825
    826 /* mark variable to be collected */
    827 collectedvars[pos] = TRUE;
    828
    829 /* return the absolute value of the objective coefficient as constriction */
    830 return REALABS(objval);
    831}
    832
    833#define MAX_CLIQUELENGTH 50
    834/** returns the objective change provided by the implications of the given variable by fixing it to the given bound
    835 * w.r.t. minimum activity of the objective function; additionally it collects all contributors for that objective
    836 * change;
    837 *
    838 * Let I(0) and I(1) be all implications of the given variable which follow by fixing it to given bound and evaluate to
    839 * fixing the implication variable to zero (I(0)) or one (I(1)), respectively. The objective change provided by the
    840 * implications are:
    841 *
    842 * \f[
    843 * \displaystyle
    844 * sum_{x\in I(1)} (1 - \mbox{bestbound}(x)) \cdot \mbox{objval}(x) - sum_{x\in I(1)} \mbox{bestbound}(x) \cdot \mbox{objval}(x)
    845 * =
    846 * sum_{x\in I(0) \cup I(1)} (\mbox{impliedbound}(x) - \mbox{bestbound}(x)) \cdot \mbox{objval}(x)
    847 * \f]
    848 */
    849static
    851 SCIP* scip, /**< SCIP data structure */
    852 SCIP_VAR* var, /**< variable to computes the objective contribution */
    853 SCIP_BOUNDTYPE bound, /**< bound to check for */
    854 SCIP_HASHMAP* binobjvarmap, /**< hash map mapping binary variables with none-zero objective to position in collected variables arrays */
    855 SCIP_Bool* collectedvars, /**< temporary buffer to mark collected variables */
    856 int nbinobjvars, /**< number of binary variables with non-zero objective coefficient */
    857 SCIP_VAR** contributors, /**< array to store the contributors */
    858 SCIP_HASHTABLE* uselesscliques, /**< hash table to store useless cliques, or NULL */
    859 int* ncontributors, /**< pointer to store number of contributor to the objective contribution */
    860 SCIP_Real* objchg /**< pointer to store the objective change */
    861 )
    862{
    863 SCIP_CLIQUE** cliques;
    864 SCIP_CLIQUE* clique;
    865 SCIP_VAR** vars;
    866 SCIP_VAR* implvar;
    867 SCIP_Bool* values;
    868 SCIP_Bool varfixing;
    869 int nbinvars;
    870 int ncliques;
    871 int c;
    872 int v;
    873
    874 assert(SCIPvarIsBinary(var));
    875 assert(SCIPvarGetLbGlobal(var) < 0.5);
    876 assert(SCIPvarGetUbGlobal(var) > 0.5);
    878 assert(objchg != NULL);
    879 assert(contributors != NULL);
    880 assert(ncontributors != NULL);
    881 assert(*ncontributors == 0);
    882
    883 assert((SCIP_Bool)SCIP_BOUNDTYPE_LOWER == FALSE); /*lint !e506*/
    884 assert((SCIP_Bool)SCIP_BOUNDTYPE_UPPER == TRUE); /*lint !e506*/
    885 varfixing = (SCIP_Bool)bound;
    886
    887 cliques = SCIPvarGetCliques(var, varfixing);
    888 ncliques = SCIPvarGetNCliques(var, varfixing);
    889
    890 if( uselesscliques == NULL )
    891 return SCIP_INVALIDDATA;
    892
    893#ifndef NDEBUG
    894 /* check that the marker array is reset */
    895 for( c = 0; c < nbinobjvars; ++c )
    896 assert(collectedvars[c] == FALSE);
    897#endif
    898
    899 /* collect all implication which are given via cliques */
    900 for( c = 0; c < ncliques; ++c )
    901 {
    902 SCIP_Bool useless;
    903
    904 clique = cliques[c];
    905 assert(clique != NULL);
    906
    907 /* check if the clique was previously detected to be useless with respect to minimum activity */
    908 if( SCIPhashtableExists(uselesscliques, (void*)clique) )
    909 continue;
    910
    911 nbinvars = SCIPcliqueGetNVars(clique);
    912
    913 if( nbinvars > MAX_CLIQUELENGTH )
    914 {
    915 SCIP_CALL( SCIPhashtableInsert(uselesscliques, (void*)clique) );
    916 continue;
    917 }
    918
    919 vars = SCIPcliqueGetVars(clique);
    920 values = SCIPcliqueGetValues(clique);
    921 useless = TRUE;
    922
    923 for( v = 0; v < nbinvars; ++v )
    924 {
    925 implvar = vars[v];
    926 assert(implvar != NULL);
    927
    928 if( implvar == var )
    929 {
    930 /* check if the clique is useful at all */
    931 if( useless )
    932 {
    933 SCIP_Real objval;
    934
    935 objval = SCIPvarGetObj(var);
    936
    937 if( varfixing == (SCIP_Bool)SCIPvarGetBestBoundType(var) && !SCIPisZero(scip, objval) )
    938 useless = FALSE;
    939 }
    940 }
    941 else if( values[v] == (SCIP_Bool)SCIPvarGetBestBoundType(implvar) )
    942 {
    943 useless = FALSE;
    944 (*objchg) += collectMinactImplicVar(scip, implvar, binobjvarmap, collectedvars, nbinobjvars, contributors, ncontributors);
    945 }
    946 }
    947
    948 /* if the clique is useless store it in the hash table to skip it later */
    949 if( useless )
    950 {
    951 assert(!SCIPhashtableExists(uselesscliques, (void*)clique));
    952 SCIP_CALL( SCIPhashtableInsert(uselesscliques, (void*)clique) );
    953 }
    954 }
    955
    956 return SCIP_OKAY;
    957}
    958
    959/** returns the objective change provided by the implications of the given variable by fixing it to the given bound
    960 * w.r.t. minimum activity of the objective function
    961 *
    962 * Let I(0) and I(1) be all implications of the given variable which follow by fixing it to given bound and evaluate to
    963 * fixing the implication variable to zero (I(0)) or one (I(1)), respectively. The objective change provided by the
    964 * implications are:
    965 *
    966 * \f[
    967 * \displaystyle
    968 * sum_{x\in I(1)} (1 - \mbox{bestbound}(x)) \cdot \mbox{objval}(x) - sum_{x\in I(1)} \mbox{bestbound}(x) \cdot \mbox{objval}(x)
    969 * =
    970 * sum_{x\in I(0) \cup I(1)} (\mbox{impliedbound}(x) - \mbox{bestbound}(x)) \cdot \mbox{objval}(x)
    971 * \f]
    972 *
    973 * This can be done w.r.t. global variable bounds (local == FALSE), w.r.t. local variable bounds (local == TRUE &&
    974 * bdchgidx == NULL), and w.r.t. given time stamp (local == TRUE && bdchgidx != NULL)
    975 */
    976static
    978 SCIP* scip, /**< SCIP data structure */
    979 SCIP_VAR* var, /**< variable to computes the objective contribution */
    980 SCIP_OBJIMPLICS* objimplics, /**< objective implication data for the given variable */
    981 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node, or NULL */
    982 SCIP_BOUNDTYPE bound, /**< bound to check for */
    983 SCIP_Bool local, /**< propagate local bounds, otherwise global bounds */
    984 SCIP_Real* objchg /**< pointer to store the objective change */
    985 )
    986{
    987 SCIP_VAR* implvar;
    988 SCIP_Bool lb;
    989 SCIP_Bool ub;
    990 int nbinvars;
    991 int v;
    992
    993 assert(SCIPvarIsBinary(var));
    994 assert(!local || SCIPgetVarLbAtIndex(scip, var, bdchgidx, FALSE) < 0.5);
    995 assert(!local || SCIPgetVarUbAtIndex(scip, var, bdchgidx, FALSE) > 0.5);
    996 assert(SCIPvarGetLbGlobal(var) < 0.5);
    997 assert(SCIPvarGetUbGlobal(var) > 0.5);
    999
    1001 {
    1002 v = 0;
    1003 nbinvars = objimplics->nlbimpls;
    1004 }
    1005 else
    1006 {
    1007 assert(bound == SCIP_BOUNDTYPE_UPPER);
    1008 v = objimplics->nlbimpls;
    1009 nbinvars = objimplics->nlbimpls + objimplics->nubimpls;
    1010 }
    1011
    1012 /* loop over all implications */
    1013 while( v < nbinvars )
    1014 {
    1015 implvar = objimplics->objvars[v];
    1016 assert(implvar != NULL);
    1017 assert(!SCIPisZero(scip, SCIPvarGetObj(implvar)));
    1018
    1019 if( local )
    1020 {
    1021 lb = SCIPgetVarLbAtIndex(scip, implvar, bdchgidx, FALSE) > 0.5;
    1022 ub = SCIPgetVarUbAtIndex(scip, implvar, bdchgidx, FALSE) > 0.5;
    1023
    1024 /* check if variable is fixed */
    1025 if( lb == TRUE || ub == FALSE )
    1026 {
    1027 v++;
    1028 continue;
    1029 }
    1030 }
    1031 else
    1032 {
    1033 lb = SCIPvarGetLbGlobal(implvar) > 0.5;
    1034 ub = SCIPvarGetUbGlobal(implvar) > 0.5;
    1035
    1036 /* check if variable is global fixed; if so remove it from the objective implication data structure and
    1037 * continue with the next candidate
    1038 */
    1039 if( lb == TRUE || ub == FALSE )
    1040 {
    1041 SCIP_CALL( objimplicsDelPos(scip, objimplics, v) );
    1042 nbinvars--;
    1043 continue;
    1044 }
    1045 }
    1046
    1047 assert(SCIPvarGetObj(implvar) > 0.0 || SCIPvarsHaveCommonClique(var, (SCIP_Bool) bound, implvar, TRUE, TRUE));
    1048 assert(SCIPvarGetObj(implvar) < 0.0 || SCIPvarsHaveCommonClique(var, (SCIP_Bool) bound, implvar, FALSE, TRUE));
    1049
    1050 /* add objective change */
    1051 (*objchg) += REALABS(SCIPvarGetObj(implvar));
    1052 v++;
    1053 }
    1054
    1055 return SCIP_OKAY;
    1056}
    1057
    1058/** computes for the given binary variable the objective contribution by fixing it to given bound w.r.t. minimum
    1059 * activity of the objective function; additionally it collects all contributors for that objective change;
    1060 */
    1061static
    1063 SCIP* scip, /**< SCIP data structure */
    1064 SCIP_VAR* var, /**< variable to computes the objective contribution */
    1065 SCIP_BOUNDTYPE bound, /**< bound to check for */
    1066 SCIP_HASHMAP* binobjvarmap, /**< hash map mapping binary variables with none-zero objective to position in collected variables arrays */
    1067 SCIP_Bool* collectedvars, /**< temporary buffer to mark collected variables */
    1068 int nbinobjvars, /**< number of binary variables with non-zero objective coefficient */
    1069 SCIP_VAR** contributors, /**< array to store the contriboters */
    1070 SCIP_HASHTABLE* uselesscliques, /**< hash table to store useless cliques, or NULL */
    1071 int* ncontributors, /**< pointer to store number of contributor to the objective contribution */
    1072 SCIP_Real* objchg /**< pointer to store the objective change */
    1073 )
    1074{
    1075 assert(SCIPvarIsBinary(var));
    1076 assert(contributors != NULL);
    1077 assert(ncontributors != NULL);
    1078
    1079 /* collects the contribution of the variable itself w.r.t. the best bound */
    1080 (*objchg) = getVarObjchg(var, SCIPvarGetBestBoundType(var), bound);
    1081
    1082 (*ncontributors) = 0;
    1083
    1084 /* add the objective contribution from the implication variable */
    1085 SCIP_CALL( collectMinactImplicVars(scip, var, bound, binobjvarmap, collectedvars, nbinobjvars, contributors, uselesscliques, ncontributors, objchg) );
    1086
    1087 return SCIP_OKAY;
    1088}
    1089
    1090/** computes for the given binary variable the objective contribution by fixing it to given bound w.r.t. minimum
    1091 * activity of the objective function; this can be done w.r.t. global variable bounds (local == FALSE), w.r.t. local
    1092 * variable bounds (local == TRUE && bdchgidx == NULL), and w.r.t. given time stamp (local == TRUE && bdchgidx != NULL)
    1093 */
    1094static
    1096 SCIP* scip, /**< SCIP data structure */
    1097 SCIP_VAR* var, /**< variable to computes the objective contribution */
    1098 SCIP_OBJIMPLICS* objimplics, /**< objective implication data for the given variable */
    1099 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node, or NULL */
    1100 SCIP_BOUNDTYPE bound, /**< bound to check for */
    1101 SCIP_Bool local, /**< propagate local bounds, otherwise global bounds */
    1102 SCIP_Real* objchg /**< pointer to store the objective change */
    1103 )
    1104{
    1105 assert(SCIPvarIsBinary(var));
    1106
    1107 /* collects the contribution of the variable itself w.r.t. the best bound */
    1108 (*objchg) = getVarObjchg(var, SCIPvarGetBestBoundType(var), bound);
    1109
    1110 /* add the objective contribution from the implication variable */
    1111 SCIP_CALL( getMinactImplicObjchg(scip, var, objimplics, bdchgidx, bound, local, objchg) );
    1112
    1113 return SCIP_OKAY;
    1114}
    1115
    1116/** returns the global (that means w.r.t. global bounds of the variables) objective change provided by all cliques of
    1117 * the given variable by fixing it to the given bound w.r.t. maximum activity of the objective function
    1118 *
    1119 * Let I(0) and I(1) be all implications of the given variable which follow by fixing it to given bound and evaluate to
    1120 * fixing the implication variable to zero (I(0)) or one (I(1)), respectively. The objective change provided by these
    1121 * implications are:
    1122 *
    1123 * \f[
    1124 * \displaystyle
    1125 * sum_{x\in I(1)} (1 - \mbox{worstbound}(x)) \cdot \mbox{objval}(x) - sum_{x\in I(1)} \mbox{worst}(x) \cdot \mbox{objval}(x)
    1126 * =
    1127 * sum_{x\in I(0) \cup I(1)} (\mbox{impliedbound}(x) - \mbox{worstbound}(x)) \cdot \mbox{objval}(x)
    1128 * \f]
    1129 */
    1130static
    1132 SCIP* scip, /**< SCIP data structure */
    1133 SCIP_VAR* var, /**< variable to computes the objective contribution */
    1134 SCIP_BOUNDTYPE bound, /**< bound to check for */
    1135 SCIP_Real* objchg /**< pointer to store the objective change */
    1136 )
    1137{
    1138 SCIP_Bool varfixing;
    1139 int ncliques;
    1140 int nvars;
    1141
    1142 assert(scip != NULL);
    1143 assert(SCIPvarIsBinary(var));
    1144 assert(SCIPvarGetLbGlobal(var) < 0.5);
    1145 assert(SCIPvarGetUbGlobal(var) > 0.5);
    1147 assert(objchg != NULL);
    1148
    1149 varfixing = (SCIP_Bool)bound;
    1150 assert((SCIP_Bool)SCIP_BOUNDTYPE_LOWER == FALSE); /*lint !e506*/
    1151 assert((SCIP_Bool)SCIP_BOUNDTYPE_UPPER == TRUE); /*lint !e506*/
    1152
    1153 *objchg = 0.0;
    1154 ncliques = SCIPvarGetNCliques(var, varfixing);
    1155
    1156 if( ncliques > 0 )
    1157 {
    1158 SCIP_CLIQUE** cliques;
    1159 SCIP_CLIQUE* clique;
    1160 SCIP_VAR** clqvars;
    1161 SCIP_VAR** probvars;
    1162 SCIP_VAR* clqvar;
    1163 SCIP_Bool* clqvalues;
    1164 int* entries;
    1165 int* ids;
    1166 SCIP_Real obj;
    1167 int nclqvars;
    1168 int nentries;
    1169 int objmult;
    1170 int nids;
    1171 int id;
    1172 int c;
    1173 int v;
    1174
    1175 assert(SCIPisTransformed(scip));
    1176
    1177 nentries = SCIPgetNVars(scip) - SCIPgetNContVars(scip) + 1;
    1178
    1179 SCIP_CALL( SCIPallocBufferArray(scip, &ids, 2*nentries) );
    1180 nids = 0;
    1181 /* @todo move this memory allocation to SCIP_SET and add a memory list there, to decrease the number of
    1182 * allocations and clear ups
    1183 */
    1184 SCIP_CALL( SCIPallocBufferArray(scip, &entries, nentries) );
    1185 BMSclearMemoryArray(entries, nentries);
    1186
    1187 cliques = SCIPvarGetCliques(var, varfixing);
    1188 assert(cliques != NULL);
    1189
    1190 /* iterate over all cliques and determine all importantimplications */
    1191 for( c = ncliques - 1; c >= 0; --c )
    1192 {
    1193 clique = cliques[c];
    1194 clqvars = SCIPcliqueGetVars(clique);
    1195 clqvalues = SCIPcliqueGetValues(clique);
    1196 nclqvars = SCIPcliqueGetNVars(clique);
    1197 assert(nclqvars > 0);
    1198 assert(clqvars != NULL);
    1199 assert(clqvalues != NULL);
    1200
    1201 if( nclqvars > MAX_CLIQUELENGTH )
    1202 continue;
    1203
    1204 /* iterate over all clique variables */
    1205 for( v = nclqvars - 1; v >= 0; --v )
    1206 {
    1207 clqvar = clqvars[v];
    1208 assert(clqvar != NULL);
    1209
    1210 objmult = (int)!clqvalues[v] - (int)SCIPvarGetWorstBoundType(clqvar);
    1211 assert(-1 <= objmult && objmult <= 1);
    1212
    1213 /* ignore binary variable which are either fixed and were the objective contribution will not be zero */
    1214 if( clqvar != var && objmult != 0 && SCIPvarIsActive(clqvar) &&
    1215 (SCIPvarGetLbGlobal(clqvar) < 0.5 && SCIPvarGetUbGlobal(clqvar) > 0.5) && !SCIPisZero(scip, SCIPvarGetObj(clqvar)) )
    1216 {
    1217 int probindex = SCIPvarGetProbindex(clqvar) + 1;
    1218 assert(0 < probindex && probindex < nentries);
    1219
    1220 /* check that the variable was not yet visited */
    1221 assert(entries[probindex] == 0 || entries[probindex] == objmult);
    1222 if( entries[probindex] == 0 )
    1223 {
    1224 /* memorize probindex */
    1225 ids[nids] = probindex;
    1226 ++nids;
    1227
    1228 assert(ABS(objmult) == 1);
    1229
    1230 /* mark variable as visited */
    1231 entries[probindex] = objmult;
    1232 }
    1233 }
    1234 }
    1235 }
    1236
    1237 probvars = SCIPgetVars(scip);
    1238 assert(probvars != NULL);
    1239
    1240 /* add all implied objective values */
    1241 for( v = nids - 1; v >= 0; --v )
    1242 {
    1243 id = ids[v];
    1244 assert(0 < id && id < nentries);
    1245 assert(entries[id] != 0);
    1246
    1247 clqvar = probvars[id - 1];
    1248 assert(clqvar != NULL);
    1249 assert(SCIPvarIsBinary(clqvar));
    1250 assert(SCIPvarIsActive(clqvar));
    1251 assert(SCIPvarGetLbGlobal(clqvar) < 0.5);
    1252 assert(SCIPvarGetUbGlobal(clqvar) > 0.5);
    1253
    1254 obj = SCIPvarGetObj(clqvar);
    1255 assert(!SCIPisZero(scip, obj));
    1256
    1257 *objchg += entries[id] * obj;
    1258 }
    1259
    1260 /* free temporary memory */
    1261 SCIPfreeBufferArray(scip, &entries);
    1263 }
    1264
    1265#ifdef SCIP_MORE_DEBUG
    1266 SCIPdebugMsg(scip, "objective contribution when variable <%s> fixed to %u using cliques is %g\n", SCIPvarGetName(var),
    1267 varfixing, *objchg);
    1268#endif
    1269
    1270 /* collect non-binary implication information */
    1271 nvars = SCIPvarGetNImpls(var, varfixing);
    1272
    1273 if( nvars > 0 )
    1274 {
    1275 SCIP_VAR** vars;
    1276 SCIP_VAR* implvar;
    1277 SCIP_Real* bounds;
    1278 SCIP_BOUNDTYPE* boundtypes;
    1279 SCIP_Real obj;
    1280 SCIP_Real lb;
    1281 SCIP_Real ub;
    1282 int v;
    1283
    1284 vars = SCIPvarGetImplVars(var, varfixing);
    1285 boundtypes = SCIPvarGetImplTypes(var, varfixing);
    1286 bounds = SCIPvarGetImplBounds(var, varfixing);
    1287
    1288 for( v = nvars - 1; v >= 0; --v )
    1289 {
    1290 implvar = vars[v];
    1291 assert(implvar != NULL);
    1292
    1293 lb = SCIPvarGetLbLocal(implvar);
    1294 ub = SCIPvarGetUbLocal(implvar);
    1295 obj = SCIPvarGetObj(implvar);
    1296
    1297 /* ignore binary variable which are fixed or not of column status */
    1298 if( SCIPisZero(scip, obj) )
    1299 continue;
    1300
    1301 /* add up objective change if applicable */
    1302 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPvarGetWorstBoundType(implvar) == SCIP_BOUNDTYPE_LOWER && SCIPisFeasGT(scip, bounds[v], lb) )
    1303 *objchg += (bounds[v] - lb)*obj;
    1304 else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPvarGetWorstBoundType(implvar) == SCIP_BOUNDTYPE_UPPER && SCIPisFeasLT(scip, bounds[v], ub) )
    1305 *objchg += (bounds[v] - ub)*obj;
    1306 }
    1307 }
    1308
    1309#ifdef SCIP_MORE_DEBUG
    1310 SCIPdebugMsg(scip, "objective contribution when variable <%s> fixed to %u using cliques and implications is %g\n", SCIPvarGetName(var),
    1311 varfixing, *objchg);
    1312#endif
    1313
    1314 return SCIP_OKAY;
    1315}
    1316
    1317/** computes for the given binary variable the gloabl (that means w.r.t. global bounds of the variables) objective
    1318 * contribution by fixing it to given bound w.r.t. maximum activity of the objective function
    1319 */
    1320static
    1322 SCIP* scip, /**< SCIP data structure */
    1323 SCIP_VAR* var, /**< variable to computes the objective contribution */
    1324 SCIP_BOUNDTYPE bound, /**< bound to check for */
    1325 SCIP_Bool useimplics, /**< should implications be used */
    1326 SCIP_Real* objchg /**< pointer to store the objective change */
    1327 )
    1328{
    1329 assert(scip != NULL);
    1330 assert(SCIPvarIsBinary(var));
    1331 assert(objchg != NULL);
    1332
    1333 *objchg = 0;
    1334
    1335 /* check if the implications should be used to increase the objective contribution for given variable */
    1336 if( useimplics )
    1337 {
    1338 /* using cliques and @todo other implications */
    1339 SCIP_CALL( getMaxactImplicObjchg(scip, var, bound, objchg) );
    1340 }
    1341
    1342 /* collects the contribution of the variable itself w.r.t. the worst bound */
    1343 *objchg += getVarObjchg(var, SCIPvarGetWorstBoundType(var), bound);
    1344
    1345 return SCIP_OKAY;
    1346}
    1347
    1348/** reset variables array which marks variables which are collected */
    1349static
    1351 SCIP_HASHMAP* binobjvarmap, /**< hash map mapping binary variables with none-zero objective to position in collected variables arrays */
    1352 SCIP_Bool* collectedvars, /**< temporary buffer to mark collected variables which should be reset */
    1353 SCIP_VAR** contributors, /**< temporary buffer to use for collecting contributors */
    1354 int ncontributors /**< number of contributors */
    1355 )
    1356{
    1357 SCIP_VAR* var;
    1358 int pos;
    1359 int c;
    1360
    1361 for( c = 0; c < ncontributors; ++c )
    1362 {
    1363 var = contributors[c];
    1364 assert(var != NULL);
    1365
    1366 assert(SCIPhashmapExists(binobjvarmap, var));
    1367 pos = SCIPhashmapGetImageInt(binobjvarmap, var);
    1368 assert(pos > 0);
    1369 collectedvars[pos] = FALSE;
    1370 }
    1371}
    1372
    1373/** check if the given variable should be collected for the minimum activity propagation */
    1374static
    1376 SCIP* scip, /**< SCIP data structure */
    1377 SCIP_VAR* var, /**< variable to check */
    1378 SCIP_OBJIMPLICS** objimplics, /**< pointer to store the objective implication data structure w.r.t. minimum activity */
    1379 SCIP_Bool useimplics, /**< should implications be used */
    1380 SCIP_HASHMAP* binobjvarmap, /**< hash map mapping binary variables with none-zero objective to position in collected variables arrays */
    1381 SCIP_Bool* collectedlbvars, /**< temporary buffer to mark collected variables for lower bound fixing */
    1382 SCIP_Bool* collectedubvars, /**< temporary buffer to mark collected variables for upper bound fixing */
    1383 int nbinobjvars, /**< number of binary variables with non-zero objective coefficient */
    1384 SCIP_VAR** contributors, /**< temporary buffer to use for collecting contributors */
    1385 SCIP_HASHTABLE* uselesscliques, /**< hash table to store useless cliques, or NULL */
    1386 SCIP_Bool* collect /**< pointer to store if the variable should be stored */
    1387 )
    1388{
    1389 SCIP_Real lbobjchg;
    1390 SCIP_Real ubobjchg;
    1391 SCIP_Real objval;
    1392 int nlbcliques;
    1393 int nubcliques;
    1394
    1395 assert(objimplics != NULL);
    1396
    1397 objval = SCIPvarGetObj(var);
    1398 (*objimplics) = NULL;
    1399
    1400 if( SCIPisZero(scip, objval) )
    1401 (*collect) = FALSE;
    1402 else
    1403 (*collect) = TRUE;
    1404
    1405 nlbcliques = SCIPvarGetNCliques(var, FALSE);
    1406 nubcliques = SCIPvarGetNCliques(var, TRUE);
    1407
    1408 /* check if implications should be used and if implications are existing */
    1409 if( useimplics && nlbcliques + nubcliques > 0 )
    1410 {
    1411 int nlbcontributors;
    1412 int nubcontributors;
    1413
    1414 assert((SCIP_Bool)SCIP_BOUNDTYPE_LOWER == FALSE); /*lint !e506*/
    1415 assert((SCIP_Bool)SCIP_BOUNDTYPE_UPPER == TRUE); /*lint !e506*/
    1416
    1417 /* get contribution of variable by fixing it to its lower bound w.r.t. minimum activity of the objective function */
    1418 SCIP_CALL( collectMinactObjchg(scip, var, SCIP_BOUNDTYPE_LOWER, binobjvarmap, collectedlbvars, nbinobjvars,
    1419 contributors, uselesscliques, &nlbcontributors, &lbobjchg) );
    1420 assert(!SCIPisNegative(scip, lbobjchg));
    1421
    1422 SCIPdebugMsg(scip, "variable <%s> fixed to bound=%d implies %d(%d)\n", SCIPvarGetName(var),
    1423 SCIP_BOUNDTYPE_LOWER, 0, nlbcontributors);
    1424
    1425 /* ignore implications if the variable has a zero objective coefficient and implications only one variable, since
    1426 * this is covered by that implied variable
    1427 */
    1428 if( !(*collect) && nlbcontributors == 1 )
    1429 {
    1430 /* reset lower bound contributors */
    1431 resetContributors(binobjvarmap, collectedlbvars, contributors, nlbcontributors);
    1432
    1433 assert(SCIPisZero(scip, objval));
    1434 nlbcontributors = 0;
    1435 }
    1436
    1437 /* get contribution of variable by fixing it to its upper bound w.r.t. minimum activity of the objective function */
    1438 SCIP_CALL( collectMinactObjchg(scip, var, SCIP_BOUNDTYPE_UPPER, binobjvarmap, collectedubvars, nbinobjvars,
    1439 &contributors[nlbcontributors], uselesscliques, &nubcontributors, &ubobjchg) );
    1440 assert(!SCIPisNegative(scip, ubobjchg));
    1441
    1442 SCIPdebugMsg(scip, "variable <%s> fixed to bound=%d implies %d(%d)\n", SCIPvarGetName(var),
    1443 SCIP_BOUNDTYPE_UPPER, 0, nubcontributors);
    1444
    1445 /* ignore implications if the variable has a zero objective coefficient and implications only one variable, since
    1446 * this is covered by that implied variable
    1447 */
    1448 if( !(*collect) && nubcontributors == 1 )
    1449 {
    1450 /* reset upper bound contributors */
    1451 resetContributors(binobjvarmap, collectedubvars, &contributors[nlbcontributors], nubcontributors);
    1452
    1453 assert(SCIPisZero(scip, objval));
    1454 nubcontributors = 0;
    1455 }
    1456
    1457 if( (*collect) || nlbcontributors > 1 || nubcontributors > 1 )
    1458 {
    1459 /* creates an objective implication data structure, fixes (globally) variables which are implied by lower and upper
    1460 * bound fixing, and clears the collected arrays for lower and upper bound
    1461 */
    1462 SCIP_CALL( objimplicsCreate(scip, objimplics, contributors, binobjvarmap, collectedlbvars, collectedubvars, lbobjchg, ubobjchg, nlbcontributors, nubcontributors) );
    1463 (*collect) = TRUE;
    1464 }
    1465 else
    1466 {
    1467 /* reset lower bound contributors */
    1468 resetContributors(binobjvarmap, collectedlbvars, contributors, nlbcontributors);
    1469
    1470 /* reset upper bound contributors */
    1471 resetContributors(binobjvarmap, collectedubvars, &contributors[nlbcontributors], nubcontributors);
    1472 }
    1473 }
    1474 else if( (*collect) )
    1475 {
    1478 assert(!SCIPisZero(scip, lbobjchg) || !SCIPisZero(scip, ubobjchg));
    1479 assert(!SCIPisNegative(scip, lbobjchg));
    1480 assert(!SCIPisNegative(scip, ubobjchg));
    1481
    1482 /* creates an "empty" objective implication data structure */
    1483 SCIP_CALL( objimplicsCreate(scip, objimplics, NULL, NULL, NULL, NULL, lbobjchg, ubobjchg, 0, 0) );
    1484 }
    1485
    1486 return SCIP_OKAY;
    1487}
    1488
    1489/** check if the given variable should be collected for the maximum activity propagation */
    1490static
    1492 SCIP* scip, /**< SCIP data structure */
    1493 SCIP_VAR* var, /**< variable to check */
    1494 SCIP_Bool useimplics, /**< should implications be used */
    1495 SCIP_Real* objchg, /**< pointer to store the objective change w.r.t. maximum activity */
    1496 SCIP_Bool* isnotzero /**< pointer to store if the objective change is unequal to zero or not */
    1497 )
    1498{
    1499 SCIP_Real lbobjchg;
    1500 SCIP_Real ubobjchg;
    1501
    1502 assert(scip != NULL);
    1503 assert(SCIPvarIsBinary(var));
    1504 assert(objchg != NULL);
    1505 assert(isnotzero != NULL);
    1506
    1507 /* get contribution of variable by fixing it to its lower bound w.r.t. maximum activity of the objective function */
    1508 SCIP_CALL( getMaxactObjchg(scip, var, SCIP_BOUNDTYPE_LOWER, useimplics, &lbobjchg) );
    1509 assert(!SCIPisPositive(scip, lbobjchg));
    1510
    1511 /* get contribution of variable by fixing it to its upper bound w.r.t. maximum activity of the objective function */
    1512 SCIP_CALL( getMaxactObjchg(scip, var, SCIP_BOUNDTYPE_UPPER, useimplics, &ubobjchg) );
    1513 assert(!SCIPisPositive(scip, ubobjchg));
    1514
    1515 (*objchg) = MIN(lbobjchg, ubobjchg);
    1516
    1517 /* only consider variables with non-zero objective contribution */
    1518 if( SCIPisZero(scip, (*objchg)) )
    1519 *isnotzero = FALSE;
    1520 else
    1521 *isnotzero = TRUE;
    1522
    1523 return SCIP_OKAY;
    1524}
    1525
    1526/** initializate the propagator */
    1527static
    1529 SCIP* scip, /**< SCIP data structure */
    1530 SCIP_PROPDATA* propdata /**< propagator data */
    1531 )
    1532{
    1533 SCIP_VAR** vars;
    1534 SCIP_VAR* var;
    1535 SCIP_HASHMAP* binobjvarmap;
    1536 int nvars;
    1537 int nbinvars;
    1538 int nintvars;
    1539 int nminactvars;
    1540 int nmaxactvars;
    1541 int nobjintvars;
    1542 int nobjcontvars;
    1543 int nobjvars;
    1544 int nbinobjvars;
    1545 int v;
    1546
    1547 assert(scip != NULL);
    1548 assert(propdata != NULL);
    1549
    1550 /* get problem variables */
    1551 vars = SCIPgetVars(scip);
    1552 nvars = SCIPgetNVars(scip);
    1553 nintvars = nvars - SCIPgetNContVars(scip);
    1554
    1555 nbinvars = 0;
    1556 nobjvars = 0;
    1557 nbinobjvars = 0;
    1558
    1560
    1561 /* count and collect variable problem indices of variables with non-zero objective coefficient */
    1562 for( v = 0; v < nvars; ++v )
    1563 {
    1564 var = vars[v];
    1565 assert(var != NULL);
    1566
    1567 if( !SCIPisZero(scip, SCIPvarGetObj(var)) )
    1568 {
    1569 nobjvars++;
    1570
    1571 if( SCIPvarIsBinary(var) )
    1572 {
    1573 SCIP_CALL( SCIPhashmapInsertInt(binobjvarmap, (void*)var, nbinobjvars + 1) );
    1574 nbinobjvars++;
    1575 }
    1576 }
    1577
    1578 if( SCIPvarIsBinary(var) )
    1579 nbinvars++;
    1580 }
    1581
    1582 nminactvars = 0;
    1583 nmaxactvars = 0;
    1584 nobjintvars = 0;
    1585 nobjcontvars = 0;
    1586
    1587 if( nobjvars > 0 )
    1588 {
    1589 SCIP_EVENTHDLR* eventhdlr;
    1590 SCIP_OBJIMPLICS* objimplics;
    1591 SCIP_HASHTABLE* uselesscliques;
    1592 SCIP_VAR** contributors;
    1593 SCIP_Bool* collectedlbvars;
    1594 SCIP_Bool* collectedubvars;
    1595 SCIP_Bool collect;
    1596 SCIP_Bool useimplics;
    1597 SCIP_Real objval;
    1598 SCIP_Real objchg;
    1599
    1600 eventhdlr = propdata->eventhdlr;
    1601 assert(eventhdlr != NULL);
    1602
    1603 useimplics = (propdata->propuseimplics && nbinobjvars < propdata->maximplvars);
    1604
    1605 /* allocate memory for all arrays */
    1606 propdata->minactsize = nbinvars;
    1607 propdata->maxactsize = nbinvars;
    1608 propdata->objintvarssize = nobjvars - nbinobjvars;
    1609 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &propdata->minactvars, propdata->minactsize) );
    1610 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &propdata->minactimpls, propdata->minactsize) );
    1611 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &propdata->maxactvars, propdata->maxactsize) );
    1612 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &propdata->maxactchgs, propdata->maxactsize) );
    1613 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &propdata->objintvars, propdata->objintvarssize) );
    1614
    1615 if( useimplics )
    1616 {
    1617 int ncliques;
    1618
    1619 /* create temporary buffer */
    1620 /* we store both lb and ub contributors in array contributors, and both could be nbinobjvars, we need twice that size */
    1621 SCIP_CALL( SCIPallocBufferArray(scip, &contributors, 2 * nbinobjvars) );
    1622 /* @todo: use SCIPallocCleanBufferArray instead? */
    1623 SCIP_CALL( SCIPallocClearBufferArray(scip, &collectedlbvars, nbinobjvars+1) );
    1624 /* @todo: use SCIPallocCleanBufferArray instead? */
    1625 SCIP_CALL( SCIPallocClearBufferArray(scip, &collectedubvars, nbinobjvars+1) );
    1626
    1627 ncliques = SCIPgetNCliques(scip);
    1628
    1629 if( ncliques > 0 )
    1630 {
    1631 SCIP_CALL( SCIPhashtableCreate(&uselesscliques, SCIPblkmem(scip), ncliques,
    1632 cliqueGetHashkey, cliqueIsHashkeyEq, cliqueGetHashkeyVal, NULL) );
    1633 }
    1634 else
    1635 uselesscliques = NULL;
    1636 }
    1637 else
    1638 {
    1639 contributors = NULL;
    1640 collectedlbvars = NULL;
    1641 collectedubvars = NULL;
    1642 uselesscliques = NULL;
    1643 }
    1644
    1645 /* collect the variables with non-zero objective contribution and catch global bound tighten events that decrease the
    1646 * maximal pseudo objective activity
    1647 */
    1648 for( v = 0; v < nvars && (nobjintvars == 0 || nobjintvars < propdata->objintvarssize); ++v )
    1649 {
    1650 var = vars[v];
    1651 assert(var != NULL);
    1652
    1653 objval = SCIPvarGetObj(var);
    1654
    1655 if( SCIPvarIsBinary(var) )
    1656 {
    1657 /* ignore variables which are globally fixed */
    1658 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
    1659 {
    1660#ifndef NDEBUG
    1661 /* check that the binary implications are applied for binary variables which are globally fixed */
    1663#endif
    1664 continue;
    1665 }
    1666
    1667 /* check if the variable should be collected for the minimum activity propagation */
    1668 SCIP_CALL( collectMinactVar(scip, var, &objimplics, useimplics, binobjvarmap, collectedlbvars, collectedubvars,
    1669 nbinobjvars, contributors, uselesscliques, &collect) );
    1670
    1671 if( collect )
    1672 {
    1673 assert(nminactvars < nbinvars);
    1674 assert(objimplics != NULL);
    1675 assert(objimplics->nlbimpls + objimplics->nubimpls <= nbinobjvars);
    1676
    1677 /* collect the binary variable with non-zero objective contribution */
    1678 propdata->minactvars[nminactvars] = var;
    1679 propdata->minactimpls[nminactvars] = objimplics;
    1680 nminactvars++;
    1681
    1682 /* catch bound relax event for the binary variable to handel the firstnonfixed index correctly */
    1684
    1685 SCIPdebugMsg(scip, "variable <%s>[obj: <%g>] implicit objective change %g\n",
    1686 SCIPvarGetName(var), objval, objimplics->maxobjchg);
    1687
    1688 /* captures the variable */
    1689 SCIP_CALL( SCIPcaptureVar(scip, var) ) ;
    1690 }
    1691 /* check if the variable should be collected for the maximum activity propagation */
    1692 SCIP_CALL( collectMaxactVar(scip, var, useimplics, &objchg, &collect) );
    1693
    1694 if( collect )
    1695 {
    1696 assert(nmaxactvars < nbinvars);
    1697
    1698 /* collect the binary variable with non-zero objective contribution */
    1699 propdata->maxactvars[nmaxactvars] = var;
    1700 propdata->maxactchgs[nmaxactvars] = -objchg;
    1701 nmaxactvars++;
    1702
    1703 /* catch bound change events if the variable has a non-zero objective coefficient to check if the maximum
    1704 * activity of the objective function changed
    1705 */
    1706 SCIP_CALL( catchObjEvent(scip, propdata, eventhdlr, var) );
    1707
    1708 /* captures the variable */
    1709 SCIP_CALL( SCIPcaptureVar(scip, var) ) ;
    1710 }
    1711 }
    1712 else
    1713 {
    1714 /* only consider non-binary variables with a non-zero objective */
    1715 if( SCIPisZero(scip, objval) )
    1716 continue;
    1717
    1718 assert(nobjintvars < propdata->objintvarssize);
    1719
    1720 propdata->objintvars[nobjintvars] = var;
    1721 nobjintvars++;
    1722
    1723 if( v >= nintvars )
    1724 nobjcontvars++;
    1725
    1726 /* catch bound change events if the variable has a non-zero objective coefficient to check if the maximum
    1727 * activity of the objective function changed
    1728 */
    1729 SCIP_CALL( catchObjEvent(scip, propdata, eventhdlr, var) );
    1730
    1731 /* captures the variable */
    1732 SCIP_CALL( SCIPcaptureVar(scip, var) );
    1733 }
    1734 }
    1735
    1736 if( useimplics )
    1737 {
    1738 if( uselesscliques != NULL )
    1739 SCIPhashtableFree(&uselesscliques);
    1740
    1741 SCIPfreeBufferArray(scip, &collectedubvars);
    1742 SCIPfreeBufferArray(scip, &collectedlbvars);
    1743 SCIPfreeBufferArray(scip, &contributors);
    1744 }
    1745
    1746 if( nminactvars == 0 )
    1747 {
    1748 SCIPfreeBlockMemoryArray(scip, &propdata->minactvars, propdata->minactsize);
    1749 SCIPfreeBlockMemoryArray(scip, &propdata->minactimpls, propdata->minactsize);
    1750 propdata->minactsize = 0;
    1751 propdata->minactvars = NULL;
    1752 propdata->minactimpls = NULL;
    1753 }
    1754 else
    1755 {
    1756 /* sort binary variables with respect to the absolute value of their maximal potential objective contribution for
    1757 * the minimum activity of the objective function
    1758 */
    1759 SCIPsortDownPtrPtr((void**)propdata->minactimpls, (void**)propdata->minactvars, objimplicsComp, nminactvars);
    1760
    1761 SCIPdebugMsg(scip, "%d binary variables with non-zero objective contribution w.r.t. the minimum activity of the objective function\n", nminactvars);
    1762 }
    1763
    1764 if( nmaxactvars == 0 )
    1765 {
    1766 SCIPfreeBlockMemoryArray(scip, &propdata->maxactvars, propdata->maxactsize);
    1767 SCIPfreeBlockMemoryArray(scip, &propdata->maxactchgs, propdata->maxactsize);
    1768 propdata->maxactsize = 0;
    1769 propdata->maxactvars = NULL;
    1770 propdata->maxactchgs = NULL;
    1771 }
    1772 else
    1773 {
    1774 /* sort binary variables with respect to the absolute value of their maximal potential objective contribution for
    1775 * the maximum activity of the objective function
    1776 */
    1777 SCIPsortDownRealPtr(propdata->maxactchgs, (void**)propdata->maxactvars, nmaxactvars);
    1778
    1779 SCIPdebugMsg(scip, "%d binary variables with non-zero objective contribution w.r.t. the maximum activity of the objective function\n", nmaxactvars);
    1780 }
    1781
    1782 if( nobjintvars == 0 )
    1783 {
    1784 SCIPfreeBlockMemoryArray(scip, &propdata->objintvars, propdata->objintvarssize);
    1785 propdata->objintvarssize = 0;
    1786 propdata->objintvars = NULL;
    1787 }
    1788 else
    1789 {
    1790 /* sort integer variables with respect to the absolute value of their objective coefficient */
    1791 SCIPsortDownPtr((void**)propdata->objintvars, varCompObj, nobjintvars - nobjcontvars);
    1792
    1793 /* sort continuous variables with respect to the absolute value of their objective coefficient */
    1794 SCIPsortDownPtr((void**)(&propdata->objintvars[nobjintvars - nobjcontvars]), varCompObj, nobjcontvars);
    1795
    1796 SCIPdebugMsg(scip, "%d integer variables and %d continuous variables with non-zero objective contribution\n",
    1797 nobjintvars - nobjcontvars, nobjcontvars);
    1798 }
    1799 }
    1800
    1801 SCIPhashmapFree(&binobjvarmap);
    1802
    1803 propdata->nminactvars = nminactvars;
    1804 propdata->nmaxactvars = nmaxactvars;
    1805 propdata->nobjintvars = nobjintvars;
    1806 propdata->maxpseudoobjact = SCIP_INVALID;
    1807 propdata->maxpseudoobjactinf = 0;
    1808 propdata->lastvarnum = -1;
    1809 propdata->glbfirstnonfixed = 0;
    1810 propdata->maxactfirstnonfixed = 0;
    1811 propdata->firstnonfixed = 0;
    1812 propdata->nnewvars = 0;
    1813 propdata->cutoffbound = SCIPinfinity(scip);
    1814 propdata->lastlowerbound = -SCIPinfinity(scip);
    1815 propdata->glbpseudoobjval = -SCIPinfinity(scip);
    1816
    1817 propdata->initialized = TRUE;
    1818
    1819 /* due to scaling after presolving we need to update the global pseudoactivity and the cutoffbound */
    1820 propdata->glbpropagated = FALSE;
    1821 propdata->glbpseudoobjval = SCIPgetGlobalPseudoObjval(scip);
    1822 propdata->cutoffbound = SCIPgetCutoffbound(scip);
    1823 assert(SCIPgetDepth(scip) > 0 || SCIPisRelEQ(scip, propdata->glbpseudoobjval, SCIPgetPseudoObjval(scip)));
    1824
    1825 /* create hash table which is used for resolving bound changes */
    1826 if( nminactvars > 0 )
    1827 {
    1828 SCIP_CALL( SCIPhashtableCreate(&propdata->addedvars, SCIPblkmem(scip), nvars,
    1829 SCIPvarGetHashkey, SCIPvarIsHashkeyEq, SCIPvarGetHashkeyVal, NULL) );
    1830 }
    1831 else
    1832 propdata->addedvars = NULL;
    1833
    1834 return SCIP_OKAY;
    1835}
    1836
    1837/** adds for the given non-binary variable a conflict bound depending on its objective contribution */
    1838static
    1840 SCIP* scip, /**< SCIP data structure */
    1841 SCIP_VAR* var, /**< variable to check for objective contribution */
    1842 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
    1843 SCIP_Real* reqpseudoobjval /**< pointer to store the remaining minimum activity which has to be proven */
    1844 )
    1845{
    1846 SCIP_Real objval;
    1847
    1848 objval = SCIPvarGetObj(var);
    1849 assert(!SCIPisZero(scip, objval));
    1850
    1851 if( objval > 0.0 )
    1852 {
    1853 SCIP_Real loclb;
    1854 SCIP_Real glblb;
    1855
    1856 glblb = SCIPvarGetLbGlobal(var);
    1857 loclb = SCIPgetVarLbAtIndex(scip, var, bdchgidx, FALSE);
    1858 assert(SCIPisFeasGE(scip, loclb, glblb));
    1859
    1860 /* check if the local lower bound (at time stamp bdchgidx) is larger than the global lower bound */
    1861 if( SCIPisGT(scip, loclb, glblb) )
    1862 {
    1863 SCIPdebugMsg(scip, " add bound change <%s>[%g] >= <%g>\n", SCIPvarGetName(var), objval, loclb);
    1864 SCIP_CALL( SCIPaddConflictLb(scip, var, bdchgidx) );
    1865
    1866 /* hard comparison is enough to make requiredpseudoobjval nonincreasing */
    1867 assert((loclb - glblb) * objval > 0.0);
    1868
    1869 (*reqpseudoobjval) -= (loclb - glblb) * objval;
    1870 }
    1871 }
    1872 else
    1873 {
    1874 SCIP_Real locub;
    1875 SCIP_Real glbub;
    1876
    1877 glbub = SCIPvarGetUbGlobal(var);
    1878 locub = SCIPgetVarUbAtIndex(scip, var, bdchgidx, FALSE);
    1879 assert(SCIPisFeasLE(scip, locub, glbub));
    1880
    1881 /* check if the local upper bound (at time stamp bdchgidx) is smaller than the global upper bound */
    1882 if( SCIPisLT(scip, locub, glbub) )
    1883 {
    1884 SCIPdebugMsg(scip, " add bound change <%s>[%g] <= <%g>\n", SCIPvarGetName(var), objval, locub);
    1885 SCIP_CALL( SCIPaddConflictUb(scip, var, bdchgidx) );
    1886
    1887 /* hard comparison is enough to make requiredpseudoobjval nonincreasing */
    1888 assert((locub - glbub) * objval > 0.0);
    1889
    1890 (*reqpseudoobjval) -= (locub - glbub) * objval;
    1891 }
    1892 }
    1893
    1894 return SCIP_OKAY;
    1895}
    1896
    1897/** check for the given implication variables if they also contribute to the required minimum activity */
    1898static
    1900 SCIP* scip, /**< SCIP data structure */
    1901 SCIP_VAR** vars, /**< variable to check for objective contribution */
    1902 int start, /**< start index */
    1903 int end, /**< end index */
    1904 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
    1905 SCIP_HASHTABLE* addedvars, /**< hash table containing variables which are already added directly or implicitly due to implications */
    1906 SCIP_Real* reqpseudoobjval, /**< pointer to store the remaining minimum activity which has to be proven */
    1907 SCIP_Bool* foundimplics /**< pointer to store if an implication is found */
    1908 )
    1909{
    1910 SCIP_VAR* var;
    1911 SCIP_Real lb;
    1912 SCIP_Real ub;
    1913 int v;
    1914
    1915 assert(foundimplics != NULL);
    1916 assert(*foundimplics == FALSE);
    1917
    1918 for( v = start; v < end; ++v )
    1919 {
    1920 var = vars[v];
    1921 assert(var != NULL);
    1922 assert(SCIPvarIsBinary(var));
    1923
    1924 /* we need to take the bounds after the bdchgidx here, since the variable of the bound change may be the implied one;
    1925 * we already counted its contribution before, so we want to see it as fixed here, which it is after the bound change.
    1926 */
    1927 lb = SCIPgetVarLbAtIndex(scip, var, bdchgidx, TRUE);
    1928 ub = SCIPgetVarUbAtIndex(scip, var, bdchgidx, TRUE);
    1929
    1930 if( lb < 0.5 && ub > 0.5 && !SCIPhashtableExists(addedvars, (void*)var) )
    1931 {
    1932 (*reqpseudoobjval) -= REALABS(SCIPvarGetObj(var));
    1933 SCIPdebugMsg(scip, " implicated variables <%s>[%g] bdchgidx [%g,%g] -> remaining <%g>\n", SCIPvarGetName(var), SCIPvarGetObj(var), lb, ub, *reqpseudoobjval);
    1934
    1935 SCIP_CALL( SCIPhashtableInsert(addedvars, (void*)var) );
    1936 assert(SCIPhashtableExists(addedvars, (void*)var));
    1937 (*foundimplics) = TRUE;
    1938 }
    1939 }
    1940
    1941 return SCIP_OKAY;
    1942}
    1943
    1944/** adds for the given binary variable a conflict bound depending on its objective contribution */
    1945static
    1947 SCIP* scip, /**< SCIP data structure */
    1948 SCIP_VAR* var, /**< variable to check for objective contribution */
    1949 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
    1950 SCIP_OBJIMPLICS* objimplics, /**< objective implication data for the given variable */
    1951 SCIP_HASHTABLE* addedvars, /**< hash table containing variables which are already add directly or implicitly due to implications */
    1952 SCIP_Bool respropuseimplics, /**< should implications be used */
    1953 SCIP_Real* reqpseudoobjval /**< pointer to store the remaining minimum activity which has to be proven */
    1954 )
    1955{
    1956 SCIP_Real objval;
    1957 SCIP_Real lb;
    1958 SCIP_Real ub;
    1959 SCIP_Bool foundimplics;
    1960
    1961 assert(SCIPvarIsBinary(var));
    1962
    1963 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
    1964 return SCIP_OKAY;
    1965
    1966 lb = SCIPgetVarLbAtIndex(scip, var, bdchgidx, FALSE);
    1967 ub = SCIPgetVarUbAtIndex(scip, var, bdchgidx, FALSE);
    1968
    1969 objval = SCIPvarGetObj(var);
    1970 foundimplics = FALSE;
    1971
    1972 /* only consider variables which are fixed */
    1973 if( lb > 0.5 )
    1974 {
    1975 if( respropuseimplics )
    1976 {
    1977 assert(objimplics != NULL);
    1978 SCIP_CALL( getConflictImplics(scip, objimplics->objvars, objimplics->nlbimpls, objimplics->nlbimpls + objimplics->nubimpls,
    1979 bdchgidx, addedvars, reqpseudoobjval, &foundimplics) );
    1980 }
    1981
    1982 /* check if the binary variable has a positive contribution (positive objective coefficient since it is fixed to
    1983 * one) or is needed due a positive contribution of an implied variable
    1984 */
    1985 if( foundimplics || SCIPisPositive(scip, objval) )
    1986 {
    1987 SCIPdebugMsg(scip, " add bound change <%s>[%g] >= <%g> bdchgidx [%g,%g]\n", SCIPvarGetName(var), objval, lb, lb, ub);
    1989
    1990 (*reqpseudoobjval) -= MAX(0.0, objval);
    1991
    1992 if( addedvars != NULL )
    1993 {
    1994 assert(!SCIPhashtableExists(addedvars, (void*)var));
    1995 SCIP_CALL( SCIPhashtableInsert(addedvars, (void*)var) );
    1996 }
    1997 }
    1998 }
    1999 else if( ub < 0.5 )
    2000 {
    2001 if( respropuseimplics )
    2002 {
    2003 assert(objimplics != NULL);
    2004 SCIP_CALL( getConflictImplics(scip, objimplics->objvars, 0, objimplics->nlbimpls,
    2005 bdchgidx, addedvars, reqpseudoobjval, &foundimplics) );
    2006 }
    2007
    2008 /* check if the binary variable has a positive contribution (negative objective coefficient since it is fixed to
    2009 * zero) or is needed due a positive contribution of an implied variable
    2010 */
    2011 if( foundimplics || SCIPisNegative(scip, objval) )
    2012 {
    2013 SCIPdebugMsg(scip, " add bound change <%s>[%g] <= <%g> bdchgidx=[%g,%g]\n", SCIPvarGetName(var), objval, ub, lb, ub);
    2015
    2016 (*reqpseudoobjval) += MIN(0.0, objval);
    2017
    2018 if( addedvars != NULL )
    2019 {
    2020 assert(!SCIPhashtableExists(addedvars, (void*)var));
    2021 SCIP_CALL( SCIPhashtableInsert(addedvars, (void*)var) );
    2022 }
    2023 }
    2024 }
    2025
    2026 return SCIP_OKAY;
    2027}
    2028
    2029
    2030/** resolves a propagation by supplying the variables whose bound changes increased the pseudo objective value above the
    2031 * cutoff bound
    2032 */
    2033static
    2035 SCIP* scip, /**< SCIP data structure */
    2036 SCIP_PROPDATA* propdata, /**< propagator data */
    2037 SCIP_VAR* var, /**< variable that was deduced */
    2038 int inferinfo, /**< inference information */
    2039 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
    2040 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
    2041 SCIP_HASHTABLE* addedvars, /**< hash table which contains variables which are already added or implicitly given as reason for the resolve, or NULL */
    2042 SCIP_Real* cutoffbound /**< pointer to store the adjusted cutoff bound */
    2043 )
    2044{
    2045 if( inferinfo != -1 )
    2046 {
    2047 SCIP_OBJIMPLICS* objimplics;
    2048 int start;
    2049 int end;
    2050
    2051 assert(var != NULL);
    2052 assert(SCIPvarIsBinary(var));
    2053 assert(bdchgidx != NULL);
    2054 assert(SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, var, bdchgidx, TRUE), SCIPgetVarUbAtIndex(scip, var, bdchgidx, TRUE)));
    2055 assert(inferinfo >= 0);
    2056 assert(inferinfo < propdata->nminactvars);
    2057 assert((SCIP_Bool)SCIP_BOUNDTYPE_LOWER == FALSE); /*lint !e506*/
    2058 assert((SCIP_Bool)SCIP_BOUNDTYPE_UPPER == TRUE); /*lint !e506*/
    2059
    2060 objimplics = propdata->minactimpls[inferinfo];
    2061 assert(objimplics != NULL);
    2062
    2063 /* get the objective contribution if we would fix the binary inference variable to its other bound */
    2064 (*cutoffbound) -= getVarObjchg(var, SCIPvarGetBestBoundType(var), boundtype);
    2065
    2066 if( boundtype == SCIP_BOUNDTYPE_LOWER )
    2067 {
    2068 start = 0;
    2069 end = objimplics->nlbimpls;
    2070 }
    2071 else
    2072 {
    2073 start = objimplics->nlbimpls;
    2074 end = objimplics->nlbimpls + objimplics->nubimpls;
    2075 }
    2076
    2077 if( addedvars != NULL )
    2078 {
    2079 SCIP_Bool foundimplics = FALSE;
    2080 SCIP_CALL( getConflictImplics(scip, objimplics->objvars, start, end, bdchgidx, addedvars, cutoffbound, &foundimplics) );
    2081 } /*lint !e438*/
    2082 }
    2083 else
    2084 {
    2085 SCIP_Real glbbound;
    2086 SCIP_Real newbound;
    2087 SCIP_Real objval;
    2088
    2089 objval = SCIPvarGetObj(var);
    2090
    2091 assert(!SCIPisZero(scip, objval));
    2092
    2093 if( objval > 0.0 )
    2094 {
    2095 newbound = SCIPgetVarUbAtIndex(scip, var, bdchgidx, TRUE);
    2096 glbbound = SCIPvarGetLbGlobal(var);
    2097 }
    2098 else
    2099 {
    2100 newbound = SCIPgetVarLbAtIndex(scip, var, bdchgidx, TRUE);
    2101 glbbound = SCIPvarGetUbGlobal(var);
    2102 }
    2103
    2104 /* in case the variable is integral we just need to prove the newbound plus/minus (1 - epsilon) since the this bound
    2105 * would be rounded to newbound due to integrability which is global information
    2106 */
    2107 if( SCIPvarIsIntegral(var) )
    2108 {
    2109 if( objval > 0.0 )
    2110 newbound += 1 - 10 * SCIPfeastol(scip);
    2111 else
    2112 newbound -= 1 - 10 * SCIPfeastol(scip);
    2113 }
    2114
    2115 /* adjust the cutoff bound by the portion the inference variable contributes to the presudo objective activity
    2116 * (minactivity)
    2117 */
    2118 assert(!SCIPisNegative(scip, objval * (newbound - glbbound)));
    2119 (*cutoffbound) -= objval * (newbound - glbbound);
    2120 }
    2121
    2122 return SCIP_OKAY;
    2123}
    2124
    2125
    2126/** resolves a propagation by supplying the variables whose bound changes increased the pseudo objective value above the
    2127 * cutoff bound
    2128 */
    2129static
    2131 SCIP* scip, /**< SCIP data structure */
    2132 SCIP_PROPDATA* propdata, /**< propagator data */
    2133 SCIP_Real cutoffbound, /**< the global cutoff */
    2134 SCIP_VAR* infervar, /**< variable that was deduced, or NULL for conflict analysis initialization */
    2135 int inferinfo, /**< inference information */
    2136 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
    2137 SCIP_BDCHGIDX* bdchgidx /**< bound change index (time stamp of bound change), or NULL for current time */
    2138 )
    2139{
    2140 SCIP_HASHTABLE* addedvars;
    2141 SCIP_VAR** vars;
    2142 SCIP_VAR* var;
    2143 SCIP_Real glbpseudoobjval;
    2144 SCIP_Real reqpseudoobjval;
    2146 int nvars;
    2147 int v;
    2148
    2149 infinity = FALSE;
    2150 addedvars = NULL;
    2151 nvars = propdata->nminactvars;
    2152
    2153 /* the global pseudo value gives us a global valid minimal activity
    2154 *
    2155 * @note The global pseudo objective activity can be minus infinity. In that case all variable are part of the
    2156 * reason/explanation
    2157 *
    2158 * @note If the global pseudo objective activity is greater than the required minactivity, the local bound change
    2159 * which has to explained is actually (now) a global one. That means, the reason/explanation is empty
    2160 */
    2161 glbpseudoobjval = SCIPgetGlobalPseudoObjval(scip);
    2162
    2163 if( SCIPisInfinity(scip, -glbpseudoobjval) )
    2164 {
    2165 infinity = TRUE;
    2166 reqpseudoobjval = cutoffbound;
    2167 }
    2168 else
    2169 {
    2170 /* clear hash table for storing variables which are not needed to add the reason due to global implications or
    2171 * already added
    2172 */
    2173 if( nvars > 0 )
    2174 {
    2175 addedvars = propdata->addedvars;
    2176 SCIPhashtableRemoveAll(addedvars);
    2177 }
    2178
    2179 if( infervar != NULL )
    2180 {
    2181 SCIP_CALL( adjustCutoffbound(scip, propdata, infervar, inferinfo, boundtype, bdchgidx, addedvars, &cutoffbound) );
    2182 }
    2183
    2184 reqpseudoobjval = cutoffbound - glbpseudoobjval;
    2185 }
    2186
    2187 SCIPdebugMsg(scip, "resolve propagation global pseudo objective <%g>, cutoff bounda <%g>, required minactivity <%g>\n",
    2188 glbpseudoobjval, cutoffbound, reqpseudoobjval);
    2189
    2190 /* the variables responsible for the propagation are the ones with
    2191 * - obj > 0 and local lb > global lb
    2192 * - obj < 0 and local ub < global ub
    2193 *
    2194 * collect all variables which contribute positively to the pseudo objective value (minimum activity) until we
    2195 * reached the (adjusted) required minimum activity for the inference bound change
    2196 */
    2197
    2198 /* first, consider the binary variables */
    2199 if( nvars > 0 )
    2200 {
    2201 SCIP_OBJIMPLICS** minactimpls;
    2202
    2203 vars = propdata->minactvars;
    2204 assert(vars != NULL);
    2205
    2206 minactimpls = propdata->minactimpls;
    2207 assert(minactimpls != NULL);
    2208
    2209#ifndef NDEBUG
    2210 checkGlbfirstnonfixed(propdata);
    2211#endif
    2212
    2213 if( infinity )
    2214 {
    2215 /* if the required minimum activity is minus infinity, we have to add all variables which contribute the local
    2216 * pseudo objective activity
    2217 */
    2218
    2219 for( v = propdata->glbfirstnonfixed; v < nvars; ++v )
    2220 {
    2221 var = vars[v];
    2222 assert(var != NULL);
    2223
    2224 /* @note binary variables can have a zero objective value */
    2225
    2226 if( var == infervar )
    2227 continue;
    2228
    2229 SCIP_CALL( addConflictBinvar(scip, var, bdchgidx, NULL, NULL, FALSE, &reqpseudoobjval) );
    2230 }
    2231 }
    2232 else
    2233 {
    2234 assert(addedvars != NULL);
    2235
    2236 for( v = propdata->glbfirstnonfixed; v < nvars && SCIPisPositive(scip, reqpseudoobjval); ++v )
    2237 {
    2238 var = vars[v];
    2239 assert(var != NULL);
    2240
    2241 /* @note binary variables can have a zero objective value */
    2242
    2243 if( var == infervar )
    2244 continue;
    2245
    2246 if( SCIPhashtableExists(addedvars, (void*)var) )
    2247 continue;
    2248
    2249 SCIP_CALL( addConflictBinvar(scip, var, bdchgidx, minactimpls[v], addedvars, propdata->respropuseimplics, &reqpseudoobjval) );
    2250 }
    2251 }
    2252 }
    2253
    2254 vars = propdata->objintvars;
    2255 nvars = propdata->nobjintvars;
    2256 assert(nvars == 0 || vars != NULL);
    2257
    2258 /* second, consider the non-binary variables */
    2259 for( v = 0; v < nvars && (infinity || SCIPisPositive(scip, reqpseudoobjval)); ++v )
    2260 {
    2261 var = vars[v];
    2262 assert(var != NULL);
    2263 assert(!SCIPisZero(scip, SCIPvarGetObj(var)));
    2264
    2265 if( var == infervar )
    2266 continue;
    2267
    2268 SCIP_CALL( addConflictBounds(scip, var, bdchgidx, &reqpseudoobjval) );
    2269 }
    2270
    2271 return SCIP_OKAY;
    2272}
    2273
    2274/** propagates the given variable against the cutoff bound */
    2275static
    2277 SCIP* scip, /**< SCIP data structure */
    2278 SCIP_PROP* prop, /**< propagator, or NULL */
    2279 SCIP_VAR* var, /**< variable to propagate */
    2280 int inferinfo, /**< inference information to store with the bound change */
    2281 SCIP_Real objchg, /**< objective change */
    2282 SCIP_Real cutoffbound, /**< cutoff bound to use */
    2283 SCIP_Real pseudoobjval, /**< pseudo objective value to use */
    2284 SCIP_Bool local, /**< local or global propagation */
    2285 SCIP_Bool* tightened /**< pointer to store if the variable domain was tightened */
    2286 )
    2287{
    2288 SCIP_Real lb;
    2289 SCIP_Real ub;
    2290 SCIP_Real newbd;
    2291 SCIP_Bool infeasible;
    2292
    2293 assert(!SCIPisZero(scip, objchg));
    2294 assert(!SCIPisInfinity(scip, -pseudoobjval));
    2295 assert(!SCIPisInfinity(scip, cutoffbound));
    2296 assert(SCIPisLT(scip, pseudoobjval, cutoffbound) );
    2297 assert(tightened != NULL);
    2298
    2299 *tightened = FALSE;
    2300
    2301 /* collect bounds of the variable */
    2302 if( local )
    2303 {
    2304 assert(prop != NULL);
    2305 lb = SCIPvarGetLbLocal(var);
    2306 ub = SCIPvarGetUbLocal(var);
    2307 }
    2308 else
    2309 {
    2310 lb = SCIPvarGetLbGlobal(var);
    2311 ub = SCIPvarGetUbGlobal(var);
    2312 }
    2313
    2314 if( SCIPisFeasEQ(scip, lb, ub) )
    2315 return SCIP_OKAY;
    2316
    2317 /* depending on the objective contribution we can try to tighten the lower or upper bound of the variable */
    2318 if( objchg > 0.0 )
    2319 {
    2320 SCIP_Real QUAD(newbdq);
    2321
    2322 /* the new variable bound is lb + (cutoffbound - pseudoobjval) / objchg */
    2323 SCIPquadprecSumDD(newbdq, cutoffbound, -pseudoobjval);
    2324 SCIPquadprecDivQD(newbdq, newbdq, objchg);
    2325 SCIPquadprecSumQD(newbdq, newbdq, lb);
    2326 newbd = QUAD_TO_DBL(newbdq);
    2327
    2328 if( local )
    2329 {
    2330 SCIP_CALL( SCIPinferVarUbProp(scip, var, newbd, prop, inferinfo, FALSE, &infeasible, tightened) );
    2331 assert(!infeasible);
    2332
    2333 if( *tightened ) /* might not be tightened due to numerical reasons */
    2334 {
    2335 SCIPdebugMsg(scip, " -> new (local) upper bound of variable <%s>[%g,%g]: %g, objective change <%g>, pseudo objective <%g>, cutoff bound <%g>\n",
    2336 SCIPvarGetName(var), lb, ub, newbd, objchg, pseudoobjval, cutoffbound);
    2337 }
    2338 }
    2339 else
    2340 {
    2341 SCIP_CALL( SCIPtightenVarUbGlobal(scip, var, newbd, FALSE, &infeasible, tightened) );
    2342 assert(!infeasible);
    2343
    2344 if( *tightened )
    2345 {
    2346 SCIPdebugMsg(scip, " -> new (global) upper bound of variable <%s>[%g,%g]: %g, objective change <%g>, pseudo objective <%g>, cutoff bound <%g>\n",
    2347 SCIPvarGetName(var), lb, ub, newbd, objchg, pseudoobjval, cutoffbound);
    2348 }
    2349 }
    2350 }
    2351 else
    2352 {
    2353 SCIP_Real QUAD(newbdq);
    2354
    2355 /* the new variable bound is ub + (cutoffbound - pseudoobjval) / objchg */
    2356 SCIPquadprecSumDD(newbdq, cutoffbound, -pseudoobjval);
    2357 SCIPquadprecDivQD(newbdq, newbdq, objchg);
    2358 SCIPquadprecSumQD(newbdq, newbdq, ub);
    2359 newbd = QUAD_TO_DBL(newbdq);
    2360
    2361 if( local )
    2362 {
    2363 SCIP_CALL( SCIPinferVarLbProp(scip, var, newbd, prop, inferinfo, FALSE, &infeasible, tightened) );
    2364 assert(!infeasible);
    2365
    2366 if( *tightened ) /* might not be tightened due to numerical reasons */
    2367 {
    2368 SCIPdebugMsg(scip, " -> new (local) lower bound of variable <%s>[%g,%g]: %g, objective change <%g>, pseudo objective <%g>, cutoff bound <%g>\n",
    2369 SCIPvarGetName(var), lb, ub, newbd, objchg, pseudoobjval, cutoffbound);
    2370 }
    2371 }
    2372 else
    2373 {
    2374 SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, newbd, FALSE, &infeasible, tightened) );
    2375 assert(!infeasible);
    2376
    2377 if( *tightened )
    2378 {
    2379 SCIPdebugMsg(scip, " -> new (global) lower bound of variable <%s>[%g,%g]: %g, objective change <%g>, pseudo objective <%g>, cutoff bound <%g>\n",
    2380 SCIPvarGetName(var), lb, ub, newbd, objchg, pseudoobjval, cutoffbound);
    2381 }
    2382 }
    2383 }
    2384
    2385 return SCIP_OKAY;
    2386}
    2387
    2388/** propagates the given binary variable against the cutoff bound */
    2389static
    2391 SCIP* scip, /**< SCIP data structure */
    2392 SCIP_PROP* prop, /**< propagator, or NULL */
    2393 SCIP_VAR* var, /**< variable to propagate */
    2394 int pos, /**< position of the variable in the corresponding propdata variable array */
    2395 SCIP_Real cutoffbound, /**< cutoff bound to use */
    2396 SCIP_Real pseudoobjval, /**< pseudo objective value to use */
    2397 SCIP_Bool* tightened, /**< pointer to store if the variable domain was tightened */
    2398 SCIP_Bool* cutoff, /**< pointer to store if a cutoff was detected */
    2399 SCIP_Bool local /**< propagate local bounds, otherwise global bounds */
    2400 )
    2401{
    2402 SCIP_PROPDATA* propdata;
    2403 SCIP_OBJIMPLICS* objimplics;
    2404 SCIP_Real lbobjchg;
    2405 SCIP_Real ubobjchg;
    2406 SCIP_Real objchg;
    2407
    2408 assert(SCIPvarIsBinary(var));
    2409
    2410 propdata = SCIPpropGetData(prop);
    2411 assert(propdata != NULL);
    2412
    2413 objimplics = propdata->minactimpls[pos];
    2414 assert(objimplics != NULL);
    2415
    2416 /* get objective change in case of fixing the variable to its lower bound (that is zero) */
    2417 SCIP_CALL( getMinactObjchg(scip, var, objimplics, NULL, SCIP_BOUNDTYPE_LOWER, local, &lbobjchg) );
    2418 assert(!SCIPisNegative(scip, lbobjchg));
    2419
    2420 /* get objective change in case of fixing the variable to its upper bound (that is one) */
    2421 SCIP_CALL( getMinactObjchg(scip, var, objimplics, NULL, SCIP_BOUNDTYPE_UPPER, local, &ubobjchg) );
    2422 assert(!SCIPisNegative(scip, ubobjchg));
    2423
    2424 (*tightened) = FALSE;
    2425
    2426 /* nothing can be done if the objective contribution is zero independently of the bound */
    2427 if( SCIPisZero(scip, lbobjchg) && SCIPisZero(scip, ubobjchg) )
    2428 return SCIP_OKAY;
    2429
    2430 /* if the lbobjchg and ubobjchg are both able to fix the variable to its upper (1.0) or lower (0.0) bound,
    2431 * respectively, we detected an cutoff
    2432 *
    2433 * @note There is no need to use SCIPisLT() in case the objective is integral since the cutoff bound in that case
    2434 * is the upper bound minus 1 plus the SCIPcutoffbounddelta() (which is MIN(100.0 * feastol, 0.0001)). However,
    2435 * if the objective is not integral we have to check w.r.t. an epsilon to avoid numerical problems.
    2436 */
    2437 if( SCIPisLT(scip, cutoffbound, pseudoobjval + ubobjchg) && SCIPisLT(scip, cutoffbound, pseudoobjval + lbobjchg) )
    2438 {
    2439 /* check if conflict analysis is applicable */
    2441 {
    2442 assert(SCIPgetDepth(scip) > 0);
    2443
    2444 /* initialize conflict analysis */
    2446
    2447 /* add all variable whose best bound changes increased the pseudo objective value above to cutoff bound */
    2448 SCIP_CALL( resolvePropagation(scip, propdata, pseudoobjval, NULL, -1, SCIP_BOUNDTYPE_UPPER, NULL) );
    2449
    2450 /* analyze the conflict */
    2452 }
    2453
    2454 (*cutoff) = TRUE;
    2455 }
    2456 else
    2457 {
    2458 /* try to tighten the variable bound use the larger objective contribution */
    2459 if( lbobjchg > ubobjchg )
    2460 objchg = -lbobjchg;
    2461 else
    2462 objchg = ubobjchg;
    2463
    2464 SCIP_CALL( propagateCutoffboundVar(scip, prop, var, pos, objchg, cutoffbound, pseudoobjval, local, tightened) );
    2465 }
    2466
    2467 return SCIP_OKAY;
    2468}
    2469
    2470/** globally propagates if a new cutoff bound or global pseudo objective value (minimum activity of the objective
    2471 * function) is available
    2472 */
    2473static
    2475 SCIP* scip, /**< SCIP data structure */
    2476 SCIP_PROP* prop, /**< propagator */
    2477 int* nchgbds, /**< pointer to store the number of bound changes */
    2478 SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */
    2479 )
    2480{
    2481 SCIP_PROPDATA* propdata;
    2482 SCIP_VAR** minactvars;
    2483 SCIP_VAR** objintvars;
    2484 SCIP_VAR* var;
    2485 SCIP_Bool tightened;
    2486 SCIP_Real pseudoobjval;
    2487 SCIP_Real cutoffbound;
    2488 int nminactvars;
    2489 int nobjintvars;
    2490 int v;
    2491
    2492 /* this method should not be called in the root node of the search tree since the standard propagation already does
    2493 * the job
    2494 */
    2495 assert(SCIPgetDepth(scip) > 0);
    2496
    2497 propdata = SCIPpropGetData(prop);
    2498 assert(propdata != NULL);
    2499
    2500 pseudoobjval = SCIPgetGlobalPseudoObjval(scip);
    2501 cutoffbound = propdata->cutoffbound;
    2502
    2503 /* nothing can be done if the global pseudo objective is minus infinity */
    2504 if( SCIPisInfinity(scip, -pseudoobjval) )
    2505 return SCIP_OKAY;
    2506
    2507 /* check if the global pseudo objective value (minimum activity of the objective function) is greater or equal to
    2508 * the cutoff bound
    2509 */
    2510 if( SCIPisGE(scip, pseudoobjval, cutoffbound) )
    2511 {
    2512 *cutoff = TRUE;
    2513 return SCIP_OKAY;
    2514 }
    2515
    2516 minactvars = propdata->minactvars;
    2517 objintvars = propdata->objintvars;
    2518 nminactvars = propdata->nminactvars;
    2519 nobjintvars = propdata->nobjintvars;
    2520
    2521#ifndef NDEBUG
    2522 checkGlbfirstnonfixed(propdata);
    2523#endif
    2524
    2525 *cutoff = FALSE;
    2526
    2527 /* always propagate the binary variables completely */
    2528 for( v = propdata->glbfirstnonfixed; v < nminactvars; ++v )
    2529 {
    2530 var = minactvars[v];
    2531 assert(var != NULL);
    2532
    2533 /* check if the variables is already globally fixed; if so continue with the potential candidate */
    2534 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5)
    2535 continue;
    2536
    2537 /* propagates the cutoff bound for the given binary variable */
    2538 SCIP_CALL( propagateCutoffboundBinvar(scip, prop, var, v, cutoffbound, pseudoobjval, &tightened, cutoff, FALSE) );
    2539
    2540 /* the binary variables are sorted in non-increasing manner w.r.t. the absolute value of their objective
    2541 * contribution w.r.t. minimum activity (pseudo objective value) of the objective function; these values are the
    2542 * increase in the pseudo objective activity we would get if we fix the variable to its worse bound; hence, we can
    2543 * stop if for a variable this potential increase is not enough too exceed the cutoff bound;
    2544 */
    2545 if( !tightened )
    2546 {
    2547 SCIPdebugMsg(scip, "interrupt global pseudo objective propagation w.r.t. cutoff bound <%.15g> for binary variables after %d from %d binary variables\n",
    2548 cutoffbound, v, nminactvars);
    2549 break;
    2550 }
    2551
    2552 if( *cutoff )
    2553 return SCIP_OKAY;
    2554
    2555 /* @note The variable might not be globally fixed right away since this would destroy the local internal
    2556 * data structure of a search node; the bound change is in that case pending; hence we cannot assert
    2557 * that the variable is globally fixed
    2558 */
    2559 (*nchgbds)++;
    2560 }
    2561 propdata->glbfirstnonfixed = v;
    2562 propdata->firstnonfixed = MAX(propdata->firstnonfixed, v);
    2563
    2564 /* check all binary variables which could potentially be fixed */
    2565 for( ; v < nminactvars && cutoffbound - pseudoobjval < propdata->minactimpls[v]->maxobjchg; ++v )
    2566 {
    2567 var = minactvars[v];
    2568 assert(var != NULL);
    2569
    2570 /* check if the variables is already globally fixed; if so continue with the potential candidate */
    2571 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5)
    2572 continue;
    2573
    2574 /* propagates the cutoff bound for the given binary variable */
    2575 SCIP_CALL( propagateCutoffboundBinvar(scip, prop, var, v, cutoffbound, pseudoobjval, &tightened, cutoff, FALSE) );
    2576
    2577 /* check if the domain of the variable was reduced */
    2578 if( tightened )
    2579 (*nchgbds)++;
    2580
    2581 if( *cutoff )
    2582 return SCIP_OKAY;
    2583 }
    2584
    2585#ifdef SCIP_DISABLED_CODE
    2586 /* might fail, but is not a real error, still need to investigate */
    2587#ifndef NDEBUG
    2588 /* check that the abort criterion for the binary variables works */
    2589 for( ; v < nminactvars; ++v )
    2590 {
    2591 assert(cutoffbound - pseudoobjval >= propdata->minactimpls[v]->maxobjchg);
    2592
    2593 var = minactvars[v];
    2594 assert(var != NULL);
    2595
    2596 /* check if the variable is already locally fixed; in that case we just continue with the next potential
    2597 * candidate
    2598 */
    2599 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5)
    2600 continue;
    2601
    2602 /* propagates the cutoff bound for the given binary variable */
    2603 SCIP_CALL( propagateCutoffboundBinvar(scip, prop, var, v, cutoffbound, pseudoobjval, &tightened, cutoff, FALSE) );
    2604 assert(!tightened);
    2605 assert(!(*cutoff));
    2606 }
    2607#endif
    2608#endif
    2609
    2610 /* propagate the non-binary variables completely */
    2611 for( v = 0; v < nobjintvars; ++v )
    2612 {
    2613 var = objintvars[v];
    2614 assert(var != NULL);
    2615 assert(!SCIPisZero(scip, SCIPvarGetObj(var)));
    2616
    2617 /* try to tighten the bound of the variable */
    2618 SCIP_CALL( propagateCutoffboundVar(scip, NULL, var, -1, SCIPvarGetObj(var), cutoffbound, pseudoobjval, FALSE, &tightened) );
    2619
    2620 /* check if the domain of the variable was reduced */
    2621 if( tightened )
    2622 (*nchgbds)++;
    2623 }
    2624
    2625 propdata->glbpropagated = TRUE;
    2626
    2627 return SCIP_OKAY;
    2628}
    2629
    2630/** propagates the cutoff bound for binary variables (c*x <= cutoff) */
    2631static
    2633 SCIP* scip, /**< SCIP data structure */
    2634 SCIP_PROP* prop, /**< propagator */
    2635 SCIP_Real cutoffbound, /**< cutoff bound to use */
    2636 SCIP_Real pseudoobjval, /**< pseudo objective value to use */
    2637 int* nfixedvars, /**< pointer to store the number of fixed variables */
    2638 SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */
    2639 )
    2640{
    2641 SCIP_PROPDATA* propdata;
    2642 SCIP_VAR** minactvars;
    2643 SCIP_VAR* var;
    2644 SCIP_Bool tightened;
    2645 int nminactvars;
    2646 int v;
    2647
    2648 propdata = SCIPpropGetData(prop);
    2649 assert(propdata != NULL);
    2650
    2651 minactvars = propdata->minactvars;
    2652 nminactvars = propdata->nminactvars;
    2653 assert(nminactvars == 0 || minactvars != NULL);
    2654
    2655 /* always propagate the binary variables completely; note that the variables before the firstnonfixed indexed are
    2656 * already locally fixed and those before glbfirstnonfixed are already globally fixed
    2657 */
    2658
    2659#ifndef NDEBUG
    2660 /* check that the variables before glbfirstnonfixed are globally fixed */
    2661 checkGlbfirstnonfixed(propdata);
    2662
    2663 /* check that the variables before firstnonfixed are locally fixed */
    2664 for( v = propdata->glbfirstnonfixed; v < propdata->firstnonfixed; ++v )
    2665 {
    2666 var = minactvars[v];
    2667 assert(var != NULL);
    2668
    2669 assert(SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5);
    2670 }
    2671#endif
    2672
    2673 (*cutoff) = FALSE;
    2674
    2675 for( v = propdata->firstnonfixed; v < nminactvars; ++v )
    2676 {
    2677 var = minactvars[v];
    2678 assert(var != NULL);
    2679
    2680 /* check if the variable is already locally fixed; in that case we just continue with the next potential
    2681 * candidate
    2682 */
    2683 if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5)
    2684 continue;
    2685
    2686 /* propagates the cutoff bound for the given binary variable */
    2687 SCIP_CALL( propagateCutoffboundBinvar(scip, prop, var, v, cutoffbound, pseudoobjval, &tightened, cutoff, TRUE) );
    2688
    2689 /* the binary variables are sorted in non-increasing manner w.r.t. the absolute value of their objective
    2690 * contribution w.r.t. minimum activity of the objective function; These values are the increase in the pseudo
    2691 * objective activity (minimum activity of the objective function) we would get if we fix the variable to its
    2692 * worse bound; hence, we can stop if for a variable this potential increase is not enough too exceed the cutoff
    2693 * bound;
    2694 */
    2695 if( !tightened )
    2696 {
    2697 SCIPdebugMsg(scip, "interrupt local pseudo objective propagation w.r.t. cutoff bound <%.15g> for binary variables after %d from %d binary variables\n",
    2698 cutoffbound, v, nminactvars);
    2699 break;
    2700 }
    2701
    2702 if( *cutoff )
    2703 return SCIP_OKAY;
    2704
    2705 /* check that the binary variable is locally fixed */
    2706 assert(SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5);
    2707 (*nfixedvars)++;
    2708 }
    2709 propdata->firstnonfixed = v;
    2710
    2711 /* check all binary variables which could potentially be fixed */
    2712 for( ; v < nminactvars && cutoffbound - pseudoobjval < propdata->minactimpls[v]->maxobjchg; ++v )
    2713 {
    2714 var = minactvars[v];
    2715 assert(var != NULL);
    2716
    2717 /* check if the variable is already locally fixed; in that case we just continue with the next potential
    2718 * candidate
    2719 */
    2720 if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5)
    2721 continue;
    2722
    2723 /* propagates the cutoff bound for the given binary variable */
    2724 SCIP_CALL( propagateCutoffboundBinvar(scip, prop, var, v, cutoffbound, pseudoobjval, &tightened, cutoff, TRUE) );
    2725
    2726 if( tightened )
    2727 {
    2728 assert(SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5);
    2729 (*nfixedvars)++;
    2730 }
    2731
    2732 if( *cutoff )
    2733 return SCIP_OKAY;
    2734 }
    2735
    2736#ifdef SCIP_DISABLED_CODE
    2737 /* might fail, but is not a real error, still need to investigate */
    2738#ifndef NDEBUG
    2739 /* check that the abort criterion for the binary variables works */
    2740 for( ; v < nminactvars; ++v )
    2741 {
    2742 var = minactvars[v];
    2743 assert(var != NULL);
    2744
    2745 assert(cutoffbound - pseudoobjval >= propdata->minactimpls[v]->maxobjchg);
    2746
    2747 /* check if the variable is already locally fixed; in that case we just continue with the next potential
    2748 * candidate
    2749 */
    2750 if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5)
    2751 continue;
    2752
    2753 /* propagates the cutoff bound for the given binary variable */
    2754 SCIP_CALL( propagateCutoffboundBinvar(scip, prop, var, v, cutoffbound, pseudoobjval, &tightened, cutoff, TRUE) );
    2755 assert(!tightened);
    2756 assert(!(*cutoff));
    2757 }
    2758#endif
    2759#endif
    2760
    2761 return SCIP_OKAY;
    2762}
    2763
    2764/** propagates the cutoff bound c*x <= cutoff */
    2765static
    2767 SCIP* scip, /**< SCIP data structure */
    2768 SCIP_PROP* prop, /**< propagator */
    2769 SCIP_RESULT* result /**< pointer to store the result of the callback method */
    2770 )
    2771{
    2772 SCIP_PROPDATA* propdata;
    2773 SCIP_Real pseudoobjval;
    2774 SCIP_Real cutoffbound;
    2775 SCIP_Bool cutoff;
    2776 SCIP_Bool tightened;
    2777 int nchgbds;
    2778
    2779 assert(result != NULL);
    2780
    2781 (*result) = SCIP_DIDNOTRUN;
    2782
    2783 propdata = SCIPpropGetData(prop);
    2784 assert(propdata != NULL);
    2785
    2786 /* get current pseudo objective value (minimum activity of the objective function) and cutoff bound */
    2787 pseudoobjval = SCIPgetPseudoObjval(scip);
    2788 if( SCIPisInfinity(scip, -pseudoobjval) )
    2789 return SCIP_OKAY;
    2790 cutoffbound = SCIPgetCutoffbound(scip);
    2791 if( SCIPisInfinity(scip, cutoffbound) )
    2792 return SCIP_OKAY;
    2793
    2794 /* @note A new global pseudo objective value could be used to retrieve global fixings. There is, however, no need to
    2795 * check if a new global pseudo objective value is available. This is the case since a new (better) global
    2796 * pseudo activity implies that a global bound change was performed. That causes that the root node of the
    2797 * search tree gets marked for repropagation. That will result in a propagation call of the pseudo objective
    2798 * propagator.
    2799 */
    2800
    2801 /* check current cutoff bound */
    2802 if( cutoffbound < propdata->cutoffbound )
    2803 {
    2804 propdata->glbpropagated = FALSE;
    2805 propdata->cutoffbound = cutoffbound;
    2806 }
    2807
    2808 nchgbds = 0;
    2809 cutoff = FALSE;
    2810 (*result) = SCIP_DIDNOTFIND;
    2811
    2812 /* check if we have a new cutoff bound; in that case we globally propagate this new bound
    2813 *
    2814 * @note there is no need to propagate the cutoff bound if we are in the root node since this will be done by the
    2815 * standard local propagation
    2816 */
    2817 if( propdata->propcutoffbound && !propdata->glbpropagated && SCIPgetDepth(scip) > 0 )
    2818 {
    2819 /* first globally propagate new cutoff bound or pseudo objective activity */
    2820 SCIP_CALL( propagateCutoffboundGlobally(scip, prop, &nchgbds, &cutoff) );
    2821
    2822 if( cutoff )
    2823 {
    2824 /* we are done with solving since a global pseudo activity is greater or equal to the cutoff bound */
    2826
    2827 (*result) = SCIP_CUTOFF;
    2828 return SCIP_OKAY;
    2829 }
    2830
    2831 /* check if the global propagation cut off the active/current node */
    2833 {
    2834 (*result) = SCIP_CUTOFF;
    2835 return SCIP_OKAY;
    2836 }
    2837 }
    2838
    2839 /* check if the pseudo objective value (minimum activity of the objective function) is greater or equal to the cutoff
    2840 * bound
    2841 */
    2842 if( SCIPisGE(scip, pseudoobjval, cutoffbound) )
    2843 {
    2844 SCIPdebugMsg(scip, "pseudo objective value <%g> exceeds cutoff bound <%g>\n", pseudoobjval, cutoffbound);
    2845
    2846 /* check if conflict analysis is applicable */
    2848 {
    2849 assert(SCIPgetDepth(scip) > 0);
    2850
    2851 /* initialize conflict analysis */
    2853
    2854 /* add all variable whose best bound changes increased the pseudo objective value above the cutoff bound */
    2855 SCIP_CALL( resolvePropagation(scip, propdata, cutoffbound, NULL, -1, SCIP_BOUNDTYPE_UPPER, NULL) );
    2856
    2857 /* analyze the conflict */
    2859 }
    2860 (*result) = SCIP_CUTOFF;
    2861
    2862 return SCIP_OKAY;
    2863 }
    2864
    2865 SCIPdebugMsg(scip, "propagating pseudo objective function (pseudoobj: %g, cutoffbound: %g)\n", pseudoobjval, cutoffbound);
    2866
    2867 /* propagate binary variables */
    2868 SCIP_CALL( propagateCutoffboundBinvars(scip, prop, cutoffbound, pseudoobjval, &nchgbds, &cutoff) );
    2869
    2870 if( cutoff )
    2871 {
    2872 (*result) = SCIP_CUTOFF;
    2873 return SCIP_OKAY;
    2874 }
    2875
    2876 /* tighten domains of non-binary variables, if they would increase the pseudo objective value above the cutoff
    2877 * bound
    2878 */
    2879 if( propdata->propfullinroot && SCIPgetDepth(scip) == 0 )
    2880 {
    2881 SCIP_VAR** objintvars;
    2882 SCIP_VAR* var;
    2883 SCIP_Real objval;
    2884 int nobjintvars;
    2885 int v;
    2886
    2887 objintvars = propdata->objintvars;
    2888 nobjintvars = propdata->nobjintvars;
    2889 assert(nobjintvars == 0 || objintvars != NULL);
    2890
    2891 /* propagate all non-binary variables */
    2892 for( v = 0; v < nobjintvars; ++v )
    2893 {
    2894 var = objintvars[v];
    2895 assert(var != NULL);
    2896
    2897 objval = SCIPvarGetObj(var);
    2898 assert(!SCIPisZero(scip, objval));
    2899
    2900 /* try to tighten the bound of the variable */
    2901 SCIP_CALL( propagateCutoffboundVar(scip, NULL, var, -1, objval, cutoffbound, pseudoobjval, FALSE, &tightened) );
    2902
    2903 /* check if the domain of the variable was reduced */
    2904 if( tightened )
    2905 nchgbds++;
    2906 }
    2907 }
    2908 else
    2909 {
    2910 SCIP_VAR** objintvars;
    2911 SCIP_VAR* var;
    2912 SCIP_Real objval;
    2913 int nobjintvars;
    2914 int nmaxuseless;
    2915 int nuseless;
    2916 int c;
    2917 int v;
    2918
    2919 objintvars = propdata->objintvars;
    2920 nobjintvars = propdata->nobjintvars;
    2921 assert(nobjintvars == 0 || objintvars != NULL);
    2922
    2923 /* compute maximum number of useless propagations before aborting */
    2924 nmaxuseless = MAX(propdata->minuseless, (int)propdata->maxvarsfrac*(nobjintvars));
    2925
    2926 nuseless = 0;
    2927 v = propdata->lastvarnum;
    2928
    2929 for( c = 0; c < nobjintvars && nuseless < nmaxuseless; ++c )
    2930 {
    2931 v++;
    2932 if( v >= nobjintvars )
    2933 v = 0;
    2934
    2935 var = objintvars[v];
    2936 assert(var != NULL);
    2937
    2938 objval = SCIPvarGetObj(var);
    2939 assert(!SCIPisZero(scip, objval));
    2940
    2941 /* try to tighten the bound of the variable */
    2942 SCIP_CALL( propagateCutoffboundVar(scip, prop, var, -1, objval, cutoffbound, pseudoobjval, TRUE, &tightened) );
    2943
    2944 /* check if the domain of the variable was reduced */
    2945 if( tightened )
    2946 nchgbds++;
    2947 else
    2948 nuseless++;
    2949 }
    2950 propdata->lastvarnum = v;
    2951 }
    2952
    2953 /* check if we chanced bounds */
    2954 if( nchgbds > 0 )
    2955 (*result) = SCIP_REDUCEDDOM;
    2956
    2957 return SCIP_OKAY;
    2958}
    2959
    2960/** recalculates the maximum objective pseudoactivity */
    2961static
    2963 SCIP* scip, /**< SCIP data structure */
    2964 SCIP_PROPDATA* propdata /**< propagator data */
    2965 )
    2966{
    2967 SCIP_VAR** vars;
    2968 SCIP_Real objval;
    2969 SCIP_Real contrib;
    2970 int nvars;
    2971 int v;
    2972
    2973 assert(propdata != NULL);
    2974
    2975 /* get problem variables */
    2976 vars = SCIPgetVars(scip);
    2977 nvars = SCIPgetNVars(scip);
    2978
    2979 /* calculate current max pseudo activity and largest contribution */
    2980 propdata->maxpseudoobjact = 0.0;
    2981 propdata->maxpseudoobjactinf = 0;
    2982
    2983 for( v = 0; v < nvars; ++v )
    2984 {
    2985 objval = SCIPvarGetObj(vars[v]);
    2986 if( SCIPisPositive(scip, objval) )
    2987 {
    2988 contrib = SCIPvarGetUbGlobal(vars[v]);
    2989 if( !SCIPisInfinity(scip, contrib) )
    2990 contrib *= objval;
    2991 }
    2992 else if( SCIPisNegative(scip, objval) )
    2993 {
    2994 contrib = SCIPvarGetLbGlobal(vars[v]);
    2995 if( !SCIPisInfinity(scip, -contrib) )
    2996 contrib *= objval;
    2997 else
    2998 contrib *= -1.0;
    2999 }
    3000 else
    3001 continue;
    3002
    3003 if( SCIPisInfinity(scip, contrib) )
    3004 propdata->maxpseudoobjactinf++;
    3005 else
    3006 propdata->maxpseudoobjact += contrib;
    3007 }
    3008}
    3009
    3010/** updates the pseudo objective activity if necessary */
    3011static
    3013 SCIP* scip, /**< SCIP data structure */
    3014 SCIP_PROPDATA* propdata /**< propagator data */
    3015 )
    3016{
    3017 assert(propdata != NULL);
    3018
    3019 /* if necessary, calculate the maximum pseudo objective activity */
    3020 if( propdata->maxpseudoobjact == SCIP_INVALID ) /*lint !e777*/
    3021 calcMaxObjPseudoactivity(scip, propdata);
    3022 assert(propdata->maxpseudoobjact != SCIP_INVALID); /*lint !e777*/
    3023}
    3024
    3025/** returns the residual pseudo objective activity without the given value */
    3026static
    3028 SCIP* scip, /**< SCIP data structure */
    3029 SCIP_PROPDATA* propdata, /**< propagator data */
    3030 SCIP_Real contrib /**< value to eliminate from pseudo objective activity */
    3031 )
    3032{
    3033 SCIP_Real residual;
    3034
    3035 assert(propdata != NULL);
    3036
    3037 /* if necessary, calculate the maximum pseudo objective activity */
    3038 if( propdata->maxpseudoobjact == SCIP_INVALID ) /*lint !e777*/
    3039 calcMaxObjPseudoactivity(scip, propdata);
    3040 assert(propdata->maxpseudoobjact != SCIP_INVALID); /*lint !e777*/
    3041
    3042 if( SCIPisInfinity(scip, contrib) )
    3043 {
    3044 assert(propdata->maxpseudoobjactinf >= 1);
    3045 /* check if this variable yields the only infinite contribution */
    3046 if( propdata->maxpseudoobjactinf == 1 )
    3047 residual = propdata->maxpseudoobjact;
    3048 else
    3049 residual = SCIPinfinity(scip);
    3050 }
    3051 else
    3052 {
    3053 /* check if there is an infinite contribution */
    3054 if( propdata->maxpseudoobjactinf >= 1 )
    3055 residual = SCIPinfinity(scip);
    3056 else
    3057 residual = propdata->maxpseudoobjact - contrib;
    3058 }
    3059
    3060 return residual;
    3061}
    3062
    3063/** returns the residual pseudo objective activity */
    3064static
    3066 SCIP* scip, /**< SCIP data structure */
    3067 SCIP_PROPDATA* propdata, /**< propagator data */
    3068 SCIP_VAR* var /**< variable to get residual activity for */
    3069 )
    3070{
    3071 SCIP_Real objval;
    3072 SCIP_Real contrib;
    3073
    3074 assert(propdata != NULL);
    3075
    3076 objval = SCIPvarGetObj(var);
    3078 {
    3079 contrib = SCIPvarGetUbGlobal(var);
    3080 if( !SCIPisInfinity(scip, contrib) )
    3081 contrib *= objval;
    3082 }
    3083 else
    3084 {
    3086 contrib = SCIPvarGetLbGlobal(var);
    3087 if( !SCIPisInfinity(scip, -contrib) )
    3088 contrib *= objval;
    3089 else
    3090 contrib *= -1.0;
    3091 }
    3092
    3093 return getMaxObjPseudoactivityResidualValue(scip, propdata, contrib);
    3094}
    3095
    3096/** returns the maximum pseudo objective activity of the objective function */
    3097static
    3099 SCIP* scip, /**< SCIP data structure */
    3100 SCIP_PROPDATA* propdata /**< propagator data */
    3101 )
    3102{
    3103 return getMaxObjPseudoactivityResidualValue(scip, propdata, 0.0);
    3104}
    3105
    3106/** propagates the global domain of the given binary variable against the lower bound (c*x >= lowerbound) */
    3107static
    3109 SCIP* scip, /**< SCIP data structure */
    3110 SCIP_VAR* var, /**< variable to propagate */
    3111 SCIP_Real lowerbound, /**< lower bound to use */
    3112 SCIP_Real maxpseudoobjact, /**< maximum pseudo objective activity */
    3113 SCIP_Bool useimplics, /**< should implications be used */
    3114 SCIP_Bool* infeasible, /**< pointer to store if the variable domain got empty, infeasible */
    3115 SCIP_Bool* tightened /**< pointer to store if the variable domain was tightened */
    3116 )
    3117{
    3118 SCIP_Real lbobjchg;
    3119 SCIP_Real ubobjchg;
    3120
    3121 assert(SCIPvarIsBinary(var));
    3122 assert(SCIPisDualfeasLE(scip, lowerbound, maxpseudoobjact));
    3123 assert(!SCIPisInfinity(scip, maxpseudoobjact));
    3124
    3125 /*@todo Instead of running always over all implications use SCIP_OBJIMPLICS in the same way as for the propagation of
    3126 * the minimum activity against the cutoff bound. If so we could use the cliques as well.
    3127 */
    3128
    3129 /* get contribution of variable by fixing it to its lower bound w.r.t. maximum activity of the objective function */
    3130 SCIP_CALL( getMaxactObjchg(scip, var, SCIP_BOUNDTYPE_LOWER, useimplics, &lbobjchg) );
    3131 assert(!SCIPisPositive(scip, lbobjchg));
    3132
    3133 /* get contribution of variable by fixing it to its upper bound w.r.t. maximum activity of the objective function */
    3134 SCIP_CALL( getMaxactObjchg(scip, var, SCIP_BOUNDTYPE_UPPER, useimplics, &ubobjchg) );
    3135 assert(!SCIPisPositive(scip, ubobjchg));
    3136
    3137 (*infeasible) = FALSE;
    3138 (*tightened) = FALSE;
    3139
    3140 /* if the maximum activity of the objective function without the contribution of the given variable shrinks below the
    3141 * global lower bound, the contribution of the variable is need; hence, we can fix it to corresponding bound globally
    3142 */
    3143 if( SCIPisFeasLT(scip, maxpseudoobjact + lbobjchg, lowerbound) && SCIPisFeasLT(scip, maxpseudoobjact + ubobjchg, lowerbound) )
    3144 {
    3145 /* fixing the variable to zero or one leads to decreases of the maximum activity below the lower bound, hence, we
    3146 * detected an cutoff
    3147 */
    3148 (*infeasible) = TRUE;
    3149 }
    3150 else if( SCIPisFeasLT(scip, maxpseudoobjact + lbobjchg, lowerbound) )
    3151 {
    3152 SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, 1.0, FALSE, infeasible, tightened) );
    3153 }
    3154 else if( SCIPisFeasLT(scip, maxpseudoobjact + ubobjchg, lowerbound) )
    3155 {
    3156 SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, 0.0, FALSE, infeasible, tightened) );
    3157 }
    3158
    3159 return SCIP_OKAY;
    3160}
    3161
    3162/** propagates the global domains of the given variable with non-zero objective coefficient against the lower bound
    3163 * (c*x >= lowerbound)
    3164 */
    3165static
    3167 SCIP* scip, /**< SCIP data structure */
    3168 SCIP_PROPDATA* propdata, /**< propagator data */
    3169 SCIP_VAR* var, /**< variable to propagate */
    3170 SCIP_Real lowerbound, /**< lower bound to use */
    3171 SCIP_Bool* infeasible, /**< pointer to store if the variable domain got empty, infeasible */
    3172 SCIP_Bool* tightened /**< pointer to store if the variable domain was tightened */
    3173 )
    3174{
    3175 SCIP_Real residual;
    3176 SCIP_Real newbd;
    3177 SCIP_Real objval;
    3178
    3179 objval = SCIPvarGetObj(var);
    3180 assert(!SCIPisZero(scip, objval));
    3181
    3182 (*tightened) = FALSE;
    3183
    3184 /* get residual pseudo objective activity, that is the pseudo objective activity without the given variable */
    3185 residual = getMaxObjPseudoactivityResidual(scip, propdata, var);
    3186
    3187 if( SCIPisInfinity(scip, residual) )
    3188 return SCIP_OKAY;
    3189
    3190 /* compute potential mew bound */
    3191 newbd = (lowerbound - residual) / objval;
    3192
    3193 /**@note In case the variable is integral we force the update of the new bound */
    3194
    3195 if( objval > 0.0 )
    3196 {
    3197 SCIP_Real lb;
    3198
    3199 lb = SCIPvarGetLbGlobal(var);
    3200
    3201 if( !SCIPvarIsIntegral(var) )
    3202 {
    3203 SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, newbd, FALSE, infeasible, tightened) );
    3204 }
    3205 else if( SCIPisFeasGT(scip, newbd, lb) )
    3206 {
    3207 SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, newbd, TRUE, infeasible, tightened) );
    3208 }
    3209 }
    3210 else
    3211 {
    3212 SCIP_Real ub;
    3213
    3214 ub = SCIPvarGetUbGlobal(var);
    3215
    3216 if( !SCIPvarIsIntegral(var) )
    3217 {
    3218 SCIP_CALL( SCIPtightenVarUbGlobal(scip, var, newbd, FALSE, infeasible, tightened) );
    3219 }
    3220 else if( SCIPisFeasLT(scip, newbd, ub) )
    3221 {
    3222 SCIP_CALL( SCIPtightenVarUbGlobal(scip, var, newbd, TRUE, infeasible, tightened) );
    3223 }
    3224 }
    3225
    3226 return SCIP_OKAY;
    3227}
    3228
    3229/** propagates the global lower (dual) bound c*x >= lowerbound */
    3230static
    3232 SCIP* scip, /**< SCIP data structure */
    3233 SCIP_PROP* prop, /**< propagator */
    3234 SCIP_RESULT* result /**< pointer to store the result of the callback method */
    3235 )
    3236{ /*lint --e{715}*/
    3237 SCIP_PROPDATA* propdata;
    3238 SCIP_Real lowerbound;
    3239 SCIP_Real maxpseudoobjact;
    3240 SCIP_Bool cutoff;
    3241 int nchgbds;
    3242
    3243 assert(result != NULL);
    3244
    3245 (*result) = SCIP_DIDNOTRUN;
    3246 cutoff = FALSE;
    3247 nchgbds = 0;
    3248
    3249 propdata = SCIPpropGetData(prop);
    3250 assert(propdata != NULL);
    3251 assert(propdata->nminactvars > 0 || propdata->nobjintvars > 0);
    3252
    3253 /* check if there is a chance to find a reduction */
    3254 lowerbound = SCIPgetLowerbound(scip);
    3255
    3256 if( SCIPisInfinity(scip, -lowerbound) )
    3257 return SCIP_OKAY;
    3258
    3259 /* if the lower bound did not change since the last propagation as well as the global bounds of the variables with a
    3260 * non-zero objective coefficient we do nothing since there is no new information available
    3261 */
    3262 if( SCIPisLE(scip, lowerbound, propdata->lastlowerbound) && propdata->maxpseudoobjact < SCIP_INVALID )
    3263 return SCIP_OKAY;
    3264
    3265 /* updates the pseudo objective activity if necessary */
    3267
    3268 /* if more than one variable contributes an infinity to the maximal pseudo activity we can do nothing */
    3269 assert(propdata->maxpseudoobjact < SCIP_INVALID);
    3270 if( propdata->maxpseudoobjactinf > 1 )
    3271 return SCIP_OKAY;
    3272
    3273 maxpseudoobjact = getMaxObjPseudoactivity(scip, propdata);
    3274 assert(!SCIPisInfinity(scip, maxpseudoobjact) || !SCIPisInfinity(scip, lowerbound));
    3275
    3276#ifndef NDEBUG
    3277 /* check that the global indices are correct */
    3278 checkGlbfirstnonfixed(propdata);
    3279#endif
    3280
    3281 /* if the maximum pseudo objective activity is smaller than the lower bound the problem is infeasible */
    3282 if( SCIPisDualfeasLT(scip, maxpseudoobjact, lowerbound) )
    3283 cutoff = TRUE;
    3284 else
    3285 {
    3286 SCIP_VAR** objintvars;
    3287 SCIP_VAR* var;
    3288 SCIP_Bool tightened;
    3289 int nobjintvars;
    3290 int v;
    3291
    3292 if( propdata->maxpseudoobjactinf == 0 && !SCIPisInfinity(scip, maxpseudoobjact) )
    3293 {
    3294 SCIP_VAR** maxactvars;
    3295 int nmaxactvars;
    3296
    3297 maxactvars = propdata->maxactvars;
    3298 nmaxactvars = propdata->nmaxactvars;
    3299 assert(nmaxactvars == 0 || maxactvars != NULL);
    3300
    3301 for( v = propdata->maxactfirstnonfixed; v < nmaxactvars; ++v )
    3302 {
    3303 var = maxactvars[v];
    3304 assert(var != NULL);
    3305 assert(SCIPvarIsBinary(var));
    3306
    3307 /* check if the variables is already globally fixed; if so continue with the next potential candidate */
    3308 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5)
    3309 continue;
    3310
    3311 /* try to propagate variable domain globally */
    3312 SCIP_CALL( propagateLowerboundBinvar(scip, var, lowerbound, maxpseudoobjact, propdata->propuseimplics, &cutoff, &tightened) );
    3313
    3314 /* the binary variables are sorted in non-increasing manner w.r.t. the absolute value of their objective
    3315 * contribution w.r.t. maximum activity of the objective function; These values are the decrease we would
    3316 * get with the maximum pseudo objective activity if we fix the variable to its best bound; hence, we can
    3317 * stop if for a variable this potential decrease is not enough anymore to fall below the lower bound.
    3318 *
    3319 * @note In case a fixing was performed. The variable might not be globally fixed right away since this would
    3320 * destroy the local internal data structure of a search node; the bound change is in that case pending;
    3321 * hence we cannot assert that the variable is globally fixed
    3322 */
    3323 if( !tightened )
    3324 {
    3325 assert(!SCIPisInfinity(scip, propdata->maxpseudoobjact));
    3326 SCIPdebugMsg(scip, "interrupt pseudo objective propagation w.r.t. lower bound <%.15g> for binary variables after %d from %d binary variables\n",
    3327 lowerbound, v, nmaxactvars);
    3328 break;
    3329 }
    3330
    3331 if( cutoff )
    3332 break;
    3333
    3334 /* update maximum pseudo activity since the previous global bound change might invalidated the maximum
    3335 * pseudo activity
    3336 */
    3337 maxpseudoobjact = getMaxObjPseudoactivity(scip, propdata);
    3338 nchgbds++;
    3339 }
    3340
    3341 /* update globally fixed index if abort criterion was applied */
    3342 propdata->maxactfirstnonfixed = v;
    3343
    3344 /* check all binary variables which could potentially be fixed */
    3345 for( ; v < nmaxactvars && maxpseudoobjact - lowerbound < propdata->maxactchgs[v] && !cutoff; ++v )
    3346 {
    3347 var = maxactvars[v];
    3348 assert(var != NULL);
    3349 assert(SCIPvarIsBinary(var));
    3350
    3351 /* check if the variables is already globally fixed; if so continue with the potential candidate */
    3352 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5)
    3353 continue;
    3354
    3355 /* propagates the cutoff bound for the given binary variable */
    3356 SCIP_CALL( propagateLowerboundBinvar(scip, var, lowerbound, maxpseudoobjact, propdata->propuseimplics, &cutoff, &tightened) );
    3357
    3358 if( tightened )
    3359 {
    3360 /* update maximum pseudo activity since the previous global bound change might invalidated the maximum
    3361 * pseudo activity
    3362 */
    3363 maxpseudoobjact = getMaxObjPseudoactivity(scip, propdata);
    3364 nchgbds++;
    3365 }
    3366 }
    3367
    3368#ifdef SCIP_DISABLED_CODE
    3369 /* might fail, but is not a real error, still need to investigate */
    3370#ifndef NDEBUG
    3371 /* check that the abort criterion for the binary variables works */
    3372 for( ; v < nmaxactvars && !cutoff; ++v )
    3373 {
    3374 var = maxactvars[v];
    3375 assert(var != NULL);
    3376 assert(SCIPvarIsBinary(var));
    3377
    3378 /* check if the variables is already globally fixed; if so continue with the next potential candidate */
    3379 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5)
    3380 continue;
    3381
    3382 /* try to propagate variable domain globally */
    3383 SCIP_CALL( propagateLowerboundBinvar(scip, var, lowerbound, maxpseudoobjact, propdata->propuseimplics, &cutoff, &tightened) );
    3384 assert(!tightened);
    3385 assert(!cutoff);
    3386 }
    3387#endif
    3388#endif
    3389 }
    3390
    3391 objintvars = propdata->objintvars;
    3392 nobjintvars = propdata->nobjintvars;
    3393 assert(nobjintvars == 0 || objintvars != NULL);
    3394
    3395 /* propagate c*x >= lowerbound for non-binary variables */
    3396 for( v = 0; v < nobjintvars && !cutoff; ++v )
    3397 {
    3398 var = objintvars[v];
    3399 assert(var != NULL);
    3400 assert(!SCIPisZero(scip, SCIPvarGetObj(var)));
    3401
    3402 /* try to propagate variable domain globally */
    3403 SCIP_CALL( propagateLowerboundVar(scip, propdata, var, lowerbound, &cutoff, &tightened) );
    3404
    3405 if( tightened )
    3406 nchgbds++;
    3407 }
    3408 }
    3409
    3410 /* evaluate propagation results */
    3411 if( cutoff )
    3412 {
    3413 /* we are done with solving since a global bound change is infeasible: cutoff root node */
    3415 (*result) = SCIP_CUTOFF;
    3416 }
    3417 else if( nchgbds > 0 )
    3418 (*result) = SCIP_REDUCEDDOM;
    3419
    3420 /* remember the lower bound which we already propagated */
    3421 propdata->lastlowerbound = lowerbound;
    3422
    3423 return SCIP_OKAY;
    3424}
    3425
    3426
    3427/*
    3428 * Callback methods of propagator
    3429 */
    3430
    3431/** copy method for propagator plugins (called when SCIP copies plugins) */
    3432static
    3433SCIP_DECL_PROPCOPY(propCopyPseudoobj)
    3434{ /*lint --e{715}*/
    3435 assert(scip != NULL);
    3436 assert(prop != NULL);
    3437 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
    3438
    3439 /* call inclusion method of propagator */
    3441
    3442 return SCIP_OKAY;
    3443}
    3444
    3445/** destructor of propagator to free user data (called when SCIP is exiting) */
    3446static
    3447SCIP_DECL_PROPFREE(propFreePseudoobj)
    3448{ /*lint --e{715}*/
    3449 SCIP_PROPDATA* propdata;
    3450
    3451 /* free propagator data */
    3452 propdata = SCIPpropGetData(prop);
    3453 SCIPfreeBlockMemory(scip, &propdata);
    3454 SCIPpropSetData(prop, NULL);
    3455
    3456 return SCIP_OKAY;
    3457}
    3458
    3459
    3460/** solving process initialization method of propagator (called when branch and bound process is about to begin) */
    3461static
    3462SCIP_DECL_PROPINITSOL(propInitsolPseudoobj)
    3463{
    3464 SCIP_PROPDATA* propdata;
    3465
    3466 propdata = SCIPpropGetData(prop);
    3467 assert(propdata != NULL);
    3468
    3469 /* do nothing if active pricer are present and force flag is not TRUE */
    3470 if( !propdata->force && SCIPgetNActivePricers(scip) > 0 )
    3471 return SCIP_OKAY;
    3472
    3473 /* if active pricer are present we want to catch the variable added event */
    3474 if( SCIPgetNActivePricers(scip) > 0 )
    3475 {
    3476 assert(!propdata->catchvaradded);
    3477 SCIP_CALL( SCIPcatchEvent(scip, SCIP_EVENTTYPE_VARADDED, propdata->eventhdlr, (SCIP_EVENTDATA*)propdata, NULL) );
    3478 propdata->catchvaradded = TRUE;
    3479 }
    3480
    3481 return SCIP_OKAY;
    3482}
    3483
    3484/** solving process deinitialization method of propagator (called before branch and bound process data is freed) */
    3485static
    3486SCIP_DECL_PROPEXITSOL(propExitsolPseudoobj)
    3487{ /*lint --e{715}*/
    3488 SCIP_PROPDATA* propdata;
    3489
    3490 propdata = SCIPpropGetData(prop);
    3491 assert(propdata != NULL);
    3492
    3493 if( propdata->catchvaradded )
    3494 {
    3495 /* drop the variable added event */
    3496 SCIP_CALL( SCIPdropEvent(scip, SCIP_EVENTTYPE_VARADDED, propdata->eventhdlr, (SCIP_EVENTDATA*)propdata, -1) );
    3497 propdata->catchvaradded = FALSE;
    3498 }
    3499
    3500 /* free propagator data */
    3501 SCIP_CALL( propdataExit(scip, propdata) );
    3502
    3503 return SCIP_OKAY;
    3504}
    3505
    3506
    3507/** presolving method of propagator */
    3508static
    3509SCIP_DECL_PROPPRESOL(propPresolPseudoobj)
    3510{ /*lint --e{715}*/
    3511 SCIP_PROPDATA* propdata;
    3512 SCIP_VAR** vars;
    3513 SCIP_Real cutoffbound;
    3514 SCIP_Real pseudoobjval;
    3515 int oldnchgbds;
    3516 int nvars;
    3517 int v;
    3518
    3519 assert(result != NULL);
    3520
    3521 propdata = SCIPpropGetData(prop);
    3522 assert(propdata != NULL);
    3523
    3524 (*result) = SCIP_DIDNOTRUN;
    3525
    3526 /* do nothing if active pricer are present and force flag is not TRUE */
    3527 if( !propdata->force && SCIPgetNActivePricers(scip) > 0 )
    3528 return SCIP_OKAY;
    3529
    3530 /* do nothing if objective propagation is not allowed */
    3532 return SCIP_OKAY;
    3533
    3534 pseudoobjval = SCIPgetGlobalPseudoObjval(scip);
    3535 if( SCIPisInfinity(scip, -pseudoobjval) )
    3536 return SCIP_OKAY;
    3537
    3538 cutoffbound = SCIPgetCutoffbound(scip);
    3539 if( SCIPisInfinity(scip, cutoffbound) )
    3540 return SCIP_OKAY;
    3541
    3542 if( SCIPisGE(scip, pseudoobjval, cutoffbound) )
    3543 {
    3544 (*result) = SCIP_CUTOFF;
    3545 return SCIP_OKAY;
    3546 }
    3547
    3548 /* only propagate if a new cutoff bound or global pseudo objective value is available */
    3549 if( cutoffbound < propdata->cutoffbound || pseudoobjval > propdata->glbpseudoobjval )
    3550 {
    3551 SCIP_Real objval;
    3552 SCIP_Bool tightened;
    3553
    3554 (*result) = SCIP_DIDNOTFIND;
    3555 oldnchgbds = *nchgbds;
    3556
    3557 /* get the problem variables */
    3558 vars = SCIPgetVars(scip);
    3559 nvars = SCIPgetNVars(scip);
    3560
    3561 /* scan the variables for pseudoobj bound reductions
    3562 * (loop backwards, since a variable fixing can change the current and the subsequent slots in the vars array)
    3563 */
    3564 for( v = nvars - 1; v >= 0; --v )
    3565 {
    3566 objval = SCIPvarGetObj(vars[v]);
    3567
    3568 if( SCIPisZero(scip, objval) )
    3569 continue;
    3570
    3571 SCIP_CALL( propagateCutoffboundVar(scip, NULL, vars[v], -1, objval, cutoffbound, pseudoobjval, FALSE, &tightened) );
    3572
    3573 if( tightened )
    3574 (*nchgbds)++;
    3575 }
    3576
    3577 /* evaluate if bound change was detected */
    3578 if( *nchgbds > oldnchgbds )
    3579 (*result) = SCIP_SUCCESS;
    3580
    3581 /* store the old values */
    3582 propdata->cutoffbound = cutoffbound;
    3583 propdata->glbpseudoobjval = pseudoobjval;
    3584 propdata->glbpropagated = TRUE;
    3585 }
    3586
    3587 return SCIP_OKAY;
    3588}
    3589
    3590/** execution method of propagator */
    3591static
    3592SCIP_DECL_PROPEXEC(propExecPseudoobj)
    3593{ /*lint --e{715}*/
    3594 SCIP_PROPDATA* propdata;
    3595
    3596 propdata = SCIPpropGetData(prop);
    3597 assert(propdata != NULL);
    3598
    3599 (*result) = SCIP_DIDNOTRUN;
    3600
    3601 if( SCIPinProbing(scip) )
    3602 return SCIP_OKAY;
    3603
    3604 if( proptiming == SCIP_PROPTIMING_DURINGLPLOOP && SCIPgetDepth(scip) != 0 )
    3605 return SCIP_OKAY;
    3606
    3607 /* do nothing if active pricer are present and force flag is not TRUE */
    3608 if( !propdata->force && SCIPgetNActivePricers(scip) > 0 )
    3609 return SCIP_OKAY;
    3610
    3611 /* do not run if propagation w.r.t. objective is not allowed */
    3613 return SCIP_OKAY;
    3614
    3615 /* check if enough new variable are added (due to column generation to reinitialized the propagator data) */
    3616 if( !propdata->initialized || propdata->nnewvars > propdata->maxnewvars )
    3617 {
    3618 /* free current propdata data */
    3619 SCIP_CALL( propdataExit(scip, propdata) );
    3620
    3621 /* initialize propdata data from scratch */
    3622 SCIP_CALL( propdataInit(scip, propdata) );
    3623 }
    3624
    3625 /* nothing to do for zero objective */
    3626 if( propdata->nminactvars == 0 && propdata->nmaxactvars == 0 && propdata->nobjintvars == 0 )
    3627 return SCIP_OKAY;
    3628
    3629 /* propagate c*x <= cutoff */
    3630 SCIP_CALL( propagateCutoffbound(scip, prop, result) );
    3631
    3632 if( (*result) != SCIP_CUTOFF && (propdata->nmaxactvars > 0 || propdata->nobjintvars > 0) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
    3633 {
    3634 SCIP_RESULT dualresult;
    3635
    3636 /* propagates the global lower (dual) bound c*x >= lowerbound */
    3637 SCIP_CALL( propagateLowerbound(scip, prop, &dualresult) );
    3638
    3639 if( dualresult == SCIP_REDUCEDDOM || dualresult == SCIP_CUTOFF )
    3640 (*result) = dualresult;
    3641 }
    3642
    3643 return SCIP_OKAY;
    3644}
    3645
    3646/** propagation conflict resolving method of propagator */
    3647static
    3648SCIP_DECL_PROPRESPROP(propRespropPseudoobj)
    3649{ /*lint --e{715}*/
    3650 SCIP_PROPDATA* propdata;
    3651 SCIP_Real cutoffbound;
    3652
    3653 assert(!SCIPisEQ(scip, SCIPvarGetLbGlobal(infervar), SCIPvarGetUbGlobal(infervar)));
    3654
    3655 propdata = SCIPpropGetData(prop);
    3656 assert(propdata != NULL);
    3657
    3658 cutoffbound = SCIPgetCutoffbound(scip);
    3659 assert(!SCIPisInfinity(scip, cutoffbound));
    3660 assert(infervar != NULL);
    3661
    3662 SCIPdebugMsg(scip, "resolve bound change <%s> %s <%g>(%g), cutoff bound <%g>\n", SCIPvarGetName(infervar),
    3663 boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE),
    3664 SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, FALSE), cutoffbound);
    3665
    3666 /* resolve the propagation of the inference variable w.r.t. required minactivity */
    3667 SCIP_CALL( resolvePropagation(scip, propdata, cutoffbound, infervar, inferinfo, boundtype, bdchgidx) );
    3668
    3669 (*result) = SCIP_SUCCESS;
    3670
    3671 return SCIP_OKAY;
    3672}
    3673
    3674
    3675/*
    3676 * Event handler
    3677 */
    3678
    3679/** execution method of bound change event handler */
    3680static
    3681SCIP_DECL_EVENTEXEC(eventExecPseudoobj)
    3682{ /*lint --e{715}*/
    3683 SCIP_PROPDATA* propdata;
    3684 SCIP_EVENTTYPE eventtype;
    3685
    3686 propdata = (SCIP_PROPDATA*)eventdata;
    3687 assert(propdata != NULL);
    3688
    3689 assert(eventhdlr != NULL);
    3690 assert(eventdata != NULL);
    3691 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
    3692 assert(event != NULL);
    3693
    3694 eventtype = SCIPeventGetType(event);
    3695
    3696 switch( eventtype )
    3697 {
    3700 /* if bound got relaxed we need to start up front for trial of bound tightening */
    3701 propdata->firstnonfixed = 0;
    3702 break;
    3704 propdata->nnewvars++;
    3705 break;
    3706 default:
    3707 assert(eventtype == SCIP_EVENTTYPE_GLBCHANGED || eventtype == SCIP_EVENTTYPE_GUBCHANGED);
    3708
    3709 /* invalidate the maximum pseudo objective activity */
    3710 propdata->maxpseudoobjact = SCIP_INVALID;
    3711 propdata->maxpseudoobjactinf = 0;
    3712 }
    3713
    3714 return SCIP_OKAY;
    3715}
    3716
    3717
    3718/*
    3719 * propagator specific interface methods
    3720 */
    3721
    3722/** creates the pseudo objective function propagator and includes it in SCIP */
    3724 SCIP* scip /**< SCIP data structure */
    3725 )
    3726{
    3727 SCIP_PROPDATA* propdata;
    3728 SCIP_PROP* prop;
    3729
    3730 /* create pseudoobj propagator data */
    3731 SCIP_CALL( SCIPallocBlockMemory(scip, &propdata) );
    3732
    3733 /* reset propagator data structure */
    3734 propdataReset(propdata);
    3735
    3736 propdata->eventhdlr = NULL;
    3737 /* include event handler for gloabl bound change events and variable added event (in case of pricing) */
    3739 eventExecPseudoobj, NULL) );
    3740
    3741 if( propdata->eventhdlr == NULL )
    3742 {
    3743 SCIPerrorMessage("event handler for pseudo objective propagator not found\n");
    3744 return SCIP_PLUGINNOTFOUND;
    3745 }
    3746
    3747 /* include propagator */
    3749 propExecPseudoobj,
    3750 propdata) );
    3751 assert(prop != NULL);
    3752
    3753 /* set optional callbacks via setter functions */
    3754 SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopyPseudoobj) );
    3755 SCIP_CALL( SCIPsetPropFree(scip, prop, propFreePseudoobj) );
    3756 SCIP_CALL( SCIPsetPropInitsol(scip, prop, propInitsolPseudoobj) );
    3757 SCIP_CALL( SCIPsetPropExitsol(scip, prop, propExitsolPseudoobj) );
    3759 SCIP_CALL( SCIPsetPropResprop(scip, prop, propRespropPseudoobj) );
    3760
    3761 /* add pseudoobj propagator parameters */
    3763 "propagating/" PROP_NAME "/minuseless",
    3764 "minimal number of successive non-binary variable propagations without a bound reduction before aborted",
    3765 &propdata->minuseless, TRUE, DEFAULT_MINUSELESS, 0, INT_MAX, NULL, NULL) );
    3766
    3768 "propagating/" PROP_NAME "/maxvarsfrac",
    3769 "maximal fraction of non-binary variables with non-zero objective without a bound reduction before aborted",
    3770 &propdata->maxvarsfrac, TRUE, DEFAULT_MAXVARSFRAC, 0.0, 1.0, NULL, NULL) );
    3771
    3773 "propagating/" PROP_NAME "/propfullinroot",
    3774 "whether to propagate all non-binary variables when we are propagating the root node",
    3775 &propdata->propfullinroot, TRUE, DEFAULT_PROPFULLINROOT, NULL, NULL) );
    3776
    3778 "propagating/" PROP_NAME "/propcutoffbound",
    3779 "propagate new cutoff bound directly globally",
    3780 &propdata->propcutoffbound, TRUE, DEFAULT_PROPCUTOFFBOUND, NULL, NULL) );
    3781
    3783 "propagating/" PROP_NAME "/force",
    3784 "should the propagator be forced even if active pricer are present?",
    3785 &propdata->force, TRUE, DEFAULT_FORCE, NULL, NULL) );
    3786
    3788 "propagating/" PROP_NAME "/maxnewvars",
    3789 "number of variables added after the propagator is reinitialized?",
    3790 &propdata->maxnewvars, TRUE, DEFAULT_MAXNEWVARS, 0, INT_MAX, NULL, NULL) );
    3791
    3793 "propagating/" PROP_NAME "/propuseimplics",
    3794 "use implications to strengthen the propagation of binary variable (increasing the objective change)?",
    3795 &propdata->propuseimplics, TRUE, DEFAULT_PROPUSEIMPLICS, NULL, NULL) );
    3796
    3798 "propagating/" PROP_NAME "/respropuseimplics",
    3799 "use implications to strengthen the resolve propagation of binary variable (increasing the objective change)?",
    3800 &propdata->respropuseimplics, TRUE, DEFAULT_RESPROPUSEIMPLICS, NULL, NULL) );
    3801
    3803 "propagating/" PROP_NAME "/maximplvars",
    3804 "maximum number of binary variables the implications are used if turned on (-1: unlimited)?",
    3805 &propdata->maximplvars, TRUE, DEFAULT_MAXIMPLVARS, -1, INT_MAX, NULL, NULL) );
    3806
    3807 return SCIP_OKAY;
    3808}
    3809
    3810/** propagates the cutoff bound for the given variables */
    3812 SCIP* scip, /**< SCIP data structure */
    3813 SCIP_PROP* prop, /**< propagator, or NULL */
    3814 SCIP_VAR* var, /**< variables to propagate */
    3815 SCIP_Real cutoffbound, /**< cutoff bound to use */
    3816 SCIP_Real pseudoobjval, /**< pseudo objective value to use */
    3817 SCIP_Bool* tightened /**< pointer to if the domain was tightened */
    3818 )
    3819{
    3820 SCIP_Real objval;
    3821
    3822 objval = SCIPvarGetObj(var);
    3823
    3824 SCIP_CALL( propagateCutoffboundVar(scip, prop, var, -1, objval, cutoffbound, pseudoobjval, TRUE, tightened) );
    3825
    3826 return SCIP_OKAY;
    3827}
    static long bound
    defines macros for basic operations in double-double arithmetic giving roughly twice the precision of...
    #define SCIPquadprecDivQD(r, a, b)
    Definition: dbldblarith.h:65
    #define SCIPquadprecSumQD(r, a, b)
    Definition: dbldblarith.h:62
    #define QUAD(x)
    Definition: dbldblarith.h:47
    #define SCIPquadprecSumDD(r, a, b)
    Definition: dbldblarith.h:60
    #define QUAD_TO_DBL(x)
    Definition: dbldblarith.h:49
    #define NULL
    Definition: def.h:248
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define ABS(x)
    Definition: def.h:216
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_CALL(x)
    Definition: def.h:355
    #define infinity
    Definition: gastrans.c:80
    SCIP_Bool SCIPisTransformed(SCIP *scip)
    Definition: scip_general.c:647
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    int SCIPgetNObjVars(SCIP *scip)
    Definition: scip_prob.c:2616
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3304
    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
    SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
    Definition: misc.c:3179
    void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
    Definition: misc.c:2348
    SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2647
    SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
    Definition: misc.c:2298
    void SCIPhashtableRemoveAll(SCIP_HASHTABLE *hashtable)
    Definition: misc.c:2743
    SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2535
    #define SCIPdebugMsgPrint
    Definition: scip_message.h:79
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPpropagateCutoffboundVar(SCIP *scip, SCIP_PROP *prop, SCIP_VAR *var, SCIP_Real cutoffbound, SCIP_Real pseudoobjval, SCIP_Bool *tightened)
    SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE SCIPincludePropPseudoobj(SCIP *scip)
    SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
    SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
    SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
    SCIP_RETCODE SCIPanalyzeConflict(SCIP *scip, int validdepth, SCIP_Bool *success)
    SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
    SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: scip_event.c:111
    const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:396
    SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
    Definition: event.c:1194
    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_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
    Definition: scip_event.c:293
    SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
    Definition: scip_event.c:333
    SCIP_Real SCIPgetPseudoObjval(SCIP *scip)
    Definition: scip_lp.c:339
    SCIP_Real SCIPgetGlobalPseudoObjval(SCIP *scip)
    Definition: scip_lp.c:314
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    #define SCIPallocClearBufferArray(scip, ptr, num)
    Definition: scip_mem.h:126
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
    Definition: scip_mem.h:111
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    int SCIPgetNActivePricers(SCIP *scip)
    Definition: scip_pricer.c:348
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    void SCIPpropSetData(SCIP_PROP *prop, SCIP_PROPDATA *propdata)
    Definition: prop.c:801
    SCIP_RETCODE SCIPsetPropInitsol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPINITSOL((*propinitsol)))
    Definition: scip_prop.c:219
    SCIP_RETCODE SCIPsetPropResprop(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPRESPROP((*propresprop)))
    Definition: scip_prop.c:316
    SCIP_PROPDATA * SCIPpropGetData(SCIP_PROP *prop)
    Definition: prop.c:791
    SCIP_RETCODE SCIPsetPropPresol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPPRESOL((*proppresol)), int presolpriority, int presolmaxrounds, SCIP_PRESOLTIMING presoltiming)
    Definition: scip_prop.c:283
    const char * SCIPpropGetName(SCIP_PROP *prop)
    Definition: prop.c:951
    SCIP_RETCODE SCIPsetPropFree(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPFREE((*propfree)))
    Definition: scip_prop.c:171
    SCIP_RETCODE SCIPsetPropCopy(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPCOPY((*propcopy)))
    Definition: scip_prop.c:155
    SCIP_RETCODE SCIPsetPropExitsol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPEXITSOL((*propexitsol)))
    Definition: scip_prop.c:235
    SCIP_RETCODE SCIPincludePropBasic(SCIP *scip, SCIP_PROP **propptr, const char *name, const char *desc, int priority, int freq, SCIP_Bool delay, SCIP_PROPTIMING timingmask, SCIP_DECL_PROPEXEC((*propexec)), SCIP_PROPDATA *propdata)
    Definition: scip_prop.c:118
    SCIP_Real SCIPgetLowerbound(SCIP *scip)
    SCIP_Real SCIPgetCutoffbound(SCIP *scip)
    SCIP_Bool SCIPisRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisDualfeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPfeastol(SCIP *scip)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisDualfeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    int SCIPgetCutoffdepth(SCIP *scip)
    Definition: scip_tree.c:498
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_RETCODE SCIPcutoffNode(SCIP *scip, SCIP_NODE *node)
    Definition: scip_tree.c:436
    SCIP_NODE * SCIPgetRootNode(SCIP *scip)
    Definition: scip_tree.c:110
    SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
    Definition: var.c:24372
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23478
    SCIP_RETCODE SCIPinferVarUbProp(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_PROP *inferprop, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:7699
    SCIP_RETCODE SCIPtightenVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:8257
    int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24568
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4386
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24585
    SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2872
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24614
    int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24642
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    int SCIPgetNCliques(SCIP *scip)
    Definition: scip_var.c:9512
    SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24653
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2736
    int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
    Definition: var.c:17274
    SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
    Definition: var.c:24400
    SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
    Definition: var.c:16807
    int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4328
    SCIP_Bool SCIPallowWeakDualReds(SCIP *scip)
    Definition: scip_var.c:10998
    SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24600
    SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:1853
    SCIP_RETCODE SCIPtightenVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:8026
    SCIP_RETCODE SCIPinferVarLbProp(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_PROP *inferprop, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:7584
    void SCIPsortDownPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
    void SCIPsortDownRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
    void SCIPsortDownPtrPtr(void **ptrarray1, void **ptrarray2, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
    SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
    Definition: implics.c:3384
    int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
    Definition: implics.c:3374
    SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
    Definition: implics.c:3396
    unsigned int SCIPcliqueGetId(SCIP_CLIQUE *clique)
    Definition: implics.c:3406
    memory allocation routines
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    #define PROP_PRESOL_MAXROUNDS
    #define PROP_PRESOLTIMING
    #define PROP_DESC
    static SCIP_RETCODE addConflictBinvar(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_OBJIMPLICS *objimplics, SCIP_HASHTABLE *addedvars, SCIP_Bool respropuseimplics, SCIP_Real *reqpseudoobjval)
    static SCIP_RETCODE getConflictImplics(SCIP *scip, SCIP_VAR **vars, int start, int end, SCIP_BDCHGIDX *bdchgidx, SCIP_HASHTABLE *addedvars, SCIP_Real *reqpseudoobjval, SCIP_Bool *foundimplics)
    static SCIP_RETCODE dropVarEvents(SCIP *scip, SCIP_PROPDATA *propdata)
    static SCIP_DECL_HASHKEYEQ(cliqueIsHashkeyEq)
    #define DEFAULT_MAXNEWVARS
    #define DEFAULT_PROPCUTOFFBOUND
    static SCIP_RETCODE getMaxactObjchg(SCIP *scip, SCIP_VAR *var, SCIP_BOUNDTYPE bound, SCIP_Bool useimplics, SCIP_Real *objchg)
    static SCIP_RETCODE adjustCutoffbound(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, int inferinfo, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_HASHTABLE *addedvars, SCIP_Real *cutoffbound)
    #define PROP_NAME
    static void resetContributors(SCIP_HASHMAP *binobjvarmap, SCIP_Bool *collectedvars, SCIP_VAR **contributors, int ncontributors)
    static SCIP_DECL_HASHGETKEY(cliqueGetHashkey)
    static SCIP_DECL_PROPCOPY(propCopyPseudoobj)
    static SCIP_RETCODE propagateLowerbound(SCIP *scip, SCIP_PROP *prop, SCIP_RESULT *result)
    static void checkImplicsApplied(SCIP *scip, SCIP_VAR *var)
    static SCIP_RETCODE collectMinactVar(SCIP *scip, SCIP_VAR *var, SCIP_OBJIMPLICS **objimplics, SCIP_Bool useimplics, SCIP_HASHMAP *binobjvarmap, SCIP_Bool *collectedlbvars, SCIP_Bool *collectedubvars, int nbinobjvars, SCIP_VAR **contributors, SCIP_HASHTABLE *uselesscliques, SCIP_Bool *collect)
    #define DEFAULT_MAXIMPLVARS
    static SCIP_RETCODE propagateLowerboundVar(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, SCIP_Real lowerbound, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    #define DEFAULT_MINUSELESS
    #define DEFAULT_RESPROPUSEIMPLICS
    static SCIP_RETCODE catchObjEvent(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_EVENTHDLR *eventhdlr, SCIP_VAR *var)
    static void updateMaxObjPseudoactivity(SCIP *scip, SCIP_PROPDATA *propdata)
    static SCIP_DECL_PROPEXEC(propExecPseudoobj)
    static SCIP_DECL_PROPPRESOL(propPresolPseudoobj)
    static SCIP_RETCODE collectMaxactVar(SCIP *scip, SCIP_VAR *var, SCIP_Bool useimplics, SCIP_Real *objchg, SCIP_Bool *isnotzero)
    static SCIP_DECL_PROPFREE(propFreePseudoobj)
    static SCIP_Real collectMinactImplicVar(SCIP *scip, SCIP_VAR *var, SCIP_HASHMAP *binobjvarmap, SCIP_Bool *collectedvars, int nbinobjvars, SCIP_VAR **contributors, int *ncontributors)
    static SCIP_RETCODE getMinactImplicObjchg(SCIP *scip, SCIP_VAR *var, SCIP_OBJIMPLICS *objimplics, SCIP_BDCHGIDX *bdchgidx, SCIP_BOUNDTYPE bound, SCIP_Bool local, SCIP_Real *objchg)
    static SCIP_DECL_PROPEXITSOL(propExitsolPseudoobj)
    static SCIP_Real getVarObjchg(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BOUNDTYPE bound)
    static SCIP_RETCODE propagateCutoffbound(SCIP *scip, SCIP_PROP *prop, SCIP_RESULT *result)
    #define DEFAULT_MAXVARSFRAC
    #define DEFAULT_PROPUSEIMPLICS
    static SCIP_DECL_PROPINITSOL(propInitsolPseudoobj)
    static SCIP_RETCODE propdataInit(SCIP *scip, SCIP_PROPDATA *propdata)
    static void checkGlbfirstnonfixed(SCIP_PROPDATA *propdata)
    #define PROP_DELAY
    static void calcMaxObjPseudoactivity(SCIP *scip, SCIP_PROPDATA *propdata)
    #define DEFAULT_PROPFULLINROOT
    static SCIP_Real getMaxObjPseudoactivityResidual(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var)
    static void propdataReset(SCIP_PROPDATA *propdata)
    static SCIP_RETCODE objimplicsCreate(SCIP *scip, SCIP_OBJIMPLICS **objimplics, SCIP_VAR **objvars, SCIP_HASHMAP *binobjvarmap, SCIP_Bool *collectedlbvars, SCIP_Bool *collectedubvars, SCIP_Real maxlbobjchg, SCIP_Real maxubobjchg, int nlbimpls, int nubimpls)
    static SCIP_DECL_PROPRESPROP(propRespropPseudoobj)
    static SCIP_RETCODE collectMinactImplicVars(SCIP *scip, SCIP_VAR *var, SCIP_BOUNDTYPE bound, SCIP_HASHMAP *binobjvarmap, SCIP_Bool *collectedvars, int nbinobjvars, SCIP_VAR **contributors, SCIP_HASHTABLE *uselesscliques, int *ncontributors, SCIP_Real *objchg)
    static SCIP_RETCODE collectMinactObjchg(SCIP *scip, SCIP_VAR *var, SCIP_BOUNDTYPE bound, SCIP_HASHMAP *binobjvarmap, SCIP_Bool *collectedvars, int nbinobjvars, SCIP_VAR **contributors, SCIP_HASHTABLE *uselesscliques, int *ncontributors, SCIP_Real *objchg)
    #define MAX_CLIQUELENGTH
    static SCIP_RETCODE propagateCutoffboundBinvars(SCIP *scip, SCIP_PROP *prop, SCIP_Real cutoffbound, SCIP_Real pseudoobjval, int *nfixedvars, SCIP_Bool *cutoff)
    static SCIP_RETCODE propdataExit(SCIP *scip, SCIP_PROPDATA *propdata)
    static SCIP_DECL_HASHKEYVAL(cliqueGetHashkeyVal)
    #define PROP_TIMING
    static SCIP_RETCODE propagateLowerboundBinvar(SCIP *scip, SCIP_VAR *var, SCIP_Real lowerbound, SCIP_Real maxpseudoobjact, SCIP_Bool useimplics, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    static SCIP_RETCODE objimplicsDelPos(SCIP *scip, SCIP_OBJIMPLICS *objimplics, int pos)
    static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Real *reqpseudoobjval)
    static SCIP_DECL_SORTPTRCOMP(objimplicsComp)
    static SCIP_Real getMaxObjPseudoactivityResidualValue(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_Real contrib)
    static SCIP_RETCODE getMaxactImplicObjchg(SCIP *scip, SCIP_VAR *var, SCIP_BOUNDTYPE bound, SCIP_Real *objchg)
    static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_Real cutoffbound, SCIP_VAR *infervar, int inferinfo, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx)
    static SCIP_RETCODE propagateCutoffboundGlobally(SCIP *scip, SCIP_PROP *prop, int *nchgbds, SCIP_Bool *cutoff)
    static SCIP_RETCODE propagateCutoffboundBinvar(SCIP *scip, SCIP_PROP *prop, SCIP_VAR *var, int pos, SCIP_Real cutoffbound, SCIP_Real pseudoobjval, SCIP_Bool *tightened, SCIP_Bool *cutoff, SCIP_Bool local)
    static SCIP_DECL_EVENTEXEC(eventExecPseudoobj)
    static SCIP_RETCODE objimplicsFree(SCIP *scip, SCIP_OBJIMPLICS **objimplics)
    static SCIP_RETCODE dropObjEvent(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_EVENTHDLR *eventhdlr, SCIP_VAR *var)
    #define EVENTHDLR_DESC
    static SCIP_Real getMaxObjPseudoactivity(SCIP *scip, SCIP_PROPDATA *propdata)
    static SCIP_RETCODE getMinactObjchg(SCIP *scip, SCIP_VAR *var, SCIP_OBJIMPLICS *objimplics, SCIP_BDCHGIDX *bdchgidx, SCIP_BOUNDTYPE bound, SCIP_Bool local, SCIP_Real *objchg)
    #define EVENTHDLR_NAME
    #define PROP_FREQ
    #define DEFAULT_FORCE
    #define PROP_PRIORITY
    #define PROP_PRESOL_PRIORITY
    static SCIP_RETCODE propagateCutoffboundVar(SCIP *scip, SCIP_PROP *prop, SCIP_VAR *var, int inferinfo, SCIP_Real objchg, SCIP_Real cutoffbound, SCIP_Real pseudoobjval, SCIP_Bool local, SCIP_Bool *tightened)
    Pseudo objective propagator.
    public methods for managing events
    public methods for implications, variable bounds, and cliques
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    public data structures and miscellaneous methods
    methods for sorting joint arrays of various types
    public methods for propagators
    public methods for problem variables
    public methods for conflict handler plugins and conflict analysis
    public methods for event handler plugins and event handlers
    general public methods
    public methods for the LP relaxation, rows and columns
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for variable pricer plugins
    public methods for global and local (sub)problems
    public methods for the probing mode
    public methods for propagator plugins
    public methods for querying solving statistics
    public methods for the branch-and-bound tree
    public methods for SCIP variables
    SCIP_VAR ** objvars
    SCIP_Real maxobjchg
    @ SCIP_CONFTYPE_PROPAGATION
    Definition: type_conflict.h:62
    #define SCIP_EVENTTYPE_GUBCHANGED
    Definition: type_event.h:76
    struct SCIP_EventData SCIP_EVENTDATA
    Definition: type_event.h:179
    #define SCIP_EVENTTYPE_LBRELAXED
    Definition: type_event.h:78
    #define SCIP_EVENTTYPE_GLBCHANGED
    Definition: type_event.h:75
    #define SCIP_EVENTTYPE_BOUNDRELAXED
    Definition: type_event.h:126
    #define SCIP_EVENTTYPE_VARADDED
    Definition: type_event.h:70
    uint64_t SCIP_EVENTTYPE
    Definition: type_event.h:156
    #define SCIP_EVENTTYPE_UBRELAXED
    Definition: type_event.h:80
    @ 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
    struct SCIP_PropData SCIP_PROPDATA
    Definition: type_prop.h:52
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_REDUCEDDOM
    Definition: type_result.h:51
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_PLUGINNOTFOUND
    Definition: type_retcode.h:54
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_SOLVING
    Definition: type_set.h:53
    #define SCIP_PROPTIMING_DURINGLPLOOP
    Definition: type_timing.h:67
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141