SCIP

    Solving Constraint Integer Programs

    cons_sos2.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 cons_sos2.c
    26 * @ingroup DEFPLUGINS_CONS
    27 * @brief constraint handler for SOS type 2 constraints
    28 * @author Marc Pfetsch
    29 *
    30 * A specially ordered set of type 2 (SOS2) is a sequence of variables such that at most two
    31 * variables are nonzero and if two variables are nonzero they must be adjacent in the specified
    32 * sequence. Note that it is in principle allowed that a variable appears twice, but it then can be
    33 * fixed to 0 if it is at least two apart in the sequence.
    34 *
    35 * This constraint is useful when considering a piecewise affine approximation of a univariate
    36 * (nonlinear) function \f$: [a,b] \rightarrow R\f$: Let \f$x_1 < \ldots < x_n\f$ be points in
    37 * \f$[a,b]\f$ and introduce variables \f$\lambda_1, \ldots, \lambda_n\f$. To evaluate \f$f(x')\f$
    38 * at some point \f$x' \in [a,b]\f$ one can use the following constraints:
    39 * \f[
    40 * \lambda_1 + \cdots + \lambda_n = 1,\quad x' = x_1 \lambda_1 + \cdots + x_n \lambda_n.
    41 * \f]
    42 * The value of \f$f(x')\f$ can the be approximated as
    43 * \f[
    44 * f(x_1) \lambda_1 + \cdots + f(x_n) \lambda_n.
    45 * \f]
    46 * To get a valid piecewise affine approximation, \f$\lambda_1, \ldots, \lambda_n\f$ have to obey an
    47 * SOS constraint of type 2.
    48 *
    49 * This implementation of this constraint handler is based on classical ideas, see e.g.@n
    50 * "Special Facilities in General Mathematical Programming System for
    51 * Non-Convex Problems Using Ordered Sets of Variables"@n
    52 * E. Beale and J. Tomlin, Proc. 5th IFORS Conference, 447-454 (1970)
    53 *
    54 * The order of the variables is determined as follows:
    55 *
    56 * - If the constraint is created with SCIPcreateConsSOS2() and weights are given, the weights
    57 * determine the order (decreasing weights). Additional variables can be added with
    58 * SCIPaddVarSOS2(), which adds a variable with given weight.
    59 *
    60 * - If an empty constraint is created and then variables are added with SCIPaddVarSOS2(), weights
    61 * are needed and stored.
    62 *
    63 * - All other calls ignore the weights, i.e., if a nonempty constraint is created or variables are
    64 * added with SCIPappendVarSOS2().
    65 *
    66 * @todo Allow to adapt the order of the constraints, e.g. by priorities. This for instance
    67 * determines the branching order.
    68 * @todo Separate the following cuts for each pair of variables x, y of at least distance 2 in the
    69 * SOS2 constraint: \f$ \min \{l_x, l_y\} \leq x + y \leq \max \{u_x, u_y\}\f$, where \f$l_x, u_x,
    70 * l_y, u_y\f$ are the lower and upper bounds of x and y, respectively.
    71 * @todo Possibly allow to generate local cuts via strengthened local cuts (would affect lhs/rhs of rows)
    72 * @todo Try to compute better estimations for the child nodes in enforceSOS2 when called for a relaxation solution;
    73 * currently pseudo costs are used, which are not computed for the relaxation.
    74 */
    75
    76/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    77
    79#include "scip/cons_linear.h"
    80#include "scip/cons_sos2.h"
    81#include "scip/pub_cons.h"
    82#include "scip/pub_event.h"
    83#include "scip/pub_lp.h"
    84#include "scip/pub_message.h"
    85#include "scip/pub_misc.h"
    86#include "scip/pub_misc_sort.h"
    87#include "scip/pub_var.h"
    88#include "scip/scip_branch.h"
    89#include "scip/scip_conflict.h"
    90#include "scip/scip_cons.h"
    91#include "scip/scip_copy.h"
    92#include "scip/scip_cut.h"
    93#include "scip/scip_event.h"
    94#include "scip/scip_general.h"
    95#include "scip/scip_lp.h"
    96#include "scip/scip_mem.h"
    97#include "scip/scip_message.h"
    98#include "scip/scip_numerics.h"
    99#include "scip/scip_prob.h"
    100#include "scip/scip_sol.h"
    101#include "scip/scip_var.h"
    102#include "scip/symmetry_graph.h"
    104#include <ctype.h>
    105#include <stdlib.h>
    106
    107
    108/* constraint handler properties */
    109#define CONSHDLR_NAME "SOS2"
    110#define CONSHDLR_DESC "SOS2 constraint handler"
    111#define CONSHDLR_SEPAPRIORITY 10 /**< priority of the constraint handler for separation */
    112#define CONSHDLR_ENFOPRIORITY 100 /**< priority of the constraint handler for constraint enforcing */
    113#define CONSHDLR_CHECKPRIORITY -10 /**< priority of the constraint handler for checking feasibility */
    114#define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
    115#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
    116#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
    117 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    118#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
    119#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
    120#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
    121#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
    122
    123#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
    124#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_FAST
    125
    126/* event handler properties */
    127#define EVENTHDLR_NAME "SOS2"
    128#define EVENTHDLR_DESC "bound change event handler for SOS2 constraints"
    129
    130#define EVENTHDLR_EVENT_TYPE (SCIP_EVENTTYPE_BOUNDCHANGED | SCIP_EVENTTYPE_GBDCHANGED)
    131
    132
    133/** constraint data for SOS2 constraints */
    134struct SCIP_ConsData
    135{
    136 int nvars; /**< number of variables in the constraint */
    137 int maxvars; /**< maximal number of variables (= size of storage) */
    138 int nfixednonzeros; /**< number of variables fixed to be nonzero */
    139 SCIP_VAR** vars; /**< variables in constraint */
    140 SCIP_ROW* row; /**< row corresponding to upper and lower bound inequalities, or NULL if not yet created */
    141 SCIP_Real* weights; /**< weights determining the order (ascending), or NULL if not used */
    142};
    143
    144/** SOS2 constraint handler data */
    145struct SCIP_ConshdlrData
    146{
    147 SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
    148};
    149
    150
    151/** fix variable in given node to 0 or add constraint if variable is multi-aggregated */
    152static
    154 SCIP* scip, /**< SCIP pointer */
    155 SCIP_VAR* var, /**< variable to be fixed to 0*/
    156 SCIP_NODE* node, /**< node */
    157 SCIP_Bool* infeasible /**< if fixing is infeasible */
    158 )
    159{
    160 /* if variable cannot be nonzero */
    161 *infeasible = FALSE;
    163 {
    164 *infeasible = TRUE;
    165 return SCIP_OKAY;
    166 }
    167
    168 /* if variable is multi-aggregated */
    170 {
    171 SCIP_CONS* cons;
    172 SCIP_Real val;
    173
    174 val = 1.0;
    175
    177 {
    178 SCIPdebugMsg(scip, "creating constraint to force multi-aggregated variable <%s> to 0.\n", SCIPvarGetName(var));
    179 /* we have to insert a local constraint var = 0 */
    180 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, "branch", 1, &var, &val, 0.0, 0.0, TRUE, TRUE, TRUE, TRUE, TRUE,
    181 TRUE, FALSE, FALSE, FALSE, FALSE) );
    182 SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
    183 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    184 }
    185 }
    186 else
    187 {
    189 SCIP_CALL( SCIPchgVarLbNode(scip, node, var, 0.0) );
    191 SCIP_CALL( SCIPchgVarUbNode(scip, node, var, 0.0) );
    192 }
    193
    194 return SCIP_OKAY;
    195}
    196
    197
    198/** fix variable in local node to 0, and return whether the operation was feasible
    199 *
    200 * @note We do not add a linear constraint if the variable is multi-aggregated as in
    201 * fixVariableZeroNode(), since this would be too time consuming.
    202 */
    203static
    205 SCIP* scip, /**< SCIP pointer */
    206 SCIP_VAR* var, /**< variable to be fixed to 0*/
    207 SCIP_CONS* cons, /**< constraint */
    208 int inferinfo, /**< info for reverse prop. */
    209 SCIP_Bool* infeasible, /**< if fixing is infeasible */
    210 SCIP_Bool* tightened, /**< if fixing was performed */
    211 SCIP_Bool* success /**< whether fixing was successful, i.e., variable is not multi-aggregated */
    212 )
    213{
    214 *infeasible = FALSE;
    215 *tightened = FALSE;
    216 *success = FALSE;
    217
    218 /* if variable cannot be nonzero */
    220 {
    221 *infeasible = TRUE;
    222 return SCIP_OKAY;
    223 }
    224
    225 /* directly fix variable if it is not multi-aggregated, do nothing otherwise */
    227 {
    228 SCIP_Bool tighten;
    229
    230 /* fix lower bound */
    231 SCIP_CALL( SCIPinferVarLbCons(scip, var, 0.0, cons, inferinfo, FALSE, infeasible, &tighten) );
    232 *tightened = *tightened || tighten;
    233
    234 /* fix upper bound */
    235 SCIP_CALL( SCIPinferVarUbCons(scip, var, 0.0, cons, inferinfo, FALSE, infeasible, &tighten) );
    236 *tightened = *tightened || tighten;
    237
    238 *success = TRUE;
    239 }
    240
    241 return SCIP_OKAY;
    242}
    243
    244
    245/** add lock on variable */
    246static
    248 SCIP* scip, /**< SCIP data structure */
    249 SCIP_CONS* cons, /**< constraint */
    250 SCIP_VAR* var /**< variable */
    251 )
    252{
    253 assert( scip != NULL );
    254 assert( cons != NULL );
    255 assert( var != NULL );
    256
    257 /* rounding down == bad if lb < 0, rounding up == bad if ub > 0 */
    260
    261 return SCIP_OKAY;
    262}
    263
    264
    265/** remove lock on variable */
    266static
    268 SCIP* scip, /**< SCIP data structure */
    269 SCIP_CONS* cons, /**< constraint */
    270 SCIP_VAR* var /**< variable */
    271 )
    272{
    273 assert( scip != NULL );
    274 assert( cons != NULL );
    275 assert( var != NULL );
    276
    277 /* rounding down == bad if lb < 0, rounding up == bad if ub > 0 */
    280
    281 return SCIP_OKAY;
    282}
    283
    284
    285/** ensures that the vars and weights array can store at least num entries */
    286static
    288 SCIP* scip, /**< SCIP data structure */
    289 SCIP_CONSDATA* consdata, /**< constraint data */
    290 int num, /**< minimum number of entries to store */
    291 SCIP_Bool reserveWeights /**< whether the weights array is handled */
    292 )
    293{
    294 assert( consdata != NULL );
    295 assert( consdata->nvars <= consdata->maxvars );
    296
    297 if ( num > consdata->maxvars )
    298 {
    299 int newsize;
    300
    301 newsize = SCIPcalcMemGrowSize(scip, num);
    302 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->maxvars, newsize) );
    303 if ( reserveWeights )
    304 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->weights, consdata->maxvars, newsize) );
    305 consdata->maxvars = newsize;
    306 }
    307 assert( num <= consdata->maxvars );
    308
    309 return SCIP_OKAY;
    310}
    311
    312
    313/** handle new variable */
    314static
    316 SCIP* scip, /**< SCIP data structure */
    317 SCIP_CONS* cons, /**< constraint */
    318 SCIP_CONSDATA* consdata, /**< constraint data */
    319 SCIP_VAR* var, /**< variable */
    320 SCIP_Bool transformed /**< whether original variable was transformed */
    321 )
    322{
    323 assert( scip != NULL );
    324 assert( cons != NULL );
    325 assert( consdata != NULL );
    326 assert( var != NULL );
    327
    328 /* if we are in transformed problem, catch the variable's events */
    329 if ( transformed )
    330 {
    331 SCIP_CONSHDLR* conshdlr;
    332 SCIP_CONSHDLRDATA* conshdlrdata;
    333
    334 /* get event handler */
    335 conshdlr = SCIPconsGetHdlr(cons);
    336 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    337 assert( conshdlrdata != NULL );
    338 assert( conshdlrdata->eventhdlr != NULL );
    339
    340 /* catch bound change events of variable */
    341 SCIP_CALL( SCIPcatchVarEvent(scip, var, EVENTHDLR_EVENT_TYPE, conshdlrdata->eventhdlr,
    342 (SCIP_EVENTDATA*)cons, NULL) );
    343
    344 /* if the variable if fixed to nonzero */
    345 assert( consdata->nfixednonzeros >= 0 );
    347 ++consdata->nfixednonzeros;
    348 }
    349
    350 /* install the rounding locks for the new variable */
    351 SCIP_CALL( lockVariableSOS2(scip, cons, var) );
    352
    353 /* add the new coefficient to the LP row, if necessary */
    354 if ( consdata->row != NULL )
    355 {
    356 /* this is currently dead code, since the constraint is not modifiable */
    357 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, 1.0) );
    358
    359 /* update lhs and rhs if necessary */
    360 if ( SCIPisFeasGT(scip, SCIPvarGetUbLocal(var), SCIProwGetRhs(consdata->row)) )
    361 SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, SCIPvarGetUbLocal(var) ) );
    362 if ( SCIPisFeasLT(scip, SCIPvarGetLbLocal(var), SCIProwGetLhs(consdata->row)) )
    363 SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, SCIPvarGetLbLocal(var) ) );
    364 }
    365
    366 return SCIP_OKAY;
    367}
    368
    369
    370/** adds a variable to an SOS2 constraint, a position given by weight - ascending order */
    371static
    373 SCIP* scip, /**< SCIP data structure */
    374 SCIP_CONS* cons, /**< constraint */
    375 SCIP_VAR* var, /**< variable to add to the constraint */
    376 SCIP_Real weight /**< weight to determine position */
    377 )
    378{
    379 SCIP_CONSDATA* consdata;
    380 SCIP_Bool transformed;
    381 int j;
    382 int pos;
    383
    384 assert( var != NULL );
    385 assert( cons != NULL );
    386
    387 consdata = SCIPconsGetData(cons);
    388 assert( consdata != NULL );
    389
    390 if ( consdata->weights == NULL && consdata->maxvars > 0 )
    391 {
    392 SCIPerrorMessage("cannot add variable to SOS2 constraint <%s> that does not contain weights.\n", SCIPconsGetName(cons));
    393 return SCIP_INVALIDCALL;
    394 }
    395
    396 /* are we in the transformed problem? */
    397 transformed = SCIPconsIsTransformed(cons);
    398
    399 /* always use transformed variables in transformed constraints */
    400 if ( transformed )
    401 {
    402 SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
    403 }
    404 assert( var != NULL );
    405 assert( transformed == SCIPvarIsTransformed(var) );
    406
    407 SCIP_CALL( consdataEnsurevarsSizeSOS2(scip, consdata, consdata->nvars + 1, TRUE) );
    408 assert( consdata->weights != NULL );
    409 assert( consdata->maxvars >= consdata->nvars+1 );
    410
    411 /* find variable position */
    412 for (pos = 0; pos < consdata->nvars; ++pos)
    413 {
    414 if ( consdata->weights[pos] > weight )
    415 break;
    416 }
    417 assert( 0 <= pos && pos <= consdata->nvars );
    418
    419 /* move other variables, if necessary */
    420 for (j = consdata->nvars; j > pos; --j)
    421 {
    422 consdata->vars[j] = consdata->vars[j-1];
    423 consdata->weights[j] = consdata->weights[j-1];
    424 }
    425
    426 /* insert variable */
    427 consdata->vars[pos] = var;
    428 consdata->weights[pos] = weight;
    429 ++consdata->nvars;
    430
    431 /* handle the new variable */
    432 SCIP_CALL( handleNewVariableSOS2(scip, cons, consdata, var, transformed) );
    433
    434 return SCIP_OKAY;
    435}
    436
    437
    438/** appends a variable to an SOS2 constraint */
    439static
    441 SCIP* scip, /**< SCIP data structure */
    442 SCIP_CONS* cons, /**< constraint */
    443 SCIP_VAR* var /**< variable to add to the constraint */
    444 )
    445{
    446 SCIP_CONSDATA* consdata;
    447 SCIP_Bool transformed;
    448
    449 assert( var != NULL );
    450 assert( cons != NULL );
    451
    452 consdata = SCIPconsGetData(cons);
    453 assert( consdata != NULL );
    454 assert( consdata->nvars >= 0 );
    455
    456 /* are we in the transformed problem? */
    457 transformed = SCIPconsIsTransformed(cons);
    458
    459 /* always use transformed variables in transformed constraints */
    460 if ( transformed )
    461 {
    462 SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
    463 }
    464 assert( var != NULL );
    465 assert( transformed == SCIPvarIsTransformed(var) );
    466
    467 if ( consdata->weights != NULL )
    468 {
    469 SCIP_CALL( consdataEnsurevarsSizeSOS2(scip, consdata, consdata->nvars + 1, TRUE) );
    470 }
    471 else
    472 {
    473 SCIP_CALL( consdataEnsurevarsSizeSOS2(scip, consdata, consdata->nvars + 1, FALSE) );
    474 }
    475
    476 /* insert variable */
    477 consdata->vars[consdata->nvars] = var;
    478 if ( consdata->weights != NULL )
    479 {
    480 if ( consdata->nvars > 0 )
    481 consdata->weights[consdata->nvars] = consdata->weights[consdata->nvars-1] + 1.0;
    482 else
    483 consdata->weights[consdata->nvars] = 0.0;
    484 }
    485 ++consdata->nvars;
    486
    487 /* handle the new variable */
    488 SCIP_CALL( handleNewVariableSOS2(scip, cons, consdata, var, transformed) );
    489
    490 return SCIP_OKAY;
    491}
    492
    493
    494/** deletes a variable of an SOS2 constraint */
    495static
    497 SCIP* scip, /**< SCIP data structure */
    498 SCIP_CONS* cons, /**< constraint */
    499 SCIP_CONSDATA* consdata, /**< constraint data */
    500 SCIP_EVENTHDLR* eventhdlr, /**< corresponding event handler */
    501 int pos /**< position of variable in array */
    502 )
    503{
    504 int j;
    505
    506 assert( 0 <= pos && pos < consdata->nvars );
    507
    508 /* remove lock of variable */
    509 SCIP_CALL( unlockVariableSOS2(scip, cons, consdata->vars[pos]) );
    510
    511 /* drop events on variable */
    512 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos], EVENTHDLR_EVENT_TYPE, eventhdlr, (SCIP_EVENTDATA*)cons, -1) );
    513
    514 /* delete variable - need to copy since order is important */
    515 for (j = pos; j < consdata->nvars-1; ++j)
    516 {
    517 consdata->vars[j] = consdata->vars[j+1]; /*lint !e679*/
    518 if ( consdata->weights != NULL )
    519 consdata->weights[j] = consdata->weights[j+1]; /*lint !e679*/
    520 }
    521 --consdata->nvars;
    522
    523 return SCIP_OKAY;
    524}
    525
    526
    527/** perform one presolving round
    528 *
    529 * We perform the following presolving steps.
    530 *
    531 * - If the bounds of one variable force it to be nonzero, we can fix all other variables with distance at least two to
    532 * zero. If two variables are certain to be nonzero, we can fix all other variables to 0 and remove the constraint.
    533 * - All variables fixed to zero, that are at the beginning or end of the constraint can be removed.
    534 * - We substitute appregated variables.
    535 * - If a constraint has at most two variables, we delete it.
    536 *
    537 * We currently do not handle the following:
    538 *
    539 * - If we have at least two variables fixed to zero next to each-other, that are positioned in the inner part of this
    540 * constraint, we can delete all but one of these variables.
    541 * - If a variable appears twice not next to each-other, it can be fixed to 0. If one variable appears next to
    542 * each-other and is already certain to be nonzero, we can fix all variables.
    543 * - If a binary variable and its negation appear in the constraint, we might fix variables to zero or can forbid a zero
    544 * value for them.
    545 * - When, after removing all zero "border" variables, a constraint with more than two variables has at most two
    546 * variables that are not fixed to 0, only one of these can take a nonzero value, because these variables need to be
    547 * the "border" variables of this constraint. The same holds if we have exactly three variables in one constraint and
    548 * the middle variable is certain to be not zero. In both cases we can upgrade this constraint constraint to an sos1
    549 * consisting only of the "border" variables. If these "border" variables are negations of each other, we can delete
    550 * this constraint.
    551 * - When, after removing all variables fixed to 0, that are possible, in a constraint each even positioned variable is
    552 * fixed to 0, we can upgrade this constraint to an sos1 that holds all non-fixed variables.
    553 * - Extract cliques for all odd and also for all even positioned binary variables
    554 */
    555static
    557 SCIP* scip, /**< SCIP pointer */
    558 SCIP_CONS* cons, /**< constraint */
    559 SCIP_CONSDATA* consdata, /**< constraint data */
    560 SCIP_EVENTHDLR* eventhdlr, /**< event handler */
    561 SCIP_Bool* cutoff, /**< whether a cutoff happened */
    562 SCIP_Bool* success, /**< whether we performed a successful reduction */
    563 int* ndelconss, /**< number of deleted constraints */
    564 int* nfixedvars, /**< number of fixed variables */
    565 int* nremovedvars /**< number of variables removed */
    566 )
    567{
    568 SCIP_VAR** vars;
    569 SCIP_Bool infeasible;
    570 SCIP_Bool fixed;
    571 int nfixednonzeros;
    572 int lastFixedNonzero;
    573 int lastzero;
    574 int localnremovedvars;
    575 int oldnfixedvars;
    576 int j;
    577
    578 assert( scip != NULL );
    579 assert( cons != NULL );
    580 assert( consdata != NULL );
    581 assert( eventhdlr != NULL );
    582 assert( cutoff != NULL );
    583 assert( success != NULL );
    584 assert( ndelconss != NULL );
    585 assert( nfixedvars != NULL );
    586 assert( nremovedvars != NULL );
    587
    588 *cutoff = FALSE;
    589 *success = FALSE;
    590
    591 SCIPdebugMsg(scip, "Presolving SOS2 constraint <%s>.\n", SCIPconsGetName(cons) );
    592
    593 /* if the number of variables is at most 2 */
    594 if( consdata->nvars <= 2 )
    595 {
    596 SCIPdebugMsg(scip, "Deleting constraint with <= 2 variables.\n");
    597
    598 /* delete constraint */
    599 assert( ! SCIPconsIsModifiable(cons) );
    600 SCIP_CALL( SCIPdelCons(scip, cons) );
    601 ++(*ndelconss);
    602 *success = TRUE;
    603
    604 return SCIP_OKAY;
    605 }
    606
    607 nfixednonzeros = 0;
    608 lastFixedNonzero = -1;
    609 vars = consdata->vars;
    610 lastzero = consdata->nvars;
    611 localnremovedvars = 0;
    612
    613 /* check for variables fixed to 0 and bounds that guarantee a variable to be nonzero; downward loop is important */
    614 for( j = consdata->nvars - 1; j >= 0; --j )
    615 {
    616 SCIP_VAR* var;
    617 SCIP_Real lb;
    618 SCIP_Real ub;
    619 SCIP_Real scalar;
    620 SCIP_Real constant;
    621
    622 /* check that our vars array is still correct */
    623 assert(vars == consdata->vars);
    624
    625 scalar = 1.0;
    626 constant = 0.0;
    627
    628 /* check aggregation: if the constant is zero, the variable is zero iff the aggregated variable is 0 */
    629 var = vars[j];
    630 SCIP_CALL( SCIPgetProbvarSum(scip, &var, &scalar, &constant) );
    631
    632 /* if constant is zero and we get a different variable, substitute variable */
    633 if ( SCIPisZero(scip, constant) && ! SCIPisZero(scip, scalar) && var != vars[j] )
    634 {
    635 SCIPdebugMsg(scip, "substituted variable <%s> by <%s>.\n", SCIPvarGetName(vars[j]), SCIPvarGetName(var));
    636 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[j], EVENTHDLR_EVENT_TYPE, eventhdlr, (SCIP_EVENTDATA*)cons, -1) );
    638
    639 /* change the rounding locks */
    640 SCIP_CALL( unlockVariableSOS2(scip, cons, consdata->vars[j]) );
    641 SCIP_CALL( lockVariableSOS2(scip, cons, var) );
    642
    643 vars[j] = var;
    644 }
    645
    646 /* get bounds */
    647 lb = SCIPvarGetLbLocal(vars[j]);
    648 ub = SCIPvarGetUbLocal(vars[j]);
    649
    650 /* if the variable if fixed to nonzero */
    652 {
    653 ++nfixednonzeros;
    654
    655 /* two variables certain to be nonzero which are not next to each other, so we are infeasible */
    656 if( lastFixedNonzero != -1 && lastFixedNonzero != j + 1 )
    657 {
    658 SCIPdebugMsg(scip, "The problem is infeasible: two non-consecutive variables have bounds that keep them from being 0.\n");
    659 *cutoff = TRUE;
    660 return SCIP_OKAY;
    661 }
    662
    663 /* if more than two variables are fixed to be nonzero, we are infeasible */
    664 if( nfixednonzeros > 2 )
    665 {
    666 SCIPdebugMsg(scip, "The problem is infeasible: more than two variables have bounds that keep them from being 0.\n");
    667 *cutoff = TRUE;
    668 return SCIP_OKAY;
    669 }
    670
    671 if( lastFixedNonzero == -1)
    672 lastFixedNonzero = j;
    673 }
    674
    675 /* if the variable is fixed to 0 we may delete it from our constraint */
    676 if( SCIPisFeasZero(scip, lb) && SCIPisFeasZero(scip, ub) )
    677 {
    678 /* all rear variables fixed to 0 can be deleted */
    679 if( j == consdata->nvars - 1 )
    680 {
    681 ++(*nremovedvars);
    682
    683 SCIPdebugMsg(scip, "deleting variable <%s> fixed to 0.\n", SCIPvarGetName(vars[j]));
    684 SCIP_CALL( deleteVarSOS2(scip, cons, consdata, eventhdlr, j) );
    685
    686 *success = TRUE;
    687 }
    688 /* remember position of last variable for which all up front and this one are fixed to 0 */
    689 else if( lastzero > j + 1 )
    690 lastzero = j;
    691 }
    692 else
    693 lastzero = consdata->nvars;
    694 }
    695
    696 /* check that our vars array is still correct */
    697 assert(vars == consdata->vars);
    698
    699 /* remove first "lastzero" many variables, that are already fixed to 0 */
    700 if( lastzero < consdata->nvars )
    701 {
    702 assert(lastzero >= 0);
    703
    704 for( j = lastzero; j >= 0; --j )
    705 {
    706 /* the variables should all be fixed to zero */
    708
    709 SCIPdebugMsg(scip, "deleting variable <%s> fixed to 0.\n", SCIPvarGetName(vars[j]));
    710 SCIP_CALL( deleteVarSOS2(scip, cons, consdata, eventhdlr, j) );
    711 }
    712 localnremovedvars += (lastzero + 1);
    713 *success = TRUE;
    714 }
    715
    716 /* check that our variable array is still correct */
    717 assert(vars == consdata->vars);
    718
    719 *nremovedvars += localnremovedvars;
    720
    721 /* we might need to correct the position of the first variable which is certain to be not zero */
    722 if( lastFixedNonzero >= 0 )
    723 {
    724 lastFixedNonzero -= localnremovedvars;
    725 assert(0 <= lastFixedNonzero && lastFixedNonzero < consdata->nvars);
    726 assert(SCIPisFeasPositive(scip, SCIPvarGetLbGlobal(vars[lastFixedNonzero])) || SCIPisFeasNegative(scip, SCIPvarGetUbGlobal(vars[lastFixedNonzero])));
    727 }
    728
    729 /* if the number of variables is at most 2 */
    730 if( consdata->nvars <= 2 )
    731 {
    732 SCIPdebugMsg(scip, "Deleting constraint with <= 2 variables.\n");
    733
    734 /* delete constraint */
    735 assert( ! SCIPconsIsModifiable(cons) );
    736 SCIP_CALL( SCIPdelCons(scip, cons) );
    737 ++(*ndelconss);
    738 *success = TRUE;
    739
    740 return SCIP_OKAY;
    741 }
    742
    743 oldnfixedvars = *nfixedvars;
    744
    745 /* if there is exactly one fixed nonzero variable */
    746 if ( nfixednonzeros == 1 )
    747 {
    748 assert(0 <= lastFixedNonzero && lastFixedNonzero < consdata->nvars);
    749 assert(SCIPisFeasPositive(scip, SCIPvarGetLbGlobal(vars[lastFixedNonzero])) ||
    750 SCIPisFeasNegative(scip, SCIPvarGetUbGlobal(vars[lastFixedNonzero])));
    751
    752 /* fix all other variables with distance two to zero */
    753 for( j = 0; j < lastFixedNonzero - 1; ++j )
    754 {
    755 SCIPdebugMsg(scip, "fixing variable <%s> to 0.\n", SCIPvarGetName(vars[j]));
    756 SCIP_CALL( SCIPfixVar(scip, vars[j], 0.0, &infeasible, &fixed) );
    757
    758 if( infeasible )
    759 {
    760 *cutoff = TRUE;
    761 return SCIP_OKAY;
    762 }
    763
    764 if ( fixed )
    765 ++(*nfixedvars);
    766 }
    767 for( j = lastFixedNonzero + 2; j < consdata->nvars; ++j )
    768 {
    769 SCIPdebugMsg(scip, "fixing variable <%s> to 0.\n", SCIPvarGetName(vars[j]));
    770 SCIP_CALL( SCIPfixVar(scip, vars[j], 0.0, &infeasible, &fixed) );
    771
    772 if( infeasible )
    773 {
    774 *cutoff = TRUE;
    775 return SCIP_OKAY;
    776 }
    777
    778 if ( fixed )
    779 ++(*nfixedvars);
    780 }
    781
    782 if( *nfixedvars > oldnfixedvars )
    783 *success = TRUE;
    784 }
    785 /* if there are exactly two fixed nonzero variables */
    786 else if ( nfixednonzeros == 2 )
    787 {
    788 assert(0 < lastFixedNonzero && lastFixedNonzero < consdata->nvars);
    789 assert(SCIPisFeasPositive(scip, SCIPvarGetLbGlobal(vars[lastFixedNonzero])) ||
    790 SCIPisFeasNegative(scip, SCIPvarGetUbGlobal(vars[lastFixedNonzero])));
    791 /* the previous variable need also to be nonzero, otherwise the infeasibility should have been detected earlier */
    792 assert(SCIPisFeasPositive(scip, SCIPvarGetLbGlobal(vars[lastFixedNonzero - 1])) ||
    793 SCIPisFeasNegative(scip, SCIPvarGetUbGlobal(vars[lastFixedNonzero - 1])));
    794
    795 /* fix all variables before lastFixedNonzero to zero */
    796 for( j = 0; j < lastFixedNonzero - 1; ++j )
    797 {
    798 SCIPdebugMsg(scip, "fixing variable <%s> to 0.\n", SCIPvarGetName(vars[j]));
    799 SCIP_CALL( SCIPfixVar(scip, vars[j], 0.0, &infeasible, &fixed) );
    800
    801 if( infeasible )
    802 {
    803 *cutoff = TRUE;
    804 return SCIP_OKAY;
    805 }
    806 if ( fixed )
    807 ++(*nfixedvars);
    808 }
    809 /* fix all variables after lastFixedNonzero + 1 to zero */
    810 for( j = lastFixedNonzero + 1; j < consdata->nvars; ++j )
    811 {
    812 SCIPdebugMsg(scip, "fixing variable <%s> to 0.\n", SCIPvarGetName(vars[j]));
    813 SCIP_CALL( SCIPfixVar(scip, vars[j], 0.0, &infeasible, &fixed) );
    814
    815 if( infeasible )
    816 {
    817 *cutoff = TRUE;
    818 return SCIP_OKAY;
    819 }
    820 if ( fixed )
    821 ++(*nfixedvars);
    822 }
    823
    824 /* delete constraint */
    825 assert( ! SCIPconsIsModifiable(cons) );
    826 SCIP_CALL( SCIPdelCons(scip, cons) );
    827 ++(*ndelconss);
    828 *success = TRUE;
    829 }
    830
    831 return SCIP_OKAY;
    832}
    833
    834
    835/** propagate variables */
    836static
    838 SCIP* scip, /**< SCIP pointer */
    839 SCIP_CONS* cons, /**< constraint */
    840 SCIP_CONSDATA* consdata, /**< constraint data */
    841 SCIP_Bool* cutoff, /**< whether a cutoff happened */
    842 int* ngen /**< pointer to incremental counter for domain changes */
    843 )
    844{
    845 int ngenold;
    846
    847 assert( scip != NULL );
    848 assert( cons != NULL );
    849 assert( consdata != NULL );
    850 assert( cutoff != NULL );
    851 assert( ngen != NULL );
    852
    853 *cutoff = FALSE;
    854 ngenold = *ngen;
    855
    856 /* if more than two variables are fixed to be nonzero */
    857 if ( consdata->nfixednonzeros > 2 )
    858 {
    859 SCIPdebugMsg(scip, "the node is infeasible, more than 2 variables are fixed to be nonzero.\n");
    861 *cutoff = TRUE;
    862 return SCIP_OKAY;
    863 }
    864
    865 /* if exactly one variable is fixed to be nonzero */
    866 if ( consdata->nfixednonzeros == 1 )
    867 {
    868 SCIP_VAR** vars;
    869 SCIP_Bool infeasible;
    870 SCIP_Bool tightened;
    871 SCIP_Bool success;
    872 int firstFixedNonzero;
    873 int nvars;
    874 int j;
    875
    876 firstFixedNonzero = -1;
    877 nvars = consdata->nvars;
    878 vars = consdata->vars;
    879 assert( vars != NULL );
    880
    881 /* search nonzero variable */
    882 for (j = 0; j < nvars; ++j)
    883 {
    885 {
    886 firstFixedNonzero = j;
    887 break;
    888 }
    889 }
    890 assert( firstFixedNonzero >= 0 );
    891
    892 SCIPdebugMsg(scip, "variable <%s> is nonzero, fixing variables with distance at least 2 to 0.\n", SCIPvarGetName(vars[firstFixedNonzero]));
    893
    894 /* fix variables before firstFixedNonzero-1 to 0 */
    895 for (j = 0; j < firstFixedNonzero-1; ++j)
    896 {
    897 /* fix variable */
    898 SCIP_CALL( inferVariableZero(scip, vars[j], cons, firstFixedNonzero, &infeasible, &tightened, &success) );
    899 assert( ! infeasible );
    900
    901 if ( tightened )
    902 ++(*ngen);
    903 }
    904
    905 /* fix variables after firstFixedNonzero+1 to 0 */
    906 for (j = firstFixedNonzero+2; j < nvars; ++j)
    907 {
    908 /* fix variable */
    909 SCIP_CALL( inferVariableZero(scip, vars[j], cons, firstFixedNonzero, &infeasible, &tightened, &success) );
    910
    911 /* no variable after firstFixedNonzero+1 should be fixed to be nonzero */
    912 if ( infeasible )
    913 {
    915 SCIPdebugMsg(scip, "the node is infeasible: variable <%s> is fixed nonzero and variable <%s> with distance at least 2 as well.\n",
    916 SCIPvarGetName(vars[firstFixedNonzero]), SCIPvarGetName(vars[j]));
    917 *cutoff = TRUE;
    918 return SCIP_OKAY;
    919 }
    920
    921 if ( tightened )
    922 ++(*ngen);
    923 }
    924 /* cannot locally delete constraint, since position of second entry is not fixed! */
    925 } /*lint !e438*/
    926 /* if exactly two variables are fixed to be nonzero */
    927 else if ( consdata->nfixednonzeros == 2 )
    928 {
    929 SCIP_VAR** vars;
    930 SCIP_Bool infeasible;
    931 SCIP_Bool tightened;
    932 SCIP_Bool success;
    933 SCIP_Bool allVarFixed;
    934 int firstFixedNonzero;
    935 int nvars;
    936 int j;
    937
    938 firstFixedNonzero = -1;
    939 nvars = consdata->nvars;
    940 vars = consdata->vars;
    941 assert( vars != NULL );
    942
    943 /* search nonzero variable */
    944 for (j = 0; j < nvars; ++j)
    945 {
    947 {
    948 firstFixedNonzero = j;
    949 break;
    950 }
    951 }
    952 assert( 0 <= firstFixedNonzero && firstFixedNonzero < nvars-1 );
    953
    954 SCIPdebugMsg(scip, "variable <%s> is fixed to be nonzero, fixing variables to 0.\n", SCIPvarGetName(vars[firstFixedNonzero]));
    955
    956 /* fix variables before firstFixedNonzero to 0 */
    957 allVarFixed = TRUE;
    958 for (j = 0; j < firstFixedNonzero; ++j)
    959 {
    960 /* fix variable */
    961 SCIP_CALL( inferVariableZero(scip, vars[j], cons, firstFixedNonzero+1, &infeasible, &tightened, &success) );
    962 assert( ! infeasible );
    963 allVarFixed = allVarFixed && success;
    964 if ( tightened )
    965 ++(*ngen);
    966 }
    967
    968 /* fix variables after firstFixedNonzero+1 to 0 */
    969 for (j = firstFixedNonzero+2; j < nvars; ++j)
    970 {
    971 /* fix variable */
    972 SCIP_CALL( inferVariableZero(scip, vars[j], cons, firstFixedNonzero, &infeasible, &tightened, &success) );
    973
    974 /* no variable after firstFixedNonzero+1 should be fixed to be nonzero */
    975 if ( infeasible )
    976 {
    978 SCIPdebugMsg(scip, "the node is infeasible: variable <%s> is fixed nonzero and variable <%s> with distance at least 2 as well.\n",
    979 SCIPvarGetName(vars[firstFixedNonzero]), SCIPvarGetName(vars[j]));
    980 *cutoff = TRUE;
    981 return SCIP_OKAY;
    982 }
    983 allVarFixed = allVarFixed && success;
    984
    985 if ( tightened )
    986 ++(*ngen);
    987 }
    988
    989 /* delete constraint locally, since the nonzero positions are fixed */
    990 if ( allVarFixed )
    991 {
    992 SCIPdebugMsg(scip, "locally deleting constraint <%s>.\n", SCIPconsGetName(cons));
    993 assert( !SCIPconsIsModifiable(cons) );
    995 }
    996 }
    997
    998 /* reset constraint age counter */
    999 if ( *ngen > ngenold )
    1001
    1002 return SCIP_OKAY;
    1003}
    1004
    1005
    1006/** enforcement method
    1007 *
    1008 * We check whether the current solution is feasible, i.e., contains
    1009 * at most one nonzero variable. If not, we branch along the lines
    1010 * indicated by Beale and Tomlin:
    1011 *
    1012 * We first compute \f$W = \sum_{j=1}^n |x_i|\f$ and \f$w =
    1013 * \sum_{j=1}^n j\, |x_i|\f$. Then we search for the index \f$k\f$ that
    1014 * satisfies
    1015 * \f[
    1016 * k \leq \frac{w}{W} < k+1.
    1017 * \f]
    1018 * The branches are then
    1019 * \f[
    1020 * x_1 = 0, \ldots, x_{k-1} = 0 \qquad \mbox{and}\qquad
    1021 * x_{k+1} = 0, \ldots, x_n = 0.
    1022 * \f]
    1023 *
    1024 * There is one special case that we have to consider: It can happen
    1025 * that \f$k\f$ is one too small. Example: \f$x_1 = 1 - \epsilon, x_2
    1026 * = 0, x_3 = \epsilon\f$. Then \f$w = 1 - \epsilon + 3 \epsilon = 1
    1027 * + 2 \epsilon\f$. This yields \f$k = 1\f$ and hence the first
    1028 * branch does not change the solution. We therefore increase \f$k\f$
    1029 * by one if \f$x_k \neq 0\f$. This is valid, since we know that
    1030 * \f$x_{k+1} \neq 0\f$ (with respect to the original \f$k\f$); the
    1031 * corresponding branch will cut off the current solution, since
    1032 * \f$x_k \neq 0\f$.
    1033 */
    1034static
    1036 SCIP* scip, /**< SCIP pointer */
    1037 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    1038 int nconss, /**< number of constraints */
    1039 SCIP_CONS** conss, /**< indicator constraints */
    1040 SCIP_SOL* sol, /**< solution to be enforced (NULL for LP solution) */
    1041 SCIP_RESULT* result /**< result */
    1042 )
    1043{
    1044 SCIP_CONSDATA* consdata;
    1045 SCIP_Bool infeasible;
    1046 SCIP_NODE* node1;
    1047 SCIP_NODE* node2;
    1049 SCIP_VAR** vars;
    1050 SCIP_Real nodeselest;
    1051 SCIP_Real objest;
    1052 int nvars;
    1053 int maxNonzeros;
    1054 int maxInd;
    1055 int j;
    1056 int c;
    1057
    1058 assert( scip != NULL );
    1059 assert( conshdlr != NULL );
    1060 assert( conss != NULL );
    1061 assert( result != NULL );
    1062
    1063 maxNonzeros = 0;
    1064 maxInd = -1;
    1065
    1066 SCIPdebugMsg(scip, "Enforcing SOS2 constraints <%s>.\n", SCIPconshdlrGetName(conshdlr) );
    1067 *result = SCIP_FEASIBLE;
    1068
    1069 /* check each constraint */
    1070 for (c = 0; c < nconss; ++c)
    1071 {
    1072 SCIP_CONS* cons;
    1073 SCIP_Bool cutoff;
    1074 SCIP_Real weight1;
    1075 SCIP_Real weight2;
    1076 SCIP_Real w;
    1077 int lastNonzero;
    1078 int ngen;
    1079 int cnt;
    1080 int ind;
    1081
    1082 cons = conss[c];
    1083 assert( cons != NULL );
    1084
    1085 consdata = SCIPconsGetData(cons);
    1086 assert( consdata != NULL );
    1087
    1088 nvars = consdata->nvars;
    1089 vars = consdata->vars;
    1090
    1091 /* do nothing if there are not enough variables - this is usually eliminated by preprocessing */
    1092 if ( nvars <= 2 )
    1093 continue;
    1094
    1095 ngen = 0;
    1096
    1097 /* first perform propagation (it might happen that standard propagation is turned off) */
    1098 SCIP_CALL( propSOS2(scip, cons, consdata, &cutoff, &ngen) );
    1099 SCIPdebugMsg(scip, "propagating <%s> in enforcing (cutoff: %u, domain reductions: %d).\n", SCIPconsGetName(cons), cutoff, ngen);
    1100 if ( cutoff )
    1101 {
    1102 *result = SCIP_CUTOFF;
    1103 return SCIP_OKAY;
    1104 }
    1105 if ( ngen > 0 )
    1106 {
    1107 *result = SCIP_REDUCEDDOM;
    1108 return SCIP_OKAY;
    1109 }
    1110
    1111 cnt = 0;
    1112 weight1 = 0.0;
    1113 weight2 = 0.0;
    1114 lastNonzero = -1;
    1115
    1116 /* compute weight */
    1117 for (j = 0; j < nvars; ++j)
    1118 {
    1119 SCIP_Real val;
    1120
    1121 val = REALABS(SCIPgetSolVal(scip, sol, vars[j]));
    1122 weight1 += val * (SCIP_Real) j;
    1123 weight2 += val;
    1124
    1125 if ( ! SCIPisFeasZero(scip, val) )
    1126 {
    1127 lastNonzero = j;
    1128 ++cnt;
    1129 }
    1130 }
    1131
    1132 /* if at most one variable is nonzero, the constraint is feasible */
    1133 if ( cnt < 2 )
    1134 continue;
    1135
    1136 /* if two adjacent variables are nonzero */
    1137 assert( 0 < lastNonzero && lastNonzero < nvars );
    1138 if ( cnt == 2 && ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, vars[lastNonzero-1])) )
    1139 continue;
    1140
    1141 assert( !SCIPisFeasZero(scip, weight2) );
    1142 w = weight1/weight2; /*lint !e795*/
    1143
    1144 ind = (int) SCIPfeasFloor(scip, w);
    1145 assert( 0 <= ind && ind < nvars-1 );
    1146
    1147 /* correct index if necessary - see above for an explanation */
    1148 if ( ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, vars[ind])) && ind < lastNonzero-1 )
    1149 ++ind;
    1150
    1151 /* check if the constraint has more nonzeros */
    1152 if ( cnt > maxNonzeros )
    1153 {
    1154 maxNonzeros = cnt;
    1155 branchCons = cons;
    1156 maxInd = ind;
    1157 }
    1158 }
    1159
    1160 /* if all constraints are feasible */
    1161 if ( branchCons == NULL )
    1162 {
    1163 SCIPdebugMsg(scip, "All SOS2 constraints are feasible.\n");
    1164 return SCIP_OKAY;
    1165 }
    1166
    1167 /* create branches */
    1168 consdata = SCIPconsGetData(branchCons);
    1169 assert( consdata != NULL );
    1170 nvars = consdata->nvars;
    1171 vars = consdata->vars;
    1172
    1173 assert( 0 < maxInd && maxInd < nvars-1 );
    1174
    1175 /* branch on variable ind: either all variables before ind or all variables after ind are zero */
    1176 SCIPdebugMsg(scip, "Branching on variable <%s> in constraint <%s> (nonzeros: %d).\n", SCIPvarGetName(vars[maxInd]),
    1177 SCIPconsGetName(branchCons), maxNonzeros);
    1178
    1179 /* calculate node selection and objective estimate for node 1 */
    1180 nodeselest = 0.0;
    1182 for (j = 0; j < maxInd; ++j)
    1183 {
    1184 objest += SCIPcalcChildEstimateIncrease(scip, vars[j], SCIPgetSolVal(scip, sol, vars[j]), 0.0);
    1185 nodeselest += SCIPcalcNodeselPriority(scip, vars[j], SCIP_BRANCHDIR_DOWNWARDS, 0.0);
    1186 }
    1187 assert( objest >= SCIPgetLocalTransEstimate(scip) );
    1188
    1189 /* create node 1 */
    1190 SCIP_CALL( SCIPcreateChild(scip, &node1, nodeselest, objest) );
    1191
    1192 for (j = 0; j < maxInd; ++j)
    1193 {
    1194 SCIP_CALL( fixVariableZeroNode(scip, vars[j], node1, &infeasible) );
    1195 assert( ! infeasible );
    1196 }
    1197
    1198 /* calculate node selection and objective estimate for node 2 */
    1199 nodeselest = 0.0;
    1201 for (j = maxInd+1; j < nvars; ++j)
    1202 {
    1203 objest += SCIPcalcChildEstimateIncrease(scip, vars[j], SCIPgetSolVal(scip, sol, vars[j]), 0.0);
    1204 nodeselest += SCIPcalcNodeselPriority(scip, vars[j], SCIP_BRANCHDIR_DOWNWARDS, 0.0);
    1205 }
    1206 assert( objest >= SCIPgetLocalTransEstimate(scip) );
    1207
    1208 /* create node 2 */
    1209 SCIP_CALL( SCIPcreateChild(scip, &node2, nodeselest, objest) );
    1210 for (j = maxInd+1; j < nvars; ++j)
    1211 {
    1212 SCIP_CALL( fixVariableZeroNode(scip, vars[j], node2, &infeasible) );
    1213 assert( ! infeasible );
    1214 }
    1216 *result = SCIP_BRANCHED;
    1217
    1218 return SCIP_OKAY;
    1219}
    1220
    1221
    1222/** Generate basic row
    1223 *
    1224 * We generate the row corresponding to the following simple valid
    1225 * inequalities. Let \f$U\f$ and \f$U'\f$ be the largest and second
    1226 * largest upper bound of variables appearing in the
    1227 * constraint. Similarly let \f$L\f$ and \f$L'\f$ be the smallest and
    1228 * second smallest lower bound. The inequalities are:
    1229 * \f[
    1230 * x_1 + \ldots + x_n \leq U + U' \qquad\mbox{and}\qquad
    1231 * x_1 + \ldots + x_n \geq L + L'.
    1232 * \f]
    1233 * Of course, these inequalities are only added if the upper and
    1234 * lower bounds are all finite and \f$L+L' < 0\f$ or \f$U+U' > 0\f$.
    1235 */
    1236static
    1238 SCIP* scip, /**< SCIP pointer */
    1239 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    1240 SCIP_CONS* cons, /**< constraint */
    1241 SCIP_Bool local /**< produce local cut? */
    1242 )
    1243{
    1244 char name[SCIP_MAXSTRLEN];
    1245 SCIP_CONSDATA* consdata;
    1246 SCIP_VAR** vars;
    1247 SCIP_Real minLb = SCIPinfinity(scip);
    1248 SCIP_Real minLb2 = SCIPinfinity(scip);
    1249 SCIP_Real maxUb = -SCIPinfinity(scip);
    1250 SCIP_Real maxUb2 = -SCIPinfinity(scip);
    1251 SCIP_Real lhs;
    1252 SCIP_Real rhs;
    1253 SCIP_ROW* row;
    1254 int nvars;
    1255 int j;
    1256
    1257 assert( scip != NULL );
    1258 assert( conshdlr != NULL );
    1259 assert( cons != NULL );
    1260
    1261 consdata = SCIPconsGetData(cons);
    1262 assert( consdata != NULL );
    1263 assert( consdata->row == NULL );
    1264
    1265 nvars = consdata->nvars;
    1266 vars = consdata->vars;
    1267 assert( vars != NULL );
    1268
    1269 /* find minimum and maximum lower and upper bounds */
    1270 for (j = 0; j < nvars; ++j)
    1271 {
    1272 SCIP_Real val;
    1273
    1274 if ( local )
    1275 val = SCIPvarGetLbLocal(vars[j]);
    1276 else
    1277 val = SCIPvarGetLbGlobal(vars[j]);
    1278
    1279 if ( val < minLb )
    1280 {
    1281 minLb2 = minLb;
    1282 minLb = val;
    1283 }
    1284 else
    1285 {
    1286 if ( val < minLb2 )
    1287 minLb2 = val;
    1288 }
    1289
    1290 if ( local )
    1291 val = SCIPvarGetUbLocal(vars[j]);
    1292 else
    1293 val = SCIPvarGetUbGlobal(vars[j]);
    1294
    1295 if ( val > maxUb )
    1296 {
    1297 maxUb2 = maxUb;
    1298 maxUb = val;
    1299 }
    1300 else
    1301 {
    1302 if ( val > maxUb2 )
    1303 maxUb2 = val;
    1304 }
    1305 }
    1306 lhs = minLb + minLb2;
    1307 rhs = maxUb + maxUb2;
    1308
    1309 /* ignore trivial inequality if left hand side would be 0 */
    1310 if ( SCIPisFeasZero(scip, lhs) )
    1311 lhs = -SCIPinfinity(scip);
    1312
    1313 /* ignore trivial inequality if right hand side would be 0 */
    1314 if ( SCIPisFeasZero(scip, rhs) )
    1315 rhs = SCIPinfinity(scip);
    1316
    1317 /* create upper and lower bound inequality if one of the bounds is finite */
    1318 if ( ! SCIPisInfinity(scip, REALABS(lhs)) || ! SCIPisInfinity(scip, REALABS(rhs)) )
    1319 {
    1320 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "sos2bnd#%s", SCIPconsGetName(cons));
    1321 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, cons, name, lhs, rhs, local, FALSE, FALSE) );
    1322 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, row, nvars, vars, 1.0) );
    1323 consdata->row = row;
    1324
    1326 }
    1327
    1328 return SCIP_OKAY;
    1329}
    1330
    1331
    1332/* ---------------------------- constraint handler callback methods ----------------------*/
    1333
    1334/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    1335static
    1336SCIP_DECL_CONSHDLRCOPY(conshdlrCopySOS2)
    1337{ /*lint --e{715}*/
    1338 assert( scip != NULL );
    1339 assert( conshdlr != NULL );
    1340
    1342
    1343 /* call inclusion method of constraint handler */
    1345
    1346 *valid = TRUE;
    1347
    1348 return SCIP_OKAY;
    1349}
    1350
    1351
    1352/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
    1353static
    1355{
    1356 SCIP_CONSHDLRDATA* conshdlrdata;
    1357
    1358 assert( scip != NULL );
    1359 assert( conshdlr != NULL );
    1360
    1362
    1363 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    1364 assert(conshdlrdata != NULL);
    1365
    1366 SCIPfreeBlockMemory(scip, &conshdlrdata);
    1367
    1368 return SCIP_OKAY;
    1369}
    1370
    1371
    1372/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
    1373static
    1375{ /*lint --e{715}*/
    1376 int c;
    1377
    1378 assert( scip != NULL );
    1379 assert( conshdlr != NULL );
    1380
    1382
    1383 /* check each constraint */
    1384 for (c = 0; c < nconss; ++c)
    1385 {
    1386 SCIP_CONSDATA* consdata;
    1387
    1388 assert( conss != NULL );
    1389 assert( conss[c] != NULL );
    1390 consdata = SCIPconsGetData(conss[c]);
    1391 assert( consdata != NULL );
    1392
    1393 SCIPdebugMsg(scip, "Exiting SOS2 constraint <%s>.\n", SCIPconsGetName(conss[c]) );
    1394
    1395 /* free row */
    1396 if ( consdata->row != NULL )
    1397 {
    1398 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
    1399 }
    1400 }
    1401 return SCIP_OKAY;
    1402}
    1403
    1404
    1405/** frees specific constraint data */
    1406static
    1408{
    1409 assert( scip != NULL );
    1410 assert( conshdlr != NULL );
    1411 assert( cons != NULL );
    1412 assert( consdata != NULL );
    1413
    1415
    1416 SCIPdebugMsg(scip, "Deleting SOS2 constraint <%s>.\n", SCIPconsGetName(cons) );
    1417
    1418 /* drop events on transformed variables */
    1419 if ( SCIPconsIsTransformed(cons) )
    1420 {
    1421 SCIP_CONSHDLRDATA* conshdlrdata;
    1422 int j;
    1423
    1424 /* get constraint handler data */
    1425 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    1426 assert( conshdlrdata != NULL );
    1427 assert( conshdlrdata->eventhdlr != NULL );
    1428
    1429 for (j = 0; j < (*consdata)->nvars; ++j)
    1430 {
    1431 SCIP_CALL( SCIPdropVarEvent(scip, (*consdata)->vars[j], EVENTHDLR_EVENT_TYPE, conshdlrdata->eventhdlr,
    1432 (SCIP_EVENTDATA*)cons, -1) );
    1433 }
    1434 }
    1435
    1436 SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, (*consdata)->maxvars);
    1437 if ( (*consdata)->weights != NULL )
    1438 {
    1439 SCIPfreeBlockMemoryArray(scip, &(*consdata)->weights, (*consdata)->maxvars);
    1440 }
    1441
    1442 /* free row */
    1443 if ( (*consdata)->row != NULL )
    1444 {
    1445 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
    1446 }
    1447 assert( (*consdata)->row == NULL );
    1448
    1449 SCIPfreeBlockMemory(scip, consdata);
    1450
    1451 return SCIP_OKAY;
    1452}
    1453
    1454
    1455/** transforms constraint data into data belonging to the transformed problem */
    1456static
    1458{
    1459 SCIP_CONSDATA* consdata;
    1460 SCIP_CONSHDLRDATA* conshdlrdata;
    1461 SCIP_CONSDATA* sourcedata;
    1462 char s[SCIP_MAXSTRLEN];
    1463 int j;
    1464
    1465 assert( scip != NULL );
    1466 assert( conshdlr != NULL );
    1467 assert( sourcecons != NULL );
    1468 assert( targetcons != NULL );
    1469
    1471
    1472 /* get constraint handler data */
    1473 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    1474 assert( conshdlrdata != NULL );
    1475 assert( conshdlrdata->eventhdlr != NULL );
    1476
    1477 SCIPdebugMsg(scip, "Transforming SOS2 constraint: <%s>.\n", SCIPconsGetName(sourcecons) );
    1478
    1479 /* get data of original constraint */
    1480 sourcedata = SCIPconsGetData(sourcecons);
    1481 assert( sourcedata != NULL );
    1482 assert( sourcedata->nvars > 0 );
    1483 assert( sourcedata->nvars <= sourcedata->maxvars );
    1484
    1485 /* create constraint data */
    1486 SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
    1487
    1488 consdata->nvars = sourcedata->nvars;
    1489 consdata->maxvars = sourcedata->nvars;
    1490 consdata->row = NULL;
    1491 consdata->nfixednonzeros = 0;
    1492 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars, consdata->nvars) );
    1493
    1494 /* if weights were used */
    1495 if ( sourcedata->weights != NULL )
    1496 {
    1497 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->weights, sourcedata->weights, consdata->nvars) );
    1498 }
    1499 else
    1500 consdata->weights = NULL;
    1501
    1502 for (j = 0; j < sourcedata->nvars; ++j)
    1503 {
    1504 assert( sourcedata->vars[j] != 0 );
    1505 SCIP_CALL( SCIPgetTransformedVar(scip, sourcedata->vars[j], &(consdata->vars[j])) );
    1506
    1507 /* if variable is fixed to be nonzero */
    1508 if ( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(consdata->vars[j])) || SCIPisFeasNegative(scip, SCIPvarGetUbLocal(consdata->vars[j])) )
    1509 ++(consdata->nfixednonzeros);
    1510 }
    1511
    1512 /* create transformed constraint with the same flags */
    1513 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "t_%s", SCIPconsGetName(sourcecons));
    1514 SCIP_CALL( SCIPcreateCons(scip, targetcons, s, conshdlr, consdata,
    1515 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
    1516 SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons),
    1517 SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
    1518 SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
    1519 SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
    1520
    1521 /* catch bound change events on variable */
    1522 for (j = 0; j < consdata->nvars; ++j)
    1523 {
    1524 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[j], EVENTHDLR_EVENT_TYPE, conshdlrdata->eventhdlr,
    1525 (SCIP_EVENTDATA*)*targetcons, NULL) );
    1526 }
    1527
    1528#ifdef SCIP_DEBUG
    1529 if ( consdata->nfixednonzeros > 0 )
    1530 {
    1531 SCIPdebugMsg(scip, "constraint <%s> has %d variables fixed to be nonzero.\n", SCIPconsGetName(*targetcons), consdata->nfixednonzeros );
    1532 }
    1533#endif
    1534
    1535 return SCIP_OKAY;
    1536}
    1537
    1538
    1539/** presolving method of constraint handler */
    1540static
    1542{ /*lint --e{715}*/
    1543 SCIPdebug( int oldnfixedvars = *nfixedvars; )
    1544 SCIPdebug( int oldndelconss = *ndelconss; )
    1545 int nremovedvars;
    1546 SCIP_EVENTHDLR* eventhdlr;
    1547 int c;
    1548
    1549 assert( scip != NULL );
    1550 assert( conshdlr != NULL );
    1551 assert( result != NULL );
    1552
    1554
    1555 *result = SCIP_DIDNOTRUN;
    1556 nremovedvars = 0;
    1557
    1558 /* only run if success is possible */
    1559 if( nrounds == 0 || nnewfixedvars > 0 || nnewaggrvars > 0 || nnewchgcoefs > 0 )
    1560 {
    1561 /* get constraint handler data */
    1562 assert( SCIPconshdlrGetData(conshdlr) != NULL );
    1563 eventhdlr = SCIPconshdlrGetData(conshdlr)->eventhdlr;
    1564 assert( eventhdlr != NULL );
    1565
    1566 *result = SCIP_DIDNOTFIND;
    1567
    1568 /* check each constraint */
    1569 for (c = 0; c < nconss; ++c)
    1570 {
    1571 SCIP_CONSDATA* consdata;
    1572 SCIP_CONS* cons;
    1573 SCIP_Bool cutoff;
    1574 SCIP_Bool success;
    1575
    1576 assert( conss != NULL );
    1577 assert( conss[c] != NULL );
    1578
    1579 cons = conss[c];
    1580 consdata = SCIPconsGetData(cons);
    1581
    1582 assert( consdata != NULL );
    1583 assert( consdata->nvars >= 0 );
    1584 assert( consdata->nvars <= consdata->maxvars );
    1585 assert( ! SCIPconsIsModifiable(cons) );
    1586
    1587 /* perform one presolving round */
    1588 SCIP_CALL( presolRoundSOS2(scip, cons, consdata, eventhdlr, &cutoff, &success, ndelconss, nfixedvars, &nremovedvars) );
    1589
    1590 if ( cutoff )
    1591 {
    1592 *result = SCIP_CUTOFF;
    1593 return SCIP_OKAY;
    1594 }
    1595
    1596 if ( success )
    1597 *result = SCIP_SUCCESS;
    1598 }
    1599 }
    1600 (*nchgcoefs) += nremovedvars;
    1601
    1602 SCIPdebug( SCIPdebugMsg(scip, "presolving fixed %d variables, removed %d variables, and deleted %d constraints.\n",
    1603 *nfixedvars - oldnfixedvars, nremovedvars, *ndelconss - oldndelconss); )
    1604
    1605 return SCIP_OKAY;
    1606}
    1607
    1608
    1609/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
    1610static
    1612{
    1613 int c;
    1614
    1615 assert( scip != NULL );
    1616 assert( conshdlr != NULL );
    1617
    1619
    1620 *infeasible = FALSE;
    1621
    1622 /* check each constraint */
    1623 for (c = 0; c < nconss && !(*infeasible); ++c)
    1624 {
    1625 SCIP_CONSDATA* consdata;
    1626
    1627 assert( conss != NULL );
    1628 assert( conss[c] != NULL );
    1629 consdata = SCIPconsGetData(conss[c]);
    1630 assert( consdata != NULL );
    1631
    1632 SCIPdebugMsg(scip, "Checking for initial rows for SOS2 constraint <%s>.\n", SCIPconsGetName(conss[c]) );
    1633
    1634 /* possibly generate row if not yet done */
    1635 if ( consdata->row == NULL )
    1636 {
    1637 SCIP_CALL( generateRowSOS2(scip, conshdlr, conss[c], FALSE) );
    1638 }
    1639
    1640 /* put corresponding rows into LP */
    1641 if ( consdata->row != NULL && ! SCIProwIsInLP(consdata->row) )
    1642 {
    1643 assert( ! SCIPisInfinity(scip, REALABS(SCIProwGetLhs(consdata->row))) || ! SCIPisInfinity(scip, REALABS(SCIProwGetRhs(consdata->row))) );
    1644
    1645 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, infeasible) );
    1646 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL) ) );
    1647 }
    1648 }
    1649
    1650 return SCIP_OKAY;
    1651}
    1652
    1653
    1654/** separation method of constraint handler for LP solutions */
    1655static
    1657{ /*lint --e{715}*/
    1658 SCIP_Bool cutoff = FALSE;
    1659 int c;
    1660 int ngen = 0;
    1661
    1662 assert( scip != NULL );
    1663 assert( conshdlr != NULL );
    1664 assert( conss != NULL );
    1665 assert( result != NULL );
    1666
    1668
    1669 *result = SCIP_DIDNOTRUN;
    1670
    1671 /* check each constraint */
    1672 for (c = 0; c < nconss && ! cutoff; ++c)
    1673 {
    1674 SCIP_CONSDATA* consdata;
    1675 SCIP_ROW* row;
    1676
    1677 *result = SCIP_DIDNOTFIND;
    1678 assert( conss[c] != NULL );
    1679 consdata = SCIPconsGetData(conss[c]);
    1680 assert( consdata != NULL );
    1681 SCIPdebugMsg(scip, "Separating inequalities for SOS2 constraint <%s>.\n", SCIPconsGetName(conss[c]) );
    1682
    1683 /* possibly generate row if not yet done */
    1684 if ( consdata->row == NULL )
    1685 {
    1686 SCIP_CALL( generateRowSOS2(scip, conshdlr, conss[c], FALSE) );
    1687 }
    1688
    1689 /* put corresponding rows into LP if they are useful */
    1690 row = consdata->row;
    1691
    1692 /* possibly add row to LP if it is useful */
    1693 if ( row != NULL && ! SCIProwIsInLP(row) && SCIPisCutEfficacious(scip, NULL, row) )
    1694 {
    1695 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &cutoff) );
    1697 SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
    1698 ++ngen;
    1699 }
    1700 }
    1701 SCIPdebugMsg(scip, "Separated %d SOS2 constraints.\n", ngen);
    1702 if ( cutoff )
    1703 *result = SCIP_CUTOFF;
    1704 else if ( ngen > 0 )
    1705 *result = SCIP_SEPARATED;
    1706
    1707 return SCIP_OKAY;
    1708}
    1709
    1710
    1711/** separation method of constraint handler for arbitrary primal solutions */
    1712static
    1714{ /*lint --e{715}*/
    1715 SCIP_Bool cutoff = FALSE;
    1716 int c;
    1717 int ngen = 0;
    1718
    1719 assert( scip != NULL );
    1720 assert( conshdlr != NULL );
    1721 assert( conss != NULL );
    1722 assert( result != NULL );
    1723
    1725
    1726 *result = SCIP_DIDNOTRUN;
    1727
    1728 /* check each constraint */
    1729 for (c = 0; c < nconss && ! cutoff; ++c)
    1730 {
    1731 SCIP_CONSDATA* consdata;
    1732 SCIP_ROW* row;
    1733
    1734 *result = SCIP_DIDNOTFIND;
    1735 assert( conss[c] != NULL );
    1736 consdata = SCIPconsGetData(conss[c]);
    1737 assert( consdata != NULL );
    1738 SCIPdebugMsg(scip, "Separating solution for SOS2 constraint <%s>.\n", SCIPconsGetName(conss[c]) );
    1739
    1740 /* put corresponding row into LP if it is useful */
    1741 row = consdata->row;
    1742
    1743 /* possibly generate row if not yet done */
    1744 if ( row == NULL )
    1745 {
    1746 SCIP_CALL( generateRowSOS2(scip, conshdlr, conss[c], FALSE) );
    1747 }
    1748
    1749 /* possibly add row to LP if it is useful */
    1750 if ( row != NULL && ! SCIProwIsInLP(row) && SCIPisCutEfficacious(scip, sol, row) )
    1751 {
    1752 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &cutoff) );
    1754 SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
    1755 ++ngen;
    1756 }
    1757 }
    1758 SCIPdebugMsg(scip, "Separated %d SOS2 constraints.\n", ngen);
    1759 if ( cutoff )
    1760 *result = SCIP_CUTOFF;
    1761 else if ( ngen > 0 )
    1762 *result = SCIP_SEPARATED;
    1763
    1764 return SCIP_OKAY;
    1765}
    1766
    1767
    1768/** constraint enforcing method of constraint handler for LP solutions */
    1769static
    1771{ /*lint --e{715}*/
    1772 assert( scip != NULL );
    1773 assert( conshdlr != NULL );
    1774 assert( conss != NULL );
    1775 assert( result != NULL );
    1776
    1778
    1779 SCIP_CALL( enforceSOS2(scip, conshdlr, nconss, conss, NULL, result) );
    1780
    1781 return SCIP_OKAY;
    1782}
    1783
    1784
    1785/** constraint enforcing method of constraint handler for relaxation solutions */
    1786static
    1787SCIP_DECL_CONSENFORELAX(consEnforelaxSOS2)
    1788{ /*lint --e{715}*/
    1789 assert( scip != NULL );
    1790 assert( conshdlr != NULL );
    1791 assert( conss != NULL );
    1792 assert( result != NULL );
    1793
    1795
    1796 SCIP_CALL( enforceSOS2(scip, conshdlr, nconss, conss, sol, result) );
    1797
    1798 return SCIP_OKAY;
    1799}
    1800
    1801
    1802/** constraint enforcing method of constraint handler for pseudo solutions */
    1803static
    1805{ /*lint --e{715}*/
    1806 assert( scip != NULL );
    1807 assert( conshdlr != NULL );
    1808 assert( conss != NULL );
    1809 assert( result != NULL );
    1810
    1812
    1813 SCIP_CALL( enforceSOS2(scip, conshdlr, nconss, conss, NULL, result) );
    1814
    1815 return SCIP_OKAY;
    1816}
    1817
    1818
    1819/** feasibility check method of constraint handler for integral solutions
    1820 *
    1821 * We simply check whether at most two variable are nonzero and in the
    1822 * case there are exactly two nonzero, then they have to be direct
    1823 * neighbors in the given solution.
    1824 */
    1825static
    1827{ /*lint --e{715}*/
    1828 int c;
    1829
    1830 assert( scip != NULL );
    1831 assert( conshdlr != NULL );
    1832 assert( conss != NULL );
    1833 assert( result != NULL );
    1834
    1836
    1837 *result = SCIP_FEASIBLE;
    1838
    1839 /* check each constraint */
    1840 for (c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c)
    1841 {
    1842 SCIP_CONSDATA* consdata;
    1843 int firstNonzero;
    1844 int j;
    1845
    1846 firstNonzero = -1;
    1847 assert( conss[c] != NULL );
    1848 consdata = SCIPconsGetData(conss[c]);
    1849 assert( consdata != NULL );
    1850 SCIPdebugMsg(scip, "Checking SOS2 constraint <%s>.\n", SCIPconsGetName(conss[c]));
    1851
    1852 /* check all variables */
    1853 for (j = 0; j < consdata->nvars; ++j)
    1854 {
    1855 /* if variable is nonzero */
    1856 if ( ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, consdata->vars[j])) )
    1857 {
    1858 if ( firstNonzero < 0 )
    1859 firstNonzero = j;
    1860 else
    1861 {
    1862 /* if we are more than one position away from the firstNonzero variable */
    1863 if ( j > firstNonzero+1 )
    1864 {
    1865 SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
    1866 *result = SCIP_INFEASIBLE;
    1867
    1868 /* update constraint violation in solution */
    1869 if ( sol != NULL )
    1870 SCIPupdateSolConsViolation(scip, sol, 1.0, 1.0);
    1871
    1872 if ( printreason )
    1873 {
    1874 SCIP_CALL( SCIPprintCons(scip, conss[c], NULL) );
    1875
    1876 SCIPinfoMessage(scip, NULL, ";\nviolation: <%s> = %.15g and <%s> = %.15g\n",
    1877 SCIPvarGetName(consdata->vars[firstNonzero]),
    1878 SCIPgetSolVal(scip, sol, consdata->vars[firstNonzero]),
    1879 SCIPvarGetName(consdata->vars[j]),
    1880 SCIPgetSolVal(scip, sol, consdata->vars[j]));
    1881 }
    1882
    1883 SCIPdebugMsg(scip, "SOS2 constraint <%s> infeasible.\n", SCIPconsGetName(conss[c]));
    1884 }
    1885 }
    1886 }
    1887 }
    1888 }
    1889
    1890 return SCIP_OKAY;
    1891}
    1892
    1893
    1894/** domain propagation method of constraint handler */
    1895static
    1897{ /*lint --e{715}*/
    1898 int c;
    1899 int ngen = 0;
    1900
    1901 assert( scip != NULL );
    1902 assert( conshdlr != NULL );
    1903 assert( conss != NULL );
    1904 assert( result != NULL );
    1905
    1907
    1908 *result = SCIP_DIDNOTRUN;
    1909
    1910 assert( SCIPisTransformed(scip) );
    1911
    1912 /* check each constraint */
    1913 for (c = 0; c < nconss; ++c)
    1914 {
    1915 SCIP_CONS* cons;
    1916 SCIP_CONSDATA* consdata;
    1917 SCIP_Bool cutoff;
    1918
    1919 assert( conss[c] != NULL );
    1920 cons = conss[c];
    1921 consdata = SCIPconsGetData(cons);
    1922 assert( consdata != NULL );
    1923 SCIPdebugMsg(scip, "Propagating SOS2 constraint <%s>.\n", SCIPconsGetName(cons) );
    1924
    1925 *result = SCIP_DIDNOTFIND;
    1926 SCIP_CALL( propSOS2(scip, cons, consdata, &cutoff, &ngen) );
    1927 if ( cutoff )
    1928 {
    1929 *result = SCIP_CUTOFF;
    1930 return SCIP_OKAY;
    1931 }
    1932 }
    1933 SCIPdebugMsg(scip, "Propagated %d domains.\n", ngen);
    1934 if ( ngen > 0 )
    1935 *result = SCIP_REDUCEDDOM;
    1936
    1937 return SCIP_OKAY;
    1938}
    1939
    1940
    1941/** propagation conflict resolving method of constraint handler
    1942 *
    1943 * We check which bound changes were the reason for infeasibility. We
    1944 * use that @a inferinfo stores the index of the variable that has
    1945 * bounds that fix it to be nonzero (these bounds are the reason). */
    1946static
    1948{ /*lint --e{715}*/
    1949 SCIP_CONSDATA* consdata;
    1950 SCIP_VAR* var;
    1951
    1952 assert( scip != NULL );
    1953 assert( cons != NULL );
    1954 assert( infervar != NULL );
    1955 assert( bdchgidx != NULL );
    1956 assert( result != NULL );
    1957
    1959
    1960 *result = SCIP_DIDNOTFIND;
    1961 SCIPdebugMsg(scip, "Propagation resolution method of SOS2 constraint <%s>.\n", SCIPconsGetName(cons));
    1962
    1963 consdata = SCIPconsGetData(cons);
    1964 assert( consdata != NULL );
    1965 assert( 0 <= inferinfo && inferinfo < consdata->nvars );
    1966 var = consdata->vars[inferinfo];
    1967 assert( var != infervar );
    1968
    1969 /* check if lower bound of var was the reason */
    1970 if ( SCIPisFeasPositive(scip, SCIPgetVarLbAtIndex(scip, var, bdchgidx, FALSE)) )
    1971 {
    1972 SCIP_CALL( SCIPaddConflictLb(scip, var, bdchgidx) );
    1973 *result = SCIP_SUCCESS;
    1974 }
    1975
    1976 /* check if upper bound of var was the reason */
    1977 if ( SCIPisFeasNegative(scip, SCIPgetVarUbAtIndex(scip, var, bdchgidx, FALSE)) )
    1978 {
    1979 SCIP_CALL( SCIPaddConflictUb(scip, var, bdchgidx) );
    1980 *result = SCIP_SUCCESS;
    1981 }
    1982
    1983 return SCIP_OKAY;
    1984}
    1985
    1986
    1987/** variable rounding lock method of constraint handler
    1988 *
    1989 * Let lb and ub be the lower and upper bounds of a
    1990 * variable. Preprocessing usually makes sure that lb <= 0 <= ub.
    1991 *
    1992 * - If lb < 0 then rounding down may violate the constraint.
    1993 * - If ub > 0 then rounding up may violated the constraint.
    1994 * - If lb > 0 or ub < 0 then the constraint is infeasible and we do
    1995 * not have to deal with it here.
    1996 * - If lb == 0 then rounding down does not violate the constraint.
    1997 * - If ub == 0 then rounding up does not violate the constraint.
    1998 */
    1999static
    2001{
    2002 SCIP_CONSDATA* consdata;
    2003 SCIP_VAR** vars;
    2004 int nvars;
    2005 int j;
    2006
    2007 assert( scip != NULL );
    2008 assert( conshdlr != NULL );
    2009 assert( cons != NULL );
    2010 assert(locktype == SCIP_LOCKTYPE_MODEL);
    2011
    2013
    2014 consdata = SCIPconsGetData(cons);
    2015 assert( consdata != NULL );
    2016
    2017 SCIPdebugMsg(scip, "Locking constraint <%s>.\n", SCIPconsGetName(cons));
    2018
    2019 vars = consdata->vars;
    2020 nvars = consdata->nvars;
    2021 assert( vars != NULL );
    2022
    2023 for (j = 0; j < nvars; ++j)
    2024 {
    2025 SCIP_VAR* var;
    2026 var = vars[j];
    2027
    2028 /* if lower bound is negative, rounding down may violate constraint */
    2030 SCIP_CALL( SCIPaddVarLocksType(scip, var, locktype, nlockspos, nlocksneg) );
    2031
    2032 /* additionally: if upper bound is positive, rounding up may violate constraint */
    2034 SCIP_CALL( SCIPaddVarLocksType(scip, var, locktype, nlocksneg, nlockspos) );
    2035 }
    2036
    2037 return SCIP_OKAY;
    2038}
    2039
    2040
    2041/** constraint display method of constraint handler */
    2042static
    2044{ /*lint --e{715}*/
    2045 SCIP_CONSDATA* consdata;
    2046 int j;
    2047
    2048 assert( scip != NULL );
    2049 assert( conshdlr != NULL );
    2050 assert( cons != NULL );
    2051
    2053
    2054 consdata = SCIPconsGetData(cons);
    2055 assert( consdata != NULL );
    2056
    2057 for (j = 0; j < consdata->nvars; ++j)
    2058 {
    2059 if ( j > 0 )
    2060 SCIPinfoMessage(scip, file, ", ");
    2061 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[j], FALSE) );
    2062 if ( consdata->weights == NULL )
    2063 SCIPinfoMessage(scip, file, " (%d)", j+1);
    2064 else
    2065 SCIPinfoMessage(scip, file, " (%3.2f)", consdata->weights[j]);
    2066 }
    2067
    2068 return SCIP_OKAY;
    2069}
    2070
    2071
    2072/** constraint copying method of constraint handler */
    2073static
    2075{ /*lint --e{715}*/
    2076 SCIP_CONSDATA* sourceconsdata;
    2077 SCIP_VAR** sourcevars;
    2078 SCIP_VAR** targetvars;
    2079 SCIP_Real* targetweights = NULL;
    2080 const char* consname;
    2081 int nvars;
    2082 int v;
    2083
    2084 assert( scip != NULL );
    2085 assert( sourcescip != NULL );
    2086 assert( sourcecons != NULL );
    2087 assert( valid != NULL );
    2088
    2090
    2091 *valid = TRUE;
    2092
    2093 if ( name != NULL )
    2094 consname = name;
    2095 else
    2096 consname = SCIPconsGetName(sourcecons);
    2097
    2098 SCIPdebugMsg(scip, "Copying SOS2 constraint <%s> ...\n", consname);
    2099
    2100 sourceconsdata = SCIPconsGetData(sourcecons);
    2101 assert( sourceconsdata != NULL );
    2102
    2103 /* get variables and weights of the source constraint */
    2104 nvars = sourceconsdata->nvars;
    2105 assert( nvars >= 0 );
    2106
    2107 /* duplicate weights array */
    2108 if ( sourceconsdata->weights != NULL )
    2109 {
    2110 SCIP_CALL( SCIPduplicateBufferArray(sourcescip, &targetweights, sourceconsdata->weights, nvars) );
    2111 }
    2112
    2113 /* get copied variables in target SCIP */
    2114 sourcevars = sourceconsdata->vars;
    2115 SCIP_CALL( SCIPallocBufferArray(sourcescip, &targetvars, nvars) );
    2116 for (v = 0; v < nvars && *valid; ++v)
    2117 {
    2118 assert( sourcevars != NULL );
    2119 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &(targetvars[v]), varmap, consmap, global, valid) );
    2120 }
    2121
    2122 /* only create the target constraint, if all variables could be copied */
    2123 if( *valid )
    2124 {
    2125 SCIP_CALL( SCIPcreateConsSOS2(scip, cons, consname, nvars, targetvars, targetweights,
    2126 initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
    2127 }
    2128
    2129 /* free buffer array */
    2130 SCIPfreeBufferArray(sourcescip, &targetvars);
    2131 SCIPfreeBufferArrayNull(sourcescip, &targetweights);
    2132
    2133 return SCIP_OKAY;
    2134}
    2135
    2136
    2137/** constraint parsing method of constraint handler */
    2138static
    2140{ /*lint --e{715}*/
    2141 SCIP_VAR* var;
    2142 SCIP_Real weight;
    2143 const char* s;
    2144 char* t;
    2145
    2146 *success = TRUE;
    2147 s = str;
    2148
    2149 /* create empty SOS2 constraint */
    2150 SCIP_CALL( SCIPcreateConsSOS2(scip, cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
    2151
    2152 /* loop through string */
    2153 while( *s != '\0' )
    2154 {
    2155 /* parse variable name */
    2156 SCIP_CALL( SCIPparseVarName(scip, s, &var, &t) );
    2157
    2158 if( var == NULL )
    2159 break;
    2160
    2161 /* skip until beginning of weight */
    2162 t = strchr(t, '(');
    2163
    2164 if( t == NULL )
    2165 {
    2166 SCIPerrorMessage("Syntax error: expected opening '(' at input: %s\n", s);
    2167 *success = FALSE;
    2168 break;
    2169 }
    2170
    2171 s = t;
    2172
    2173 /* skip '(' */
    2174 ++s;
    2175
    2176 /* find weight */
    2177 weight = strtod(s, &t);
    2178
    2179 if( t == NULL )
    2180 {
    2181 SCIPerrorMessage("Syntax error during parsing of the weight: %s\n", s);
    2182 *success = FALSE;
    2183 break;
    2184 }
    2185
    2186 s = t;
    2187
    2188 /* skip until ending of weight */
    2189 t = strchr(t, ')');
    2190
    2191 if( t == NULL )
    2192 {
    2193 SCIPerrorMessage("Syntax error: expected closing ')' at input %s\n", s);
    2194 *success = FALSE;
    2195 break;
    2196 }
    2197
    2198 s = t;
    2199
    2200 /* skip ')' */
    2201 ++s;
    2202
    2203 /* skip white space */
    2204 SCIP_CALL( SCIPskipSpace((char**)&s) );
    2205
    2206 /* skip ',' */
    2207 if( *s == ',' )
    2208 ++s;
    2209
    2210 /* add variable */
    2211 SCIP_CALL( SCIPaddVarSOS2(scip, *cons, var, weight) );
    2212 }
    2213
    2214 if( !*success )
    2215 SCIP_CALL( SCIPreleaseCons(scip, cons) );
    2216
    2217 return SCIP_OKAY;
    2218}
    2219
    2220
    2221/** constraint method of constraint handler which returns the variables (if possible) */
    2222static
    2224{ /*lint --e{715}*/
    2225 SCIP_CONSDATA* consdata;
    2226
    2227 consdata = SCIPconsGetData(cons);
    2228 assert(consdata != NULL);
    2229
    2230 if( varssize < consdata->nvars )
    2231 (*success) = FALSE;
    2232 else
    2233 {
    2234 assert(vars != NULL);
    2235
    2236 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
    2237 (*success) = TRUE;
    2238 }
    2239
    2240 return SCIP_OKAY;
    2241}
    2242
    2243
    2244/** constraint method of constraint handler which returns the number of variables (if possible) */
    2245static
    2246SCIP_DECL_CONSGETNVARS(consGetNVarsSOS2)
    2247{ /*lint --e{715}*/
    2248 SCIP_CONSDATA* consdata;
    2249
    2250 consdata = SCIPconsGetData(cons);
    2251 assert(consdata != NULL);
    2252
    2253 (*nvars) = consdata->nvars;
    2254 (*success) = TRUE;
    2255
    2256 return SCIP_OKAY;
    2257}
    2258
    2259
    2260/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
    2261static
    2262SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphSOS2)
    2263{ /*lint --e{715}*/
    2264 SCIP_CONSDATA* consdata;
    2265 SCIP_VAR** consvars;
    2266 SCIP_VAR** locvars;
    2267 SCIP_Real* locvals;
    2268 SCIP_Real constant;
    2269 int consnodeidx;
    2270 int opnodeidx;
    2271 int nodeidx;
    2272 int nconsvars;
    2273 int nlocvars;
    2274 int nvars;
    2275 int i;
    2276 int j;
    2277
    2278 assert(success != NULL);
    2279
    2280 consdata = SCIPconsGetData(cons);
    2281 assert(consdata != NULL);
    2282
    2283 /* get active variables of the constraint */
    2284 nvars = SCIPgetNVars(scip);
    2285 nconsvars = consdata->nvars;
    2286 consvars = SCIPgetVarsSOS2(scip, cons);
    2287 assert(consvars != NULL);
    2288
    2289 SCIP_CALL( SCIPallocBufferArray(scip, &locvars, nvars) );
    2290 SCIP_CALL( SCIPallocBufferArray(scip, &locvals, nvars) );
    2291
    2292 /* add node initializing constraint (with artificial rhs) */
    2293 SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, 0.0, 0.0, &consnodeidx) );
    2294
    2295 /* for all pairs of variables, add a node indicating a tuple and add nodes for (aggregated) variables */
    2296 for( i = 0; i < nconsvars - 1; ++i )
    2297 {
    2298 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_SOS2_TUPLE, &opnodeidx) ); /*lint !e641*/
    2299 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, opnodeidx, FALSE, 0.0) );
    2300
    2301 for( j = i; j < i + 2; ++j )
    2302 {
    2303 locvars[0] = consvars[j];
    2304 locvals[0] = 1.0;
    2305 constant = 0.0;
    2306 nlocvars = 1;
    2307
    2308 /* ignore weights of SOS2 constraint (variables are sorted according to these weights) */
    2310 &nlocvars, &constant, SCIPisTransformed(scip)) );
    2311
    2312 if( nlocvars == 1 && SCIPisZero(scip, constant) && SCIPisEQ(scip, locvals[0], 1.0) )
    2313 {
    2314 nodeidx = SCIPgetSymgraphVarnodeidx(scip, graph, locvars[0]);
    2315 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, opnodeidx, nodeidx, FALSE, 0.0) );
    2316 }
    2317 else
    2318 {
    2319 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_SUM, &nodeidx) ); /*lint !e641*/
    2320 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, opnodeidx, nodeidx, FALSE, 0.0) );
    2321 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, nodeidx, locvars, locvals, nlocvars, constant) );
    2322 }
    2323 }
    2324 }
    2325
    2326 SCIPfreeBufferArray(scip, &locvals);
    2327 SCIPfreeBufferArray(scip, &locvars);
    2328
    2329 *success = TRUE;
    2330
    2331 return SCIP_OKAY;
    2332}
    2333
    2334
    2335/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
    2336static
    2337SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphSOS2)
    2338{ /*lint --e{715}*/
    2339 SCIP_CONSDATA* consdata;
    2340 SCIP_VAR** consvars;
    2341 SCIP_VAR** locvars;
    2342 SCIP_Real* locvals;
    2343 SCIP_Real constant;
    2344 int consnodeidx;
    2345 int opnodeidx;
    2346 int nodeidx;
    2347 int nconsvars;
    2348 int nlocvars;
    2349 int nvars;
    2350 int i;
    2351 int j;
    2352
    2353 assert(success != NULL);
    2354
    2355 consdata = SCIPconsGetData(cons);
    2356 assert(consdata != NULL);
    2357
    2358 /* get active variables of the constraint */
    2359 nvars = SCIPgetNVars(scip);
    2360 nconsvars = consdata->nvars;
    2361 consvars = SCIPgetVarsSOS2(scip, cons);
    2362 assert(consvars != NULL);
    2363
    2364 SCIP_CALL( SCIPallocBufferArray(scip, &locvars, nvars) );
    2365 SCIP_CALL( SCIPallocBufferArray(scip, &locvals, nvars) );
    2366
    2367 /* add node initializing constraint (with artificial rhs) */
    2368 SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, 0.0, 0.0, &consnodeidx) );
    2369
    2370 /* for all pairs of variables, add a node indicating a tuple and add nodes for (aggregated) variables */
    2371 for( i = 0; i < nconsvars - 1; ++i )
    2372 {
    2373 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_SOS2_TUPLE, &opnodeidx) ); /*lint !e641*/
    2374 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, opnodeidx, FALSE, 0.0) );
    2375
    2376 for( j = i; j < i + 2; ++j )
    2377 {
    2378 locvars[0] = consvars[j];
    2379 locvals[0] = 1.0;
    2380 constant = 0.0;
    2381 nlocvars = 1;
    2382
    2383 /* ignore weights of SOS2 constraint (variables are sorted according to these weights) */
    2384
    2385 /* use SYM_SYMTYPE_PERM here to NOT center variable domains at 0, as the latter might not preserve
    2386 * SOS1 constraints */
    2388 &nlocvars, &constant, SCIPisTransformed(scip)) );
    2389
    2390 if( nlocvars == 1 && SCIPisZero(scip, constant) && SCIPisEQ(scip, locvals[0], 1.0) )
    2391 {
    2392 SCIP_Bool allownegation = FALSE;
    2393
    2394 /* a negation is allowed if it is centered around 0 */
    2395 if ( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(locvars[0])) == SCIPisInfinity(scip, SCIPvarGetUbGlobal(locvars[0]))
    2396 && (SCIPisInfinity(scip, SCIPvarGetUbGlobal(locvars[0]))
    2397 || SCIPisZero(scip, (SCIPvarGetLbGlobal(locvars[0]) + SCIPvarGetUbGlobal(locvars[0]))/2)) )
    2398 allownegation = TRUE;
    2399
    2400 nodeidx = SCIPgetSymgraphVarnodeidx(scip, graph, locvars[0]);
    2401 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, opnodeidx, nodeidx, TRUE, 1.0) );
    2402
    2403 nodeidx = SCIPgetSymgraphNegatedVarnodeidx(scip, graph, locvars[0]);
    2404 if( allownegation )
    2405 {
    2406 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, opnodeidx, nodeidx, TRUE, 1.0) );
    2407 }
    2408 else
    2409 {
    2410 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, opnodeidx, nodeidx, TRUE, -1.0) );
    2411 }
    2412 }
    2413 else
    2414 {
    2415 int sumnodeidx;
    2416 int k;
    2417
    2418 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_SUM, &sumnodeidx) ); /*lint !e641*/
    2419 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, sumnodeidx, FALSE, 0.0) );
    2420
    2421 /* add nodes and edges for variables in aggregation, do not add edges to negated variables
    2422 * since this might not necessarily be a symmetry of the SOS1 constraint; therefore,
    2423 * do not use SCIPaddSymgraphVarAggregation() */
    2424 for( k = 0; k < nlocvars; ++k )
    2425 {
    2426 nodeidx = SCIPgetSymgraphVarnodeidx(scip, graph, locvars[k]);
    2427 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, sumnodeidx, nodeidx, TRUE, locvals[k]) );
    2428 }
    2429
    2430 /* possibly add node for constant */
    2431 if( ! SCIPisZero(scip, constant) )
    2432 {
    2433 SCIP_CALL( SCIPaddSymgraphValnode(scip, graph, constant, &nodeidx) );
    2434 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, sumnodeidx, nodeidx, FALSE, 0.0) );
    2435 }
    2436 }
    2437 }
    2438 }
    2439
    2440 SCIPfreeBufferArray(scip, &locvals);
    2441 SCIPfreeBufferArray(scip, &locvars);
    2442
    2443 *success = TRUE;
    2444
    2445 return SCIP_OKAY;
    2446}
    2447
    2448
    2449/* ---------------- Callback methods of event handler ---------------- */
    2450
    2451/** exec the event handler
    2452 *
    2453 * We update the number of variables fixed to be nonzero
    2454 */
    2455static
    2457{
    2458 SCIP_EVENTTYPE eventtype;
    2459 SCIP_CONS* cons;
    2460 SCIP_CONSDATA* consdata;
    2461 SCIP_VAR* var;
    2462 SCIP_Real oldbound, newbound;
    2463
    2464 assert( eventhdlr != NULL );
    2465 assert( eventdata != NULL );
    2466 assert( event != NULL );
    2467
    2469
    2470 cons = (SCIP_CONS*)eventdata;
    2471 assert( cons != NULL );
    2472 consdata = SCIPconsGetData(cons);
    2473 assert( consdata != NULL );
    2474 assert( 0 <= consdata->nfixednonzeros && consdata->nfixednonzeros <= consdata->nvars );
    2475
    2476 oldbound = SCIPeventGetOldbound(event);
    2477 newbound = SCIPeventGetNewbound(event);
    2478
    2479 eventtype = SCIPeventGetType(event);
    2480 switch ( eventtype )
    2481 {
    2483 /* if variable is now fixed to be nonzero */
    2484 if ( ! SCIPisFeasPositive(scip, oldbound) && SCIPisFeasPositive(scip, newbound) )
    2485 ++(consdata->nfixednonzeros);
    2486 break;
    2488 /* if variable is now fixed to be nonzero */
    2489 if ( ! SCIPisFeasNegative(scip, oldbound) && SCIPisFeasNegative(scip, newbound) )
    2490 ++(consdata->nfixednonzeros);
    2491 break;
    2493 /* if variable is not fixed to be nonzero anymore */
    2494 if ( SCIPisFeasPositive(scip, oldbound) && ! SCIPisFeasPositive(scip, newbound) )
    2495 --(consdata->nfixednonzeros);
    2496 break;
    2498 /* if variable is not fixed to be nonzero anymore */
    2499 if ( SCIPisFeasNegative(scip, oldbound) && ! SCIPisFeasNegative(scip, newbound) )
    2500 --(consdata->nfixednonzeros);
    2501 break;
    2503 var = SCIPeventGetVar(event);
    2504 assert(var != NULL);
    2505
    2506 /* global lower bound is not negative anymore -> remove down lock */
    2507 if ( SCIPisFeasNegative(scip, oldbound) && ! SCIPisFeasNegative(scip, newbound) )
    2508 SCIP_CALL( SCIPunlockVarCons(scip, var, cons, TRUE, FALSE) );
    2509 /* global lower bound turned negative -> add down lock */
    2510 else if ( ! SCIPisFeasNegative(scip, oldbound) && SCIPisFeasNegative(scip, newbound) )
    2511 SCIP_CALL( SCIPlockVarCons(scip, var, cons, TRUE, FALSE) );
    2512 break;
    2514 var = SCIPeventGetVar(event);
    2515 assert(var != NULL);
    2516
    2517 /* global upper bound is not positive anymore -> remove up lock */
    2518 if ( SCIPisFeasPositive(scip, oldbound) && ! SCIPisFeasPositive(scip, newbound) )
    2519 SCIP_CALL( SCIPunlockVarCons(scip, var, cons, FALSE, TRUE) );
    2520 /* global upper bound turned positive -> add up lock */
    2521 else if ( ! SCIPisFeasPositive(scip, oldbound) && SCIPisFeasPositive(scip, newbound) )
    2522 SCIP_CALL( SCIPlockVarCons(scip, var, cons, FALSE, TRUE) );
    2523 break;
    2524 default:
    2525 SCIPerrorMessage("invalid event type.\n");
    2526 return SCIP_INVALIDDATA;
    2527 }
    2528 assert( 0 <= consdata->nfixednonzeros && consdata->nfixednonzeros <= consdata->nvars );
    2529
    2530 SCIPdebugMsg(scip, "changed bound of variable <%s> from %f to %f (nfixednonzeros: %d).\n", SCIPvarGetName(SCIPeventGetVar(event)),
    2531 oldbound, newbound, consdata->nfixednonzeros);
    2532
    2533 return SCIP_OKAY;
    2534}
    2535
    2536
    2537/* ---------------- Constraint specific interface methods ---------------- */
    2538
    2539/** creates the handler for SOS2 constraints and includes it in SCIP */
    2541 SCIP* scip /**< SCIP data structure */
    2542 )
    2543{
    2544 SCIP_CONSHDLRDATA* conshdlrdata;
    2545 SCIP_CONSHDLR* conshdlr;
    2546
    2547 /* create constraint handler data */
    2548 SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
    2549
    2550 conshdlrdata->eventhdlr = NULL;
    2551 /* create event handler for bound change events */
    2553 eventExecSOS2, NULL) );
    2554 if ( conshdlrdata->eventhdlr == NULL )
    2555 {
    2556 SCIPerrorMessage("event handler for SOS2 constraints not found.\n");
    2557 return SCIP_PLUGINNOTFOUND;
    2558 }
    2559
    2560 /* include constraint handler */
    2563 consEnfolpSOS2, consEnfopsSOS2, consCheckSOS2, consLockSOS2, conshdlrdata) );
    2564 assert(conshdlr != NULL);
    2565
    2566 /* set non-fundamental callbacks via specific setter functions */
    2567 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopySOS2, consCopySOS2) );
    2568 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteSOS2) );
    2569 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolSOS2) );
    2570 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeSOS2) );
    2571 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsSOS2) );
    2572 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsSOS2) );
    2573 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpSOS2) );
    2574 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseSOS2) );
    2576 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintSOS2) );
    2578 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropSOS2) );
    2579 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpSOS2, consSepasolSOS2, CONSHDLR_SEPAFREQ, CONSHDLR_SEPAPRIORITY, CONSHDLR_DELAYSEPA) );
    2580 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransSOS2) );
    2581 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxSOS2) );
    2582 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphSOS2) );
    2583 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphSOS2) );
    2584
    2585 return SCIP_OKAY;
    2586}
    2587
    2588
    2589/** creates and captures a SOS2 constraint
    2590 *
    2591 * We set the constraint to not be modifable. If the weights are non
    2592 * NULL, the variables are ordered according to these weights (in
    2593 * ascending order).
    2594 *
    2595 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    2596 */
    2598 SCIP* scip, /**< SCIP data structure */
    2599 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    2600 const char* name, /**< name of constraint */
    2601 int nvars, /**< number of variables in the constraint */
    2602 SCIP_VAR** vars, /**< array with variables of constraint entries */
    2603 SCIP_Real* weights, /**< weights determining the variable order, or NULL if natural order should be used */
    2604 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
    2605 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    2606 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
    2607 * Usually set to TRUE. */
    2608 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    2609 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    2610 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    2611 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    2612 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
    2613 * Usually set to TRUE. */
    2614 SCIP_Bool local, /**< is constraint only valid locally?
    2615 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    2616 SCIP_Bool dynamic, /**< is constraint subject to aging?
    2617 * Usually set to FALSE. Set to TRUE for own cuts which
    2618 * are separated as constraints. */
    2619 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
    2620 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
    2621 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    2622 * if it may be moved to a more global node?
    2623 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
    2624 )
    2625{
    2626 SCIP_CONSHDLR* conshdlr;
    2627 SCIP_CONSDATA* consdata;
    2628 SCIP_Bool modifiable;
    2629
    2630 modifiable = FALSE;
    2631
    2632 /* find the SOS2 constraint handler */
    2633 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    2634 if ( conshdlr == NULL )
    2635 {
    2636 SCIPerrorMessage("<%s> constraint handler not found\n", CONSHDLR_NAME);
    2637 return SCIP_PLUGINNOTFOUND;
    2638 }
    2639
    2640#ifndef NDEBUG
    2641 /* Check that the weights are sensible (not nan or inf); although not strictly needed, such values are likely a mistake. */
    2642 if ( nvars > 0 && weights != NULL )
    2643 {
    2644 int v;
    2645 for (v = 0; v < nvars; ++v)
    2646 assert( SCIPisFinite(weights[v]) );
    2647 }
    2648#endif
    2649
    2650 /* create constraint data */
    2651 SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
    2652 consdata->vars = NULL;
    2653 consdata->nvars = nvars;
    2654 consdata->maxvars = nvars;
    2655 consdata->row = NULL;
    2656 consdata->nfixednonzeros = -1;
    2657 consdata->weights = NULL;
    2658 if ( nvars > 0 )
    2659 {
    2660 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->vars, vars, nvars) );
    2661
    2662 /* check weights */
    2663 if ( weights != NULL )
    2664 {
    2665 /* store weights */
    2666 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->weights, weights, nvars) );
    2667
    2668 /* sort variables - ascending order */
    2669 SCIPsortRealPtr(consdata->weights, (void**)consdata->vars, nvars);
    2670 }
    2671 }
    2672 else
    2673 assert( weights == NULL );
    2674
    2675 /* create constraint */
    2676 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
    2677 local, modifiable, dynamic, removable, stickingatnode) );
    2678
    2679 return SCIP_OKAY;
    2680}
    2681
    2682
    2683/** creates and captures a SOS2 constraint with all constraint flags set to their default values.
    2684 *
    2685 * @warning Do NOT set the constraint to be modifiable manually, because this might lead
    2686 * to wrong results as the variable array will not be re-sorted
    2687 *
    2688 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    2689 */
    2691 SCIP* scip, /**< SCIP data structure */
    2692 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    2693 const char* name, /**< name of constraint */
    2694 int nvars, /**< number of variables in the constraint */
    2695 SCIP_VAR** vars, /**< array with variables of constraint entries */
    2696 SCIP_Real* weights /**< weights determining the variable order, or NULL if natural order should be used */
    2697 )
    2698{
    2699 SCIP_CALL( SCIPcreateConsSOS2( scip, cons, name, nvars, vars, weights, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
    2700
    2701 return SCIP_OKAY;
    2702}
    2703
    2704
    2705/** adds variable to SOS2 constraint, the position is determined by the given weight */
    2707 SCIP* scip, /**< SCIP data structure */
    2708 SCIP_CONS* cons, /**< constraint */
    2709 SCIP_VAR* var, /**< variable to add to the constraint */
    2710 SCIP_Real weight /**< weight determining position of variable */
    2711 )
    2712{
    2713 assert( scip != NULL );
    2714 assert( var != NULL );
    2715 assert( cons != NULL );
    2716 /* Check weight is sensible (not nan or inf); although not strictly needed, such values are likely a mistake. */
    2717 assert( SCIPisFinite(weight) );
    2718
    2719 SCIPdebugMsg(scip, "adding variable <%s> to constraint <%s> with weight %g\n", SCIPvarGetName(var), SCIPconsGetName(cons), weight);
    2720
    2722
    2723 SCIP_CALL( addVarSOS2(scip, cons, var, weight) );
    2724
    2725 return SCIP_OKAY;
    2726}
    2727
    2728
    2729/** appends variable to SOS2 constraint */
    2731 SCIP* scip, /**< SCIP data structure */
    2732 SCIP_CONS* cons, /**< constraint */
    2733 SCIP_VAR* var /**< variable to add to the constraint */
    2734 )
    2735{
    2736 assert( scip != NULL );
    2737 assert( var != NULL );
    2738 assert( cons != NULL );
    2739
    2740 SCIPdebugMsg(scip, "appending variable <%s> to constraint <%s>\n", SCIPvarGetName(var), SCIPconsGetName(cons));
    2741
    2743
    2744 SCIP_CALL( appendVarSOS2(scip, cons, var) );
    2745
    2746 return SCIP_OKAY;
    2747}
    2748
    2749
    2750/** gets number of variables in SOS2 constraint */
    2752 SCIP* scip, /**< SCIP data structure */
    2753 SCIP_CONS* cons /**< constraint */
    2754 )
    2755{
    2756 SCIP_CONSDATA* consdata;
    2757
    2758 assert( scip != NULL );
    2759 assert( cons != NULL );
    2760
    2762
    2763 consdata = SCIPconsGetData(cons);
    2764 assert( consdata != NULL );
    2765
    2766 return consdata->nvars;
    2767}
    2768
    2769
    2770/** gets array of variables in SOS2 constraint */
    2772 SCIP* scip, /**< SCIP data structure */
    2773 SCIP_CONS* cons /**< constraint data */
    2774 )
    2775{
    2776 SCIP_CONSDATA* consdata;
    2777
    2778 assert( scip != NULL );
    2779 assert( cons != NULL );
    2780
    2782
    2783 consdata = SCIPconsGetData(cons);
    2784 assert( consdata != NULL );
    2785
    2786 return consdata->vars;
    2787}
    2788
    2789
    2790/** gets array of weights in SOS2 constraint (or NULL if not existent) */
    2792 SCIP* scip, /**< SCIP data structure */
    2793 SCIP_CONS* cons /**< constraint data */
    2794 )
    2795{
    2796 SCIP_CONSDATA* consdata;
    2797
    2798 assert( scip != NULL );
    2799 assert( cons != NULL );
    2800
    2802
    2803 consdata = SCIPconsGetData(cons);
    2804 assert( consdata != NULL );
    2805
    2806 return consdata->weights;
    2807}
    SCIP_VAR * w
    Definition: circlepacking.c:67
    static SCIP_RETCODE branchCons(SCIP *scip, SCIP_CONS *cons, SCIP_RESULT *result)
    Constraint handler for linear constraints in their most general form, .
    #define CONSHDLR_NEEDSCONS
    Definition: cons_sos2.c:121
    #define CONSHDLR_SEPAFREQ
    Definition: cons_sos2.c:114
    static SCIP_DECL_CONSGETNVARS(consGetNVarsSOS2)
    Definition: cons_sos2.c:2246
    static SCIP_RETCODE propSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_Bool *cutoff, int *ngen)
    Definition: cons_sos2.c:837
    #define CONSHDLR_CHECKPRIORITY
    Definition: cons_sos2.c:113
    static SCIP_DECL_CONSSEPASOL(consSepasolSOS2)
    Definition: cons_sos2.c:1713
    #define CONSHDLR_DESC
    Definition: cons_sos2.c:110
    #define CONSHDLR_PROP_TIMING
    Definition: cons_sos2.c:123
    static SCIP_DECL_CONSEXITSOL(consExitsolSOS2)
    Definition: cons_sos2.c:1374
    static SCIP_DECL_CONSCOPY(consCopySOS2)
    Definition: cons_sos2.c:2074
    static SCIP_DECL_CONSRESPROP(consRespropSOS2)
    Definition: cons_sos2.c:1947
    static SCIP_RETCODE handleNewVariableSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Bool transformed)
    Definition: cons_sos2.c:315
    static SCIP_RETCODE deleteVarSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos)
    Definition: cons_sos2.c:496
    #define CONSHDLR_MAXPREROUNDS
    Definition: cons_sos2.c:118
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopySOS2)
    Definition: cons_sos2.c:1336
    #define CONSHDLR_SEPAPRIORITY
    Definition: cons_sos2.c:111
    static SCIP_DECL_CONSPARSE(consParseSOS2)
    Definition: cons_sos2.c:2139
    static SCIP_DECL_CONSINITLP(consInitlpSOS2)
    Definition: cons_sos2.c:1611
    static SCIP_DECL_CONSENFORELAX(consEnforelaxSOS2)
    Definition: cons_sos2.c:1787
    static SCIP_DECL_EVENTEXEC(eventExecSOS2)
    Definition: cons_sos2.c:2456
    static SCIP_DECL_CONSENFOLP(consEnfolpSOS2)
    Definition: cons_sos2.c:1770
    static SCIP_RETCODE presolRoundSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, SCIP_Bool *success, int *ndelconss, int *nfixedvars, int *nremovedvars)
    Definition: cons_sos2.c:556
    static SCIP_RETCODE unlockVariableSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_sos2.c:267
    static SCIP_RETCODE appendVarSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_sos2.c:440
    static SCIP_DECL_CONSCHECK(consCheckSOS2)
    Definition: cons_sos2.c:1826
    static SCIP_RETCODE fixVariableZeroNode(SCIP *scip, SCIP_VAR *var, SCIP_NODE *node, SCIP_Bool *infeasible)
    Definition: cons_sos2.c:153
    static SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphSOS2)
    Definition: cons_sos2.c:2337
    static SCIP_RETCODE inferVariableZero(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, int inferinfo, SCIP_Bool *infeasible, SCIP_Bool *tightened, SCIP_Bool *success)
    Definition: cons_sos2.c:204
    static SCIP_DECL_CONSPRESOL(consPresolSOS2)
    Definition: cons_sos2.c:1541
    static SCIP_DECL_CONSDELETE(consDeleteSOS2)
    Definition: cons_sos2.c:1407
    static SCIP_DECL_CONSENFOPS(consEnfopsSOS2)
    Definition: cons_sos2.c:1804
    static SCIP_DECL_CONSFREE(consFreeSOS2)
    Definition: cons_sos2.c:1354
    static SCIP_DECL_CONSGETVARS(consGetVarsSOS2)
    Definition: cons_sos2.c:2223
    static SCIP_DECL_CONSTRANS(consTransSOS2)
    Definition: cons_sos2.c:1457
    #define CONSHDLR_PROPFREQ
    Definition: cons_sos2.c:115
    static SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphSOS2)
    Definition: cons_sos2.c:2262
    #define CONSHDLR_PRESOLTIMING
    Definition: cons_sos2.c:124
    #define CONSHDLR_EAGERFREQ
    Definition: cons_sos2.c:116
    #define EVENTHDLR_DESC
    Definition: cons_sos2.c:128
    #define EVENTHDLR_EVENT_TYPE
    Definition: cons_sos2.c:130
    #define CONSHDLR_ENFOPRIORITY
    Definition: cons_sos2.c:112
    #define CONSHDLR_DELAYSEPA
    Definition: cons_sos2.c:119
    static SCIP_RETCODE generateRowSOS2(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons, SCIP_Bool local)
    Definition: cons_sos2.c:1237
    static SCIP_RETCODE lockVariableSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_sos2.c:247
    static SCIP_RETCODE addVarSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real weight)
    Definition: cons_sos2.c:372
    static SCIP_RETCODE consdataEnsurevarsSizeSOS2(SCIP *scip, SCIP_CONSDATA *consdata, int num, SCIP_Bool reserveWeights)
    Definition: cons_sos2.c:287
    static SCIP_DECL_CONSPRINT(consPrintSOS2)
    Definition: cons_sos2.c:2043
    #define CONSHDLR_NAME
    Definition: cons_sos2.c:109
    static SCIP_DECL_CONSLOCK(consLockSOS2)
    Definition: cons_sos2.c:2000
    static SCIP_RETCODE enforceSOS2(SCIP *scip, SCIP_CONSHDLR *conshdlr, int nconss, SCIP_CONS **conss, SCIP_SOL *sol, SCIP_RESULT *result)
    Definition: cons_sos2.c:1035
    static SCIP_DECL_CONSPROP(consPropSOS2)
    Definition: cons_sos2.c:1896
    #define EVENTHDLR_NAME
    Definition: cons_sos2.c:127
    static SCIP_DECL_CONSSEPALP(consSepalpSOS2)
    Definition: cons_sos2.c:1656
    #define CONSHDLR_DELAYPROP
    Definition: cons_sos2.c:120
    constraint handler for SOS type 2 constraints
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_Bool
    Definition: def.h:100
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_Real * SCIPgetWeightsSOS2(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_sos2.c:2791
    SCIP_VAR ** SCIPgetVarsSOS2(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_sos2.c:2771
    SCIP_RETCODE SCIPappendVarSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_sos2.c:2730
    int SCIPgetNVarsSOS2(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_sos2.c:2751
    SCIP_RETCODE SCIPcreateConsSOS2(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *weights, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    Definition: cons_sos2.c:2597
    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 SCIPaddVarSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real weight)
    Definition: cons_sos2.c:2706
    SCIP_RETCODE SCIPcreateConsBasicSOS2(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *weights)
    Definition: cons_sos2.c:2690
    SCIP_RETCODE SCIPincludeConshdlrSOS2(SCIP *scip)
    Definition: cons_sos2.c:2540
    SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
    Definition: scip_copy.c:713
    SCIP_Bool SCIPisTransformed(SCIP *scip)
    Definition: scip_general.c:655
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3420
    SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:4067
    SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
    Definition: scip_prob.c:3901
    SCIP_Real SCIPgetLocalTransEstimate(SCIP *scip)
    Definition: scip_prob.c:4139
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_Real SCIPcalcNodeselPriority(SCIP *scip, SCIP_VAR *var, SCIP_BRANCHDIR branchdir, SCIP_Real targetvalue)
    Definition: scip_branch.c:928
    SCIP_Real SCIPcalcChildEstimateIncrease(SCIP *scip, SCIP_VAR *var, SCIP_Real varsol, SCIP_Real targetvalue)
    Definition: scip_branch.c:979
    SCIP_RETCODE SCIPcreateChild(SCIP *scip, SCIP_NODE **node, SCIP_Real nodeselprio, SCIP_Real estimate)
    Definition: scip_branch.c:1025
    SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
    SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
    SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
    Definition: scip_cons.c:808
    SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
    Definition: scip_cons.c:540
    SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
    Definition: scip_cons.c:831
    SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
    Definition: scip_cons.c:235
    SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
    Definition: scip_cons.c:281
    SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: scip_cons.c:181
    SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)))
    Definition: scip_cons.c:900
    SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
    Definition: scip_cons.c:578
    SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
    Definition: scip_cons.c:372
    SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
    Definition: scip_cons.c:323
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4320
    SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
    Definition: scip_cons.c:347
    SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
    Definition: scip_cons.c:940
    SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH((*consgetsignedpermsymgraph)))
    Definition: scip_cons.c:924
    SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
    Definition: scip_cons.c:468
    SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
    Definition: scip_cons.c:624
    SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4340
    SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
    Definition: scip_cons.c:601
    SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
    Definition: scip_cons.c:647
    SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
    Definition: scip_cons.c:854
    SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
    Definition: scip_cons.c:785
    SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
    Definition: cons.c:8423
    SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
    Definition: cons.c:8652
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8413
    SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
    Definition: cons.c:8562
    SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
    Definition: scip_cons.c:2536
    SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8592
    SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
    Definition: cons.c:8702
    SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
    Definition: cons.c:8582
    SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, 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)
    Definition: scip_cons.c:997
    SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
    Definition: cons.c:8612
    SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
    Definition: cons.c:8632
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8393
    SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1812
    SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
    Definition: cons.c:8642
    SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
    Definition: cons.c:8672
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8572
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8662
    SCIP_Bool SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
    Definition: scip_cut.c:117
    SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
    Definition: scip_cut.c:225
    SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: scip_event.c:111
    const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:396
    SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
    Definition: event.c:1194
    SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
    Definition: scip_event.c:367
    SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
    Definition: scip_event.c:413
    SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
    Definition: event.c:1391
    SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
    Definition: event.c:1217
    SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
    Definition: event.c:1415
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    int SCIPcalcMemGrowSize(SCIP *scip, int num)
    Definition: scip_mem.c:139
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPduplicateBufferArray(scip, ptr, source, num)
    Definition: scip_mem.h:132
    #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 SCIPfreeBufferArrayNull(scip, ptr)
    Definition: scip_mem.h:137
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    #define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:105
    SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
    Definition: lp.c:17686
    SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
    Definition: scip_lp.c:1529
    SCIP_RETCODE SCIPaddVarsToRowSameCoef(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real val)
    Definition: scip_lp.c:1718
    SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
    Definition: lp.c:17696
    SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
    Definition: scip_lp.c:1398
    SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_lp.c:1646
    SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
    Definition: scip_lp.c:2176
    SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
    Definition: scip_lp.c:1508
    SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
    Definition: scip_lp.c:1553
    SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
    Definition: lp.c:17917
    void SCIPupdateSolConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
    Definition: scip_sol.c:451
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasNegative(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 SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
    SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
    Definition: scip_var.c:5210
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23418
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
    Definition: var.c:23462
    SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:7069
    SCIP_RETCODE SCIPchgVarUbNode(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:6088
    SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
    Definition: scip_var.c:728
    SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
    Definition: scip_var.c:2499
    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_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
    Definition: scip_var.c:5296
    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_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
    Definition: scip_var.c:10318
    SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:6964
    SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2736
    SCIP_RETCODE SCIPchgVarLbNode(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:6044
    SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
    Definition: scip_var.c:361
    SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
    Definition: scip_var.c:2078
    void SCIPsortRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    SCIP_RETCODE SCIPskipSpace(char **s)
    Definition: misc.c:10816
    SCIP_RETCODE SCIPaddSymgraphEdge(SCIP *scip, SYM_GRAPH *graph, int first, int second, SCIP_Bool hasval, SCIP_Real val)
    SCIP_RETCODE SCIPaddSymgraphOpnode(SCIP *scip, SYM_GRAPH *graph, int op, int *nodeidx)
    SCIP_RETCODE SCIPgetSymActiveVariables(SCIP *scip, SYM_SYMTYPE symtype, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
    SCIP_RETCODE SCIPaddSymgraphValnode(SCIP *scip, SYM_GRAPH *graph, SCIP_Real val, int *nodeidx)
    int SCIPgetSymgraphVarnodeidx(SCIP *scip, SYM_GRAPH *graph, SCIP_VAR *var)
    SCIP_RETCODE SCIPaddSymgraphConsnode(SCIP *scip, SYM_GRAPH *graph, SCIP_CONS *cons, SCIP_Real lhs, SCIP_Real rhs, int *nodeidx)
    SCIP_RETCODE SCIPaddSymgraphVarAggregation(SCIP *scip, SYM_GRAPH *graph, int rootidx, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Real constant)
    int SCIPgetSymgraphNegatedVarnodeidx(SCIP *scip, SYM_GRAPH *graph, SCIP_VAR *var)
    memory allocation routines
    #define BMScopyMemoryArray(ptr, source, num)
    Definition: memory.h:134
    public methods for managing constraints
    public methods for managing events
    public methods for LP management
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    public data structures and miscellaneous methods
    #define SCIPisFinite(x)
    Definition: pub_misc.h:82
    methods for sorting joint arrays of various types
    public methods for problem variables
    public methods for branching rule plugins and branching
    public methods for conflict handler plugins and conflict analysis
    public methods for constraint handler plugins and constraints
    public methods for problem copies
    public methods for cuts and aggregation rows
    public methods for event handler plugins and event handlers
    general public methods
    public methods for the LP relaxation, rows and columns
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for global and local (sub)problems
    public methods for solutions
    public methods for SCIP variables
    static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
    Main separation function.
    Definition: sepa_flower.c:1219
    structs for symmetry computations
    methods for dealing with symmetry detection graphs
    struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
    Definition: type_cons.h:64
    struct SCIP_ConsData SCIP_CONSDATA
    Definition: type_cons.h:65
    #define SCIP_EVENTTYPE_GUBCHANGED
    Definition: type_event.h:76
    struct SCIP_EventData SCIP_EVENTDATA
    Definition: type_event.h:179
    #define SCIP_EVENTTYPE_UBTIGHTENED
    Definition: type_event.h:79
    #define SCIP_EVENTTYPE_LBRELAXED
    Definition: type_event.h:78
    #define SCIP_EVENTTYPE_GLBCHANGED
    Definition: type_event.h:75
    uint64_t SCIP_EVENTTYPE
    Definition: type_event.h:156
    #define SCIP_EVENTTYPE_LBTIGHTENED
    Definition: type_event.h:77
    #define SCIP_EVENTTYPE_UBRELAXED
    Definition: type_event.h:80
    @ SCIP_BRANCHDIR_DOWNWARDS
    Definition: type_history.h:43
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_FEASIBLE
    Definition: type_result.h:45
    @ SCIP_REDUCEDDOM
    Definition: type_result.h:51
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_BRANCHED
    Definition: type_result.h:54
    @ SCIP_SEPARATED
    Definition: type_result.h:49
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    @ SCIP_INFEASIBLE
    Definition: type_result.h:46
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_PLUGINNOTFOUND
    Definition: type_retcode.h:54
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SYM_CONSOPTYPE_SOS2_TUPLE
    Definition: type_symmetry.h:82
    @ SYM_CONSOPTYPE_SUM
    Definition: type_symmetry.h:83
    @ SYM_SYMTYPE_PERM
    Definition: type_symmetry.h:61
    @ SCIP_VARSTATUS_MULTAGGR
    Definition: type_var.h:56
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141