SCIP

    Solving Constraint Integer Programs

    cons_cardinality.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_cardinality.c
    26 * @ingroup DEFPLUGINS_CONS
    27 * @brief constraint handler for cardinality constraints
    28 * @author Tobias Fischer
    29 *
    30 * This constraint handler handles cardinality constraints of the form
    31 * \f[
    32 * |\mbox{supp}(x)| \leq b
    33 * \f]
    34 * with integer right-hand side \f$b\f$. Here, \f$|\mbox{supp}(x)|\f$ denotes the number of nonzero entries of the
    35 * vector \f$x\f$.
    36 *
    37 * Note that cardinality constraints generalize special ordered set of type one (SOS1) constraints in which \f$b = 1\f$.
    38 *
    39 * The implementation of this constraint handler is based on@n
    40 * "On the Structure of Linear Programs with Overlapping Cardinality Constraints"@n
    41 * T. Fischer and M. E. Pfetsch, Tech. rep., 2016
    42 */
    43
    44/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    45
    48#include "scip/cons_knapsack.h"
    49#include "scip/cons_linear.h"
    50#include "scip/pub_cons.h"
    51#include "scip/pub_event.h"
    52#include "scip/pub_lp.h"
    53#include "scip/pub_message.h"
    54#include "scip/pub_misc.h"
    55#include "scip/pub_misc_sort.h"
    56#include "scip/pub_var.h"
    57#include "scip/scip_branch.h"
    58#include "scip/scip_cons.h"
    59#include "scip/scip_copy.h"
    60#include "scip/scip_cut.h"
    61#include "scip/scip_event.h"
    62#include "scip/scip_general.h"
    63#include "scip/scip_lp.h"
    64#include "scip/scip_mem.h"
    65#include "scip/scip_message.h"
    66#include "scip/scip_numerics.h"
    67#include "scip/scip_param.h"
    68#include "scip/scip_prob.h"
    69#include "scip/scip_sol.h"
    71#include "scip/scip_tree.h"
    72#include "scip/scip_var.h"
    73#include "scip/symmetry_graph.h"
    75#include <ctype.h>
    76#include <stdlib.h>
    77#include <string.h>
    78
    79/* constraint handler properties */
    80#define CONSHDLR_NAME "cardinality"
    81#define CONSHDLR_DESC "cardinality constraint handler"
    82#define CONSHDLR_SEPAPRIORITY 10 /**< priority of the constraint handler for separation */
    83#define CONSHDLR_ENFOPRIORITY 100 /**< priority of the constraint handler for constraint enforcing */
    84#define CONSHDLR_CHECKPRIORITY -10 /**< priority of the constraint handler for checking feasibility */
    85#define CONSHDLR_SEPAFREQ 10 /**< frequency for separating cuts; zero means to separate only in the root node */
    86#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
    87#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
    88 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    89#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in
    90 * (-1: no limit) */
    91#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
    92#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
    93#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
    94
    95#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
    96#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_FAST
    97
    98/* branching rules */
    99#define DEFAULT_BRANCHBALANCED FALSE /**< whether to use balanced instead of unbalanced branching */
    100#define DEFAULT_BALANCEDDEPTH 20 /**< maximum depth for using balanced branching (-1: no limit) */
    101#define DEFAULT_BALANCEDCUTOFF 2.0 /**< determines that balanced branching is only used if the branching cut off value
    102 * w.r.t. the current LP solution is greater than a given value */
    103
    104/* event handler properties */
    105#define EVENTHDLR_NAME "cardinality"
    106#define EVENTHDLR_DESC "bound change event handler for cardinality constraints"
    107
    108#define EVENTHDLR_EVENT_TYPE (SCIP_EVENTTYPE_BOUNDCHANGED | SCIP_EVENTTYPE_GBDCHANGED)
    109
    110
    111/** constraint data for cardinality constraints */
    112struct SCIP_ConsData
    113{
    114 SCIP_CONS* cons; /**< cardinality constraint */
    115 int cardval; /**< number of variables that the constraint allows to be nonzero */
    116 int nvars; /**< number of variables in the constraint */
    117 int maxvars; /**< maximal number of variables (= size of storage) */
    118 int ntreatnonzeros; /**< number of variables in constraint that are either known to be nonzero
    119 * (because zero is not in variable domain) or may be treated as nonzero */
    120 SCIP_EVENTDATA** eventdatascurrent; /**< event datas for current bound change events */
    121 SCIP_VAR** eventvarscurrent; /**< event variables for current bound change events */
    122 int neventdatascurrent; /**< number of current bound change events */
    123 SCIP_EVENTDATA** eventdatas; /**< event data array for bound change events */
    124 SCIP_VAR** vars; /**< variables in constraint */
    125 SCIP_VAR** indvars; /**< indicator variables that indicate which variables may be treated as
    126 * nonzero in cardinality constraint */
    127 SCIP_Real* weights; /**< weights determining the order (ascending), or NULL if not used */
    128 SCIP_ROW* rowlb; /**< row corresponding to lower bounds, or NULL if not yet created */
    129 SCIP_ROW* rowub; /**< row corresponding to upper bounds, or NULL if not yet created */
    130};
    131
    132/** cardinality constraint handler data */
    133struct SCIP_ConshdlrData
    134{
    135 SCIP_HASHMAP* varhash; /**< hash map from implied variable to (binary) indicator variable */
    136 SCIP_Bool branchbalanced; /**< whether to use balanced instead of unbalanced branching */
    137 int balanceddepth; /**< maximum depth for using balanced branching (-1: no limit) */
    138 SCIP_Real balancedcutoff; /**< determines that balanced branching is only used if the branching cut off
    139 * value w.r.t. the current LP solution is greater than a given value */
    140 SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
    141};
    142
    143/** event data for bound changes events */
    144struct SCIP_EventData
    145{
    146 SCIP_CONSDATA* consdata; /**< cardinality constraint data to process the bound change for */
    147 SCIP_VAR* var; /**< implied variable */
    148 SCIP_VAR* indvar; /**< indicator variable */
    149 unsigned int pos:30; /**< position in constraint */
    150 unsigned int varmarked:1; /**< whether implied variable is marked for propagation */
    151 unsigned int indvarmarked:1; /**< whether indicator variable is marked for propagation */
    152};
    153
    154/** catches bound change events for a variable and its indicator variable */
    155static
    157 SCIP* scip, /**< SCIP data structure */
    158 SCIP_EVENTHDLR* eventhdlr, /**< event handler for bound change events */
    159 SCIP_CONSDATA* consdata, /**< constraint data */
    160 SCIP_VAR* var, /**< implied variable */
    161 SCIP_VAR* indvar, /**< indicator variable */
    162 int pos, /**< position in constraint */
    163 SCIP_EVENTDATA** eventdata /**< pointer to store event data for bound change events */
    164 )
    165{
    166 assert(eventhdlr != NULL);
    167 assert(consdata != NULL);
    168 assert(var != NULL);
    169 assert(indvar != NULL);
    170 assert(pos >= 0);
    171
    172 /* create event data of indicator variable */
    173 SCIP_CALL( SCIPallocBlockMemory(scip, eventdata) );
    174
    175 (*eventdata)->consdata = consdata;
    176 (*eventdata)->var = var;
    177 (*eventdata)->indvar = indvar;
    178 (*eventdata)->varmarked = FALSE;
    179 (*eventdata)->indvarmarked = FALSE;
    180 (*eventdata)->pos = (unsigned int)pos;
    181
    182 /* catch bound change events of each variable */
    183 SCIP_CALL( SCIPcatchVarEvent(scip, var, EVENTHDLR_EVENT_TYPE, eventhdlr, *eventdata, NULL) );
    184 SCIP_CALL( SCIPcatchVarEvent(scip, indvar, SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr, *eventdata, NULL) );
    185
    186 return SCIP_OKAY;
    187}
    188
    189/** drops bound change events for a variable and its indicator variable */
    190static
    192 SCIP* scip, /**< SCIP data structure */
    193 SCIP_EVENTHDLR* eventhdlr, /**< event handler for bound change events */
    194 SCIP_CONSDATA* consdata, /**< constraint data */
    195 SCIP_VAR* var, /**< implied variable */
    196 SCIP_VAR* indvar, /**< indicator variable */
    197 SCIP_EVENTDATA** eventdata /**< pointer of event data for bound change events */
    198 )
    199{
    200 assert(eventhdlr != NULL);
    201 assert(consdata != NULL);
    202 assert(var != NULL);
    203 assert(indvar != NULL);
    204 assert(eventdata != NULL);
    205
    206 /* drop bound change events of each variable */
    207 SCIP_CALL( SCIPdropVarEvent(scip, var, EVENTHDLR_EVENT_TYPE, eventhdlr, *eventdata, -1) );
    208 SCIP_CALL( SCIPdropVarEvent(scip, indvar, SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr, *eventdata, -1) );
    209
    210 /* free event data of indicator variable */
    211 SCIPfreeBlockMemory(scip, eventdata);
    212 *eventdata = NULL;
    213
    214 return SCIP_OKAY;
    215}
    216
    217/** fix variable in given node to 0 or add constraint if variable is multi-aggregated
    218 *
    219 * @todo Try to handle multi-aggregated variables as in \ref fixVariableZero() below.
    220 */
    221static
    223 SCIP* scip, /**< SCIP pointer */
    224 SCIP_VAR* var, /**< variable to be fixed to 0 */
    225 SCIP_NODE* node, /**< node */
    226 SCIP_Bool* infeasible /**< pointer to store if fixing is infeasible */
    227 )
    228{
    229 /* if variable cannot be nonzero */
    230 *infeasible = FALSE;
    232 {
    233 *infeasible = TRUE;
    234 return SCIP_OKAY;
    235 }
    236
    237 /* if variable is multi-aggregated */
    239 {
    240 SCIP_CONS* cons;
    241 SCIP_Real val;
    242
    243 val = 1.0;
    244
    246 {
    247 SCIPdebugMsg(scip, "creating constraint to force multi-aggregated variable <%s> to 0.\n", SCIPvarGetName(var));
    248
    249 /* we have to insert a local constraint var = 0 */
    250 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, "branch", 1, &var, &val, 0.0, 0.0, TRUE, TRUE, TRUE, TRUE, TRUE,
    251 TRUE, FALSE, FALSE, FALSE, FALSE) );
    252 SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
    253 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    254 }
    255 }
    256 else
    257 {
    259 {
    260 SCIP_CALL( SCIPchgVarLbNode(scip, node, var, 0.0) );
    261 }
    263 {
    264 SCIP_CALL( SCIPchgVarUbNode(scip, node, var, 0.0) );
    265 }
    266 }
    267
    268 return SCIP_OKAY;
    269}
    270
    271/** try to fix variable to 0
    272 *
    273 * Try to treat fixing by special consideration of multiaggregated variables. For a multi-aggregation
    274 * \f[
    275 * x = \sum_{i=1}^n \alpha_i x_i + c,
    276 * \f]
    277 * we can express the fixing \f$x = 0\f$ by fixing all \f$x_i\f$ to 0 if \f$c = 0\f$ and the lower bounds of \f$x_i\f$
    278 * are nonnegative if \f$\alpha_i > 0\f$ or the upper bounds are nonpositive if \f$\alpha_i < 0\f$.
    279 */
    280static
    282 SCIP* scip, /**< SCIP pointer */
    283 SCIP_VAR* var, /**< variable to be fixed to 0*/
    284 SCIP_Bool* infeasible, /**< if fixing is infeasible */
    285 SCIP_Bool* tightened /**< if fixing was performed */
    286 )
    287{
    288 assert(scip != NULL);
    289 assert(var != NULL);
    290 assert(infeasible != NULL);
    291 assert(tightened != NULL);
    292
    293 *infeasible = FALSE;
    294 *tightened = FALSE;
    295
    297 {
    298 SCIP_Real aggrconst;
    299
    300 /* if constant is 0 */
    301 aggrconst = SCIPvarGetMultaggrConstant(var);
    302 if( SCIPisZero(scip, aggrconst) )
    303 {
    304 SCIP_VAR** aggrvars;
    305 SCIP_Real* aggrvals;
    306 SCIP_Bool allnonnegative = TRUE;
    307 int naggrvars;
    308 int i;
    309
    311
    312 /* check whether all variables are "nonnegative" */
    313 naggrvars = SCIPvarGetMultaggrNVars(var);
    314 aggrvars = SCIPvarGetMultaggrVars(var);
    315 aggrvals = SCIPvarGetMultaggrScalars(var);
    316 for( i = 0; i < naggrvars; ++i )
    317 {
    318 if( (SCIPisPositive(scip, aggrvals[i]) && SCIPisNegative(scip, SCIPvarGetLbLocal(aggrvars[i]))) ||
    319 (SCIPisNegative(scip, aggrvals[i]) && SCIPisPositive(scip, SCIPvarGetUbLocal(aggrvars[i]))) )
    320 {
    321 allnonnegative = FALSE;
    322 break;
    323 }
    324 }
    325
    326 if( allnonnegative )
    327 {
    328 /* all variables are nonnegative -> fix variables */
    329 for( i = 0; i < naggrvars; ++i )
    330 {
    331 SCIP_Bool fixed;
    332 SCIP_CALL( SCIPfixVar(scip, aggrvars[i], 0.0, infeasible, &fixed) );
    333 if( *infeasible )
    334 return SCIP_OKAY;
    335 *tightened = *tightened || fixed;
    336 }
    337 }
    338 }
    339 }
    340 else
    341 {
    342 SCIP_CALL( SCIPfixVar(scip, var, 0.0, infeasible, tightened) );
    343 }
    344
    345 return SCIP_OKAY;
    346}
    347
    348/** add lock on variable */
    349static
    351 SCIP* scip, /**< SCIP data structure */
    352 SCIP_CONS* cons, /**< constraint */
    353 SCIP_VAR* var, /**< variable */
    354 SCIP_VAR* indvar /**< indicator variable */
    355 )
    356{
    357 assert(scip != NULL);
    358 assert(cons != NULL);
    359 assert(var != NULL);
    360
    361 /* rounding down == bad if lb < 0, rounding up == bad if ub > 0 */
    364 SCIP_CALL( SCIPlockVarCons(scip, indvar, cons, TRUE, TRUE) );
    365
    366 return SCIP_OKAY;
    367}
    368
    369/* remove lock on variable */
    370static
    372 SCIP* scip, /**< SCIP data structure */
    373 SCIP_CONS* cons, /**< constraint */
    374 SCIP_VAR* var, /**< variable */
    375 SCIP_VAR* indvar /**< indicator variable */
    376 )
    377{
    378 assert(scip != NULL);
    379 assert(cons != NULL);
    380 assert(var != NULL);
    381
    382 /* rounding down == bad if lb < 0, rounding up == bad if ub > 0 */
    385 SCIP_CALL( SCIPunlockVarCons(scip, indvar, cons, TRUE, TRUE) );
    386
    387 return SCIP_OKAY;
    388}
    389
    390/** ensures that the vars and weights array can store at least num entries */
    391static
    393 SCIP* scip, /**< SCIP data structure */
    394 SCIP_CONSDATA* consdata, /**< constraint data */
    395 int num, /**< minimum number of entries to store */
    396 SCIP_Bool reserveweights /**< whether the weights array is handled */
    397 )
    398{
    399 assert(consdata != NULL);
    400 assert(consdata->nvars <= consdata->maxvars);
    401
    402 if( num > consdata->maxvars )
    403 {
    404 int newsize;
    405
    406 newsize = SCIPcalcMemGrowSize(scip, num);
    407 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->maxvars, newsize) );
    408 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->indvars, consdata->maxvars, newsize) );
    409 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdatas, consdata->maxvars, newsize) );
    410 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdatascurrent, 4*consdata->maxvars, 4*newsize) );/*lint !e647*/
    411 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventvarscurrent, 4*consdata->maxvars, 4*newsize) );/*lint !e647*/
    412
    413 if ( reserveweights )
    414 {
    415 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->weights, consdata->maxvars, newsize) );
    416 }
    417 consdata->maxvars = newsize;
    418 }
    419 assert(num <= consdata->maxvars);
    420
    421 return SCIP_OKAY;
    422}
    423
    424/** handle new variable that was added to the constraint
    425 *
    426 * We perform the following steps:
    427 *
    428 * - Catch bound change events of variable.
    429 * - Update rounding locks of variable.
    430 * - Don't allow multiaggregation of variable, since this cannot be handled by branching in the current implementation.
    431 * - Update lower and upper bound row, i.e., the linear representations of the cardinality constraints.
    432 */
    433static
    435 SCIP* scip, /**< SCIP data structure */
    436 SCIP_CONS* cons, /**< constraint */
    437 SCIP_CONSDATA* consdata, /**< constraint data */
    438 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
    439 SCIP_VAR* var, /**< variable */
    440 SCIP_VAR* indvar, /**< indicator variable to indicate whether variable may be treated as
    441 * nonzero in cardinality constraint */
    442 int pos, /**< position in constraint */
    443 SCIP_Bool transformed, /**< whether original variable was transformed */
    444 SCIP_EVENTDATA** eventdata /**< pointer to store event data for bound change events */
    445 )
    446{
    447 assert(scip != NULL);
    448 assert(cons != NULL);
    449 assert(consdata != NULL);
    450 assert(conshdlrdata != NULL);
    451 assert(var != NULL);
    452
    453 /* if we are in transformed problem, catch the variable's events */
    454 if( transformed )
    455 {
    456 /* catch bound change events of variable */
    457 SCIP_CALL( catchVarEventCardinality(scip, conshdlrdata->eventhdlr, consdata, var, indvar, pos, eventdata) );
    458 assert(eventdata != NULL );
    459
    460 /* if the variable is fixed to nonzero */
    461 assert(consdata->ntreatnonzeros >= 0);
    462 assert(SCIPvarIsBinary(indvar));
    463 if( SCIPvarGetLbLocal(indvar) > 0.5 )
    464 ++consdata->ntreatnonzeros;
    465 }
    466
    467 /* branching on multiaggregated variables does not seem to work well, so avoid it */
    469
    470 /* install the rounding locks for the new variable */
    471 SCIP_CALL( lockVariableCardinality(scip, cons, var, indvar) );
    472
    473 /* add the new coefficient to the upper bound LP row, if necessary */
    474 if( consdata->rowub != NULL && !SCIPisInfinity(scip, SCIPvarGetUbGlobal(var))
    476 {
    477 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rowub, var, 1.0/SCIPvarGetUbGlobal(var)) );
    478 }
    479
    480 /* add the new coefficient to the lower bound LP row, if necessary */
    481 if( consdata->rowlb != NULL && !SCIPisInfinity(scip, SCIPvarGetLbGlobal(var))
    483 {
    484 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rowlb, var, 1.0/SCIPvarGetLbGlobal(var)) );
    485 }
    486
    487 return SCIP_OKAY;
    488}
    489
    490/** adds a variable to a cardinality constraint, at position given by weight - ascending order */
    491static
    493 SCIP* scip, /**< SCIP data structure */
    494 SCIP_CONS* cons, /**< constraint */
    495 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
    496 SCIP_VAR* var, /**< variable to add to the constraint */
    497 SCIP_VAR* indvar, /**< indicator variable to indicate whether variable may be treated as nonzero
    498 * in cardinality constraint (or NULL) */
    499 SCIP_Real weight /**< weight to determine position */
    500 )
    501{
    502 SCIP_EVENTDATA* eventdata = NULL;
    503 SCIP_CONSDATA* consdata;
    504 SCIP_Bool transformed;
    505 int pos;
    506
    507 assert(var != NULL);
    508 assert(cons != NULL);
    509 assert(conshdlrdata != NULL);
    510
    511 consdata = SCIPconsGetData(cons);
    512 assert(consdata != NULL );
    513
    514 if( consdata->weights == NULL && consdata->maxvars > 0 )
    515 {
    516 SCIPerrorMessage("cannot add variable to cardinality constraint <%s> that does not contain weights.\n",
    517 SCIPconsGetName(cons));
    518 return SCIP_INVALIDCALL;
    519 }
    520
    521 /* check indicator variable */
    522 if( indvar == NULL )
    523 {
    524 if( conshdlrdata->varhash == NULL )
    525 {
    526 /* set up hash map */
    527 SCIP_CALL( SCIPhashmapCreate(&conshdlrdata->varhash, SCIPblkmem(scip), SCIPgetNTotalVars(scip)) );
    528 }
    529
    530 /* check whether an indicator variable already exists for implied variable */
    531 if( SCIPhashmapExists(conshdlrdata->varhash, var) )
    532 {
    533 assert((SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, var) != NULL);
    534 indvar = (SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, var);
    535 assert(indvar != NULL);
    536 }
    537 else
    538 {
    539 /* if implied variable is binary, then it is also not necessary to create an indicator variable */
    540 if( SCIPvarIsBinary(var) )
    541 indvar = var;
    542 else
    543 {
    544 char varname[SCIP_MAXSTRLEN];
    545 SCIP_VAR* newvar;
    546
    547 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "ind_%s", SCIPvarGetName(var));
    548 SCIP_CALL( SCIPcreateVar(scip, &newvar, varname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY, FALSE, FALSE,
    549 NULL, NULL, NULL, NULL, NULL) );
    550 SCIP_CALL( SCIPaddVar(scip, newvar) );
    551 indvar = newvar;
    552
    553 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
    554 }
    555 assert(indvar != NULL);
    556
    557 /* insert implied variable to hash map */
    558 SCIP_CALL( SCIPhashmapInsert(conshdlrdata->varhash, var, (void*) indvar) );/*lint !e571*/
    559 assert(indvar == (SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, var));
    560 assert(SCIPhashmapExists(conshdlrdata->varhash, var));
    561 }
    562 }
    563
    564 /* are we in the transformed problem? */
    565 transformed = SCIPconsIsTransformed(cons);
    566
    567 /* always use transformed variables in transformed constraints */
    568 if( transformed )
    569 {
    570 SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
    571 SCIP_CALL( SCIPgetTransformedVar(scip, indvar, &indvar) );
    572 }
    573 assert(var != NULL);
    574 assert(indvar != NULL);
    575 assert(transformed == SCIPvarIsTransformed(var));
    576 assert(transformed == SCIPvarIsTransformed(indvar));
    577
    578 /* ensure that the new information can be storend in the constraint data */
    579 SCIP_CALL( consdataEnsurevarsSizeCardinality(scip, consdata, consdata->nvars + 1, TRUE) );
    580 assert(consdata->weights != NULL);
    581 assert(consdata->maxvars >= consdata->nvars+1);
    582
    583 /* move other variables, if necessary */
    584 for( pos = consdata->nvars; pos >= 1; --pos )
    585 {
    586 /* coverity[var_deref_model] */
    587 if( consdata->weights[pos-1] > weight )
    588 {
    589 consdata->vars[pos] = consdata->vars[pos-1];
    590 consdata->indvars[pos] = consdata->indvars[pos-1];
    591 consdata->eventdatas[pos] = consdata->eventdatas[pos-1];
    592 consdata->weights[pos] = consdata->weights[pos-1];
    593
    594 if( consdata->eventdatas[pos] != NULL )
    595 {
    596 consdata->eventdatas[pos]->pos = (unsigned int)pos;
    597 }
    598 }
    599 else
    600 break;
    601 }
    602 assert(0 <= pos && pos <= consdata->nvars);
    603
    604 /* handle the new variable */
    605 SCIP_CALL( handleNewVariableCardinality(scip, cons, consdata, conshdlrdata, var, indvar, pos, transformed, &eventdata) );
    606 assert(! transformed || eventdata != NULL);
    607
    608 /* insert variable */
    609 consdata->vars[pos] = var;
    610 consdata->indvars[pos] = indvar;
    611 consdata->eventdatas[pos] = eventdata;
    612 consdata->weights[pos] = weight;
    613 ++consdata->nvars;
    614
    615 return SCIP_OKAY;
    616}
    617
    618/** appends a variable to a cardinality constraint */
    619static
    621 SCIP* scip, /**< SCIP data structure */
    622 SCIP_CONS* cons, /**< constraint */
    623 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
    624 SCIP_VAR* var, /**< variable to add to the constraint */
    625 SCIP_VAR* indvar /**< indicator variable to indicate whether variable may be treated as nonzero
    626 * in cardinality constraint */
    627 )
    628{
    629 SCIP_EVENTDATA* eventdata = NULL;
    630 SCIP_CONSDATA* consdata;
    631 SCIP_Bool transformed;
    632
    633 assert(var != NULL);
    634 assert(cons != NULL);
    635 assert(conshdlrdata != NULL);
    636
    637 consdata = SCIPconsGetData(cons);
    638 assert(consdata != NULL);
    639
    640 /* check indicator variable */
    641 if( indvar == NULL )
    642 {
    643 if( conshdlrdata->varhash == NULL )
    644 {
    645 /* set up hash map */
    646 SCIP_CALL( SCIPhashmapCreate(&conshdlrdata->varhash, SCIPblkmem(scip), SCIPgetNTotalVars(scip)) );
    647 }
    648
    649 /* check whether an indicator variable already exists for implied variable */
    650 if( SCIPhashmapExists(conshdlrdata->varhash, var) )
    651 {
    652 assert((SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, var) != NULL);
    653 indvar = (SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, var);
    654 assert(indvar != NULL);
    655 }
    656 else
    657 {
    658 /* if implied variable is binary, then it is also not necessary to create an indicator variable */
    659 if( SCIPvarIsBinary(var) )
    660 indvar = var;
    661 else
    662 {
    663 char varname[SCIP_MAXSTRLEN];
    664 SCIP_VAR* newvar;
    665
    666 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "ind_%s", SCIPvarGetName(var));
    667 SCIP_CALL( SCIPcreateVar(scip, &newvar, varname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY, FALSE, FALSE,
    668 NULL, NULL, NULL, NULL, NULL) );
    669 SCIP_CALL( SCIPaddVar(scip, newvar) );
    670 indvar = newvar;
    671
    672 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
    673 }
    674 assert(indvar != NULL);
    675
    676 /* insert implied variable to hash map */
    677 SCIP_CALL( SCIPhashmapInsert(conshdlrdata->varhash, var, (void*) indvar) );/*lint !e571*/
    678 assert(indvar == (SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, var));
    679 assert(SCIPhashmapExists(conshdlrdata->varhash, var));
    680 }
    681 }
    682
    683 /* are we in the transformed problem? */
    684 transformed = SCIPconsIsTransformed(cons);
    685
    686 /* always use transformed variables in transformed constraints */
    687 if( transformed )
    688 {
    689 SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
    690 SCIP_CALL( SCIPgetTransformedVar(scip, indvar, &indvar) );
    691 }
    692 assert(var != NULL);
    693 assert(indvar != NULL);
    694 assert(transformed == SCIPvarIsTransformed(var));
    695 assert(transformed == SCIPvarIsTransformed(indvar));
    696
    697 /* ensure that the new information can be stored in the constraint data */
    698 SCIP_CALL( consdataEnsurevarsSizeCardinality(scip, consdata, consdata->nvars + 1, FALSE) );
    699
    700 /* handle the new variable */
    701 SCIP_CALL( handleNewVariableCardinality(scip, cons, consdata, conshdlrdata, var, indvar, consdata->nvars, transformed,
    702 &eventdata) );
    703 assert(!transformed || eventdata != NULL);
    704
    705 /* insert variable */
    706 consdata->vars[consdata->nvars] = var;
    707 consdata->indvars[consdata->nvars] = indvar;
    708 consdata->eventdatas[consdata->nvars] = eventdata;
    709
    710 if( consdata->weights != NULL && consdata->nvars > 0 )
    711 consdata->weights[consdata->nvars] = consdata->weights[consdata->nvars-1] + 1.0;
    712 ++consdata->nvars;
    713
    714 assert(consdata->weights != NULL || consdata->nvars > 0);
    715
    716 return SCIP_OKAY;
    717}
    718
    719/** deletes a variable from a cardinality constraint */
    720static
    722 SCIP* scip, /**< SCIP data structure */
    723 SCIP_CONS* cons, /**< constraint */
    724 SCIP_CONSDATA* consdata, /**< constraint data */
    725 SCIP_EVENTHDLR* eventhdlr, /**< corresponding event handler */
    726 int pos /**< position of variable in array */
    727 )
    728{ /*lint --e{679}*/
    729 int j;
    730
    731 assert(0 <= pos && pos < consdata->nvars);
    732
    733 /* remove lock of variable */
    734 SCIP_CALL( unlockVariableCardinality(scip, cons, consdata->vars[pos], consdata->indvars[pos]) );
    735
    736 /* drop events on indicator variable and implied variable */
    737 SCIP_CALL( dropVarEventCardinality(scip, eventhdlr, consdata, consdata->vars[pos], consdata->indvars[pos],
    738 &consdata->eventdatas[pos]) );
    739
    740 /* update number of variables that may be treated as nonzero */
    741 assert(SCIPvarIsBinary(consdata->indvars[pos]));
    742 if( SCIPvarGetLbLocal(consdata->indvars[pos]) > 0.5 )
    743 --(consdata->ntreatnonzeros);
    744
    745 /* delete variable - need to copy since order is important */
    746 for( j = pos; j < consdata->nvars-1; ++j )
    747 {
    748 consdata->vars[j] = consdata->vars[j+1];
    749 consdata->indvars[j] = consdata->indvars[j+1];
    750 consdata->eventdatas[j] = consdata->eventdatas[j+1];
    751 if( consdata->weights != NULL )
    752 consdata->weights[j] = consdata->weights[j+1];
    753
    754 consdata->eventdatas[j]->pos = (unsigned int)j;
    755 }
    756 --consdata->nvars;
    757
    758 return SCIP_OKAY;
    759}
    760
    761/** for each indicator variable sets solution to 1.0 if the solution value of the implied variable is nonzero */
    762static
    764 SCIP* scip, /**< SCIP pointer */
    765 SCIP_CONS** conss, /**< constraints */
    766 int nconss, /**< number of constraints */
    767 SCIP_SOL* sol, /**< solution to be enforced (or NULL) */
    768 SCIP_SOL* primsol /**< primal solution */
    769 )
    770{
    771 SCIP_CONSDATA* consdata;
    772 SCIP_VAR** indvars;
    773 SCIP_VAR** vars;
    774 int nvars;
    775 int c;
    776
    777 /* check each constraint */
    778 for( c = 0; c < nconss; ++c )
    779 {
    780 SCIP_CONS* cons;
    781 int j;
    782
    783 cons = conss[c];
    784 assert(cons != NULL);
    785 consdata = SCIPconsGetData(cons);
    786 assert(consdata != NULL);
    787
    788 nvars = consdata->nvars;
    789 vars = consdata->vars;
    790 indvars = consdata->indvars;
    791
    792 for( j = 0; j < nvars; ++j )
    793 {
    794 if( SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, vars[j])) )
    795 {
    796 SCIP_CALL( SCIPsetSolVal(scip, primsol, indvars[j], 0.0) );
    797 }
    798 else
    799 {
    800 SCIP_CALL( SCIPsetSolVal(scip, primsol, indvars[j], 1.0) );
    801 }
    802 }
    803 }
    804
    805 return SCIP_OKAY;
    806}
    807
    808/** unmark variables that are marked for propagation */
    809static
    811 SCIP_CONSDATA* consdata /**< constraint data */
    812 )
    813{
    814 SCIP_EVENTDATA** eventdatas;
    815 int nvars;
    816 int j;
    817
    818 eventdatas = consdata->eventdatas;
    819 nvars = consdata->nvars;
    820 assert(eventdatas != NULL);
    821
    822 for( j = 0; j < nvars; ++j )
    823 {
    824 SCIP_EVENTDATA* eventdata;
    825
    826 eventdata = eventdatas[j];
    827 eventdata->varmarked = FALSE;
    828 eventdata->indvarmarked = FALSE;
    829 }
    830}
    831
    832/** perform one presolving round
    833 *
    834 * We perform the following presolving steps:
    835 *
    836 * - If the bounds of some variable force it to be nonzero, we can
    837 * fix all other variables to zero and remove the cardinality constraints
    838 * that contain it.
    839 * - If a variable is fixed to zero, we can remove the variable.
    840 * - If a variable appears twice, it can be fixed to 0.
    841 * - We substitute appregated variables.
    842 */
    843static
    845 SCIP* scip, /**< SCIP pointer */
    846 SCIP_CONS* cons, /**< constraint */
    847 SCIP_CONSDATA* consdata, /**< constraint data */
    848 SCIP_EVENTHDLR* eventhdlr, /**< event handler */
    849 SCIP_Bool* cutoff, /**< whether a cutoff happened */
    850 SCIP_Bool* success, /**< whether we performed a successful reduction */
    851 int* ndelconss, /**< number of deleted constraints */
    852 int* nupgdconss, /**< number of upgraded constraints */
    853 int* nfixedvars, /**< number of fixed variables */
    854 int* nremovedvars /**< number of variables removed */
    855 )
    856{
    857 SCIP_VAR** indvars;
    858 SCIP_VAR** vars;
    859 SCIP_Bool allvarsbinary;
    860 SCIP_Bool infeasible;
    861 SCIP_Bool fixed;
    862 int j;
    863
    864 assert(scip != NULL);
    865 assert(cons != NULL);
    866 assert(consdata != NULL);
    867 assert(eventhdlr != NULL);
    868 assert(cutoff != NULL);
    869 assert(success != NULL);
    870 assert(ndelconss != NULL);
    871 assert(nfixedvars != NULL);
    872 assert(nremovedvars != NULL);
    873
    874 *cutoff = FALSE;
    875 *success = FALSE;
    876
    877 SCIPdebugMsg(scip, "Presolving cardinality constraint <%s>.\n", SCIPconsGetName(cons) );
    878
    879 /* reset number of events stored for propagation, since presolving already performs a
    880 * complete propagation of all variables */
    881 consdata->neventdatascurrent = 0;
    883
    884 j = 0;
    885 allvarsbinary = TRUE;
    886 vars = consdata->vars;
    887 indvars = consdata->indvars;
    888
    889 /* check for variables fixed to 0 and bounds that fix a variable to be nonzero */
    890 while ( j < consdata->nvars )
    891 {
    892 SCIP_VAR* var;
    893 SCIP_VAR* indvar;
    894 SCIP_Real lb;
    895 SCIP_Real ub;
    896 SCIP_Real indlb;
    897 SCIP_Real indub;
    898 SCIP_Real scalar;
    899 SCIP_Real constant;
    900
    901 scalar = 1.0;
    902 constant = 0.0;
    903
    904 indvar = indvars[j];
    905 assert(SCIPvarIsBinary(indvar));
    906
    907 /* check for aggregation: if the constant is zero the variable is zero iff the aggregated
    908 * variable is 0 */
    909 var = vars[j];
    910 SCIP_CALL( SCIPgetProbvarSum(scip, &var, &scalar, &constant) );
    911
    912 /* try to substitute variable entry */
    913 if( var != vars[j] )
    914 {
    915 /* only if constant is zero and scalar not zero, the variable condition is equivalent */
    916 if( SCIPisZero(scip, constant) && !SCIPisZero(scip, scalar) )
    917 {
    918 SCIPdebugMsg(scip, "substituted variable <%s> by <%s>.\n", SCIPvarGetName(vars[j]), SCIPvarGetName(var));
    919
    920 /* we reuse the same indicator variable for the new variable */
    921 SCIP_CALL( dropVarEventCardinality(scip, eventhdlr, consdata, consdata->vars[j], consdata->indvars[j],
    922 &consdata->eventdatas[j]) );
    923 SCIP_CALL( catchVarEventCardinality(scip, eventhdlr, consdata, var, consdata->indvars[j], j,
    924 &consdata->eventdatas[j]) );
    925 assert(consdata->eventdatas[j] != NULL);
    926
    927 /* change the rounding locks */
    928 SCIP_CALL( unlockVariableCardinality(scip, cons, consdata->vars[j], consdata->indvars[j]) );
    929 SCIP_CALL( lockVariableCardinality(scip, cons, var, consdata->indvars[j]) );
    930
    931 /* update event data */
    932 consdata->eventdatas[j]->var = var;
    933
    934 vars[j] = var;
    935 }
    936 /* otherwise reset variable */
    937 else
    938 var = vars[j];
    939 }
    940 assert(var == vars[j]);
    941
    942 /* get bounds of variable */
    943 lb = SCIPvarGetLbLocal(var);
    944 ub = SCIPvarGetUbLocal(var);
    945
    946 /* if the variable is fixed to nonzero */
    948 {
    949 /* fix (binary) indicator variable to 1.0 (the cardinality constraint will then be modified below) */
    950 SCIP_CALL( SCIPfixVar(scip, indvar, 1.0, &infeasible, &fixed) );
    951 if( infeasible )
    952 {
    953 *cutoff = TRUE;
    954 return SCIP_OKAY;
    955 }
    956
    957 if( fixed )
    958 {
    959 SCIPdebugMsg(scip, "fixed binary variable <%s> to 1.0.\n", SCIPvarGetName(indvar));
    960 ++(*nfixedvars);
    961 }
    962 }
    963
    964 /* if the variable is fixed to 0 and strong dual reductions are allowed */
    966 {
    967 /* fix (binary) indicator variable to 0.0, if possible (the cardinality constraint will then be modified below)
    968 * note that an infeasibility implies no cut off */
    969 SCIP_CALL( SCIPfixVar(scip, indvar, 0.0, &infeasible, &fixed) );
    970 if( fixed )
    971 {
    972 SCIPdebugMsg(scip, "fixed binary variable <%s> to 0.0.\n", SCIPvarGetName(indvar));
    973 ++(*nfixedvars);
    974 }
    975 }
    976
    977 /* get bounds of indicator variable */
    978 indlb = SCIPvarGetLbLocal(indvar);
    979 indub = SCIPvarGetUbLocal(indvar);
    980
    981 /* if the variable may be treated as nonzero */
    982 if( indlb > 0.5 )
    983 {
    984 assert(indub == 1.0);
    985
    986 /* modify row and delete variable */
    987 SCIP_CALL( deleteVarCardinality(scip, cons, consdata, eventhdlr, j) );
    988 SCIPdebugMsg(scip, "deleting variable <%s> from constraint <%s>, since it may be treated as nonzero.\n",
    989 SCIPvarGetName(var), SCIPconsGetName(cons));
    990 --(consdata->cardval);
    991 ++(*nremovedvars);
    992 }
    993 /* if the indicator variable is fixed to 0 */
    994 else if( indub < 0.5 )
    995 {
    996 assert(indlb == 0.0);
    997
    998 /* fix variable to 0.0 */
    999 SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) );
    1000 if( infeasible )
    1001 {
    1002 *cutoff = TRUE;
    1003 return SCIP_OKAY;
    1004 }
    1005 if( fixed )
    1006 {
    1007 SCIPdebugMsg(scip, "fixed variable <%s> to 0.0.\n", SCIPvarGetName(var));
    1008 ++(*nfixedvars);
    1009 }
    1010
    1011 /* delete variable */
    1012 SCIP_CALL( deleteVarCardinality(scip, cons, consdata, eventhdlr, j) );
    1013 SCIPdebugMsg(scip, "deleting variable <%s> from constraint <%s>, since it is fixed to 0.\n", SCIPvarGetName(var),
    1014 SCIPconsGetName(cons));
    1015 ++(*nremovedvars);
    1016 }
    1017 else
    1018 {
    1019 /* check whether all variables are binary */
    1020 if( !SCIPvarIsBinary(var) )
    1021 allvarsbinary = FALSE;
    1022
    1023 ++j;
    1024 }
    1025 }
    1026
    1027 /* if the cardinality value is smaller than 0, then the problem is infeasible */
    1028 if( consdata->cardval < 0 )
    1029 {
    1030 SCIPdebugMsg(scip, "The problem is infeasible: more variables have bounds that keep them from being 0 than allowed.\n");
    1031
    1032 *cutoff = TRUE;
    1033 return SCIP_OKAY;
    1034 }
    1035 /* else if the cardinality value is 0 */
    1036 else if( consdata->cardval == 0 )
    1037 {
    1038 /* fix all variables of the constraint to 0 */
    1039 for( j = 0; j < consdata->nvars; ++j )
    1040 {
    1041 SCIP_CALL( SCIPfixVar(scip, consdata->vars[j], 0.0, &infeasible, &fixed) );
    1042 if( infeasible )
    1043 {
    1044 *cutoff = TRUE;
    1045 return SCIP_OKAY;
    1046 }
    1047 if( fixed )
    1048 {
    1049 SCIPdebugMsg(scip, "fixed variable <%s> to 0.0.\n", SCIPvarGetName(consdata->vars[j]));
    1050 ++(*nfixedvars);
    1051 }
    1052 }
    1053 }
    1054
    1055 /* if the cardinality constraint is redundant */
    1056 if( consdata->nvars <= consdata->cardval )
    1057 {
    1058 SCIPdebugMsg(scip, "Deleting cardinality constraint <%s> with <%d> variables and cardinality value <%d>.\n",
    1059 SCIPconsGetName(cons), consdata->nvars, consdata->cardval);
    1060
    1061 /* delete constraint */
    1062 assert(!SCIPconsIsModifiable(cons));
    1063 SCIP_CALL( SCIPdelCons(scip, cons) );
    1064 ++(*ndelconss);
    1065 *success = TRUE;
    1066 return SCIP_OKAY;
    1067 }
    1068 else
    1069 {
    1070 /* if all variables are binary create a knapsack constraint */
    1071 if( allvarsbinary )
    1072 {
    1073 SCIP_CONS* knapsackcons;
    1074 SCIP_Longint* vals;
    1075
    1076 SCIP_CALL( SCIPallocBufferArray(scip, &vals, consdata->nvars) );
    1077 for( j = 0; j < consdata->nvars; ++j )
    1078 vals[j] = 1;
    1079
    1080 /* create, add, and release the knapsack constraint */
    1081 SCIP_CALL( SCIPcreateConsKnapsack(scip, &knapsackcons, SCIPconsGetName(cons), consdata->nvars, consdata->vars,
    1082 vals, (SCIP_Longint) consdata->cardval, SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons),
    1085 SCIPconsIsStickingAtNode(cons)) );/*lint !e524*/
    1086 SCIP_CALL( SCIPaddCons(scip, knapsackcons) );
    1087 SCIP_CALL( SCIPreleaseCons(scip, &knapsackcons) );
    1088
    1089 SCIPfreeBufferArray(scip, &vals);
    1090
    1091 SCIPdebugMsg(scip, "Upgrading cardinality constraint <%s> to knapsack constraint.\n", SCIPconsGetName(cons));
    1092
    1093 /* remove the cardinality constraint globally */
    1094 assert(!SCIPconsIsModifiable(cons));
    1095 SCIP_CALL( SCIPdelCons(scip, cons) );
    1096 ++(*nupgdconss);
    1097 *success = TRUE;
    1098 }
    1099 }
    1100
    1101 return SCIP_OKAY;
    1102}
    1103
    1104/** propagates a cardinality constraint and its variables
    1105 *
    1106 * The number 'ntreatnonzeros' that is assigned to the constraint data returns the number of variables that are either
    1107 * known to be nonzero or can be treated as nonzero. We say that a variable is known to be nonzero, if zero is outside
    1108 * the domain of this variable. A variable can be treated as nonzero, if its corresponding indicator variable 'indvar' is
    1109 * fixed to 1.0, e.g., by branching.
    1110 *
    1111 * We perform the following propagation steps:
    1112 *
    1113 * - If the number 'ntreatnonzeros' is greater than the cardinality value of the constraint, then the current subproblem
    1114 * is marked as infeasible.
    1115 * - If the cardinality constraint is saturated, i.e., the number 'ntreatnonzeros' is equal to the cardinality value of
    1116 * the constraint, then fix all the other variables of the constraint to zero.
    1117 * - Remove the cardinality constraint locally if all variables are either fixed to zero or can be treated as nonzero.
    1118 * - If a (binary) indicator variable is fixed to zero, then fix the corresponding implied variable to zero.
    1119 * - If zero is outside of the domain of an implied variable, then fix the corresponding indicator variable to one.
    1120 */
    1121static
    1123 SCIP* scip, /**< SCIP pointer */
    1124 SCIP_CONS* cons, /**< constraint */
    1125 SCIP_CONSDATA* consdata, /**< constraint data */
    1126 SCIP_Bool* cutoff, /**< whether a cutoff happened */
    1127 int* nchgdomain /**< number of domain changes */
    1128 )
    1129{
    1130 assert(scip != NULL);
    1131 assert(cons != NULL);
    1132 assert(consdata != NULL);
    1133 assert(cutoff != NULL);
    1134 assert(nchgdomain != NULL);
    1135
    1136 *cutoff = FALSE;
    1137
    1138 /* if more variables may be treated as nonzero than allowed */
    1139 if( consdata->ntreatnonzeros > consdata->cardval )
    1140 {
    1141 SCIPdebugMsg(scip, "the node is infeasible, more than %d variables are fixed to be nonzero.\n", consdata->cardval);
    1143 *cutoff = TRUE;
    1144
    1145 return SCIP_OKAY;
    1146 }
    1147
    1148 /* if number of nonzeros is saturated */
    1149 if( consdata->ntreatnonzeros == consdata->cardval )
    1150 {
    1151 SCIP_VAR** vars;
    1152 SCIP_VAR** indvars;
    1153 SCIP_Bool infeasible;
    1154 SCIP_Bool tightened;
    1155 SCIP_Bool allvarfixed;
    1156 int nvars;
    1157#ifndef NDEBUG
    1158 int cnt = 0;
    1159#endif
    1160 int j;
    1161
    1162 nvars = consdata->nvars;
    1163 vars = consdata->vars;
    1164 indvars = consdata->indvars;
    1165 assert(vars != NULL);
    1166 assert(indvars != NULL);
    1167
    1168 /* fix free variables to zero */
    1169 allvarfixed = TRUE;
    1170 for( j = 0; j < nvars; ++j )
    1171 {
    1172 /* if variable is implied to be treated as nonzero */
    1173 assert( SCIPvarIsBinary(indvars[j]) );
    1174 if( SCIPvarGetLbLocal(indvars[j]) > 0.5 )
    1175 {
    1176#ifndef NDEBUG
    1177 ++cnt;
    1178#endif
    1179 }
    1180 /* else fix variable to zero if not done already */
    1181 else
    1182 {
    1183 SCIP_VAR* var;
    1184
    1185 var = vars[j];
    1186
    1187 /* fix variable */
    1189 {
    1190 SCIP_CALL( fixVariableZero(scip, var, &infeasible, &tightened) );
    1191 if( infeasible )
    1192 {
    1193 SCIPdebugMsg(scip, "the node is infeasible, more than %d variables are fixed to be nonzero.\n",
    1194 consdata->cardval);
    1196 *cutoff = TRUE;
    1197
    1198 return SCIP_OKAY;
    1199 }
    1200
    1201 if( tightened )
    1202 {
    1203 SCIPdebugMsg(scip, "fixed variable <%s> to 0, since constraint <%s> with cardinality value %d is \
    1204 saturated.\n", SCIPvarGetName(var), SCIPconsGetName(cons), consdata->cardval);
    1205 ++(*nchgdomain);
    1206 }
    1207 else
    1208 allvarfixed = FALSE;
    1209 }
    1210 }
    1211 }
    1212 assert(cnt == consdata->ntreatnonzeros);
    1213
    1214 /* reset constraint age counter */
    1215 if( *nchgdomain > 0 )
    1216 {
    1218 }
    1219
    1220 /* delete constraint locally */
    1221 if( allvarfixed )
    1222 {
    1223 assert(!SCIPconsIsModifiable(cons));
    1225
    1226 return SCIP_OKAY;
    1227 }
    1228 }
    1229
    1230 /* if relevant bound change events happened */
    1231 if( consdata->neventdatascurrent > 0 )
    1232 {
    1233 SCIP_EVENTDATA** eventdatas;
    1234 SCIP_VAR** eventvars;
    1235 int neventdatas;
    1236 int j;
    1237
    1238 neventdatas = consdata->neventdatascurrent;
    1239 eventvars = consdata->eventvarscurrent;
    1240 eventdatas = consdata->eventdatascurrent;
    1241 assert(eventdatas != NULL && eventvars != NULL);
    1242
    1243 for( j = 0; j < neventdatas; ++j )
    1244 {
    1245 SCIP_EVENTDATA* eventdata;
    1246 SCIP_Bool infeasible;
    1247 SCIP_Bool tightened;
    1248 SCIP_VAR* var;
    1249
    1250 eventdata = eventdatas[j];
    1251 var = eventvars[j];
    1252 assert(var != NULL && eventdata != NULL);
    1253 assert(eventdata->var != NULL);
    1254 assert(eventdata->indvar != NULL);
    1255 assert(var == eventdata->var || var == eventdata->indvar);
    1256 assert(SCIPvarIsBinary(eventdata->indvar));
    1257
    1258 /* if variable is an indicator variable */
    1259 if( eventdata->indvar == var )
    1260 {
    1261 assert(eventdata->indvarmarked);
    1262
    1263 /* if variable is fixed to zero */
    1265 {
    1266 SCIP_VAR* implvar;
    1267
    1268 implvar = eventdata->var;
    1269
    1270 /* fix implied variable to zero if not done already */
    1271 if( SCIPisFeasNegative(scip, SCIPvarGetLbLocal(implvar)) ||
    1273 {
    1274 SCIP_CALL( fixVariableZero(scip, implvar, &infeasible, &tightened) );
    1275
    1276 if( infeasible )
    1277 {
    1278 SCIPdebugMsg(scip, "the node is infeasible, indicator variable %s is fixed to zero although implied "
    1279 "variable %s is nonzero.\n", SCIPvarGetName(var), SCIPvarGetName(implvar));
    1281 *cutoff = TRUE;
    1282
    1283 return SCIP_OKAY;
    1284 }
    1285
    1286 if( tightened )
    1287 {
    1288 SCIPdebugMsg(scip, "fixed variable <%s> to 0, since indicator variable %s is 0.\n",
    1289 SCIPvarGetName(implvar), SCIPvarGetName(var));
    1290 ++(*nchgdomain);
    1291 }
    1292 }
    1293 }
    1294 eventdata->indvarmarked = FALSE;
    1295 }
    1296 /* else if variable is an implied variable */
    1297 else
    1298 {
    1299 assert(eventdata->var == var);
    1300 assert(eventdata->varmarked);
    1301
    1302 /* if variable is is nonzero */
    1304 {
    1305 SCIP_VAR* indvar;
    1306
    1307 indvar = eventdata->indvar;
    1308 assert(SCIPvarIsBinary(indvar));
    1309
    1310 /* fix indicator variable to 1.0 if not done already */
    1311 if( SCIPvarGetLbLocal(indvar) < 0.5 )
    1312 {
    1313 /* if fixing is infeasible */
    1314 if( SCIPvarGetUbLocal(indvar) < 0.5 )
    1315 {
    1316 SCIPdebugMsg(scip, "the node is infeasible, implied variable %s is fixed to nonzero "
    1317 "although indicator variable %s is 0.\n", SCIPvarGetName(var), SCIPvarGetName(indvar));
    1319 *cutoff = TRUE;
    1320
    1321 return SCIP_OKAY;
    1322 }
    1323 SCIP_CALL( SCIPchgVarLb(scip, indvar, 1.0) );
    1324 SCIPdebugMsg(scip, "fixed variable <%s> to 1.0, since implied variable %s is nonzero.\n",
    1325 SCIPvarGetName(indvar), SCIPvarGetName(var));
    1326 ++(*nchgdomain);
    1327 }
    1328 }
    1329 eventdata->varmarked = FALSE;
    1330 }
    1331 }
    1332 }
    1333 consdata->neventdatascurrent = 0;
    1334
    1335 return SCIP_OKAY;
    1336}
    1337
    1338/** apply unbalanced branching (see the function \ref enforceCardinality() for further information) */
    1339static
    1341 SCIP* scip, /**< SCIP pointer */
    1342 SCIP_SOL* sol, /**< solution to be enforced (or NULL) */
    1343 SCIP_CONS* branchcons, /**< cardinality constraint */
    1344 SCIP_VAR** vars, /**< variables of constraint */
    1345 SCIP_VAR** indvars, /**< indicator variables */
    1346 int nvars, /**< number of variables of constraint */
    1347 int cardval, /**< cardinality value of constraint */
    1348 int branchnnonzero, /**< number of variables that are fixed to be nonzero */
    1349 int branchpos /**< position in array 'vars' */
    1350 )
    1351{
    1352 SCIP_Bool infeasible;
    1353 SCIP_NODE* node1;
    1354 SCIP_NODE* node2;
    1355
    1356 /* check whether the variable selected for branching has a nonzero LP solution */
    1357 assert(!SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, vars[branchpos])));
    1358 assert(SCIPisFeasZero(scip, SCIPvarGetLbLocal(indvars[branchpos])));
    1359 assert(SCIPisFeasEQ(scip, SCIPvarGetUbLocal(indvars[branchpos]), 1.0));
    1360
    1361 /* create branches */
    1362 SCIPdebugMsg(scip, "apply unbalanced branching on variable <%s> of constraint <%s>.\n",
    1363 SCIPvarGetName(indvars[branchpos]), SCIPconsGetName(branchcons));
    1364
    1365 /* create node 1 */
    1366
    1367 /* calculate node selection and objective estimate for node 1 */
    1369 SCIPcalcChildEstimate(scip, vars[branchpos], 0.0) ) );
    1370
    1371 /* fix branching variable to zero */
    1372 SCIP_CALL( fixVariableZeroNode(scip, vars[branchpos], node1, &infeasible) );
    1373 assert(! infeasible);
    1374
    1375 /* create node 2 */
    1376
    1377 /* if the new number of nonzero variables is equal to the number of allowed nonzero variables;
    1378 * i.e. cardinality constraint is saturated */
    1379 assert(branchnnonzero + 1 <= cardval);
    1380 if( branchnnonzero + 1 == cardval )
    1381 {
    1382 SCIP_Real nodeselest;
    1383 SCIP_Real objest;
    1384#ifndef NDEBUG
    1385 int cnt = 0;
    1386#endif
    1387 int j;
    1388
    1389 /* calculate node selection and objective estimate for node 2 */
    1390 nodeselest = 0.0;
    1392 for( j = 0; j < nvars; ++j )
    1393 {
    1394 /* we only consider variables in constraint that are not the branching variable and are not fixed to nonzero */
    1395 if( j != branchpos && SCIPvarGetLbLocal(indvars[j]) < 0.5 && !SCIPisFeasPositive(scip, SCIPvarGetLbLocal(vars[j]))
    1397 )
    1398 {
    1399 objest += SCIPcalcChildEstimateIncrease(scip, vars[j], SCIPgetSolVal(scip, sol, vars[j]), 0.0);
    1400 nodeselest += SCIPcalcNodeselPriority(scip, vars[j], SCIP_BRANCHDIR_DOWNWARDS, 0.0);
    1401#ifndef NDEBUG
    1402 ++cnt;
    1403#endif
    1404 }
    1405 }
    1406 assert(objest >= SCIPgetLocalTransEstimate(scip));
    1407 assert(cnt == nvars - (1 + branchnnonzero));
    1408 assert(cnt > 0);
    1409
    1410 /* create node 2 */
    1411 SCIP_CALL( SCIPcreateChild(scip, &node2, nodeselest, objest) );
    1412
    1413 /* indicate that branching variable may be treated as nonzero */
    1414 SCIP_CALL( SCIPchgVarLbNode(scip, node2, indvars[branchpos], 1.0) );
    1415
    1416 /* fix variables to zero since cardinality constraint is now saturated */
    1417 for( j = 0; j < nvars; ++j )
    1418 {
    1419 /* we only consider variables in constraint that are not the branching variable and are not fixed to nonzero */
    1420 if( j != branchpos && SCIPvarGetLbLocal(indvars[j]) < 0.5
    1423 )
    1424 {
    1425 SCIP_CALL( fixVariableZeroNode(scip, vars[j], node2, &infeasible) );
    1426 assert(!infeasible);
    1427 }
    1428 }
    1429 }
    1430 else
    1431 {
    1432 /* calculate node selection estimate for node 2 */
    1434
    1435 /* indicate that branching variable may be treated as nonzero */
    1436 SCIP_CALL( SCIPchgVarLbNode(scip, node2, indvars[branchpos], 1.0) );
    1437 }
    1438
    1439 return SCIP_OKAY;
    1440}
    1441
    1442/** apply balanced branching (see the function enforceCardinality() for further information) */
    1443static
    1445 SCIP* scip, /**< SCIP pointer */
    1446 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    1447 SCIP_SOL* sol, /**< solution to be enforced (or NULL) */
    1448 SCIP_CONS* branchcons, /**< cardinality constraint */
    1449 SCIP_VAR** vars, /**< variables of constraint */
    1450 SCIP_VAR** indvars, /**< indicator variables */
    1451 int nvars, /**< number of variables of constraint */
    1452 int cardval, /**< cardinality value of constraint */
    1453 int branchnnonzero, /**< number of variables that are fixed to be nonzero */
    1454 int branchpos, /**< position in array 'vars' */
    1455 SCIP_Real balancedcutoff /**< cut off value for deciding whether to apply balanced branching */
    1456 )
    1457{
    1458 SCIP_VAR** branchvars;
    1459 SCIP_VAR** branchindvars;
    1460 int nbranchvars;
    1461 SCIP_Real splitval1;
    1462 SCIP_Real splitval2;
    1463 SCIP_Real weight1;
    1464 SCIP_Real weight2;
    1465 SCIP_Real sum1;
    1466 SCIP_Real sum2;
    1467 SCIP_Real w;
    1468 int newcardval;
    1469 int nnonzero;
    1470 int nzero;
    1471 int nbuffer;
    1472 int ind;
    1473 int cnt;
    1474 int j;
    1475
    1476 /* check parameters */
    1477 if( SCIPconshdlrGetSepaFreq(conshdlr) != 1 )
    1478 {
    1479 SCIPerrorMessage("balanced branching is only possible if separation frequency of constraint handler is 1.\n");
    1481 }
    1482
    1483 cnt = 0;
    1484 nzero = 0;
    1485 nnonzero = 0;
    1486 nbranchvars = 0;
    1487
    1488 weight1 = 0.0;
    1489 weight2 = 0.0;
    1490 sum1 = 0.0;
    1491 sum2 = 0.0;
    1492
    1493 /* allocate buffer arrays */
    1494 nbuffer = nvars-branchnnonzero;
    1495 SCIP_CALL( SCIPallocBufferArray(scip, &branchvars, nbuffer) );
    1496 SCIP_CALL( SCIPallocBufferArray(scip, &branchindvars, nbuffer) );
    1497
    1498 /* compute weight */
    1499 for( j = 0; j < nvars; ++j )
    1500 {
    1501 SCIP_VAR* var;
    1502
    1503 var = vars[j];
    1504
    1505 /* if(binary) indicator variable is not fixed to 1.0 */
    1506 if( SCIPvarGetLbLocal(indvars[j]) < 0.5 && !SCIPisFeasPositive(scip, SCIPvarGetLbLocal(var))
    1508 {
    1509 /* if implied variable is not already fixed to zero */
    1511 {
    1512 SCIP_Real val = REALABS(SCIPgetSolVal(scip, sol, var));
    1513
    1514 weight1 += val * (SCIP_Real) (j - (nnonzero + nzero));
    1515 weight2 += val;
    1516 branchindvars[nbranchvars] = indvars[j];
    1517 branchvars[nbranchvars++] = var;
    1518
    1519 if( !SCIPisFeasZero(scip, val) )
    1520 ++cnt;
    1521 }
    1522 else
    1523 ++nzero;
    1524 }
    1525 else
    1526 ++nnonzero;
    1527 }
    1528 assert(nnonzero == branchnnonzero);
    1529 assert(nbranchvars <= nvars - branchnnonzero);
    1530
    1531 assert(cnt >= cardval-nnonzero);
    1532 assert(!SCIPisFeasZero(scip, weight2));
    1533 w = weight1/weight2; /*lint !e414*/
    1534
    1535 ind = (int)SCIPfloor(scip, w);
    1536 assert(0 <= ind && ind < nbranchvars-1);
    1537
    1538 /* compute LP sums */
    1539 for( j = 0; j <= ind; ++j )
    1540 {
    1541 SCIP_Real val;
    1542
    1543 val = SCIPgetSolVal(scip, sol, branchvars[j]);
    1544
    1545 if( SCIPisFeasPositive(scip, val) )
    1546 {
    1547 assert(SCIPisFeasPositive(scip, SCIPvarGetUbLocal(branchvars[j])));
    1548 sum1 += val / SCIPvarGetUbLocal(branchvars[j]);
    1549 }
    1550 else if( SCIPisFeasNegative(scip, val) )
    1551 {
    1552 assert(SCIPisFeasNegative(scip, SCIPvarGetLbLocal(branchvars[j])));
    1553 sum1 += val / SCIPvarGetLbLocal(branchvars[j]);
    1554 }
    1555 }
    1556 for( j = ind+1; j < nbranchvars; ++j )
    1557 {
    1558 SCIP_Real val;
    1559
    1560 val = SCIPgetSolVal(scip, sol, branchvars[j]);
    1561
    1562 if( SCIPisFeasPositive(scip, val) )
    1563 {
    1564 assert(SCIPisFeasPositive(scip, SCIPvarGetUbLocal(branchvars[j])));
    1565 sum2 += val/SCIPvarGetUbLocal(branchvars[j]);
    1566 }
    1567 else if( SCIPisFeasNegative(scip, val) )
    1568 {
    1569 assert(SCIPisFeasNegative(scip, SCIPvarGetLbLocal(branchvars[j])));
    1570 sum2 += val/SCIPvarGetLbLocal(branchvars[j]);
    1571 }
    1572 }
    1573
    1574 /* compute cardinality values of branching constraints */
    1575 newcardval = cardval - nnonzero;
    1576 splitval1 = sum1 + (SCIP_Real)newcardval - sum2 - 1.0;/*lint !e834*/
    1577 splitval1 = SCIPfloor(scip, splitval1/2);
    1578 splitval1 = MAX(splitval1, 0);
    1579 assert((int)splitval1 >= 0);
    1580 assert((int)splitval1 <= MIN(newcardval-1, ind));
    1581 splitval2 = (SCIP_Real)(newcardval-1);
    1582 splitval2 -= splitval1;
    1583
    1584 /* the lower or upper LP row of each branching constraint should cut off the current LP solution
    1585 * if this is not the case, then use unbalanced branching */
    1586 if ( !SCIPisFeasLT(scip, (SCIP_Real) splitval1 + balancedcutoff, sum1) ||
    1587 !SCIPisFeasLT(scip, (SCIP_Real) splitval2 + balancedcutoff, sum2) )
    1588 {
    1589 SCIP_CALL( branchUnbalancedCardinality(scip, sol, branchcons, vars, indvars, nvars, cardval,
    1590 branchnnonzero, branchpos) );
    1591 }
    1592 else
    1593 {
    1594 char name[SCIP_MAXSTRLEN];
    1595 SCIP_NODE* node1;
    1596 SCIP_NODE* node2;
    1597 SCIP_CONS* cons1;
    1598 SCIP_CONS* cons2;
    1599
    1600 SCIPdebugMsg(scip, "apply balanced branching on constraint <%s>.\n", SCIPconsGetName(branchcons));
    1601
    1602 if( SCIPisFeasZero(scip, splitval1) )
    1603 {
    1604 SCIP_Bool infeasible;
    1605 SCIP_Real nodeselest;
    1606 SCIP_Real objest;
    1607
    1608 nodeselest = 0.0;
    1610
    1611 /* calculate node selection and objective estimate for node */
    1612 for( j = 0; j <= ind; ++j )
    1613 {
    1614 objest += SCIPcalcChildEstimateIncrease(scip, branchvars[j], SCIPgetSolVal(scip, sol, branchvars[j]), 0.0);
    1615 nodeselest += SCIPcalcNodeselPriority(scip, branchvars[j], SCIP_BRANCHDIR_DOWNWARDS, 0.0);
    1616 }
    1617 assert( objest >= SCIPgetLocalTransEstimate(scip) );
    1618
    1619 /* create node 1 */
    1620 SCIP_CALL( SCIPcreateChild(scip, &node1, nodeselest, objest) );
    1621
    1622 for( j = 0; j <= ind; ++j )
    1623 {
    1624 SCIP_CALL( fixVariableZeroNode(scip, branchvars[j], node1, &infeasible) );
    1625 assert(!infeasible);
    1626 }
    1627 }
    1628 else
    1629 {
    1630 /* calculate node selection and objective estimate for node */
    1632
    1633 /* create branching constraint for node 1 */
    1635 SCIP_CALL( SCIPcreateConsCardinality(scip, &cons1, name, ind+1, branchvars, (int)splitval1, branchindvars, NULL,
    1637
    1638 /* add constraint to node */
    1639 SCIP_CALL( SCIPaddConsNode(scip, node1, cons1, NULL) );
    1640
    1641 /* release constraint */
    1642 SCIP_CALL( SCIPreleaseCons(scip, &cons1) );
    1643 }
    1644
    1645 if( SCIPisFeasZero(scip, splitval2) )
    1646 {
    1647 SCIP_Bool infeasible;
    1648 SCIP_Real nodeselest;
    1649 SCIP_Real objest;
    1650
    1651 nodeselest = 0.0;
    1653
    1654 /* calculate node selection and objective estimate for node */
    1655 for( j = ind+1; j < nbranchvars; ++j )
    1656 {
    1657 objest += SCIPcalcChildEstimateIncrease(scip, branchvars[j], SCIPgetSolVal(scip, sol, branchvars[j]), 0.0);
    1658 nodeselest += SCIPcalcNodeselPriority(scip, branchvars[j], SCIP_BRANCHDIR_DOWNWARDS, 0.0);
    1659 }
    1660 assert(nbranchvars - (ind + 1) > 0);
    1661 assert(objest >= SCIPgetLocalTransEstimate(scip));
    1662
    1663 /* create node 1 */
    1664 SCIP_CALL( SCIPcreateChild(scip, &node2, nodeselest, objest) );
    1665
    1666 for( j = ind+1; j < nbranchvars; ++j )
    1667 {
    1668 SCIP_CALL( fixVariableZeroNode(scip, branchvars[j], node2, &infeasible) );
    1669 assert(!infeasible);
    1670 }
    1671 }
    1672 else
    1673 {
    1674 /* calculate node selection and objective estimate for node */
    1676
    1677 /* shift the second half of variables */
    1678 cnt = 0;
    1679 for( j = ind+1; j < nbranchvars; ++j )
    1680 {
    1681 branchvars[cnt] = branchvars[j];
    1682 branchindvars[cnt++] = branchindvars[j];
    1683 }
    1684 assert(cnt == nbranchvars - (ind + 1));
    1685
    1686 /* create branching constraint for node 2 */
    1687 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "brright_#% " SCIP_LONGINT_FORMAT , SCIPgetNNodes(scip));
    1688 SCIP_CALL( SCIPcreateConsCardinality(scip, &cons2, name, cnt, branchvars, (int)splitval2, branchindvars, NULL,
    1690
    1691 /* add constraint to node */
    1692 SCIP_CALL( SCIPaddConsNode(scip, node2, cons2, NULL) );
    1693
    1694 /* release constraint */
    1695 SCIP_CALL( SCIPreleaseCons(scip, &cons2) );
    1696 }
    1697 }
    1698
    1699 /* free buffer arrays */
    1700 SCIPfreeBufferArray(scip, &branchindvars);
    1701 SCIPfreeBufferArray(scip, &branchvars);
    1702
    1703 return SCIP_OKAY;
    1704}
    1705
    1706/** enforcement method
    1707 *
    1708 * We check whether the current solution is feasible. If not, the cardinality constraints can be enforced by different
    1709 * branching rules:
    1710 *
    1711 * - Unbalanced branching: Branch on the neighborhood of a single variable \f$i\f$, i.e., in one branch \f$x_i\f$ is
    1712 * fixed to zero and in the other we modify cardinality constraints \f$|\mbox{supp}(x)| \leq k\f$ with \f$i\in D\f$ to
    1713 * \f$|\mbox{supp}(x_{D\setminus i}) \leq k-1\f$
    1714 *
    1715 * - Balanced branching: First, choose a cardinality constraint \f$|\mbox{supp}(x_D) \leq k\f$ that is violated by the
    1716 * current LP solution. Then, we compute \f$W = \sum_{j=1}^n |x_i|\f$ and \f$w = \sum_{j=1}^n j\, |x_i|\f$. Next,
    1717 * search for the index \f$r\f$ that satisfies
    1718 * \f[
    1719 * r \leq \frac{w}{W} < r+1.
    1720 * \f]
    1721 * Choose a number \f$s\f$ with \f$0\leq s < \min\{k, r\}\f$. The branches are then
    1722 * \f[
    1723 * |\mbox{supp}(x_{d_1}, \ldots, x_{d_r})| \leq s \qquad \mbox{and}\qquad
    1724 * |\mbox{supp}(x_{d_{r+1}}, \ldots, x_{d_{n}})| \leq k-s-1,
    1725 * \f]
    1726 * where \f$d_1, \ldots, d_n\f$ are the elements of the set \f$D\f$.
    1727 *
    1728 * The branching constraint is chosen by the largest sum of variable values.
    1729 */
    1730static
    1732 SCIP* scip, /**< SCIP pointer */
    1733 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    1734 SCIP_SOL* sol, /**< solution to be enforced (or NULL) */
    1735 int nconss, /**< number of constraints */
    1736 SCIP_CONS** conss, /**< indicator constraints */
    1737 SCIP_RESULT* result /**< result */
    1738 )
    1739{
    1740 SCIP_CONSHDLRDATA* conshdlrdata;
    1741 SCIP_CONSDATA* consdata;
    1742 SCIP_CONS* branchcons;
    1743 SCIP_Real maxweight;
    1744 SCIP_VAR** indvars;
    1745 SCIP_VAR** vars;
    1746 int nvars;
    1747 int cardval;
    1748
    1749 SCIP_Bool branchbalanced = FALSE;
    1750 SCIP_Bool branchallpos = TRUE;
    1751 SCIP_Bool branchallneg = TRUE;
    1752 int branchnnonzero;
    1753 int branchpos;
    1754 int c;
    1755
    1756 assert(scip != NULL);
    1757 assert(conshdlr != NULL);
    1758 assert(conss != NULL);
    1759 assert(result != NULL);
    1760
    1761 maxweight = -SCIP_REAL_MAX;
    1762 branchcons = NULL;
    1763 branchnnonzero = -1;
    1764 branchpos = -1;
    1765
    1766 SCIPdebugMsg(scip, "Enforcing cardinality constraints <%s>.\n", SCIPconshdlrGetName(conshdlr) );
    1767 *result = SCIP_FEASIBLE;
    1768
    1769 /* get constraint handler data */
    1770 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    1771 assert(conshdlrdata != NULL);
    1772
    1773 /* search for a constraint with largest violation; from this constraint, we select the variable with largest LP value */
    1774 for( c = 0; c < nconss; ++c )
    1775 {
    1776 SCIP_CONS* cons;
    1777 SCIP_Bool cutoff;
    1778 SCIP_Real weight;
    1779 SCIP_Real maxval;
    1780 SCIP_Bool allpos = TRUE;
    1781 SCIP_Bool allneg = TRUE;
    1782 int nnonzero; /* number of variables that are currently deactivated in constraint */
    1783 int pos; /* position of variable with largest LP solution value */
    1784 int nchgdomain;
    1785 int cnt;
    1786 int j;
    1787
    1788 cons = conss[c];
    1789 assert(cons != NULL);
    1790 consdata = SCIPconsGetData(cons);
    1791 assert(consdata != NULL);
    1792
    1793 nchgdomain = 0;
    1794 cnt = 0;
    1795 nnonzero = 0;
    1796 pos = -1;
    1797 nvars = consdata->nvars;
    1798 vars = consdata->vars;
    1799 indvars = consdata->indvars;
    1800 cardval = consdata->cardval;
    1801
    1802 /* do nothing if there are not enough variables - this is usually eliminated by preprocessing */
    1803 if( nvars < 2 )
    1804 continue;
    1805
    1806 /* first perform propagation (it might happen that standard propagation is turned off) */
    1807 SCIP_CALL( propCardinality(scip, cons, consdata, &cutoff, &nchgdomain) );
    1808
    1809 SCIPdebugMsg(scip, "propagating <%s> in enforcing (cutoff: %u, domain reductions: %d).\n",
    1810 SCIPconsGetName(cons), cutoff, nchgdomain);
    1811 if( cutoff )
    1812 {
    1813 *result = SCIP_CUTOFF;
    1814 return SCIP_OKAY;
    1815 }
    1816 if( nchgdomain > 0 )
    1817 {
    1818 *result = SCIP_REDUCEDDOM;
    1819 return SCIP_OKAY;
    1820 }
    1821 assert(nchgdomain == 0);
    1822
    1823 /* check constraint */
    1824 weight = 0.0;
    1825 maxval = -SCIPinfinity(scip);
    1826
    1827 for( j = 0; j < nvars; ++j )
    1828 {
    1829 SCIP_VAR* var;
    1830
    1831 /* check whether indicator variable is zero, but variable in cardinality constraint is not fixed to zero;
    1832 * if the variable is not multiaggregated this case should already be handled in propagation */
    1833 if( SCIPvarGetUbLocal(indvars[j]) == 0.0 &&
    1834 (
    1836 )
    1837 )
    1838 {
    1839 *result = SCIP_CUTOFF;
    1840 return SCIP_OKAY;
    1841 }
    1842
    1843 assert(SCIPvarGetStatus(indvars[j]) != SCIP_VARSTATUS_MULTAGGR);
    1844
    1845 var = vars[j];
    1846
    1847 /* variable is not fixed to nonzero */
    1848 if( SCIPvarGetLbLocal(indvars[j]) < 0.5
    1851 )
    1852 {
    1853 SCIP_Real val;
    1854
    1855 val = SCIPgetSolVal(scip, sol, var);
    1856 if( SCIPisFeasPositive(scip, val))
    1857 allneg = FALSE;
    1858 else if( SCIPisFeasNegative(scip, val))
    1859 allpos = FALSE;
    1860 val = REALABS(val);
    1861
    1862 if( !SCIPisFeasZero(scip, val) )
    1863 {
    1864 /* determine maximum nonzero-variable solution value */
    1865 if( SCIPisFeasGT(scip, val, maxval) )
    1866 {
    1867 pos = j;
    1868 maxval = val;
    1869 }
    1870
    1871 weight += val;
    1872 ++cnt;
    1873 }
    1874 }
    1875 else
    1876 ++nnonzero;
    1877 }
    1878 weight -= cardval;
    1879 weight += nnonzero;
    1880
    1881 /* if we detected a cut off */
    1882 if( nnonzero > cardval )
    1883 {
    1884 SCIPdebugMsg(scip, "Detected cut off: constraint <%s> has %d many variables that can be treated as nonzero, \
    1885 although only %d many are feasible.\n", SCIPconsGetName(cons), nnonzero, cardval);
    1886 *result = SCIP_CUTOFF;
    1887 return SCIP_OKAY;
    1888 }
    1889 /* else if domain can be reduced (since node 2 created in branchUnbalancedCardinality() would be infeasible) */
    1890 else if( cnt > 0 && nnonzero + 1 > cardval )
    1891 {
    1892 SCIP_Bool infeasible;
    1893 int v;
    1894
    1895 for( v = 0; v < nvars; ++v )
    1896 {
    1897 SCIP_VAR* var;
    1898
    1899 var = vars[v];
    1900
    1901 /* variable is not fixed to nonzero */
    1902 assert(SCIPvarIsBinary(indvars[v]));
    1903 if( SCIPvarGetLbLocal(indvars[v]) < 0.5
    1906 )
    1907 {
    1909 assert(!infeasible);
    1910 SCIPdebugMsg(scip, "detected domain reduction in enforcing: fixed variable <%s> to zero.\n", SCIPvarGetName(var));
    1911 }
    1912 }
    1913
    1914 *result = SCIP_REDUCEDDOM;
    1915 return SCIP_OKAY;
    1916 }
    1917
    1918 /* if constraint is violated */
    1919 if( cnt > cardval - nnonzero && weight > maxweight )
    1920 {
    1921 maxweight = weight;
    1922 branchcons = cons;
    1923 branchnnonzero = nnonzero;
    1924 branchpos = pos;
    1925 branchallneg = allneg;
    1926 branchallpos = allpos;
    1927 }
    1928 }
    1929
    1930 /* if all constraints are feasible */
    1931 if( branchcons == NULL )
    1932 {
    1933 SCIP_SOL* primsol;
    1934 SCIP_Bool success;
    1935
    1936 /* polish primal solution */
    1937 SCIP_CALL( SCIPcreateSolCopy(scip, &primsol, sol) );
    1938 SCIP_CALL( polishPrimalSolution(scip, conss, nconss, sol, primsol) );
    1939 SCIP_CALL( SCIPtrySol(scip, primsol, FALSE, TRUE, FALSE, TRUE, FALSE, &success) );
    1940 SCIP_CALL( SCIPfreeSol(scip, &primsol) );
    1941
    1942 SCIPdebugMsg(scip, "All cardinality constraints are feasible.\n");
    1943 return SCIP_OKAY;
    1944 }
    1945 assert(branchnnonzero >= 0);
    1946 assert(branchpos >= 0);
    1947
    1948 /* get data for branching or domain reduction */
    1949 consdata = SCIPconsGetData(branchcons);
    1950 assert(consdata != NULL);
    1951 nvars = consdata->nvars;
    1952 vars = consdata->vars;
    1953 indvars = consdata->indvars;
    1954 cardval = consdata->cardval;
    1955
    1956 /* we only use balanced branching if either the lower or the upper bound row of the branching constraint is known
    1957 * to be tight or violated */
    1958 if( conshdlrdata->branchbalanced && !SCIPisFeasNegative(scip, maxweight) && ( branchallneg || branchallpos )
    1959 && (conshdlrdata->balanceddepth == -1 || SCIPgetDepth(scip) <= conshdlrdata->balanceddepth)
    1960 )
    1961 {
    1962 branchbalanced = TRUE;
    1963 }
    1964
    1965 /* apply branching rule */
    1966 if( branchbalanced )
    1967 {
    1968 SCIP_CALL( branchBalancedCardinality(scip, conshdlr, sol, branchcons, vars, indvars, nvars, cardval, branchnnonzero, branchpos,
    1969 conshdlrdata->balancedcutoff) );
    1970 }
    1971 else
    1972 {
    1973 SCIP_CALL( branchUnbalancedCardinality(scip, sol, branchcons, vars, indvars, nvars, cardval, branchnnonzero,
    1974 branchpos) );
    1975 }
    1976
    1977 SCIP_CALL( SCIPresetConsAge(scip, branchcons) );
    1978 *result = SCIP_BRANCHED;
    1979
    1980 return SCIP_OKAY;
    1981}
    1982
    1983/** Generate row
    1984 *
    1985 * We generate the row corresponding to the following simple valid inequalities:
    1986 * \f[
    1987 * \frac{x_1}{u_1} + \ldots + \frac{x_n}{u_n} \leq k\qquad\mbox{and}\qquad
    1988 * \frac{x_1}{\ell_1} + \ldots + \frac{x_n}{\ell_1} \leq k,
    1989 * \f]
    1990 * where \f$\ell_1, \ldots, \ell_n\f$ and \f$u_1, \ldots, u_n\f$ are the nonzero and finite lower and upper bounds of
    1991 * the variables \f$x_1, \ldots, x_n\f$ and k is the right hand side of the cardinality constraint. If at least k upper
    1992 * bounds < 0 or a lower bounds > 0, the constraint itself is redundant, so the cut is not applied (lower bounds > 0
    1993 * and upper bounds < 0 are usually detected in presolving or propagation). Infinite bounds and zero are skipped. Thus
    1994 * \f$\ell_1, \ldots, \ell_n\f$ are all negative, which results in the \f$\leq\f$ inequality.
    1995 *
    1996 * Note that in fact, any mixture of nonzero finite lower and upper bounds would lead to a valid inequality as
    1997 * above. However, usually either the lower or upper bound is nonzero. Thus, the above inequalities are the most
    1998 * interesting.
    1999 */
    2000static
    2002 SCIP* scip, /**< SCIP pointer */
    2003 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    2004 SCIP_CONS* cons, /**< constraint */
    2005 SCIP_Bool local, /**< produce local cut? */
    2006 SCIP_ROW** rowlb, /**< output: row for lower bounds (or NULL if not needed) */
    2007 SCIP_ROW** rowub /**< output: row for upper bounds (or NULL if not needed) */
    2008 )
    2009{
    2010 char name[SCIP_MAXSTRLEN];
    2011 SCIP_CONSDATA* consdata;
    2012 SCIP_VAR** vars;
    2013 SCIP_Real* vals;
    2014 SCIP_Real val;
    2015 int nvars;
    2016 int cnt;
    2017 int j;
    2018
    2019 assert(scip != NULL);
    2020 assert(conshdlr != NULL);
    2021 assert(cons != NULL);
    2022
    2023 consdata = SCIPconsGetData(cons);
    2024 assert(consdata != NULL);
    2025 assert(consdata->vars != NULL);
    2026 assert(consdata->indvars != NULL);
    2027
    2028 nvars = consdata->nvars;
    2029 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    2030 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
    2031
    2032 /* take care of upper bounds */
    2033 if( rowub != NULL )
    2034 {
    2035 int cardval;
    2036
    2037 cnt = 0;
    2038 cardval = consdata->cardval;
    2039 for( j = 0; j < nvars; ++j )
    2040 {
    2041 if( local )
    2042 val = SCIPvarGetLbLocal(consdata->vars[j]);
    2043 else
    2044 val = SCIPvarGetUbGlobal(consdata->vars[j]);
    2045
    2046 /* if a variable may be treated as nonzero, then update cardinality value */
    2047 if( SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(consdata->indvars[j]), 1.0) )
    2048 {
    2049 --cardval;
    2050 continue;
    2051 }
    2052
    2053 if( !SCIPisInfinity(scip, val) && !SCIPisZero(scip, val) && !SCIPisNegative(scip, val) )
    2054 {
    2055 assert(consdata->vars[j] != NULL);
    2056 vars[cnt] = consdata->vars[j];
    2057 vals[cnt++] = 1.0/val;
    2058 }
    2059 }
    2060 assert(cardval >= 0);
    2061
    2062 /* if cut is meaningful */
    2063 if( cnt > cardval )
    2064 {
    2065 /* create upper bound inequality if at least two of the bounds are finite and nonzero */
    2066 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "cardub#%s", SCIPconsGetName(cons));
    2067 SCIP_CALL( SCIPcreateEmptyRowCons(scip, rowub, cons, name, -SCIPinfinity(scip), (SCIP_Real)cardval,
    2068 local, TRUE, FALSE) );
    2069 SCIP_CALL( SCIPaddVarsToRow(scip, *rowub, cnt, vars, vals) );
    2070 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, *rowub, NULL) ) );
    2071 }
    2072 }
    2073
    2074 /* take care of lower bounds */
    2075 if( rowlb != NULL )
    2076 {
    2077 int cardval;
    2078
    2079 cnt = 0;
    2080 cardval = consdata->cardval;
    2081 for( j = 0; j < nvars; ++j )
    2082 {
    2083 if( local )
    2084 val = SCIPvarGetLbLocal(consdata->vars[j]);
    2085 else
    2086 val = SCIPvarGetLbGlobal(consdata->vars[j]);
    2087
    2088 /* if a variable may be treated as nonzero, then update cardinality value */
    2089 if( SCIPvarGetLbGlobal(consdata->indvars[j]) > 0.5 )
    2090 {
    2091 --cardval;
    2092 continue;
    2093 }
    2094
    2095 if( !SCIPisInfinity(scip, -val) && !SCIPisZero(scip, val) && !SCIPisPositive(scip, val) )
    2096 {
    2097 assert(consdata->vars[j] != NULL);
    2098 vars[cnt] = consdata->vars[j];
    2099 vals[cnt++] = 1.0/val;
    2100 }
    2101 }
    2102 assert(cardval >= 0);
    2103
    2104 /* if cut is meaningful */
    2105 /* coverity[copy_paste_error] */
    2106 if( cnt > cardval )
    2107 {
    2108 /* create lower bound inequality if at least two of the bounds are finite and nonzero */
    2109 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "cardlb#%s", SCIPconsGetName(cons));
    2110 SCIP_CALL( SCIPcreateEmptyRowCons(scip, rowlb, cons, name, -SCIPinfinity(scip), (SCIP_Real)cardval,
    2111 local, TRUE, FALSE) );
    2112 SCIP_CALL( SCIPaddVarsToRow(scip, *rowlb, nvars, vars, vals) );
    2113 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, *rowlb, NULL) ) );
    2114 }
    2115 }
    2116
    2117 SCIPfreeBufferArray(scip, &vals);
    2118 SCIPfreeBufferArray(scip, &vars);
    2119
    2120 return SCIP_OKAY;
    2121}
    2122
    2123/** initialize or separate bound inequalities from cardinality constraints
    2124 * (see the function \ref generateRowCardinality() for an explanation of bound inequalities)
    2125 */
    2126static
    2128 SCIP* scip, /**< SCIP pointer */
    2129 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    2130 SCIP_CONS** conss, /**< cardinality constraints */
    2131 int nconss, /**< number of cardinality constraints */
    2132 SCIP_SOL* sol, /**< LP solution to be separated (or NULL) */
    2133 SCIP_Bool solvedinitlp, /**< TRUE if initial LP relaxation at a node is solved */
    2134 int* ngen, /**< pointer to store number of cuts generated (or NULL) */
    2135 SCIP_Bool* cutoff /**< pointer to store whether a cutoff occurred */
    2136 )
    2137{
    2138 int cnt = 0;
    2139 int c;
    2140
    2141 assert(scip != NULL);
    2142 assert(conss != NULL);
    2143
    2144 *cutoff = FALSE;
    2145
    2146 for( c = nconss-1; c >= 0; --c )
    2147 {
    2148 SCIP_CONSDATA* consdata;
    2149 SCIP_ROW* rowub = NULL;
    2150 SCIP_ROW* rowlb = NULL;
    2151 SCIP_Bool release = FALSE;
    2152
    2153 assert(conss != NULL);
    2154 assert(conss[c] != NULL);
    2155 consdata = SCIPconsGetData(conss[c]);
    2156 assert(consdata != NULL);
    2157
    2158 if( solvedinitlp )
    2159 SCIPdebugMsg(scip, "Separating inequalities for cardinality constraint <%s>.\n", SCIPconsGetName(conss[c]) );
    2160 else
    2161 SCIPdebugMsg(scip, "Checking for initial rows for cardinality constraint <%s>.\n", SCIPconsGetName(conss[c]) );
    2162
    2163 /* generate rows associated to cardinality constraint; the rows are stored in the constraint data
    2164 * if they are globally valid */
    2165 if( SCIPconsIsLocal(conss[c]) )
    2166 {
    2167 SCIP_CALL( generateRowCardinality(scip, conshdlr, conss[c], TRUE, &rowlb, &rowub) );
    2168 release = TRUE;
    2169 }
    2170 else
    2171 {
    2172 if( consdata->rowub == NULL || consdata->rowlb == NULL )
    2173 {
    2174 SCIP_CALL( generateRowCardinality(scip, conshdlr, conss[c], FALSE,
    2175 (consdata->rowlb == NULL) ? &consdata->rowlb : NULL,
    2176 (consdata->rowub == NULL) ? &consdata->rowub : NULL) );/*lint !e826*/
    2177 }
    2178 rowub = consdata->rowub;
    2179 rowlb = consdata->rowlb;
    2180 }
    2181
    2182 /* put corresponding rows into LP */
    2183 if( rowub != NULL && !SCIProwIsInLP(rowub) && ( solvedinitlp || SCIPisCutEfficacious(scip, sol, rowub) ) )
    2184 {
    2185 assert(SCIPisInfinity(scip, -SCIProwGetLhs(rowub)));
    2186 assert(SCIPisLE(scip, SCIProwGetRhs(rowub), (SCIP_Real)consdata->cardval));
    2187
    2188 SCIP_CALL( SCIPaddRow(scip, rowub, FALSE, cutoff) );
    2189 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, rowub, NULL) ) );
    2190
    2191 if( solvedinitlp )
    2192 {
    2193 SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
    2194 }
    2195 ++cnt;
    2196 }
    2197
    2198 if( ! (*cutoff) && rowlb != NULL && !SCIProwIsInLP(rowlb)
    2199 && ( solvedinitlp || SCIPisCutEfficacious(scip, sol, rowlb) )
    2200 )
    2201 {
    2202 assert(SCIPisInfinity(scip, -SCIProwGetLhs(rowlb)));
    2203 assert(SCIPisLE(scip, SCIProwGetRhs(rowlb), (SCIP_Real)consdata->cardval));
    2204
    2205 SCIP_CALL( SCIPaddRow(scip, rowlb, FALSE, cutoff) );
    2206 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, rowlb, NULL) ) );
    2207
    2208 if( solvedinitlp )
    2209 {
    2210 SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
    2211 }
    2212 ++cnt;
    2213 }
    2214
    2215 if( release )
    2216 {
    2217 if( rowlb != NULL )
    2218 {
    2219 SCIP_CALL( SCIPreleaseRow(scip, &rowlb) );
    2220 }
    2221 if( rowub != NULL )
    2222 {
    2223 SCIP_CALL( SCIPreleaseRow(scip, &rowub) );
    2224 }
    2225 }
    2226
    2227 if( *cutoff )
    2228 break;
    2229 }
    2230
    2231 /* store number of generated cuts */
    2232 if( ngen != NULL )
    2233 *ngen = cnt;
    2234
    2235 return SCIP_OKAY;
    2236}
    2237
    2238/** separates cardinality constraints for arbitrary solutions */
    2239static
    2241 SCIP* scip, /**< SCIP pointer */
    2242 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    2243 SCIP_SOL* sol, /**< solution to be separated (or NULL) */
    2244 int nconss, /**< number of constraints */
    2245 SCIP_CONS** conss, /**< cardinality constraints */
    2246 SCIP_RESULT* result /**< result */
    2247 )
    2248{
    2249 SCIP_Bool cutoff;
    2250 int ngen = 0;
    2251
    2252 assert(scip != NULL);
    2253 assert(conshdlr != NULL);
    2254 assert(conss != NULL);
    2255 assert(result != NULL);
    2256
    2257 *result = SCIP_DIDNOTRUN;
    2258
    2259 if( nconss == 0 )
    2260 return SCIP_OKAY;
    2261
    2262 /* only separate cuts if we are not close to terminating */
    2263 if( SCIPisStopped(scip) )
    2264 return SCIP_OKAY;
    2265
    2266 *result = SCIP_DIDNOTFIND;
    2267
    2268 /* separate bound inequalities from cardinality constraints */
    2269 SCIP_CALL( initsepaBoundInequalityFromCardinality(scip, conshdlr, conss, nconss, sol, TRUE, &ngen, &cutoff) );
    2270 if( cutoff )
    2271 {
    2272 *result = SCIP_CUTOFF;
    2273 return SCIP_OKAY;
    2274 }
    2275
    2276 /* evaluate results */
    2277 if( ngen > 0 )
    2278 *result = SCIP_SEPARATED;
    2279 SCIPdebugMsg(scip, "Separated %d bound inequalities.\n", ngen);
    2280
    2281 return SCIP_OKAY;
    2282}
    2283
    2284/* ---------------------------- constraint handler callback methods ----------------------*/
    2285
    2286/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    2287static
    2288SCIP_DECL_CONSHDLRCOPY(conshdlrCopyCardinality)
    2289{ /*lint --e{715}*/
    2290 assert(scip != NULL);
    2291 assert(conshdlr != NULL);
    2292 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2293
    2294 /* call inclusion method of constraint handler */
    2296
    2297 *valid = TRUE;
    2298
    2299 return SCIP_OKAY;
    2300}
    2301
    2302/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
    2303static
    2304SCIP_DECL_CONSFREE(consFreeCardinality)
    2305{
    2306 SCIP_CONSHDLRDATA* conshdlrdata;
    2307
    2308 assert(scip != NULL);
    2309 assert(conshdlr != NULL);
    2310 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2311
    2312 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2313 assert(conshdlrdata != NULL);
    2314
    2315 /* free hash map */
    2316 if( conshdlrdata->varhash != NULL )
    2317 {
    2318 SCIPhashmapFree(&conshdlrdata->varhash);
    2319 }
    2320
    2321 SCIPfreeBlockMemory(scip, &conshdlrdata);
    2322
    2323 return SCIP_OKAY;
    2324}
    2325
    2326/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
    2327static
    2328SCIP_DECL_CONSEXITSOL(consExitsolCardinality)
    2329{ /*lint --e{715}*/
    2330 SCIP_CONSHDLRDATA* conshdlrdata;
    2331 int c;
    2332
    2333 assert(scip != NULL);
    2334 assert(conshdlr != NULL);
    2335 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2336
    2337 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2338 assert(conshdlrdata != NULL);
    2339
    2340 /* check each constraint */
    2341 for( c = 0; c < nconss; ++c )
    2342 {
    2343 SCIP_CONSDATA* consdata;
    2344
    2345 assert(conss != NULL);
    2346 assert(conss[c] != NULL);
    2347 consdata = SCIPconsGetData(conss[c]);
    2348 assert(consdata != NULL);
    2349
    2350 SCIPdebugMsg(scip, "Exiting cardinality constraint <%s>.\n", SCIPconsGetName(conss[c]) );
    2351
    2352 /* free rows */
    2353 if( consdata->rowub != NULL )
    2354 {
    2355 SCIP_CALL( SCIPreleaseRow(scip, &consdata->rowub) );
    2356 }
    2357 if( consdata->rowlb != NULL )
    2358 {
    2359 SCIP_CALL( SCIPreleaseRow(scip, &consdata->rowlb) );
    2360 }
    2361 }
    2362
    2363 /* free hash map */
    2364 if( conshdlrdata->varhash != NULL )
    2365 {
    2366 SCIPhashmapFree(&conshdlrdata->varhash);
    2367 }
    2368
    2369 return SCIP_OKAY;
    2370}
    2371
    2372/** frees specific constraint data */
    2373static
    2374SCIP_DECL_CONSDELETE(consDeleteCardinality)
    2375{ /*lint --e{737, 647}*/
    2376 assert(scip != NULL);
    2377 assert(conshdlr != NULL);
    2378 assert(cons != NULL);
    2379 assert(consdata != NULL);
    2380 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2381
    2382 SCIPdebugMsg(scip, "Deleting cardinality constraint <%s>.\n", SCIPconsGetName(cons) );
    2383
    2384 /* drop events on transformed variables */
    2385 if( SCIPconsIsTransformed(cons) )
    2386 {
    2387 SCIP_CONSHDLRDATA* conshdlrdata;
    2388 int j;
    2389
    2390 /* get constraint handler data */
    2391 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2392 assert(conshdlrdata != NULL);
    2393 assert(conshdlrdata->eventhdlr != NULL);
    2394
    2395 for( j = 0; j < (*consdata)->nvars; ++j )
    2396 {
    2397 SCIP_CALL( dropVarEventCardinality(scip, conshdlrdata->eventhdlr, *consdata, (*consdata)->vars[j],
    2398 (*consdata)->indvars[j], &(*consdata)->eventdatas[j]) );
    2399 assert((*consdata)->eventdatas[j] == NULL);
    2400 }
    2401 }
    2402
    2403 if( (*consdata)->weights != NULL )
    2404 {
    2405 SCIPfreeBlockMemoryArray(scip, &(*consdata)->weights, (*consdata)->maxvars);
    2406 }
    2407 SCIPfreeBlockMemoryArray(scip, &(*consdata)->eventdatas, (*consdata)->maxvars);
    2408 SCIPfreeBlockMemoryArray(scip, &(*consdata)->eventvarscurrent, 4 * (*consdata)->maxvars);/*lint !e647*/
    2409 SCIPfreeBlockMemoryArray(scip, &(*consdata)->eventdatascurrent, 4 * (*consdata)->maxvars);/*lint !e647*/
    2410 SCIPfreeBlockMemoryArray(scip, &(*consdata)->indvars, (*consdata)->maxvars);
    2411 SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, (*consdata)->maxvars);
    2412
    2413 /* free rows */
    2414 if( (*consdata)->rowub != NULL )
    2415 {
    2416 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->rowub) );
    2417 }
    2418 if( (*consdata)->rowlb != NULL )
    2419 {
    2420 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->rowlb) );
    2421 }
    2422 assert((*consdata)->rowub == NULL);
    2423 assert((*consdata)->rowlb == NULL);
    2424
    2425 SCIPfreeBlockMemory(scip, consdata);
    2426
    2427 /* Make sure that the hash for indicator binary variables is freed. If we read a problem and then another problem without
    2428 * solving (transforming) between, then no callback of constraint handlers are called. Thus, we cannot easily free the
    2429 * hash map there. */
    2430 if ( SCIPconshdlrGetNConss(conshdlr) == 0 )
    2431 {
    2432 SCIP_CONSHDLRDATA* conshdlrdata;
    2433
    2434 /* get constraint handler data */
    2435 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2436 assert( conshdlrdata != NULL );
    2437
    2438 if ( conshdlrdata->varhash != NULL )
    2439 SCIPhashmapFree(&conshdlrdata->varhash);
    2440 }
    2441
    2442 return SCIP_OKAY;
    2443}
    2444
    2445/** transforms constraint data into data belonging to the transformed problem */
    2446static
    2447SCIP_DECL_CONSTRANS(consTransCardinality)
    2448{
    2449 SCIP_CONSDATA* consdata;
    2450 SCIP_CONSHDLRDATA* conshdlrdata;
    2451 SCIP_CONSDATA* sourcedata;
    2452 char s[SCIP_MAXSTRLEN];
    2453 int j;
    2454
    2455 assert(scip != NULL);
    2456 assert(conshdlr != NULL);
    2457 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2458 assert(sourcecons != NULL);
    2459 assert(targetcons != NULL);
    2460
    2461 /* get constraint handler data */
    2462 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2463 assert(conshdlrdata != NULL);
    2464 assert(conshdlrdata->eventhdlr != NULL);
    2465
    2466 SCIPdebugMsg(scip, "Transforming cardinality constraint: <%s>.\n", SCIPconsGetName(sourcecons) );
    2467
    2468 /* get data of original constraint */
    2469 sourcedata = SCIPconsGetData(sourcecons);
    2470 assert(sourcedata != NULL);
    2471 assert(sourcedata->nvars > 0);
    2472 assert(sourcedata->nvars <= sourcedata->maxvars);
    2473
    2474 /* create constraint data */
    2475 SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
    2476
    2477 consdata->cons = NULL;
    2478 consdata->nvars = sourcedata->nvars;
    2479 consdata->maxvars = sourcedata->nvars;
    2480 consdata->cardval = sourcedata->cardval;
    2481 consdata->rowub = NULL;
    2482 consdata->rowlb = NULL;
    2483 consdata->eventdatascurrent = NULL;
    2484 consdata->neventdatascurrent = 0;
    2485 consdata->ntreatnonzeros = 0;
    2486 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars, consdata->nvars) );
    2487 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->indvars, consdata->nvars) );
    2488 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdatas, consdata->nvars) );
    2489 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdatascurrent, 4*consdata->nvars) );/*lint !e647*/
    2490 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventvarscurrent, 4*consdata->nvars) );/*lint !e647*/
    2491
    2492 /* if weights were used */
    2493 if( sourcedata->weights != NULL )
    2494 {
    2495 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->weights, sourcedata->weights, consdata->nvars) );
    2496 }
    2497 else
    2498 consdata->weights = NULL;
    2499
    2500 for( j = 0; j < sourcedata->nvars; ++j )
    2501 {
    2502 assert(sourcedata->vars[j] != 0);
    2503 assert(sourcedata->indvars[j] != 0);
    2504 SCIP_CALL( SCIPgetTransformedVar(scip, sourcedata->vars[j], &(consdata->vars[j])) );
    2505 SCIP_CALL( SCIPgetTransformedVar(scip, sourcedata->indvars[j], &(consdata->indvars[j])) );
    2506
    2507 /* if variable is fixed to be nonzero */
    2508 if( SCIPvarGetLbLocal(consdata->indvars[j]) > 0.5 )
    2509 ++(consdata->ntreatnonzeros);
    2510 }
    2511
    2512 /* create transformed constraint with the same flags */
    2513 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "t_%s", SCIPconsGetName(sourcecons));
    2514 SCIP_CALL( SCIPcreateCons(scip, targetcons, s, conshdlr, consdata,
    2515 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
    2516 SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons),
    2517 SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
    2518 SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
    2519 SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
    2520
    2521 consdata->cons = *targetcons;
    2522 assert(consdata->cons != NULL);
    2523
    2524 /* catch bound change events on variable */
    2525 for( j = 0; j < consdata->nvars; ++j )
    2526 {
    2527 SCIP_CALL( catchVarEventCardinality(scip, conshdlrdata->eventhdlr, consdata,
    2528 consdata->vars[j], consdata->indvars[j], j, &consdata->eventdatas[j]) );
    2529 assert(consdata->eventdatas[j] != NULL);
    2530 }
    2531
    2532#ifdef SCIP_DEBUG
    2533 if( SCIPisGT(scip, (SCIP_Real)consdata->ntreatnonzeros, consdata->cardval) )
    2534 {
    2535 SCIPdebugMsg(scip, "constraint <%s> has %d variables fixed to be nonzero, allthough the constraint allows \
    2536 only %d nonzero variables\n", SCIPconsGetName(*targetcons), consdata->ntreatnonzeros, consdata->cardval);
    2537 }
    2538#endif
    2539
    2540 return SCIP_OKAY;
    2541}
    2542
    2543/** presolving method of constraint handler */
    2544static
    2545SCIP_DECL_CONSPRESOL(consPresolCardinality)
    2546{ /*lint --e{715}*/
    2547 SCIPdebug( int oldnfixedvars; )
    2548 SCIPdebug( int oldndelconss; )
    2549 SCIPdebug( int oldnupgdconss; )
    2550 int nremovedvars;
    2551 SCIP_EVENTHDLR* eventhdlr;
    2552 int c;
    2553
    2554 assert(scip != NULL);
    2555 assert(conshdlr != NULL);
    2556 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2557 assert(result != NULL);
    2558
    2559 SCIPdebugMsg(scip, "Presolving cardinality constraints.\n");
    2560
    2561 *result = SCIP_DIDNOTRUN;
    2562 SCIPdebug( oldnfixedvars = *nfixedvars; )
    2563 SCIPdebug( oldndelconss = *ndelconss; )
    2564 SCIPdebug( oldnupgdconss = *nupgdconss; )
    2565 nremovedvars = 0;
    2566
    2567 /* only run if success if possible */
    2568 if( nrounds == 0 || nnewfixedvars > 0 || nnewaggrvars > 0 )
    2569 {
    2570 /* get constraint handler data */
    2571 assert(SCIPconshdlrGetData(conshdlr) != NULL);
    2572 eventhdlr = SCIPconshdlrGetData(conshdlr)->eventhdlr;
    2573 assert(eventhdlr != NULL);
    2574
    2575 *result = SCIP_DIDNOTFIND;
    2576
    2577 /* check each constraint */
    2578 for( c = 0; c < nconss; ++c )
    2579 {
    2580 SCIP_CONSDATA* consdata;
    2581 SCIP_CONS* cons;
    2582 SCIP_Bool cutoff;
    2583 SCIP_Bool success;
    2584
    2585 assert(conss != NULL);
    2586 assert(conss[c] != NULL);
    2587 cons = conss[c];
    2588 consdata = SCIPconsGetData(cons);
    2589
    2590 assert(consdata != NULL);
    2591 assert(consdata->nvars >= 0);
    2592 assert(consdata->nvars <= consdata->maxvars);
    2593 assert(!SCIPconsIsModifiable(cons));
    2594
    2595 /* perform one presolving round */
    2596 SCIP_CALL( presolRoundCardinality(scip, cons, consdata, eventhdlr, &cutoff, &success,
    2597 ndelconss, nupgdconss, nfixedvars, &nremovedvars) );
    2598
    2599 if( cutoff )
    2600 {
    2601 SCIPdebugMsg(scip, "presolving detected cutoff.\n");
    2602 *result = SCIP_CUTOFF;
    2603 return SCIP_OKAY;
    2604 }
    2605
    2606 if( success )
    2607 *result = SCIP_SUCCESS;
    2608 }
    2609 }
    2610 (*nchgcoefs) += nremovedvars;
    2611
    2612 SCIPdebug( SCIPdebugMsg(scip, "presolving fixed %d variables, removed %d variables, deleted %d constraints, "
    2613 "and upgraded %d constraints.\n", *nfixedvars - oldnfixedvars, nremovedvars, *ndelconss - oldndelconss,
    2614 *nupgdconss - oldnupgdconss); )
    2615
    2616 return SCIP_OKAY;
    2617}
    2618
    2619/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
    2620static
    2621SCIP_DECL_CONSINITLP(consInitlpCardinality)
    2622{ /*lint --e{715}*/
    2623 SCIP_Bool cutoff;
    2624
    2625 assert(scip != NULL);
    2626 assert(conshdlr != NULL);
    2627
    2628 /* checking for initial rows for cardinality constraints */
    2629 SCIP_CALL( initsepaBoundInequalityFromCardinality(scip, conshdlr, conss, nconss, NULL, FALSE, NULL, &cutoff) );
    2630 assert(!cutoff);
    2631
    2632 return SCIP_OKAY;
    2633}
    2634
    2635/** separation method of constraint handler for LP solutions */
    2636static
    2637SCIP_DECL_CONSSEPALP(consSepalpCardinality)
    2638{ /*lint --e{715}*/
    2639 assert(scip != NULL);
    2640 assert(conshdlr != NULL);
    2641 assert(conss != NULL);
    2642 assert(result != NULL);
    2643
    2644 SCIP_CALL( separateCardinality(scip, conshdlr, NULL, nconss, conss, result) );
    2645
    2646 return SCIP_OKAY;
    2647}
    2648
    2649/** separation method of constraint handler for arbitrary primal solutions */
    2650static
    2651SCIP_DECL_CONSSEPASOL(consSepasolCardinality)
    2652{ /*lint --e{715}*/
    2653 assert(scip != NULL);
    2654 assert(conshdlr != NULL);
    2655 assert(conss != NULL);
    2656 assert(result != NULL);
    2657
    2658 SCIP_CALL( separateCardinality(scip, conshdlr, sol, nconss, conss, result) );
    2659
    2660 return SCIP_OKAY;
    2661}
    2662
    2663/** constraint enforcing method of constraint handler for LP solutions */
    2664static
    2665SCIP_DECL_CONSENFOLP(consEnfolpCardinality)
    2666{ /*lint --e{715}*/
    2667 assert(scip != NULL);
    2668 assert(conshdlr != NULL);
    2669 assert(conss != NULL);
    2670 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2671 assert(result != NULL);
    2672
    2673 SCIP_CALL( enforceCardinality(scip, conshdlr, NULL, nconss, conss, result) );
    2674
    2675 return SCIP_OKAY;
    2676}
    2677
    2678/** constraint enforcing method of constraint handler for relaxation solutions */
    2679static
    2680SCIP_DECL_CONSENFORELAX(consEnforelaxCardinality)
    2681{ /*lint --e{715}*/
    2682 assert( scip != NULL );
    2683 assert( conshdlr != NULL );
    2684 assert( conss != NULL );
    2685 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    2686 assert( result != NULL );
    2687
    2688 SCIP_CALL( enforceCardinality(scip, conshdlr, sol, nconss, conss, result) );
    2689
    2690 return SCIP_OKAY;
    2691}
    2692
    2693/** constraint enforcing method of constraint handler for pseudo solutions */
    2694static
    2695SCIP_DECL_CONSENFOPS(consEnfopsCardinality)
    2696{ /*lint --e{715}*/
    2697 assert(scip != NULL);
    2698 assert(conshdlr != NULL);
    2699 assert(conss != NULL);
    2700 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2701 assert(result != NULL);
    2702
    2703 SCIP_CALL( enforceCardinality(scip, conshdlr, NULL, nconss, conss, result) );
    2704
    2705 return SCIP_OKAY;
    2706}
    2707
    2708/** feasibility check method of constraint handler for integral solutions
    2709 *
    2710 * We simply check whether more variables than allowed are nonzero in the given solution.
    2711 */
    2712static
    2713SCIP_DECL_CONSCHECK(consCheckCardinality)
    2714{ /*lint --e{715}*/
    2715 int c;
    2716
    2717 assert(scip != NULL);
    2718 assert(conshdlr != NULL);
    2719 assert(conss != NULL);
    2720 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2721 assert(result != NULL);
    2722
    2723 /* check each constraint */
    2724 for( c = 0; c < nconss; ++c )
    2725 {
    2726 SCIP_CONSDATA* consdata;
    2727 int cardval;
    2728 int j;
    2729 int cnt;
    2730
    2731 cnt = 0;
    2732 assert(conss[c] != NULL);
    2733 consdata = SCIPconsGetData(conss[c]);
    2734 assert(consdata != NULL);
    2735 cardval = consdata->cardval;
    2736 SCIPdebugMsg(scip, "Checking cardinality constraint <%s>.\n", SCIPconsGetName(conss[c]));
    2737
    2738 /* check all variables */
    2739 for( j = 0; j < consdata->nvars; ++j )
    2740 {
    2741 /* if variable is nonzero */
    2742 if( !SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, consdata->vars[j])) )
    2743 {
    2744 ++cnt;
    2745
    2746 /* if more variables than allowed are nonzero */
    2747 if( cnt > cardval )
    2748 {
    2749 SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
    2750 *result = SCIP_INFEASIBLE;
    2751
    2752 if( printreason )
    2753 {
    2754 int l;
    2755
    2756 SCIP_CALL( SCIPprintCons(scip, conss[c], NULL) );
    2757 SCIPinfoMessage(scip, NULL, ";\nviolation: ");
    2758
    2759 for( l = 0; l < consdata->nvars; ++l )
    2760 {
    2761 /* if variable is nonzero */
    2762 if( !SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, consdata->vars[l])) )
    2763 {
    2764 SCIPinfoMessage(scip, NULL, "<%s> = %.15g ",
    2765 SCIPvarGetName(consdata->vars[l]), SCIPgetSolVal(scip, sol, consdata->vars[l]));
    2766 }
    2767 }
    2768 SCIPinfoMessage(scip, NULL, "\n");
    2769 }
    2770 if( sol != NULL )
    2771 SCIPupdateSolConsViolation(scip, sol, 1.0, 1.0);
    2772 return SCIP_OKAY;
    2773 }
    2774 }
    2775 }
    2776 }
    2777 *result = SCIP_FEASIBLE;
    2778
    2779 return SCIP_OKAY;
    2780}
    2781
    2782/** domain propagation method of constraint handler */
    2783static
    2784SCIP_DECL_CONSPROP(consPropCardinality)
    2785{ /*lint --e{715}*/
    2786 int nchgdomain = 0;
    2787 int c;
    2788
    2789 assert(scip != NULL);
    2790 assert(conshdlr != NULL);
    2791 assert(conss != NULL);
    2792 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2793 assert(result != NULL);
    2794 *result = SCIP_DIDNOTRUN;
    2795
    2796 assert(SCIPisTransformed(scip));
    2797
    2798 /* check each constraint */
    2799 for( c = 0; c < nconss; ++c )
    2800 {
    2801 SCIP_CONS* cons;
    2802 SCIP_CONSDATA* consdata;
    2803 SCIP_Bool cutoff;
    2804
    2805 *result = SCIP_DIDNOTFIND;
    2806 assert(conss[c] != NULL);
    2807 cons = conss[c];
    2808 consdata = SCIPconsGetData(cons);
    2809 assert(consdata != NULL);
    2810 SCIPdebugMsg(scip, "Propagating cardinality constraint <%s>.\n", SCIPconsGetName(cons) );
    2811
    2812 *result = SCIP_DIDNOTFIND;
    2813 SCIP_CALL( propCardinality(scip, cons, consdata, &cutoff, &nchgdomain) );
    2814 if( cutoff )
    2815 {
    2816 *result = SCIP_CUTOFF;
    2817 return SCIP_OKAY;
    2818 }
    2819 }
    2820 SCIPdebugMsg(scip, "Propagated %d domains.\n", nchgdomain);
    2821 if( nchgdomain > 0 )
    2822 *result = SCIP_REDUCEDDOM;
    2823
    2824 return SCIP_OKAY;
    2825}
    2826
    2827/** variable rounding lock method of constraint handler
    2828 *
    2829 * Let lb and ub be the lower and upper bounds of a
    2830 * variable. Preprocessing usually makes sure that lb <= 0 <= ub.
    2831 *
    2832 * - If lb < 0 then rounding down may violate the constraint.
    2833 * - If ub > 0 then rounding up may violated the constraint.
    2834 * - If lb > 0 or ub < 0 then the rhs of the constraint can be updated and the variable
    2835 * can be removed from the constraint. Thus, we do not have to deal with it here.
    2836 * - If lb == 0 then rounding down does not violate the constraint.
    2837 * - If ub == 0 then rounding up does not violate the constraint.
    2838 */
    2839static
    2840SCIP_DECL_CONSLOCK(consLockCardinality)
    2841{
    2842 SCIP_CONSDATA* consdata;
    2843 SCIP_VAR** vars;
    2844 int nvars;
    2845 SCIP_VAR** indvars;
    2846 int j;
    2847
    2848 assert(scip != NULL);
    2849 assert(conshdlr != NULL);
    2850 assert(cons != NULL);
    2851 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2852 assert(locktype == SCIP_LOCKTYPE_MODEL);
    2853
    2854 consdata = SCIPconsGetData(cons);
    2855 assert(consdata != NULL);
    2856
    2857 SCIPdebugMsg(scip, "Locking constraint <%s>.\n", SCIPconsGetName(cons));
    2858
    2859 vars = consdata->vars;
    2860 indvars = consdata->indvars;
    2861 nvars = consdata->nvars;
    2862 assert(vars != NULL);
    2863
    2864 for( j = 0; j < nvars; ++j )
    2865 {
    2866 SCIP_VAR* var;
    2867 SCIP_VAR* indvar;
    2868 var = vars[j];
    2869 indvar = indvars[j];
    2870
    2871 /* if lower bound is negative, rounding down may violate constraint */
    2873 {
    2874 SCIP_CALL( SCIPaddVarLocksType(scip, var, locktype, nlockspos, nlocksneg) );
    2875 }
    2876
    2877 /* additionally: if upper bound is positive, rounding up may violate constraint */
    2879 {
    2880 SCIP_CALL( SCIPaddVarLocksType(scip, var, locktype, nlocksneg, nlockspos) );
    2881 }
    2882
    2883 /* add lock on indicator variable in both directions; @todo write constraint handler to handle down locks */
    2884 SCIP_CALL( SCIPaddVarLocksType(scip, indvar, locktype, nlockspos + nlocksneg, nlockspos + nlocksneg) );
    2885 }
    2886
    2887 return SCIP_OKAY;
    2888}
    2889
    2890/** constraint display method of constraint handler */
    2891static
    2892SCIP_DECL_CONSPRINT(consPrintCardinality)
    2893{ /*lint --e{715}*/
    2894 SCIP_CONSDATA* consdata;
    2895 int j;
    2896
    2897 assert(scip != NULL);
    2898 assert(conshdlr != NULL);
    2899 assert(cons != NULL);
    2900 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    2901
    2902 consdata = SCIPconsGetData(cons);
    2903 assert(consdata != NULL);
    2904
    2905 for( j = 0; j < consdata->nvars; ++j )
    2906 {
    2907 if( j > 0 )
    2908 SCIPinfoMessage(scip, file, ", ");
    2909 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[j], FALSE) );
    2910
    2911 if( consdata->indvars[j] != NULL )
    2912 {
    2913 SCIPinfoMessage(scip, file, " [");
    2914 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->indvars[j], FALSE) );
    2915 SCIPinfoMessage(scip, file, "]");
    2916 }
    2917
    2918 if( consdata->weights == NULL )
    2919 SCIPinfoMessage(scip, file, " (%d)", j+1);
    2920 else
    2921 SCIPinfoMessage(scip, file, " (%3.2f)", consdata->weights[j]);
    2922 }
    2923 SCIPinfoMessage(scip, file, " <= %d", consdata->cardval);
    2924
    2925 return SCIP_OKAY;
    2926}
    2927
    2928/** constraint copying method of constraint handler */
    2929static
    2930SCIP_DECL_CONSCOPY(consCopyCardinality)
    2931{ /*lint --e{715}*/
    2932 SCIP_CONSDATA* sourceconsdata;
    2933 SCIP_VAR** sourcevars;
    2934 SCIP_VAR** targetvars;
    2935 SCIP_VAR** sourceindvars;
    2936 SCIP_VAR** targetindvars;
    2937 SCIP_Real* sourceweights;
    2938 SCIP_Real* targetweights;
    2939 const char* consname;
    2940 int nvars;
    2941 int v;
    2942
    2943 assert(scip != NULL);
    2944 assert(sourcescip != NULL);
    2945 assert(sourcecons != NULL);
    2946 assert(SCIPisTransformed(sourcescip));
    2947 assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(sourcecons)), CONSHDLR_NAME) == 0);
    2948
    2949 *valid = TRUE;
    2950
    2951 if( name != NULL )
    2952 consname = name;
    2953 else
    2954 consname = SCIPconsGetName(sourcecons);
    2955
    2956 SCIPdebugMsg(scip, "Copying cardinality constraint <%s> ...\n", consname);
    2957
    2958 sourceconsdata = SCIPconsGetData(sourcecons);
    2959 assert(sourceconsdata != NULL);
    2960
    2961 /* get variables and weights of the source constraint */
    2962 nvars = sourceconsdata->nvars;
    2963
    2964 if( nvars == 0 )
    2965 return SCIP_OKAY;
    2966
    2967 sourcevars = sourceconsdata->vars;
    2968 assert(sourcevars != NULL);
    2969 sourceindvars = sourceconsdata->indvars;
    2970 assert(sourceindvars != NULL);
    2971 sourceweights = sourceconsdata->weights;
    2972 assert(sourceweights != NULL);
    2973
    2974 /* duplicate variable array */
    2975 SCIP_CALL( SCIPallocBufferArray(sourcescip, &targetvars, nvars) );
    2976 SCIP_CALL( SCIPallocBufferArray(sourcescip, &targetindvars, nvars) );
    2977 SCIP_CALL( SCIPduplicateBufferArray(sourcescip, &targetweights, sourceweights, nvars) );
    2978
    2979 /* get copied variables in target SCIP */
    2980 for( v = 0; v < nvars && *valid; ++v )
    2981 {
    2982 assert(sourcevars[v] != NULL);
    2983 assert(sourceindvars[v] != NULL);
    2984
    2985 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &(targetvars[v]), varmap, consmap, global, valid) );
    2986 if( *valid )
    2987 {
    2988 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourceindvars[v], &(targetindvars[v]), varmap, consmap, global, valid) );
    2989 }
    2990 }
    2991
    2992 /* only create the target constraint, if all variables could be copied */
    2993 if( *valid )
    2994 {
    2995 SCIP_CALL( SCIPcreateConsCardinality(scip, cons, consname, nvars, targetvars, sourceconsdata->cardval, targetindvars,
    2996 targetweights, initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
    2997 }
    2998
    2999 /* free buffer array */
    3000 SCIPfreeBufferArray(sourcescip, &targetweights);
    3001 SCIPfreeBufferArray(sourcescip, &targetindvars);
    3002 SCIPfreeBufferArray(sourcescip, &targetvars);
    3003
    3004 return SCIP_OKAY;
    3005}
    3006
    3007/** constraint parsing method of constraint handler */
    3008static
    3009SCIP_DECL_CONSPARSE(consParseCardinality)
    3010{ /*lint --e{715}*/
    3011 SCIP_VAR* var;
    3012 SCIP_VAR* indvar;
    3013 SCIP_Real weight;
    3014 int cardval;
    3015 const char* s;
    3016 char* t;
    3017
    3018 assert(scip != NULL);
    3019 assert(conshdlr != NULL);
    3020 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    3021 assert(cons != NULL);
    3022 assert(success != NULL);
    3023
    3024 *success = TRUE;
    3025 s = str;
    3026
    3027 /* create empty cardinality constraint */
    3028 SCIP_CALL( SCIPcreateConsCardinality(scip, cons, name, 0, NULL, 0, NULL, NULL, initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
    3029
    3030 /* loop through string */
    3031 while( *s != '\0' )
    3032 {
    3033 /* parse variable name */
    3034 SCIP_CALL( SCIPparseVarName(scip, s, &var, &t) );
    3035
    3036 if( var == NULL )
    3037 {
    3038 t = strchr(t, '<');
    3039
    3040 if( t != NULL )
    3041 s = t;
    3042
    3043 break;
    3044 }
    3045
    3046 /* skip until beginning of indicator variable or weight */
    3047 while( *t != '\0' && *t != '(' && *t != '[' )
    3048 ++t;
    3049
    3050 if( *t == '\0' )
    3051 {
    3052 SCIPerrorMessage("Syntax error: expected opening '[' or '(' at input: %s\n", s);
    3053 *success = FALSE;
    3054 break;
    3055 }
    3056
    3057 s = t;
    3058
    3059 /* parse indicator variable */
    3060 indvar = NULL;
    3061 if( *s == '[' )
    3062 {
    3063 ++s;
    3064 SCIP_CALL( SCIPparseVarName(scip, s, &indvar, &t) );
    3065
    3066 if( indvar == NULL )
    3067 {
    3068 SCIPerrorMessage("Syntax error: expected indicator variable name at input: %s\n", s);
    3069 *success = FALSE;
    3070 break;
    3071 }
    3072 s = t;
    3073
    3074 /* skip ']' */
    3075 if( *s != ']' )
    3076 {
    3077 SCIPerrorMessage("Syntax error: expected closing ']' at input: %s\n", s);
    3078 *success = FALSE;
    3079 break;
    3080 }
    3081 ++s;
    3082
    3083 /* skip white space */
    3084 SCIP_CALL( SCIPskipSpace((char**)&s) );
    3085 }
    3086
    3087 /* skip '(' */
    3088 if( *s != '(' )
    3089 {
    3090 SCIPerrorMessage("Syntax error: expected opening '(' at input: %s\n", s);
    3091 *success = FALSE;
    3092 break;
    3093 }
    3094 ++s;
    3095
    3096 /* find weight */
    3097 weight = strtod(s, &t);
    3098
    3099 if( t == NULL )
    3100 {
    3101 SCIPerrorMessage("Syntax error during parsing of the weight: %s\n", s);
    3102 *success = FALSE;
    3103 break;
    3104 }
    3105
    3106 s = t;
    3107
    3108 /* skip until ending of weight */
    3109 t = strchr(t, ')');
    3110
    3111 if( t == NULL )
    3112 {
    3113 SCIPerrorMessage("Syntax error: expected closing ')' at input %s\n", s);
    3114 *success = FALSE;
    3115 break;
    3116 }
    3117
    3118 s = t;
    3119
    3120 /* skip ')' */
    3121 ++s;
    3122
    3123 /* skip white space */
    3124 SCIP_CALL( SCIPskipSpace((char**)&s) );
    3125
    3126 /* skip ',' */
    3127 if( *s == ',' )
    3128 ++s;
    3129
    3130 /* add variable */
    3131 SCIP_CALL( SCIPaddVarCardinality(scip, *cons, var, indvar, weight) );
    3132 }
    3133
    3134 /* check if there is a '<=' */
    3135 if( *success && *s == '<' && *(s+1) == '=' )
    3136 {
    3137 s = s + 2;
    3138
    3139 /* skip white space */
    3140 SCIP_CALL( SCIPskipSpace((char**)&s) );
    3141
    3142 cardval = (int)strtod(s, &t);
    3143
    3144 if( t == NULL )
    3145 {
    3146 SCIPerrorMessage("Syntax error during parsing of the cardinality restriction value: %s\n", s);
    3147 *success = FALSE;
    3148 }
    3149 else
    3150 SCIP_CALL( SCIPchgCardvalCardinality(scip, *cons, cardval) );
    3151 }
    3152
    3153 if( !*success )
    3154 SCIP_CALL( SCIPreleaseCons(scip, cons) );
    3155
    3156 return SCIP_OKAY;
    3157}
    3158
    3159/** constraint method of constraint handler which returns the variables (if possible) */
    3160static
    3161SCIP_DECL_CONSGETVARS(consGetVarsCardinality)
    3162{ /*lint --e{715}*/
    3163 SCIP_CONSDATA* consdata;
    3164
    3165 consdata = SCIPconsGetData(cons);
    3166 assert(consdata != NULL);
    3167
    3168 if( varssize < 2 * consdata->nvars )
    3169 (*success) = FALSE;
    3170 else
    3171 {
    3172 int v;
    3173 int cnt = 0;
    3174
    3175 assert(vars != NULL);
    3176
    3177 for (v = 0; v < consdata->nvars; ++v)
    3178 {
    3179 vars[cnt++] = consdata->vars[v];
    3180 vars[cnt++] = consdata->indvars[v];
    3181 }
    3182 (*success) = TRUE;
    3183 }
    3184
    3185 return SCIP_OKAY;
    3186}
    3187
    3188/** constraint method of constraint handler which returns the number of variables (if possible) */
    3189static
    3190SCIP_DECL_CONSGETNVARS(consGetNVarsCardinality)
    3191{ /*lint --e{715}*/
    3192 SCIP_CONSDATA* consdata;
    3193
    3194 consdata = SCIPconsGetData(cons);
    3195 assert(consdata != NULL);
    3196
    3197 (*nvars) = 2 * consdata->nvars;
    3198 (*success) = TRUE;
    3199
    3200 return SCIP_OKAY;
    3201}
    3202
    3203/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
    3204static
    3205SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphCardinality)
    3206{ /*lint --e{715}*/
    3207 SCIP_CONSDATA* consdata;
    3208 SCIP_VAR** vars;
    3209 SCIP_Real* vals;
    3210 SCIP_Real constant;
    3211 SCIP_Real rhs;
    3212 int consnodeidx;
    3213 int pairnodeidx;
    3214 int nodeidx;
    3215 int nconsvars;
    3216 int nlocvars;
    3217 int nvars;
    3218 int i;
    3219
    3220 consdata = SCIPconsGetData(cons);
    3221 assert(consdata != NULL);
    3222 assert(graph != NULL);
    3223
    3224 nconsvars = consdata->nvars;
    3225 rhs = (SCIP_Real) consdata->cardval;
    3226
    3227 /* add node for constraint */
    3228 SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, -SCIPinfinity(scip), rhs, &consnodeidx) );
    3229
    3230 /* create nodes and edges for each variable */
    3231 nvars = SCIPgetNVars(scip);
    3232 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    3233 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
    3234
    3235 for( i = 0; i < nconsvars; ++i )
    3236 {
    3237 /* connect each variable and its indicator variable with an intermediate node, which is connected with consnode */
    3238 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_CARD_TUPLE , &pairnodeidx) );
    3239
    3240 /* connect variable with pair node*/
    3241 vars[0] = consdata->vars[i];
    3242 vals[0] = 1.0;
    3243 nlocvars = 1;
    3244 constant = 0.0;
    3245
    3247 &nlocvars, &constant, SCIPisTransformed(scip)) );
    3248
    3249 /* check whether variable is (multi-)aggregated or negated */
    3250 if( nlocvars > 1 || !SCIPisEQ(scip, vals[0], 1.0) || !SCIPisZero(scip, constant) )
    3251 {
    3252 /* encode aggregation by a sum-expression */
    3253 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_SUM, &nodeidx) ); /*lint !e641*/
    3254
    3255 /* we do not need to take weights of variables into account;
    3256 * they are only used to sort variables within the constraint */
    3257 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, pairnodeidx, nodeidx, FALSE, 0.0) );
    3258
    3259 /* add nodes and edges for variables in aggregation */
    3260 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, nodeidx, vars, vals, nlocvars, constant) );
    3261 }
    3262 else if( nlocvars == 1 )
    3263 {
    3264 nodeidx = SCIPgetSymgraphVarnodeidx(scip, graph, vars[0]);
    3265
    3266 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, pairnodeidx, nodeidx, FALSE, 0.0) );
    3267 }
    3268
    3269 /* connect indicator variable with pair node*/
    3270 vars[0] = consdata->indvars[i];
    3271 vals[0] = 1.0;
    3272 nlocvars = 1;
    3273 constant = 0.0;
    3274
    3276 &nlocvars, &constant, SCIPisTransformed(scip)) );
    3277
    3278 /* check whether variable is (multi-)aggregated or negated */
    3279 if( nlocvars > 1 || !SCIPisEQ(scip, vals[0], 1.0) || !SCIPisZero(scip, constant) )
    3280 {
    3281 /* encode aggregation by a sum-expression */
    3282 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_SUM, &nodeidx) ); /*lint !e641*/
    3283
    3284 /* we do not need to take weights of variables into account;
    3285 * they are only used to sort variables within the constraint */
    3286 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, pairnodeidx, nodeidx, FALSE, 0.0) );
    3287
    3288 /* add nodes and edges for variables in aggregation */
    3289 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, nodeidx, vars, vals, nlocvars, constant) );
    3290 }
    3291 else if( nlocvars == 1 )
    3292 {
    3293 nodeidx = SCIPgetSymgraphVarnodeidx(scip, graph, vars[0]);
    3294
    3295 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, pairnodeidx, nodeidx, FALSE, 0.0) );
    3296 }
    3297 }
    3298
    3299 SCIPfreeBufferArray(scip, &vals);
    3300 SCIPfreeBufferArray(scip, &vars);
    3301
    3302 assert(success != NULL);
    3303 *success = TRUE;
    3304
    3305 return SCIP_OKAY;
    3306}
    3307
    3308/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
    3309static
    3310SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphCardinality)
    3311{ /*lint --e{715}*/
    3312 SCIP_CONSDATA* consdata;
    3313 SCIP_VAR** vars;
    3314 SCIP_Real* vals;
    3315 SCIP_Real constant;
    3316 SCIP_Real rhs;
    3317 int consnodeidx;
    3318 int pairnodeidx;
    3319 int nodeidx;
    3320 int nconsvars;
    3321 int nlocvars;
    3322 int nvars;
    3323 int i;
    3324
    3325 consdata = SCIPconsGetData(cons);
    3326 assert(consdata != NULL);
    3327 assert(graph != NULL);
    3328
    3329 nconsvars = consdata->nvars;
    3330 rhs = (SCIP_Real) consdata->cardval;
    3331
    3332 /* add node for constraint */
    3333 SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, -SCIPinfinity(scip), rhs, &consnodeidx) );
    3334
    3335 /* create nodes and edges for each variable */
    3336 nvars = SCIPgetNVars(scip);
    3337 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    3338 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
    3339
    3340 for( i = 0; i < nconsvars; ++i )
    3341 {
    3342 /* connect each variable and its indicator variable with an intermediate node, which is connected with consnode */
    3343 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_CARD_TUPLE , &pairnodeidx) );
    3344
    3345 vars[0] = consdata->vars[i];
    3346 vals[0] = 1.0;
    3347 nlocvars = 1;
    3348 constant = 0.0;
    3349
    3350 /* use SYM_SYMTYPE_PERM here to NOT center variable domains at 0, as the latter might not preserve
    3351 * cardinality constraints */
    3353 &nlocvars, &constant, SCIPisTransformed(scip)) );
    3354
    3355 /* check whether variable is (multi-) aggregated or negated */
    3356 if( nlocvars > 1 || !SCIPisEQ(scip, vals[0], 1.0) || !SCIPisZero(scip, constant) )
    3357 {
    3358 int sumnodeidx;
    3359 int j;
    3360
    3361 /* encode aggregation by a sum-expression */
    3362 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_SUM, &sumnodeidx) ); /*lint !e641*/
    3363
    3364 /* we do not need to take weights of variables into account;
    3365 * they are only used to sort variables within the constraint */
    3366 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, pairnodeidx, sumnodeidx, FALSE, 0.0) );
    3367
    3368 /* add nodes and edges for variables in aggregation, do not add edges to negated variables
    3369 * since this might not necessarily be a symmetry of the cardinality constraint; therefore,
    3370 * do not use SCIPaddSymgraphVarAggregation() */
    3371 for( j = 0; j < nlocvars; ++j )
    3372 {
    3373 nodeidx = SCIPgetSymgraphVarnodeidx(scip, graph, vars[j]);
    3374 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, sumnodeidx, nodeidx, TRUE, vals[j]) );
    3375 }
    3376
    3377 /* possibly add node for constant */
    3378 if( ! SCIPisZero(scip, constant) )
    3379 {
    3380 SCIP_CALL( SCIPaddSymgraphValnode(scip, graph, constant, &nodeidx) );
    3381
    3382 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, sumnodeidx, nodeidx, FALSE, 0.0) );
    3383 }
    3384 }
    3385 else if( nlocvars == 1 )
    3386 {
    3387 SCIP_Bool allownegation = FALSE;
    3388
    3389 /* a negation is allowed if it is centered around 0 */
    3392 || SCIPisZero(scip, (SCIPvarGetLbGlobal(vars[0]) + SCIPvarGetUbGlobal(vars[0]))/2)) )
    3393 allownegation = TRUE;
    3394
    3395 nodeidx = SCIPgetSymgraphVarnodeidx(scip, graph, vars[0]);
    3396 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, pairnodeidx, nodeidx, TRUE, 1.0) );
    3397
    3398 nodeidx = SCIPgetSymgraphNegatedVarnodeidx(scip, graph, vars[0]);
    3399 if( allownegation )
    3400 {
    3401 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, pairnodeidx, nodeidx, TRUE, 1.0) );
    3402 }
    3403 else
    3404 {
    3405 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, pairnodeidx, nodeidx, FALSE, 0.0) );
    3406 }
    3407 }
    3408
    3409 /* connect indicator variable with pair node, do not add edges to negated variables since negating
    3410 * might not preserve the cardinality requirement
    3411 */
    3412 vars[0] = consdata->indvars[i];
    3413 vals[0] = 1.0;
    3414 nlocvars = 1;
    3415 constant = 0.0;
    3416
    3418 &nlocvars, &constant, SCIPisTransformed(scip)) );
    3419
    3420 /* check whether variable is (multi-)aggregated or negated */
    3421 if( nlocvars > 1 || !SCIPisEQ(scip, vals[0], 1.0) || !SCIPisZero(scip, constant) )
    3422 {
    3423 /* encode aggregation by a sum-expression */
    3424 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_SUM, &nodeidx) ); /*lint !e641*/
    3425
    3426 /* we do not need to take weights of variables into account;
    3427 * they are only used to sort variables within the constraint */
    3428 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, pairnodeidx, nodeidx, FALSE, 0.0) );
    3429
    3430 /* add nodes and edges for variables in aggregation */
    3431 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, nodeidx, vars, vals, nlocvars, constant) );
    3432 }
    3433 else if( nlocvars == 1 )
    3434 {
    3435 nodeidx = SCIPgetSymgraphVarnodeidx(scip, graph, vars[0]);
    3436
    3437 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, pairnodeidx, nodeidx, FALSE, 0.0) );
    3438 }
    3439 }
    3440
    3441 SCIPfreeBufferArray(scip, &vals);
    3442 SCIPfreeBufferArray(scip, &vars);
    3443
    3444 assert(success != NULL);
    3445 *success = TRUE;
    3446
    3447 return SCIP_OKAY;
    3448}
    3449
    3450/* ---------------- Callback methods of event handler ---------------- */
    3451
    3452/* exec the event handler
    3453 *
    3454 * update the number of variables fixed to be nonzero
    3455 * update the bound constraints
    3456 */
    3457static
    3458SCIP_DECL_EVENTEXEC(eventExecCardinality)
    3459{
    3460 SCIP_EVENTTYPE eventtype;
    3461 SCIP_CONSDATA* consdata;
    3462 SCIP_Real oldbound;
    3463 SCIP_Real newbound;
    3464 SCIP_VAR* var;
    3465
    3466 assert(eventhdlr != NULL);
    3467 assert(eventdata != NULL);
    3468 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
    3469 assert(event != NULL);
    3470
    3471 consdata = eventdata->consdata;
    3472 assert(consdata != NULL);
    3473 assert(0 <= consdata->ntreatnonzeros && consdata->ntreatnonzeros <= consdata->nvars);
    3474 assert(consdata->eventdatascurrent != NULL);
    3475 assert(consdata->eventvarscurrent != NULL);
    3476
    3477 var = SCIPeventGetVar(event);
    3478 assert(var != NULL);
    3479 oldbound = SCIPeventGetOldbound(event);
    3480 newbound = SCIPeventGetNewbound(event);
    3481 eventtype = SCIPeventGetType(event);
    3482
    3483#ifdef SCIP_DEBUG
    3484 if( ( eventdata->varmarked && var == eventdata->var) || ( eventdata->indvarmarked && var == eventdata->indvar) )
    3485 {
    3486 int i;
    3487
    3488 for( i = 0; i < consdata->neventdatascurrent; ++i )
    3489 {
    3490 if( var == consdata->eventvarscurrent[i] )
    3491 {
    3492 break;
    3493 }
    3494 }
    3495 assert(i < consdata->neventdatascurrent);
    3496 }
    3497#endif
    3498
    3499 if( eventtype & SCIP_EVENTTYPE_GBDCHANGED )
    3500 {
    3501 if( eventtype == SCIP_EVENTTYPE_GLBCHANGED )
    3502 {
    3503 /* global lower bound is not negative anymore -> remove down lock */
    3504 if ( SCIPisFeasNegative(scip, oldbound) && ! SCIPisFeasNegative(scip, newbound) )
    3505 SCIP_CALL( SCIPunlockVarCons(scip, var, consdata->cons, TRUE, FALSE) );
    3506 /* global lower bound turned negative -> add down lock */
    3507 else if ( ! SCIPisFeasNegative(scip, oldbound) && SCIPisFeasNegative(scip, newbound) )
    3508 SCIP_CALL( SCIPlockVarCons(scip, var, consdata->cons, TRUE, FALSE) );
    3509
    3510 return SCIP_OKAY;
    3511 }
    3512 if( eventtype == SCIP_EVENTTYPE_GUBCHANGED )
    3513 {
    3514 /* global upper bound is not positive anymore -> remove up lock */
    3515 if ( SCIPisFeasPositive(scip, oldbound) && ! SCIPisFeasPositive(scip, newbound) )
    3516 SCIP_CALL( SCIPunlockVarCons(scip, var, consdata->cons, FALSE, TRUE) );
    3517 /* global upper bound turned positive -> add up lock */
    3518 else if ( ! SCIPisFeasPositive(scip, oldbound) && SCIPisFeasPositive(scip, newbound) )
    3519 SCIP_CALL( SCIPlockVarCons(scip, var, consdata->cons, FALSE, TRUE) );
    3520
    3521 return SCIP_OKAY;
    3522 }
    3523 }
    3524
    3525 /* if variable is an indicator variable */
    3526 if( var == eventdata->indvar )
    3527 {
    3528 assert(SCIPvarIsBinary(var));
    3529 assert(consdata->cons != NULL);
    3530
    3531 if( eventtype == SCIP_EVENTTYPE_LBTIGHTENED )
    3532 ++(consdata->ntreatnonzeros);
    3533 else if( eventtype == SCIP_EVENTTYPE_LBRELAXED )
    3534 --(consdata->ntreatnonzeros);
    3535 else if( eventtype == SCIP_EVENTTYPE_UBTIGHTENED && ! eventdata->indvarmarked )
    3536 {
    3537 assert(oldbound == 1.0 && newbound == 0.0 );
    3538
    3539 /* save event data for propagation */
    3540 consdata->eventdatascurrent[consdata->neventdatascurrent] = eventdata;
    3541 consdata->eventvarscurrent[consdata->neventdatascurrent] = var;
    3542 ++consdata->neventdatascurrent;
    3543 eventdata->indvarmarked = TRUE;
    3544 assert(consdata->neventdatascurrent <= 4 * consdata->maxvars);
    3545 assert(var == eventdata->indvar );
    3546 }
    3547 assert(0 <= consdata->ntreatnonzeros && consdata->ntreatnonzeros <= consdata->nvars);
    3548 }
    3549
    3550 /* if variable is an implied variable,
    3551 * notice that the case consdata->var = consdata->indvar is possible */
    3552 if( var == eventdata->var && ! eventdata->varmarked )
    3553 {
    3554 if( eventtype == SCIP_EVENTTYPE_LBTIGHTENED )
    3555 {
    3556 /* if variable is now fixed to be nonzero */
    3557 if( !SCIPisFeasPositive(scip, oldbound) && SCIPisFeasPositive(scip, newbound) )
    3558 {
    3559 /* save event data for propagation */
    3560 consdata->eventdatascurrent[consdata->neventdatascurrent] = eventdata;
    3561 consdata->eventvarscurrent[consdata->neventdatascurrent] = var;
    3562 ++consdata->neventdatascurrent;
    3563 eventdata->varmarked = TRUE;
    3564 assert(consdata->neventdatascurrent <= 4 * consdata->maxvars );
    3565 assert(var == eventdata->var );
    3566 }
    3567 }
    3568 else if( eventtype == SCIP_EVENTTYPE_UBTIGHTENED )
    3569 {
    3570 /* if variable is now fixed to be nonzero */
    3571 if( !SCIPisFeasNegative(scip, oldbound) && SCIPisFeasNegative(scip, newbound) )
    3572 {
    3573 /* save event data for propagation */
    3574 consdata->eventdatascurrent[consdata->neventdatascurrent] = eventdata;
    3575 consdata->eventvarscurrent[consdata->neventdatascurrent] = var;
    3576 ++consdata->neventdatascurrent;
    3577 eventdata->varmarked = TRUE;
    3578 assert(consdata->neventdatascurrent <= 4 * consdata->maxvars );
    3579 assert(var == eventdata->var);
    3580 }
    3581 }
    3582 }
    3583 assert(0 <= consdata->ntreatnonzeros && consdata->ntreatnonzeros <= consdata->nvars);
    3584
    3585 SCIPdebugMsg(scip, "event exec cons <%s>: changed %s bound of variable <%s> from %g to %g (ntreatnonzeros: %d).\n",
    3586 SCIPconsGetName(consdata->cons), eventtype & (SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_GUBCHANGED) ? "upper" : "lower", SCIPvarGetName(SCIPeventGetVar(event)),
    3587 oldbound, newbound, consdata->ntreatnonzeros);
    3588
    3589 return SCIP_OKAY;
    3590}
    3591
    3592/* ---------------- Constraint specific interface methods ---------------- */
    3593
    3594/** creates the handler for cardinality constraints and includes it in SCIP */
    3596 SCIP* scip /**< SCIP data structure */
    3597 )
    3598{
    3599 SCIP_CONSHDLRDATA* conshdlrdata;
    3600 SCIP_CONSHDLR* conshdlr;
    3601
    3602 /* create constraint handler data */
    3603 SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
    3604 conshdlrdata->eventhdlr = NULL;
    3605 conshdlrdata->varhash = NULL;
    3606
    3607 /* create event handler for bound change events */
    3609 eventExecCardinality, NULL) );
    3610 if( conshdlrdata->eventhdlr == NULL )
    3611 {
    3612 SCIPerrorMessage("event handler for cardinality constraints not found.\n");
    3613 return SCIP_PLUGINNOTFOUND;
    3614 }
    3615
    3616 /* include constraint handler */
    3619 consEnfolpCardinality, consEnfopsCardinality, consCheckCardinality, consLockCardinality, conshdlrdata) );
    3620 assert(conshdlr != NULL);
    3621
    3622 /* set non-fundamental callbacks via specific setter functions */
    3623 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyCardinality, consCopyCardinality) );
    3624 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteCardinality) );
    3625 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolCardinality) );
    3626 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeCardinality) );
    3627 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsCardinality) );
    3628 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsCardinality) );
    3629 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpCardinality) );
    3630 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseCardinality) );
    3632 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintCardinality) );
    3633 SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropCardinality, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
    3635 /*SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropCardinality) ); @todo: implement repropagation */
    3636 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpCardinality, consSepasolCardinality, CONSHDLR_SEPAFREQ,
    3638 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransCardinality) );
    3639 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxCardinality) );
    3640 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphCardinality) );
    3641 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphCardinality) );
    3642
    3643 /* add cardinality constraint handler parameters */
    3644 SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/branchbalanced",
    3645 "whether to use balanced instead of unbalanced branching",
    3646 &conshdlrdata->branchbalanced, TRUE, DEFAULT_BRANCHBALANCED, NULL, NULL) );
    3647
    3648 SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/balanceddepth",
    3649 "maximum depth for using balanced branching (-1: no limit)",
    3650 &conshdlrdata->balanceddepth, TRUE, DEFAULT_BALANCEDDEPTH, -1, INT_MAX, NULL, NULL) );
    3651
    3652 SCIP_CALL( SCIPaddRealParam(scip, "constraints/" CONSHDLR_NAME "/balancedcutoff",
    3653 "determines that balanced branching is only used if the branching cut off value "
    3654 "w.r.t. the current LP solution is greater than a given value",
    3655 &conshdlrdata->balancedcutoff, TRUE, DEFAULT_BALANCEDCUTOFF, 0.01, SCIP_REAL_MAX, NULL, NULL) );
    3656
    3657 return SCIP_OKAY;
    3658}
    3659
    3660/** creates and captures a cardinality constraint
    3661 *
    3662 * We set the constraint to not be modifable. If the weights are non
    3663 * NULL, the variables are ordered according to these weights (in
    3664 * ascending order).
    3665 *
    3666 * @note the constraint gets captured, hence at one point you have to release it using the method \ref SCIPreleaseCons()
    3667 */
    3669 SCIP* scip, /**< SCIP data structure */
    3670 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    3671 const char* name, /**< name of constraint */
    3672 int nvars, /**< number of variables in the constraint */
    3673 SCIP_VAR** vars, /**< array with variables of constraint entries */
    3674 int cardval, /**< number of variables allowed to be nonzero */
    3675 SCIP_VAR** indvars, /**< indicator variables indicating which variables may be treated as nonzero
    3676 * in cardinality constraint, or NULL if new indicator variables should be
    3677 * introduced automatically */
    3678 SCIP_Real* weights, /**< weights determining the variable order, or NULL if variables should be
    3679 * ordered in the same way they were added to the constraint */
    3680 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
    3681 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    3682 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
    3683 * Usually set to TRUE. */
    3684 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    3685 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    3686 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    3687 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    3688 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
    3689 * Usually set to TRUE. */
    3690 SCIP_Bool local, /**< is constraint only valid locally?
    3691 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    3692 SCIP_Bool dynamic, /**< is constraint subject to aging?
    3693 * Usually set to FALSE. Set to TRUE for own cuts which
    3694 * are separated as constraints. */
    3695 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
    3696 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
    3697 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    3698 * if it may be moved to a more global node?
    3699 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
    3700 )
    3701{
    3702 SCIP_CONSHDLRDATA* conshdlrdata;
    3703 SCIP_CONSHDLR* conshdlr;
    3704 SCIP_CONSDATA* consdata;
    3705 SCIP_Bool modifiable;
    3706 SCIP_Bool transformed;
    3707 int v;
    3708
    3709 modifiable = FALSE;
    3710
    3711#ifndef NDEBUG
    3712 /* Check that the weights are sensible (not nan or inf); although not strictly needed, such values are likely a mistake. */
    3713 if ( nvars > 0 && weights != NULL )
    3714 {
    3715 for (v = 0; v < nvars; ++v)
    3716 assert( SCIPisFinite(weights[v]) );
    3717 }
    3718#endif
    3719
    3720 /* find the cardinality constraint handler */
    3721 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    3722 if( conshdlr == NULL )
    3723 {
    3724 SCIPerrorMessage("<%s> constraint handler not found\n", CONSHDLR_NAME);
    3725 return SCIP_PLUGINNOTFOUND;
    3726 }
    3727
    3728 /* check whether indicator variables are binary */
    3729 if( indvars != NULL )
    3730 {
    3731 for( v = 0; v < nvars; ++v )
    3732 {
    3733 if( !SCIPvarIsBinary(indvars[v]) )
    3734 {
    3735 SCIPerrorMessage("indicator <%s> is not binary\n", SCIPvarGetName(indvars[v]));
    3736 return SCIP_INVALIDDATA;
    3737 }
    3738 }
    3739 }
    3740
    3741 /* get constraint handler data */
    3742 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3743 assert(conshdlrdata != NULL);
    3744
    3745 /* are we in the transformed problem? */
    3746 transformed = SCIPgetStage(scip) >= SCIP_STAGE_TRANSFORMED;
    3747
    3748 /* create constraint data */
    3749 SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
    3750 consdata->cons = NULL;
    3751 consdata->vars = NULL;
    3752 consdata->indvars = NULL;
    3753 consdata->eventdatas = NULL;
    3754 consdata->nvars = nvars;
    3755 consdata->cardval = cardval;
    3756 consdata->maxvars = nvars;
    3757 consdata->rowub = NULL;
    3758 consdata->rowlb = NULL;
    3759 consdata->eventdatascurrent = NULL;
    3760 consdata->eventvarscurrent = NULL;
    3761 consdata->neventdatascurrent = 0;
    3762 consdata->ntreatnonzeros = transformed ? 0 : -1;
    3763 consdata->weights = NULL;
    3764
    3765 if( nvars > 0 )
    3766 {
    3767 /* duplicate memory for implied variables */
    3768 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->vars, vars, nvars) );
    3769
    3770 /* create indicator variables if not present */
    3771 if( indvars != NULL )
    3772 {
    3773 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->indvars, indvars, nvars) );
    3774 }
    3775 else
    3776 {
    3777 if( conshdlrdata->varhash == NULL )
    3778 {
    3779 /* set up hash map */
    3780 SCIP_CALL( SCIPhashmapCreate(&conshdlrdata->varhash, SCIPblkmem(scip), SCIPgetNTotalVars(scip)) );
    3781 }
    3782
    3783 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->indvars, nvars) );
    3784 for( v = 0; v < nvars; ++v )
    3785 {
    3786 SCIP_VAR* implvar;
    3787
    3788 implvar = vars[v];
    3789 assert(implvar != NULL);
    3790
    3791 /* check whether an indicator variable already exists for implied variable */
    3792 if( SCIPhashmapExists(conshdlrdata->varhash, implvar) )
    3793 {
    3794 assert((SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, implvar) != NULL);
    3795 consdata->indvars[v] = (SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, implvar);
    3796 }
    3797 else
    3798 {
    3799 /* if implied variable is binary, then it is not necessary to create an indicator variable */
    3800 if( SCIPvarIsBinary(implvar) )
    3801 consdata->indvars[v] = implvar;
    3802 else
    3803 {
    3804 char varname[SCIP_MAXSTRLEN];
    3805 SCIP_VAR* var;
    3806
    3807 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "ind_%s", SCIPvarGetName(vars[v]));
    3808 SCIP_CALL( SCIPcreateVar(scip, &var, varname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY, FALSE, FALSE,
    3809 NULL, NULL, NULL, NULL, NULL) );
    3810 SCIP_CALL( SCIPaddVar(scip, var) );
    3811 consdata->indvars[v] = var;
    3812 SCIP_CALL( SCIPreleaseVar(scip, &var) );
    3813 }
    3814
    3815 /* insert implied variable to hash map */
    3816 SCIP_CALL( SCIPhashmapInsert(conshdlrdata->varhash, implvar, (void*) consdata->indvars[v]) );/*lint !e571*/
    3817 assert(consdata->indvars[v] == (SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, implvar));
    3818 assert(SCIPhashmapExists(conshdlrdata->varhash, implvar));
    3819 }
    3820 }
    3821 }
    3822
    3823 /* allocate block memory */
    3824 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdatascurrent, 4*nvars) );/*lint !e647*/
    3825 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventvarscurrent, 4*nvars) );/*lint !e647*/
    3826 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdatas, nvars) );
    3827
    3828 /* check weights */
    3829 if( weights != NULL )
    3830 {
    3831 /* store weights */
    3832 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->weights, weights, nvars) );
    3833
    3834 /* sort variables - ascending order */
    3835 SCIPsortRealPtrPtr(consdata->weights, (void**)consdata->vars, (void**)consdata->indvars, nvars);
    3836 }
    3837 }
    3838 else
    3839 {
    3840 assert(weights == NULL);
    3841 }
    3842
    3843 /* create cardinality constraint */
    3844 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
    3845 local, modifiable, dynamic, removable, stickingatnode) );
    3846
    3847 consdata->cons = *cons;
    3848 assert(consdata->cons != NULL);
    3849
    3850 /* replace original variables by transformed variables in transformed constraint, add locks, and catch events */
    3851 for( v = nvars - 1; v >= 0; --v )
    3852 {
    3853 /* always use transformed variables in transformed constraints */
    3854 if( transformed )
    3855 {
    3856 SCIP_CALL( SCIPgetTransformedVar(scip, consdata->vars[v], &(consdata->vars[v])) );
    3857 SCIP_CALL( SCIPgetTransformedVar(scip, consdata->indvars[v], &(consdata->indvars[v])) );
    3858 }
    3859 assert(consdata->vars[v] != NULL);
    3860 assert(consdata->indvars[v] != NULL);
    3861 assert(transformed == SCIPvarIsTransformed(consdata->vars[v]));
    3862 assert(transformed == SCIPvarIsTransformed(consdata->indvars[v]));
    3863
    3864 /* handle the new variable */
    3865 SCIP_CALL( handleNewVariableCardinality(scip, *cons, consdata, conshdlrdata, consdata->vars[v],
    3866 consdata->indvars[v], v, transformed, &consdata->eventdatas[v]) );
    3867 assert(! transformed || consdata->eventdatas[v] != NULL);
    3868 }
    3869
    3870 return SCIP_OKAY;
    3871}
    3872
    3873/** creates and captures a cardinality constraint with all constraint flags set to their default values.
    3874 *
    3875 * @warning Do NOT set the constraint to be modifiable manually, because this might lead
    3876 * to wrong results as the variable array will not be re-sorted
    3877 *
    3878 * @note the constraint gets captured, hence at one point you have to release it using the method \ref SCIPreleaseCons()
    3879 */
    3881 SCIP* scip, /**< SCIP data structure */
    3882 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    3883 const char* name, /**< name of constraint */
    3884 int nvars, /**< number of variables in the constraint */
    3885 SCIP_VAR** vars, /**< array with variables of constraint entries */
    3886 int cardval, /**< number of variables allowed to be nonzero */
    3887 SCIP_VAR** indvars, /**< indicator variables indicating which variables may be treated as nonzero
    3888 * in cardinality constraint, or NULL if new indicator variables should be
    3889 * introduced automatically */
    3890 SCIP_Real* weights /**< weights determining the variable order, or NULL if variables should be
    3891 * ordered in the same way they were added to the constraint */
    3892 )
    3893{
    3894 SCIP_CALL( SCIPcreateConsCardinality(scip, cons, name, nvars, vars, cardval, indvars, weights, TRUE, TRUE, TRUE, TRUE,
    3895 TRUE, FALSE, FALSE, FALSE, FALSE) );
    3896
    3897 return SCIP_OKAY;
    3898}
    3899
    3900/** changes cardinality value of cardinality constraint (i.e., right hand side of cardinality constraint) */
    3902 SCIP* scip, /**< SCIP data structure */
    3903 SCIP_CONS* cons, /**< pointer to hold the created constraint */
    3904 int cardval /**< number of variables allowed to be nonzero */
    3905 )
    3906{
    3907 SCIP_CONSDATA* consdata;
    3908
    3909 assert(scip != NULL);
    3910 assert(cons != NULL);
    3911
    3912 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    3913 {
    3914 SCIPerrorMessage("constraint is not a cardinality constraint.\n");
    3915 return SCIP_INVALIDDATA;
    3916 }
    3917
    3918 consdata = SCIPconsGetData(cons);
    3919 assert(consdata != NULL);
    3920
    3921 SCIPdebugMsg(scip, "modify right hand side of cardinality constraint from <%i> to <%i>\n", consdata->cardval, cardval);
    3922
    3923 /* create constraint data */
    3924 consdata->cardval = cardval;
    3925
    3926 return SCIP_OKAY;
    3927}
    3928
    3929/** adds variable to cardinality constraint, the position is determined by the given weight */
    3931 SCIP* scip, /**< SCIP data structure */
    3932 SCIP_CONS* cons, /**< constraint */
    3933 SCIP_VAR* var, /**< variable to add to the constraint */
    3934 SCIP_VAR* indvar, /**< indicator variable indicating whether variable may be treated as nonzero
    3935 * in cardinality constraint (or NULL if this variable should be created
    3936 * automatically) */
    3937 SCIP_Real weight /**< weight determining position of variable */
    3938 )
    3939{
    3940 SCIP_CONSHDLRDATA* conshdlrdata;
    3941 SCIP_CONSHDLR* conshdlr;
    3942
    3943 assert(scip != NULL);
    3944 assert(var != NULL);
    3945 assert(cons != NULL);
    3946
    3947 SCIPdebugMsg(scip, "adding variable <%s> to constraint <%s> with weight %g\n", SCIPvarGetName(var),
    3948 SCIPconsGetName(cons), weight);
    3949
    3950 conshdlr = SCIPconsGetHdlr(cons);
    3951 assert(conshdlr != NULL);
    3952 if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
    3953 {
    3954 SCIPerrorMessage("constraint is not a cardinality constraint.\n");
    3955 return SCIP_INVALIDDATA;
    3956 }
    3957
    3958 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3959 assert(conshdlrdata != NULL);
    3960
    3961 SCIP_CALL( addVarCardinality(scip, cons, conshdlrdata, var, indvar, weight) );
    3962
    3963 return SCIP_OKAY;
    3964}
    3965
    3966/** appends variable to cardinality constraint */
    3968 SCIP* scip, /**< SCIP data structure */
    3969 SCIP_CONS* cons, /**< constraint */
    3970 SCIP_VAR* var, /**< variable to add to the constraint */
    3971 SCIP_VAR* indvar /**< indicator variable indicating whether variable may be treated as nonzero
    3972 * in cardinality constraint (or NULL if this variable should be created
    3973 * automatically) */
    3974 )
    3975{
    3976 SCIP_CONSHDLRDATA* conshdlrdata;
    3977 SCIP_CONSHDLR* conshdlr;
    3978
    3979 assert(scip != NULL);
    3980 assert(var != NULL);
    3981 assert(cons != NULL);
    3982
    3983 SCIPdebugMsg(scip, "appending variable <%s> to constraint <%s>\n", SCIPvarGetName(var), SCIPconsGetName(cons));
    3984
    3985 conshdlr = SCIPconsGetHdlr(cons);
    3986 assert(conshdlr != NULL);
    3987 if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
    3988 {
    3989 SCIPerrorMessage("constraint is not a cardinality constraint.\n");
    3990 return SCIP_INVALIDDATA;
    3991 }
    3992
    3993 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3994 assert(conshdlrdata != NULL);
    3995
    3996 SCIP_CALL( appendVarCardinality(scip, cons, conshdlrdata, var, indvar) );
    3997
    3998 return SCIP_OKAY;
    3999}
    4000
    4001/** gets number of variables in cardinality constraint */
    4003 SCIP* scip, /**< SCIP data structure */
    4004 SCIP_CONS* cons /**< constraint */
    4005 )
    4006{
    4007 SCIP_CONSDATA* consdata;
    4008
    4009 assert(scip != NULL);
    4010 assert(cons != NULL);
    4011
    4012 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    4013 {
    4014 SCIPerrorMessage("constraint is not a cardinality constraint.\n");
    4015 SCIPABORT();
    4016 return -1; /*lint !e527*/
    4017 }
    4018
    4019 consdata = SCIPconsGetData(cons);
    4020 assert(consdata != NULL);
    4021
    4022 return consdata->nvars;
    4023}
    4024
    4025/** gets array of variables in cardinality constraint */
    4027 SCIP* scip, /**< SCIP data structure */
    4028 SCIP_CONS* cons /**< constraint data */
    4029 )
    4030{
    4031 SCIP_CONSDATA* consdata;
    4032
    4033 assert(scip != NULL);
    4034 assert(cons != NULL);
    4035
    4036 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    4037 {
    4038 SCIPerrorMessage("constraint is not a cardinality constraint.\n");
    4039 SCIPABORT();
    4040 return NULL; /*lint !e527*/
    4041 }
    4042
    4043 consdata = SCIPconsGetData(cons);
    4044 assert(consdata != NULL);
    4045
    4046 return consdata->vars;
    4047}
    4048
    4049/** gets cardinality value of cardinality constraint (i.e., right hand side of cardinality constraint) */
    4051 SCIP* scip, /**< SCIP data structure */
    4052 SCIP_CONS* cons /**< constraint data */
    4053 )
    4054{
    4055 SCIP_CONSDATA* consdata;
    4056
    4057 assert(scip != NULL);
    4058 assert(cons != NULL);
    4059
    4060 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    4061 {
    4062 SCIPerrorMessage("constraint is not a cardinality constraint.\n");
    4063 return -1; /*lint !e527*/
    4064 }
    4065
    4066 consdata = SCIPconsGetData(cons);
    4067 assert(consdata != NULL);
    4068
    4069 return consdata->cardval;
    4070}
    4071
    4072/** gets array of weights in cardinality constraint (or NULL if not existent) */
    4074 SCIP* scip, /**< SCIP data structure */
    4075 SCIP_CONS* cons /**< constraint data */
    4076 )
    4077{
    4078 SCIP_CONSDATA* consdata;
    4079
    4080 assert(scip != NULL);
    4081 assert(cons != NULL);
    4082
    4083 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    4084 {
    4085 SCIPerrorMessage("constraint is not a cardinality constraint.\n");
    4086 SCIPABORT();
    4087 return NULL; /*lint !e527*/
    4088 }
    4089
    4090 consdata = SCIPconsGetData(cons);
    4091 assert(consdata != NULL);
    4092
    4093 return consdata->weights;
    4094}
    SCIP_VAR * w
    Definition: circlepacking.c:67
    static SCIP_RETCODE unlockVariableCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_VAR *indvar)
    #define CONSHDLR_NEEDSCONS
    #define CONSHDLR_SEPAFREQ
    static SCIP_DECL_CONSFREE(consFreeCardinality)
    static SCIP_DECL_CONSPARSE(consParseCardinality)
    #define CONSHDLR_CHECKPRIORITY
    static SCIP_DECL_CONSSEPALP(consSepalpCardinality)
    #define CONSHDLR_DESC
    static SCIP_DECL_CONSINITLP(consInitlpCardinality)
    #define CONSHDLR_PROP_TIMING
    static SCIP_RETCODE consdataEnsurevarsSizeCardinality(SCIP *scip, SCIP_CONSDATA *consdata, int num, SCIP_Bool reserveweights)
    #define CONSHDLR_MAXPREROUNDS
    static SCIP_DECL_CONSSEPASOL(consSepasolCardinality)
    static SCIP_RETCODE lockVariableCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_VAR *indvar)
    #define CONSHDLR_SEPAPRIORITY
    static SCIP_RETCODE appendVarCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_VAR *var, SCIP_VAR *indvar)
    static void consdataUnmarkEventdataVars(SCIP_CONSDATA *consdata)
    static SCIP_DECL_CONSEXITSOL(consExitsolCardinality)
    static SCIP_RETCODE fixVariableZeroNode(SCIP *scip, SCIP_VAR *var, SCIP_NODE *node, SCIP_Bool *infeasible)
    static SCIP_DECL_CONSPRESOL(consPresolCardinality)
    static SCIP_DECL_CONSPRINT(consPrintCardinality)
    static SCIP_RETCODE generateRowCardinality(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons, SCIP_Bool local, SCIP_ROW **rowlb, SCIP_ROW **rowub)
    static SCIP_DECL_CONSDELETE(consDeleteCardinality)
    static SCIP_RETCODE deleteVarCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos)
    static SCIP_RETCODE fixVariableZero(SCIP *scip, SCIP_VAR *var, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    static SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphCardinality)
    static SCIP_RETCODE polishPrimalSolution(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_SOL *sol, SCIP_SOL *primsol)
    static SCIP_RETCODE branchBalancedCardinality(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_SOL *sol, SCIP_CONS *branchcons, SCIP_VAR **vars, SCIP_VAR **indvars, int nvars, int cardval, int branchnnonzero, int branchpos, SCIP_Real balancedcutoff)
    static SCIP_DECL_CONSCOPY(consCopyCardinality)
    static SCIP_DECL_CONSCHECK(consCheckCardinality)
    static SCIP_DECL_CONSENFOPS(consEnfopsCardinality)
    static SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphCardinality)
    #define DEFAULT_BALANCEDDEPTH
    static SCIP_RETCODE initsepaBoundInequalityFromCardinality(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, SCIP_SOL *sol, SCIP_Bool solvedinitlp, int *ngen, SCIP_Bool *cutoff)
    #define DEFAULT_BALANCEDCUTOFF
    #define CONSHDLR_PROPFREQ
    static SCIP_RETCODE enforceCardinality(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_SOL *sol, int nconss, SCIP_CONS **conss, SCIP_RESULT *result)
    static SCIP_DECL_CONSTRANS(consTransCardinality)
    static SCIP_RETCODE presolRoundCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, SCIP_Bool *success, int *ndelconss, int *nupgdconss, int *nfixedvars, int *nremovedvars)
    #define CONSHDLR_PRESOLTIMING
    static SCIP_DECL_CONSPROP(consPropCardinality)
    static SCIP_DECL_CONSLOCK(consLockCardinality)
    #define DEFAULT_BRANCHBALANCED
    static SCIP_DECL_CONSENFORELAX(consEnforelaxCardinality)
    static SCIP_RETCODE catchVarEventCardinality(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_VAR *indvar, int pos, SCIP_EVENTDATA **eventdata)
    static SCIP_RETCODE addVarCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_VAR *var, SCIP_VAR *indvar, SCIP_Real weight)
    #define CONSHDLR_EAGERFREQ
    #define EVENTHDLR_DESC
    static SCIP_DECL_CONSGETVARS(consGetVarsCardinality)
    static SCIP_RETCODE separateCardinality(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_SOL *sol, int nconss, SCIP_CONS **conss, SCIP_RESULT *result)
    static SCIP_RETCODE handleNewVariableCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_VAR *var, SCIP_VAR *indvar, int pos, SCIP_Bool transformed, SCIP_EVENTDATA **eventdata)
    #define EVENTHDLR_EVENT_TYPE
    static SCIP_RETCODE propCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_Bool *cutoff, int *nchgdomain)
    #define CONSHDLR_ENFOPRIORITY
    static SCIP_DECL_CONSGETNVARS(consGetNVarsCardinality)
    #define CONSHDLR_DELAYSEPA
    #define CONSHDLR_NAME
    static SCIP_DECL_CONSENFOLP(consEnfolpCardinality)
    static SCIP_RETCODE dropVarEventCardinality(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_VAR *indvar, SCIP_EVENTDATA **eventdata)
    #define EVENTHDLR_NAME
    static SCIP_RETCODE branchUnbalancedCardinality(SCIP *scip, SCIP_SOL *sol, SCIP_CONS *branchcons, SCIP_VAR **vars, SCIP_VAR **indvars, int nvars, int cardval, int branchnnonzero, int branchpos)
    static SCIP_DECL_EVENTEXEC(eventExecCardinality)
    #define CONSHDLR_DELAYPROP
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyCardinality)
    constraint handler for cardinality constraints
    Constraint handler for knapsack constraints of the form , x binary and .
    Constraint handler for linear constraints in their most general form, .
    #define NULL
    Definition: def.h:255
    #define SCIP_MAXSTRLEN
    Definition: def.h:276
    #define SCIP_Longint
    Definition: def.h:148
    #define SCIP_REAL_MAX
    Definition: def.h:165
    #define SCIP_Bool
    Definition: def.h:98
    #define MIN(x, y)
    Definition: def.h:231
    #define SCIP_Real
    Definition: def.h:163
    #define TRUE
    Definition: def.h:100
    #define FALSE
    Definition: def.h:101
    #define MAX(x, y)
    Definition: def.h:227
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:155
    #define SCIPABORT()
    Definition: def.h:334
    #define REALABS(x)
    Definition: def.h:189
    #define SCIP_CALL(x)
    Definition: def.h:362
    SCIP_Real * SCIPgetWeightsCardinality(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcreateConsCardinality(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, int cardval, SCIP_VAR **indvars, 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)
    SCIP_RETCODE SCIPcreateConsBasicCardinality(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, int cardval, SCIP_VAR **indvars, SCIP_Real *weights)
    int SCIPgetCardvalCardinality(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPappendVarCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_VAR *indvar)
    SCIP_RETCODE SCIPcreateConsKnapsack(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Longint *weights, SCIP_Longint capacity, 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 SCIPaddVarCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_VAR *indvar, SCIP_Real weight)
    int SCIPgetNVarsCardinality(SCIP *scip, SCIP_CONS *cons)
    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_VAR ** SCIPgetVarsCardinality(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPchgCardvalCardinality(SCIP *scip, SCIP_CONS *cons, int cardval)
    SCIP_RETCODE SCIPincludeConshdlrCardinality(SCIP *scip)
    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:647
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_prob.c:1907
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3420
    int SCIPgetNTotalVars(SCIP *scip)
    Definition: scip_prob.c:3064
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3284
    SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
    Definition: misc.c:3143
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3466
    SCIP_RETCODE 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_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_Real SCIPcalcNodeselPriority(SCIP *scip, SCIP_VAR *var, SCIP_BRANCHDIR branchdir, SCIP_Real targetvalue)
    Definition: scip_branch.c:928
    SCIP_Real SCIPcalcChildEstimate(SCIP *scip, SCIP_VAR *var, SCIP_Real targetvalue)
    Definition: scip_branch.c:955
    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 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
    int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4782
    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 SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
    Definition: scip_cons.c:854
    int SCIPconshdlrGetSepaFreq(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:5276
    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
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    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 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_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_Bool SCIProwIsInLP(SCIP_ROW *row)
    Definition: lp.c:17917
    SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
    Definition: scip_lp.c:1672
    SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
    Definition: scip_sol.c:884
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    void SCIPupdateSolConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
    Definition: scip_sol.c:453
    SCIP_RETCODE SCIPtrySol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
    Definition: scip_sol.c:4019
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1571
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfloor(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 SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
    Definition: scip_var.c:5210
    SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
    Definition: var.c:23844
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23479
    SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:5697
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23387
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24269
    SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
    Definition: var.c:23431
    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:24143
    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
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23268
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:2332
    SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
    Definition: var.c:23807
    int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
    Definition: var.c:23795
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24235
    SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
    Definition: scip_var.c:120
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24121
    SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:11057
    SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
    Definition: scip_var.c:10318
    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
    SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
    Definition: scip_var.c:10984
    SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
    Definition: var.c:23819
    void SCIPsortRealPtrPtr(SCIP_Real *realarray, void **ptrarray1, void **ptrarray2, 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
    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 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 SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for solutions
    public methods for querying solving statistics
    public methods for the branch-and-bound tree
    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:1221
    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_BOUNDCHANGED
    Definition: type_event.h:127
    #define SCIP_EVENTTYPE_GUBCHANGED
    Definition: type_event.h:76
    #define SCIP_EVENTTYPE_GBDCHANGED
    Definition: type_event.h:122
    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
    @ 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_PARAMETERWRONGVAL
    Definition: type_retcode.h:57
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_TRANSFORMED
    Definition: type_set.h:47
    @ SYM_CONSOPTYPE_CARD_TUPLE
    Definition: type_symmetry.h:87
    @ SYM_CONSOPTYPE_SUM
    Definition: type_symmetry.h:83
    @ SYM_SYMTYPE_PERM
    Definition: type_symmetry.h:61
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64
    @ SCIP_VARSTATUS_MULTAGGR
    Definition: type_var.h:56
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141