Scippy

    SCIP

    Solving Constraint Integer Programs

    prop_genvbounds.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_genvbounds.c
    26 * @ingroup DEFPLUGINS_PROP
    27 * @brief generalized variable bounds propagator
    28 * @author Stefan Weltge
    29 * @author Ambros Gleixner
    30 * @author Benjamin Mueller
    31 */
    32
    33/**@todo should we only discard events catched from nodes that are not the current node's ancestors? */
    34/**@todo improve computation of minactivity */
    35/**@todo for multaggr vars on left-hand side, create a linear constraint, probably in exitpre */
    36
    37/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    38
    40#include "scip/cons_linear.h"
    41#include "scip/debug.h"
    43#include "scip/pub_event.h"
    44#include "scip/pub_message.h"
    45#include "scip/pub_misc.h"
    46#include "scip/pub_prop.h"
    47#include "scip/pub_tree.h"
    48#include "scip/pub_var.h"
    49#include "scip/scip_conflict.h"
    50#include "scip/scip_cons.h"
    52#include "scip/scip_event.h"
    53#include "scip/scip_general.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_prob.h"
    59#include "scip/scip_probing.h"
    60#include "scip/scip_prop.h"
    61#include "scip/scip_sol.h"
    62#include "scip/scip_solve.h"
    64#include "scip/scip_tree.h"
    65#include "scip/scip_var.h"
    66#include <string.h>
    67
    68#define PROP_NAME "genvbounds"
    69#define PROP_DESC "generalized variable bounds propagator"
    70#define PROP_TIMING SCIP_PROPTIMING_ALWAYS
    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
    74 * found reductions? */
    75#define PROP_PRESOL_PRIORITY -2000000 /**< priority of the presolving method (>= 0: before, < 0: after
    76 * constraint handlers); combined with presolvers */
    77#define PROP_PRESOLTIMING SCIP_PRESOLTIMING_FAST /* timing of the presolving method (fast, medium, or exhaustive) */
    78#define PROP_PRESOL_MAXROUNDS -1 /**< maximal number of presolving rounds the presolver participates
    79 * in (-1: no limit) */
    80#define DEFAULT_GLOBAL_PROPAGATION TRUE /**< apply global propagation? */
    81#define DEFAULT_PROPAGATE_IN_ROOT_NODE TRUE /**< apply genvbounds in root node if no new incumbent was found? */
    82#define DEFAULT_SORT TRUE /**< sort genvbounds and wait for bound change events? (otherwise all
    83 * genvbounds are applied in each node) */
    84#define DEFAULT_PROPASCONSS FALSE /**< should genvbounds be transformed to (linear) constraints? */
    85
    86#define EVENTHDLR_NAME "genvbounds"
    87#define EVENTHDLR_DESC "event handler for generalized variable bounds propagator"
    88
    89
    90/*
    91 * Data structures
    92 */
    93
    94/** GenVBound data */
    96{
    97 SCIP_VAR** vars; /**< pointers to variables x_j occurring in this generalized variable
    98 * bound */
    99 SCIP_VAR* var; /**< pointer to variable x_i */
    100 SCIP_Real* coefs; /**< coefficients a_j of the variables listed in vars */
    101 SCIP_Real constant; /**< constant term in generalized variable bound */
    102 SCIP_Real cutoffcoef; /**< cutoff bound's coefficient */
    103 int coefssize; /**< size of coefs array */
    104 int index; /**< index of this genvbound in genvboundstore array */
    105 int ncoefs; /**< number of nonzero coefficients a_j */
    106 SCIP_BOUNDTYPE boundtype; /**< type of bound provided by the genvbound, SCIP_BOUNDTYPE_LOWER/UPPER
    107 * if +/- x_i on left-hand side */
    108 SCIP_Bool relaxonly; /**< contains a relaxation-only variable */
    109};
    110typedef struct GenVBound GENVBOUND;
    111
    112/** starting indices data structure */
    113struct SCIP_EventData
    114{
    115 SCIP_PROP* prop; /**< pointer to genvbounds propagator */
    116 SCIP_VAR* var; /**< variable */
    117 int* startindices; /**< array to store the first indices of genvbounds in components that are
    118 * impacted by a change of this bound */
    119 int* startcomponents; /**< array to store the components corresponding to startindices array */
    120 int nstarts; /**< number of indices stored in startindices array */
    121 int startindicessize; /**< size of the startindices and startcomponents arrays */
    122};
    123
    124/** propagator data */
    125struct SCIP_PropData
    126{
    127 GENVBOUND** genvboundstore; /**< array to store genvbounds; fast access is provided by hashmaps
    128 * lbgenvbounds and ubgenvbounds */
    129 SCIP_EVENTDATA** lbevents; /**< array of lower bound event data */
    130 SCIP_EVENTDATA** ubevents; /**< array of upper bound event data */
    131 SCIP_EVENTHDLR* eventhdlr; /**< genvbounds propagator event handler */
    132 SCIP_HASHMAP* lbgenvbounds; /**< hashmap to provide fast access to lower bound genvbounds in
    133 * genvboundstore array */
    134 SCIP_HASHMAP* ubgenvbounds; /**< hashmap to provide fast access to upper bound genvbounds in
    135 * genvboundstore array */
    136 SCIP_HASHMAP* lbeventsmap; /**< hashmap to provide fast access to lbevents array */
    137 SCIP_HASHMAP* ubeventsmap; /**< hashmap to provide fast access to ubevents array */
    138 SCIP_HASHMAP* startmap; /**< hashmap to provide fast access to startindices array */
    139 SCIP_PROP* prop; /**< pointer to genvbounds propagator */
    140 SCIP_Longint lastnodenumber; /**< last node number where events for starting indices were caught */
    141 SCIP_VAR* cutoffboundvar; /**< artificial variable representing primal cutoff bound */
    142 int* componentsstart; /**< stores the components starting indices in genvboundstore array; the
    143 * entry componentsstart[ncomponents] is equal to ngenvbounds, which
    144 * makes it easier to iterate over all components */
    145 int componentsstartsize;/**< size of componentsstart array */
    146 int* startindices; /**< storing indices of components where local propagation should start */
    147 int* startcomponents; /**< components corresponding to indices stored in startindices array */
    148 int startindicessize; /**< size of startindices and startcomponents arrays */
    149 int* gstartindices; /**< storing indices of components where global propagation, i.e.,
    150 * propagation of an improved primal bound, should start */
    151 int* gstartcomponents; /**< components corresponding to indices stored in gstartindices array */
    152 int gstartindicessize; /**< size of gstartindices and gstartcomponents arrays */
    153 SCIP_Real lastcutoff; /**< cutoff bound's value last time genvbounds propagator was called */
    154 int genvboundstoresize; /**< size of genvboundstore array */
    155 int ngenvbounds; /**< number of genvbounds stored in genvboundstore array */
    156 int ncomponents; /**< number of components in genvboundstore array */
    157 int nindices; /**< number of indices stored in startindices array */
    158 int ngindices; /**< number of indices stored in gstartindices array */
    159 int nlbevents; /**< number of data entries in lbevents array */
    160 int nubevents; /**< number of data entries in ubevents array */
    161 SCIP_Bool issorted; /**< stores wether array genvboundstore is topologically sorted */
    162 SCIP_Bool global; /**< apply global propagation? */
    163 SCIP_Bool propinrootnode; /**< apply genvbounds in root node if no new incumbent was found? */
    164 SCIP_Bool sort; /**< sort genvbounds and wait for bound change events? (otherwise all
    165 * genvbounds are applied in each node) */
    166 SCIP_Bool propasconss; /**< should genvbounds be transformed to (linear) constraints? */
    167 SCIP_PROPTIMING inittiming; /**< initial propagator timing */
    168};
    169
    170
    171/*
    172 * Local methods
    173 */
    174
    175/** returns correct cutoff bound value */
    176static
    178 SCIP* scip /**< SCIP data structure */
    179 )
    180{
    181 assert(scip != NULL);
    182
    183 SCIPdebugMsg(scip, "cutoff = %.9g (%.9g + %.9g * %.9g)\n",
    186
    187 /* the cutoff bound is valid w.r.t. the current objective function in the transformed problem; during presolving,
    188 * however, the objective function can change (e.g., when a variable is fixed, its contribution in the objective is
    189 * subtracted from the cutoff bound and added to the objective offset); we solve this by transforming the
    190 * contribution of the cutoff bound in the generalized variable bound to the original problem as described in
    191 * function SCIPgenVBoundAdd()
    192 */
    194}
    195
    196/** returns corresponding genvbound in genvboundstore if there is one, NULL otherwise */
    197static
    199 SCIP* scip, /**< SCIP data structure */
    200 SCIP_PROPDATA* propdata, /**< data of the genvbounds propagator */
    201 SCIP_VAR* var, /**< bounds variable */
    202 SCIP_BOUNDTYPE boundtype /**< bounds type */
    203 )
    204{
    205 SCIP_HASHMAP* hashmap;
    206
    207 assert(scip != NULL);
    208 assert(propdata != NULL);
    209 assert(var != NULL);
    210
    211 hashmap = boundtype == SCIP_BOUNDTYPE_LOWER ? propdata->lbgenvbounds : propdata->ubgenvbounds;
    212
    213 return (GENVBOUND*) SCIPhashmapGetImage(hashmap, var);
    214}
    215
    216#ifdef SCIP_DEBUG
    217/** prints a genvbound as debug message */
    218static
    219void printGenVBound(
    220 SCIP* scip, /**< SCIP data structure */
    221 GENVBOUND* genvbound /**< genvbound to be printed */
    222 )
    223{
    224 SCIP_Bool first;
    225 int i;
    226
    227 assert(genvbound != NULL);
    228
    229 if( genvbound->boundtype == SCIP_BOUNDTYPE_UPPER )
    230 {
    231 SCIPdebugMsgPrint(scip, "- ");
    232 }
    233
    234 SCIPdebugMsgPrint(scip, "<%s> >= ", SCIPvarGetName(genvbound->var));
    235
    236 first = TRUE;
    237 for( i = 0; i < genvbound->ncoefs; i++ )
    238 {
    239 if( !first )
    240 {
    241 SCIPdebugMsgPrint(scip, " + ");
    242 }
    243
    244 SCIPdebugMsgPrint(scip, "%g * <%s>", genvbound->coefs[i], SCIPvarGetName(genvbound->vars[i]));
    245
    246 first = FALSE;
    247 }
    248
    249 if( !SCIPisZero(scip, genvbound->cutoffcoef) )
    250 {
    251 SCIPdebugMsgPrint(scip, " + %g * cutoff_bound", genvbound->cutoffcoef);
    252 }
    253
    254 if( !SCIPisZero(scip, genvbound->constant) )
    255 {
    256 SCIPdebugMsgPrint(scip, " + %g", genvbound->constant);
    257 }
    258
    259 SCIPdebugMsgPrint(scip, "\n");
    260}
    261#endif
    262
    263/** calculates the minactivity of a linear combination of variables stored in an array */
    264static
    266 SCIP* scip, /**< SCIP data structure */
    267 SCIP_VAR** vars, /**< array of variables */
    268 SCIP_Real* coefs, /**< array of coefficients */
    269 int nvars, /**< number of variables */
    270 SCIP_Bool global /**< use global variable bounds? */
    271 )
    272{
    273 SCIP_Real minval;
    274 int i;
    275
    276 assert(scip != NULL);
    277 assert(vars != NULL);
    278 assert(coefs != NULL);
    279 assert(nvars >= 0);
    280
    281 minval = 0.0;
    282
    283 for( i = 0; i < nvars; i++ )
    284 {
    286
    287 /* get global or local bound */
    288 if( global )
    289 bound = coefs[i] > 0.0 ? SCIPvarGetLbGlobal(vars[i]) : SCIPvarGetUbGlobal(vars[i]);
    290 else
    291 bound = coefs[i] > 0.0 ? SCIPvarGetLbLocal(vars[i]) : SCIPvarGetUbLocal(vars[i]);
    292
    293 /* with infinite bounds we cannot compute a valid minactivity and return minus infinity */
    295 return -SCIPinfinity(scip);
    296
    297 /* add contribution to minactivity */
    298 minval += coefs[i] * bound;
    299 }
    300
    301 return minval;
    302}
    303
    304/** calculates the minactivity of a linear combination of variables stored in the current conflict set */
    305static
    307 SCIP* scip, /**< SCIP data structure */
    308 SCIP_VAR** vars, /**< array of variables */
    309 SCIP_Real* coefs, /**< array of coefficients */
    310 int nvars, /**< number of variables */
    311 SCIP_BDCHGIDX* bdchgidx /**< bound change at which minactivity should be computed; if NULL use local bounds */
    312 )
    313{
    314 SCIP_Real minval;
    315 int i;
    316
    317 assert(scip != NULL);
    318 assert(vars != NULL);
    319 assert(coefs != NULL);
    320 assert(nvars >= 0);
    321
    322 minval = 0.0;
    323
    324 for( i = 0; i < nvars; i++ )
    325 {
    327
    328 if( coefs[i] > 0.0 )
    329 {
    330 /* get bound at current bound change */
    331 bound = SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, TRUE);
    332
    333 /* if bdchgidx is NULL, assert that we use local bounds */
    334 assert(bdchgidx != NULL || SCIPisEQ(scip, bound, SCIPvarGetLbLocal(vars[i])));
    335
    336 /* if bdchgidx is not NULL, use the possibly tighter bound already in the current conflict set */
    337 if( bdchgidx != NULL && SCIPgetConflictVarLb(scip, vars[i]) > bound )
    338 bound = SCIPgetConflictVarLb(scip, vars[i]);
    339 }
    340 else
    341 {
    342 /* get bound at current bound change */
    343 bound = SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, TRUE);
    344
    345 /* if bdchgidx is NULL, assert that we use local bounds */
    346 assert(bdchgidx != NULL || SCIPisEQ(scip, bound, SCIPvarGetUbLocal(vars[i])));
    347
    348 /* if bdchgidx is not NULL, use the possibly tighter bound already in the current conflict set */
    349 if( bdchgidx != NULL && SCIPgetConflictVarUb(scip, vars[i]) < bound )
    350 bound = SCIPgetConflictVarUb(scip, vars[i]);
    351 }
    352
    353 /* with infinite bounds we cannot compute a valid minactivity and return minus infinity */
    355 return -SCIPinfinity(scip);
    356
    357 /* add contribution to minactivity */
    358 minval += coefs[i] * bound;
    359 }
    360
    361 return minval;
    362}
    363
    364/** returns a valid bound given by a generalized variable bound */
    365static
    367 SCIP* scip, /**< SCIP data structure */
    368 GENVBOUND* genvbound, /**< generalized variable bound */
    369 SCIP_Bool global /**< use global variable bounds? */
    370 )
    371{
    372 SCIP_Real boundval;
    373
    374 assert(scip != NULL);
    375 assert(genvbound != NULL);
    376
    377 boundval = getGenVBoundsMinActivity(scip, genvbound->vars, genvbound->coefs, genvbound->ncoefs, global);
    378
    379 if( SCIPisInfinity(scip, -boundval) )
    380 return (genvbound->boundtype == SCIP_BOUNDTYPE_LOWER) ? -SCIPinfinity(scip) : SCIPinfinity(scip);
    381
    382 if( genvbound->cutoffcoef != 0.0 )
    383 boundval += genvbound->cutoffcoef * getCutoffboundGenVBound(scip);
    384
    385 boundval += genvbound->constant;
    386
    387 if( genvbound->boundtype == SCIP_BOUNDTYPE_UPPER )
    388 boundval *= -1.0;
    389
    390 return boundval;
    391}
    392
    393#ifdef WITH_DEBUG_SOLUTION
    394/** checks whether a generalized variable bound violates the debug solution */
    395static
    396SCIP_RETCODE checkDebugSolutionGenVBound(
    397 SCIP* scip, /**< SCIP data structure */
    398 GENVBOUND* genvbound /**< generalized variable bound */
    399 )
    400{
    401 SCIP_SOL* debugsol;
    402 SCIP_Real activity;
    403 SCIP_Real solval;
    404 int i;
    405
    406 assert(scip != NULL);
    407 assert(genvbound != NULL);
    408
    409 if( !SCIPdebugIsMainscip(scip) )
    410 return SCIP_OKAY;
    411
    412 /* the genvbound must be valid for all cutoff bounds greater equal the objective value of the debug solution */
    413 SCIP_CALL( SCIPdebugGetSol(scip, &debugsol) );
    414
    415 /* check whether a debug solution is available */
    416 if( debugsol == NULL )
    417 return SCIP_OKAY;
    418
    419 activity = 0.0;
    420 for( i = 0; i < genvbound->ncoefs; i++ )
    421 {
    422 SCIP_CALL( SCIPdebugGetSolVal(scip, genvbound->vars[i], &solval) );
    423 if( solval != SCIP_UNKNOWN || solval != SCIP_INVALID )
    424 activity += genvbound->coefs[i] * solval;
    425 else
    426 printf("***** debug: ignoring variable with %s value in debug solution\n",
    427 solval == SCIP_UNKNOWN ? "unknown" : "invalid");
    428 }
    429
    430 activity += genvbound->cutoffcoef *
    432 activity += genvbound->constant;
    433
    434 SCIP_CALL( SCIPdebugGetSolVal(scip, genvbound->var, &solval) );
    435 if( solval != SCIP_UNKNOWN || solval != SCIP_INVALID )
    436 {
    437 if( genvbound->boundtype == SCIP_BOUNDTYPE_LOWER )
    438 {
    439 SCIP_CALL( SCIPdebugCheckLbGlobal(scip, genvbound->var, activity) );
    440 }
    441 else if( genvbound->boundtype == SCIP_BOUNDTYPE_UPPER )
    442 {
    443 SCIP_CALL( SCIPdebugCheckUbGlobal(scip, genvbound->var, -activity) );
    444 }
    445 }
    446
    447 return SCIP_OKAY;
    448}
    449#endif
    450
    451/** allocate local and global startindices, startcomponents and startmap */
    452static
    454 SCIP* scip, /**< SCIP data structure */
    455 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
    456 )
    457{
    458 assert(scip != NULL);
    459 assert(propdata != NULL);
    460
    461 assert(propdata->startcomponents == NULL);
    462 assert(propdata->startindices == NULL);
    463 assert(propdata->startmap == NULL);
    464 assert(propdata->nindices == -1);
    465
    466 assert(propdata->gstartindices == NULL);
    467 assert(propdata->gstartcomponents == NULL);
    468 assert(propdata->ngindices == -1);
    469
    470 assert(propdata->ngenvbounds >= 1);
    471 assert(propdata->ncomponents >= 1);
    472
    473 SCIPdebugMsg(scip, "create starting data\n");
    474
    475 /* allocate memory for arrays */
    476 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->startindices), propdata->ncomponents) );
    477 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->startcomponents), propdata->ncomponents) );
    478 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->gstartindices), propdata->ncomponents) );
    479 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->gstartcomponents), propdata->ncomponents) );
    480 propdata->startindicessize = propdata->ncomponents;
    481 propdata->gstartindicessize = propdata->ncomponents;
    482
    483 /* create hashmap */
    484 SCIP_CALL( SCIPhashmapCreate(&(propdata->startmap), SCIPblkmem(scip), propdata->ncomponents) );
    485
    486 propdata->nindices = 0;
    487 propdata->ngindices = 0;
    488
    489 return SCIP_OKAY;
    490}
    491
    492/** free local and global startindices, startcomponents and startmap */
    493static
    495 SCIP* scip, /**< SCIP data structure */
    496 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
    497 )
    498{
    499 assert(scip != NULL);
    500 assert(propdata != NULL);
    501
    502 SCIPdebugMsg(scip, "free starting data\n");
    503
    504 if( propdata->startcomponents != NULL )
    505 {
    506 assert(propdata->startindices != NULL);
    507 assert(propdata->startmap != NULL);
    508 assert(propdata->nindices >= 0);
    509
    510 SCIPfreeBlockMemoryArray(scip, &(propdata->startindices), propdata->startindicessize);
    511 SCIPfreeBlockMemoryArray(scip, &(propdata->startcomponents), propdata->startindicessize);
    512 propdata->startindicessize = 0;
    513 SCIPhashmapFree(&(propdata->startmap));
    514 propdata->nindices = -1;
    515
    516 assert(propdata->gstartindices != NULL);
    517 assert(propdata->gstartcomponents != NULL);
    518 assert(propdata->ngindices >= 0);
    519
    520 SCIPfreeBlockMemoryArray(scip, &(propdata->gstartindices), propdata->gstartindicessize);
    521 SCIPfreeBlockMemoryArray(scip, &(propdata->gstartcomponents), propdata->gstartindicessize);
    522 propdata->gstartindicessize = 0;
    523 propdata->ngindices = -1;
    524 }
    525
    526 assert(propdata->startcomponents == NULL);
    527 assert(propdata->startindices == NULL);
    528 assert(propdata->startmap == NULL);
    529 assert(propdata->nindices == -1);
    530
    531 assert(propdata->gstartindices == NULL);
    532 assert(propdata->gstartcomponents == NULL);
    533 assert(propdata->ngindices == -1);
    534
    535 return SCIP_OKAY;
    536}
    537
    538static
    540 SCIP* scip, /**< SCIP data structure */
    541 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
    542 )
    543{
    544 int i;
    545
    546 assert(scip != NULL);
    547 assert(propdata != NULL);
    548
    549 assert(propdata->gstartindices != NULL);
    550 assert(propdata->gstartcomponents != NULL);
    551 assert(propdata->ngindices == 0);
    552
    553 SCIPdebugMsg(scip, "fill global starting data\n");
    554
    555 for( i = 0; i < propdata->ncomponents; i++ )
    556 {
    557 int j;
    558
    559 for( j = propdata->componentsstart[i]; j < propdata->componentsstart[i+1]; j++ ) /*lint !e679*/
    560 {
    561 assert(j < propdata->ngenvbounds);
    562
    563 if( !SCIPisZero(scip, propdata->genvboundstore[j]->cutoffcoef) )
    564 {
    565 assert(SCIPisNegative(scip, propdata->genvboundstore[j]->cutoffcoef));
    566
    567 propdata->gstartcomponents[propdata->ngindices] = i;
    568 propdata->gstartindices[propdata->ngindices] = j;
    569
    570 /* go to next component */
    571 propdata->ngindices++;
    572 break;
    573 }
    574 }
    575 }
    576
    577 /* resize arrays */
    578 if( propdata->gstartindicessize != propdata->ngindices )
    579 {
    580 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(propdata->gstartindices), propdata->gstartindicessize, \
    581 propdata->ngindices) );
    582 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(propdata->gstartcomponents), propdata->gstartindicessize, \
    583 propdata->ngindices) );
    584 propdata->gstartindicessize = propdata->ngindices;
    585 }
    586
    587 return SCIP_OKAY;
    588}
    589
    590
    591/** resets local starting data */
    592static
    594 SCIP* scip, /**< SCIP data structure */
    595 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
    596 )
    597{
    598 assert(scip != NULL);
    599 assert(propdata != NULL);
    600 assert(propdata->startcomponents != NULL);
    601 assert(propdata->startindices != NULL);
    602 assert(propdata->startmap != NULL);
    603 assert(propdata->nindices >= 0);
    604
    605 SCIP_CALL( SCIPhashmapRemoveAll(propdata->startmap) );
    606 propdata->nindices = 0;
    607
    608 return SCIP_OKAY;
    609}
    610
    611/** frees sorted components data */
    612static
    614 SCIP* scip, /**< SCIP data structure */
    615 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
    616 )
    617{
    618 assert(scip != NULL);
    619 assert(propdata != NULL);
    620
    621 SCIPdebugMsg(scip, "free components data\n");
    622
    623 if( propdata->componentsstart != NULL )
    624 {
    625 assert(propdata->ncomponents > 0);
    626
    627 SCIPfreeBlockMemoryArray(scip, &(propdata->componentsstart), propdata->componentsstartsize);
    628 propdata->componentsstartsize = 0;
    629 propdata->ncomponents = -1;
    630 }
    631
    632 assert(propdata->componentsstart == NULL);
    633 assert(propdata->ncomponents == -1);
    634
    635 return SCIP_OKAY;
    636}
    637
    638/** frees memory allocated for a generalized variable bound */
    639static
    641 SCIP* scip,
    642 GENVBOUND* genvbound
    643 )
    644{
    645 int i;
    646
    647 assert(scip != NULL);
    648 assert(genvbound != NULL);
    649 assert(genvbound->coefs != NULL);
    650 assert(genvbound->vars != NULL);
    651 assert(genvbound->var != NULL);
    652
    653 /* release variables */
    654 for( i = 0; i < genvbound->ncoefs; ++i )
    655 {
    656 assert(genvbound->vars[i] != NULL);
    657 SCIP_CALL( SCIPreleaseVar(scip, &(genvbound->vars[i])) );
    658 }
    659 SCIP_CALL( SCIPreleaseVar(scip, &genvbound->var) );
    660
    661 /* free memory */
    662 SCIPfreeBlockMemoryArray(scip, &(genvbound->coefs), genvbound->coefssize);
    663 SCIPfreeBlockMemoryArray(scip, &(genvbound->vars), genvbound->coefssize);
    664 SCIPfreeBlockMemory(scip, &genvbound);
    665
    666 return SCIP_OKAY;
    667}
    668
    669/** helper function to release all genvbounds */
    670static
    672 SCIP* scip,
    673 SCIP_PROP* prop,
    674 SCIP_PROPDATA* propdata
    675 )
    676{
    677 int i;
    678
    679 assert(scip != NULL);
    680 assert(prop != NULL);
    681 assert(propdata != NULL);
    682
    683 if( propdata->genvboundstore != NULL )
    684 {
    685 /* disable genvbounds propagator */
    686 if( propdata->ngenvbounds >= 1 )
    688
    689 /* free genvbounds */
    690 for( i = propdata->ngenvbounds - 1; i >= 0; i-- )
    691 {
    692 SCIP_CALL( freeGenVBound(scip, propdata->genvboundstore[i]) );
    693 }
    694
    695 /* free genvboundstore hashmaps */
    696 SCIPhashmapFree(&(propdata->lbgenvbounds));
    697 SCIPhashmapFree(&(propdata->ubgenvbounds));
    698
    699 /* free genvboundstore array */
    700 SCIPfreeBlockMemoryArray(scip, &(propdata->genvboundstore), propdata->genvboundstoresize);
    701
    702 /* set the number of genvbounds to zero */
    703 propdata->ngenvbounds = 0;
    704
    705 /* free componentsstart array */
    706 SCIP_CALL( freeComponentsData(scip, propdata) );
    707
    708 /* free starting indices data */
    709 SCIP_CALL( freeStartingData(scip, propdata) );
    710
    711 /* release the cutoffboundvar and undo the locks */
    712 if( propdata->cutoffboundvar != NULL )
    713 {
    714 SCIP_CALL( SCIPaddVarLocksType(scip, propdata->cutoffboundvar, SCIP_LOCKTYPE_MODEL, -1, -1) );
    715 SCIP_CALL( SCIPreleaseVar(scip, &(propdata->cutoffboundvar)) );
    716 propdata->cutoffboundvar = NULL;
    717 SCIPdebugMsg(scip, "release cutoffboundvar!\n");
    718 }
    719 }
    720
    721 return SCIP_OKAY;
    722}
    723
    724/** helper function to release relax-only genvbounds */
    725static
    727 SCIP* scip,
    728 SCIP_PROP* prop,
    729 SCIP_PROPDATA* propdata
    730 )
    731{
    732 SCIP_Bool freedgenvbound;
    733 int i;
    734
    735 assert(scip != NULL);
    736 assert(propdata != NULL);
    737
    738 if( propdata->genvboundstore == NULL )
    739 return SCIP_OKAY;
    740
    741 /* free genvbounds */
    742 freedgenvbound = FALSE;
    743 for( i = 0 ; i < propdata->ngenvbounds; )
    744 {
    745 if( propdata->genvboundstore[i]->relaxonly )
    746 {
    747 SCIP_CALL( SCIPhashmapRemove(propdata->genvboundstore[i]->boundtype == SCIP_BOUNDTYPE_LOWER ? propdata->lbgenvbounds : propdata->ubgenvbounds,
    748 propdata->genvboundstore[i]->var) );
    749
    750 SCIP_CALL( freeGenVBound(scip, propdata->genvboundstore[i]) );
    751 if( i != propdata->ngenvbounds-1 )
    752 {
    753 propdata->genvboundstore[i] = propdata->genvboundstore[propdata->ngenvbounds-1];
    754 propdata->genvboundstore[i]->index = i;
    755 }
    756 --propdata->ngenvbounds;
    757
    758 propdata->issorted = FALSE;
    759 freedgenvbound = TRUE;
    760 }
    761 else
    762 ++i;
    763 }
    764
    765 if( freedgenvbound )
    766 {
    767 /* free componentsstart array */
    768 SCIP_CALL( freeComponentsData(scip, propdata) );
    769
    770 /* free starting indices data */
    771 SCIP_CALL( freeStartingData(scip, propdata) );
    772 }
    773
    774 /* disable genvbounds propagator */
    775 if( propdata->ngenvbounds == 0 )
    777
    778 return SCIP_OKAY;
    779}
    780
    781/** resolves propagation of lower bound on +/- left-hand side variable of a generalized variable bound */
    782static
    784 SCIP* scip, /**< SCIP data structure */
    785 GENVBOUND* genvbound, /**< genvbound data structure */
    786 SCIP_BDCHGIDX* bdchgidx, /**< the index of the bound change, representing the point of time where the change took place */
    787 SCIP_Real* boundval, /**< pointer to lower bound value on +/- left-hand side variable */
    788 SCIP_Bool* success /**< was the explanation succesful? */
    789 )
    790{
    791 SCIP_VAR* lhsvar;
    792 SCIP_VAR** vars;
    793 SCIP_Real minactivity;
    794 SCIP_Real tmpboundval;
    795 SCIP_Real slack;
    796 int nvars;
    797 int i;
    798
    799 assert(scip != NULL);
    800 assert(genvbound != NULL);
    801 assert(boundval != NULL);
    802 assert(success != NULL);
    803
    804 *success = FALSE;
    805
    806 /* get left-hand side variable */
    807 lhsvar = genvbound->var;
    808 assert(lhsvar != NULL);
    809
    810 /* get right-hand side variables */
    811 vars = genvbound->vars;
    812 nvars = genvbound->ncoefs;
    813 assert(vars != NULL);
    814
    815 /* if only the primal bound participates in the propagation, it is globally valid and should not be analyzed */
    816 assert(nvars > 0);
    817
    818 /* when resolving a propagation, bdchgidx is not NULL and boundval should be the bound change performed for the
    819 * left-hand side variable
    820 */
    821 assert(bdchgidx == NULL || genvbound->boundtype != SCIP_BOUNDTYPE_LOWER || SCIPisEQ(scip,
    822 SCIPvarIsIntegral(genvbound->var) ? SCIPfeasCeil(scip, *boundval) : *boundval, SCIPgetVarLbAtIndex(scip, lhsvar, bdchgidx, TRUE)));
    823 assert(bdchgidx == NULL || genvbound->boundtype != SCIP_BOUNDTYPE_UPPER || SCIPisEQ(scip,
    824 SCIPvarIsIntegral(genvbound->var) ? SCIPfeasCeil(scip, *boundval) : *boundval, -SCIPgetVarUbAtIndex(scip, lhsvar, bdchgidx, TRUE)));
    825
    826 /* when creating an initial conflict, bdchgidx is NULL and +/-boundval must exceed the upper/lower bound of the
    827 * left-hand side variable
    828 */
    829 assert(bdchgidx != NULL || genvbound->boundtype != SCIP_BOUNDTYPE_LOWER
    830 || SCIPisGT(scip, *boundval, SCIPvarGetUbLocal(lhsvar)));
    831 assert(bdchgidx != NULL || genvbound->boundtype != SCIP_BOUNDTYPE_UPPER
    832 || SCIPisGT(scip, *boundval, -SCIPvarGetLbLocal(lhsvar)));
    833
    834 SCIPdebugMsg(scip, "resolving genvbound propagation: lhs=%s<%s> >= boundval=%.15g\n",
    835 genvbound->boundtype == SCIP_BOUNDTYPE_LOWER ? "+" : "-", SCIPvarGetName(lhsvar), *boundval);
    836
    837 /* subtract constant terms from bound value */
    838 tmpboundval = *boundval;
    839 tmpboundval -= genvbound->cutoffcoef * getCutoffboundGenVBound(scip);
    840 tmpboundval -= genvbound->constant;
    841
    842 SCIPdebugMsg(scip, "subtracting constant terms gives boundval=%.15g\n", tmpboundval);
    843
    844 /* compute minimal activity; if bdchgidx is NULL, we create the initial conflict and use local bounds */
    845 minactivity = getGenVBoundsMinActivityConflict(scip, genvbound->vars, genvbound->coefs, genvbound->ncoefs, bdchgidx);
    846
    847 SCIPdebugMsg(scip, "minactivity of right-hand side is minactivity=%.15g\n", minactivity);
    848
    849 /* a genvbound might have been replaced since the propagation took place, hence we have to check that the current
    850 * genvbound can explain the propagation at the given bound change index; note that by now, with smaller cutoff
    851 * bound, we might even perform a stronger propagation
    852 */
    853 if( SCIPisLT(scip, minactivity, tmpboundval) )
    854 {
    855 SCIPdebugMsg(scip, "minactivity is too small to explain propagation; was genvbound replaced?\n");
    856 return SCIP_OKAY;
    857 }
    858
    859 /* if bdchgidx is NULL, i.e., we create the initial conflict, we should be able to explain the bound change */
    860 assert(SCIPisGE(scip, minactivity, tmpboundval));
    861
    862 slack = MAX(minactivity - tmpboundval, 0.0);
    863
    864 SCIPdebugMsg(scip, "slack=%.15g\n", slack);
    865
    866 /* add variables on the right-hand side as reasons for propagation */
    867 for( i = 0; i < nvars; i++ )
    868 {
    869 assert(vars[i] != NULL);
    870 assert(SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, TRUE), SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE)));
    871 assert(SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, TRUE), SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE)));
    872
    873 /* coefficient is positive */
    874 if( genvbound->coefs[i] > 0.0 )
    875 {
    876 SCIP_Real lbatindex;
    877 SCIP_Real conflictlb;
    878
    879 /* get bound at current bound change */
    880 lbatindex = SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, TRUE);
    881
    882 /* get bound already enforced by conflict set */
    883 conflictlb = SCIPgetConflictVarLb(scip, genvbound->vars[i]);
    884 assert(SCIPisGE(scip, conflictlb, SCIPvarGetLbGlobal(genvbound->vars[i])));
    885
    886 SCIPdebugMsg(scip, "lower bound of variable <%s> (genvbound->vars[%d]) in conflict set / at index is %.15g / %.15g\n",
    887 SCIPvarGetName(genvbound->vars[i]), i, conflictlb, lbatindex);
    888
    889 /* if bound is already enforced by conflict set we do not need to add the bound change; since we used the
    890 * tighest bound already when computing the initial minactivity, the slack is already correct
    891 */
    892 if( SCIPisLE(scip, lbatindex, conflictlb) )
    893 {
    894 SCIPdebugMsg(scip, "skipping lower bound of variable <%s> (genvbound->vars[%d]) already enforced in conflict set\n",
    895 SCIPvarGetName(genvbound->vars[i]), i);
    896 }
    897 else
    898 {
    899 SCIP_Real relaxedlb;
    900
    901 /* compute relaxed bound that would suffice to explain the bound change */
    902 relaxedlb = lbatindex - (slack / genvbound->coefs[i]);
    903 assert(relaxedlb <= lbatindex);
    904
    905 /* add variable to conflict set */
    906 SCIP_CALL( SCIPaddConflictRelaxedLb(scip, genvbound->vars[i], bdchgidx, relaxedlb ) );
    907
    908 /* get new bound of variable in conflict set; after possible bound widening in SCIPaddConflictLbRelaxed(),
    909 * it should be between conflictlb and lbatindex
    910 */
    911 relaxedlb = SCIPgetConflictVarLb(scip, genvbound->vars[i]);
    912 assert(SCIPisGE(scip, relaxedlb, conflictlb));
    913 assert(SCIPisLE(scip, relaxedlb, lbatindex));
    914
    915 /* update slack and ensure that its nonegative */
    916 slack -= genvbound->coefs[i] * (lbatindex - relaxedlb);
    917 slack = MAX(slack, 0.0);
    918
    919 SCIPdebugMsg(scip, "added lower bound of variable <%s> (genvbound->vars[%d]); new slack=%.15g\n",
    920 SCIPvarGetName(genvbound->vars[i]), i, slack);
    921 }
    922 }
    923 /* coefficient is negative */
    924 else
    925 {
    926 SCIP_Real ubatindex;
    927 SCIP_Real conflictub;
    928
    929 /* get bound at current bound change */
    930 ubatindex = SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, TRUE);
    931
    932 /* get bound already enforced by conflict set */
    933 conflictub = SCIPgetConflictVarUb(scip, genvbound->vars[i]);
    934 assert(SCIPisLE(scip, conflictub, SCIPvarGetUbGlobal(genvbound->vars[i])));
    935
    936 SCIPdebugMsg(scip, "upper bound of variable <%s> (genvbound->vars[%d]) in conflict set / at index is %.15g / %.15g\n",
    937 SCIPvarGetName(genvbound->vars[i]), i, conflictub, ubatindex);
    938
    939 /* if bound is already enforced by conflict set we do not need to add the bound change; since we used the
    940 * tighest bound already when computing the initial minactivity, the slack is already correct
    941 */
    942 if( SCIPisGE(scip, ubatindex, conflictub) )
    943 {
    944 SCIPdebugMsg(scip, "skipping upper bound of variable <%s> (genvbound->vars[%d]) already enforced in conflict set\n",
    945 SCIPvarGetName(genvbound->vars[i]), i);
    946 }
    947 else
    948 {
    949 SCIP_Real relaxedub;
    950
    951 /* compute relaxed bound that would suffice to explain the bound change */
    952 relaxedub = ubatindex - (slack / genvbound->coefs[i]);
    953 assert(relaxedub >= ubatindex);
    954
    955 /* add variable to conflict set */
    956 SCIP_CALL( SCIPaddConflictRelaxedUb(scip, genvbound->vars[i], bdchgidx, relaxedub ) );
    957
    958 /* get new bound of variable in conflict set; after possible bound widening in SCIPaddConflictUbRelaxed(),
    959 * it should be between conflictub and ubatindex
    960 */
    961 relaxedub = SCIPgetConflictVarUb(scip, genvbound->vars[i]);
    962 assert(SCIPisLE(scip, relaxedub, conflictub));
    963 assert(SCIPisGE(scip, relaxedub, ubatindex));
    964
    965 /* update slack and ensure that its nonegative */
    966 slack -= genvbound->coefs[i] * (ubatindex - relaxedub);
    967 slack = MAX(slack, 0.0);
    968
    969 SCIPdebugMsg(scip, "added upper bound of variable <%s> (genvbound->vars[%d]); new slack=%.15g\n",
    970 SCIPvarGetName(genvbound->vars[i]), i, slack);
    971 }
    972 }
    973 }
    974
    975 /* if slack is positive, return increased boundval */
    976 if( SCIPisPositive(scip, slack) )
    977 tmpboundval += slack;
    978
    979 /* add constant terms again */
    980 tmpboundval += genvbound->cutoffcoef * getCutoffboundGenVBound(scip);
    981 tmpboundval += genvbound->constant;
    982
    983 /* boundval should not have been decreased; if this happened nevertheless, maybe due to numerical errors, we quit
    984 * without success
    985 */
    986 if( SCIPisLT(scip, tmpboundval, *boundval) )
    987 {
    988 SCIPdebugMsg(scip, "boundval was reduced from %.15g to %.15g; propagation not resolved\n", *boundval, tmpboundval);
    989 return SCIP_OKAY;
    990 }
    991
    992 /* return widened boundval */
    993 *boundval = tmpboundval;
    994 *success = TRUE;
    995
    996 return SCIP_OKAY;
    997}
    998
    999/** create initial conflict */
    1000static
    1002 SCIP* scip, /**< SCIP data structure */
    1003 GENVBOUND* genvbound /**< genvbound data structure */
    1004 )
    1005{
    1006 SCIP_Bool success;
    1007
    1008 assert(scip != NULL);
    1009 assert(genvbound != NULL);
    1010
    1011 /* check if conflict analysis is applicable */
    1013 return SCIP_OKAY;
    1014
    1015 /* initialize conflict analysis */
    1017
    1018 /* left-hand side variable >= ... */
    1019 if( genvbound->boundtype == SCIP_BOUNDTYPE_LOWER )
    1020 {
    1021 SCIP_Real infeasthreshold;
    1023
    1024 /* get minimal right-hand side bound that leads to infeasibility; first try with a factor of 2 for robustness */
    1025 bound = REALABS(SCIPvarGetUbLocal(genvbound->var));
    1026 infeasthreshold = MAX(bound, 1.0) * 2 * SCIPfeastol(scip);
    1027 bound = SCIPvarGetUbLocal(genvbound->var) + infeasthreshold;
    1028
    1029 /* add right-hand side variables that force the lower bound of the left-hand side variable above its upper bound
    1030 * to conflict set
    1031 */
    1032 SCIP_CALL( resolveGenVBoundPropagation(scip, genvbound, NULL, &bound, &success) );
    1033 assert(!success || SCIPisFeasGT(scip, bound, SCIPvarGetUbLocal(genvbound->var)));
    1034
    1035 /* if infeasibility cannot be proven with the tighter bound, try with actual bound */
    1036 if( !success )
    1037 {
    1038 bound = REALABS(SCIPvarGetUbLocal(genvbound->var));
    1039 infeasthreshold = MAX(bound, 1.0) * SCIPfeastol(scip);
    1040 bound = SCIPvarGetUbLocal(genvbound->var) + infeasthreshold;
    1041
    1042 SCIP_CALL( resolveGenVBoundPropagation(scip, genvbound, NULL, &bound, &success) );
    1043 success = success && SCIPisFeasGT(scip, bound, SCIPvarGetUbLocal(genvbound->var));
    1044 }
    1045
    1046 /* compute upper bound on left-hand side variable that leads to infeasibility */
    1047 bound -= infeasthreshold;
    1048 success = success && SCIPisGE(scip, bound, SCIPvarGetUbLocal(genvbound->var));
    1049
    1050 /* initial reason could not be constructed, maybe due to numerics; do not apply conflict analysis */
    1051 if( !success )
    1052 {
    1053 SCIPdebugMsg(scip, "strange: could not create initial reason to start conflict analysis\n");
    1054 return SCIP_OKAY;
    1055 }
    1056
    1057 /* if bound is already enforced by conflict set we do not have to add it */
    1058 if( SCIPisGE(scip, bound, SCIPgetConflictVarUb(scip, genvbound->var)) )
    1059 {
    1060 SCIPdebugMsg(scip, "skipping upper bound of left-hand side variable <%s> already enforced in conflict set\n",
    1061 SCIPvarGetName(genvbound->var));
    1062 }
    1063 else
    1064 {
    1065 SCIPdebugMsg(scip, "adding upper bound of left-hand side variable <%s>\n", SCIPvarGetName(genvbound->var));
    1066
    1068 }
    1069 }
    1070 /* left-hand side variable <= ..., i.e., - left-hand side variable >= ... */
    1071 else
    1072 {
    1073 SCIP_Real infeasthreshold;
    1075
    1076 /* get minimal right-hand side bound that leads to infeasibility; try with a factor of 2 first for robustness */
    1077 bound = REALABS(SCIPvarGetLbLocal(genvbound->var));
    1078 infeasthreshold = MAX(bound, 1.0) * 2 * SCIPfeastol(scip);
    1079 bound = -SCIPvarGetLbLocal(genvbound->var) + infeasthreshold;
    1080
    1081 /* add right-hand side variables that force the upper bound of the left-hand side variable below its lower bound
    1082 * to conflict set
    1083 */
    1084 SCIP_CALL( resolveGenVBoundPropagation(scip, genvbound, NULL, &bound, &success) );
    1085 assert(!success || SCIPisFeasLT(scip, -bound, SCIPvarGetLbLocal(genvbound->var)));
    1086
    1087 /* if infeasibility cannot be proven with the tighter bound, try with actual bound */
    1088 if( !success )
    1089 {
    1090 bound = REALABS(SCIPvarGetLbLocal(genvbound->var));
    1091 infeasthreshold = MAX(bound, 1.0) * SCIPfeastol(scip);
    1092 bound = -SCIPvarGetLbLocal(genvbound->var) + infeasthreshold;
    1093
    1094 SCIP_CALL( resolveGenVBoundPropagation(scip, genvbound, NULL, &bound, &success) );
    1095 success = success && SCIPisFeasLT(scip, -bound, SCIPvarGetLbLocal(genvbound->var));
    1096 }
    1097
    1098 /* compute lower bound on left-hand side variable that leads to infeasibility */
    1099 bound = -bound + infeasthreshold;
    1100 success = success && SCIPisLE(scip, bound, SCIPvarGetLbLocal(genvbound->var));
    1101
    1102 /* initial reason could not be constructed, maybe due to numerics; do not apply conflict analysis */
    1103 if( !success )
    1104 {
    1105 SCIPdebugMsg(scip, "strange: could not create initial reason to start conflict analysis\n");
    1106 return SCIP_OKAY;
    1107 }
    1108
    1109 /* if bound is already enforced by conflict set we do not have to add it */
    1110 if( SCIPisLE(scip, bound, SCIPgetConflictVarLb(scip, genvbound->var)) )
    1111 {
    1112 SCIPdebugMsg(scip, "skipping lower bound of left-hand side variable <%s> already enforced in conflict set\n",
    1113 SCIPvarGetName(genvbound->var));
    1114 }
    1115 else
    1116 {
    1117 SCIPdebugMsg(scip, "adding lower bound of left-hand side variable <%s>\n", SCIPvarGetName(genvbound->var));
    1118
    1120 }
    1121 }
    1122
    1123 /* analyze the conflict */
    1125
    1126 return SCIP_OKAY;
    1127}
    1128
    1129/** apply propagation for one generalized variable bound; also if the left-hand side variable is locally fixed, we
    1130 * compute the right-hand side minactivity to possibly detect infeasibility
    1131 */
    1132static
    1134 SCIP* scip, /**< SCIP data structure */
    1135 SCIP_PROP* prop, /**< genvbounds propagator */
    1136 GENVBOUND* genvbound, /**< genvbound data structure */
    1137 SCIP_Bool global, /**< apply global bound changes? (global: true, local: false)*/
    1138 SCIP_RESULT* result, /**< result pointer */
    1139 int* nchgbds /**< counter to increment if bound was tightened */
    1140 )
    1141{
    1142 SCIP_Real boundval;
    1143 SCIP_Bool infeas;
    1144 SCIP_Bool tightened;
    1145
    1146 assert(scip != NULL);
    1147 assert(genvbound != NULL);
    1148 assert(genvbound->var != NULL);
    1149 assert(SCIPvarGetStatus(genvbound->var) != SCIP_VARSTATUS_MULTAGGR);
    1150 assert(result != NULL);
    1151 assert(*result != SCIP_DIDNOTRUN);
    1152
    1153 /* get bound value provided by genvbound */
    1154 boundval = getGenVBoundsBound(scip, genvbound, global);
    1155
    1156 if( SCIPisInfinity(scip, REALABS(boundval)) )
    1157 return SCIP_OKAY;
    1158
    1159#ifdef SCIP_DEBUG
    1160 {
    1161 SCIP_Real lb;
    1162 SCIP_Real ub;
    1163 SCIP_Real new_lb;
    1164 SCIP_Real new_ub;
    1165
    1166 lb = global ? SCIPvarGetLbGlobal(genvbound->var) : SCIPvarGetLbLocal(genvbound->var);
    1167 ub = global ? SCIPvarGetUbGlobal(genvbound->var) : SCIPvarGetUbLocal(genvbound->var);
    1168 new_lb = genvbound->boundtype == SCIP_BOUNDTYPE_LOWER ? boundval : lb;
    1169 new_ub = genvbound->boundtype == SCIP_BOUNDTYPE_UPPER ? boundval : ub;
    1170
    1171 SCIPdebugMsg(scip, " %s genvbound propagation for <%s>\n", global ?
    1172 "global" : "local", SCIPvarGetName(genvbound->var));
    1173 SCIPdebugMsg(scip, " genvbound: ");
    1174 printGenVBound(scip, genvbound);
    1175 SCIPdebugMsg(scip, " [%.15g,%.15g] -> [%.15g,%.15g]\n", lb, ub, new_lb, new_ub);
    1176 }
    1177#endif
    1178
    1179 /* tighten bound globally */
    1180 if( global || genvbound->ncoefs <= 0 )
    1181 {
    1182 if( genvbound->boundtype == SCIP_BOUNDTYPE_LOWER )
    1183 {
    1184 SCIP_CALL( SCIPtightenVarLbGlobal(scip, genvbound->var, boundval, FALSE, &infeas, &tightened) );
    1185 }
    1186 else
    1187 {
    1188 SCIP_CALL( SCIPtightenVarUbGlobal(scip, genvbound->var, boundval, FALSE, &infeas, &tightened) );
    1189 }
    1190 }
    1191 /* tighten bound locally and start conflict analysis in case of infeasibility; as inferinfo we pass the index of the
    1192 * genvbound that was used for propagation
    1193 */
    1194 else
    1195 {
    1196 if( genvbound->boundtype == SCIP_BOUNDTYPE_LOWER )
    1197 {
    1198 SCIP_CALL( SCIPinferVarLbProp(scip, genvbound->var, boundval, prop, genvbound->index, FALSE, &infeas, &tightened) );
    1199
    1200 /* initialize conflict analysis if infeasible */
    1201 if( infeas )
    1202 {
    1203 SCIPdebugMsg(scip, " -> lower bound tightening on variable <%s> led to infeasibility\n",
    1204 SCIPvarGetName(genvbound->var));
    1205
    1207 }
    1208 }
    1209 else
    1210 {
    1211 SCIP_CALL( SCIPinferVarUbProp(scip, genvbound->var, boundval, prop, genvbound->index, FALSE, &infeas, &tightened) );
    1212
    1213 /* initialize conflict analysis if infeasible */
    1214 if( infeas )
    1215 {
    1216 SCIPdebugMsg(scip, " -> upper bound tightening on variable <%s> led to infeasibility\n",
    1217 SCIPvarGetName(genvbound->var));
    1218
    1220 }
    1221 }
    1222 }
    1223
    1224 /* handle result */
    1225 if( infeas )
    1226 {
    1227 *result = SCIP_CUTOFF;
    1228 SCIPdebugMsg(scip, " cutoff!\n");
    1229 }
    1230 else if( tightened )
    1231 {
    1233 if( nchgbds != NULL )
    1234 ++(*nchgbds);
    1235 SCIPdebugMsg(scip, " tightened!\n");
    1236 }
    1237
    1238 return SCIP_OKAY;
    1239}
    1240
    1241#ifdef SCIP_DEBUG
    1242/** prints event data as debug message */
    1243static
    1244void printEventData(
    1245 SCIP_EVENTDATA* eventdata,
    1246 SCIP_BOUNDTYPE boundtype
    1247 )
    1248{
    1249 int i;
    1250
    1251 SCIPdebugMessage("event data: %s bound of <%s> tightened ==> start propagating at ",
    1252 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(eventdata->var));
    1253
    1254 /* if there is eventdata it should contain at least one starting index */
    1255 assert(eventdata->nstarts > 0);
    1256
    1257 for( i = 0; i < eventdata->nstarts; i++ )
    1258 {
    1259 SCIPdebugPrintf("(component %d, index %d) ", eventdata->startcomponents[i], eventdata->startindices[i]);
    1260 }
    1261 SCIPdebugPrintf("\n");
    1262}
    1263#endif
    1264
    1265/** frees event data */
    1266static
    1268 SCIP* scip, /**< SCIP data structure */
    1269 SCIP_EVENTDATA** eventdata /**< event data to be freed */
    1270 )
    1271{
    1272 assert(scip != NULL);
    1273 assert(eventdata != NULL);
    1274 assert(*eventdata != NULL);
    1275
    1276 SCIPfreeBlockMemoryArray(scip, &((*eventdata)->startcomponents), (*eventdata)->startindicessize);
    1277 SCIPfreeBlockMemoryArray(scip, &((*eventdata)->startindices), (*eventdata)->startindicessize);
    1278
    1279 (*eventdata)->startindicessize = 0;
    1280 (*eventdata)->nstarts = -1;
    1281 (*eventdata)->var = NULL;
    1282 (*eventdata)->prop = NULL;
    1283
    1284 SCIPfreeBlockMemory(scip, eventdata);
    1285
    1286 return SCIP_OKAY;
    1287}
    1288
    1289/** frees all eventdata stored */
    1290static
    1292 SCIP* scip, /**< SCIP data structure */
    1293 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
    1294 )
    1295{
    1296 int i;
    1297
    1298 assert(scip != NULL);
    1299 assert(propdata != NULL);
    1300
    1301 if( propdata->lbevents != NULL )
    1302 {
    1303 assert(propdata->ubevents != NULL);
    1304 assert(propdata->lbeventsmap != NULL);
    1305 assert(propdata->ubeventsmap != NULL);
    1306
    1307 SCIPhashmapFree(&(propdata->lbeventsmap));
    1308 SCIPhashmapFree(&(propdata->ubeventsmap));
    1309
    1310 for( i = propdata->nlbevents - 1; i >= 0; i-- )
    1311 {
    1312 SCIP_CALL( freeEventData(scip, &(propdata->lbevents[i])) );
    1313 }
    1314
    1315 for( i = propdata->nubevents - 1; i >= 0; i-- )
    1316 {
    1317 SCIP_CALL( freeEventData(scip, &(propdata->ubevents[i])) );
    1318 }
    1319
    1320 SCIPfreeBlockMemoryArray(scip, &(propdata->ubevents), propdata->nubevents);
    1321 SCIPfreeBlockMemoryArray(scip, &(propdata->lbevents), propdata->nlbevents);
    1322 propdata->nlbevents = -1;
    1323 propdata->nubevents = -1;
    1324 }
    1325
    1326 assert(propdata->lbevents == NULL);
    1327 assert(propdata->ubevents == NULL);
    1328 assert(propdata->lbeventsmap == NULL);
    1329 assert(propdata->ubeventsmap == NULL);
    1330 assert(propdata->nlbevents == -1);
    1331 assert(propdata->nubevents == -1);
    1332
    1333 return SCIP_OKAY;
    1334}
    1335
    1336/** drops all events caught by genvbounds propagator and frees their data */
    1337static
    1339 SCIP* scip, /**< SCIP data structure */
    1340 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
    1341 )
    1342{
    1343 int i;
    1344
    1345 SCIPdebugMsg(scip, "drop and free events\n");
    1346
    1347 assert(scip != NULL);
    1348 assert(propdata != NULL);
    1349 assert(propdata->eventhdlr != NULL);
    1350
    1351 if( propdata->lbevents != NULL )
    1352 {
    1353 assert(propdata->ubevents != NULL);
    1354 assert(propdata->nlbevents >= 0);
    1355 assert(propdata->nubevents >= 0);
    1356
    1357 for( i = propdata->nlbevents - 1; i >= 0; i-- )
    1358 {
    1359 /* drop event */
    1360 SCIP_CALL( SCIPdropVarEvent(scip, propdata->lbevents[i]->var, SCIP_EVENTTYPE_LBTIGHTENED, propdata->eventhdlr,
    1361 propdata->lbevents[i], -1) );
    1362 }
    1363
    1364 for( i = propdata->nubevents - 1; i >= 0; i-- )
    1365 {
    1366 /* drop event */
    1367 SCIP_CALL( SCIPdropVarEvent(scip, propdata->ubevents[i]->var, SCIP_EVENTTYPE_UBTIGHTENED, propdata->eventhdlr,
    1368 propdata->ubevents[i], -1) );
    1369 }
    1370
    1371 /* free event data */
    1372 SCIP_CALL( freeAllEventData(scip, propdata) );
    1373 }
    1374
    1375 assert(propdata->lbevents == NULL);
    1376 assert(propdata->ubevents == NULL);
    1377 assert(propdata->nlbevents == -1);
    1378 assert(propdata->nubevents == -1);
    1379
    1380 return SCIP_OKAY;
    1381}
    1382
    1383/** returns the corresponding event data entry in the corresponding array, if there is one; if not: allocates a new
    1384 * event data entry, stores it in the array and returns its adress
    1385 */
    1386static
    1388 SCIP* scip, /**< SCIP data structure */
    1389 SCIP_PROPDATA* propdata, /**< data of the genvbounds propagator */
    1390 SCIP_VAR* var, /**< variable */
    1391 SCIP_BOUNDTYPE boundtype, /**< type of bound */
    1392 SCIP_EVENTDATA** eventdata /**< event data to return */
    1393 )
    1394{
    1395 SCIP_HASHMAP* hashmap;
    1396
    1397 assert(scip != NULL);
    1398 assert(propdata != NULL);
    1399 assert(var != NULL);
    1400
    1401 hashmap = boundtype == SCIP_BOUNDTYPE_LOWER ? propdata->lbeventsmap : propdata->ubeventsmap;
    1402
    1403 if( SCIPhashmapExists(hashmap, var) )
    1404 *eventdata = (SCIP_EVENTDATA*) SCIPhashmapGetImage(hashmap, var);
    1405 else
    1406 {
    1407 /* set up new eventdata entry */
    1408 SCIP_CALL( SCIPallocBlockMemory(scip, eventdata) );
    1409 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*eventdata)->startcomponents), propdata->ncomponents) );
    1410 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*eventdata)->startindices), propdata->ncomponents) );
    1411 (*eventdata)->startindicessize = propdata->ncomponents;
    1412 (*eventdata)->nstarts = 0;
    1413 (*eventdata)->var = var;
    1414 (*eventdata)->prop = propdata->prop;
    1415
    1416 /* store event data in eventarray */
    1417 if( boundtype == SCIP_BOUNDTYPE_LOWER )
    1418 {
    1419 propdata->lbevents[propdata->nlbevents] = *eventdata;
    1420 propdata->nlbevents++;
    1421 }
    1422 else
    1423 {
    1424 propdata->ubevents[propdata->nubevents] = *eventdata;
    1425 propdata->nubevents++;
    1426 }
    1427
    1428 /* store hashmap entry */
    1429 SCIP_CALL( SCIPhashmapInsert(hashmap, var, (*eventdata)) );
    1430 }
    1431
    1432 return SCIP_OKAY;
    1433}
    1434
    1435/** adds an event to the event array lbevents (if boundtype == SCIP_BOUNDTYPE_LOWER) or ubevents (if boundtype ==
    1436 * SCIP_BOUNDTYPE_UPPER)
    1437 */
    1438static
    1440 SCIP* scip, /**< SCIP data structure */
    1441 SCIP_PROPDATA* propdata, /**< data of the genvbounds propagator */
    1442 SCIP_VAR* var, /**< variable thats event to be added */
    1443 int startindex, /**< starting index */
    1444 int startcomponent, /**< starting components index */
    1445 SCIP_BOUNDTYPE boundtype /**< type of bound */
    1446 )
    1447{
    1448 SCIP_EVENTDATA* eventdata;
    1449
    1450 assert(scip != NULL);
    1451 assert(propdata != NULL);
    1452 assert(var != NULL);
    1453 assert(startindex >= 0);
    1454 assert(startcomponent >= 0);
    1455
    1456 /* get eventdata entry */
    1457 SCIP_CALL( getEventData(scip, propdata, var, boundtype, &eventdata) );
    1458 assert(eventdata != NULL);
    1459
    1460 if( eventdata->nstarts > 0 && eventdata->startcomponents[eventdata->nstarts - 1] == startcomponent )
    1461 {
    1462 /* if there is already a starting index for startcomponent stored at the last entry of eventdata->startindices,
    1463 * it should be smaller; this relies on the implementation of setUpEvents(), calling addEventData() in
    1464 * topological order
    1465 */
    1466 assert(eventdata->startindices[eventdata->nstarts - 1] < startindex);
    1467 }
    1468 else
    1469 {
    1470 /* append starting information */
    1471 eventdata->startcomponents[eventdata->nstarts] = startcomponent;
    1472 eventdata->startindices[eventdata->nstarts] = startindex;
    1473
    1474 /* increase counter */
    1475 eventdata->nstarts++;
    1476 }
    1477
    1478 return SCIP_OKAY;
    1479}
    1480
    1481static
    1483 SCIP* scip, /**< SCIP data structure */
    1484 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
    1485 )
    1486{
    1487 int nprobvars;
    1488 int i;
    1489
    1490 assert(scip != NULL);
    1491 assert(propdata != NULL);
    1492 assert(propdata->eventhdlr != NULL);
    1493 assert(propdata->lbevents == NULL);
    1494 assert(propdata->ubevents == NULL);
    1495 assert(propdata->issorted);
    1496 assert(propdata->nlbevents == -1);
    1497 assert(propdata->nubevents == -1);
    1498
    1499 SCIPdebugMsg(scip, "set up events\n");
    1500
    1501 /* allocate lbevents, ubevents, and their hashmaps */
    1502 nprobvars = SCIPgetNVars(scip) + SCIPgetNFixedVars(scip);
    1503 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->lbevents), nprobvars) );
    1504 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->ubevents), nprobvars) );
    1505 SCIP_CALL( SCIPhashmapCreate(&(propdata->lbeventsmap), SCIPblkmem(scip), nprobvars) );
    1506 SCIP_CALL( SCIPhashmapCreate(&(propdata->ubeventsmap), SCIPblkmem(scip), nprobvars) );
    1507 propdata->nlbevents = 0;
    1508 propdata->nubevents = 0;
    1509
    1510 /* loop over all components of genvboundstore */
    1511 for( i = 0; i < propdata->ncomponents; i++ )
    1512 {
    1513 int j;
    1514
    1515 /* loop over all genvbounds in this component */
    1516 for( j = propdata->componentsstart[i]; j < propdata->componentsstart[i+1]; j++ ) /*lint !e679*/
    1517 {
    1518 GENVBOUND* genvbound;
    1519 int k;
    1520
    1521 assert(j < propdata->ngenvbounds);
    1522
    1523 genvbound = propdata->genvboundstore[j];
    1524 assert(genvbound != NULL);
    1525
    1526 /* loop over all coefficients in this genvbound */
    1527 for( k = 0; k < genvbound->ncoefs; k++ )
    1528 {
    1529 if( SCIPisPositive(scip, genvbound->coefs[k]) )
    1530 {
    1531 SCIP_CALL( addEventData(scip, propdata, genvbound->vars[k], j, i, SCIP_BOUNDTYPE_LOWER) );
    1532 }
    1533 else
    1534 {
    1535 SCIP_CALL( addEventData(scip, propdata, genvbound->vars[k], j, i, SCIP_BOUNDTYPE_UPPER) );
    1536 }
    1537 }
    1538 }
    1539 }
    1540
    1541 /* resize lbevents and ubevents array */
    1542 assert(propdata->nlbevents <= nprobvars);
    1543 assert(propdata->nubevents <= nprobvars);
    1544 if( propdata->nlbevents < nprobvars )
    1545 {
    1546 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(propdata->lbevents), nprobvars, propdata->nlbevents) );
    1547 }
    1548 if( propdata->nubevents < nprobvars )
    1549 {
    1550 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(propdata->ubevents), nprobvars, propdata->nubevents) );
    1551 }
    1552
    1553 /* resize and register lower bound events */
    1554 for( i = 0; i < propdata->nlbevents; i++ )
    1555 {
    1556 SCIP_EVENTDATA* eventdata = propdata->lbevents[i];
    1557
    1558 assert(eventdata != NULL);
    1559 assert(eventdata->nstarts > 0);
    1560 assert(eventdata->startcomponents != NULL);
    1561 assert(eventdata->startindices != NULL);
    1562
    1563 /* resize arrays stored in eventdata */
    1564 if( eventdata->startindicessize != eventdata->nstarts )
    1565 {
    1566 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(eventdata->startcomponents), eventdata->startindicessize, \
    1567 eventdata->nstarts) );
    1568 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(eventdata->startindices), eventdata->startindicessize, \
    1569 eventdata->nstarts) );
    1570 eventdata->startindicessize = eventdata->nstarts;
    1571 }
    1572
    1573 /* register event */
    1574 SCIP_CALL( SCIPcatchVarEvent(scip, eventdata->var, SCIP_EVENTTYPE_LBTIGHTENED, propdata->eventhdlr, eventdata, \
    1575 NULL) );
    1576 }
    1577
    1578 /* resize and register upper bound events */
    1579 for( i = 0; i < propdata->nubevents; i++ )
    1580 {
    1581 SCIP_EVENTDATA* eventdata = propdata->ubevents[i];
    1582
    1583 assert(eventdata != NULL);
    1584 assert(eventdata->nstarts > 0);
    1585 assert(eventdata->startcomponents != NULL);
    1586 assert(eventdata->startindices != NULL);
    1587
    1588 /* resize arrays stored in eventdata */
    1589 if( eventdata->startindicessize != eventdata->nstarts )
    1590 {
    1591 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(eventdata->startcomponents), eventdata->startindicessize, \
    1592 eventdata->nstarts) );
    1593 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(eventdata->startindices), eventdata->startindicessize, \
    1594 eventdata->nstarts) );
    1595 eventdata->startindicessize = eventdata->nstarts;
    1596 }
    1597 /* register event */
    1598 SCIP_CALL( SCIPcatchVarEvent(scip, eventdata->var, SCIP_EVENTTYPE_UBTIGHTENED, propdata->eventhdlr, eventdata,
    1599 NULL) );
    1600 }
    1601
    1602 return SCIP_OKAY;
    1603}
    1604
    1605/** performs a topological sort on genvboundstore array
    1606 *
    1607 * The genvbounds graph is defined as follows: Given two genvbounds
    1608 *
    1609 * (genvbound1) c1 * x_i1 >= RHS1
    1610 *
    1611 * and
    1612 *
    1613 * (genvbound2) c2 * x_i2 >= RHS2,
    1614 *
    1615 * there is an arc from genvbound1 to genvbound2 iff c1 = +1 and x_i1 appears with positive coefficient in RHS2 or
    1616 * c1 = -1 and x_i1 appears with negative coefficient in RHS2; in this case, a bound change of x_i1 deduced from
    1617 * genvbound1 improves genvbound2's minactivity in RHS2.
    1618 *
    1619 * The method computes the strongly connected components and sorts them topologically. The order of the nodes in an
    1620 * strongly connected component is arbitrary.
    1621 */
    1622static
    1624 SCIP* scip, /**< SCIP data structure */
    1625 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
    1626 )
    1627{
    1628 GENVBOUND** genvboundssorted; /* array to store the sorted genvbounds */
    1629 SCIP_DIGRAPH* graph;
    1630 int* strongcomponents;
    1631 int* strongcompstartidx;
    1632 int sortedindex;
    1633 int i;
    1634
    1635 assert(scip != NULL);
    1636 assert(propdata != NULL);
    1637 assert(propdata->componentsstart == NULL);
    1638
    1639 SCIPdebugMsg(scip, "(re-)sort genvbounds topologically\n");
    1640
    1641 /* create digraph */
    1642 SCIP_CALL( SCIPcreateDigraph(scip, &graph, propdata->ngenvbounds) );
    1643
    1644 /* add outgoing arcs for each genvbound */
    1645 for( i = 0; i < propdata->ngenvbounds; i++ )
    1646 {
    1647 GENVBOUND* genvbound;
    1648 int j;
    1649
    1650 assert(i < propdata->ngenvbounds);
    1651
    1652 genvbound = propdata->genvboundstore[i];
    1653
    1654 for( j = 0; j < genvbound->ncoefs; j++ )
    1655 {
    1656 if( SCIPisPositive(scip, genvbound->coefs[j]) &&
    1657 SCIPhashmapExists(propdata->lbgenvbounds, genvbound->vars[j]) )
    1658 {
    1659 int from = ((GENVBOUND*) SCIPhashmapGetImage(propdata->lbgenvbounds, genvbound->vars[j]))->index;
    1660 SCIP_CALL( SCIPdigraphAddArc(graph, from, i, NULL) );
    1661 }
    1662 else if( SCIPisNegative(scip, genvbound->coefs[j]) &&
    1663 SCIPhashmapExists(propdata->ubgenvbounds, genvbound->vars[j]) )
    1664 {
    1665 int from = ((GENVBOUND*) SCIPhashmapGetImage(propdata->ubgenvbounds, genvbound->vars[j]))->index;
    1666 SCIP_CALL( SCIPdigraphAddArc(graph, from, i, NULL) );
    1667 }
    1668 }
    1669 }
    1670
    1671 /* perform the topological sort */
    1672 SCIP_CALL( SCIPdigraphComputeUndirectedComponents(graph, 1, NULL, &(propdata->ncomponents)) );
    1674 assert(SCIPdigraphGetNComponents(graph) == propdata->ncomponents);
    1675
    1676 /* allocate memory for genvboundssorted and componentsstart array */
    1677 SCIP_CALL( SCIPallocBufferArray(scip, &genvboundssorted, propdata->ngenvbounds) );
    1678 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->componentsstart), propdata->ncomponents + 1) );
    1679 propdata->componentsstartsize = propdata->ncomponents + 1;
    1680
    1681 /* allocate memory for strong component arrays */
    1682 SCIP_CALL( SCIPallocBufferArray(scip, &strongcomponents, SCIPdigraphGetNNodes(graph)) ); /*lint !e666*/
    1683 SCIP_CALL( SCIPallocBufferArray(scip, &strongcompstartidx, SCIPdigraphGetNNodes(graph) + 1) ); /*lint !e666*/
    1684
    1685 /* compute sorted genvbounds array, fill componentsstart array */
    1686 sortedindex = 0;
    1687 propdata->componentsstart[propdata->ncomponents] = propdata->ngenvbounds;
    1688 for( i = 0; i < propdata->ncomponents; i++ )
    1689 {
    1690 int j;
    1691 int *nodes;
    1692 int nnodes;
    1693 int nstrongcomponents;
    1694
    1695 SCIPdigraphGetComponent(graph, i, &nodes, &nnodes);
    1696 propdata->componentsstart[i] = sortedindex;
    1697
    1698 /* compute the strong components of the i-th undirected component */
    1699 if( nnodes > 2 )
    1700 {
    1701 SCIP_CALL( SCIPdigraphComputeDirectedComponents(graph, i, strongcomponents, strongcompstartidx,
    1702 &nstrongcomponents) );
    1703
    1704 for( j = 0; j < nnodes; ++j )
    1705 {
    1706 int node;
    1707
    1708 /* take the nodes at the end of the strong components array first to respect the topological
    1709 * order of the different strong components
    1710 */
    1711 node = strongcomponents[nnodes - j - 1];
    1712
    1713 assert(node < propdata->ngenvbounds);
    1714 genvboundssorted[sortedindex] = propdata->genvboundstore[node];
    1715 sortedindex++;
    1716 }
    1717 }
    1718 else
    1719 {
    1720 for( j = 0; j < nnodes; j++ )
    1721 {
    1722 assert(nodes[j] < propdata->ngenvbounds);
    1723 genvboundssorted[sortedindex] = propdata->genvboundstore[nodes[j]];
    1724 sortedindex++;
    1725 }
    1726 }
    1727 }
    1728 assert(sortedindex == propdata->ngenvbounds);
    1729
    1730 /* copy sorted genvbounds into genvboundstore */
    1731 for( i = 0; i < propdata->ngenvbounds; i++ )
    1732 {
    1733 assert(genvboundssorted[i] != NULL);
    1734
    1735 propdata->genvboundstore[i] = genvboundssorted[i];
    1736 propdata->genvboundstore[i]->index = i;
    1737 }
    1738
    1739 /* free strong component arrays */
    1740 SCIPfreeBufferArray(scip, &strongcompstartidx);
    1741 SCIPfreeBufferArray(scip, &strongcomponents);
    1742
    1743 SCIPfreeBufferArray(scip, &(genvboundssorted));
    1744
    1745 /* free digraph */
    1746 SCIPdigraphFree(&graph);
    1747
    1748 /* remember genvboundstore as sorted */
    1749 propdata->issorted = TRUE;
    1750
    1751#ifdef SCIP_DEBUG
    1752 SCIPdebugMsg(scip, "genvbounds got: %d\n", propdata->ngenvbounds);
    1753 for( i = 0; i < propdata->ncomponents; i++ )
    1754 {
    1755 int j;
    1756
    1757 SCIPdebugMsg(scip, "{\n");
    1758
    1759 for( j = propdata->componentsstart[i]; j < propdata->componentsstart[i+1]; j++ )
    1760 {
    1761 SCIPdebugMsg(scip, " [%d] ", j);
    1762 printGenVBound(scip, propdata->genvboundstore[j]);
    1763 }
    1764
    1765 SCIPdebugMsg(scip, "}\n");
    1766 }
    1767#endif
    1768
    1769 return SCIP_OKAY;
    1770}
    1771
    1772/** apply propagation of generalized variable bounds */
    1773static
    1775 SCIP* scip, /**< SCIP data structure */
    1776 SCIP_PROP* prop, /**< genvbounds propagator */
    1777 SCIP_Bool global, /**< use global variable bounds for propagation? */
    1778 SCIP_RESULT* result, /**< result pointer */
    1779 int* nchgbds /**< counter to increase by the number of changed bounds */
    1780 )
    1781{
    1782 SCIP_PROPDATA* propdata;
    1783 int* startingcomponents;
    1784 int* startingindices;
    1785 int nindices;
    1786 int i;
    1787
    1788 SCIPdebugMsg(scip, "applying %s genvbound propagation in depth %d\n", global ?
    1789 "global" : "local", SCIPgetDepth(scip));
    1790
    1791 assert(scip != NULL);
    1792 assert(prop != NULL);
    1793 assert(result != NULL);
    1794
    1795 propdata = SCIPpropGetData(prop);
    1796 assert(propdata != NULL);
    1797 assert(propdata->genvboundstore != NULL);
    1798
    1799 if( *result == SCIP_DIDNOTRUN )
    1800 *result = SCIP_DIDNOTFIND;
    1801
    1802 /* if the genvbounds are not sorted, i.e. if root node processing has not been finished, yet, we just propagate in
    1803 * the order in which they have been added to genvboundstore
    1804 */
    1805 if( !propdata->issorted )
    1806 {
    1807 int j;
    1808
    1809 assert(!propdata->sort || SCIPinProbing(scip) || SCIPgetDepth(scip) == 0);
    1810
    1811 for( j = 0; j < propdata->ngenvbounds && *result != SCIP_CUTOFF; j++ )
    1812 {
    1813 if( ! SCIPvarIsActive(propdata->genvboundstore[j]->var) )
    1814 {
    1815 /**@todo resolve multiaggregation in exitpre */
    1816 }
    1817 else
    1818 {
    1819 SCIPdebugMsg(scip, "applying genvbound with index %d (unsorted mode)\n", j);
    1820 SCIP_CALL( applyGenVBound(scip, prop, propdata->genvboundstore[j], global, result, nchgbds) );
    1821 }
    1822 }
    1823
    1824 return SCIP_OKAY;
    1825 }
    1826
    1827 /* otherwise, we propagate only components affected by the latest bound changes */
    1828 startingcomponents = global ? propdata->gstartcomponents : propdata->startcomponents;
    1829 startingindices = global ? propdata->gstartindices : propdata->startindices;
    1830 nindices = global ? propdata->ngindices : propdata->nindices;
    1831
    1832 for( i = 0; i < nindices && *result != SCIP_CUTOFF; i++ )
    1833 {
    1834 int j;
    1835
    1836 SCIPdebugMsg(scip, "starting in component %d at index %d\n", startingcomponents[i], startingindices[i]);
    1837 for( j = startingindices[i]; j < propdata->componentsstart[startingcomponents[i] + 1] &&
    1838 *result != SCIP_CUTOFF; j++ ) /*lint !e679*/
    1839 {
    1840 assert(j < propdata->ngenvbounds);
    1841
    1842 if( ! SCIPvarIsActive(propdata->genvboundstore[j]->var) )
    1843 {
    1844 /**@todo resolve multiaggregation in exitpre */
    1845 }
    1846 else
    1847 {
    1848 SCIPdebugMsg(scip, "applying genvbound with index %d, component %d\n", j, startingcomponents[i]);
    1849 SCIP_CALL( applyGenVBound(scip, prop, propdata->genvboundstore[j], global, result, nchgbds) );
    1850 }
    1851 }
    1852 }
    1853
    1854 /* we dont want to run again caused by this starting data */
    1855 if( !global )
    1856 {
    1858 }
    1859
    1860 return SCIP_OKAY;
    1861}
    1862
    1863/** initialize propagator data */
    1864static
    1866 SCIP* scip, /**< SCIP data structure */
    1867 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
    1868 )
    1869{
    1870 int nprobvars;
    1871
    1872 assert(scip != NULL);
    1873 assert(propdata != NULL);
    1874 assert(propdata->eventhdlr != NULL);
    1875 assert(propdata->ngenvbounds == -1);
    1876
    1877 SCIPdebugMsg(scip, "init propdata\n");
    1878
    1879 nprobvars = SCIPgetNVars(scip);
    1880
    1881 /* init genvboundstore */
    1882 propdata->genvboundstoresize = 2 * nprobvars;
    1883 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->genvboundstore), propdata->genvboundstoresize) );
    1884 BMSclearMemoryArray(propdata->genvboundstore, propdata->genvboundstoresize);
    1885 propdata->ngenvbounds = 0;
    1886
    1887 /* init genvboundstore hashmaps */
    1888 SCIP_CALL( SCIPhashmapCreate(&(propdata->lbgenvbounds), SCIPblkmem(scip), nprobvars) );
    1889 SCIP_CALL( SCIPhashmapCreate(&(propdata->ubgenvbounds), SCIPblkmem(scip), nprobvars) );
    1890
    1891 return SCIP_OKAY;
    1892}
    1893
    1894/** adds a new genvbound to genvboundstore array and sets a hashmap entry */
    1895static
    1897 SCIP* scip, /**< SCIP data structure */
    1898 SCIP_PROP* prop, /**< genvbounds propagator */
    1899 SCIP_PROPDATA* propdata, /**< data of the genvbounds propagator */
    1900 GENVBOUND* genvbound /**< genvbound to be added */
    1901 )
    1902{
    1903 SCIP_HASHMAP* hashmap;
    1904
    1905 assert(scip != NULL);
    1906 assert(propdata != NULL);
    1907 assert(genvbound != NULL);
    1908 assert(getGenVBound(scip, propdata, genvbound->var, genvbound->boundtype) == NULL);
    1909
    1910 hashmap = genvbound->boundtype == SCIP_BOUNDTYPE_LOWER ? propdata->lbgenvbounds : propdata->ubgenvbounds;
    1911
    1912 /* e.g., during presolving after a restart, new variables might have been created; in this case, we need to extend
    1913 * the genvboundstore; the new size may even exceed 2*SCIPgetNVars() if we have genvbounds with nonactive left-hand
    1914 * side variables
    1915 */
    1916 assert(propdata->ngenvbounds <= propdata->genvboundstoresize);
    1917 if( propdata->ngenvbounds == propdata->genvboundstoresize )
    1918 {
    1919 int oldsize = propdata->genvboundstoresize;
    1920 propdata->genvboundstoresize = 2*propdata->genvboundstoresize + 1;
    1921 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(propdata->genvboundstore), oldsize, propdata->genvboundstoresize) );
    1922 }
    1923
    1924 /* enable genvbounds propagator */
    1925 if( propdata->ngenvbounds == 0 )
    1926 SCIPpropSetTimingmask(prop, propdata->inittiming);
    1927
    1928 /* new index is propdata->ngenvbounds */
    1929 SCIP_CALL( SCIPhashmapInsert(hashmap, genvbound->var, genvbound) );
    1930 propdata->genvboundstore[propdata->ngenvbounds] = genvbound;
    1931 genvbound->index = propdata->ngenvbounds;
    1932 propdata->ngenvbounds++;
    1933
    1934 assert(propdata->ngenvbounds <= propdata->genvboundstoresize);
    1935
    1936 return SCIP_OKAY;
    1937}
    1938
    1939/** runs propagation routine */
    1940static
    1942 SCIP* scip, /**< SCIP data structure */
    1943 SCIP_PROPDATA* propdata, /**< data of the genvbounds propagator */
    1944 SCIP_RESULT* result, /**< result pointer */
    1945 SCIP_Bool local, /**< should local propagation be applied? */
    1946 int* nchgbds /**< counter to increase by the number of changed bounds */
    1947 )
    1948{
    1949 assert(scip != NULL);
    1950 assert(propdata != NULL);
    1951 assert(propdata->prop != NULL);
    1952 assert(result != NULL);
    1953
    1954 /* we only sort after the root node is finished; this avoids having to sort again after adding more genvbounds; if
    1955 * the genvbounds are not sorted, we will simply propagate all of them in the order given
    1956 */
    1957 if( propdata->sort && !SCIPinProbing(scip) && SCIPgetDepth(scip) > 0 )
    1958 {
    1959 if( !propdata->issorted )
    1960 {
    1961 *result = SCIP_DIDNOTFIND;
    1962
    1963 SCIPdebugMsg(scip, "genvbounds are not sorted\n");
    1964
    1965 /* drop and free old events */
    1966 SCIP_CALL( dropAndFreeEvents(scip, propdata) );
    1967
    1968 /* free old starting data */
    1969 SCIP_CALL( freeStartingData(scip, propdata) );
    1970
    1971 /* free sorted components data */
    1972 SCIP_CALL( freeComponentsData(scip, propdata) );
    1973
    1974 /* sort genvbounds */
    1975 SCIP_CALL( sortGenVBounds(scip, propdata) );
    1976
    1977 /* create starting data */
    1978 SCIP_CALL( createStartingData(scip, propdata) );
    1979
    1980 /* fill global starting data */
    1982 }
    1983
    1984 /* set up new events to catch (if not done so far) */
    1985 if( propdata->lbevents == NULL )
    1986 {
    1987 SCIP_CALL( setUpEvents(scip, propdata) );
    1988 }
    1989 }
    1990
    1991 /* apply global propagation if primal bound has improved */
    1992 if( propdata->global && SCIPgetDepth(scip) > 0 && SCIPisFeasLT(scip, SCIPgetCutoffbound(scip), propdata->lastcutoff) )
    1993 {
    1994 if( propdata->ngindices > 0 )
    1995 {
    1996 SCIP_CALL( applyGenVBounds(scip, propdata->prop, TRUE, result, nchgbds) );
    1997 assert(*result != SCIP_DIDNOTRUN);
    1998 }
    1999
    2000 /* within the tree, the objective function should not change anymore, hence the cutoff bound should be a stable
    2001 * point of reference
    2002 */
    2003 propdata->lastcutoff = SCIPgetCutoffbound(scip);
    2004 }
    2005
    2006 /* apply local propagation if allowed */
    2007 if( local && *result != SCIP_CUTOFF )
    2008 {
    2009 /* check if local propagation in root node is allowed */
    2010 if( SCIPgetDepth(scip) > 0 || propdata->propinrootnode )
    2011 {
    2012 /* if genvbounds are already sorted, check if bound change events were caught; otherwise apply all genvbounds */
    2013 if( !propdata->issorted
    2014 || ( SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) == propdata->lastnodenumber && propdata->nindices > 0 ) )
    2015 {
    2016 SCIP_CALL( applyGenVBounds(scip, propdata->prop, FALSE, result, nchgbds) );
    2017 assert(*result != SCIP_DIDNOTRUN);
    2018 }
    2019 }
    2020 }
    2021
    2022 return SCIP_OKAY;
    2023}
    2024
    2025/* adds all genvbounds in the genvboundstore as constraints to the problem; afterwards clears the genvboundstore */
    2026static
    2028 SCIP* scip, /**< SCIP data structure */
    2029 SCIP_PROP* prop, /**< genvbounds propagator */
    2030 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
    2031 )
    2032{
    2033 int i;
    2034
    2035 assert(scip != NULL);
    2036 assert(propdata != NULL);
    2037 assert(propdata->propasconss);
    2038
    2039 /* ensure that the cutoffboundvar is available */
    2040 if( propdata->cutoffboundvar == NULL )
    2041 {
    2042 SCIP_Real ub;
    2043 char name[16];
    2044
    2045 /* set the upper bound to the best primal value in the original problem */
    2047
    2048 SCIPdebugMsg(scip, "initialize cutoffboundvar with UB = %e\n", ub);
    2049
    2050 (void) SCIPsnprintf(name, 16, "cutoffboundvar");
    2051 SCIP_CALL( SCIPcreateVarBasic(scip, &propdata->cutoffboundvar, name, -SCIPinfinity(scip), ub, 0.0, SCIP_VARTYPE_CONTINUOUS) );
    2052 SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, propdata->cutoffboundvar) );
    2053
    2054 SCIP_CALL( SCIPaddVar(scip, propdata->cutoffboundvar) );
    2055
    2056 /* lock the variable because it should not be subject to dual presolving reductions; because we create the
    2057 * linear constraints as non-check constraints, the cutoffboundvar will not be locked by the linear constraint
    2058 * handler
    2059 */
    2060 SCIP_CALL( SCIPaddVarLocksType(scip, propdata->cutoffboundvar, SCIP_LOCKTYPE_MODEL, 1, 1) );
    2061 }
    2062
    2063 assert(propdata->cutoffboundvar != NULL);
    2064
    2065 /* now iterate over all genvbounds in the store and construct a linear constraint for each of them */
    2066 for( i = 0; i < propdata->ngenvbounds; ++i )
    2067 {
    2068 GENVBOUND* genvbound;
    2069 SCIP_CONS* cons;
    2070 SCIP_VAR** vars;
    2071 SCIP_Real* vals;
    2072 char name[SCIP_MAXSTRLEN];
    2073 int nvars;
    2074 int j;
    2075
    2076 genvbound = propdata->genvboundstore[i];
    2077 assert(genvbound != NULL);
    2078
    2079 nvars = genvbound->ncoefs + 2;
    2080 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    2081 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
    2082
    2083 SCIPdebugMsgPrint(scip, "add cons: ");
    2084
    2085 /* copy the coefs/vars array */
    2086 for( j = 0; j < genvbound->ncoefs; j++ )
    2087 {
    2088 vars[j] = genvbound->vars[j];
    2089 vals[j] = genvbound->coefs[j];
    2090 SCIPdebugMsgPrint(scip, "%e%s + ", vals[j], SCIPvarGetName(vars[j]));
    2091 }
    2092
    2093 /* add the variable and the coefficient of the genvbound */
    2094 vars[genvbound->ncoefs] = genvbound->var;
    2095 vals[genvbound->ncoefs] = (genvbound->boundtype == SCIP_BOUNDTYPE_LOWER) ? -1.0 : 1.0;
    2096
    2097 SCIPdebugMsgPrint(scip, "%e%s + ", vals[genvbound->ncoefs], SCIPvarGetName(vars[genvbound->ncoefs]));
    2098
    2099 /* add cutoffcoef * cutoffboundvar */
    2100 vars[genvbound->ncoefs + 1] = propdata->cutoffboundvar;
    2101 vals[genvbound->ncoefs + 1] = genvbound->cutoffcoef;
    2102
    2103 SCIPdebugMsgPrint(scip, "%e%s <= %e\n", vals[genvbound->ncoefs + 1], SCIPvarGetName(vars[genvbound->ncoefs + 1]), -1.0*genvbound->constant);
    2104
    2105 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "genvbound_cons%d", genvbound->index);
    2106
    2107 /* create linear constraint with only propagate flag as TRUE */
    2108 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, name, nvars, vars, vals, -SCIPinfinity(scip), -genvbound->constant,
    2110
    2111 SCIP_CALL( SCIPaddCons(scip, cons) );
    2112 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    2113
    2114 /* free memory */
    2115 SCIPfreeBufferArray(scip, &vars);
    2116 SCIPfreeBufferArray(scip, &vals);
    2117 }
    2118
    2119 /* now delete all genvbounds in the genvboundstore */
    2120 if( propdata->genvboundstore != NULL )
    2121 {
    2122 /* disable genvbounds propagator */
    2123 if( propdata->ngenvbounds >= 1 )
    2125
    2126 for( i = propdata->ngenvbounds - 1; i >= 0; i-- )
    2127 {
    2128 SCIP_CALL( freeGenVBound(scip, propdata->genvboundstore[i]) );
    2129 }
    2130
    2131 /* free genvboundstore hashmaps */
    2132 SCIPhashmapFree(&(propdata->lbgenvbounds));
    2133 SCIPhashmapFree(&(propdata->ubgenvbounds));
    2134
    2135 /* drop and free all events */
    2136 SCIP_CALL( dropAndFreeEvents(scip, propdata) );
    2137
    2138 /* free componentsstart array */
    2139 SCIP_CALL( freeComponentsData(scip, propdata) );
    2140
    2141 /* free starting indices data */
    2142 SCIP_CALL( freeStartingData(scip, propdata) );
    2143
    2144 SCIPfreeBlockMemoryArray(scip, &(propdata->genvboundstore), propdata->genvboundstoresize);
    2145 propdata->genvboundstore = NULL;
    2146 propdata->genvboundstoresize = 0;
    2147 propdata->ngenvbounds = 0;
    2148 }
    2149
    2150 return SCIP_OKAY;
    2151}
    2152
    2153
    2154
    2155/*
    2156 * Public methods
    2157 */
    2158
    2159/** adds a generalized variable bound to the genvbounds propagator; if there is already a genvbound for the bound
    2160 * "boundtype" of variable "var", it will be replaced
    2161 */
    2163 SCIP* scip, /**< SCIP data structure */
    2164 SCIP_PROP* genvboundprop, /**< genvbound propagator */
    2165 SCIP_VAR** vars, /**< array of RHSs variables */
    2166 SCIP_VAR* var, /**< LHSs variable */
    2167 SCIP_Real* coefs, /**< array of coefficients for the RHSs variables */
    2168 int ncoefs, /**< size of coefs array */
    2169 SCIP_Real coefcutoffbound, /**< nonpositive value of the cutoff bounds multiplier */
    2170 SCIP_Real constant, /**< constant term */
    2171 SCIP_BOUNDTYPE boundtype /**< type of bound provided by the genvbound */
    2172 )
    2173{
    2174 /**@todo in debug mode: check if genvbound is nontrivial */
    2175
    2176 SCIP_PROPDATA* propdata;
    2177 GENVBOUND* genvbound;
    2178 SCIP_Bool newgenvbound;
    2179 int i;
    2180
    2181 assert(scip != NULL);
    2182 assert(genvboundprop != NULL);
    2183 assert(strcmp(SCIPpropGetName(genvboundprop), PROP_NAME) == 0);
    2184 assert(vars != NULL);
    2185 assert(var != NULL);
    2186 assert(coefs != NULL);
    2187 assert(ncoefs >= 0);
    2188 assert(coefcutoffbound <= 0.0);
    2189 assert(!SCIPisInfinity(scip, -constant));
    2190
    2191 if( ncoefs < 0 || coefcutoffbound > 0.0 || SCIPisInfinity(scip, -constant) )
    2192 {
    2193 SCIPerrorMessage("cannot create generalized variable bound from invalid data\n");
    2194 return SCIP_INVALIDDATA;
    2195 }
    2196
    2197 propdata = SCIPpropGetData(genvboundprop);
    2198 assert(propdata != NULL);
    2199
    2200 /* initialize propdata if not done yet */
    2201 if( propdata->genvboundstore == NULL )
    2202 {
    2203 SCIP_CALL( initPropdata(scip, propdata) );
    2204 }
    2205
    2206 genvbound = getGenVBound(scip, propdata, var, boundtype);
    2207 newgenvbound = (genvbound == NULL);
    2208
    2209 /* release previous variables */
    2210 if( !newgenvbound )
    2211 {
    2212 for( i = 0; i < genvbound->ncoefs; ++i )
    2213 {
    2214 assert(genvbound->vars[i] != NULL);
    2215 SCIP_CALL( SCIPreleaseVar(scip, &(genvbound->vars[i])) );
    2216 }
    2217 }
    2218
    2219 /* check if there already is a genvbound corresponding to this bound, freeing its data and overwriting it */
    2220 if( !newgenvbound && genvbound->ncoefs < ncoefs )
    2221 {
    2222 /* do not realloc since we do not want to keep and possibly copy the old entries */
    2223 SCIPfreeBlockMemoryArray(scip, &(genvbound->coefs), genvbound->coefssize);
    2224 SCIPfreeBlockMemoryArray(scip, &(genvbound->vars), genvbound->coefssize);
    2225
    2226 /* allocate and copy arrays in genvbound */
    2227 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(genvbound->coefs), coefs, ncoefs) );
    2228 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(genvbound->vars), vars, ncoefs) );
    2229 genvbound->coefssize = ncoefs;
    2230 }
    2231 else if( !newgenvbound && genvbound->ncoefs == ncoefs )
    2232 {
    2233 /* just update entries */
    2234 for( i = 0; i < ncoefs; i++ )
    2235 {
    2236 genvbound->coefs[i] = coefs[i];
    2237 genvbound->vars[i] = vars[i];
    2238 }
    2239 }
    2240 else if( !newgenvbound && genvbound->ncoefs > ncoefs )
    2241 {
    2242 /* reallocate memory for arrays in genvbound to free unused memory */
    2243 if( genvbound->coefssize < ncoefs )
    2244 {
    2245 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(genvbound->coefs), genvbound->coefssize, ncoefs) );
    2246 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(genvbound->vars), genvbound->coefssize, ncoefs) );
    2247 genvbound->coefssize = ncoefs;
    2248 }
    2249
    2250 /* update entries */
    2251 for( i = 0; i < ncoefs; i++ )
    2252 {
    2253 genvbound->coefs[i] = coefs[i];
    2254 genvbound->vars[i] = vars[i];
    2255 }
    2256 }
    2257 else if( newgenvbound )
    2258 {
    2259 /* allocate memory for genvbound data */
    2260 SCIP_CALL( SCIPallocBlockMemory(scip, &genvbound) );
    2261
    2262 /* allocate and copy arrays in genvbound */
    2263 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(genvbound->coefs), coefs, ncoefs) );
    2264 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(genvbound->vars), vars, ncoefs) );
    2265 genvbound->coefssize = ncoefs;
    2266 }
    2267
    2268 /* set up data for genvbound */
    2269 genvbound->boundtype = boundtype;
    2270 genvbound->var = var;
    2271 genvbound->ncoefs = ncoefs;
    2272 genvbound->constant = constant;
    2273 genvbound->relaxonly = SCIPvarIsRelaxationOnly(genvbound->var);
    2274
    2275 /* capture variables and check for relax-only vars */
    2276 for( i = 0; i < genvbound->ncoefs; ++i )
    2277 {
    2278 assert(genvbound->vars[i] != NULL);
    2279 SCIP_CALL( SCIPcaptureVar(scip, genvbound->vars[i]) );
    2280 if( SCIPvarIsRelaxationOnly(genvbound->vars[i]) )
    2281 genvbound->relaxonly = TRUE;
    2282 }
    2283 if( newgenvbound )
    2284 {
    2285 assert(genvbound->var != NULL);
    2286 SCIP_CALL( SCIPcaptureVar(scip, genvbound->var) );
    2287 }
    2288
    2289 /* the cutoff bound is valid w.r.t. the current objective function in the transformed problem; during presolving,
    2290 * however, the objective function can change (e.g., when a variable is fixed, its contribution in the objective
    2291 * is subtracted from the cutoff bound and added to the objective offset); we solve this by transforming the
    2292 * contribution of the cutoff bound in the generalized variable bound to the original problem as follows:
    2293 *
    2294 * +/- var >= ... + z * SCIPgetCutoffbound() + constant
    2295 *
    2296 * becomes
    2297 *
    2298 * +/- var >= ... + (z / SCIPgetTransObjscale()) * origcutoffbound + (constant - z * SCIPgetTransObjoffset())
    2299 *
    2300 * with SCIPgetCutoffbound() = origcutoffbound / SCIPgetTransObjscale() - SCIPgetTransObjoffset(); in the
    2301 * propagation later, we will use (SCIPgetCutoffbound() + SCIPgetTransObjoffset()) * SCIPgetTransObjscale(), see
    2302 * function getCutoffboundGenVBound()
    2303 */
    2304 if( SCIPisNegative(scip, coefcutoffbound) )
    2305 {
    2307 genvbound->cutoffcoef = coefcutoffbound / SCIPgetTransObjscale(scip);
    2308 genvbound->constant -= (coefcutoffbound * SCIPgetTransObjoffset(scip));
    2309 }
    2310 else
    2311 genvbound->cutoffcoef = 0.0;
    2312
    2313 /* if genvbound is not overwritten, create a new entry in genvboundstore */
    2314 if( newgenvbound )
    2315 {
    2316 SCIP_CALL( addNewGenVBound(scip, genvboundprop, propdata, genvbound) );
    2317 }
    2318
    2319 /* mark genvbounds array to be re-sorted */
    2320 propdata->issorted = FALSE;
    2321
    2322 /* debug message */
    2323 SCIPdebugMsg(scip, "added genvbound ");
    2324 SCIPdebug( printGenVBound(scip, genvbound) );
    2325#ifdef WITH_DEBUG_SOLUTION
    2326 SCIP_CALL( checkDebugSolutionGenVBound(scip, genvbound) );
    2327#endif
    2328
    2329 return SCIP_OKAY;
    2330}
    2331
    2332
    2333/*
    2334 * Callback methods of propagator
    2335 */
    2336
    2337/** copy method for propagator plugins (called when SCIP copies plugins)
    2338 *
    2339 * @note The UG framework assumes that all default plug-ins of SCIP implement a copy callback.
    2340 */
    2341static
    2342SCIP_DECL_PROPCOPY(propCopyGenvbounds)
    2343{ /*lint --e{715}*/
    2344 assert(scip != NULL);
    2345 assert(prop != NULL);
    2346 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
    2347
    2348 /* call inclusion method of constraint handler */
    2350
    2351 return SCIP_OKAY;
    2352}
    2353
    2354/** initialization method of propagator (called after problem was transformed) */
    2355static
    2356SCIP_DECL_PROPINIT(propInitGenvbounds)
    2357{ /*lint --e{715}*/
    2358 SCIP_PROPDATA* propdata;
    2359
    2360 assert(scip != NULL);
    2361 assert(prop != NULL);
    2362 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
    2363
    2364 /* get propagator data */
    2365 propdata = SCIPpropGetData(prop);
    2366 assert(propdata != NULL);
    2367
    2368 propdata->genvboundstore = NULL;
    2369 propdata->genvboundstoresize = 0;
    2370 propdata->lbevents = NULL;
    2371 propdata->ubevents = NULL;
    2372 propdata->lbgenvbounds = NULL;
    2373 propdata->ubgenvbounds = NULL;
    2374 propdata->lbeventsmap = NULL;
    2375 propdata->ubeventsmap = NULL;
    2376 propdata->startmap = NULL;
    2377 propdata->componentsstart = NULL;
    2378 propdata->startindices = NULL;
    2379 propdata->startcomponents = NULL;
    2380 propdata->gstartindices = NULL;
    2381 propdata->gstartcomponents = NULL;
    2382 propdata->lastcutoff = SCIPinfinity(scip);
    2383 propdata->lastnodenumber = -1;
    2384 propdata->cutoffboundvar = NULL;
    2385 propdata->ngenvbounds = -1;
    2386 propdata->ncomponents = -1;
    2387 propdata->nindices = -1;
    2388 propdata->ngindices = -1;
    2389 propdata->nlbevents = -1;
    2390 propdata->nubevents = -1;
    2391 propdata->issorted = FALSE;
    2392
    2393 propdata->prop = prop;
    2394
    2395 /* store genvbounds timing */
    2396 propdata->inittiming = SCIPpropGetTimingmask(prop);
    2397
    2398 /* disable genvbounds propagator, enabled when genvbounds are added */
    2400
    2401 return SCIP_OKAY;
    2402}
    2403
    2404
    2405/** presolving method of propagator */
    2406static
    2407SCIP_DECL_PROPPRESOL(propPresolGenvbounds)
    2408{ /*lint --e{715}*/
    2409 SCIP_PROPDATA* propdata;
    2410
    2411 assert(scip != NULL);
    2412 assert(prop != NULL);
    2413 assert(result != NULL);
    2414 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
    2415
    2416 *result = SCIP_DIDNOTRUN;
    2417
    2418 /* get propagator data */
    2419 propdata = SCIPpropGetData(prop);
    2420 assert(propdata != NULL);
    2421
    2422 /* do not run if no genvbounds were added yet */
    2423 if( propdata->ngenvbounds < 1 )
    2424 return SCIP_OKAY;
    2425
    2427 return SCIP_OKAY;
    2428
    2429 SCIPdebugMsg(scip, "proppresol in problem <%s>\n", SCIPgetProbName(scip));
    2430
    2431 /* propagate */
    2432 SCIP_CALL( execGenVBounds(scip, propdata, result, TRUE, nchgbds) );
    2433
    2434 return SCIP_OKAY;
    2435}
    2436
    2437
    2438/** presolving initialization method of propagator (called when presolving is about to begin) */
    2439static
    2440SCIP_DECL_PROPINITPRE(propInitpreGenvbounds)
    2441{ /*lint --e{715}*/
    2442 SCIP_PROPDATA* propdata;
    2443
    2444 assert(scip != NULL);
    2445 assert(prop != NULL);
    2446 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
    2447
    2448 /* get propagator data */
    2449 propdata = SCIPpropGetData(prop);
    2450 assert(propdata != NULL);
    2451
    2452 /* lock the variable because it should not be deleted after a restart */
    2453 if( propdata->cutoffboundvar != NULL )
    2454 {
    2455 SCIPdebugMsg(scip, "propinitpre in problem <%s>: locking cutoffboundvar (current downlocks=%d, uplocks=%d)\n",
    2457 SCIPvarGetNLocksUpType(propdata->cutoffboundvar, SCIP_LOCKTYPE_MODEL));
    2458
    2459 SCIP_CALL( SCIPaddVarLocksType(scip, propdata->cutoffboundvar, SCIP_LOCKTYPE_MODEL, 1, 1) );
    2460 }
    2461
    2462 return SCIP_OKAY;
    2463}
    2464
    2465
    2466/** presolving deinitialization method of propagator (called after presolving has been finished) */
    2467static
    2468SCIP_DECL_PROPEXITPRE(propExitpreGenvbounds)
    2469{ /*lint --e{715}*/
    2470 SCIP_VAR** vars;
    2471 SCIP_PROPDATA* propdata;
    2472 int i;
    2473
    2474 assert(scip != NULL);
    2475 assert(prop != NULL);
    2476 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
    2477
    2478 SCIPdebugMsg(scip, "propexitpre in problem <%s>: removing fixed, aggregated, negated, and multi-aggregated variables from right-hand side\n",
    2480
    2481 /* get propagator data */
    2482 propdata = SCIPpropGetData(prop);
    2483 assert(propdata != NULL);
    2484
    2485 /* there should be no events on the right-hand side variables */
    2486 assert(propdata->lbevents == NULL);
    2487 assert(propdata->ubevents == NULL);
    2488
    2489 /* allocate memory to store new variables */
    2491
    2492 for( i = 0; i < propdata->ngenvbounds; )
    2493 {
    2494 GENVBOUND* genvbound;
    2495 int requiredsize;
    2496 int nvars;
    2497 int j;
    2498
    2499 genvbound = propdata->genvboundstore[i];
    2500 assert(genvbound != NULL);
    2501
    2502 /* store variables of the genvbound to release them properly */
    2503 assert(genvbound->ncoefs <= SCIPgetNTotalVars(scip));
    2504 BMScopyMemoryArray(vars, genvbound->vars, genvbound->ncoefs);
    2505 nvars = genvbound->ncoefs;
    2506
    2507 /* replace non-active by active variables and update constant; note that this may result in coefficients where
    2508 * SCIPisZero() is true; this should not create any problems
    2509 */
    2510 SCIP_CALL( SCIPgetProbvarLinearSum(scip, genvbound->vars, genvbound->coefs, &genvbound->ncoefs, genvbound->ncoefs, &genvbound->constant, &requiredsize) );
    2511
    2512 /* if space was not enough we need to resize the buffers */
    2513 if( requiredsize > genvbound->ncoefs )
    2514 {
    2515 /* reallocate memory for arrays in genvbound to free unused memory */
    2516 if( genvbound->coefssize < requiredsize )
    2517 {
    2518 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(genvbound->coefs), genvbound->coefssize, requiredsize) );
    2519 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(genvbound->vars), genvbound->coefssize, requiredsize) );
    2520 genvbound->coefssize = requiredsize;
    2521 }
    2522
    2523 SCIP_CALL( SCIPgetProbvarLinearSum(scip, genvbound->vars, genvbound->coefs, &genvbound->ncoefs, requiredsize, &genvbound->constant, &requiredsize) );
    2524 assert(requiredsize <= genvbound->coefssize);
    2525 }
    2526 assert(requiredsize == genvbound->ncoefs);
    2527
    2528 /* capture new and release old variables */
    2529 for( j = 0; j < genvbound->ncoefs; ++j )
    2530 {
    2531 assert(genvbound->vars[j] != NULL);
    2532 SCIP_CALL( SCIPcaptureVar(scip, genvbound->vars[j]) );
    2533 }
    2534 for( j = 0; j < nvars; ++j )
    2535 {
    2536 assert(vars[j] != NULL);
    2537 SCIP_CALL( SCIPreleaseVar(scip, &vars[j]) );
    2538 }
    2539
    2540 /* if the resulting genvbound is trivial, remove it */
    2541 /* we remove all genvbounds with an aggregated or multi-aggregated genvbound->var; tightening aggregated variables
    2542 * might lead to some asserts in tree.c if the active variable has been already tightened (see !398);
    2543 *
    2544 * @todo replace aggregated variable by their active part
    2545 */
    2546 if( (genvbound->ncoefs == 0 && SCIPisZero(scip, genvbound->cutoffcoef))
    2549 {
    2550 SCIP_HASHMAP* hashmap;
    2551
    2552 hashmap = genvbound->boundtype == SCIP_BOUNDTYPE_LOWER ? propdata->lbgenvbounds : propdata->ubgenvbounds;
    2553
    2554 /* remove genvbound from hashmap */
    2555 assert(SCIPhashmapExists(hashmap, genvbound->var));
    2556 SCIP_CALL( SCIPhashmapRemove(hashmap, genvbound->var) );
    2557
    2558 /* free genvbound and fill gap */
    2559 SCIP_CALL( freeGenVBound(scip, propdata->genvboundstore[i]) );
    2560 --(propdata->ngenvbounds);
    2561
    2562 /* move the last genvbound to the i-th position */
    2563 if( i < propdata->ngenvbounds )
    2564 {
    2565 propdata->genvboundstore[i] = propdata->genvboundstore[propdata->ngenvbounds];
    2566 propdata->genvboundstore[i]->index = i;
    2567
    2568 /* mark genvbounds array to be re-sorted */
    2569 propdata->issorted = FALSE;
    2570 }
    2571 }
    2572 else
    2573 ++i;
    2574 }
    2575
    2576 SCIPfreeBufferArray(scip, &vars);
    2577
    2578 /* disable genvbounds propagator */
    2579 if( propdata->ngenvbounds == 0 )
    2581
    2582 return SCIP_OKAY;
    2583}
    2584
    2585/** deinitialization method of propagator (called before transformed problem is freed) */
    2586static
    2587SCIP_DECL_PROPEXIT(propExitGenvbounds)
    2588{
    2589 SCIP_PROPDATA* propdata;
    2590
    2591 assert(scip != NULL);
    2592 assert(prop != NULL);
    2593 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
    2594
    2595 /* get propagator data */
    2596 propdata = SCIPpropGetData(prop);
    2597 assert(propdata != NULL);
    2598
    2599 /* free remaining genvbounds */
    2600 SCIP_CALL( freeGenVBounds(scip, prop, propdata) );
    2601
    2602 /* reset genvbounds timing */
    2603 SCIPpropSetTimingmask(prop, propdata->inittiming);
    2604
    2605 return SCIP_OKAY;
    2606}
    2607
    2608/** execution method of propagator */
    2609static
    2610SCIP_DECL_PROPEXEC(propExecGenvbounds)
    2611{ /*lint --e{715}*/
    2612 SCIP_PROPDATA* propdata;
    2613
    2614 assert(scip != NULL);
    2615 assert(prop != NULL);
    2616 assert(result != NULL);
    2617 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
    2618
    2619 *result = SCIP_DIDNOTRUN;
    2620
    2621 /* get propagator data */
    2622 propdata = SCIPpropGetData(prop);
    2623 assert(propdata != NULL);
    2624 assert(propdata->ngenvbounds >= 1);
    2625
    2626 /* do not run if propagation w.r.t. current objective is not allowed */
    2628 return SCIP_OKAY;
    2629
    2630 /* update upper bound of the cutoffboundvar */
    2631 if( propdata->cutoffboundvar != NULL )
    2632 {
    2633 SCIP_Real newub;
    2634 SCIP_Real oldub;
    2635 SCIP_Bool infeasible;
    2636 SCIP_Bool tightened;
    2637
    2638 assert(propdata->propasconss);
    2639
    2640 /* compute the primal bound in the original problem */
    2642 oldub = SCIPvarGetUbLocal(propdata->cutoffboundvar);
    2643
    2644 if( SCIPisInfinity(scip, newub) == FALSE && SCIPisFeasLT(scip, newub, oldub) )
    2645 {
    2646 SCIP_CALL( SCIPtightenVarUbGlobal(scip, propdata->cutoffboundvar, newub, FALSE, &infeasible, &tightened) );
    2647
    2648 if( tightened )
    2649 {
    2650 SCIPdebugMsg(scip, "tightened UB of cutoffboundvar to %e (old: %e, infeas: %u, tightened: %u)\n",
    2651 newub, oldub, infeasible, tightened);
    2652 }
    2653
    2654 assert(infeasible == FALSE);
    2655 }
    2656 }
    2657
    2658 SCIPdebugMsg(scip, "propexec in problem <%s> at depth %d%s\n", SCIPgetProbName(scip), SCIPgetDepth(scip),
    2659 SCIPinProbing(scip) ? " in probing" : "");
    2660
    2661 /* add the genvbounds in the genvboundstore as constraints to the problem; afterwards clear the genvboundstore */
    2662 if( propdata->propasconss )
    2663 {
    2664 SCIP_CALL( createConstraints(scip, prop, propdata) );
    2665 return SCIP_OKAY;
    2666 }
    2667
    2668 /* propagate locally and globally */
    2669 SCIP_CALL( execGenVBounds(scip, propdata, result, !SCIPinProbing(scip), NULL) );
    2670
    2671 /* when called in presolving stage the result is set to SCIP_SUCCESS instead of SCIP_REDUCEDDOM, this is corrected
    2672 * here
    2673 */
    2674 if( *result == SCIP_SUCCESS )
    2675 *result = SCIP_REDUCEDDOM;
    2676
    2677 SCIPdebugMsg(scip, "end of exec\n");
    2678
    2679 return SCIP_OKAY;
    2680}
    2681
    2682/** propagation conflict resolving method of propagator */
    2683static
    2684SCIP_DECL_PROPRESPROP(propRespropGenvbounds)
    2685{ /*lint --e{715}*/
    2686 SCIP_PROPDATA* propdata;
    2687 GENVBOUND* genvbound;
    2688 SCIP_Real boundval;
    2689 SCIP_Bool success;
    2690
    2691 SCIPdebugMsg(scip, "explain %s bound change of variable <%s>\n",
    2692 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
    2693
    2694 /* get propagator data */
    2695 propdata = SCIPpropGetData(prop);
    2696 assert(propdata != NULL);
    2697 assert(propdata->genvboundstore != NULL);
    2698
    2699 /* as inferinfo we passed the index of the genvbound that was used for propagation; the genvbound might have been
    2700 * replaced, but also the new genvbound at this position has the same variable on the left-hand side
    2701 */
    2702 assert(inferinfo >= 0);
    2703 assert(inferinfo < propdata->ngenvbounds);
    2704
    2705 *result = SCIP_DIDNOTFIND;
    2706
    2707 /* check also in optimized mode that inferinfo is correct */
    2708 if( inferinfo >= propdata->ngenvbounds)
    2709 {
    2710 SCIPerrorMessage("generalized variable bounds propagator received inferinfo out of range; propagation not resolved, safe to continue\n");
    2711 return SCIP_OKAY;
    2712 }
    2713
    2714 /* get genvbound responsible for the bound change */
    2715 genvbound = propdata->genvboundstore[inferinfo];
    2716 assert(genvbound != NULL);
    2717 assert(genvbound->var == infervar);
    2718
    2719 /* check also in optimized mode that inferinfo is correct */
    2720 if( genvbound->var != infervar )
    2721 {
    2722 SCIPerrorMessage("generalized variable bounds propagator received incorrect inferinfo; propagation not resolved, but it's safe to continue\n");
    2723 return SCIP_OKAY;
    2724 }
    2725
    2726 /* get value of bound change on left-hand side */
    2727 boundval = genvbound->boundtype == SCIP_BOUNDTYPE_LOWER
    2728 ? SCIPgetVarLbAtIndex(scip, genvbound->var, bdchgidx, TRUE)
    2729 : -SCIPgetVarUbAtIndex(scip, genvbound->var, bdchgidx, TRUE);
    2730
    2731 /* if left-hand side variable is integral, it suffices to explain a bound change greater than boundval - 1 */
    2732 if( SCIPvarIsIntegral(genvbound->var) )
    2733 {
    2734 SCIP_Real roundedboundval;
    2735
    2736 assert(SCIPisIntegral(scip, boundval));
    2737
    2738 roundedboundval = SCIPfeasCeil(scip, boundval - 1.0) + 2 * SCIPfeastol(scip);
    2739 boundval = MIN(boundval, roundedboundval);
    2740 }
    2741
    2742 /* resolve propagation */
    2743 SCIP_CALL( resolveGenVBoundPropagation(scip, genvbound, bdchgidx, &boundval, &success) );
    2744
    2745 if( success )
    2746 *result = SCIP_SUCCESS;
    2747
    2748 return SCIP_OKAY;
    2749}
    2750
    2751/** solving process deinitialization method of propagator (called before branch and bound process data is freed) */
    2752static
    2753SCIP_DECL_PROPEXITSOL(propExitsolGenvbounds)
    2754{ /*lint --e{715}*/
    2755 SCIP_PROPDATA* propdata;
    2756
    2757 assert(scip != NULL);
    2758 assert(prop != NULL);
    2759 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
    2760
    2761 SCIPdebugMsg(scip, "propexitsol in problem <%s>\n", SCIPgetProbName(scip));
    2762
    2763 /* get propagator data */
    2764 propdata = SCIPpropGetData(prop);
    2765 assert(propdata != NULL);
    2766
    2767 if( !SCIPisInRestart(scip) )
    2768 {
    2769 /* free all genvbounds if we are not in a restart */
    2770 SCIP_CALL( freeGenVBounds(scip, prop, propdata) );
    2771 }
    2772 else
    2773 {
    2774 /* free all genvbounds that use relax-only variables if we are in a restart */
    2775 SCIP_CALL( freeGenVBoundsRelaxOnly(scip, prop, propdata) );
    2776 }
    2777
    2778 /* drop and free all events */
    2779 SCIP_CALL( dropAndFreeEvents(scip, propdata) );
    2780
    2781 return SCIP_OKAY;
    2782}
    2783
    2784/** destructor of propagator to free user data (called when SCIP is exiting) */
    2785static
    2786SCIP_DECL_PROPFREE(propFreeGenvbounds)
    2787{ /*lint --e{715}*/
    2788 SCIP_PROPDATA* propdata;
    2789
    2790 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
    2791
    2792 /* free propagator data */
    2793 propdata = SCIPpropGetData(prop);
    2794 assert(propdata != NULL);
    2795
    2796 SCIPfreeBlockMemory(scip, &propdata);
    2797
    2798 SCIPpropSetData(prop, NULL);
    2799
    2800 return SCIP_OKAY;
    2801}
    2802
    2803
    2804/*
    2805 * Callback methods of event handler
    2806 */
    2807
    2808static
    2809SCIP_DECL_EVENTEXEC(eventExecGenvbounds)
    2810{ /*lint --e{715}*/
    2811 SCIP_PROPDATA* propdata;
    2813 int i;
    2814
    2817 assert(eventdata != NULL);
    2818 assert(eventdata->startcomponents != NULL);
    2819 assert(eventdata->startindices != NULL);
    2820 assert(eventdata->nstarts > 0);
    2821 assert(eventdata->prop != NULL);
    2822
    2823 /* ignore final events */
    2824 if( node == NULL )
    2825 return SCIP_OKAY;
    2826
    2827 propdata = SCIPpropGetData(eventdata->prop);
    2828 assert(propdata != NULL);
    2829
    2830 assert(propdata->startcomponents != NULL);
    2831 assert(propdata->startmap != NULL);
    2832 assert(propdata->startindices != NULL);
    2833
    2834 SCIPdebugMsg(scip, "catching eventdata:\n");
    2835 SCIPdebug( printEventData(eventdata, SCIPeventGetType(event) == SCIP_EVENTTYPE_LBTIGHTENED ?
    2837
    2838 /**@todo find a way to identify when we are at a new probing node; in probing mode, the node number is always zero,
    2839 * so we may miss resetting the starting data and may propagate more than necessary
    2840 */
    2841 /* check if we need to reset old local starting indices data */
    2842 if( SCIPnodeGetNumber(node) != propdata->lastnodenumber )
    2843 {
    2845 propdata->lastnodenumber = SCIPnodeGetNumber(node);
    2846 }
    2847
    2848 for( i = 0; i < eventdata->nstarts; i++ )
    2849 {
    2850 int component;
    2851 int startidx;
    2852
    2853 component = eventdata->startcomponents[i];
    2854 assert(component >= 0);
    2855 startidx = eventdata->startindices[i];
    2856
    2857 /* there is already an entry for this component */
    2858 if( SCIPhashmapExists(propdata->startmap, (void*)(size_t) (component + 1)) )
    2859 {
    2860 int componentidx;
    2861
    2862 /* get its index */
    2863 componentidx = (SCIPhashmapGetImageInt(propdata->startmap, (void*)(size_t) (component + 1))) - 1; /*lint !e571 !e776*/
    2864 assert(componentidx >= 0);
    2865 assert(propdata->startcomponents[componentidx] == component);
    2866
    2867 if( propdata->startindices[componentidx] > startidx )
    2868 propdata->startindices[componentidx] = startidx;
    2869 }
    2870 else
    2871 {
    2872 /* get a new entry */
    2873 int componentidx;
    2874 componentidx = propdata->nindices;
    2875
    2876 /* store index */
    2877 propdata->startcomponents[componentidx] = component;
    2878 propdata->startindices[componentidx] = startidx;
    2879
    2880 /* store component in hashmap */
    2881 SCIP_CALL( SCIPhashmapInsertInt(propdata->startmap, (void*)(size_t) (component + 1), componentidx + 1) ); /*lint !e571 !e776*/
    2882
    2883 /* increase number of starting indices */
    2884 propdata->nindices++;
    2885 }
    2886 }
    2887
    2888 return SCIP_OKAY;
    2889}
    2890
    2891/*
    2892 * propagator specific interface methods
    2893 */
    2894
    2895/** creates the genvbounds propagator and includes it in SCIP */
    2897 SCIP* scip /**< SCIP data structure */
    2898 )
    2899{
    2900 SCIP_PROPDATA* propdata;
    2901 SCIP_PROP* prop;
    2902
    2903 /* create genvbounds propagator data */
    2904 SCIP_CALL( SCIPallocBlockMemory(scip, &propdata) );
    2905 propdata->inittiming = PROP_TIMING;
    2906
    2907 /* include propagator */
    2909 propExecGenvbounds, propdata) );
    2910
    2911 SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopyGenvbounds) );
    2912 SCIP_CALL( SCIPsetPropFree(scip, prop, propFreeGenvbounds) );
    2913 SCIP_CALL( SCIPsetPropInit(scip, prop, propInitGenvbounds) );
    2914 SCIP_CALL( SCIPsetPropInitpre(scip, prop, propInitpreGenvbounds) );
    2915 SCIP_CALL( SCIPsetPropExitpre(scip, prop, propExitpreGenvbounds) );
    2916 SCIP_CALL( SCIPsetPropExit(scip, prop, propExitGenvbounds) );
    2917 SCIP_CALL( SCIPsetPropExitsol(scip, prop, propExitsolGenvbounds) );
    2918 SCIP_CALL( SCIPsetPropPresol(scip, prop, propPresolGenvbounds, PROP_PRESOL_PRIORITY,
    2920 SCIP_CALL( SCIPsetPropResprop(scip, prop, propRespropGenvbounds) );
    2921
    2922 SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/global",
    2923 "apply global propagation?",
    2924 &propdata->global, TRUE, DEFAULT_GLOBAL_PROPAGATION, NULL, NULL) );
    2925
    2926 SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/propinrootnode",
    2927 "apply genvbounds in root node if no new incumbent was found?",
    2928 &propdata->propinrootnode, TRUE, DEFAULT_PROPAGATE_IN_ROOT_NODE, NULL, NULL) );
    2929
    2930 SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/sort",
    2931 "sort genvbounds and wait for bound change events?",
    2932 &propdata->sort, TRUE, DEFAULT_SORT, NULL, NULL) );
    2933
    2934 SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/propasconss",
    2935 "should genvbounds be transformed to (linear) constraints?",
    2936 &propdata->propasconss, TRUE, DEFAULT_PROPASCONSS, NULL, NULL) );
    2937
    2938 /* include event handler */
    2939 SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &propdata->eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecGenvbounds, NULL) );
    2940
    2941 return SCIP_OKAY;
    2942}
    static long bound
    Constraint handler for linear constraints in their most general form, .
    methods for debugging
    #define SCIPdebugCheckLbGlobal(scip, var, lb)
    Definition: debug.h:298
    #define SCIPdebugGetSolVal(scip, var, val)
    Definition: debug.h:312
    #define SCIPdebugCheckUbGlobal(scip, var, ub)
    Definition: debug.h:299
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #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 SCIP_UNKNOWN
    Definition: def.h:179
    #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 nnodes
    Definition: gastrans.c:74
    SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_RETCODE SCIPdigraphComputeUndirectedComponents(SCIP_DIGRAPH *digraph, int minsize, int *components, int *ncomponents)
    Definition: misc.c:8165
    int SCIPdigraphGetNNodes(SCIP_DIGRAPH *digraph)
    Definition: misc.c:7823
    void SCIPdigraphGetComponent(SCIP_DIGRAPH *digraph, int compidx, int **nodes, int *nnodes)
    Definition: misc.c:8374
    SCIP_RETCODE SCIPdigraphAddArc(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
    Definition: misc.c:7739
    SCIP_RETCODE SCIPdigraphTopoSortComponents(SCIP_DIGRAPH *digraph)
    Definition: misc.c:8295
    SCIP_RETCODE SCIPdigraphComputeDirectedComponents(SCIP_DIGRAPH *digraph, int compidx, int *strongcomponents, int *strongcompstartidx, int *nstrongcomponents)
    Definition: misc.c:8506
    void SCIPdigraphFree(SCIP_DIGRAPH **digraph)
    Definition: misc.c:7645
    int SCIPdigraphGetNComponents(SCIP_DIGRAPH *digraph)
    Definition: misc.c:8361
    SCIP_RETCODE SCIPcreateDigraph(SCIP *scip, SCIP_DIGRAPH **digraph, int nnodes)
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_prob.c:1907
    const char * SCIPgetProbName(SCIP *scip)
    Definition: scip_prob.c:1242
    SCIP_Real SCIPgetTransObjoffset(SCIP *scip)
    Definition: scip_prob.c:1606
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    int SCIPgetNFixedVars(SCIP *scip)
    Definition: scip_prob.c:2705
    int SCIPgetNTotalVars(SCIP *scip)
    Definition: scip_prob.c:3064
    SCIP_Real SCIPgetTransObjscale(SCIP *scip)
    Definition: scip_prob.c:1629
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3304
    void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3284
    SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
    Definition: misc.c:3143
    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
    SCIP_RETCODE SCIPhashmapRemoveAll(SCIP_HASHMAP *hashmap)
    Definition: misc.c:3676
    SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3482
    #define SCIPdebugMsgPrint
    Definition: scip_message.h:79
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPgenVBoundAdd(SCIP *scip, SCIP_PROP *genvboundprop, SCIP_VAR **vars, SCIP_VAR *var, SCIP_Real *coefs, int ncoefs, SCIP_Real coefcutoffbound, SCIP_Real constant, SCIP_BOUNDTYPE boundtype)
    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 SCIPincludePropGenvbounds(SCIP *scip)
    SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
    SCIP_RETCODE SCIPaddConflictRelaxedLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedlb)
    SCIP_RETCODE SCIPanalyzeConflict(SCIP *scip, int validdepth, SCIP_Bool *success)
    SCIP_RETCODE SCIPaddConflictRelaxedUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedub)
    SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
    SCIP_Real SCIPgetConflictVarUb(SCIP *scip, SCIP_VAR *var)
    SCIP_Real SCIPgetConflictVarLb(SCIP *scip, SCIP_VAR *var)
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    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
    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
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    #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 SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    #define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:105
    SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
    Definition: tree.c:8483
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    void SCIPpropSetData(SCIP_PROP *prop, SCIP_PROPDATA *propdata)
    Definition: prop.c:801
    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
    SCIP_RETCODE SCIPsetPropExitpre(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPEXITPRE((*propexitpre)))
    Definition: scip_prop.c:267
    const char * SCIPpropGetName(SCIP_PROP *prop)
    Definition: prop.c:951
    SCIP_RETCODE SCIPsetPropExit(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPEXIT((*propexit)))
    Definition: scip_prop.c:203
    void SCIPpropSetTimingmask(SCIP_PROP *prop, SCIP_PROPTIMING timingmask)
    Definition: prop.c:1296
    SCIP_RETCODE SCIPsetPropInit(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPINIT((*propinit)))
    Definition: scip_prop.c:187
    SCIP_RETCODE SCIPsetPropInitpre(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPINITPRE((*propinitpre)))
    Definition: scip_prop.c:251
    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_PROPTIMING SCIPpropGetTimingmask(SCIP_PROP *prop)
    Definition: prop.c:1286
    SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:2005
    SCIP_Bool SCIPisInRestart(SCIP *scip)
    Definition: scip_solve.c:3709
    SCIP_Real SCIPgetCutoffbound(SCIP *scip)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeasCeil(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_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)
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    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
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4386
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
    Definition: scip_var.c:5118
    SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2872
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
    Definition: scip_var.c:2378
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
    Definition: var.c:23600
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:11057
    SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2736
    SCIP_RETCODE SCIPcreateVarBasic(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype)
    Definition: scip_var.c:184
    int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4328
    SCIP_Bool SCIPallowWeakDualReds(SCIP *scip)
    Definition: scip_var.c:10998
    SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:1853
    SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
    Definition: scip_var.c:10984
    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
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    memory allocation routines
    #define BMScopyMemoryArray(ptr, source, num)
    Definition: memory.h:134
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    #define PROP_PRESOL_MAXROUNDS
    #define PROP_PRESOLTIMING
    #define PROP_DESC
    static SCIP_RETCODE addEventData(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, int startindex, int startcomponent, SCIP_BOUNDTYPE boundtype)
    static SCIP_RETCODE freeComponentsData(SCIP *scip, SCIP_PROPDATA *propdata)
    static SCIP_DECL_PROPRESPROP(propRespropGenvbounds)
    #define DEFAULT_PROPAGATE_IN_ROOT_NODE
    static SCIP_RETCODE analyzeGenVBoundConflict(SCIP *scip, GENVBOUND *genvbound)
    static SCIP_DECL_PROPCOPY(propCopyGenvbounds)
    static SCIP_RETCODE freeGenVBoundsRelaxOnly(SCIP *scip, SCIP_PROP *prop, SCIP_PROPDATA *propdata)
    static SCIP_RETCODE execGenVBounds(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_RESULT *result, SCIP_Bool local, int *nchgbds)
    #define PROP_NAME
    static SCIP_Real getGenVBoundsMinActivityConflict(SCIP *scip, SCIP_VAR **vars, SCIP_Real *coefs, int nvars, SCIP_BDCHGIDX *bdchgidx)
    static SCIP_DECL_PROPINITPRE(propInitpreGenvbounds)
    static SCIP_Real getGenVBoundsMinActivity(SCIP *scip, SCIP_VAR **vars, SCIP_Real *coefs, int nvars, SCIP_Bool global)
    static SCIP_Real getGenVBoundsBound(SCIP *scip, GENVBOUND *genvbound, SCIP_Bool global)
    static SCIP_RETCODE freeEventData(SCIP *scip, SCIP_EVENTDATA **eventdata)
    static SCIP_RETCODE dropAndFreeEvents(SCIP *scip, SCIP_PROPDATA *propdata)
    #define DEFAULT_PROPASCONSS
    static SCIP_RETCODE setUpEvents(SCIP *scip, SCIP_PROPDATA *propdata)
    static SCIP_RETCODE sortGenVBounds(SCIP *scip, SCIP_PROPDATA *propdata)
    #define DEFAULT_SORT
    static SCIP_DECL_PROPEXEC(propExecGenvbounds)
    static SCIP_DECL_PROPFREE(propFreeGenvbounds)
    static SCIP_RETCODE fillGlobalStartingData(SCIP *scip, SCIP_PROPDATA *propdata)
    static SCIP_RETCODE resetLocalStartingData(SCIP *scip, SCIP_PROPDATA *propdata)
    #define PROP_DELAY
    static GENVBOUND * getGenVBound(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype)
    static SCIP_RETCODE freeGenVBound(SCIP *scip, GENVBOUND *genvbound)
    static SCIP_Real getCutoffboundGenVBound(SCIP *scip)
    static SCIP_RETCODE createConstraints(SCIP *scip, SCIP_PROP *prop, SCIP_PROPDATA *propdata)
    static SCIP_RETCODE applyGenVBounds(SCIP *scip, SCIP_PROP *prop, SCIP_Bool global, SCIP_RESULT *result, int *nchgbds)
    #define DEFAULT_GLOBAL_PROPAGATION
    static SCIP_RETCODE freeStartingData(SCIP *scip, SCIP_PROPDATA *propdata)
    static SCIP_DECL_PROPEXITSOL(propExitsolGenvbounds)
    #define PROP_TIMING
    static SCIP_RETCODE addNewGenVBound(SCIP *scip, SCIP_PROP *prop, SCIP_PROPDATA *propdata, GENVBOUND *genvbound)
    static SCIP_RETCODE getEventData(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_EVENTDATA **eventdata)
    static SCIP_DECL_EVENTEXEC(eventExecGenvbounds)
    static SCIP_DECL_PROPPRESOL(propPresolGenvbounds)
    static SCIP_RETCODE createStartingData(SCIP *scip, SCIP_PROPDATA *propdata)
    static SCIP_DECL_PROPEXITPRE(propExitpreGenvbounds)
    static SCIP_DECL_PROPEXIT(propExitGenvbounds)
    static SCIP_RETCODE applyGenVBound(SCIP *scip, SCIP_PROP *prop, GENVBOUND *genvbound, SCIP_Bool global, SCIP_RESULT *result, int *nchgbds)
    static SCIP_RETCODE freeAllEventData(SCIP *scip, SCIP_PROPDATA *propdata)
    static SCIP_DECL_PROPINIT(propInitGenvbounds)
    #define EVENTHDLR_DESC
    static SCIP_RETCODE freeGenVBounds(SCIP *scip, SCIP_PROP *prop, SCIP_PROPDATA *propdata)
    #define EVENTHDLR_NAME
    static SCIP_RETCODE resolveGenVBoundPropagation(SCIP *scip, GENVBOUND *genvbound, SCIP_BDCHGIDX *bdchgidx, SCIP_Real *boundval, SCIP_Bool *success)
    #define PROP_FREQ
    #define PROP_PRIORITY
    static SCIP_RETCODE initPropdata(SCIP *scip, SCIP_PROPDATA *propdata)
    #define PROP_PRESOL_PRIORITY
    generalized variable bounds propagator
    public methods for managing events
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    #define SCIPdebugPrintf
    Definition: pub_message.h:99
    public data structures and miscellaneous methods
    public methods for propagators
    public methods for branch and bound tree
    public methods for problem variables
    public methods for conflict handler plugins and conflict analysis
    public methods for constraint handler plugins and constraints
    public methods for data structures
    public methods for event handler plugins and event handlers
    general public methods
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for the probing mode
    public methods for propagator plugins
    public methods for solutions
    public solving methods
    public methods for querying solving statistics
    public methods for the branch-and-bound tree
    public methods for SCIP variables
    SCIP_BOUNDTYPE boundtype
    SCIP_Real constant
    SCIP_Real * coefs
    SCIP_VAR * var
    SCIP_VAR ** vars
    SCIP_Real cutoffcoef
    SCIP_Bool relaxonly
    @ SCIP_CONFTYPE_PROPAGATION
    Definition: type_conflict.h:62
    struct SCIP_EventData SCIP_EVENTDATA
    Definition: type_event.h:179
    #define SCIP_EVENTTYPE_UBTIGHTENED
    Definition: type_event.h:79
    #define SCIP_EVENTTYPE_LBTIGHTENED
    Definition: type_event.h:77
    @ 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_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_PRESOLVING
    Definition: type_set.h:49
    #define SCIP_PROPTIMING_NONE
    Definition: type_timing.h:65
    unsigned int SCIP_PROPTIMING
    Definition: type_timing.h:75
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71
    @ SCIP_VARSTATUS_MULTAGGR
    Definition: type_var.h:56
    @ SCIP_VARSTATUS_AGGREGATED
    Definition: type_var.h:55
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141