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-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file 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
    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(vars != NULL);
    2184 assert(var != NULL);
    2185 assert(coefs != NULL);
    2186 assert(ncoefs >= 0);
    2187 assert(coefcutoffbound <= 0.0);
    2188 assert(!SCIPisInfinity(scip, -constant));
    2189
    2191
    2192 if( ncoefs < 0 || coefcutoffbound > 0.0 || SCIPisInfinity(scip, -constant) )
    2193 {
    2194 SCIPerrorMessage("cannot create generalized variable bound from invalid data\n");
    2195 return SCIP_INVALIDDATA;
    2196 }
    2197
    2198 propdata = SCIPpropGetData(genvboundprop);
    2199 assert(propdata != NULL);
    2200
    2201 /* initialize propdata if not done yet */
    2202 if( propdata->genvboundstore == NULL )
    2203 {
    2204 SCIP_CALL( initPropdata(scip, propdata) );
    2205 }
    2206
    2207 genvbound = getGenVBound(scip, propdata, var, boundtype);
    2208 newgenvbound = (genvbound == NULL);
    2209
    2210 /* release previous variables */
    2211 if( !newgenvbound )
    2212 {
    2213 for( i = 0; i < genvbound->ncoefs; ++i )
    2214 {
    2215 assert(genvbound->vars[i] != NULL);
    2216 SCIP_CALL( SCIPreleaseVar(scip, &(genvbound->vars[i])) );
    2217 }
    2218 }
    2219
    2220 /* check if there already is a genvbound corresponding to this bound, freeing its data and overwriting it */
    2221 if( !newgenvbound && genvbound->ncoefs < ncoefs )
    2222 {
    2223 /* do not realloc since we do not want to keep and possibly copy the old entries */
    2224 SCIPfreeBlockMemoryArray(scip, &(genvbound->coefs), genvbound->coefssize);
    2225 SCIPfreeBlockMemoryArray(scip, &(genvbound->vars), genvbound->coefssize);
    2226
    2227 /* allocate and copy arrays in genvbound */
    2228 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(genvbound->coefs), coefs, ncoefs) );
    2229 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(genvbound->vars), vars, ncoefs) );
    2230 genvbound->coefssize = ncoefs;
    2231 }
    2232 else if( !newgenvbound && genvbound->ncoefs == ncoefs )
    2233 {
    2234 /* just update entries */
    2235 for( i = 0; i < ncoefs; i++ )
    2236 {
    2237 genvbound->coefs[i] = coefs[i];
    2238 genvbound->vars[i] = vars[i];
    2239 }
    2240 }
    2241 else if( !newgenvbound && genvbound->ncoefs > ncoefs )
    2242 {
    2243 /* reallocate memory for arrays in genvbound to free unused memory */
    2244 if( genvbound->coefssize < ncoefs )
    2245 {
    2246 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(genvbound->coefs), genvbound->coefssize, ncoefs) );
    2247 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(genvbound->vars), genvbound->coefssize, ncoefs) );
    2248 genvbound->coefssize = ncoefs;
    2249 }
    2250
    2251 /* update entries */
    2252 for( i = 0; i < ncoefs; i++ )
    2253 {
    2254 genvbound->coefs[i] = coefs[i];
    2255 genvbound->vars[i] = vars[i];
    2256 }
    2257 }
    2258 else if( newgenvbound )
    2259 {
    2260 /* allocate memory for genvbound data */
    2261 SCIP_CALL( SCIPallocBlockMemory(scip, &genvbound) );
    2262
    2263 /* allocate and copy arrays in genvbound */
    2264 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(genvbound->coefs), coefs, ncoefs) );
    2265 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(genvbound->vars), vars, ncoefs) );
    2266 genvbound->coefssize = ncoefs;
    2267 }
    2268
    2269 /* set up data for genvbound */
    2270 genvbound->boundtype = boundtype;
    2271 genvbound->var = var;
    2272 genvbound->ncoefs = ncoefs;
    2273 genvbound->constant = constant;
    2274 genvbound->relaxonly = SCIPvarIsRelaxationOnly(genvbound->var);
    2275
    2276 /* capture variables and check for relax-only vars */
    2277 for( i = 0; i < genvbound->ncoefs; ++i )
    2278 {
    2279 assert(genvbound->vars[i] != NULL);
    2280 SCIP_CALL( SCIPcaptureVar(scip, genvbound->vars[i]) );
    2281 if( SCIPvarIsRelaxationOnly(genvbound->vars[i]) )
    2282 genvbound->relaxonly = TRUE;
    2283 }
    2284 if( newgenvbound )
    2285 {
    2286 assert(genvbound->var != NULL);
    2287 SCIP_CALL( SCIPcaptureVar(scip, genvbound->var) );
    2288 }
    2289
    2290 /* the cutoff bound is valid w.r.t. the current objective function in the transformed problem; during presolving,
    2291 * however, the objective function can change (e.g., when a variable is fixed, its contribution in the objective
    2292 * is subtracted from the cutoff bound and added to the objective offset); we solve this by transforming the
    2293 * contribution of the cutoff bound in the generalized variable bound to the original problem as follows:
    2294 *
    2295 * +/- var >= ... + z * SCIPgetCutoffbound() + constant
    2296 *
    2297 * becomes
    2298 *
    2299 * +/- var >= ... + (z / SCIPgetTransObjscale()) * origcutoffbound + (constant - z * SCIPgetTransObjoffset())
    2300 *
    2301 * with SCIPgetCutoffbound() = origcutoffbound / SCIPgetTransObjscale() - SCIPgetTransObjoffset(); in the
    2302 * propagation later, we will use (SCIPgetCutoffbound() + SCIPgetTransObjoffset()) * SCIPgetTransObjscale(), see
    2303 * function getCutoffboundGenVBound()
    2304 */
    2305 if( SCIPisNegative(scip, coefcutoffbound) )
    2306 {
    2308 genvbound->cutoffcoef = coefcutoffbound / SCIPgetTransObjscale(scip);
    2309 genvbound->constant -= (coefcutoffbound * SCIPgetTransObjoffset(scip));
    2310 }
    2311 else
    2312 genvbound->cutoffcoef = 0.0;
    2313
    2314 /* if genvbound is not overwritten, create a new entry in genvboundstore */
    2315 if( newgenvbound )
    2316 {
    2317 SCIP_CALL( addNewGenVBound(scip, genvboundprop, propdata, genvbound) );
    2318 }
    2319
    2320 /* mark genvbounds array to be re-sorted */
    2321 propdata->issorted = FALSE;
    2322
    2323 /* debug message */
    2324 SCIPdebugMsg(scip, "added genvbound ");
    2325 SCIPdebug( printGenVBound(scip, genvbound) );
    2326#ifdef WITH_DEBUG_SOLUTION
    2327 SCIP_CALL( checkDebugSolutionGenVBound(scip, genvbound) );
    2328#endif
    2329
    2330 return SCIP_OKAY;
    2331}
    2332
    2333
    2334/*
    2335 * Callback methods of propagator
    2336 */
    2337
    2338/** copy method for propagator plugins (called when SCIP copies plugins)
    2339 *
    2340 * @note The UG framework assumes that all default plug-ins of SCIP implement a copy callback.
    2341 */
    2342static
    2343SCIP_DECL_PROPCOPY(propCopyGenvbounds)
    2344{ /*lint --e{715}*/
    2345 assert(scip != NULL);
    2346 assert(prop != NULL);
    2347
    2349
    2350 /* call inclusion method of constraint handler */
    2352
    2353 return SCIP_OKAY;
    2354}
    2355
    2356/** initialization method of propagator (called after problem was transformed) */
    2357static
    2358SCIP_DECL_PROPINIT(propInitGenvbounds)
    2359{ /*lint --e{715}*/
    2360 SCIP_PROPDATA* propdata;
    2361
    2362 assert(scip != NULL);
    2363 assert(prop != NULL);
    2364
    2366
    2367 /* get propagator data */
    2368 propdata = SCIPpropGetData(prop);
    2369 assert(propdata != NULL);
    2370
    2371 propdata->genvboundstore = NULL;
    2372 propdata->genvboundstoresize = 0;
    2373 propdata->lbevents = NULL;
    2374 propdata->ubevents = NULL;
    2375 propdata->lbgenvbounds = NULL;
    2376 propdata->ubgenvbounds = NULL;
    2377 propdata->lbeventsmap = NULL;
    2378 propdata->ubeventsmap = NULL;
    2379 propdata->startmap = NULL;
    2380 propdata->componentsstart = NULL;
    2381 propdata->startindices = NULL;
    2382 propdata->startcomponents = NULL;
    2383 propdata->gstartindices = NULL;
    2384 propdata->gstartcomponents = NULL;
    2385 propdata->lastcutoff = SCIPinfinity(scip);
    2386 propdata->lastnodenumber = -1;
    2387 propdata->cutoffboundvar = NULL;
    2388 propdata->ngenvbounds = -1;
    2389 propdata->ncomponents = -1;
    2390 propdata->nindices = -1;
    2391 propdata->ngindices = -1;
    2392 propdata->nlbevents = -1;
    2393 propdata->nubevents = -1;
    2394 propdata->issorted = FALSE;
    2395
    2396 propdata->prop = prop;
    2397
    2398 /* store genvbounds timing */
    2399 propdata->inittiming = SCIPpropGetTimingmask(prop);
    2400
    2401 /* disable genvbounds propagator, enabled when genvbounds are added */
    2403
    2404 return SCIP_OKAY;
    2405}
    2406
    2407
    2408/** presolving method of propagator */
    2409static
    2410SCIP_DECL_PROPPRESOL(propPresolGenvbounds)
    2411{ /*lint --e{715}*/
    2412 SCIP_PROPDATA* propdata;
    2413
    2414 assert(scip != NULL);
    2415 assert(prop != NULL);
    2416 assert(result != NULL);
    2417
    2419
    2420 *result = SCIP_DIDNOTRUN;
    2421
    2422 /* get propagator data */
    2423 propdata = SCIPpropGetData(prop);
    2424 assert(propdata != NULL);
    2425
    2426 /* do not run if no genvbounds were added yet */
    2427 if( propdata->ngenvbounds < 1 )
    2428 return SCIP_OKAY;
    2429
    2431 return SCIP_OKAY;
    2432
    2433 SCIPdebugMsg(scip, "proppresol in problem <%s>\n", SCIPgetProbName(scip));
    2434
    2435 /* propagate */
    2436 SCIP_CALL( execGenVBounds(scip, propdata, result, TRUE, nchgbds) );
    2437
    2438 return SCIP_OKAY;
    2439}
    2440
    2441
    2442/** presolving initialization method of propagator (called when presolving is about to begin) */
    2443static
    2444SCIP_DECL_PROPINITPRE(propInitpreGenvbounds)
    2445{ /*lint --e{715}*/
    2446 SCIP_PROPDATA* propdata;
    2447
    2448 assert(scip != NULL);
    2449 assert(prop != NULL);
    2450
    2452
    2453 /* get propagator data */
    2454 propdata = SCIPpropGetData(prop);
    2455 assert(propdata != NULL);
    2456
    2457 /* lock the variable because it should not be deleted after a restart */
    2458 if( propdata->cutoffboundvar != NULL )
    2459 {
    2460 SCIPdebugMsg(scip, "propinitpre in problem <%s>: locking cutoffboundvar (current downlocks=%d, uplocks=%d)\n",
    2462 SCIPvarGetNLocksUpType(propdata->cutoffboundvar, SCIP_LOCKTYPE_MODEL));
    2463
    2464 SCIP_CALL( SCIPaddVarLocksType(scip, propdata->cutoffboundvar, SCIP_LOCKTYPE_MODEL, 1, 1) );
    2465 }
    2466
    2467 return SCIP_OKAY;
    2468}
    2469
    2470
    2471/** presolving deinitialization method of propagator (called after presolving has been finished) */
    2472static
    2473SCIP_DECL_PROPEXITPRE(propExitpreGenvbounds)
    2474{ /*lint --e{715}*/
    2475 SCIP_VAR** vars;
    2476 SCIP_PROPDATA* propdata;
    2477 int i;
    2478
    2479 assert(scip != NULL);
    2480 assert(prop != NULL);
    2481
    2483
    2484 SCIPdebugMsg(scip, "propexitpre in problem <%s>: removing fixed, aggregated, negated, and multi-aggregated variables from right-hand side\n",
    2486
    2487 /* get propagator data */
    2488 propdata = SCIPpropGetData(prop);
    2489 assert(propdata != NULL);
    2490
    2491 /* there should be no events on the right-hand side variables */
    2492 assert(propdata->lbevents == NULL);
    2493 assert(propdata->ubevents == NULL);
    2494
    2495 /* allocate memory to store new variables */
    2497
    2498 for( i = 0; i < propdata->ngenvbounds; )
    2499 {
    2500 GENVBOUND* genvbound;
    2501 int requiredsize;
    2502 int nvars;
    2503 int j;
    2504
    2505 genvbound = propdata->genvboundstore[i];
    2506 assert(genvbound != NULL);
    2507
    2508 /* store variables of the genvbound to release them properly */
    2509 assert(genvbound->ncoefs <= SCIPgetNTotalVars(scip));
    2510 BMScopyMemoryArray(vars, genvbound->vars, genvbound->ncoefs);
    2511 nvars = genvbound->ncoefs;
    2512
    2513 /* replace non-active by active variables and update constant; note that this may result in coefficients where
    2514 * SCIPisZero() is true; this should not create any problems
    2515 */
    2516 SCIP_CALL( SCIPgetProbvarLinearSum(scip, genvbound->vars, genvbound->coefs, &genvbound->ncoefs, genvbound->ncoefs, &genvbound->constant, &requiredsize) );
    2517
    2518 /* if space was not enough we need to resize the buffers */
    2519 if( requiredsize > genvbound->ncoefs )
    2520 {
    2521 /* reallocate memory for arrays in genvbound to free unused memory */
    2522 if( genvbound->coefssize < requiredsize )
    2523 {
    2524 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(genvbound->coefs), genvbound->coefssize, requiredsize) );
    2525 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(genvbound->vars), genvbound->coefssize, requiredsize) );
    2526 genvbound->coefssize = requiredsize;
    2527 }
    2528
    2529 SCIP_CALL( SCIPgetProbvarLinearSum(scip, genvbound->vars, genvbound->coefs, &genvbound->ncoefs, requiredsize, &genvbound->constant, &requiredsize) );
    2530 assert(requiredsize <= genvbound->coefssize);
    2531 }
    2532 assert(requiredsize == genvbound->ncoefs);
    2533
    2534 /* capture new and release old variables */
    2535 for( j = 0; j < genvbound->ncoefs; ++j )
    2536 {
    2537 assert(genvbound->vars[j] != NULL);
    2538 SCIP_CALL( SCIPcaptureVar(scip, genvbound->vars[j]) );
    2539 }
    2540 for( j = 0; j < nvars; ++j )
    2541 {
    2542 assert(vars[j] != NULL);
    2543 SCIP_CALL( SCIPreleaseVar(scip, &vars[j]) );
    2544 }
    2545
    2546 /* if the resulting genvbound is trivial, remove it */
    2547 /* we remove all genvbounds with an aggregated or multi-aggregated genvbound->var; tightening aggregated variables
    2548 * might lead to some asserts in tree.c if the active variable has been already tightened (see !398);
    2549 *
    2550 * @todo replace aggregated variable by their active part
    2551 */
    2552 if( (genvbound->ncoefs == 0 && SCIPisZero(scip, genvbound->cutoffcoef))
    2555 {
    2556 SCIP_HASHMAP* hashmap;
    2557
    2558 hashmap = genvbound->boundtype == SCIP_BOUNDTYPE_LOWER ? propdata->lbgenvbounds : propdata->ubgenvbounds;
    2559
    2560 /* remove genvbound from hashmap */
    2561 assert(SCIPhashmapExists(hashmap, genvbound->var));
    2562 SCIP_CALL( SCIPhashmapRemove(hashmap, genvbound->var) );
    2563
    2564 /* free genvbound and fill gap */
    2565 SCIP_CALL( freeGenVBound(scip, propdata->genvboundstore[i]) );
    2566 --(propdata->ngenvbounds);
    2567
    2568 /* move the last genvbound to the i-th position */
    2569 if( i < propdata->ngenvbounds )
    2570 {
    2571 propdata->genvboundstore[i] = propdata->genvboundstore[propdata->ngenvbounds];
    2572 propdata->genvboundstore[i]->index = i;
    2573
    2574 /* mark genvbounds array to be re-sorted */
    2575 propdata->issorted = FALSE;
    2576 }
    2577 }
    2578 else
    2579 ++i;
    2580 }
    2581
    2582 SCIPfreeBufferArray(scip, &vars);
    2583
    2584 /* disable genvbounds propagator */
    2585 if( propdata->ngenvbounds == 0 )
    2587
    2588 return SCIP_OKAY;
    2589}
    2590
    2591/** deinitialization method of propagator (called before transformed problem is freed) */
    2592static
    2593SCIP_DECL_PROPEXIT(propExitGenvbounds)
    2594{
    2595 SCIP_PROPDATA* propdata;
    2596
    2597 assert(scip != NULL);
    2598 assert(prop != NULL);
    2599
    2601
    2602 /* get propagator data */
    2603 propdata = SCIPpropGetData(prop);
    2604 assert(propdata != NULL);
    2605
    2606 /* free remaining genvbounds */
    2607 SCIP_CALL( freeGenVBounds(scip, prop, propdata) );
    2608
    2609 /* reset genvbounds timing */
    2610 SCIPpropSetTimingmask(prop, propdata->inittiming);
    2611
    2612 return SCIP_OKAY;
    2613}
    2614
    2615/** execution method of propagator */
    2616static
    2617SCIP_DECL_PROPEXEC(propExecGenvbounds)
    2618{ /*lint --e{715}*/
    2619 SCIP_PROPDATA* propdata;
    2620
    2621 assert(scip != NULL);
    2622 assert(prop != NULL);
    2623 assert(result != NULL);
    2624
    2626
    2627 *result = SCIP_DIDNOTRUN;
    2628
    2629 /* get propagator data */
    2630 propdata = SCIPpropGetData(prop);
    2631 assert(propdata != NULL);
    2632 assert(propdata->ngenvbounds >= 1);
    2633
    2634 /* do not run if propagation w.r.t. current objective is not allowed */
    2636 return SCIP_OKAY;
    2637
    2638 /* update upper bound of the cutoffboundvar */
    2639 if( propdata->cutoffboundvar != NULL )
    2640 {
    2641 SCIP_Real newub;
    2642 SCIP_Real oldub;
    2643 SCIP_Bool infeasible;
    2644 SCIP_Bool tightened;
    2645
    2646 assert(propdata->propasconss);
    2647
    2648 /* compute the primal bound in the original problem */
    2650 oldub = SCIPvarGetUbLocal(propdata->cutoffboundvar);
    2651
    2652 if( SCIPisInfinity(scip, newub) == FALSE && SCIPisFeasLT(scip, newub, oldub) )
    2653 {
    2654 SCIP_CALL( SCIPtightenVarUbGlobal(scip, propdata->cutoffboundvar, newub, FALSE, &infeasible, &tightened) );
    2655
    2656 if( tightened )
    2657 {
    2658 SCIPdebugMsg(scip, "tightened UB of cutoffboundvar to %e (old: %e, infeas: %u, tightened: %u)\n",
    2659 newub, oldub, infeasible, tightened);
    2660 }
    2661
    2662 assert(infeasible == FALSE);
    2663 }
    2664 }
    2665
    2666 SCIPdebugMsg(scip, "propexec in problem <%s> at depth %d%s\n", SCIPgetProbName(scip), SCIPgetDepth(scip),
    2667 SCIPinProbing(scip) ? " in probing" : "");
    2668
    2669 /* add the genvbounds in the genvboundstore as constraints to the problem; afterwards clear the genvboundstore */
    2670 if( propdata->propasconss )
    2671 {
    2672 SCIP_CALL( createConstraints(scip, prop, propdata) );
    2673 return SCIP_OKAY;
    2674 }
    2675
    2676 /* propagate locally and globally */
    2677 SCIP_CALL( execGenVBounds(scip, propdata, result, !SCIPinProbing(scip), NULL) );
    2678
    2679 /* when called in presolving stage the result is set to SCIP_SUCCESS instead of SCIP_REDUCEDDOM, this is corrected
    2680 * here
    2681 */
    2682 if( *result == SCIP_SUCCESS )
    2683 *result = SCIP_REDUCEDDOM;
    2684
    2685 SCIPdebugMsg(scip, "end of exec\n");
    2686
    2687 return SCIP_OKAY;
    2688}
    2689
    2690/** propagation conflict resolving method of propagator */
    2691static
    2692SCIP_DECL_PROPRESPROP(propRespropGenvbounds)
    2693{ /*lint --e{715}*/
    2694 SCIP_PROPDATA* propdata;
    2695 GENVBOUND* genvbound;
    2696 SCIP_Real boundval;
    2697 SCIP_Bool success;
    2698
    2699 SCIPdebugMsg(scip, "explain %s bound change of variable <%s>\n",
    2700 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
    2701
    2702 /* get propagator data */
    2703 propdata = SCIPpropGetData(prop);
    2704 assert(propdata != NULL);
    2705 assert(propdata->genvboundstore != NULL);
    2706
    2707 /* as inferinfo we passed the index of the genvbound that was used for propagation; the genvbound might have been
    2708 * replaced, but also the new genvbound at this position has the same variable on the left-hand side
    2709 */
    2710 assert(inferinfo >= 0);
    2711 assert(inferinfo < propdata->ngenvbounds);
    2712
    2713 *result = SCIP_DIDNOTFIND;
    2714
    2715 /* check also in optimized mode that inferinfo is correct */
    2716 if( inferinfo >= propdata->ngenvbounds)
    2717 {
    2718 SCIPerrorMessage("generalized variable bounds propagator received inferinfo out of range; propagation not resolved, safe to continue\n");
    2719 return SCIP_OKAY;
    2720 }
    2721
    2722 /* get genvbound responsible for the bound change */
    2723 genvbound = propdata->genvboundstore[inferinfo];
    2724 assert(genvbound != NULL);
    2725 assert(genvbound->var == infervar);
    2726
    2727 /* check also in optimized mode that inferinfo is correct */
    2728 if( genvbound->var != infervar )
    2729 {
    2730 SCIPerrorMessage("generalized variable bounds propagator received incorrect inferinfo; propagation not resolved, but it's safe to continue\n");
    2731 return SCIP_OKAY;
    2732 }
    2733
    2734 /* get value of bound change on left-hand side */
    2735 boundval = genvbound->boundtype == SCIP_BOUNDTYPE_LOWER
    2736 ? SCIPgetVarLbAtIndex(scip, genvbound->var, bdchgidx, TRUE)
    2737 : -SCIPgetVarUbAtIndex(scip, genvbound->var, bdchgidx, TRUE);
    2738
    2739 /* if left-hand side variable is integral, it suffices to explain a bound change greater than boundval - 1 */
    2740 if( SCIPvarIsIntegral(genvbound->var) )
    2741 {
    2742 SCIP_Real roundedboundval;
    2743
    2744 assert(SCIPisIntegral(scip, boundval));
    2745
    2746 roundedboundval = SCIPfeasCeil(scip, boundval - 1.0) + 2 * SCIPfeastol(scip);
    2747 boundval = MIN(boundval, roundedboundval);
    2748 }
    2749
    2750 /* resolve propagation */
    2751 SCIP_CALL( resolveGenVBoundPropagation(scip, genvbound, bdchgidx, &boundval, &success) );
    2752
    2753 if( success )
    2754 *result = SCIP_SUCCESS;
    2755
    2756 return SCIP_OKAY;
    2757}
    2758
    2759/** solving process deinitialization method of propagator (called before branch and bound process data is freed) */
    2760static
    2761SCIP_DECL_PROPEXITSOL(propExitsolGenvbounds)
    2762{ /*lint --e{715}*/
    2763 SCIP_PROPDATA* propdata;
    2764
    2765 assert(scip != NULL);
    2766 assert(prop != NULL);
    2767
    2769
    2770 SCIPdebugMsg(scip, "propexitsol in problem <%s>\n", SCIPgetProbName(scip));
    2771
    2772 /* get propagator data */
    2773 propdata = SCIPpropGetData(prop);
    2774 assert(propdata != NULL);
    2775
    2776 if( !SCIPisInRestart(scip) )
    2777 {
    2778 /* free all genvbounds if we are not in a restart */
    2779 SCIP_CALL( freeGenVBounds(scip, prop, propdata) );
    2780 }
    2781 else
    2782 {
    2783 /* free all genvbounds that use relax-only variables if we are in a restart */
    2784 SCIP_CALL( freeGenVBoundsRelaxOnly(scip, prop, propdata) );
    2785 }
    2786
    2787 /* drop and free all events */
    2788 SCIP_CALL( dropAndFreeEvents(scip, propdata) );
    2789
    2790 return SCIP_OKAY;
    2791}
    2792
    2793/** destructor of propagator to free user data (called when SCIP is exiting) */
    2794static
    2795SCIP_DECL_PROPFREE(propFreeGenvbounds)
    2796{ /*lint --e{715}*/
    2797 SCIP_PROPDATA* propdata;
    2798
    2800
    2801 /* free propagator data */
    2802 propdata = SCIPpropGetData(prop);
    2803 assert(propdata != NULL);
    2804
    2805 SCIPfreeBlockMemory(scip, &propdata);
    2806
    2807 SCIPpropSetData(prop, NULL);
    2808
    2809 return SCIP_OKAY;
    2810}
    2811
    2812
    2813/*
    2814 * Callback methods of event handler
    2815 */
    2816
    2817static
    2818SCIP_DECL_EVENTEXEC(eventExecGenvbounds)
    2819{ /*lint --e{715}*/
    2820 SCIP_PROPDATA* propdata;
    2822 int i;
    2823
    2826 assert(eventdata != NULL);
    2827 assert(eventdata->startcomponents != NULL);
    2828 assert(eventdata->startindices != NULL);
    2829 assert(eventdata->nstarts > 0);
    2830 assert(eventdata->prop != NULL);
    2831
    2832 /* ignore final events */
    2833 if( node == NULL )
    2834 return SCIP_OKAY;
    2835
    2836 propdata = SCIPpropGetData(eventdata->prop);
    2837 assert(propdata != NULL);
    2838
    2839 assert(propdata->startcomponents != NULL);
    2840 assert(propdata->startmap != NULL);
    2841 assert(propdata->startindices != NULL);
    2842
    2843 SCIPdebugMsg(scip, "catching eventdata:\n");
    2844 SCIPdebug( printEventData(eventdata, SCIPeventGetType(event) == SCIP_EVENTTYPE_LBTIGHTENED ?
    2846
    2847 /**@todo find a way to identify when we are at a new probing node; in probing mode, the node number is always zero,
    2848 * so we may miss resetting the starting data and may propagate more than necessary
    2849 */
    2850 /* check if we need to reset old local starting indices data */
    2851 if( SCIPnodeGetNumber(node) != propdata->lastnodenumber )
    2852 {
    2854 propdata->lastnodenumber = SCIPnodeGetNumber(node);
    2855 }
    2856
    2857 for( i = 0; i < eventdata->nstarts; i++ )
    2858 {
    2859 int component;
    2860 int startidx;
    2861
    2862 component = eventdata->startcomponents[i];
    2863 assert(component >= 0);
    2864 startidx = eventdata->startindices[i];
    2865
    2866 /* there is already an entry for this component */
    2867 if( SCIPhashmapExists(propdata->startmap, (void*)(size_t) (component + 1)) )
    2868 {
    2869 int componentidx;
    2870
    2871 /* get its index */
    2872 componentidx = (SCIPhashmapGetImageInt(propdata->startmap, (void*)(size_t) (component + 1))) - 1; /*lint !e571 !e776*/
    2873 assert(componentidx >= 0);
    2874 assert(propdata->startcomponents[componentidx] == component);
    2875
    2876 if( propdata->startindices[componentidx] > startidx )
    2877 propdata->startindices[componentidx] = startidx;
    2878 }
    2879 else
    2880 {
    2881 /* get a new entry */
    2882 int componentidx;
    2883 componentidx = propdata->nindices;
    2884
    2885 /* store index */
    2886 propdata->startcomponents[componentidx] = component;
    2887 propdata->startindices[componentidx] = startidx;
    2888
    2889 /* store component in hashmap */
    2890 SCIP_CALL( SCIPhashmapInsertInt(propdata->startmap, (void*)(size_t) (component + 1), componentidx + 1) ); /*lint !e571 !e776*/
    2891
    2892 /* increase number of starting indices */
    2893 propdata->nindices++;
    2894 }
    2895 }
    2896
    2897 return SCIP_OKAY;
    2898}
    2899
    2900/*
    2901 * propagator specific interface methods
    2902 */
    2903
    2904/** creates the genvbounds propagator and includes it in SCIP */
    2906 SCIP* scip /**< SCIP data structure */
    2907 )
    2908{
    2909 SCIP_PROPDATA* propdata;
    2910 SCIP_PROP* prop;
    2911
    2912 /* create genvbounds propagator data */
    2913 SCIP_CALL( SCIPallocBlockMemory(scip, &propdata) );
    2914 propdata->inittiming = PROP_TIMING;
    2915
    2916 /* include propagator */
    2918 propExecGenvbounds, propdata) );
    2919
    2920 SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopyGenvbounds) );
    2921 SCIP_CALL( SCIPsetPropFree(scip, prop, propFreeGenvbounds) );
    2922 SCIP_CALL( SCIPsetPropInit(scip, prop, propInitGenvbounds) );
    2923 SCIP_CALL( SCIPsetPropInitpre(scip, prop, propInitpreGenvbounds) );
    2924 SCIP_CALL( SCIPsetPropExitpre(scip, prop, propExitpreGenvbounds) );
    2925 SCIP_CALL( SCIPsetPropExit(scip, prop, propExitGenvbounds) );
    2926 SCIP_CALL( SCIPsetPropExitsol(scip, prop, propExitsolGenvbounds) );
    2927 SCIP_CALL( SCIPsetPropPresol(scip, prop, propPresolGenvbounds, PROP_PRESOL_PRIORITY,
    2929 SCIP_CALL( SCIPsetPropResprop(scip, prop, propRespropGenvbounds) );
    2930
    2931 SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/global",
    2932 "apply global propagation?",
    2933 &propdata->global, TRUE, DEFAULT_GLOBAL_PROPAGATION, NULL, NULL) );
    2934
    2935 SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/propinrootnode",
    2936 "apply genvbounds in root node if no new incumbent was found?",
    2937 &propdata->propinrootnode, TRUE, DEFAULT_PROPAGATE_IN_ROOT_NODE, NULL, NULL) );
    2938
    2939 SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/sort",
    2940 "sort genvbounds and wait for bound change events?",
    2941 &propdata->sort, TRUE, DEFAULT_SORT, NULL, NULL) );
    2942
    2943 SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/propasconss",
    2944 "should genvbounds be transformed to (linear) constraints?",
    2945 &propdata->propasconss, TRUE, DEFAULT_PROPASCONSS, NULL, NULL) );
    2946
    2947 /* include event handler */
    2948 SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &propdata->eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecGenvbounds, NULL) );
    2949
    2950 return SCIP_OKAY;
    2951}
    static long bound
    Constraint handler for linear constraints in their most general form, .
    methods for debugging
    #define SCIPdebugCheckLbGlobal(scip, var, lb)
    Definition: debug.h:299
    #define SCIPdebugGetSolVal(scip, var, val)
    Definition: debug.h:313
    #define SCIPdebugCheckUbGlobal(scip, var, ub)
    Definition: debug.h:300
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_INVALID
    Definition: def.h:187
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define SCIP_UNKNOWN
    Definition: def.h:188
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_CALL(x)
    Definition: def.h:364
    #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:8513
    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:2003
    SCIP_Bool SCIPisInRestart(SCIP *scip)
    Definition: scip_solve.c:3722
    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:23674
    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:23418
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4380
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24174
    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:23299
    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:23522
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
    Definition: var.c:23632
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    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:4322
    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
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    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