Scippy

    SCIP

    Solving Constraint Integer Programs

    cons_xor.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file cons_xor.c
    26 * @ingroup DEFPLUGINS_CONS
    27 * @brief Constraint handler for "xor" constraints, \f$rhs = x_1 \oplus x_2 \oplus \dots \oplus x_n\f$
    28 * @author Tobias Achterberg
    29 * @author Stefan Heinz
    30 * @author Marc Pfetsch
    31 * @author Michael Winkler
    32 *
    33 * This constraint handler deals with "xor" constraint. These are constraint of the form:
    34 *
    35 * \f[
    36 * rhs = x_1 \oplus x_2 \oplus \dots \oplus x_n
    37 * \f]
    38 *
    39 * where \f$x_i\f$ is a binary variable for all \f$i\f$ and \f$rhs\f$ is bool. The variables \f$x\f$'s are called
    40 * operators. This constraint is satisfied if \f$rhs\f$ is TRUE and an odd number of the operators are TRUE or if the
    41 * \f$rhs\f$ is FALSE and a even number of operators are TRUE. Hence, if the sum of \f$rhs\f$ and operators is even.
    42 *
    43 * @todo reduce code duplication
    44 * - unified treatment of constraint with 0/1/2 binary variables
    45 * - static functions for certain operations that respect deleteintvar flag properly (e.g., deletion of constraints)
    46 * @todo add offset for activity which might allow to handle intvar in a more unified way
    47 * (right now, we do not remove fixed variables from the constraint, because we must ensure that the intvar gets
    48 * the correct value in the end)
    49 * @todo check if preprocessConstraintPairs can also be executed for non-artificial intvars (after the previous changes)
    50 */
    51
    52/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    53
    55#include "scip/cons_linear.h"
    56#include "scip/cons_setppc.h"
    57#include "scip/cons_xor.h"
    58#include "scip/debug.h"
    59#include "scip/heur_trysol.h"
    60#include "scip/pub_cons.h"
    61#include "scip/pub_event.h"
    62#include "scip/pub_lp.h"
    63#include "scip/pub_message.h"
    64#include "scip/pub_misc.h"
    65#include "scip/pub_misc_sort.h"
    66#include "scip/pub_var.h"
    67#include "scip/scip_conflict.h"
    68#include "scip/scip_cons.h"
    69#include "scip/scip_copy.h"
    70#include "scip/scip_cut.h"
    71#include "scip/scip_event.h"
    72#include "scip/scip_general.h"
    73#include "scip/scip_heur.h"
    74#include "scip/scip_lp.h"
    75#include "scip/scip_mem.h"
    76#include "scip/scip_message.h"
    77#include "scip/scip_numerics.h"
    78#include "scip/scip_param.h"
    79#include "scip/scip_prob.h"
    80#include "scip/scip_probing.h"
    81#include "scip/scip_sol.h"
    82#include "scip/scip_tree.h"
    83#include "scip/scip_var.h"
    84#include "scip/symmetry_graph.h"
    86#include <string.h>
    87
    88/* constraint handler properties */
    89#define CONSHDLR_NAME "xor"
    90#define CONSHDLR_DESC "constraint handler for xor constraints: r = xor(x1, ..., xn)"
    91#define CONSHDLR_SEPAPRIORITY +850200 /**< priority of the constraint handler for separation */
    92#define CONSHDLR_ENFOPRIORITY -850200 /**< priority of the constraint handler for constraint enforcing */
    93#define CONSHDLR_CHECKPRIORITY -850200 /**< priority of the constraint handler for checking feasibility */
    94#define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
    95#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
    96#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
    97 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    98#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
    99#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
    100#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
    101#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
    102
    103#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
    104#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_ALWAYS
    105
    106#define EVENTHDLR_NAME "xor"
    107#define EVENTHDLR_DESC "event handler for xor constraints"
    108
    109#define LINCONSUPGD_PRIORITY +600000 /**< priority of the constraint handler for upgrading of linear constraints */
    110
    111#define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
    112#define DEFAULT_ADDEXTENDEDFORM FALSE /**< should the extended formulation be added in presolving? */
    113#define DEFAULT_ADDFLOWEXTENDED FALSE /**< should the extended flow formulation be added (nonsymmetric formulation otherwise)? */
    114#define DEFAULT_SEPARATEPARITY FALSE /**< should parity inequalities be separated? */
    115#define DEFAULT_GAUSSPROPFREQ 5 /**< frequency for applying the Gauss propagator */
    116#define HASHSIZE_XORCONS 500 /**< minimal size of hash table in logicor constraint tables */
    117#define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
    118#define NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
    119#define MINGAINPERNMINCOMPARISONS 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
    120#define MAXXORCONSSSYSTEM 1000 /**< maximal number of active constraints for which checking the system over GF2 is performed */
    121#define MAXXORVARSSYSTEM 1000 /**< maximal number of variables in xor constraints for which checking the system over GF2 is performed */
    122
    123#define NROWS 5
    124
    125
    126/*
    127 * Data structures
    128 */
    129
    130/** type used for matrix entries in function checkGauss() */
    131typedef unsigned short Type;
    132
    133/** constraint data for xor constraints */
    134struct SCIP_ConsData
    135{
    136 SCIP_VAR** vars; /**< variables in the xor operation */
    137 SCIP_VAR* intvar; /**< internal variable for LP relaxation */
    138 SCIP_VAR** extvars; /**< variables in extended (flow|asymmetric) formulation (order for flow formulation: nn, ns, sn, ss) */
    139 SCIP_ROW* rows[NROWS]; /**< rows for linear relaxation of xor constraint */
    140 int nvars; /**< number of variables in xor operation */
    141 int nextvars; /**< number of variables in extended flow formulation */
    142 int varssize; /**< size of vars array */
    143 int extvarssize; /**< size of extvars array */
    144 int watchedvar1; /**< position of first watched operator variable */
    145 int watchedvar2; /**< position of second watched operator variable */
    146 int filterpos1; /**< event filter position of first watched operator variable */
    147 int filterpos2; /**< event filter position of second watched operator variable */
    148 SCIP_Bool rhs; /**< right hand side of the constraint */
    149 unsigned int deleteintvar:1; /**< should artificial variable be deleted */
    150 unsigned int propagated:1; /**< is constraint already preprocessed/propagated? */
    151 unsigned int sorted:1; /**< are the constraint's variables sorted? */
    152 unsigned int changed:1; /**< was constraint changed since last pair preprocessing round? */
    153};
    154
    155/** constraint handler data */
    156struct SCIP_ConshdlrData
    157{
    158 SCIP_EVENTHDLR* eventhdlr; /**< event handler for events on watched variables */
    159 SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
    160 SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance? */
    161 SCIP_Bool addextendedform; /**< should the extended formulation be added in presolving? */
    162 SCIP_Bool addflowextended; /**< should the extended flow formulation be added (nonsymmetric formulation otherwise)? */
    163 SCIP_Bool separateparity; /**< should parity inequalities be separated? */
    164 int gausspropfreq; /**< frequency for applying the Gauss propagator */
    165};
    166
    167
    168/*
    169 * Propagation rules
    170 */
    171
    173{
    174 PROPRULE_0, /**< all variables are fixed => fix integral variable */
    175 PROPRULE_1, /**< all except one variable fixed => fix remaining variable */
    176 PROPRULE_INTLB, /**< lower bound propagation of integral variable */
    177 PROPRULE_INTUB, /**< upper bound propagation of integral variable */
    178 PROPRULE_INVALID /**< propagation was applied without a specific propagation rule */
    180typedef enum Proprule PROPRULE;
    181
    182
    183/*
    184 * Local methods
    185 */
    186
    187/** installs rounding locks for the given variable in the given xor constraint */
    188static
    190 SCIP* scip, /**< SCIP data structure */
    191 SCIP_CONS* cons, /**< xor constraint */
    192 SCIP_VAR* var /**< variable of constraint entry */
    193 )
    194{
    196
    197 /* rounding in both directions may violate the constraint */
    198 SCIP_CALL( SCIPlockVarCons(scip, var, cons, TRUE, TRUE) );
    199
    200 return SCIP_OKAY;
    201}
    202
    203/** removes rounding locks for the given variable in the given xor constraint */
    204static
    206 SCIP* scip, /**< SCIP data structure */
    207 SCIP_CONS* cons, /**< xor constraint */
    208 SCIP_VAR* var /**< variable of constraint entry */
    209 )
    210{
    212
    213 /* rounding in both directions may violate the constraint */
    214 SCIP_CALL( SCIPunlockVarCons(scip, var, cons, TRUE, TRUE) );
    215
    216 return SCIP_OKAY;
    217}
    218
    219/** creates constraint handler data */
    220static
    222 SCIP* scip, /**< SCIP data structure */
    223 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
    224 SCIP_EVENTHDLR* eventhdlr /**< event handler */
    225 )
    226{
    227 assert(scip != NULL);
    228 assert(conshdlrdata != NULL);
    229 assert(eventhdlr != NULL);
    230
    231 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
    232
    233 /* set event handler for catching events on watched variables */
    234 (*conshdlrdata)->eventhdlr = eventhdlr;
    235
    236 return SCIP_OKAY;
    237}
    238
    239/** frees constraint handler data */
    240static
    242 SCIP* scip, /**< SCIP data structure */
    243 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
    244 )
    245{
    246 assert(conshdlrdata != NULL);
    247 assert(*conshdlrdata != NULL);
    248
    249 SCIPfreeBlockMemory(scip, conshdlrdata);
    250}
    251
    252/** stores the given variable numbers as watched variables, and updates the event processing */
    253static
    255 SCIP* scip, /**< SCIP data structure */
    256 SCIP_CONSDATA* consdata, /**< xor constraint data */
    257 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    258 int watchedvar1, /**< new first watched variable */
    259 int watchedvar2 /**< new second watched variable */
    260 )
    261{
    262 assert(consdata != NULL);
    263 assert(watchedvar1 == -1 || watchedvar1 != watchedvar2);
    264 assert(watchedvar1 != -1 || watchedvar2 == -1);
    265 assert(watchedvar1 == -1 || (0 <= watchedvar1 && watchedvar1 < consdata->nvars));
    266 assert(watchedvar2 == -1 || (0 <= watchedvar2 && watchedvar2 < consdata->nvars));
    267
    268 /* if one watched variable is equal to the old other watched variable, just switch positions */
    269 if( watchedvar1 == consdata->watchedvar2 || watchedvar2 == consdata->watchedvar1 )
    270 {
    271 int tmp;
    272
    273 tmp = consdata->watchedvar1;
    274 consdata->watchedvar1 = consdata->watchedvar2;
    275 consdata->watchedvar2 = tmp;
    276 tmp = consdata->filterpos1;
    277 consdata->filterpos1 = consdata->filterpos2;
    278 consdata->filterpos2 = tmp;
    279 }
    280 assert(watchedvar1 == -1 || watchedvar1 != consdata->watchedvar2);
    281 assert(watchedvar2 == -1 || watchedvar2 != consdata->watchedvar1);
    282
    283 /* drop events on old watched variables */
    284 if( consdata->watchedvar1 != -1 && consdata->watchedvar1 != watchedvar1 )
    285 {
    286 assert(consdata->filterpos1 != -1);
    287 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar1], SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr,
    288 (SCIP_EVENTDATA*)consdata, consdata->filterpos1) );
    289 }
    290 if( consdata->watchedvar2 != -1 && consdata->watchedvar2 != watchedvar2 )
    291 {
    292 assert(consdata->filterpos2 != -1);
    293 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar2], SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr,
    294 (SCIP_EVENTDATA*)consdata, consdata->filterpos2) );
    295 }
    296
    297 /* catch events on new watched variables */
    298 if( watchedvar1 != -1 && watchedvar1 != consdata->watchedvar1 )
    299 {
    300 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[watchedvar1], SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr,
    301 (SCIP_EVENTDATA*)consdata, &consdata->filterpos1) );
    302 }
    303 if( watchedvar2 != -1 && watchedvar2 != consdata->watchedvar2 )
    304 {
    305 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[watchedvar2], SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr,
    306 (SCIP_EVENTDATA*)consdata, &consdata->filterpos2) );
    307 }
    308
    309 /* set the new watched variables */
    310 consdata->watchedvar1 = watchedvar1;
    311 consdata->watchedvar2 = watchedvar2;
    312
    313 return SCIP_OKAY;
    314}
    315
    316/** ensures, that the vars array can store at least num entries */
    317static
    319 SCIP* scip, /**< SCIP data structure */
    320 SCIP_CONSDATA* consdata, /**< linear constraint data */
    321 int num /**< minimum number of entries to store */
    322 )
    323{
    324 assert(consdata != NULL);
    325 assert(consdata->nvars <= consdata->varssize);
    326
    327 if( num > consdata->varssize )
    328 {
    329 int newsize;
    330
    331 newsize = SCIPcalcMemGrowSize(scip, num);
    332 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
    333 consdata->varssize = newsize;
    334 }
    335 assert(num <= consdata->varssize);
    336
    337 return SCIP_OKAY;
    338}
    339
    340/** creates constraint data for xor constraint */
    341static
    343 SCIP* scip, /**< SCIP data structure */
    344 SCIP_CONSDATA** consdata, /**< pointer to store the constraint data */
    345 SCIP_Bool rhs, /**< right hand side of the constraint */
    346 int nvars, /**< number of variables in the xor operation */
    347 SCIP_VAR** vars, /**< variables in xor operation */
    348 SCIP_VAR* intvar /**< artificial integer variable for linear relaxation */
    349 )
    350{
    351 int r;
    352
    353 assert(consdata != NULL);
    354 assert(nvars == 0 || vars != NULL);
    355
    356 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
    357 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
    358
    359 (*consdata)->rhs = rhs;
    360 (*consdata)->intvar = intvar;
    361 for( r = 0; r < NROWS; ++r )
    362 (*consdata)->rows[r] = NULL;
    363 (*consdata)->nvars = nvars;
    364 (*consdata)->varssize = nvars;
    365 (*consdata)->watchedvar1 = -1;
    366 (*consdata)->watchedvar2 = -1;
    367 (*consdata)->filterpos1 = -1;
    368 (*consdata)->filterpos2 = -1;
    369 (*consdata)->deleteintvar = (intvar == NULL);
    370 (*consdata)->propagated = FALSE;
    371 (*consdata)->sorted = FALSE;
    372 (*consdata)->changed = TRUE;
    373 (*consdata)->extvars = NULL;
    374 (*consdata)->nextvars = 0;
    375 (*consdata)->extvarssize = 0;
    376
    377 /* get transformed variables, if we are in the transformed problem */
    379 {
    380 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
    381
    382 if( (*consdata)->intvar != NULL )
    383 {
    384 SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->intvar, &((*consdata)->intvar)) );
    385 }
    386
    388 {
    389 SCIP_CONSHDLRDATA* conshdlrdata;
    390 SCIP_CONSHDLR* conshdlr;
    391 int v;
    392
    394 assert(conshdlr != NULL);
    395 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    396 assert(conshdlrdata != NULL);
    397
    398 for( v = (*consdata)->nvars - 1; v >= 0; --v )
    399 {
    400 SCIP_CALL( SCIPcatchVarEvent(scip, (*consdata)->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
    401 (SCIP_EVENTDATA*)(*consdata), NULL) );
    402 }
    403 }
    404 }
    405
    406 if( (*consdata)->intvar != NULL )
    407 {
    408 /* capture artificial variable */
    409 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->intvar) );
    410 }
    411
    412 return SCIP_OKAY;
    413}
    414
    415/** releases LP row of constraint data */
    416static
    418 SCIP* scip, /**< SCIP data structure */
    419 SCIP_CONSDATA* consdata /**< constraint data */
    420 )
    421{
    422 int r;
    423
    424 assert(consdata != NULL);
    425
    426 for( r = 0; r < NROWS; ++r )
    427 {
    428 if( consdata->rows[r] != NULL )
    429 {
    430 SCIP_CALL( SCIPreleaseRow(scip, &consdata->rows[r]) );
    431 }
    432 }
    433
    434 return SCIP_OKAY;
    435}
    436
    437/** frees constraint data for xor constraint */
    438static
    440 SCIP* scip, /**< SCIP data structure */
    441 SCIP_CONSDATA** consdata, /**< pointer to the constraint data */
    442 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
    443 )
    444{
    445 assert(consdata != NULL);
    446 assert(*consdata != NULL);
    447
    449 {
    450 int j;
    451
    452 /* drop events for watched variables */
    453 SCIP_CALL( consdataSwitchWatchedvars(scip, *consdata, eventhdlr, -1, -1) );
    454
    455 /* release flow variables */
    456 if( (*consdata)->nextvars > 0 )
    457 {
    458 assert((*consdata)->extvars != NULL);
    459 for( j = 0; j < (*consdata)->extvarssize; ++j )
    460 {
    461 if( (*consdata)->extvars[j] != NULL )
    462 {
    463 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->extvars[j])) );
    464 }
    465 }
    466
    467 SCIPfreeBlockMemoryArray(scip, &((*consdata)->extvars), (*consdata)->extvarssize);
    468 (*consdata)->nextvars = 0;
    469 (*consdata)->extvarssize = 0;
    470 }
    471 }
    472 else
    473 {
    474 assert((*consdata)->watchedvar1 == -1);
    475 assert((*consdata)->watchedvar2 == -1);
    476 }
    477
    478 /* release LP row */
    479 SCIP_CALL( consdataFreeRows(scip, *consdata) );
    480
    481 /* release internal variable */
    482 if( (*consdata)->intvar != NULL )
    483 {
    484 /* if the constraint is deleted and the integral variable is present, it should be fixed */
    485 assert(SCIPisEQ(scip, SCIPvarGetLbGlobal((*consdata)->intvar), SCIPvarGetLbGlobal((*consdata)->intvar)));
    486
    487 /* We do not delete the integral variable, but leave the handling to SCIP, because it might happen that the
    488 integral variable is stored in some basis information somewhere. */
    489 SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->intvar) );
    490 }
    491
    492 SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, (*consdata)->varssize);
    493 SCIPfreeBlockMemory(scip, consdata);
    494
    495 return SCIP_OKAY;
    496}
    497
    498/** prints xor constraint to file stream */
    499static
    501 SCIP* scip, /**< SCIP data structure */
    502 SCIP_CONSDATA* consdata, /**< xor constraint data */
    503 FILE* file, /**< output file (or NULL for standard output) */
    504 SCIP_Bool endline /**< should an endline be set? */
    505 )
    506{
    507 assert(consdata != NULL);
    508
    509 /* start variable list */
    510 SCIPinfoMessage(scip, file, "xor(");
    511
    512 /* print variable list */
    513 SCIP_CALL( SCIPwriteVarsList(scip, file, consdata->vars, consdata->nvars, TRUE, ',') );
    514
    515 /* close variable list and write right hand side */
    516 SCIPinfoMessage(scip, file, ") = %u", consdata->rhs);
    517
    518 /* write integer variable if it exists */
    519 if( consdata->intvar != NULL )
    520 {
    521 SCIPinfoMessage(scip, file, " (intvar = ");
    522 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->intvar, TRUE) );
    523 SCIPinfoMessage(scip, file, ")");
    524 }
    525
    526 if( endline )
    527 SCIPinfoMessage(scip, file, "\n");
    528
    529 return SCIP_OKAY;
    530}
    531
    532/** sets intvar of an xor constraint */
    533static
    535 SCIP* scip, /**< SCIP data structure */
    536 SCIP_CONS* cons, /**< xor constraint */
    537 SCIP_VAR* var /**< variable to add to the constraint */
    538 )
    539{
    540 SCIP_CONSDATA* consdata;
    541 SCIP_Bool transformed;
    542
    543 assert(var != NULL);
    544
    545 consdata = SCIPconsGetData(cons);
    546 assert(consdata != NULL);
    547 assert(consdata->rows[0] == NULL);
    548
    549 /* are we in the transformed problem? */
    550 transformed = SCIPconsIsTransformed(cons);
    551
    552 /* always use transformed variables in transformed constraints */
    553 if( transformed )
    554 {
    555 SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
    556 }
    557 assert(var != NULL);
    558 assert(transformed == SCIPvarIsTransformed(var));
    559
    560 /* remove the rounding locks for the old variable and release it */
    561 if( consdata->intvar != NULL )
    562 {
    563 SCIP_CALL( unlockRounding(scip, cons, consdata->intvar) );
    564 SCIP_CALL( SCIPreleaseVar(scip, &(consdata->intvar)) );
    565 }
    566
    567 consdata->intvar = var;
    568 consdata->changed = TRUE;
    569
    570 /* install the rounding locks for the new variable and capture it */
    571 SCIP_CALL( lockRounding(scip, cons, consdata->intvar) );
    572 SCIP_CALL( SCIPcaptureVar(scip, consdata->intvar) );
    573
    574 /**@todo update LP rows */
    575 if( consdata->rows[0] != NULL )
    576 {
    577 SCIPerrorMessage("cannot change intvar of xor constraint after LP relaxation was created\n");
    578 return SCIP_INVALIDCALL;
    579 }
    580
    581 return SCIP_OKAY;
    582}
    583
    584/** adds coefficient to xor constraint */
    585static
    587 SCIP* scip, /**< SCIP data structure */
    588 SCIP_CONS* cons, /**< xor constraint */
    589 SCIP_VAR* var /**< variable to add to the constraint */
    590 )
    591{
    592 SCIP_CONSDATA* consdata;
    593 SCIP_Bool transformed;
    594
    595 assert(var != NULL);
    596
    597 consdata = SCIPconsGetData(cons);
    598 assert(consdata != NULL);
    599 assert(consdata->rows[0] == NULL);
    600
    601 /* are we in the transformed problem? */
    602 transformed = SCIPconsIsTransformed(cons);
    603
    604 /* always use transformed variables in transformed constraints */
    605 if( transformed )
    606 {
    607 SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
    608 }
    609 assert(var != NULL);
    610 assert(transformed == SCIPvarIsTransformed(var));
    611
    612 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
    613 consdata->vars[consdata->nvars] = var;
    614 consdata->nvars++;
    615 consdata->sorted = (consdata->nvars == 1);
    616 consdata->changed = TRUE;
    617
    618 /* install the rounding locks for the new variable */
    619 SCIP_CALL( lockRounding(scip, cons, var) );
    620
    621 /* we only catch this event in presolving stages
    622 * we need to catch this event also during exiting presolving because we call applyFixings to clean up the constraint
    623 * and this can lead to an insertion of a replacement of variables for which we will try to drop the VARFIXED event.
    624 */
    627 {
    628 SCIP_CONSHDLRDATA* conshdlrdata;
    629 SCIP_CONSHDLR* conshdlr;
    630
    632 assert(conshdlr != NULL);
    633 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    634 assert(conshdlrdata != NULL);
    635
    636 SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
    637 (SCIP_EVENTDATA*)consdata, NULL) );
    638 }
    639
    640 /**@todo update LP rows */
    641 if( consdata->rows[0] != NULL )
    642 {
    643 SCIPerrorMessage("cannot add coefficients to xor constraint after LP relaxation was created\n");
    644 return SCIP_INVALIDCALL;
    645 }
    646
    647 return SCIP_OKAY;
    648}
    649
    650/** deletes coefficient at given position from xor constraint data */
    651static
    653 SCIP* scip, /**< SCIP data structure */
    654 SCIP_CONS* cons, /**< xor constraint */
    655 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    656 int pos /**< position of coefficient to delete */
    657 )
    658{
    659 SCIP_CONSDATA* consdata;
    660
    661 assert(eventhdlr != NULL);
    662
    663 consdata = SCIPconsGetData(cons);
    664 assert(consdata != NULL);
    665 assert(0 <= pos && pos < consdata->nvars);
    666 assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(consdata->vars[pos]));
    667
    668 /* remove the rounding locks of the deleted variable */
    669 SCIP_CALL( unlockRounding(scip, cons, consdata->vars[pos]) );
    670
    671 /* we only catch this event in presolving stage, so we need to only drop it there */
    674 {
    675 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos], SCIP_EVENTTYPE_VARFIXED, eventhdlr,
    676 (SCIP_EVENTDATA*)consdata, -1) );
    677 }
    678
    679 if( SCIPconsIsTransformed(cons) )
    680 {
    681 /* if the position is watched, stop watching the position */
    682 if( consdata->watchedvar1 == pos )
    683 {
    684 SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar2, -1) );
    685 }
    686 if( consdata->watchedvar2 == pos )
    687 {
    688 SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar1, -1) );
    689 }
    690 }
    691 assert(pos != consdata->watchedvar1);
    692 assert(pos != consdata->watchedvar2);
    693
    694 /* move the last variable to the free slot */
    695 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
    696 consdata->nvars--;
    697
    698 /* if the last variable (that moved) was watched, update the watched position */
    699 if( consdata->watchedvar1 == consdata->nvars )
    700 consdata->watchedvar1 = pos;
    701 if( consdata->watchedvar2 == consdata->nvars )
    702 consdata->watchedvar2 = pos;
    703
    704 consdata->propagated = FALSE;
    705 consdata->sorted = FALSE;
    706 consdata->changed = TRUE;
    707
    708 return SCIP_OKAY;
    709}
    710
    711/** sorts and constraint's variables by non-decreasing variable index */
    712static
    714 SCIP_CONSDATA* consdata /**< constraint data */
    715 )
    716{
    717 assert(consdata != NULL);
    718
    719 if( !consdata->sorted )
    720 {
    721 if( consdata->nvars <= 1 )
    722 consdata->sorted = TRUE;
    723 else
    724 {
    725 SCIP_VAR* var1 = NULL;
    726 SCIP_VAR* var2 = NULL;
    727
    728 /* remember watch variables */
    729 if( consdata->watchedvar1 != -1 )
    730 {
    731 var1 = consdata->vars[consdata->watchedvar1];
    732 assert(var1 != NULL);
    733 consdata->watchedvar1 = -1;
    734 if( consdata->watchedvar2 != -1 )
    735 {
    736 var2 = consdata->vars[consdata->watchedvar2];
    737 assert(var2 != NULL);
    738 consdata->watchedvar2 = -1;
    739 }
    740 }
    741 assert(consdata->watchedvar1 == -1);
    742 assert(consdata->watchedvar2 == -1);
    743 assert(var1 != NULL || var2 == NULL);
    744
    745 /* sort variables after index */
    746 SCIPsortPtr((void**)consdata->vars, SCIPvarCompActiveAndNegated, consdata->nvars);
    747 consdata->sorted = TRUE;
    748
    749 /* correct watched variables */
    750 if( var1 != NULL )
    751 {
    752 int v;
    753
    754 /* since negated variables exist, we need to loop over all variables to find the old variable and cannot use
    755 * SCIPsortedvecFindPtr()
    756 */
    757 for( v = consdata->nvars - 1; v >= 0; --v )
    758 {
    759 if( consdata->vars[v] == var1 )
    760 {
    761 consdata->watchedvar1 = v;
    762 if( var2 == NULL || consdata->watchedvar2 != -1 )
    763 break;
    764 }
    765 else if( consdata->vars[v] == var2 )
    766 {
    767 assert(consdata->vars[v] != NULL);
    768 consdata->watchedvar2 = v;
    769 if( consdata->watchedvar1 != -1 )
    770 break;
    771 }
    772 }
    773 assert(consdata->watchedvar1 != -1);
    774 assert(consdata->watchedvar2 != -1 || var2 == NULL);
    775 assert(consdata->watchedvar1 < consdata->nvars);
    776 assert(consdata->watchedvar2 < consdata->nvars);
    777 }
    778 }
    779 }
    780
    781#ifdef SCIP_DEBUG
    782 /* check sorting */
    783 {
    784 int v;
    785
    786 for( v = 0; v < consdata->nvars; ++v )
    787 {
    788 assert(v == consdata->nvars-1 || SCIPvarCompareActiveAndNegated(consdata->vars[v], consdata->vars[v+1]) <= 0);
    789 }
    790 }
    791#endif
    792}
    793
    794
    795/** gets the key of the given element */
    796static
    797SCIP_DECL_HASHGETKEY(hashGetKeyXorcons)
    798{ /*lint --e{715}*/
    799 /* the key is the element itself */
    800 return elem;
    801}
    802
    803/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables */
    804static
    805SCIP_DECL_HASHKEYEQ(hashKeyEqXorcons)
    806{
    807 SCIP_CONSDATA* consdata1;
    808 SCIP_CONSDATA* consdata2;
    809 int i;
    810#ifndef NDEBUG
    811 SCIP* scip;
    812
    813 scip = (SCIP*)userptr;
    814 assert(scip != NULL);
    815#endif
    816
    817 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
    818 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
    819
    820 /* checks trivial case */
    821 if( consdata1->nvars != consdata2->nvars )
    822 return FALSE;
    823
    824 /* sorts the constraints */
    825 consdataSort(consdata1);
    826 consdataSort(consdata2);
    827 assert(consdata1->sorted);
    828 assert(consdata2->sorted);
    829
    830 for( i = 0; i < consdata1->nvars ; ++i )
    831 {
    832 /* tests if variables are equal */
    833 if( consdata1->vars[i] != consdata2->vars[i] )
    834 {
    835 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
    836 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
    837 return FALSE;
    838 }
    839 assert(SCIPvarCompareActiveAndNegated(consdata1->vars[i], consdata2->vars[i]) == 0);
    840 }
    841
    842 return TRUE;
    843}
    844
    845/** returns the hash value of the key */
    846static
    847SCIP_DECL_HASHKEYVAL(hashKeyValXorcons)
    848{ /*lint --e{715}*/
    849 SCIP_CONSDATA* consdata;
    850 int minidx;
    851 int mididx;
    852 int maxidx;
    853
    854 consdata = SCIPconsGetData((SCIP_CONS*)key);
    855 assert(consdata != NULL);
    856 assert(consdata->sorted);
    857 assert(consdata->nvars > 0);
    858
    859 /* only active, fixed or negated variables are allowed */
    860 assert(consdata->vars[0] != NULL);
    861 assert(consdata->vars[consdata->nvars / 2] != NULL);
    862 assert(consdata->vars[consdata->nvars - 1] != NULL);
    863 assert(SCIPvarIsActive(consdata->vars[0]) || SCIPvarGetStatus(consdata->vars[0]) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(consdata->vars[0]) == SCIP_VARSTATUS_FIXED);
    864 assert(SCIPvarIsActive(consdata->vars[consdata->nvars / 2]) || SCIPvarGetStatus(consdata->vars[consdata->nvars / 2]) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(consdata->vars[consdata->nvars / 2]) == SCIP_VARSTATUS_FIXED);
    865 assert(SCIPvarIsActive(consdata->vars[consdata->nvars - 1]) || SCIPvarGetStatus(consdata->vars[consdata->nvars - 1]) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(consdata->vars[consdata->nvars - 1]) == SCIP_VARSTATUS_FIXED);
    866
    867 minidx = SCIPvarGetIndex(consdata->vars[0]);
    868 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
    869 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
    870 /* note that for all indices it does not hold that they are sorted, because variables are sorted with
    871 * SCIPvarCompareActiveAndNegated (see var.c)
    872 */
    873
    874 return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
    875}
    876
    877/** deletes all fixed variables and all pairs of equal variables */
    878static
    880 SCIP* scip, /**< SCIP data structure */
    881 SCIP_CONS* cons, /**< xor constraint */
    882 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    883 int* nchgcoefs, /**< pointer to add up the number of changed coefficients */
    884 int* naggrvars, /**< pointer to add up the number of aggregated variables */
    885 int* naddconss, /**< pointer to add up the number of added constraints */
    886 SCIP_Bool* cutoff /**< whether a cutoff has been detected */
    887 )
    888{
    889 SCIP_VAR** intoffsetvars = NULL;
    890 SCIP_Real* intoffsetvals = NULL;
    891 SCIP_CONSDATA* consdata;
    892 int intoffsetnvars = 0;
    893 int intoffsetconst = 0;
    894 int v;
    895
    896 assert(nchgcoefs != NULL);
    897 consdata = SCIPconsGetData(cons);
    898 assert(consdata != NULL);
    899 assert(consdata->nvars == 0 || consdata->vars != NULL);
    900
    901 SCIPdebugMsg(scip, "before fixings: ");
    902 SCIPdebug( SCIP_CALL( consdataPrint(scip, consdata, NULL, TRUE) ) );
    903
    904 for( v = consdata->nvars - 1; v >= 0; --v )
    905 {
    906 SCIP_VAR* var;
    907
    908 var = consdata->vars[v];
    909 assert(SCIPvarIsBinary(var));
    910
    911 if( SCIPvarGetUbGlobal(var) < 0.5 )
    912 {
    913 assert(SCIPisEQ(scip, SCIPvarGetLbGlobal(var), 0.0));
    914 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    915 ++(*nchgcoefs);
    916 }
    917 else if( SCIPvarGetLbGlobal(var) > 0.5 )
    918 {
    919 assert(SCIPisEQ(scip, SCIPvarGetUbGlobal(var), 1.0));
    920 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    921 ++(*nchgcoefs);
    922 consdata->rhs = !consdata->rhs;
    923 if( consdata->rhs )
    924 ++intoffsetconst;
    925 }
    926 else
    927 {
    928 SCIP_VAR* repvar;
    929 SCIP_Bool negated;
    930
    931 /* get binary representative of variable */
    932 SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &repvar, &negated) );
    933
    934 /* check if the variable should be replaced with the representative */
    935 if( repvar != var )
    936 {
    937 /* delete old (aggregated) variable */
    938 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    939
    940 /* add representative instead */
    941 SCIP_CALL( addCoef(scip, cons, repvar) );
    942 }
    943 }
    944 }
    945
    946 /* sort the variables in the constraint */
    947 consdataSort(consdata);
    948 assert(consdata->sorted);
    949
    950 SCIPdebugMsg(scip, "after sort : ");
    951 SCIPdebug( SCIP_CALL( consdataPrint(scip, consdata, NULL, TRUE) ) );
    952
    953 if( consdata->intvar != NULL )
    954 {
    955 SCIP_CALL( SCIPallocBufferArray(scip, &intoffsetvars, consdata->nvars / 2 + 2) );
    956 SCIP_CALL( SCIPallocBufferArray(scip, &intoffsetvals, consdata->nvars / 2 + 2) );
    957 intoffsetvars[1] = consdata->intvar;
    958 intoffsetvals[1] = -1.0;
    959 intoffsetnvars = 2;
    960 }
    961
    962 /* delete pairs of equal or negated variables; scan backwards to not affect the order of the front variables */
    963 v = consdata->nvars - 2;
    964 while( v >= 0 )
    965 {
    966 if( consdata->vars[v] == consdata->vars[v + 1] ) /*lint !e679*/
    967 {
    968 /* delete both variables */
    969 SCIPdebugMsg(scip, "xor constraint <%s>: deleting pair of equal variables <%s>\n",
    970 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[v]));
    971 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v + 1) );
    972 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    973 *nchgcoefs += 2;
    974 if( consdata->intvar != NULL )
    975 {
    976 assert(intoffsetvars != NULL);
    977 assert(intoffsetvals != NULL);
    978 assert(intoffsetnvars >= 2);
    979 assert(intoffsetconst >= 0);
    980
    981 if( consdata->intvar == consdata->vars[v] )
    982 intoffsetvals[1] += 1.0;
    983 else if( intoffsetvars[intoffsetnvars - 1] == consdata->vars[v] )
    984 intoffsetvals[intoffsetnvars - 1] += 1.0;
    985 else
    986 {
    987 intoffsetvars[intoffsetnvars] = consdata->vars[v];
    988 intoffsetvals[intoffsetnvars] = 1.0;
    989 ++intoffsetnvars;
    990 }
    991 }
    992 --v;
    993 }
    994 else if( consdata->vars[v] == SCIPvarGetNegatedVar(consdata->vars[v + 1]) ) /*lint !e679*/
    995 {
    996 /* delete both variables and negate the rhs */
    997 SCIPdebugMsg(scip, "xor constraint <%s>: deleting pair of negated variables <%s> and <%s>\n",
    998 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[v]), SCIPvarGetName(consdata->vars[v+1])); /*lint !e679*/
    999 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v + 1) );
    1000 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    1001 *nchgcoefs += 2;
    1002 consdata->rhs = !consdata->rhs;
    1003 if( consdata->rhs )
    1004 ++intoffsetconst;
    1005 --v;
    1006 }
    1007 else
    1008 assert(SCIPvarGetProbvar(consdata->vars[v]) != SCIPvarGetProbvar(consdata->vars[v + 1])); /*lint !e679*/
    1009 --v;
    1010 }
    1011
    1012 /* if there is an offset of the integer variable y, it needs to be replaced by z with
    1013 * y = z + intoffsetsum and z in [max(lb_y - intoffsetmax, 0), ub_y - intoffsetmin]
    1014 */
    1015 if( consdata->intvar != NULL )
    1016 {
    1017 assert(intoffsetvars != NULL);
    1018 assert(intoffsetvals != NULL);
    1019 assert(intoffsetnvars >= 2);
    1020 assert(intoffsetconst >= 0);
    1021
    1022 if( intoffsetconst >= 1 || intoffsetvals[1] != -1.0 || intoffsetnvars > 2 ) /*lint !e777*/
    1023 {
    1024 SCIP_Real lb = -(double)intoffsetconst;
    1025 SCIP_Real ub = -(double)intoffsetconst;
    1026 SCIP_Bool aggregated;
    1027 SCIP_Bool infeasible = FALSE;
    1028 SCIP_Bool redundant = FALSE;
    1029 char varname[SCIP_MAXSTRLEN];
    1030
    1031 (void)SCIPsnprintf(varname, SCIP_MAXSTRLEN, "agg_%s", SCIPvarGetName(consdata->intvar));
    1032
    1033 if( intoffsetvals[1] < 0.0 )
    1034 {
    1035 lb -= intoffsetvals[1] * SCIPvarGetLbGlobal(consdata->intvar);
    1036 ub -= intoffsetvals[1] * SCIPvarGetUbGlobal(consdata->intvar);
    1037 }
    1038 else
    1039 {
    1040 lb -= intoffsetvals[1] * SCIPvarGetUbGlobal(consdata->intvar);
    1041 ub -= intoffsetvals[1] * SCIPvarGetLbGlobal(consdata->intvar);
    1042 }
    1043
    1044 for( v = 2; v < intoffsetnvars; ++v )
    1045 {
    1046 lb -= intoffsetvals[v] * SCIPvarGetUbGlobal(intoffsetvars[v]);
    1047 ub -= intoffsetvals[v] * SCIPvarGetLbGlobal(intoffsetvars[v]);
    1048 }
    1049
    1050 if( lb < 0.0 )
    1051 {
    1052 lb = 0.0;
    1053
    1054 if( ub < 0.0 )
    1055 ub = 0.0;
    1056 }
    1057
    1058 SCIP_CALL( SCIPcreateVarImpl(scip, intoffsetvars, varname, lb, ub, 0.0,
    1059 SCIPvarGetType(consdata->intvar), SCIPvarGetImplType(consdata->intvar),
    1060 SCIPvarIsInitial(consdata->intvar), SCIPvarIsRemovable(consdata->intvar),
    1061 NULL, NULL, NULL, NULL, NULL) );
    1062 intoffsetvals[0] = 1.0;
    1063 SCIP_CALL( SCIPaddVar(scip, intoffsetvars[0]) );
    1064
    1065 if( intoffsetnvars == 2 )
    1066 {
    1067 if( intoffsetvals[1] == 0.0 ) /*lint !e777*/
    1068 redundant = TRUE;
    1069 else
    1070 {
    1071 SCIP_CALL( SCIPaggregateVars(scip, intoffsetvars[1], intoffsetvars[0], -intoffsetvals[1], -intoffsetvals[0],
    1072 (double)intoffsetconst, &infeasible, &redundant, &aggregated) );
    1073
    1074 if( aggregated )
    1075 ++(*naggrvars);
    1076 }
    1077 assert(infeasible || redundant || SCIPdoNotAggr(scip));
    1078 }
    1079
    1080 if( infeasible )
    1081 *cutoff = TRUE;
    1082 else if( redundant )
    1083 {
    1084 SCIP_CALL( setIntvar(scip, cons, intoffsetvars[0]) );
    1085 }
    1086 else
    1087 {
    1088 SCIP_CONS* newcons;
    1089 char consname[SCIP_MAXSTRLEN];
    1090
    1091 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "agg_%s", SCIPconsGetName(cons));
    1092
    1093 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, intoffsetnvars, intoffsetvars, intoffsetvals,
    1094 -(double)intoffsetconst, -(double)intoffsetconst,
    1096 TRUE, TRUE, TRUE, /*SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons),*/
    1099 SCIP_CALL( SCIPaddCons(scip, newcons) );
    1100 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    1101 ++(*naddconss);
    1102
    1103 SCIP_CALL( setIntvar(scip, cons, intoffsetvars[0]) );
    1104 }
    1105
    1106 SCIP_CALL( SCIPreleaseVar(scip, intoffsetvars) );
    1107 }
    1108
    1109 SCIPfreeBufferArray(scip, &intoffsetvals);
    1110 SCIPfreeBufferArray(scip, &intoffsetvars);
    1111 }
    1112
    1113 SCIPdebugMsg(scip, "after fixings : ");
    1114 SCIPdebug( SCIP_CALL( consdataPrint(scip, consdata, NULL, TRUE) ) );
    1115
    1116 return SCIP_OKAY;
    1117}
    1118
    1119/** adds extended flow formulation
    1120 *
    1121 * The extended flow formulation is built as follows: Let \f$x_1, \dots, x_k\f$ be the variables contained in the given
    1122 * XOR constraint. We construct a two layered flow network. The upper layer is called the north layer and the lower is
    1123 * called the south layer. For each \f$x_i,\; i = 2, \ldots, k-1\f$, we add arcs that stay in the north and south layer
    1124 * (denoted by 'nn' and 'ss', respectively), as well as arcs that change the layers (denoted by 'ns' and 'sn'). For
    1125 * \f$x_1\f$, we only add two arcs from the source to the two layers. The source is located on the north layer. For
    1126 * \f$x_k\f$, we add two arcs connecting the two layers to the sink. Depending on the rhs of the constraint the sink is
    1127 * located on the north or south layer. A change in the layers corresponds to a parity change, i.e., the corresponding
    1128 * variable \f$x_i\f$ is 1 (and 0 otherwise).
    1129 */
    1130static
    1132 SCIP* scip, /**< SCIP data structure */
    1133 SCIP_CONS* cons, /**< constraint to check */
    1134 int* naggrvars, /**< pointer to add up the number of aggregated variables */
    1135 int* naddedconss /**< number of added constraints */
    1136 )
    1137{
    1138 char name[SCIP_MAXSTRLEN];
    1139 SCIP_CONSDATA* consdata;
    1140 SCIP_VAR* varprevnn = NULL;
    1141 SCIP_VAR* varprevns = NULL;
    1142 SCIP_VAR* varprevsn = NULL;
    1143 SCIP_VAR* varprevss = NULL;
    1144 SCIP_VAR* vars[4];
    1145 SCIP_Real vals[4];
    1146 int i;
    1147
    1148 assert(scip != NULL);
    1149 assert(cons != NULL);
    1150 assert(naddedconss != NULL);
    1151 *naddedconss = 0;
    1152
    1153 /* exit if contraints is modifiable */
    1154 if( SCIPconsIsModifiable(cons) )
    1155 return SCIP_OKAY;
    1156
    1157 consdata = SCIPconsGetData(cons);
    1158 assert(consdata != NULL);
    1159
    1160 /* exit if extended formulation has been added already */
    1161 if( consdata->extvars != NULL )
    1162 return SCIP_OKAY;
    1163
    1164 /* xor constraints with at most 3 variables are handled directly through rows for the convex hull */
    1165 if( consdata->nvars <= 3 )
    1166 return SCIP_OKAY;
    1167
    1168 SCIPdebugMsg(scip, "Add extended formulation for xor constraint <%s> ...\n", SCIPconsGetName(cons));
    1169 assert(consdata->extvars == NULL);
    1170 assert(consdata->nextvars == 0);
    1171 assert(consdata->extvarssize == 0);
    1172
    1173 /* get storage for auxiliary variables */
    1174 consdata->extvarssize = 4 * (consdata->nvars);
    1175 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(consdata->extvars), consdata->extvarssize) );
    1176
    1177 /* pass through components */
    1178 for( i = 0; i < consdata->nvars; ++i )
    1179 {
    1180 /* variables: n - north, s - south */
    1181 SCIP_VAR* varnn = NULL;
    1182 SCIP_VAR* varns = NULL;
    1183 SCIP_VAR* varsn = NULL;
    1184 SCIP_VAR* varss = NULL;
    1185 SCIP_CONS* newcons;
    1186 SCIP_Real rhs = 0.0;
    1187 SCIP_Bool infeasible = FALSE;
    1188 SCIP_Bool redundant = FALSE;
    1189 SCIP_Bool aggregated = FALSE;
    1190 int cnt = 0;
    1191
    1192 /* create variables */
    1193 if( i == 0 )
    1194 {
    1195 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_nn", SCIPconsGetName(cons), i);
    1196 SCIP_CALL( SCIPcreateVarImpl(scip, &varnn, name, 0.0, 1.0, 0.0,
    1198 NULL, NULL, NULL, NULL, NULL) );
    1199 SCIP_CALL( SCIPaddVar(scip, varnn) );
    1200
    1201 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_ns", SCIPconsGetName(cons), i);
    1202 SCIP_CALL( SCIPcreateVarImpl(scip, &varns, name, 0.0, 1.0, 0.0,
    1204 NULL, NULL, NULL, NULL, NULL) );
    1205 SCIP_CALL( SCIPaddVar(scip, varns) );
    1206
    1207 /* need to lock variables, because we aggregate them */
    1208 SCIP_CALL( SCIPlockVarCons(scip, varnn, cons, TRUE, TRUE) );
    1209 SCIP_CALL( SCIPlockVarCons(scip, varns, cons, TRUE, TRUE) );
    1210
    1211 /* aggregate ns variable with original variable */
    1212 SCIP_CALL( SCIPaggregateVars(scip, varns, consdata->vars[0], 1.0, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
    1213 assert(!infeasible);
    1214 assert(redundant);
    1215 assert(aggregated);
    1216 ++(*naggrvars);
    1217 }
    1218 else
    1219 {
    1220 if( i == consdata->nvars-1 )
    1221 {
    1222 if( consdata->rhs )
    1223 {
    1224 /* if the rhs is 1 (true) the flow goes to the bottom level */
    1225 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_ns", SCIPconsGetName(cons), i);
    1226 SCIP_CALL( SCIPcreateVarImpl(scip, &varns, name, 0.0, 1.0, 0.0,
    1228 NULL, NULL, NULL, NULL, NULL) );
    1229 SCIP_CALL( SCIPaddVar(scip, varns) );
    1230
    1231 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_ss", SCIPconsGetName(cons), i);
    1232 SCIP_CALL( SCIPcreateVarImpl(scip, &varss, name, 0.0, 1.0, 0.0,
    1234 NULL, NULL, NULL, NULL, NULL) );
    1235 SCIP_CALL( SCIPaddVar(scip, varss) );
    1236
    1237 /* need to lock variables, because we aggregate them */
    1238 SCIP_CALL( SCIPlockVarCons(scip, varns, cons, TRUE, TRUE) );
    1239 SCIP_CALL( SCIPlockVarCons(scip, varss, cons, TRUE, TRUE) );
    1240
    1241 /* aggregate ns variable with original variable */
    1242 SCIP_CALL( SCIPaggregateVars(scip, varns, consdata->vars[i], 1.0, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
    1243 assert(!infeasible);
    1244 assert(redundant);
    1245 assert(aggregated);
    1246 ++(*naggrvars);
    1247 }
    1248 else
    1249 {
    1250 /* if the rhs is 0 (false) the flow stays on the top level */
    1251 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_nn", SCIPconsGetName(cons), i);
    1252 SCIP_CALL( SCIPcreateVarImpl(scip, &varnn, name, 0.0, 1.0, 0.0,
    1254 NULL, NULL, NULL, NULL, NULL) );
    1255 SCIP_CALL( SCIPaddVar(scip, varnn) );
    1256
    1257 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_sn", SCIPconsGetName(cons), i);
    1258 SCIP_CALL( SCIPcreateVarImpl(scip, &varsn, name, 0.0, 1.0, 0.0,
    1260 NULL, NULL, NULL, NULL, NULL) );
    1261 SCIP_CALL( SCIPaddVar(scip, varsn) );
    1262
    1263 /* need to lock variables, because we aggregate them */
    1264 SCIP_CALL( SCIPlockVarCons(scip, varnn, cons, TRUE, TRUE) );
    1265 SCIP_CALL( SCIPlockVarCons(scip, varsn, cons, TRUE, TRUE) );
    1266
    1267 /* aggregate sn variable with original variable */
    1268 SCIP_CALL( SCIPaggregateVars(scip, varsn, consdata->vars[i], 1.0, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
    1269 assert(!infeasible);
    1270 assert(redundant);
    1271 assert(aggregated);
    1272 ++(*naggrvars);
    1273 }
    1274 }
    1275 else
    1276 {
    1277 /* add the four flow variables */
    1278 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_nn", SCIPconsGetName(cons), i);
    1279 SCIP_CALL( SCIPcreateVarImpl(scip, &varnn, name, 0.0, 1.0, 0.0,
    1281 NULL, NULL, NULL, NULL, NULL) );
    1282 SCIP_CALL( SCIPaddVar(scip, varnn) );
    1283
    1284 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_ns", SCIPconsGetName(cons), i);
    1285 SCIP_CALL( SCIPcreateVarImpl(scip, &varns, name, 0.0, 1.0, 0.0,
    1287 NULL, NULL, NULL, NULL, NULL) );
    1288 SCIP_CALL( SCIPaddVar(scip, varns) );
    1289
    1290 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_sn", SCIPconsGetName(cons), i);
    1291 SCIP_CALL( SCIPcreateVarImpl(scip, &varsn, name, 0.0, 1.0, 0.0,
    1293 NULL, NULL, NULL, NULL, NULL) );
    1294 SCIP_CALL( SCIPaddVar(scip, varsn) );
    1295
    1296 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_ss", SCIPconsGetName(cons), i);
    1297 SCIP_CALL( SCIPcreateVarImpl(scip, &varss, name, 0.0, 1.0, 0.0,
    1299 NULL, NULL, NULL, NULL, NULL) );
    1300 SCIP_CALL( SCIPaddVar(scip, varss) );
    1301
    1302 SCIP_CALL( SCIPlockVarCons(scip, varnn, cons, TRUE, TRUE) );
    1303 SCIP_CALL( SCIPlockVarCons(scip, varns, cons, TRUE, TRUE) );
    1304 SCIP_CALL( SCIPlockVarCons(scip, varsn, cons, TRUE, TRUE) );
    1305 SCIP_CALL( SCIPlockVarCons(scip, varss, cons, TRUE, TRUE) );
    1306
    1307 /* add coupling constraint */
    1308 cnt = 0;
    1309 if( varns != NULL )
    1310 {
    1311 vars[cnt] = varns;
    1312 vals[cnt++] = 1.0;
    1313 }
    1314 if( varsn != NULL )
    1315 {
    1316 vars[cnt] = varsn;
    1317 vals[cnt++] = 1.0;
    1318 }
    1319 assert(SCIPvarIsTransformed(consdata->vars[i]));
    1320 vars[cnt] = consdata->vars[i];
    1321 vals[cnt++] = -1.0;
    1322
    1323 assert(cnt >= 2);
    1324 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_couple", SCIPconsGetName(cons));
    1325 /* not initial, separate, do not enforce, do not check, propagate, not local, not modifiable, dynamic, removable, not sticking */
    1326 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, cnt, vars, vals, 0.0, 0.0,
    1328 SCIP_CALL( SCIPaddCons(scip, newcons) );
    1329 SCIPdebugPrintCons(scip, newcons, NULL);
    1330 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    1331 ++(*naddedconss);
    1332 }
    1333
    1334 /* add south flow conservation constraint */
    1335
    1336 /* incoming variables */
    1337 cnt = 0;
    1338 if( varprevss != NULL )
    1339 {
    1340 vars[cnt] = varprevss;
    1341 vals[cnt++] = 1.0;
    1342 }
    1343 if( varprevns != NULL )
    1344 {
    1345 vars[cnt] = varprevns;
    1346 vals[cnt++] = 1.0;
    1347 }
    1348
    1349 /* outgoing variables */
    1350 if( varss != NULL )
    1351 {
    1352 vars[cnt] = varss;
    1353 vals[cnt++] = -1.0;
    1354 }
    1355 if( varsn != NULL )
    1356 {
    1357 vars[cnt] = varsn;
    1358 vals[cnt++] = -1.0;
    1359 }
    1360
    1361 assert(cnt >= 2);
    1362 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_south", SCIPconsGetName(cons));
    1363 /* not initial, separate, do not enforce, do not check, propagate, not local, not modifiable, dynamic, removable, not sticking */
    1364 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, cnt, vars, vals, 0.0, 0.0,
    1366 SCIP_CALL( SCIPaddCons(scip, newcons) );
    1367 SCIPdebugPrintCons(scip, newcons, NULL);
    1368 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    1369 ++(*naddedconss);
    1370 }
    1371
    1372 /* add north flow conservation constraint */
    1373
    1374 /* incoming variables */
    1375 cnt = 0;
    1376 if( varprevnn != NULL )
    1377 {
    1378 vars[cnt] = varprevnn;
    1379 vals[cnt++] = 1.0;
    1380 }
    1381 if( varprevsn != NULL )
    1382 {
    1383 vars[cnt] = varprevsn;
    1384 vals[cnt++] = 1.0;
    1385 }
    1386
    1387 /* outgoing variables */
    1388 if( varnn != NULL )
    1389 {
    1390 vars[cnt] = varnn;
    1391 vals[cnt++] = -1.0;
    1392 }
    1393 if( varns != NULL )
    1394 {
    1395 vars[cnt] = varns;
    1396 vals[cnt++] = -1.0;
    1397 }
    1398
    1399 assert(cnt >= 2);
    1400 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_north", SCIPconsGetName(cons));
    1401 if( i == 0 )
    1402 rhs = -1.0;
    1403 else
    1404 rhs = 0.0;
    1405
    1406 /* not initial, separate, do not enforce, do not check, propagate, not local, not modifiable, dynamic, removable, not sticking */
    1407 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, cnt, vars, vals, rhs, rhs,
    1409 SCIP_CALL( SCIPaddCons(scip, newcons) );
    1410 SCIPdebugPrintCons(scip, newcons, NULL);
    1411 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    1412 ++(*naddedconss);
    1413
    1414 /* store variables */
    1415 consdata->extvars[4*i] = varnn; /*lint !e679*/
    1416 consdata->extvars[4*i + 1] = varns; /*lint !e679*/
    1417 consdata->extvars[4*i + 2] = varsn; /*lint !e679*/
    1418 consdata->extvars[4*i + 3] = varss; /*lint !e679*/
    1419
    1420 if( varnn != NULL )
    1421 ++(consdata->nextvars);
    1422 if( varns != NULL )
    1423 ++(consdata->nextvars);
    1424 if( varsn != NULL )
    1425 ++(consdata->nextvars);
    1426 if( varss != NULL )
    1427 ++(consdata->nextvars);
    1428
    1429 /* store previous variables */
    1430 varprevnn = varnn;
    1431 varprevns = varns;
    1432 varprevsn = varsn;
    1433 varprevss = varss;
    1434 }
    1435
    1436 return SCIP_OKAY;
    1437}
    1438
    1439/** adds extended asymmetric formulation
    1440 *
    1441 * The extended asymmetric formulation is constructed as follows: Let \f$x_1, \dots, x_k\f$ be the variables contained
    1442 * in the given XOR constraint. We introduce variables \f$p_1, \ldots, p_k\f$ with the following constraints: \f$p_1 =
    1443 * x_1\f$, \f$p_k = 1\f$, and for \f$i = 2, \ldots, k-1\f$:
    1444 * \f[
    1445 * \begin{array}{ll}
    1446 * p_i & \leq p_{i-1} + x_i\\
    1447 * p_i & \leq 2 - (p_{i-1} + x_i)\\
    1448 * p_i & \geq p_{i-1} - x_i\\
    1449 * p_i & \geq x_i - p_{i-1}.
    1450 * \end{array}
    1451 * \f]
    1452 * This formulation is described in
    1453 *
    1454 * Robert D. Carr and Goran Konjevod@n
    1455 * Polyhedral combinatorics@n
    1456 * In Harvey Greenberg, editor, Tutorials on emerging methodologies and applications in Operations Research,@n
    1457 * Chapter 2, pages (2-1)-(2-48). Springer, 2004.
    1458 */
    1459static
    1461 SCIP* scip, /**< SCIP data structure */
    1462 SCIP_CONS* cons, /**< constraint to check */
    1463 int* naggrvars, /**< pointer to add up the number of aggregated variables */
    1464 int* naddedconss /**< number of added constraints */
    1465 )
    1466{
    1467 char name[SCIP_MAXSTRLEN];
    1468 SCIP_CONSDATA* consdata;
    1469 SCIP_VAR* vars[3];
    1470 SCIP_Real vals[3];
    1471 SCIP_VAR* prevvar = NULL;
    1472 int i;
    1473
    1474 assert(scip != NULL);
    1475 assert(cons != NULL);
    1476 assert(naddedconss != NULL);
    1477 *naddedconss = 0;
    1478
    1479 /* exit if contraints is modifiable */
    1480 if( SCIPconsIsModifiable(cons) )
    1481 return SCIP_OKAY;
    1482
    1483 consdata = SCIPconsGetData(cons);
    1484 assert(consdata != NULL);
    1485
    1486 /* exit if extended formulation has been added already */
    1487 if( consdata->extvars != NULL )
    1488 return SCIP_OKAY;
    1489
    1490 /* xor constraints with at most 3 variables are handled directly through rows for the convex hull */
    1491 if( consdata->nvars <= 3 )
    1492 return SCIP_OKAY;
    1493
    1494 SCIPdebugMsg(scip, "Add extended formulation for xor constraint <%s> ...\n", SCIPconsGetName(cons));
    1495 assert(consdata->extvars == NULL);
    1496 assert(consdata->nextvars == 0);
    1497
    1498 /* get storage for auxiliary variables */
    1499 consdata->extvarssize = consdata->nvars;
    1500 consdata->nextvars = consdata->nvars;
    1501 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(consdata->extvars), consdata->extvarssize ) );
    1502
    1503 /* pass through components */
    1504 for( i = 0; i < consdata->nvars; ++i )
    1505 {
    1506 SCIP_Bool infeasible = FALSE;
    1507 SCIP_Bool redundant = FALSE;
    1508 SCIP_Bool aggregated = FALSE;
    1509 SCIP_CONS* newcons;
    1510 SCIP_VAR* artvar = NULL;
    1511 SCIP_Real lb = 0.0;
    1512 SCIP_Real ub = 1.0;
    1513
    1514 /* determine fixing for last variables */
    1515 if( i == consdata->nvars-1 )
    1516 {
    1517 if( consdata->rhs )
    1518 {
    1519 lb = 1.0;
    1520 ub = 1.0;
    1521 }
    1522 else
    1523 {
    1524 lb = 0.0;
    1525 ub = 0.0;
    1526 }
    1527 }
    1528
    1529 /* create variable */
    1530 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "p_%s_%d", SCIPconsGetName(cons), i);
    1531 SCIP_CALL( SCIPcreateVarImpl(scip, &artvar, name, lb, ub, 0.0,
    1533 NULL, NULL, NULL, NULL, NULL) );
    1534 SCIP_CALL( SCIPaddVar(scip, artvar) );
    1535 SCIP_CALL( SCIPlockVarCons(scip, artvar, cons, TRUE, TRUE) );
    1536
    1537 /* create constraints */
    1538 if( i == 0 )
    1539 {
    1540 /* aggregate artificial variable with original variable */
    1541 SCIP_CALL( SCIPaggregateVars(scip, artvar, consdata->vars[0], 1.0, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
    1542 assert(!infeasible);
    1543 assert(redundant);
    1544 assert(aggregated);
    1545 ++(*naggrvars);
    1546 }
    1547 else
    1548 {
    1549 assert(SCIPvarIsTransformed(consdata->vars[i]));
    1550
    1551 /* add first constraint */
    1552 vars[0] = artvar;
    1553 vals[0] = 1.0;
    1554 vars[1] = prevvar;
    1555 vals[1] = -1.0;
    1556 vars[2] = consdata->vars[i];
    1557 vals[2] = -1.0;
    1558
    1559 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_1", SCIPconsGetName(cons), i);
    1560 /* not initial, separate, do not enforce, do not check, propagate, not local, not modifiable, dynamic, removable, not sticking */
    1561 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, 3, vars, vals, -SCIPinfinity(scip), 0.0,
    1563 SCIP_CALL( SCIPaddCons(scip, newcons) );
    1564 SCIPdebugPrintCons(scip, newcons, NULL);
    1565 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    1566 ++(*naddedconss);
    1567
    1568 /* add second constraint */
    1569 vars[0] = artvar;
    1570 vals[0] = 1.0;
    1571 vars[1] = prevvar;
    1572 vals[1] = 1.0;
    1573 vars[2] = consdata->vars[i];
    1574 vals[2] = 1.0;
    1575
    1576 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_2", SCIPconsGetName(cons), i);
    1577 /* not initial, separate, do not enforce, do not check, propagate, not local, not modifiable, dynamic, removable, not sticking */
    1578 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, 3, vars, vals, -SCIPinfinity(scip), 2.0,
    1580 SCIP_CALL( SCIPaddCons(scip, newcons) );
    1581 SCIPdebugPrintCons(scip, newcons, NULL);
    1582 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    1583 ++(*naddedconss);
    1584
    1585 /* add third constraint */
    1586 vars[0] = artvar;
    1587 vals[0] = -1.0;
    1588 vars[1] = prevvar;
    1589 vals[1] = 1.0;
    1590 vars[2] = consdata->vars[i];
    1591 vals[2] = -1.0;
    1592
    1593 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_3", SCIPconsGetName(cons), i);
    1594 /* not initial, separate, do not enforce, do not check, propagate, not local, not modifiable, dynamic, removable, not sticking */
    1595 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, 3, vars, vals, -SCIPinfinity(scip), 0.0,
    1597 SCIP_CALL( SCIPaddCons(scip, newcons) );
    1598 SCIPdebugPrintCons(scip, newcons, NULL);
    1599 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    1600 ++(*naddedconss);
    1601
    1602 /* add fourth constraint */
    1603 vars[0] = artvar;
    1604 vals[0] = -1.0;
    1605 vars[1] = prevvar;
    1606 vals[1] = -1.0;
    1607 vars[2] = consdata->vars[i];
    1608 vals[2] = 1.0;
    1609
    1610 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_4", SCIPconsGetName(cons), i);
    1611 /* not initial, separate, do not enforce, do not check, propagate, not local, not modifiable, dynamic, removable, not sticking */
    1612 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, 3, vars, vals, -SCIPinfinity(scip), 0.0,
    1614 SCIP_CALL( SCIPaddCons(scip, newcons) );
    1615 SCIPdebugPrintCons(scip, newcons, NULL);
    1616 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    1617 ++(*naddedconss);
    1618 }
    1619
    1620 /* store variable */
    1621 consdata->extvars[i] = artvar;
    1622 prevvar = artvar;
    1623 }
    1624
    1625 return SCIP_OKAY;
    1626}
    1627
    1628/** creates LP row corresponding to xor constraint:
    1629 * x1 + ... + xn - 2q == rhs
    1630 * with internal integer variable q;
    1631 * in the special case of 3 variables and c = 0, the following linear system is created:
    1632 * + x - y - z <= 0
    1633 * - x + y - z <= 0
    1634 * - x - y + z <= 0
    1635 * + x + y + z <= 2
    1636 * in the special case of 3 variables and c = 1, the following linear system is created:
    1637 * - x + y + z <= 1
    1638 * + x - y + z <= 1
    1639 * + x + y - z <= 1
    1640 * - x - y - z <= -1
    1641 */
    1642static
    1644 SCIP* scip, /**< SCIP data structure */
    1645 SCIP_CONS* cons /**< constraint to check */
    1646 )
    1647{
    1648 SCIP_CONSDATA* consdata;
    1649 char varname[SCIP_MAXSTRLEN];
    1650
    1651 consdata = SCIPconsGetData(cons);
    1652 assert(consdata != NULL);
    1653 assert(consdata->rows[0] == NULL);
    1654
    1655 if( SCIPconsIsModifiable(cons) || consdata->nvars != 3 )
    1656 {
    1657 SCIP_Real rhsval;
    1658
    1659 /* create internal variable, if not yet existing */
    1660 if( consdata->intvar == NULL )
    1661 {
    1662 int ub;
    1663
    1664 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "XOR_artificial_%s_int", SCIPconsGetName(cons));
    1665 ub = consdata->nvars/2;
    1666 SCIP_CALL( SCIPcreateVar(scip, &consdata->intvar, varname, 0.0, (SCIP_Real)ub, 0.0,
    1667 consdata->nvars >= 4 ? SCIP_VARTYPE_INTEGER : SCIP_VARTYPE_BINARY,
    1669 SCIP_CALL( SCIPaddVar(scip, consdata->intvar) );
    1670
    1671#ifdef WITH_DEBUG_SOLUTION
    1672 if( SCIPdebugIsMainscip(scip) )
    1673 {
    1674 SCIP_Real solval;
    1675 int count = 0;
    1676 int v;
    1677
    1678 for( v = consdata->nvars - 1; v >= 0; --v )
    1679 {
    1680 SCIP_CALL( SCIPdebugGetSolVal(scip, consdata->vars[v], &solval) );
    1681 count += (solval > 0.5 ? 1 : 0);
    1682 }
    1683 assert((count - consdata->rhs) % 2 == 0);
    1684 solval = (SCIP_Real) ((count - consdata->rhs) / 2);
    1685
    1686 /* store debug sol value of artificial integer variable */
    1687 SCIP_CALL( SCIPdebugAddSolVal(scip, consdata->intvar, solval) );
    1688 }
    1689#endif
    1690
    1691 /* install the rounding locks for the internal variable */
    1692 SCIP_CALL( lockRounding(scip, cons, consdata->intvar) );
    1693 }
    1694
    1695 /* create LP row */
    1696 rhsval = (consdata->rhs ? 1.0 : 0.0);
    1697 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[0], cons, SCIPconsGetName(cons), rhsval, rhsval,
    1699 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[0], consdata->intvar, -2.0) );
    1700 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->rows[0], consdata->nvars, consdata->vars, 1.0) );
    1701 }
    1702 else if( !consdata->rhs )
    1703 {
    1704 char rowname[SCIP_MAXSTRLEN];
    1705 int r;
    1706
    1707 /* create the <= 0 rows with one positive sign */
    1708 for( r = 0; r < 3; ++r )
    1709 {
    1710 int v;
    1711
    1712 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), r);
    1713 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[r], cons, rowname, -SCIPinfinity(scip), 0.0,
    1715 for( v = 0; v < 3; ++v )
    1716 {
    1717 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[r], consdata->vars[v], v == r ? +1.0 : -1.0) );
    1718 }
    1719 }
    1720
    1721 /* create the <= 2 row with all positive signs */
    1722 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_3", SCIPconsGetName(cons));
    1723 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[3], cons, rowname, -SCIPinfinity(scip), 2.0,
    1725 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->rows[3], consdata->nvars, consdata->vars, 1.0) );
    1726
    1727 /* create extra LP row if integer variable exists */
    1728 if( consdata->intvar != NULL )
    1729 {
    1730 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[4], cons, SCIPconsGetName(cons), 0.0, 0.0,
    1732 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[4], consdata->intvar, -2.0) );
    1733 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->rows[4], consdata->nvars, consdata->vars, 1.0) );
    1734 }
    1735 }
    1736 else
    1737 {
    1738 char rowname[SCIP_MAXSTRLEN];
    1739 int r;
    1740
    1741 /* create the <= 1 rows with one negative sign */
    1742 for( r = 0; r < 3; ++r )
    1743 {
    1744 int v;
    1745
    1746 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), r);
    1747 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[r], cons, rowname, -SCIPinfinity(scip), 1.0,
    1749 for( v = 0; v < 3; ++v )
    1750 {
    1751 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[r], consdata->vars[v], v == r ? -1.0 : +1.0) );
    1752 }
    1753 }
    1754
    1755 /* create the <= -1 row with all negative signs */
    1756 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_3", SCIPconsGetName(cons));
    1757 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[3], cons, rowname, -SCIPinfinity(scip), -1.0,
    1759 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->rows[3], consdata->nvars, consdata->vars, -1.0) );
    1760
    1761 /* create extra LP row if integer variable exists */
    1762 if( consdata->intvar != NULL )
    1763 {
    1764 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[4], cons, SCIPconsGetName(cons), 1.0, 1.0,
    1766 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[4], consdata->intvar, -2.0) );
    1767 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->rows[4], consdata->nvars, consdata->vars, 1.0) );
    1768 }
    1769 }
    1770
    1771 return SCIP_OKAY;
    1772}
    1773
    1774/** adds linear relaxation of or constraint to the LP */
    1775static
    1777 SCIP* scip, /**< SCIP data structure */
    1778 SCIP_CONS* cons, /**< constraint to check */
    1779 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
    1780 )
    1781{
    1782 SCIP_CONSDATA* consdata;
    1783 int r;
    1784
    1785 consdata = SCIPconsGetData(cons);
    1786 assert(consdata != NULL);
    1787 assert(infeasible != NULL);
    1788 assert(!(*infeasible));
    1789
    1790 if( consdata->rows[0] == NULL )
    1791 {
    1793 }
    1794 assert(consdata->rows[0] != NULL);
    1795 for( r = 0; r < NROWS && !(*infeasible); ++r )
    1796 {
    1797 if( consdata->rows[r] != NULL && !SCIProwIsInLP(consdata->rows[r]) )
    1798 {
    1799 SCIP_CALL( SCIPaddRow(scip, consdata->rows[r], FALSE, infeasible) );
    1800 }
    1801 }
    1802
    1803 return SCIP_OKAY;
    1804}
    1805
    1806/** returns whether all rows of the LP relaxation are in the current LP */
    1807static
    1809 SCIP_CONSDATA* consdata /**< constraint data */
    1810 )
    1811{
    1812 assert(consdata != NULL);
    1813
    1814 if( consdata->rows[0] == NULL ) /* LP relaxation does not exist */
    1815 return FALSE;
    1816 else
    1817 {
    1818 int r;
    1819 for( r = 0; r < NROWS; ++r )
    1820 {
    1821 if( consdata->rows[r] != NULL && !SCIProwIsInLP(consdata->rows[r]) )
    1822 return FALSE;
    1823 }
    1824 return TRUE;
    1825 }
    1826}
    1827
    1828/** checks xor constraint for feasibility of given solution: returns TRUE iff constraint is feasible */
    1829static
    1831 SCIP* scip, /**< SCIP data structure */
    1832 SCIP_CONS* cons, /**< constraint to check */
    1833 SCIP_SOL* sol, /**< solution to check, NULL for current solution */
    1834 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
    1835 SCIP_Bool printreason, /**< Should the reason for the violation be printed? */
    1836 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
    1837 )
    1838{
    1839 SCIP_CONSDATA* consdata;
    1840
    1841 assert(violated != NULL);
    1842
    1843 consdata = SCIPconsGetData(cons);
    1844 assert(consdata != NULL);
    1845
    1846 *violated = FALSE;
    1847
    1848 /* check feasibility of constraint if necessary */
    1849 if( checklprows || !allRowsInLP(consdata) )
    1850 {
    1851 SCIP_Real maxcenval = 0.0;
    1852 SCIP_Real sumcenval = 0.0;
    1853 SCIP_Real sumsolval = 0.0;
    1854 SCIP_Real cenval;
    1855 SCIP_Real solval;
    1856 SCIP_Real viol;
    1857 SCIP_Bool odd = consdata->rhs;
    1858 int ones = 0;
    1859 int i;
    1860
    1861 /* increase age of constraint; age is reset to zero, if a violation was found only in case we are in
    1862 * enforcement
    1863 */
    1864 if( sol == NULL )
    1865 {
    1866 SCIP_CALL( SCIPincConsAge(scip, cons) );
    1867 }
    1868
    1869 /* evaluate operator variables */
    1870 for( i = 0; i < consdata->nvars; ++i )
    1871 {
    1872 solval = SCIPgetSolVal(scip, sol, consdata->vars[i]);
    1873
    1874 if( solval > 0.5 )
    1875 {
    1876 odd = !odd;
    1877 ++ones;
    1878 cenval = 1.0 - solval;
    1879 }
    1880 else
    1881 cenval = solval;
    1882
    1883 if( maxcenval < cenval )
    1884 maxcenval = cenval;
    1885
    1886 sumcenval += cenval;
    1887 sumsolval += solval;
    1888 }
    1889
    1890 /* the center value sum is the additive distance to the nearest integral solution infeasible if odd
    1891 * and otherwise the additive distance to the next nearest integral solution infeasible must be at least one
    1892 * see separateCons() for further intuition
    1893 */
    1894 viol = MAX(0.0, (odd ? 1.0 : 2.0 * maxcenval) - sumcenval);
    1895
    1896 /* additionally check linear feasibility of an existing integer variable */
    1897 if( consdata->intvar != NULL )
    1898 {
    1899 solval = REALABS(sumsolval - 2 * SCIPgetSolVal(scip, sol, consdata->intvar) - (SCIP_Real)consdata->rhs);
    1900
    1901 if( viol < solval )
    1902 viol = solval;
    1903 }
    1904
    1905 if( SCIPisFeasPositive(scip, viol) )
    1906 {
    1907 *violated = TRUE;
    1908
    1909 /* only reset constraint age if we are in enforcement */
    1910 if( sol == NULL )
    1911 {
    1913 }
    1914
    1915 if( printreason )
    1916 {
    1917 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
    1918 SCIPinfoMessage(scip, NULL, ";\n");
    1919 SCIPinfoMessage(scip, NULL, "violation: %d operands are set to TRUE ", ones);
    1920
    1921 if( consdata->intvar == NULL )
    1922 SCIPinfoMessage(scip, NULL, "and all sum up to %g\n", sumsolval);
    1923 else
    1924 SCIPinfoMessage(scip, NULL, "but integer variable is %g\n", SCIPgetSolVal(scip, sol, consdata->intvar));
    1925 }
    1926 }
    1927
    1928 /* update constraint violation in solution */
    1929 if( sol != NULL )
    1930 SCIPupdateSolConsViolation(scip, sol, viol, viol);
    1931 }
    1932
    1933 return SCIP_OKAY;
    1934}
    1935
    1936/** separates current LP solution
    1937 *
    1938 * Consider a XOR-constraint
    1939 * \f[
    1940 * x_1 \oplus x_2 \oplus \dots \oplus x_n = b
    1941 * \f]
    1942 * with \f$b \in \{0,1\}\f$ and a solution \f$x^*\f$ to be cut off. Small XOR constraints are handled by adding the
    1943 * inequalities of the convex hull.
    1944 *
    1945 * The separation of larger XOR constraints has been described by @n
    1946 * Xiaojie Zhang and Paul H. Siegel@n
    1947 * "Adaptive Cut Generation Algorithm for Improved Linear Programming Decoding of Binary Linear Codes"@n
    1948 * IEEE Transactions on Information Theory, vol. 58, no. 10, 2012
    1949 *
    1950 * We separate the inequalities
    1951 * \f[
    1952 * \sum_{j \in S} (1 - x_j) + \sum_{j \notin S} x_j \geq 1
    1953 * \f]
    1954 * with \f$|S| \equiv (b+1) \mbox{ mod } 2\f$ as follows. That these inequalities are valid can be seen as follows: Let
    1955 * \f$x\f$ be a feasible solution and suppose that the inequality is violated for some \f$S\f$. Then \f$x_j = 1\f$ for
    1956 * all \f$j \in S\f$ and \f$x_j = 0\f$ for all \f$j \notin S\f$. Thus we should have
    1957 * \f[
    1958 * \oplus_{j \in S} x_j = |S| \mbox{ mod } 2 = b+1 \mbox{ mod } 2,
    1959 * \f]
    1960 * which is not equal to \f$b\f$ as required by the XOR-constraint.
    1961 *
    1962 * Let \f$L= \{j \;:\; x^*_j > \frac{1}{2}\}\f$. Suppose that \f$|L|\f$ has @em not the same parity as \f$b\f$ rhs. Then
    1963 * \f[
    1964 * \sum_{j \in L} (1 - x_j) + \sum_{j \notin L} x_j \geq 1
    1965 * \f]
    1966 * is the only inequality that can be violated. We rewrite the inequality as
    1967 * \f[
    1968 * \sum_{j \in L} x_j - \sum_{j \notin L} x_j \leq |L| - 1.
    1969 * \f]
    1970 * These inequalities are added.
    1971 *
    1972 * Otherwise let \f$k = \mbox{argmin}\{x^*_j \;:\; j \in L\}\f$ and check the inequality for \f$L \setminus \{k\}\f$
    1973 * and similarly for \f$k = \mbox{argmax}\{x^*_j \;:\; j \in L\}\f$.
    1974 */
    1975static
    1977 SCIP* scip, /**< SCIP data structure */
    1978 SCIP_CONS* cons, /**< constraint to check */
    1979 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
    1980 SCIP_Bool separateparity, /**< should parity inequalities be separated? */
    1981 SCIP_Bool* separated, /**< pointer to store whether a cut was found */
    1982 SCIP_Bool* cutoff /**< whether a cutoff has been detected */
    1983 )
    1984{
    1985 SCIP_CONSDATA* consdata;
    1986 SCIP_Real feasibility;
    1987 int r;
    1988
    1989 assert(separated != NULL);
    1990 assert(cutoff != NULL);
    1991 *cutoff = FALSE;
    1992
    1993 consdata = SCIPconsGetData(cons);
    1994 assert(consdata != NULL);
    1995
    1996 *separated = FALSE;
    1997
    1998 /* create row for the linear relaxation */
    1999 if( consdata->rows[0] == NULL )
    2000 {
    2002 }
    2003 assert(consdata->rows[0] != NULL);
    2004
    2005 /* test rows for feasibility and add it, if it is infeasible */
    2006 for( r = 0; r < NROWS; ++r )
    2007 {
    2008 if( consdata->rows[r] != NULL && !SCIProwIsInLP(consdata->rows[r]) )
    2009 {
    2010 feasibility = SCIPgetRowSolFeasibility(scip, consdata->rows[r], sol);
    2011 if( SCIPisFeasNegative(scip, feasibility) )
    2012 {
    2013 SCIP_CALL( SCIPaddRow(scip, consdata->rows[r], FALSE, cutoff) );
    2014 if( *cutoff )
    2015 return SCIP_OKAY;
    2016 *separated = TRUE;
    2017 }
    2018 }
    2019 }
    2020
    2021 /* separate parity inequalities if required */
    2022 if( separateparity && consdata->nvars > 3 )
    2023 {
    2024 char name[SCIP_MAXSTRLEN];
    2025 SCIP_Real maxval = -1.0;
    2026 SCIP_Real minval = 2.0;
    2027 SCIP_Real sum = 0.0;
    2028 int maxidx = -1;
    2029 int minidx = -1;
    2030 int ngen = 0;
    2031 int cnt = 0;
    2032 int j;
    2033
    2034 SCIPdebugMsg(scip, "separating parity inequalities ...\n");
    2035
    2036 /* compute value */
    2037 for( j = 0; j < consdata->nvars; ++j )
    2038 {
    2039 SCIP_Real val;
    2040
    2041 val = SCIPgetSolVal(scip, sol, consdata->vars[j]);
    2042 if( val > 0.5 )
    2043 {
    2044 if( val < minval )
    2045 {
    2046 minval = val;
    2047 minidx = j;
    2048 }
    2049 ++cnt;
    2050 sum += (1.0 - val);
    2051 }
    2052 else
    2053 {
    2054 if( val > maxval )
    2055 {
    2056 maxval = val;
    2057 maxidx = j;
    2058 }
    2059 sum += val;
    2060 }
    2061 }
    2062
    2063 /* if size of set does not have the same parity as rhs (e.g., size is odd if rhs is 0) */
    2064 if( (cnt - (int) consdata->rhs) % 2 == 1 )
    2065 {
    2066 if( SCIPisEfficacious(scip, 1.0 - sum) )
    2067 {
    2068 SCIP_ROW* row;
    2069
    2070 SCIPdebugMsg(scip, "found violated parity cut (efficiacy: %f)\n", 1.0 - sum);
    2071
    2072 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "parity#%s", SCIPconsGetName(cons));
    2073 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, cons, name, -SCIPinfinity(scip), (SCIP_Real) (cnt - 1), FALSE, FALSE, TRUE) );
    2075
    2076 /* fill in row */
    2077 for( j = 0; j < consdata->nvars; ++j )
    2078 {
    2079 if( SCIPgetSolVal(scip, sol, consdata->vars[j]) > 0.5 )
    2080 {
    2081 SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], 1.0) );
    2082 }
    2083 else
    2084 {
    2085 SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], -1.0) );
    2086 }
    2087 }
    2090 SCIP_CALL( SCIPaddRow(scip, row, FALSE, cutoff) );
    2091 assert(SCIPisGT(scip, SCIPgetRowLPActivity(scip, row), (SCIP_Real) (cnt-1)));
    2092 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    2093 ++ngen;
    2094 }
    2095 }
    2096 else
    2097 {
    2098 /* If the parity is equal: check removing the element with smallest value from the set and adding the
    2099 * element with largest value to the set. If we remove the element with smallest value, we have to subtract (1
    2100 * - minval) and add minval to correct the sum. */
    2101 if( SCIPisEfficacious(scip, 1.0 - (sum - 1.0 + 2.0 * minval)) )
    2102 {
    2103 SCIP_ROW* row;
    2104
    2105 SCIPdebugMsg(scip, "found violated parity cut (efficiacy: %f, minval: %f)\n", 1.0 - (sum - 1.0 + 2.0 * minval), minval);
    2106
    2107 /* the rhs of the inequality is the corrected set size minus 1 */
    2108 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "parity#%s", SCIPconsGetName(cons));
    2109 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, cons, name, -SCIPinfinity(scip), (SCIP_Real) (cnt - 2), FALSE, FALSE, TRUE) );
    2111
    2112 /* fill in row */
    2113 for( j = 0; j < consdata->nvars; ++j )
    2114 {
    2115 if( SCIPgetSolVal(scip, sol, consdata->vars[j]) > 0.5 )
    2116 {
    2117 /* if the index corresponds to the smallest element, we reverse the sign */
    2118 if( j == minidx )
    2119 SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], -1.0) );
    2120 else
    2121 SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], 1.0) );
    2122 }
    2123 else
    2124 {
    2125 SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], -1.0) );
    2126 }
    2127 }
    2130 SCIP_CALL( SCIPaddRow(scip, row, FALSE, cutoff) );
    2131 assert(SCIPisGT(scip, SCIPgetRowLPActivity(scip, row), (SCIP_Real) (cnt-2)));
    2132 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    2133 ++ngen;
    2134 }
    2135
    2136 /* If we add the element with largest value, we have to add (1 - maxval) and subtract maxval to get the correct sum. */
    2137 if( SCIPisEfficacious(scip, 1.0 - (sum + 1.0 - 2.0 * maxval)) )
    2138 {
    2139 SCIP_ROW* row;
    2140
    2141 SCIPdebugMsg(scip, "found violated parity cut (efficiacy: %f, maxval: %f)\n", 1.0 - (sum + 1.0 - 2.0 * maxval), maxval);
    2142
    2143 /* the rhs of the inequality is the size of the corrected set */
    2144 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "parity#%s", SCIPconsGetName(cons));
    2145 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, cons, name, -SCIPinfinity(scip), (SCIP_Real) cnt, FALSE, FALSE, TRUE) );
    2147
    2148 /* fill in row */
    2149 for( j = 0; j < consdata->nvars; ++j )
    2150 {
    2151 if( SCIPgetSolVal(scip, sol, consdata->vars[j]) > 0.5 )
    2152 {
    2153 SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], 1.0) );
    2154 }
    2155 else
    2156 {
    2157 /* if the index corresponds to the largest element, we reverse the sign */
    2158 if( j == maxidx )
    2159 SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], 1.0) );
    2160 else
    2161 SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], -1.0) );
    2162 }
    2163 }
    2166 SCIP_CALL( SCIPaddRow(scip, row, FALSE, cutoff) );
    2167 assert(SCIPisGT(scip, SCIPgetRowLPActivity(scip, row), (SCIP_Real)cnt));
    2168 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    2169 ++ngen;
    2170 }
    2171 }
    2172
    2173 SCIPdebugMsg(scip, "separated parity inequalites: %d\n", ngen);
    2174 if( ngen > 0 )
    2175 *separated = TRUE;
    2176 }
    2177
    2178 return SCIP_OKAY;
    2179}
    2180
    2181/** Transform linear system \f$A x = b\f$ into row echelon form via the Gauss algorithm with row pivoting over GF2
    2182 * @returns the rank of @p A
    2183 *
    2184 * Here, \f$A \in R^{m \times n},\; b \in R^m\f$. On exit, the vector @p p contains a permutation of the row indices
    2185 * used for pivoting and the function returns the rank @p r of @p A. For each row \f$i = 1, \ldots, r\f$, the entry @p
    2186 * s[i] contains the column index of the first nonzero in row @p i.
    2187 */
    2188static
    2190 SCIP* scip, /**< SCIP data structure */
    2191 int m, /**< number of rows */
    2192 int n, /**< number of columns */
    2193 int* p, /**< row permutation */
    2194 int* s, /**< steps indicators of the row echelon form */
    2195 Type** A, /**< matrix */
    2196 Type* b /**< rhs */
    2197 )
    2198{
    2199 int pi;
    2200 int i;
    2201 int j;
    2202 int k;
    2203
    2204 assert(A != NULL);
    2205 assert(b != NULL);
    2206 assert(p != NULL);
    2207 assert(s != NULL);
    2208
    2209 /* init permutation and step indicators */
    2210 for( i = 0; i < m; ++i )
    2211 {
    2212 p[i] = i;
    2213 s[i] = i;
    2214 }
    2215
    2216 /* loop through possible steps in echelon form (stop at min {n, m}) */
    2217 for( i = 0; i < m && i < n; ++i )
    2218 {
    2219 assert(s[i] == i);
    2220
    2221 /* init starting column */
    2222 if( i == 0 )
    2223 j = 0;
    2224 else
    2225 j = s[i-1] + 1;
    2226
    2227 /* find pivot row (i.e., first nonzero entry), if all entries in current row are 0 we search the next column */
    2228 do
    2229 {
    2230 /* search in current column j */
    2231 k = i;
    2232 while( k < m && A[p[k]][j] == 0 )
    2233 ++k;
    2234
    2235 /* found pivot */
    2236 if( k < m )
    2237 break;
    2238
    2239 /* otherwise search next column */
    2240 ++j;
    2241 }
    2242 while( j < n );
    2243
    2244 /* if not pivot entry was found (checked all columns), the rank of A is equal to the current index i; in this case
    2245 * all entries in and below row i are 0 */
    2246 if( j >= n )
    2247 return i;
    2248
    2249 /* at this place: we have found a pivot entry (p[k], j) */
    2250 assert(k < m);
    2251
    2252 /* store step index */
    2253 s[i] = j;
    2254 assert(A[p[k]][j] != 0);
    2255
    2256 /* swap row indices */
    2257 if( k != i )
    2258 {
    2259 int h = p[i];
    2260 p[i] = p[k];
    2261 p[k] = h;
    2262 }
    2263 pi = p[i];
    2264 assert(A[pi][s[i]] != 0);
    2265
    2266 /* do elimination */
    2267 for( k = i+1; k < m; ++k )
    2268 {
    2269 int pk = p[k];
    2270 /* if entry in leading column is nonzero (otherwise we already have a 0) */
    2271 if( A[pk][s[i]] != 0 )
    2272 {
    2273 for( j = s[i]; j < n; ++j )
    2274 A[pk][j] = A[pk][j] ^ A[pi][j]; /*lint !e732*/
    2275 b[pk] = b[pk] ^ b[pi]; /*lint !e732*/
    2276 }
    2277 }
    2278
    2279 /* check stopped (only every 100 rows in order to save time */
    2280 if( i % 100 == 99 )
    2281 {
    2282 if( SCIPisStopped(scip) )
    2283 return -1;
    2284 }
    2285 }
    2286
    2287 /* at this point we have treated all rows in which a step can occur; the rank is the minimum of the number of rows or
    2288 * columns min {n,m}. */
    2289 if( n <= m )
    2290 return n;
    2291 return m;
    2292}
    2293
    2294/** Construct solution from matrix in row echelon form over GF2
    2295 *
    2296 * Compute solution of \f$A x = b\f$, which is already in row echelon form (@see computeRowEchelonGF2()) */
    2297static
    2299 int m, /**< number of rows */
    2300 int n, /**< number of columns */
    2301 int r, /**< rank of matrix */
    2302 int* p, /**< row permutation */
    2303 int* s, /**< steps indicators of the row echelon form */
    2304 Type** A, /**< matrix */
    2305 Type* b, /**< rhs */
    2306 Type* x /**< solution vector on exit */
    2307 )
    2308{
    2309 int i;
    2310 int k;
    2311
    2312 assert(A != NULL);
    2313 assert(b != NULL);
    2314 assert(s != NULL);
    2315 assert(p != NULL);
    2316 assert(x != NULL);
    2317 assert(r <= m && r <= n);
    2318
    2319 /* init solution vector to 0 */
    2320 for( k = 0; k < n; ++k )
    2321 x[k] = 0;
    2322
    2323 /* loop backwards through solution vector */
    2324 for( i = r-1; i >= 0; --i )
    2325 {
    2326 Type val;
    2327
    2328 assert(i <= s[i] && s[i] <= n);
    2329
    2330 /* init val with rhs and then add the contributions of the components of x already computed */
    2331 val = b[p[i]];
    2332 for( k = i+1; k < r; ++k )
    2333 {
    2334 assert(i <= s[k] && s[k] <= n);
    2335 if( A[p[i]][s[k]] != 0 )
    2336 val = val ^ x[s[k]]; /*lint !e732*/
    2337 }
    2338
    2339 /* store solution */
    2340 x[s[i]] = val;
    2341 }
    2342}
    2343
    2344/** solve equation system over GF 2 by Gauss algorithm and create solution out of it or return cutoff
    2345 *
    2346 * Collect all information in xor constraints into a linear system over GF2. Then solve the system by computing a row
    2347 * echelon form. If the system is infeasible, the current node is infeasible. Otherwise, we can compute a solution for
    2348 * the xor constraints given. We check whether this gives a solution for the whole problem.
    2349 *
    2350 * We sort the columns with respect to the product of the objective coefficients and 1 minus the current LP solution
    2351 * value. The idea is that columns that are likely to provide the steps in the row echelon form should appear towards
    2352 * the front of the matrix. The smaller the product, the more it makes sense to set the variable to 1 (because the
    2353 * solution value is already close to 1 and the objective function is small).
    2354 *
    2355 * Note that this function is called from propagation where usually no solution is available. However, the solution is
    2356 * only used for sorting the columns. Thus, the procedure stays correct even with nonsense solutions.
    2357 */
    2358static
    2360 SCIP* scip, /**< SCIP data structure */
    2361 SCIP_CONS** conss, /**< xor constraints */
    2362 int nconss, /**< number of xor constraints */
    2363 SCIP_SOL* currentsol, /**< current solution (maybe NULL) */
    2364 SCIP_RESULT* result /**< result of propagation (possibly cutoff, no change if primal solution has been tried) */
    2365 )
    2366{
    2367 SCIP_CONSDATA* consdata;
    2368 SCIP_HASHMAP* varhash;
    2369 SCIP_Bool* xoractive;
    2370 SCIP_Real* xorvals;
    2371 SCIP_VAR** xorvars;
    2372 SCIP_Bool noaggr = TRUE;
    2373 Type** A;
    2374 Type* b;
    2375 int* s;
    2376 int* p;
    2377 int* xoridx;
    2378 int* xorbackidx;
    2379 int nconssactive = 0;
    2380 int nconssmat = 0;
    2381 int nvarsmat = 0;
    2382 int nvars;
    2383 int rank;
    2384 int i;
    2385 int j;
    2386
    2387 assert(scip != NULL);
    2388 assert(conss != NULL);
    2389 assert(result != NULL);
    2390
    2391 if( *result == SCIP_CUTOFF )
    2392 return SCIP_OKAY;
    2393
    2394 SCIPdebugMsg(scip, "Checking feasibility via the linear equation system over GF2 using Gauss.\n");
    2395
    2396 nvars = SCIPgetNVars(scip);
    2397
    2398 /* set up hash map from variable to column index */
    2399 SCIP_CALL( SCIPhashmapCreate(&varhash, SCIPblkmem(scip), nvars) );
    2400 SCIP_CALL( SCIPallocBufferArray(scip, &xoractive, nconss) );
    2401 SCIP_CALL( SCIPallocBufferArray(scip, &xorvars, nvars) );
    2402 SCIP_CALL( SCIPallocBufferArray(scip, &xoridx, nvars) );
    2403 SCIP_CALL( SCIPallocBufferArray(scip, &xorvals, nvars) );
    2404
    2405 /* collect variables */
    2406 for( i = 0; i < nconss; ++i )
    2407 {
    2408 int cnt = 0;
    2409
    2410 xoractive[i] = FALSE;
    2411
    2412 assert(conss[i] != NULL);
    2413 consdata = SCIPconsGetData(conss[i]);
    2414 assert(consdata != NULL);
    2415
    2416 /* count nonfixed variables in constraint */
    2417 for( j = 0; j < consdata->nvars; ++j )
    2418 {
    2419 SCIP_VAR* var;
    2420
    2421 var = consdata->vars[j];
    2422 assert(var != NULL);
    2423 assert(SCIPvarIsBinary(var));
    2424
    2425 /* replace negated variables */
    2426 if( SCIPvarIsNegated(var) )
    2427 var = SCIPvarGetNegatedVar(var);
    2428 assert(var != NULL);
    2429
    2430 /* get the active variable */
    2431 while( var != NULL && SCIPvarGetStatus(var) == SCIP_VARSTATUS_AGGREGATED )
    2432 var = SCIPisEQ(scip, SCIPvarGetAggrScalar(var), 0.0) ? NULL : SCIPvarGetAggrVar(var);
    2433 /* consider nonfixed variables */
    2434 if( var != NULL && SCIPcomputeVarLbLocal(scip, var) < 0.5 && SCIPcomputeVarUbLocal(scip, var) > 0.5 )
    2435 {
    2436 /* consider active variables and collect only new ones */
    2437 if( SCIPvarIsActive(var) && !SCIPhashmapExists(varhash, var) )
    2438 {
    2439 /* add variable in map */
    2440 SCIP_CALL( SCIPhashmapInsertInt(varhash, var, nvarsmat) );
    2441 assert(nvarsmat == SCIPhashmapGetImageInt(varhash, var));
    2442 xorvals[nvarsmat] = SCIPvarGetObj(var) * (1.0 - SCIPgetSolVal(scip, currentsol, var));
    2443 xorvars[nvarsmat++] = var;
    2444 }
    2445 ++cnt;
    2446 }
    2447 }
    2448
    2449 if( cnt > 0 )
    2450 {
    2451 xoractive[i] = TRUE;
    2452 ++nconssactive;
    2453 }
    2454#ifdef SCIP_DISABLED_CODE
    2455 /* The following can save time, if there are constraints with all variables fixed that are infeasible; this
    2456 * should, however, be detected somewhere else, e.g., in propagateCons(). */
    2457 else
    2458 {
    2459 /* all variables are fixed - check whether constraint is feasible (could be that the constraint is not propagated) */
    2460 assert(cnt == 0);
    2461 for( j = 0; j < consdata->nvars; ++j )
    2462 {
    2463 /* count variables fixed to 1 */
    2464 if( SCIPcomputeVarLbLocal(scip, consdata->vars[j]) > 0.5 )
    2465 ++cnt;
    2466 else
    2467 assert(SCIPcomputeVarUbLocal(scip, consdata->vars[j]) < 0.5);
    2468 }
    2469 if( ( cnt - consdata->rhs ) % 2 != 0 )
    2470 {
    2471 SCIPdebugMsg(scip, "constraint <%s> with all variables fixed is violated.\n", SCIPconsGetName(conss[i]));
    2472 *result = SCIP_CUTOFF;
    2473 break;
    2474 }
    2475 }
    2476#endif
    2477 }
    2478 assert(nvarsmat <= nvars);
    2479 assert(nconssactive <= nconss);
    2480
    2481 if( nconssactive > MAXXORCONSSSYSTEM || nvarsmat > MAXXORVARSSYSTEM || *result == SCIP_CUTOFF )
    2482 {
    2483 SCIPdebugMsg(scip, "Skip checking the xor system over GF2 (%d conss, %d vars).\n", nconssactive, nvarsmat);
    2484 SCIPfreeBufferArray(scip, &xorvals);
    2485 SCIPfreeBufferArray(scip, &xoridx);
    2486 SCIPfreeBufferArray(scip, &xorvars);
    2487 SCIPfreeBufferArray(scip, &xoractive);
    2488 SCIPhashmapFree(&varhash);
    2489 return SCIP_OKAY;
    2490 }
    2491
    2492 /* init index */
    2493 for( j = 0; j < nvarsmat; ++j )
    2494 xoridx[j] = j;
    2495
    2496 /* Sort variables non-decreasingly with respect to product of objective and 1 minus the current solution value: the
    2497 * smaller the value the better it would be to set the variable to 1. This is more likely if the variable appears
    2498 * towards the front of the matrix, because only the entries on the steps in the row echelon form will have the
    2499 * chance to be nonzero.
    2500 */
    2501 SCIPsortRealIntPtr(xorvals, xoridx, (void**) xorvars, nvarsmat);
    2502 SCIPfreeBufferArray(scip, &xorvals);
    2503
    2504 /* build back index */
    2505 SCIP_CALL( SCIPallocBufferArray(scip, &xorbackidx, nvarsmat) );
    2506 for( j = 0; j < nvarsmat; ++j )
    2507 {
    2508 assert(0 <= xoridx[j] && xoridx[j] < nvarsmat);
    2509 xorbackidx[xoridx[j]] = j;
    2510 }
    2511
    2512 /* init matrix and rhs */
    2513 SCIP_CALL( SCIPallocBufferArray(scip, &b, nconssactive) );
    2514 SCIP_CALL( SCIPallocBufferArray(scip, &A, nconssactive) );
    2515 for( i = 0; i < nconss; ++i )
    2516 {
    2517 if( !xoractive[i] )
    2518 continue;
    2519
    2520 assert(conss[i] != NULL);
    2521 consdata = SCIPconsGetData(conss[i]);
    2522 assert(consdata != NULL);
    2523 assert(consdata->nvars > 0);
    2524
    2525 SCIP_CALL( SCIPallocBufferArray(scip, &(A[nconssmat]), nvarsmat) ); /*lint !e866*/
    2526 BMSclearMemoryArray(A[nconssmat], nvarsmat); /*lint !e866*/
    2527
    2528 /* correct rhs w.r.t. to fixed variables and count nonfixed variables in constraint */
    2529 b[nconssmat] = (Type) consdata->rhs;
    2530 for( j = 0; j < consdata->nvars; ++j )
    2531 {
    2532 SCIP_VAR* var;
    2533 int idx;
    2534
    2535 var = consdata->vars[j];
    2536 assert(var != NULL);
    2537
    2538 /* replace negated variables */
    2539 if( SCIPvarIsNegated(var) )
    2540 {
    2541 var = SCIPvarGetNegatedVar(var);
    2542 assert(var != NULL);
    2543 b[nconssmat] = !b[nconssmat];
    2544 }
    2545
    2546 /* replace aggregated variables */
    2548 {
    2549 SCIP_Real scalar;
    2550 SCIP_Real constant;
    2551
    2552 scalar = SCIPvarGetAggrScalar(var);
    2553 constant = SCIPvarGetAggrConstant(var);
    2554
    2555 /* the variable resolves to a constant, we just update the rhs */
    2556 if( SCIPisEQ(scip, scalar, 0.0) )
    2557 {
    2558 assert(SCIPisEQ(scip, constant, 0.0) || SCIPisEQ(scip, constant, 1.0));
    2559 if( SCIPisEQ(scip, constant, 1.0) )
    2560 b[nconssmat] = !b[nconssmat];
    2561 var = NULL;
    2562 break;
    2563 }
    2564 /* replace aggregated variable by active variable and update rhs, if needed */
    2565 else
    2566 {
    2567 assert(SCIPisEQ(scip, scalar, 1.0) || SCIPisEQ(scip, scalar, -1.0));
    2568 if( SCIPisEQ(scip, constant, 1.0) )
    2569 b[nconssmat] = !b[nconssmat];
    2570
    2571 var = SCIPvarGetAggrVar(var);
    2572 assert(var != NULL);
    2573 }
    2574 }
    2575 /* variable resolved to a constant */
    2576 if( var == NULL )
    2577 continue;
    2578
    2579 /* If the constraint contains multiaggregated variables, the solution might not be valid, since the
    2580 * implications are not represented in the matrix.
    2581 */
    2583 noaggr = FALSE;
    2584
    2585 if( SCIPcomputeVarLbLocal(scip, var) > 0.5 )
    2586 {
    2587 /* variable is fixed to 1, invert rhs */
    2588 b[nconssmat] = !b[nconssmat];
    2589 assert(!SCIPhashmapExists(varhash, var));
    2590 }
    2591 else
    2592 {
    2595 if( SCIPvarIsActive(var) && SCIPcomputeVarUbLocal(scip, var) > 0.5 )
    2596 {
    2597 assert(SCIPhashmapExists(varhash, var));
    2598 idx = SCIPhashmapGetImageInt(varhash, var);
    2599 assert(idx >= 0);
    2600 assert(idx < nvarsmat);
    2601 idx = xorbackidx[idx];
    2602 assert(idx >= 0);
    2603 assert(idx < nvarsmat);
    2604 A[nconssmat][idx] = !A[nconssmat][idx];
    2605 }
    2606 }
    2607 }
    2608 ++nconssmat;
    2609 }
    2610 SCIPdebugMsg(scip, "Found %d non-fixed variables in %d nonempty xor constraints.\n", nvarsmat, nconssmat);
    2611 assert(nconssmat == nconssactive);
    2612
    2613 /* perform Gauss algorithm */
    2614 SCIP_CALL( SCIPallocBufferArray(scip, &p, nconssmat) );
    2615 SCIP_CALL( SCIPallocBufferArray(scip, &s, nconssmat) );
    2616
    2617#ifdef SCIP_OUTPUT
    2618 SCIPinfoMessage(scip, NULL, "Matrix before Gauss (size: %d x %d):\n", nconssmat, nvarsmat);
    2619 for( i = 0; i < nconssmat; ++i )
    2620 {
    2621 for( j = 0; j < nvarsmat; ++j )
    2622 SCIPinfoMessage(scip, NULL, "%d ", A[i][j]);
    2623 SCIPinfoMessage(scip, NULL, " = %d\n", b[i]);
    2624 }
    2625 SCIPinfoMessage(scip, NULL, "\n");
    2626#endif
    2627
    2628 rank = -1;
    2629 if( !SCIPisStopped(scip) )
    2630 {
    2631 rank = computeRowEchelonGF2(scip, nconssmat, nvarsmat, p, s, A, b);
    2632 assert(rank <= nconssmat && rank <= nvarsmat);
    2633 }
    2634
    2635 /* rank is < 0 if the solution process has been stopped */
    2636 if( rank >= 0 )
    2637 {
    2638#ifdef SCIP_OUTPUT
    2639 SCIPinfoMessage(scip, NULL, "Matrix after Gauss (rank: %d):\n", rank);
    2640 for( i = 0; i < nconssmat; ++i )
    2641 {
    2642 for( j = 0; j < nvarsmat; ++j )
    2643 SCIPinfoMessage(scip, NULL, "%d ", A[p[i]][j]);
    2644 SCIPinfoMessage(scip, NULL, " = %d\n", b[p[i]]);
    2645 }
    2646 SCIPinfoMessage(scip, NULL, "\n");
    2647#endif
    2648
    2649 /* check whether system is feasible */
    2650 for( i = rank; i < nconssmat; ++i )
    2651 {
    2652 if( b[p[i]] != 0 )
    2653 break;
    2654 }
    2655
    2656 /* did not find nonzero entry in b -> equation system is feasible */
    2657 if( i >= nconssmat )
    2658 {
    2659 SCIPdebugMsg(scip, "System feasible with rank %d (nconss=%d)\n", rank, nconssmat);
    2660
    2661 /* matrix has full rank, solution is unique */
    2662 if( rank == nvarsmat && noaggr )
    2663 {
    2664 SCIP_Bool tightened;
    2665 SCIP_Bool infeasible;
    2666 Type* x;
    2667
    2668 SCIPdebugMsg(scip, "Found unique solution.\n");
    2669
    2670 /* construct solution */
    2671 SCIP_CALL( SCIPallocBufferArray(scip, &x, nvarsmat) );
    2672 solveRowEchelonGF2(nconssmat, nvarsmat, rank, p, s, A, b, x);
    2673
    2674#ifdef SCIP_OUTPUT
    2675 SCIPinfoMessage(scip, NULL, "Solution:\n");
    2676 for( j = 0; j < nvarsmat; ++j )
    2677 SCIPinfoMessage(scip, NULL, "%d ", x[j]);
    2678 SCIPinfoMessage(scip, NULL, "\n");
    2679#endif
    2680
    2681 /* fix variables according to computed unique solution */
    2682 for( j = 0; j < nvarsmat; ++j )
    2683 {
    2684 assert(SCIPhashmapGetImageInt(varhash, xorvars[j]) < nvars);
    2685 assert(xorbackidx[SCIPhashmapGetImageInt(varhash, xorvars[j])] == j);
    2686 assert(SCIPcomputeVarLbLocal(scip, xorvars[j]) < 0.5);
    2687 if( x[j] == 0 )
    2688 {
    2689 SCIP_CALL( SCIPtightenVarUb(scip, xorvars[j], 0.0, FALSE, &infeasible, &tightened) );
    2690 assert(tightened);
    2691 assert(!infeasible);
    2692 }
    2693 else
    2694 {
    2695 assert(x[j] == 1);
    2696 SCIP_CALL( SCIPtightenVarLb(scip, xorvars[j], 1.0, FALSE, &infeasible, &tightened) );
    2697 assert(tightened);
    2698 assert(!infeasible);
    2699 }
    2700 }
    2702 }
    2703 /* matrix does not have full rank, we add the solution, but cannot derive fixings */
    2704 else
    2705 {
    2706 SCIP_HEUR* heurtrysol;
    2707
    2708 SCIPdebugMsg(scip, "Found solution.\n");
    2709
    2710 /* try solution */
    2711 heurtrysol = SCIPfindHeur(scip, "trysol");
    2712
    2713 if( heurtrysol != NULL )
    2714 {
    2715 SCIP_Bool success;
    2716 SCIP_VAR** vars;
    2717 SCIP_SOL* sol;
    2718 Type* x;
    2719
    2720 /* construct solution */
    2721 SCIP_CALL( SCIPallocBufferArray(scip, &x, nvarsmat) );
    2722 solveRowEchelonGF2(nconssmat, nvarsmat, rank, p, s, A, b, x);
    2723
    2724#ifdef SCIP_OUTPUT
    2725 SCIPinfoMessage(scip, NULL, "Solution:\n");
    2726 for( j = 0; j < nvarsmat; ++j )
    2727 SCIPinfoMessage(scip, NULL, "%d ", x[j]);
    2728 SCIPinfoMessage(scip, NULL, "\n");
    2729#endif
    2730
    2731 /* create solution */
    2732 SCIP_CALL( SCIPcreateSol(scip, &sol, heurtrysol) );
    2733
    2734 /* transfer solution */
    2735 for( j = 0; j < nvarsmat; ++j )
    2736 {
    2737 if( x[j] != 0 )
    2738 {
    2739 assert(SCIPhashmapGetImageInt(varhash, xorvars[j]) < nvars);
    2740 assert(xorbackidx[SCIPhashmapGetImageInt(varhash, xorvars[j])] == j);
    2741 assert(SCIPcomputeVarLbLocal(scip, xorvars[j]) < 0.5);
    2742 SCIP_CALL( SCIPsetSolVal(scip, sol, xorvars[j], 1.0) );
    2743 }
    2744 }
    2746
    2747 /* add *all* variables fixed to 1 */
    2748 vars = SCIPgetVars(scip);
    2749 for( j = 0; j < nvars; ++j )
    2750 {
    2751 if( SCIPcomputeVarLbLocal(scip, vars[j]) > 0.5 )
    2752 {
    2753 SCIP_CALL( SCIPsetSolVal(scip, sol, vars[j], 1.0) );
    2754 SCIPdebugMsg(scip, "Added fixed variable <%s>.\n", SCIPvarGetName(vars[j]));
    2755 }
    2756 }
    2757
    2758 /* correct integral variables if necessary */
    2759 for( i = 0; i < nconss; ++i )
    2760 {
    2761 consdata = SCIPconsGetData(conss[i]);
    2762 assert(consdata != NULL);
    2763
    2764 /* only try for active constraints and integral variable; hope for the best if they are not active */
    2765 if( xoractive[i] && consdata->intvar != NULL && SCIPvarIsActive(consdata->intvar) )
    2766 {
    2767 SCIP_Real val;
    2768 int nones = 0;
    2769
    2770 for( j = 0; j < consdata->nvars; ++j )
    2771 {
    2772 if( SCIPgetSolVal(scip, sol, consdata->vars[j]) > 0.5 )
    2773 ++nones;
    2774 }
    2775 /* if there are aggregated variables, the solution might not be feasible */
    2776 assert(!noaggr || nones % 2 == (int) consdata->rhs);
    2777 if( (unsigned int) nones != consdata->rhs )
    2778 {
    2779 val = (SCIP_Real) (nones - (int) consdata->rhs)/2;
    2780 if( SCIPisGE(scip, val, SCIPvarGetLbGlobal(consdata->intvar)) && SCIPisLE(scip, val, SCIPvarGetUbGlobal(consdata->intvar)) )
    2781 {
    2782 SCIP_CALL( SCIPsetSolVal(scip, sol, consdata->intvar, val) );
    2783 }
    2784 }
    2785 }
    2786 }
    2788
    2789 /* check feasibility of new solution and pass it to trysol heuristic */
    2790 SCIP_CALL( SCIPcheckSol(scip, sol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
    2791 if( success )
    2792 {
    2793 SCIP_CALL( SCIPheurPassSolAddSol(scip, heurtrysol, sol) );
    2794 SCIPdebugMsg(scip, "Creating solution was successful.\n");
    2795 }
    2796#ifdef SCIP_DEBUG
    2797 else
    2798 {
    2799 /* the solution might not be feasible, because of additional constraints */
    2800 SCIPdebugMsg(scip, "Creating solution was not successful.\n");
    2801 }
    2802#endif
    2803 SCIP_CALL( SCIPfreeSol(scip, &sol) );
    2804 }
    2805 }
    2806 }
    2807 else
    2808 {
    2809 *result = SCIP_CUTOFF;
    2810 SCIPdebugMsg(scip, "System not feasible.\n");
    2811 }
    2812 }
    2813
    2814 /* free storage */
    2817 j = nconssmat - 1;
    2818 for( i = nconss - 1; i >= 0 ; --i )
    2819 {
    2820 consdata = SCIPconsGetData(conss[i]);
    2821 assert(consdata != NULL);
    2822
    2823 if( consdata->nvars == 0 )
    2824 continue;
    2825
    2826 if( !xoractive[i] )
    2827 continue;
    2828
    2829 SCIPfreeBufferArray(scip, &(A[j]));
    2830 --j;
    2831 }
    2834 SCIPfreeBufferArray(scip, &xorbackidx);
    2835 SCIPfreeBufferArray(scip, &xoridx);
    2836 SCIPfreeBufferArray(scip, &xorvars);
    2837 SCIPfreeBufferArray(scip, &xoractive);
    2838 SCIPhashmapFree(&varhash);
    2839
    2840 return SCIP_OKAY;
    2841}
    2842
    2843/** for each variable in the xor constraint, add it to conflict set; for integral variable add corresponding bound */
    2844static
    2846 SCIP* scip, /**< SCIP data structure */
    2847 SCIP_CONS* cons, /**< constraint that inferred the bound change */
    2848 SCIP_VAR* infervar, /**< variable that was deduced, or NULL (not equal to integral variable) */
    2849 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
    2850 PROPRULE proprule /**< propagation rule */
    2851 )
    2852{
    2853 SCIP_CONSDATA* consdata;
    2854 SCIP_VAR** vars;
    2855 int nvars;
    2856 int i;
    2857
    2858 assert(cons != NULL);
    2859
    2860 consdata = SCIPconsGetData(cons);
    2861 assert(consdata != NULL);
    2862 vars = consdata->vars;
    2863 nvars = consdata->nvars;
    2864
    2865 switch( proprule )
    2866 {
    2867 case PROPRULE_0:
    2868 assert(infervar == NULL || infervar == consdata->intvar);
    2869
    2870 /* the integral variable was fixed, because all variables were fixed */
    2871 for( i = 0; i < nvars; ++i )
    2872 {
    2873 assert(SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE)));
    2875 }
    2876 break;
    2877
    2878 case PROPRULE_1:
    2879 /* the variable was inferred, because all other variables were fixed */
    2880 for( i = 0; i < nvars; ++i )
    2881 {
    2882 /* add variables that were fixed to 1 before */
    2883 if( SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) > 0.5 )
    2884 {
    2885 assert(SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, TRUE) > 0.5);
    2887 }
    2888 /* add variables that were fixed to 0 */
    2889 else if( SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) < 0.5 )
    2890 {
    2891 assert(SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, TRUE) < 0.5);
    2893 }
    2894 else
    2895 {
    2896 /* check changed variable (changed variable is 0 or 1 afterwards) */
    2897 assert(vars[i] == infervar);
    2898 }
    2899 }
    2900 break;
    2901
    2902 case PROPRULE_INTLB:
    2903 assert(consdata->intvar != NULL);
    2904
    2905 if( infervar != consdata->intvar )
    2906 {
    2907 /* the variable was fixed, because of the lower bound of the integral variable */
    2908 SCIP_CALL( SCIPaddConflictLb(scip, consdata->intvar, NULL) );
    2909 }
    2910 /* to many and the other fixed variables */
    2911 for( i = 0; i < nvars; ++i )
    2912 {
    2913 /* add variables that were fixed to 0 */
    2914 if( SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) < 0.5 )
    2915 {
    2916 assert(SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, TRUE) < 0.5);
    2918 }
    2919 }
    2920 break;
    2921
    2922 case PROPRULE_INTUB:
    2923 assert(consdata->intvar != NULL);
    2924
    2925 if( infervar != consdata->intvar )
    2926 {
    2927 /* the variable was fixed, because of upper bound of the integral variable and the other fixed variables */
    2928 SCIP_CALL( SCIPaddConflictUb(scip, consdata->intvar, NULL) );
    2929 }
    2930 for( i = 0; i < nvars; ++i )
    2931 {
    2932 /* add variables that were fixed to 1 */
    2933 if( SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) > 0.5 )
    2934 {
    2935 assert(SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, TRUE) > 0.5);
    2937 }
    2938 }
    2939 break;
    2940
    2941 case PROPRULE_INVALID:
    2942 default:
    2943 SCIPerrorMessage("invalid inference information %d in xor constraint <%s>\n", proprule, SCIPconsGetName(cons));
    2944 SCIPABORT();
    2945 return SCIP_INVALIDDATA; /*lint !e527*/
    2946 }
    2947
    2948 return SCIP_OKAY;
    2949}
    2950
    2951/** analyzes conflicting assignment on given constraint, and adds conflict constraint to problem */
    2952static
    2954 SCIP* scip, /**< SCIP data structure */
    2955 SCIP_CONS* cons, /**< xor constraint that detected the conflict */
    2956 SCIP_VAR* infervar, /**< variable that was deduced, or NULL (not equal to integral variable) */
    2957 PROPRULE proprule /**< propagation rule */
    2958 )
    2959{
    2960 /* conflict analysis can only be applied in solving stage and if it is applicable */
    2962 return SCIP_OKAY;
    2963
    2964 /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
    2966
    2967 /* add bound changes */
    2968 SCIP_CALL( addConflictBounds(scip, cons, infervar, NULL, proprule) );
    2969
    2970 /* analyze the conflict */
    2972
    2973 return SCIP_OKAY;
    2974}
    2975
    2976/** propagates constraint with the following rules:
    2977 * (0) all variables are fixed => can fix integral variable
    2978 * (1) all except one variable fixed => fix remaining variable and integral variable
    2979 * (2) depending on the amount of fixed binary variables we can tighten the integral variable
    2980 * (3) depending on the lower bound of the integral variable one can fix variables to 1
    2981 * (4) depending on the upper bound of the integral variable one can fix variables to 0
    2982 */
    2983static
    2985 SCIP* scip, /**< SCIP data structure */
    2986 SCIP_CONS* cons, /**< xor constraint to be processed */
    2987 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    2988 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    2989 int* nfixedvars, /**< pointer to add up the number of fixed variables */
    2990 int* nchgbds /**< pointer to add up the number of found domain reductions */
    2991 )
    2992{
    2993 SCIP_CONSDATA* consdata;
    2994 SCIP_VAR** vars;
    2995 SCIP_Bool infeasible;
    2996 SCIP_Bool tightened;
    2997 SCIP_Bool odd;
    2998 SCIP_Bool counted;
    2999 int nvars;
    3000 int nfixedones;
    3001 int nfixedzeros;
    3002 int watchedvar1;
    3003 int watchedvar2;
    3004 int i;
    3005
    3006 assert(scip != NULL);
    3007 assert(cons != NULL);
    3008 assert(eventhdlr != NULL);
    3009 assert(cutoff != NULL);
    3010 assert(nfixedvars != NULL);
    3011 assert(nchgbds != NULL);
    3012
    3013 /* propagation can only be applied, if we know all operator variables */
    3014 if( SCIPconsIsModifiable(cons) )
    3015 return SCIP_OKAY;
    3016
    3017 consdata = SCIPconsGetData(cons);
    3018 assert(consdata != NULL);
    3019
    3020 vars = consdata->vars;
    3021 nvars = consdata->nvars;
    3022
    3023 /* don't process the constraint, if the watched variables weren't fixed to any value since last propagation call */
    3024 if( consdata->propagated )
    3025 return SCIP_OKAY;
    3026
    3027 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
    3029 {
    3030 SCIP_CALL( SCIPincConsAge(scip, cons) );
    3031 }
    3032
    3033 /* propagation cannot be applied, if we have at least two unfixed variables left;
    3034 * that means, we only have to watch (i.e. capture events) of two variables, and switch to other variables
    3035 * if these ones get fixed
    3036 */
    3037 watchedvar1 = consdata->watchedvar1;
    3038 watchedvar2 = consdata->watchedvar2;
    3039
    3040 /* check, if watched variables are still unfixed */
    3041 if( watchedvar1 != -1 )
    3042 {
    3043 if( SCIPvarGetLbLocal(vars[watchedvar1]) > 0.5 || SCIPvarGetUbLocal(vars[watchedvar1]) < 0.5 )
    3044 watchedvar1 = -1;
    3045 }
    3046 if( watchedvar2 != -1 )
    3047 {
    3048 if( SCIPvarGetLbLocal(vars[watchedvar2]) > 0.5 || SCIPvarGetUbLocal(vars[watchedvar2]) < 0.5 )
    3049 watchedvar2 = -1;
    3050 }
    3051
    3052 /* if only one watched variable is still unfixed, make it the first one */
    3053 if( watchedvar1 == -1 )
    3054 {
    3055 watchedvar1 = watchedvar2;
    3056 watchedvar2 = -1;
    3057 }
    3058 assert(watchedvar1 != -1 || watchedvar2 == -1);
    3059
    3060 /* if the watched variables are invalid (fixed), find new ones if existing; count the parity */
    3061 odd = consdata->rhs;
    3062 nfixedones = 0;
    3063 nfixedzeros = 0;
    3064 counted = FALSE;
    3065 if( watchedvar2 == -1 )
    3066 {
    3067 for( i = 0; i < nvars; ++i )
    3068 {
    3069 if( SCIPvarGetLbLocal(vars[i]) > 0.5 )
    3070 {
    3071 odd = !odd;
    3072 ++nfixedones;
    3073 }
    3074 else if( SCIPvarGetUbLocal(vars[i]) < 0.5 )
    3075 ++nfixedzeros;
    3076 else
    3077 {
    3078 assert(SCIPvarGetUbLocal(vars[i]) > 0.5);
    3079 assert(SCIPvarGetLbLocal(vars[i]) < 0.5);
    3080
    3081 if( watchedvar1 == -1 )
    3082 {
    3083 assert(watchedvar2 == -1);
    3084 watchedvar1 = i;
    3085 }
    3086 else if( watchedvar2 == -1 && watchedvar1 != i )
    3087 {
    3088 watchedvar2 = i;
    3089 }
    3090 }
    3091 }
    3092 counted = TRUE;
    3093 }
    3094 assert(watchedvar1 != -1 || watchedvar2 == -1);
    3095
    3096 /* if all variables are fixed, we can decide the feasibility of the constraint */
    3097 if( watchedvar1 == -1 )
    3098 {
    3099 assert(watchedvar2 == -1);
    3100 assert(counted);
    3101
    3102 if( odd )
    3103 {
    3104 SCIPdebugMsg(scip, "constraint <%s>: all vars fixed, constraint is infeasible\n", SCIPconsGetName(cons));
    3105
    3106 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
    3109
    3110 *cutoff = TRUE;
    3111 }
    3112 else
    3113 {
    3114 /* fix integral variable if present */
    3115 if( consdata->intvar != NULL )
    3116 {
    3117 int fixval;
    3118
    3119 assert(!*cutoff);
    3120 assert((nfixedones - (int) consdata->rhs) % 2 == 0);
    3121
    3122 fixval = (nfixedones - (int) consdata->rhs)/2; /*lint !e713*/
    3123
    3124 SCIPdebugMsg(scip, "fix integral variable <%s> to %d\n", SCIPvarGetName(consdata->intvar), fixval);
    3125
    3126 /* check whether value to fix is outside bounds */
    3127 if( fixval + 0.5 < SCIPvarGetLbLocal(consdata->intvar) )
    3128 {
    3129 /* cannot fix auxiliary variable (maybe it has been branched on): we are infeasible */
    3130 SCIPdebugMsg(scip, "node infeasible: activity is %d, bounds of integral variable are [%g,%g]\n",
    3131 fixval, SCIPvarGetLbLocal(consdata->intvar), SCIPvarGetUbLocal(consdata->intvar));
    3132
    3135
    3136 *cutoff = TRUE;
    3137 }
    3138 else if( fixval - 0.5 > SCIPvarGetUbLocal(consdata->intvar) )
    3139 {
    3140 /* cannot fix auxiliary variable (maybe it has been branched on): we are infeasible */
    3141 SCIPdebugMsg(scip, "node infeasible: activity is %d, bounds of integral variable are [%g,%g]\n",
    3142 fixval, SCIPvarGetLbLocal(consdata->intvar), SCIPvarGetUbLocal(consdata->intvar));
    3143
    3146
    3147 *cutoff = TRUE;
    3148 }
    3149 else if( SCIPvarGetStatus(consdata->intvar) != SCIP_VARSTATUS_MULTAGGR )
    3150 {
    3151 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->intvar), (SCIP_Real) fixval) )
    3152 {
    3153 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->intvar, (SCIP_Real) fixval, cons, (int)PROPRULE_0, FALSE, &infeasible, &tightened) );
    3154 assert(tightened);
    3155 assert(!infeasible);
    3156 }
    3157
    3158 if( !SCIPisEQ(scip, SCIPvarGetUbLocal(consdata->intvar), (SCIP_Real) fixval) )
    3159 {
    3160 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->intvar, (SCIP_Real) fixval, cons, (int)PROPRULE_0, FALSE, &infeasible, &tightened) );
    3161 assert(tightened);
    3162 assert(!infeasible);
    3163 }
    3164
    3165 ++(*nfixedvars);
    3166 }
    3167 }
    3168 else
    3169 {
    3170 SCIPdebugMsg(scip, "constraint <%s>: all vars fixed, constraint is feasible\n", SCIPconsGetName(cons));
    3171 }
    3172 }
    3174
    3175 return SCIP_OKAY;
    3176 }
    3177
    3178 /* if only one variable is not fixed, this variable can be deduced */
    3179 if( watchedvar2 == -1 )
    3180 {
    3181 assert(watchedvar1 != -1);
    3182 assert(counted);
    3183
    3184 SCIPdebugMsg(scip, "constraint <%s>: only one unfixed variable -> fix <%s> to %u\n",
    3185 SCIPconsGetName(cons), SCIPvarGetName(vars[watchedvar1]), odd);
    3186
    3187 SCIP_CALL( SCIPinferBinvarCons(scip, vars[watchedvar1], odd, cons, (int)PROPRULE_1, &infeasible, &tightened) );
    3188 assert(!infeasible);
    3189 assert(tightened);
    3190
    3191 (*nfixedvars)++;
    3192
    3193 /* fix integral variable if present and not multi-aggregated */
    3194 if( consdata->intvar != NULL && SCIPvarGetStatus(consdata->intvar) != SCIP_VARSTATUS_MULTAGGR )
    3195 {
    3196 int fixval;
    3197
    3198 /* if variable has been fixed to 1, adjust number of fixed variables */
    3199 if( odd )
    3200 ++nfixedones;
    3201
    3202 assert((nfixedones - (int) consdata->rhs) % 2 == 0);
    3203
    3204 fixval = (nfixedones - (int) consdata->rhs)/2; /*lint !e713*/
    3205 SCIPdebugMsg(scip, "should fix integral variable <%s> to %d\n", SCIPvarGetName(consdata->intvar), fixval);
    3206
    3207 /* check whether value to fix is outside bounds */
    3208 if( fixval + 0.5 < SCIPvarGetLbLocal(consdata->intvar) )
    3209 {
    3210 /* cannot fix auxiliary variable (maybe it has been branched on): we are infeasible */
    3211 SCIPdebugMsg(scip, "node infeasible: activity is %d, bounds of integral variable are [%g,%g]\n",
    3212 fixval, SCIPvarGetLbLocal(consdata->intvar), SCIPvarGetUbLocal(consdata->intvar));
    3213
    3216
    3217 *cutoff = TRUE;
    3218 }
    3219 else if( fixval - 0.5 > SCIPvarGetUbLocal(consdata->intvar) )
    3220 {
    3221 /* cannot fix auxiliary variable (maybe it has been branched on): we are infeasible */
    3222 SCIPdebugMsg(scip, "node infeasible: activity is %d, bounds of integral variable are [%g,%g]\n",
    3223 fixval, SCIPvarGetLbLocal(consdata->intvar), SCIPvarGetUbLocal(consdata->intvar));
    3224
    3227
    3228 *cutoff = TRUE;
    3229 }
    3230 else
    3231 {
    3232 if( SCIPvarGetLbLocal(consdata->intvar) + 0.5 < (SCIP_Real) fixval )
    3233 {
    3234 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->intvar, (SCIP_Real) fixval, cons, (int)PROPRULE_1, TRUE, &infeasible, &tightened) );
    3235 assert(tightened);
    3236 assert(!infeasible);
    3237 }
    3238
    3239 if( SCIPvarGetUbLocal(consdata->intvar) - 0.5 > (SCIP_Real) fixval )
    3240 {
    3241 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->intvar, (SCIP_Real) fixval, cons, (int)PROPRULE_1, TRUE, &infeasible, &tightened) );
    3242 assert(tightened);
    3243 assert(!infeasible);
    3244 }
    3245 assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->intvar), SCIPvarGetUbLocal(consdata->intvar)));
    3246
    3247 ++(*nfixedvars);
    3248 }
    3249 }
    3250
    3253
    3254 return SCIP_OKAY;
    3255 }
    3256
    3257 /* propagate w.r.t. integral variable */
    3258 if( consdata->intvar != NULL && !consdata->deleteintvar )
    3259 {
    3260 SCIP_Real newlb;
    3261 SCIP_Real newub;
    3262 int nonesmin;
    3263 int nonesmax;
    3264
    3265 if( !counted )
    3266 {
    3267 assert(nfixedzeros == 0);
    3268 assert(nfixedones == 0);
    3269
    3270 for( i = 0; i < nvars; ++i )
    3271 {
    3272 if( SCIPvarGetLbLocal(vars[i]) > 0.5 )
    3273 ++nfixedones;
    3274 else if( SCIPvarGetUbLocal(vars[i]) < 0.5 )
    3275 ++nfixedzeros;
    3276 }
    3277 }
    3278 assert(nfixedones + nfixedzeros < nvars);
    3279
    3280 assert(SCIPisFeasIntegral(scip, SCIPvarGetLbLocal(consdata->intvar)));
    3281 assert(SCIPisFeasIntegral(scip, SCIPvarGetUbLocal(consdata->intvar)));
    3282
    3283 nonesmin = 2 * (int)(SCIPvarGetLbLocal(consdata->intvar) + 0.5) + (int) consdata->rhs; /*lint !e713*/
    3284 nonesmax = 2 * (int)(SCIPvarGetUbLocal(consdata->intvar) + 0.5) + (int) consdata->rhs; /*lint !e713*/
    3285
    3286 /* the number of possible variables that can get value 1 is less than the minimum bound */
    3287 if( nvars - nfixedzeros < nonesmin )
    3288 {
    3289 SCIPdebugMsg(scip, "constraint <%s>: at most %d variables can take value 1, but there should be at least %d.\n", SCIPconsGetName(cons), nvars - nfixedones, nonesmin);
    3290
    3293
    3294 *cutoff = TRUE;
    3295
    3296 return SCIP_OKAY;
    3297 }
    3298
    3299 /* the number of variables that are fixed to 1 is larger than the maximum bound */
    3300 if( nfixedones > nonesmax )
    3301 {
    3302 SCIPdebugMsg(scip, "constraint <%s>: at least %d variables are fixed to 1, but there should be at most %d.\n", SCIPconsGetName(cons), nfixedones, nonesmax);
    3303
    3306
    3307 *cutoff = TRUE;
    3308
    3309 return SCIP_OKAY;
    3310 }
    3311
    3312 if( SCIPvarGetStatus(consdata->intvar) != SCIP_VARSTATUS_MULTAGGR )
    3313 {
    3314 /* compute new bounds on the integral variable */
    3315 newlb = (SCIP_Real)((nfixedones + 1 - (int) consdata->rhs) / 2); /*lint !e653*/
    3316 newub = (SCIP_Real)((nvars - nfixedzeros - (int) consdata->rhs) / 2); /*lint !e653*/
    3317
    3318 /* new lower bound is better */
    3319 if( newlb > SCIPvarGetLbLocal(consdata->intvar) + 0.5 )
    3320 {
    3321 SCIPdebugMsg(scip, "constraint <%s>: propagated lower bound of integral variable <%s> to %g\n", SCIPconsGetName(cons), SCIPvarGetName(consdata->intvar), newlb);
    3322 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->intvar, newlb, cons, (int)PROPRULE_INTUB, TRUE, &infeasible, &tightened) );
    3323 assert(tightened);
    3324 assert(!infeasible);
    3325
    3326 ++(*nchgbds);
    3327
    3328 nonesmin = 2 * (int)(SCIPvarGetLbLocal(consdata->intvar) + 0.5) + (int) consdata->rhs; /*lint !e713*/
    3329 }
    3330
    3331 /* new upper bound is better */
    3332 if( newub < SCIPvarGetUbLocal(consdata->intvar) - 0.5 )
    3333 {
    3334 SCIPdebugMsg(scip, "constraint <%s>: propagated upper bound of integral variable <%s> to %g\n", SCIPconsGetName(cons), SCIPvarGetName(consdata->intvar), newub);
    3335 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->intvar, newub, cons, (int)PROPRULE_INTLB, TRUE, &infeasible, &tightened) );
    3336 assert(tightened);
    3337 assert(!infeasible);
    3338
    3339 ++(*nchgbds);
    3340
    3341 nonesmax = 2 * (int)(SCIPvarGetUbLocal(consdata->intvar) + 0.5) + (int) consdata->rhs; /*lint !e713*/
    3342 }
    3343
    3344 assert(nvars - nfixedzeros >= nonesmin);
    3345 assert(nfixedones <= nonesmax);
    3346
    3347 /* the number of variables that are free or fixed to 1 is exactly the minimum required -> fix free variables to 1 */
    3348 if( nvars - nfixedzeros == nonesmin )
    3349 {
    3350 SCIPdebugMsg(scip, "constraint <%s>: fix %d free variables to 1 to reach lower bound of %d\n", SCIPconsGetName(cons), nvars - nfixedzeros - nfixedones, nonesmin);
    3351
    3352 for( i = 0; i < nvars; ++i )
    3353 {
    3354 if( SCIPvarGetLbLocal(vars[i]) < 0.5 && SCIPvarGetUbLocal(vars[i]) > 0.5 )
    3355 {
    3356 SCIP_CALL( SCIPinferBinvarCons(scip, vars[i], TRUE, cons, (int)PROPRULE_INTLB, &infeasible, &tightened) );
    3357 assert(!infeasible);
    3358 assert(tightened);
    3359
    3360 ++(*nfixedvars);
    3361 }
    3362 }
    3365
    3366 return SCIP_OKAY;
    3367 }
    3368
    3369 /* the number of variables that are fixed to 1 is exactly the maximum required -> fix free variables to 0 */
    3370 if( nfixedones == nonesmax )
    3371 {
    3372 SCIPdebugMsg(scip, "constraint <%s>: fix %d free variables to 0 to guarantee upper bound of %d\n", SCIPconsGetName(cons), nvars - nfixedzeros - nfixedones, nonesmax);
    3373
    3374 for( i = 0; i < nvars; ++i )
    3375 {
    3376 if( SCIPvarGetLbLocal(vars[i]) < 0.5 && SCIPvarGetUbLocal(vars[i]) > 0.5 )
    3377 {
    3378 SCIP_CALL( SCIPinferBinvarCons(scip, vars[i], FALSE, cons, (int)PROPRULE_INTUB, &infeasible, &tightened) );
    3379 assert(!infeasible);
    3380 assert(tightened);
    3381 ++(*nfixedvars);
    3382 }
    3383 }
    3386
    3387 return SCIP_OKAY;
    3388 }
    3389 }
    3390 }
    3391
    3392 /* switch to the new watched variables */
    3393 SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, watchedvar1, watchedvar2) );
    3394
    3395 /* mark the constraint propagated */
    3396 consdata->propagated = TRUE;
    3397
    3398 return SCIP_OKAY;
    3399}
    3400
    3401/** resolves a conflict on the given variable by supplying the variables needed for applying the corresponding
    3402 * propagation rules (see propagateCons())
    3403 */
    3404static
    3406 SCIP* scip, /**< SCIP data structure */
    3407 SCIP_CONS* cons, /**< constraint that inferred the bound change */
    3408 SCIP_VAR* infervar, /**< variable that was deduced */
    3409 PROPRULE proprule, /**< propagation rule that deduced the value */
    3410 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
    3411 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
    3412 )
    3413{
    3414 assert(result != NULL);
    3415
    3416 SCIPdebugMsg(scip, "resolving fixations according to rule %d\n", (int) proprule);
    3417
    3418 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, proprule) );
    3419 *result = SCIP_SUCCESS;
    3420
    3421 return SCIP_OKAY;
    3422}
    3423
    3424/** try to use clique information to delete a part of the xor constraint or even fix variables */
    3425static
    3427 SCIP* scip, /**< SCIP data structure */
    3428 SCIP_CONS* cons, /**< constraint that inferred the bound change */
    3429 int* nfixedvars, /**< pointer to add up the number of found domain reductions */
    3430 int* naggrvars, /**< pointer to add up the number of aggregated variables */
    3431 int* nchgcoefs, /**< pointer to add up the number of deleted entries */
    3432 int* ndelconss, /**< pointer to add up the number of deleted constraints */
    3433 int* naddconss, /**< pointer to add up the number of added constraints */
    3434 SCIP_Bool* cutoff /**< pointer to store TRUE, if the node can be cut off */
    3435 )
    3436{
    3437 SCIP_CONSDATA* consdata;
    3438 SCIP_VAR** vars;
    3439 int nvars;
    3440 SCIP_Bool breaked;
    3441 SCIP_Bool restart;
    3442 int posnotinclq1;
    3443 int posnotinclq2;
    3444 int v;
    3445 int v1;
    3446
    3447 assert(scip != NULL);
    3448 assert(cons != NULL);
    3449 assert(nfixedvars != NULL);
    3450 assert(nchgcoefs != NULL);
    3451 assert(ndelconss != NULL);
    3452 assert(naddconss != NULL);
    3453 assert(cutoff != NULL);
    3454
    3455 /* propagation can only be applied, if we know all operator variables */
    3456 if( SCIPconsIsModifiable(cons) )
    3457 return SCIP_OKAY;
    3458
    3459 consdata = SCIPconsGetData(cons);
    3460 assert(consdata != NULL);
    3461
    3462 vars = consdata->vars;
    3463 nvars = consdata->nvars;
    3464
    3465 if( nvars < 3 )
    3466 return SCIP_OKAY;
    3467
    3468 /* we cannot perform this steps if the integer variables in not artificial */
    3469 if( !consdata->deleteintvar )
    3470 return SCIP_OKAY;
    3471
    3472#ifdef SCIP_DISABLED_CODE
    3473 /* try to evaluate if clique presolving should only be done multiple times when the constraint changed */
    3474 if( !consdata->changed )
    3475 return SCIP_OKAY;
    3476#endif
    3477
    3478 /* @todo: if clique information would have saved the type of the clique, like <= 1, or == 1 we could do more
    3479 * presolving like:
    3480 *
    3481 * (xor(x1,x2,x3,x4) = 1 and clique(x1,x2) == 1) => xor(x3,x4) = 0
    3482 * (xor(x1,x2,x3,x4) = 1 and clique(x1,x2,x3) == 1) => (x4 = 0 and delete xor constraint)
    3483 */
    3484
    3485 /* 1. we have only clique information "<=", so we can check if all variables are in the same clique
    3486 *
    3487 * (xor(x1,x2,x3) = 1 and clique(x1,x2,x3) <= 1) => (add set-partioning constraint x1 + x2 + x3 = 1 and delete old
    3488 * xor-constraint)
    3489 *
    3490 * (xor(x1,x2,x3) = 0 and clique(x1,x2,x3) <= 1) => (fix all variables x1 = x2 = x3 = 0 and delete old xor-
    3491 * constraint)
    3492 */
    3493
    3494 /* 2. we have only clique information "<=", so we can check if all but one variable are in the same clique
    3495 *
    3496 * (xor(x1,x2,x3,x4) = 1 and clique(x1,x2,x3) <= 1) => (add set-partioning constraint x1 + x2 + x3 + x4 = 1 and
    3497 * delete old xor constraint)
    3498 *
    3499 * (xor(x1,x2,x3,x4) = 0 and clique(x1,x2,x3) <= 1) => (add set-partioning constraint x1 + x2 + x3 + ~x4 = 1 and
    3500 * delete old xor constraint)
    3501 */
    3502
    3503 posnotinclq1 = -1; /* index of variable that is possible not in the clique */
    3504 posnotinclq2 = -1; /* index of variable that is possible not in the clique */
    3505 breaked = FALSE;
    3506 restart = FALSE;
    3507
    3508 v = nvars - 2;
    3509 while( v >= 0 )
    3510 {
    3511 SCIP_VAR* var;
    3512 SCIP_VAR* var1;
    3513 SCIP_Bool value;
    3514 SCIP_Bool value1;
    3515
    3517
    3518 value = SCIPvarIsActive(vars[v]);
    3519
    3520 if( !value )
    3521 var = SCIPvarGetNegationVar(vars[v]);
    3522 else
    3523 var = vars[v];
    3524
    3525 if( posnotinclq1 == v )
    3526 {
    3527 --v;
    3528 continue;
    3529 }
    3530
    3531 for( v1 = v+1; v1 < nvars; ++v1 )
    3532 {
    3533 if( posnotinclq1 == v1 )
    3534 continue;
    3535
    3536 value1 = SCIPvarIsActive(vars[v1]);
    3537
    3538 if( !value1 )
    3539 var1 = SCIPvarGetNegationVar(vars[v1]);
    3540 else
    3541 var1 = vars[v1];
    3542
    3543 if( !SCIPvarsHaveCommonClique(var, value, var1, value1, TRUE) )
    3544 {
    3545 /* if the position of the variable which is not in the clique with all other variables is not yet
    3546 * initialized, than do now, one of both variables does not fit
    3547 */
    3548 if( posnotinclq1 == -1 )
    3549 {
    3550 posnotinclq1 = v;
    3551 posnotinclq2 = v1;
    3552 }
    3553 else
    3554 {
    3555 /* no clique with exactly nvars-1 variables */
    3556 if( restart || (posnotinclq2 != v && posnotinclq2 != v1) )
    3557 {
    3558 breaked = TRUE;
    3559 break;
    3560 }
    3561
    3562 /* check the second variables for not fitting into the clique of (nvars - 1) variables */
    3563 posnotinclq1 = posnotinclq2;
    3564 restart = TRUE;
    3565 v = nvars - 1;
    3566 }
    3567
    3568 break;
    3569 }
    3570 else
    3571 assert(vars[v] != vars[v1]);
    3572 }
    3573
    3574 if( breaked )
    3575 break;
    3576
    3577 --v;
    3578 }
    3579
    3580 /* at least nvars-1 variables are in one clique */
    3581 if( !breaked ) /*lint !e774*/
    3582 {
    3583 SCIP_Bool replaced = FALSE;
    3584
    3585 /* if rhs == TRUE, all variables of xor-constraint are in one clique, so create a setpartitioning constraint with
    3586 * all variables and delete this xor-constraint
    3587 */
    3588 if( consdata->rhs )
    3589 {
    3590 if( SCIPconsGetNUpgradeLocks(cons) == 0 )
    3591 {
    3592 SCIP_CONS* newcons;
    3593 char consname[SCIP_MAXSTRLEN];
    3594
    3595 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_complete_clq", SCIPconsGetName(cons));
    3596 SCIP_CALL( SCIPcreateConsSetpart(scip, &newcons, consname, nvars, vars,
    3601 SCIPdebugMsg(scip, "adding a clique/setppc constraint <%s>\n", SCIPconsGetName(newcons));
    3602 SCIPdebug( SCIP_CALL( SCIPprintCons(scip, newcons, NULL) ) );
    3603 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &newcons) );
    3604 ++(*naddconss);
    3605 replaced = TRUE;
    3606 }
    3607 }
    3608 /* all variables of xor-constraint are in one clique and rhs == FALSE, so fix all variables to 0, case 1 */
    3609 else if( posnotinclq1 == -1 )
    3610 {
    3611 SCIP_Bool infeasible;
    3612 SCIP_Bool fixed;
    3613
    3614 SCIPdebugMsg(scip, "all variables of xor constraints <%s> are in one clique, so fixed all variables to 0\n",
    3615 SCIPconsGetName(cons));
    3617
    3618 for( v = nvars - 1; v >= 0; --v )
    3619 {
    3620 SCIPdebugMsg(scip, "fixing variable <%s> to 0\n", SCIPvarGetName(vars[v]));
    3621 SCIP_CALL( SCIPfixVar(scip, vars[v], 0.0, &infeasible, &fixed) );
    3622 assert(infeasible || fixed);
    3623
    3624 if( infeasible )
    3625 {
    3626 *cutoff = TRUE;
    3627
    3628 return SCIP_OKAY;
    3629 }
    3630 else
    3631 ++(*nfixedvars);
    3632 }
    3633
    3634 replaced = TRUE;
    3635 }
    3636 /* all but one variable are in one clique and rhs == FALSE, so we need to exchange the variable not appearing in
    3637 * the clique with the negated variable, case 2
    3638 */
    3639 else
    3640 {
    3641 if( SCIPconsGetNUpgradeLocks(cons) == 0 )
    3642 {
    3643 SCIP_CONS* newcons;
    3644 char consname[SCIP_MAXSTRLEN];
    3645
    3646 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_completed_clq", SCIPconsGetName(cons));
    3647
    3648 /* complete clique by creating a set partioning constraint over all variables */
    3649 SCIP_CALL( SCIPcreateConsSetpart(scip, &newcons, consname, 0, NULL,
    3654
    3655 for( v = 0; v < nvars; ++v )
    3656 {
    3657 if( v == posnotinclq1 )
    3658 {
    3659 SCIP_VAR* var;
    3660
    3661 SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &var) );
    3662 assert(var != NULL);
    3663
    3664 SCIP_CALL( SCIPaddCoefSetppc(scip, newcons, var) );
    3665 }
    3666 else
    3667 {
    3668 SCIP_CALL( SCIPaddCoefSetppc(scip, newcons, vars[v]) );
    3669 }
    3670 }
    3671
    3672 SCIPdebugMsg(scip, "adding a clique/setppc constraint <%s>\n", SCIPconsGetName(newcons));
    3673 SCIPdebug( SCIP_CALL( SCIPprintCons(scip, newcons, NULL) ) );
    3674 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &newcons) );
    3675 ++(*naddconss);
    3676 replaced = TRUE;
    3677 }
    3678 }
    3679
    3680 /* remove integer variable if it exists */
    3681 if( consdata->intvar != NULL )
    3682 {
    3683 SCIP_Bool infeasible;
    3684 SCIP_Bool fixed;
    3685
    3686 /* fix integer variable to zero if at most one xor-variable can be one */
    3687 if( consdata->rhs || posnotinclq1 == -1 )
    3688 {
    3689 SCIPdebugMsg(scip, "fix the integer variable <%s> to 0\n", SCIPvarGetName(consdata->intvar));
    3690 SCIP_CALL( SCIPfixVar(scip, consdata->intvar, 0.0, &infeasible, &fixed) );
    3691 assert(infeasible || fixed);
    3692
    3693 if( infeasible )
    3694 {
    3695 *cutoff = TRUE;
    3696
    3697 return SCIP_OKAY;
    3698 }
    3699 else
    3700 ++(*nfixedvars);
    3701 }
    3702 /* otherwise aggregate integer variable to xor-variable not in clique */
    3703 else
    3704 {
    3705 SCIP_Bool redundant;
    3706
    3707 SCIPdebugMsg(scip, "aggregate the integer variable <%s> to <%s>\n", SCIPvarGetName(consdata->intvar), SCIPvarGetName(vars[posnotinclq1]));
    3708 SCIP_CALL( SCIPaggregateVars(scip, consdata->intvar, vars[posnotinclq1], 1.0, -1.0, 0.0, &infeasible, &redundant, &fixed) );
    3709 assert(infeasible || redundant);
    3710
    3711 if( infeasible )
    3712 {
    3713 *cutoff = TRUE;
    3714
    3715 return SCIP_OKAY;
    3716 }
    3717 else if( fixed )
    3718 ++(*naggrvars);
    3719 }
    3720 }
    3721
    3722 /* delete old replaced xor-constraint */
    3723 if( replaced )
    3724 {
    3725 SCIP_CALL( SCIPdelCons(scip, cons) );
    3726 ++(*ndelconss);
    3727 }
    3728 }
    3729
    3730 return SCIP_OKAY;
    3731}
    3732
    3733/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
    3734 * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
    3735 */
    3736static
    3738 SCIP* scip, /**< SCIP data structure */
    3739 BMS_BLKMEM* blkmem, /**< block memory */
    3740 SCIP_CONS** conss, /**< constraint set */
    3741 int nconss, /**< number of constraints in constraint set */
    3742 int* firstchange, /**< pointer to store first changed constraint */
    3743 int* nchgcoefs, /**< pointer to add up the number of changed coefficients */
    3744 int* nfixedvars, /**< pointer to add up the number of found domain reductions */
    3745 int* naggrvars, /**< pointer to add up the number of aggregated variables */
    3746 int* ndelconss, /**< pointer to count number of deleted constraints */
    3747 int* naddconss, /**< pointer to count number of added constraints */
    3748 SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
    3749 )
    3750{
    3751 SCIP_HASHTABLE* hashtable;
    3752 int hashtablesize;
    3753 int c;
    3754
    3755 assert(conss != NULL);
    3756 assert(ndelconss != NULL);
    3757
    3758 /* create a hash table for the constraint set */
    3759 hashtablesize = nconss;
    3760 hashtablesize = MAX(hashtablesize, HASHSIZE_XORCONS);
    3761
    3762 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
    3763 hashGetKeyXorcons, hashKeyEqXorcons, hashKeyValXorcons, (void*) scip) );
    3764
    3765 /* check all constraints in the given set for redundancy */
    3766 for( c = 0; c < nconss; ++c )
    3767 {
    3768 SCIP_CONS* cons0;
    3769 SCIP_CONS* cons1;
    3770 SCIP_CONSDATA* consdata0;
    3771 SCIP_CONSHDLR* conshdlr;
    3772 SCIP_CONSHDLRDATA* conshdlrdata;
    3773
    3774 cons0 = conss[c];
    3775
    3776 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
    3777 continue;
    3778
    3779 /* get constraint handler data */
    3780 conshdlr = SCIPconsGetHdlr(cons0);
    3781 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3782 assert(conshdlrdata != NULL);
    3783
    3784 /* it can happen that during preprocessing some variables got aggregated and a constraint now has not active
    3785 * variables inside so we need to remove them for sorting
    3786 */
    3787 /* remove all variables that are fixed to zero and all pairs of variables fixed to one;
    3788 * merge multiple entries of the same or negated variables
    3789 */
    3790 SCIP_CALL( applyFixings(scip, cons0, conshdlrdata->eventhdlr, nchgcoefs, naggrvars, naddconss, cutoff) );
    3791 if( *cutoff )
    3792 goto TERMINATE;
    3793
    3794 consdata0 = SCIPconsGetData(cons0);
    3795
    3796 assert(consdata0 != NULL);
    3797
    3798 /* applyFixings() led to an empty or trivial constraint */
    3799 if( consdata0->nvars <= 1 )
    3800 {
    3801 if( consdata0->nvars == 0 )
    3802 {
    3803 /* the constraints activity cannot match an odd right hand side */
    3804 if( consdata0->rhs )
    3805 {
    3806 *cutoff = TRUE;
    3807 break;
    3808 }
    3809 }
    3810 else
    3811 {
    3812 /* exactly 1 variable left. */
    3813 SCIP_Bool infeasible;
    3814 SCIP_Bool fixed;
    3815
    3816 /* fix remaining variable */
    3817 SCIP_CALL( SCIPfixVar(scip, consdata0->vars[0], (SCIP_Real) consdata0->rhs, &infeasible, &fixed) );
    3818 assert(!infeasible);
    3819
    3820 if( fixed )
    3821 ++(*nfixedvars);
    3822 }
    3823
    3824 /* fix integral variable if present */
    3825 if( consdata0->intvar != NULL )
    3826 {
    3827 SCIP_Bool infeasible;
    3828 SCIP_Bool fixed;
    3829
    3830 SCIP_CALL( SCIPfixVar(scip, consdata0->intvar, 0.0, &infeasible, &fixed) );
    3831 assert(!infeasible);
    3832
    3833 if( fixed )
    3834 ++(*nfixedvars);
    3835 }
    3836
    3837 /* delete empty constraint */
    3838 SCIP_CALL( SCIPdelCons(scip, cons0) );
    3839 ++(*ndelconss);
    3840
    3841 continue;
    3842 }
    3843
    3844 /* sort the constraint */
    3845 consdataSort(consdata0);
    3846 assert(consdata0->sorted);
    3847
    3848 /* get constraint from current hash table with same variables as cons0 */
    3849 cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
    3850
    3851 if( cons1 != NULL )
    3852 {
    3853 SCIP_CONSDATA* consdata1;
    3854
    3855 assert(SCIPconsIsActive(cons1));
    3856 assert(!SCIPconsIsModifiable(cons1));
    3857
    3858 consdata1 = SCIPconsGetData(cons1);
    3859
    3860 assert(consdata1 != NULL);
    3861 assert(consdata0->nvars >= 1 && consdata0->nvars == consdata1->nvars);
    3862
    3863 assert(consdata0->sorted && consdata1->sorted);
    3864 assert(consdata0->vars[0] == consdata1->vars[0]);
    3865
    3866 if( consdata0->rhs != consdata1->rhs )
    3867 {
    3868 *cutoff = TRUE;
    3869 goto TERMINATE;
    3870 }
    3871
    3872 /* aggregate parity variables into each other */
    3873 if( consdata0->intvar != consdata1->intvar && consdata0->intvar != NULL )
    3874 {
    3875 if( consdata1->intvar != NULL )
    3876 {
    3877 SCIP_Bool redundant;
    3878 SCIP_Bool aggregated;
    3879 SCIP_Bool infeasible;
    3880
    3881 SCIP_CALL( SCIPaggregateVars(scip, consdata0->intvar, consdata1->intvar, 1.0, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
    3882
    3883 if( aggregated )
    3884 {
    3885 ++(*naggrvars);
    3886 }
    3887 if( infeasible )
    3888 {
    3889 *cutoff = TRUE;
    3890 goto TERMINATE;
    3891 }
    3892 }
    3893 /* the special case that only cons0 has a parity variable 'intvar' is treated by swapping cons0 and cons1 */
    3894 else
    3895 {
    3896 SCIP_CALL( SCIPhashtableInsert(hashtable, (void *)cons0) );
    3897 assert(SCIPhashtableRetrieve(hashtable, (void *)cons1) == cons0);
    3898
    3899 SCIPswapPointers((void**)&cons0, (void**)(&cons1));
    3900 SCIPswapPointers((void**)&consdata0, (void**)(&consdata1));
    3901 }
    3902 }
    3903
    3904 /* delete cons0 and update flags of cons1 s.t. nonredundant information doesn't get lost */
    3905 /* coverity[swapped_arguments] */
    3906 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
    3907 SCIP_CALL( SCIPdelCons(scip, cons0) );
    3908 (*ndelconss)++;
    3909
    3910 /* update the first changed constraint to begin the next aggregation round with */
    3911 if( consdata0->changed && SCIPconsGetPos(cons1) < *firstchange )
    3912 *firstchange = SCIPconsGetPos(cons1);
    3913
    3914 assert(SCIPconsIsActive(cons1));
    3915 }
    3916 else
    3917 {
    3918 /* no such constraint in current hash table: insert cons0 into hash table */
    3919 SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
    3920 }
    3921 }
    3922
    3923 TERMINATE:
    3924 /* free hash table */
    3925 SCIPhashtableFree(&hashtable);
    3926
    3927 return SCIP_OKAY;
    3928}
    3929
    3930/** compares constraint with all prior constraints for possible redundancy or aggregation,
    3931 * and removes or changes constraint accordingly
    3932 */
    3933static
    3935 SCIP* scip, /**< SCIP data structure */
    3936 SCIP_CONS** conss, /**< constraint set */
    3937 int firstchange, /**< first constraint that changed since last pair preprocessing round */
    3938 int chkind, /**< index of constraint to check against all prior indices upto startind */
    3939 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    3940 int* nfixedvars, /**< pointer to add up the number of found domain reductions */
    3941 int* naggrvars, /**< pointer to count number of aggregated variables */
    3942 int* ndelconss, /**< pointer to count number of deleted constraints */
    3943 int* naddconss, /**< pointer to count number of added constraints */
    3944 int* nchgcoefs /**< pointer to add up the number of changed coefficients */
    3945 )
    3946{
    3947 SCIP_CONSHDLR* conshdlr;
    3948 SCIP_CONSHDLRDATA* conshdlrdata;
    3949 SCIP_CONS* cons0;
    3950 SCIP_CONSDATA* consdata0;
    3951 SCIP_Bool cons0changed;
    3952 int c;
    3953
    3954 assert(conss != NULL);
    3955 assert(firstchange <= chkind);
    3956 assert(cutoff != NULL);
    3957 assert(nfixedvars != NULL);
    3958 assert(naggrvars != NULL);
    3959 assert(ndelconss != NULL);
    3960 assert(nchgcoefs != NULL);
    3961
    3962 /* get the constraint to be checked against all prior constraints */
    3963 cons0 = conss[chkind];
    3964 assert(SCIPconsIsActive(cons0));
    3965 assert(!SCIPconsIsModifiable(cons0));
    3966
    3967 consdata0 = SCIPconsGetData(cons0);
    3968 assert(consdata0 != NULL);
    3969 assert(consdata0->nvars >= 1);
    3970
    3971 /* get constraint handler data */
    3972 conshdlr = SCIPconsGetHdlr(cons0);
    3973 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3974 assert(conshdlrdata != NULL);
    3975
    3976 /* it can happen that during preprocessing some variables got aggregated and a constraint now has not active
    3977 * variables inside so we need to remove them for sorting
    3978 */
    3979 /* remove all variables that are fixed to zero and all pairs of variables fixed to one;
    3980 * merge multiple entries of the same or negated variables
    3981 */
    3982 SCIP_CALL( applyFixings(scip, cons0, conshdlrdata->eventhdlr, nchgcoefs, naggrvars, naddconss, cutoff) );
    3983 if( *cutoff )
    3984 return SCIP_OKAY;
    3985
    3986 /* sort cons0 */
    3987 consdataSort(consdata0);
    3988 assert(consdata0->sorted);
    3989
    3990 /* check constraint against all prior constraints */
    3991 cons0changed = consdata0->changed;
    3992 consdata0->changed = FALSE;
    3993 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && SCIPconsIsActive(cons0) && !SCIPisStopped(scip); ++c )
    3994 {
    3995 SCIP_CONS* cons1;
    3996 SCIP_CONSDATA* consdata1;
    3997 SCIP_VAR* singlevar0;
    3998 SCIP_VAR* singlevar1;
    3999 SCIP_Bool parity;
    4000 SCIP_Bool cons0hastwoothervars;
    4001 SCIP_Bool cons1hastwoothervars;
    4002 SCIP_Bool aborted;
    4003 SCIP_Bool infeasible;
    4004 SCIP_Bool fixed;
    4005 SCIP_Bool redundant;
    4006 SCIP_Bool aggregated;
    4007 int v0;
    4008 int v1;
    4009
    4010 cons1 = conss[c];
    4011
    4012 /* ignore inactive and modifiable constraints */
    4013 if( !SCIPconsIsActive(cons1) || SCIPconsIsModifiable(cons1) )
    4014 continue;
    4015
    4016 consdata1 = SCIPconsGetData(cons1);
    4017 assert(consdata1 != NULL);
    4018
    4019 if( !consdata1->deleteintvar )
    4020 continue;
    4021
    4022 /* it can happen that during preprocessing some variables got aggregated and a constraint now has not active
    4023 * variables inside so we need to remove them for sorting
    4024 */
    4025 /* remove all variables that are fixed to zero and all pairs of variables fixed to one;
    4026 * merge multiple entries of the same or negated variables
    4027 */
    4028 SCIP_CALL( applyFixings(scip, cons1, conshdlrdata->eventhdlr, nchgcoefs, naggrvars, naddconss, cutoff) );
    4029 assert(consdata1 == SCIPconsGetData(cons1));
    4030 if( *cutoff )
    4031 return SCIP_OKAY;
    4032
    4033 SCIPdebugMsg(scip, "preprocess xor constraint pair <%s>[chg:%u] and <%s>[chg:%u]\n",
    4034 SCIPconsGetName(cons0), cons0changed, SCIPconsGetName(cons1), consdata1->changed);
    4035
    4036 /* if both constraints were not changed since last round, we can ignore the pair */
    4037 if( !cons0changed && !consdata1->changed )
    4038 continue;
    4039
    4040 /* applyFixings() led to an empty constraint */
    4041 if( consdata1->nvars == 0 )
    4042 {
    4043 if( consdata1->rhs )
    4044 {
    4045 *cutoff = TRUE;
    4046 break;
    4047 }
    4048 else
    4049 {
    4050 /* fix integral variable if present */
    4051 if( consdata1->intvar != NULL )
    4052 {
    4053 SCIP_CALL( SCIPfixVar(scip, consdata1->intvar, 0.0, &infeasible, &fixed) );
    4054 assert(!infeasible);
    4055 if( fixed )
    4056 ++(*nfixedvars);
    4057 }
    4058
    4059 /* delete empty constraint */
    4060 SCIP_CALL( SCIPdelCons(scip, cons1) );
    4061 ++(*ndelconss);
    4062
    4063 continue;
    4064 }
    4065 }
    4066 else if( consdata1->nvars == 1 )
    4067 {
    4068 /* fix remaining variable */
    4069 SCIP_CALL( SCIPfixVar(scip, consdata1->vars[0], (SCIP_Real) consdata1->rhs, &infeasible, &fixed) );
    4070 assert(!infeasible);
    4071
    4072 if( fixed )
    4073 ++(*nfixedvars);
    4074
    4075 /* fix integral variable if present */
    4076 if( consdata1->intvar != NULL )
    4077 {
    4078 SCIP_CALL( SCIPfixVar(scip, consdata1->intvar, 0.0, &infeasible, &fixed) );
    4079 assert(!infeasible);
    4080 if( fixed )
    4081 ++(*nfixedvars);
    4082 }
    4083
    4084 SCIP_CALL( SCIPdelCons(scip, cons1) );
    4085 ++(*ndelconss);
    4086
    4087 /* check for fixed variable in cons0 and remove it */
    4088 SCIP_CALL( applyFixings(scip, cons0, conshdlrdata->eventhdlr, nchgcoefs, naggrvars, naddconss, cutoff) );
    4089 assert(!(*cutoff));
    4090
    4091 /* sort cons0 */
    4092 consdataSort(consdata0);
    4093 assert(consdata0->sorted);
    4094
    4095 continue;
    4096 }
    4097 else if( consdata1->nvars == 2 )
    4098 {
    4099 if( !(consdata1->rhs) )
    4100 {
    4101 /* aggregate var0 == var1 */
    4102 SCIP_CALL( SCIPaggregateVars(scip, consdata1->vars[0], consdata1->vars[1], 1.0, -1.0, 0.0,
    4103 &infeasible, &redundant, &aggregated) );
    4104 }
    4105 else
    4106 {
    4107 /* aggregate var0 == 1 - var1 */
    4108 SCIP_CALL( SCIPaggregateVars(scip, consdata1->vars[0], consdata1->vars[1], 1.0, 1.0, 1.0,
    4109 &infeasible, &redundant, &aggregated) );
    4110 }
    4111 assert(!infeasible);
    4112 assert(redundant || SCIPdoNotAggr(scip));
    4113
    4114 if( aggregated )
    4115 {
    4116 ++(*naggrvars);
    4117
    4118 /* check for aggregated variable in cons0 and remove it */
    4119 SCIP_CALL( applyFixings(scip, cons0, conshdlrdata->eventhdlr, nchgcoefs, naggrvars, naddconss, cutoff) );
    4120 if( *cutoff )
    4121 return SCIP_OKAY;
    4122
    4123 /* sort cons0 */
    4124 consdataSort(consdata0);
    4125 assert(consdata0->sorted);
    4126 }
    4127
    4128 if( redundant )
    4129 {
    4130 /* fix or aggregate the intvar, if it exists */
    4131 if( consdata1->intvar != NULL )
    4132 {
    4133 /* we have var0 + var1 - 2 * intvar = 1, and aggregated var1 = 1 - var0,
    4134 * thus, intvar is always 0 */
    4135 if( consdata1->rhs )
    4136 {
    4137 SCIP_CALL( SCIPfixVar(scip, consdata1->intvar, 0.0, &infeasible, &fixed) );
    4138 assert(!infeasible);
    4139 if( fixed )
    4140 ++(*nfixedvars);
    4141 }
    4142 /* we have var0 + var1 - 2 * intvar = 0, and aggregated var1 = var0,
    4143 * i.e., 2 * var0 - 2 * intvar = 0, so intvar = var0 holds and we aggregate */
    4144 else
    4145 {
    4146 assert(!consdata1->rhs);
    4147
    4148 /* aggregate intvar == var0 */
    4149 SCIP_CALL( SCIPaggregateVars(scip, consdata1->vars[0], consdata1->intvar, 1.0, -1.0, 0.0,
    4150 &infeasible, &redundant, &aggregated) );
    4151 assert(!infeasible);
    4152 assert(redundant || SCIPdoNotAggr(scip));
    4153
    4154 if( aggregated )
    4155 {
    4156 ++(*naggrvars);
    4157 }
    4158 }
    4159 }
    4160
    4161 if( redundant )
    4162 {
    4163 SCIP_CALL( SCIPdelCons(scip, cons1) );
    4164 ++(*ndelconss);
    4165 }
    4166 }
    4167
    4168 continue;
    4169 }
    4170 assert(consdata0->sorted);
    4171
    4172 /* sort cons1 */
    4173 consdataSort(consdata1);
    4174 assert(consdata1->sorted);
    4175
    4176 /* check whether
    4177 * (a) one problem variable set is a subset of the other, or
    4178 * (b) the problem variable sets are almost equal with only one variable in each constraint that is not
    4179 * member of the other
    4180 */
    4181 aborted = FALSE;
    4182 parity = (consdata0->rhs ^ consdata1->rhs);
    4183 cons0hastwoothervars = FALSE;
    4184 cons1hastwoothervars = FALSE;
    4185 singlevar0 = NULL;
    4186 singlevar1 = NULL;
    4187 v0 = 0;
    4188 v1 = 0;
    4189 while( (v0 < consdata0->nvars || v1 < consdata1->nvars) && !aborted )
    4190 {
    4191 int cmp;
    4192
    4193 assert(v0 <= consdata0->nvars);
    4194 assert(v1 <= consdata1->nvars);
    4195
    4196 if( v0 == consdata0->nvars )
    4197 cmp = +1;
    4198 else if( v1 == consdata1->nvars )
    4199 cmp = -1;
    4200 else
    4201 cmp = SCIPvarCompareActiveAndNegated(consdata0->vars[v0], consdata1->vars[v1]);
    4202
    4203 switch( cmp )
    4204 {
    4205 case -1:
    4206 /* variable doesn't appear in cons1 */
    4207 assert(v0 < consdata0->nvars);
    4208 if( singlevar0 == NULL )
    4209 {
    4210 singlevar0 = consdata0->vars[v0];
    4211 if( cons1hastwoothervars )
    4212 aborted = TRUE;
    4213 }
    4214 else
    4215 {
    4216 cons0hastwoothervars = TRUE;
    4217 if( singlevar1 != NULL )
    4218 aborted = TRUE;
    4219 }
    4220 v0++;
    4221 break;
    4222
    4223 case +1:
    4224 /* variable doesn't appear in cons0 */
    4225 assert(v1 < consdata1->nvars);
    4226 if( singlevar1 == NULL )
    4227 {
    4228 singlevar1 = consdata1->vars[v1];
    4229 if( cons0hastwoothervars )
    4230 aborted = TRUE;
    4231 }
    4232 else
    4233 {
    4234 cons1hastwoothervars = TRUE;
    4235 if( singlevar0 != NULL )
    4236 aborted = TRUE;
    4237 }
    4238 v1++;
    4239 break;
    4240
    4241 case 0:
    4242 /* variable appears in both constraints */
    4243 assert(v0 < consdata0->nvars);
    4244 assert(v1 < consdata1->nvars);
    4245 assert(SCIPvarGetProbvar(consdata0->vars[v0]) == SCIPvarGetProbvar(consdata1->vars[v1]));
    4246 if( consdata0->vars[v0] != consdata1->vars[v1] )
    4247 {
    4248 assert(SCIPvarGetNegatedVar(consdata0->vars[v0]) == consdata1->vars[v1]);
    4249 parity = !parity;
    4250 }
    4251 v0++;
    4252 v1++;
    4253 break;
    4254
    4255 default:
    4256 SCIPerrorMessage("invalid comparison result\n");
    4257 SCIPABORT();
    4258 return SCIP_INVALIDDATA; /*lint !e527*/
    4259 }
    4260 }
    4261
    4262 /* check if a useful presolving is possible */
    4263 if( (cons0hastwoothervars && singlevar1 != NULL) || (cons1hastwoothervars && singlevar0 != NULL) )
    4264 continue;
    4265
    4266 /* check if one problem variable set is a subset of the other */
    4267 if( singlevar0 == NULL && singlevar1 == NULL )
    4268 {
    4269 /* both constraints are equal */
    4270 if( !parity )
    4271 {
    4272 /* even parity: constraints are redundant */
    4273 SCIPdebugMsg(scip, "xor constraints <%s> and <%s> are redundant: delete <%s>\n",
    4274 SCIPconsGetName(cons0), SCIPconsGetName(cons1), SCIPconsGetName(cons1));
    4275 SCIPdebugPrintCons(scip, cons0, NULL);
    4276 SCIPdebugPrintCons(scip, cons1, NULL);
    4277
    4278 /* delete cons1 and update flags of cons0 s.t. nonredundant information doesn't get lost */
    4279 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
    4280 SCIP_CALL( SCIPdelCons(scip, cons1) );
    4281 (*ndelconss)++;
    4282
    4283 if( consdata1->intvar != NULL )
    4284 {
    4285 /* need to update integer variable, consider the following case:
    4286 * c1: xor(x1, x2, x3) = 1 (intvar1 = y1)
    4287 * c2: xor(x1, x2, x3) = 1 (intvar0 = NULL or intvar0 = y0)
    4288 *
    4289 * if intvar0 = NULL we have to assign intvar0 = y1. otherwise, we have to ensure that y1 = y0 holds.
    4290 * if aggregation is allowed, we can aggregate both variables. otherwise, we have to add a linear
    4291 * constraint y1 - y0 = 0.
    4292 */
    4293 if( consdata0->intvar == NULL )
    4294 {
    4295 SCIP_CALL( setIntvar(scip, cons0, consdata1->intvar) );
    4296 }
    4297 else
    4298 {
    4299 /* aggregate integer variables */
    4300 SCIP_CALL( SCIPaggregateVars(scip, consdata1->intvar, consdata0->intvar, 1.0, -1.0, 0.0,
    4301 &infeasible, &redundant, &aggregated) );
    4302
    4303 *cutoff = *cutoff || infeasible;
    4304
    4305 if( aggregated )
    4306 {
    4307 ++(*naggrvars);
    4308 assert(SCIPvarIsActive(consdata0->intvar));
    4309 }
    4310 else
    4311 {
    4312 SCIP_CONS* newcons;
    4313 char consname[SCIP_MAXSTRLEN];
    4314 SCIP_VAR* newvars[2];
    4315 SCIP_Real vals[2];
    4316
    4317 newvars[0] = consdata1->intvar;
    4318 vals[0] = 1.0;
    4319 newvars[1] = consdata0->intvar;
    4320 vals[1] = -1.0;
    4321
    4322 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "agg_%s", SCIPconsGetName(cons1));
    4323
    4324 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, 2, newvars, vals, 0.0, 0.0,
    4325 SCIPconsIsInitial(cons1), SCIPconsIsSeparated(cons1), TRUE, /*SCIPconsIsEnforced(cons),*/
    4326 TRUE, TRUE, /*SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons),*/
    4329
    4330 SCIP_CALL( SCIPaddCons(scip, newcons) );
    4331 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    4332 ++(*naddconss);
    4333 }
    4334 }
    4335 }
    4336 }
    4337 else
    4338 {
    4339 /* odd parity: constraints are contradicting */
    4340 SCIPdebugMsg(scip, "xor constraints <%s> and <%s> are contradicting\n",
    4341 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
    4342 SCIPdebugPrintCons(scip, cons0, NULL);
    4343 SCIPdebugPrintCons(scip, cons1, NULL);
    4344 *cutoff = TRUE;
    4345 }
    4346 }
    4347 else if( singlevar1 == NULL )
    4348 {
    4349 /* cons1 is a subset of cons0 */
    4350 if( !cons0hastwoothervars )
    4351 {
    4352 /* only one additional variable in cons0: fix this variable according to the parity */
    4353 SCIPdebugMsg(scip, "xor constraints <%s> and <%s> yield sum %u == <%s>\n",
    4354 SCIPconsGetName(cons0), SCIPconsGetName(cons1), parity, SCIPvarGetName(singlevar0));
    4355 SCIPdebugPrintCons(scip, cons0, NULL);
    4356 SCIPdebugPrintCons(scip, cons1, NULL);
    4357 SCIP_CALL( SCIPfixVar(scip, singlevar0, parity ? 1.0 : 0.0, &infeasible, &fixed) );
    4358 *cutoff = *cutoff || infeasible;
    4359 if( fixed )
    4360 (*nfixedvars)++;
    4361
    4362 /* delete cons1 and update flags of cons0 s.t. nonredundant information doesn't get lost */
    4363 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
    4364 SCIP_CALL( SCIPdelCons(scip, cons1) );
    4365 (*ndelconss)++;
    4366 }
    4367 else
    4368 {
    4369 int v;
    4370
    4371 /* more than one additional variable in cons0: add cons1 to cons0, thus eliminating the equal variables */
    4372 SCIPdebugMsg(scip, "xor constraint <%s> is superset of <%s> with parity %u\n",
    4373 SCIPconsGetName(cons0), SCIPconsGetName(cons1), parity);
    4374 SCIPdebugPrintCons(scip, cons0, NULL);
    4375 SCIPdebugPrintCons(scip, cons1, NULL);
    4376 for( v = 0; v < consdata1->nvars; ++v )
    4377 {
    4378 SCIP_CALL( addCoef(scip, cons0, consdata1->vars[v]) );
    4379 }
    4380
    4381 SCIP_CALL( applyFixings(scip, cons0, conshdlrdata->eventhdlr, nchgcoefs, naggrvars, naddconss, cutoff) );
    4382 assert(SCIPconsGetData(cons0) == consdata0);
    4383 assert(consdata0->nvars >= 2); /* at least the two "other" variables should remain in the constraint */
    4384 }
    4385
    4386 if( *cutoff )
    4387 return SCIP_OKAY;
    4388
    4389 consdataSort(consdata0);
    4390 assert(consdata0->sorted);
    4391 }
    4392 else if( singlevar0 == NULL )
    4393 {
    4394 /* cons0 is a subset of cons1 */
    4395 if( !cons1hastwoothervars )
    4396 {
    4397 /* only one additional variable in cons1: fix this variable according to the parity */
    4398 SCIPdebugMsg(scip, "xor constraints <%s> and <%s> yield sum %u == <%s>\n",
    4399 SCIPconsGetName(cons0), SCIPconsGetName(cons1), parity, SCIPvarGetName(singlevar1));
    4400 SCIPdebugPrintCons(scip, cons0, NULL);
    4401 SCIPdebugPrintCons(scip, cons1, NULL);
    4402 SCIP_CALL( SCIPfixVar(scip, singlevar1, parity ? 1.0 : 0.0, &infeasible, &fixed) );
    4403 assert(infeasible || fixed);
    4404 *cutoff = *cutoff || infeasible;
    4405 (*nfixedvars)++;
    4406
    4407 /* delete cons1 and update flags of cons0 s.t. nonredundant information doesn't get lost */
    4408 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
    4409 SCIP_CALL( SCIPdelCons(scip, cons1) );
    4410 (*ndelconss)++;
    4411 }
    4412 else
    4413 {
    4414 int v;
    4415
    4416 /* more than one additional variable in cons1: add cons0 to cons1, thus eliminating the equal variables */
    4417 SCIPdebugMsg(scip, "xor constraint <%s> is subset of <%s> with parity %u\n",
    4418 SCIPconsGetName(cons0), SCIPconsGetName(cons1), parity);
    4419 SCIPdebugPrintCons(scip, cons0, NULL);
    4420 SCIPdebugPrintCons(scip, cons1, NULL);
    4421 for( v = 0; v < consdata0->nvars; ++v )
    4422 {
    4423 SCIP_CALL( addCoef(scip, cons1, consdata0->vars[v]) );
    4424 }
    4425 SCIP_CALL( applyFixings(scip, cons1, conshdlrdata->eventhdlr, nchgcoefs, naggrvars, naddconss, cutoff) );
    4426 assert(SCIPconsGetData(cons1) == consdata1);
    4427 assert(consdata1->nvars >= 2); /* at least the two "other" variables should remain in the constraint */
    4428
    4429 if( *cutoff )
    4430 return SCIP_OKAY;
    4431
    4432 consdataSort(consdata1);
    4433 assert(consdata1->sorted);
    4434 }
    4435 }
    4436 else
    4437 {
    4438 assert(!cons0hastwoothervars);
    4439 assert(!cons1hastwoothervars);
    4440
    4441 /* sum of constraints is parity == singlevar0 xor singlevar1: aggregate variables and delete cons1 */
    4442 SCIPdebugMsg(scip, "xor constraints <%s> and <%s> yield sum %u == xor(<%s>,<%s>)\n",
    4443 SCIPconsGetName(cons0), SCIPconsGetName(cons1), parity, SCIPvarGetName(singlevar0),
    4444 SCIPvarGetName(singlevar1));
    4445 if( !parity )
    4446 {
    4447 /* aggregate singlevar0 == singlevar1 */
    4448 SCIP_CALL( SCIPaggregateVars(scip, singlevar1, singlevar0, 1.0, -1.0, 0.0,
    4449 &infeasible, &redundant, &aggregated) );
    4450 }
    4451 else
    4452 {
    4453 /* aggregate singlevar0 == 1-singlevar1 */
    4454 SCIP_CALL( SCIPaggregateVars(scip, singlevar1, singlevar0, 1.0, 1.0, 1.0,
    4455 &infeasible, &redundant, &aggregated) );
    4456 }
    4457 assert(infeasible || redundant || SCIPdoNotAggr(scip));
    4458
    4459 *cutoff = *cutoff || infeasible;
    4460 if( aggregated )
    4461 ++(*naggrvars);
    4462
    4463 if( redundant )
    4464 {
    4465 /* delete cons1 and update flags of cons0 s.t. nonredundant information doesn't get lost */
    4466 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
    4467 SCIP_CALL( SCIPdelCons(scip, cons1) );
    4468 (*ndelconss)++;
    4469
    4470 if( consdata1->intvar != NULL )
    4471 {
    4472 if( consdata0->intvar == NULL )
    4473 {
    4474 SCIP_CALL( setIntvar(scip, cons0, consdata0->intvar) );
    4475 }
    4476 else
    4477 {
    4478 /* aggregate integer variables */
    4479 SCIP_CALL( SCIPaggregateVars(scip, consdata1->intvar, consdata0->intvar, 1.0, -1.0, 0.0,
    4480 &infeasible, &redundant, &aggregated) );
    4481
    4482 *cutoff = *cutoff || infeasible;
    4483 if( aggregated )
    4484 ++(*naggrvars);
    4485 }
    4486 }
    4487 }
    4488
    4489 if( !consdata0->sorted )
    4490 consdataSort(consdata0);
    4491 assert(consdata0->sorted);
    4492
    4493#ifdef SCIP_DISABLED_CODE
    4494 /* TODO: consider running applyFixings() on the persistent constraint to detect a cutoff */
    4495 /* remove all variables that are fixed to zero and all pairs of variables fixed to one;
    4496 * merge multiple entries of the same or negated variables
    4497 */
    4498 SCIP_CALL( applyFixings(scip, cons0, conshdlrdata->eventhdlr, nchgcoefs, naggrvars, naddconss, cutoff) );
    4499
    4500 if( *cutoff )
    4501 return SCIP_OKAY;
    4502#endif
    4503 }
    4504 }
    4505
    4506 return SCIP_OKAY;
    4507}
    4508
    4509/** creates and captures a xor constraint x_0 xor ... xor x_{k-1} = rhs with a given artificial integer variable for the
    4510 * linear relaxation
    4511 *
    4512 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    4513 */
    4514static
    4516 SCIP* scip, /**< SCIP data structure */
    4517 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    4518 const char* name, /**< name of constraint */
    4519 SCIP_Bool rhs, /**< right hand side of the constraint */
    4520 int nvars, /**< number of operator variables in the constraint */
    4521 SCIP_VAR** vars, /**< array with operator variables of constraint */
    4522 SCIP_VAR* intvar, /**< integer variable for linear relaxation or NULL if artificial */
    4523 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
    4524 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    4525 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
    4526 * Usually set to TRUE. */
    4527 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    4528 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    4529 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    4530 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    4531 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
    4532 * Usually set to TRUE. */
    4533 SCIP_Bool local, /**< is constraint only valid locally?
    4534 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    4535 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
    4536 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
    4537 * adds coefficients to this constraint. */
    4538 SCIP_Bool dynamic, /**< is constraint subject to aging?
    4539 * Usually set to FALSE. Set to TRUE for own cuts which
    4540 * are separated as constraints. */
    4541 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
    4542 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
    4543 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    4544 * if it may be moved to a more global node?
    4545 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
    4546 )
    4547{
    4548 SCIP_CONSHDLR* conshdlr;
    4549 SCIP_CONSDATA* consdata;
    4550 SCIP_VARTYPE intvartype;
    4551 int i;
    4552
    4553 /* find the xor constraint handler */
    4554 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    4555 if( conshdlr == NULL )
    4556 {
    4557 SCIPerrorMessage("xor constraint handler not found\n");
    4558 return SCIP_PLUGINNOTFOUND;
    4559 }
    4560
    4561 /* check whether int variable is integral */
    4562 if( intvar != NULL )
    4563 {
    4564 intvartype = SCIPvarGetType(intvar);
    4565
    4566 if( intvartype != SCIP_VARTYPE_BINARY && intvartype != SCIP_VARTYPE_INTEGER )
    4567 {
    4568 SCIPerrorMessage("intvar <%s> is not enforced integral\n", SCIPvarGetName(intvar));
    4569 return SCIP_INVALIDDATA;
    4570 }
    4571 }
    4572
    4573 /* check whether all variables are binary */
    4574 assert(vars != NULL || nvars == 0);
    4575 for( i = 0; i < nvars; ++i )
    4576 {
    4577 if( !SCIPvarIsBinary(vars[i]) )
    4578 {
    4579 SCIPerrorMessage("operand <%s> is not binary\n", SCIPvarGetName(vars[i]));
    4580 return SCIP_INVALIDDATA;
    4581 }
    4582 }
    4583
    4584 /* create constraint data */
    4585 SCIP_CALL( consdataCreate(scip, &consdata, rhs, nvars, vars, intvar) );
    4586
    4587 /* create constraint */
    4588 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
    4589 local, modifiable, dynamic, removable, stickingatnode) );
    4590
    4591 return SCIP_OKAY;
    4592}
    4593
    4594
    4595
    4596/*
    4597 * Linear constraint upgrading
    4598 */
    4599
    4600/** tries to upgrade a linear constraint into an xor constraint
    4601 *
    4602 * Assuming all variables are binary and have coefficients with an absolute value 1, except for an integer (or binary) variable
    4603 * \f$z\f$ which has coefficient \f$a \in \{-2,2\}\f$ with absolute value 2 and appears only in this constraint,
    4604 * we can transform:
    4605 * \f[
    4606 * \begin{array}{ll}
    4607 * & -\sum_{i \in I} x_i + \sum_{j \in J} x_j + a \cdot z = r \\
    4608 * \Leftrightarrow & \sum_{i \in I} \bar{x}_i + \sum_{j \in J} x_j + a \cdot z = r + |I| \\
    4609 * \Leftrightarrow & \sum_{i \in I} \bar{x}_i + \sum_{j \in J} x_j - 2 \cdot y = (r + |I|) \text{ mod } 2,
    4610 * \end{array}
    4611 * \f]
    4612 * where
    4613 * \f[
    4614 * y = \begin{cases}
    4615 * \left\lfloor \frac{r + |I|}{2} \right\rfloor + z & \text{if }a = -2\\
    4616 * \left\lfloor \frac{r + |I|}{2} \right\rfloor - z & \text{if }a = 2.
    4617 * \end{cases}
    4618 * \f]
    4619 * If \f$a = -2\f$ and \f$z \in [\ell_z, u_z]\f$, then \f$y \in [\ell_y, u_y]\f$, where \f$\ell_y = \left\lfloor
    4620 * \frac{r + |I|}{2} \right\rfloor + \ell_z\f$ and \f$u_y = \left\lfloor \frac{r + |I|}{2} \right\rfloor + u_z\f$.
    4621 *
    4622 * If \f$a = 2\f$, then \f$\ell_y = \left\lfloor \frac{r + |I|}{2} \right\rfloor - u_z\f$ and \f$u_y = \left\lfloor
    4623 * \frac{r + |I|}{2} \right\rfloor - \ell_z\f$.
    4624 *
    4625 * Then consider the resulting XOR-constraint
    4626 * \f[
    4627 * \bigoplus_{i \in I} \bar{x}_i \oplus \bigoplus_{j \in j} x_j = (r + |I|) \text{ mod } 2.
    4628 * \f]
    4629 * If \f$\ell_y \leq 0\f$ and \f$u_y \geq (|I| + |J|)/2\f$, then the XOR constraint is a reformulation of the above
    4630 * transformed constraint, otherwise it is a relaxation because the bounds on the \f$y\f$-variable may disallow
    4631 * too many (or too few) operators set to 1. Therefore, the XOR constraint handler verifies in this case that the linear
    4632 * equation holds, ie., that the \f$y\f$-variable has the correct value.
    4633 */
    4634static
    4636{ /*lint --e{715}*/
    4637 assert(upgdcons != NULL);
    4638 assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), "linear") == 0);
    4639 assert(!SCIPconsIsModifiable(cons));
    4640
    4641 /* check, if linear constraint can be upgraded to xor constraint */
    4642 /* @todo also applicable if the integer variable has a coefficient different from 2, e.g. a coefficient like 0.5 then
    4643 * we could generate a new integer variable aggregated to the old one, possibly the constraint was then
    4644 * normalized and all binary variables have coefficients of 2.0, if the coefficient is 4 then we need holes ...
    4645 */
    4646 if( integral && nposcont + nnegcont == 0 && nposbin + nnegbin + nposimplbin + nnegimplbin >= nvars-1 && ncoeffspone + ncoeffsnone == nvars-1 && ncoeffspint + ncoeffsnint == 1 )
    4647 {
    4648 assert(ncoeffspfrac + ncoeffsnfrac == 0);
    4649
    4650 if( SCIPisEQ(scip, lhs, rhs) && SCIPisIntegral(scip, lhs) )
    4651 {
    4652 SCIP_VAR** xorvars;
    4653 SCIP_VAR* parityvar = NULL;
    4654 SCIP_VARTYPE parityvartype;
    4655 SCIP_Bool postwo = FALSE;
    4656 int cnt = 0;
    4657 int j;
    4658
    4659 SCIP_CALL( SCIPallocBufferArray(scip, &xorvars, nvars) );
    4660
    4661 /* check parity of constraints */
    4662 for( j = nvars - 1; j >= 0; --j )
    4663 {
    4664 if( SCIPisEQ(scip, REALABS(vals[j]), 2.0) )
    4665 {
    4666 parityvar = vars[j];
    4667 parityvartype = SCIPvarGetType(parityvar);
    4668
    4669 /* parity variable requires enforced integrality */
    4670 if( parityvartype != SCIP_VARTYPE_BINARY && parityvartype != SCIP_VARTYPE_INTEGER )
    4671 {
    4672 parityvar = NULL;
    4673 break;
    4674 }
    4675
    4676 postwo = (vals[j] > 0.0);
    4677 }
    4678 else if( !SCIPisEQ(scip, REALABS(vals[j]), 1.0) )
    4679 break;
    4680 else
    4681 {
    4682 /* exit if variable is not binary or implicit binary */
    4683 if( !SCIPvarIsBinary(vars[j]) )
    4684 {
    4685 parityvar = NULL;
    4686 break;
    4687 }
    4688
    4689 /* need negated variables for correct propagation to the integer variable */
    4690 if( vals[j] < 0.0 )
    4691 {
    4692 SCIP_CALL( SCIPgetNegatedVar(scip, vars[j], &(xorvars[cnt])) );
    4693 assert(xorvars[cnt] != NULL);
    4694 }
    4695 else
    4696 xorvars[cnt] = vars[j];
    4697 ++cnt;
    4698 }
    4699 }
    4700
    4701 if( parityvar != NULL )
    4702 {
    4703 assert(cnt == nvars - 1);
    4704
    4705 /* check whether parity variable is present only in this constraint */
    4707 && SCIPvarGetNLocksUpType(parityvar, SCIP_LOCKTYPE_MODEL) <= 1 )
    4708 {
    4709 SCIP_VAR* intvar;
    4710 SCIP_Bool rhsparity;
    4711 SCIP_Bool neednew;
    4712 int intrhs;
    4713
    4714 /* adjust the side, since we negated all binary variables with -1.0 as a coefficient */
    4715 rhs += ncoeffsnone;
    4716
    4717 intrhs = (int) SCIPfloor(scip, rhs);
    4718 rhsparity = ((SCIP_Bool) (intrhs % 2)); /*lint !e571*/
    4719
    4720 /* we need a new variable if the rhs is not 0 or 1 or if the coefficient was +2, since in these cases, we
    4721 * need to aggregate the variables (flipping signs and/or shifting */
    4722 if( (intrhs != 1 && intrhs != 0) || postwo )
    4723 neednew = TRUE;
    4724 else
    4725 neednew = FALSE;
    4726
    4727 /* check if we can use the parity variable as integer variable of the XOR constraint or do we need to
    4728 * create a new variable and aggregate */
    4729 if( neednew )
    4730 {
    4731 char varname[SCIP_MAXSTRLEN];
    4732 SCIP_Real lb;
    4733 SCIP_Real ub;
    4734 SCIP_Bool isbinary;
    4735 SCIP_Bool infeasible;
    4736 SCIP_Bool redundant;
    4737 SCIP_Bool aggregated;
    4738 int intrhshalfed;
    4739
    4740 intrhshalfed = intrhs / 2;
    4741
    4742 if( postwo )
    4743 {
    4744 lb = intrhshalfed - SCIPvarGetUbGlobal(parityvar);
    4745 ub = intrhshalfed - SCIPvarGetLbGlobal(parityvar);
    4746 }
    4747 else
    4748 {
    4749 lb = intrhshalfed + SCIPvarGetLbGlobal(parityvar);
    4750 ub = intrhshalfed + SCIPvarGetUbGlobal(parityvar);
    4751 }
    4752 assert(SCIPisFeasLE(scip, lb, ub));
    4753 assert(SCIPisFeasIntegral(scip, lb));
    4754 assert(SCIPisFeasIntegral(scip, ub));
    4755
    4756 /* adjust bounds to be more integral */
    4757 lb = SCIPfeasFloor(scip, lb);
    4758 ub = SCIPfeasFloor(scip, ub);
    4759
    4760 isbinary = (SCIPisZero(scip, lb) && SCIPisEQ(scip, ub, 1.0));
    4761
    4762 /* something is wrong if parity variable is already binary, but artificial variable is not */
    4763 if( SCIPvarIsBinary(parityvar) && !isbinary )
    4764 {
    4765 SCIPfreeBufferArray(scip, &xorvars);
    4766 return SCIP_OKAY;
    4767 }
    4768
    4769 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s_xor_upgr", SCIPvarGetName(parityvar));
    4770 SCIP_CALL( SCIPcreateVar(scip, &intvar, varname, lb, ub, 0.0,
    4772 SCIPvarIsInitial(parityvar), SCIPvarIsRemovable(parityvar), NULL, NULL, NULL, NULL, NULL) );
    4773 SCIP_CALL( SCIPaddVar(scip, intvar) );
    4774
    4775 SCIPdebugMsg(scip, "created new variable for aggregation:");
    4776 SCIPdebug( SCIPprintVar(scip, intvar, NULL) );
    4777
    4778 SCIP_CALL( SCIPaggregateVars(scip, parityvar, intvar, 1.0, postwo ? 1.0 : -1.0,
    4779 (SCIP_Real) (postwo ? intrhshalfed : -intrhshalfed), &infeasible, &redundant, &aggregated) );
    4780 assert(!infeasible);
    4781
    4782 /* maybe aggregation was forbidden, than we cannot upgrade this constraint */
    4783 if( !aggregated )
    4784 {
    4785 SCIPfreeBufferArray(scip, &xorvars);
    4786 return SCIP_OKAY;
    4787 }
    4788
    4789 assert(redundant);
    4790 assert(SCIPvarIsActive(intvar));
    4791
    4792#ifdef SCIP_DEBUG
    4794 {
    4795 SCIPdebugMsg(scip, "aggregated: <%s> = %g * <%s> + %g\n", SCIPvarGetName(parityvar),
    4797 SCIPvarGetAggrConstant(parityvar));
    4798 }
    4799 else
    4800 {
    4801 assert(SCIPvarGetStatus(parityvar) == SCIP_VARSTATUS_NEGATED);
    4802 SCIPdebugMsg(scip, "negated: <%s> = 1 - <%s>\n", SCIPvarGetName(parityvar),
    4804 }
    4805#endif
    4806 }
    4807 else
    4808 intvar = parityvar;
    4809
    4810 assert(intvar != NULL);
    4811
    4812 SCIP_CALL( createConsXorIntvar(scip, upgdcons, SCIPconsGetName(cons), rhsparity, nvars - 1, xorvars, intvar,
    4817
    4818 SCIPdebugMsg(scip, "upgraded constraint <%s> to XOR constraint:\n", SCIPconsGetName(cons));
    4819 SCIPdebugPrintCons(scip, *upgdcons, NULL);
    4820
    4821 if( neednew )
    4822 {
    4823 assert(intvar != parityvar);
    4824 SCIP_CALL( SCIPreleaseVar(scip, &intvar) );
    4825 }
    4826 }
    4827 }
    4828
    4829 SCIPfreeBufferArray(scip, &xorvars);
    4830 }
    4831 }
    4832
    4833 return SCIP_OKAY;
    4834}
    4835
    4836/** adds symmetry information of constraint to a symmetry detection graph */
    4837static
    4839 SCIP* scip, /**< SCIP pointer */
    4840 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
    4841 SCIP_CONS* cons, /**< constraint */
    4842 SYM_GRAPH* graph, /**< symmetry detection graph */
    4843 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
    4844 )
    4845{
    4846 SCIP_CONSDATA* consdata;
    4847 SCIP_VAR** xorvars;
    4848 SCIP_VAR** vars;
    4849 SCIP_Real* vals;
    4850 SCIP_Real constant;
    4851 int consnodeidx;
    4852 int nlocvars;
    4853 int i;
    4854
    4855 assert(scip != NULL);
    4856 assert(cons != NULL);
    4857 assert(graph != NULL);
    4858 assert(success != NULL);
    4859
    4860 consdata = SCIPconsGetData(cons);
    4861 assert(consdata != NULL);
    4862
    4863 /* create arrays to store active representation of variables */
    4864 nlocvars = MAX(consdata->nvars, 1);
    4865 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nlocvars) );
    4866 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nlocvars) );
    4867
    4868 /* add constraint node */
    4869 SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, 0.0, 0.0, &consnodeidx) );
    4870
    4871 /* add intvar to symmetry detection graph */
    4872 if( consdata->intvar != NULL)
    4873 {
    4874 int xornodeidx;
    4875
    4876 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int)SYM_CONSOPTYPE_XORINT, &xornodeidx) );
    4877 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, xornodeidx, FALSE, 0.0) );
    4878
    4879 vars[0] = consdata->intvar;
    4880 vals[0] = 1.0;
    4881 constant = 0.0;
    4882 nlocvars = 1;
    4883 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
    4884 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, xornodeidx, vars, vals, nlocvars, constant) );
    4885 }
    4886
    4887 /* add node modeling the XOR-part and connect it with constraint node */
    4888 xorvars = consdata->vars;
    4889 for( i = 0; i < consdata->nvars; ++i )
    4890 {
    4891 assert(xorvars[i] != NULL);
    4892 vars[i] = xorvars[i];
    4893 vals[i] = 1.0;
    4894 }
    4895 constant = -(SCIP_Real)SCIPgetRhsXor(scip, cons);
    4896 nlocvars = consdata->nvars;
    4897 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
    4898 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, consnodeidx, vars, vals, nlocvars, constant) );
    4899
    4900 SCIPfreeBufferArray(scip, &vals);
    4901 SCIPfreeBufferArray(scip, &vars);
    4902
    4903 *success = TRUE;
    4904
    4905 return SCIP_OKAY;
    4906}
    4907
    4908/*
    4909 * Callback methods of constraint handler
    4910 */
    4911
    4912/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    4913static
    4915{ /*lint --e{715}*/
    4916 assert(scip != NULL);
    4917 assert(conshdlr != NULL);
    4918 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    4919
    4920 /* call inclusion method of constraint handler */
    4922
    4923 *valid = TRUE;
    4924
    4925 return SCIP_OKAY;
    4926}
    4927
    4928/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
    4929static
    4931{ /*lint --e{715}*/
    4932 SCIP_CONSHDLRDATA* conshdlrdata;
    4933
    4934 /* free constraint handler data */
    4935 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4936 assert(conshdlrdata != NULL);
    4937
    4938 conshdlrdataFree(scip, &conshdlrdata);
    4939
    4940 SCIPconshdlrSetData(conshdlr, NULL);
    4941
    4942 return SCIP_OKAY;
    4943}
    4944
    4945/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
    4946static
    4948{ /*lint --e{715}*/
    4949 SCIP_CONSDATA* consdata;
    4950 int c;
    4951
    4952 /* release and free the rows of all constraints */
    4953 for( c = 0; c < nconss; ++c )
    4954 {
    4955 consdata = SCIPconsGetData(conss[c]);
    4956 SCIP_CALL( consdataFreeRows(scip, consdata) );
    4957 }
    4958
    4959 return SCIP_OKAY;
    4960}
    4961
    4962
    4963/** frees specific constraint data */
    4964static
    4966{ /*lint --e{715}*/
    4967 SCIP_CONSHDLRDATA* conshdlrdata;
    4968
    4969 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4970 assert(conshdlrdata != NULL);
    4971
    4973 {
    4974 int v;
    4975
    4976 for( v = (*consdata)->nvars - 1; v >= 0; --v )
    4977 {
    4978 SCIP_CALL( SCIPdropVarEvent(scip, (*consdata)->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
    4979 (SCIP_EVENTDATA*)(*consdata), -1) );
    4980 }
    4981 }
    4982
    4983 SCIP_CALL( consdataFree(scip, consdata, conshdlrdata->eventhdlr) );
    4984
    4985 return SCIP_OKAY;
    4986}
    4987
    4988
    4989/** transforms constraint data into data belonging to the transformed problem */
    4990static
    4992{ /*lint --e{715}*/
    4993 SCIP_CONSDATA* sourcedata;
    4994 SCIP_CONSDATA* targetdata;
    4995
    4996 sourcedata = SCIPconsGetData(sourcecons);
    4997 assert(sourcedata != NULL);
    4998 assert(sourcedata->nvars >= 1);
    4999 assert(sourcedata->vars != NULL);
    5000
    5001 /* create target constraint data */
    5002 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->rhs, sourcedata->nvars, sourcedata->vars, sourcedata->intvar) );
    5003
    5004 /* create target constraint */
    5005 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
    5006 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
    5007 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
    5008 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
    5009 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
    5010
    5011 return SCIP_OKAY;
    5012}
    5013
    5014
    5015/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
    5016static
    5018{ /*lint --e{715}*/
    5019 int i;
    5020
    5021 assert(infeasible != NULL);
    5022
    5023 *infeasible = FALSE;
    5024
    5025 for( i = 0; i < nconss && !(*infeasible); i++ )
    5026 {
    5027 assert(SCIPconsIsInitial(conss[i]));
    5028 SCIP_CALL( addRelaxation(scip, conss[i], infeasible) );
    5029 }
    5030
    5031 return SCIP_OKAY;
    5032}
    5033
    5034
    5035/** separation method of constraint handler for LP solutions */
    5036static
    5038{ /*lint --e{715}*/
    5039 SCIP_CONSHDLRDATA* conshdlrdata;
    5040 SCIP_Bool separated;
    5041 SCIP_Bool cutoff;
    5042 int c;
    5043
    5044 *result = SCIP_DIDNOTFIND;
    5045
    5046 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    5047 assert(conshdlrdata != NULL);
    5048
    5049 /* separate all useful constraints */
    5050 for( c = 0; c < nusefulconss; ++c )
    5051 {
    5052 SCIP_CALL( separateCons(scip, conss[c], NULL, conshdlrdata->separateparity, &separated, &cutoff) );
    5053 if( cutoff )
    5054 *result = SCIP_CUTOFF;
    5055 else if( separated )
    5056 *result = SCIP_SEPARATED;
    5057 }
    5058
    5059 /* combine constraints to get more cuts */
    5060 /**@todo combine constraints to get further cuts */
    5061
    5062 return SCIP_OKAY;
    5063}
    5064
    5065
    5066/** separation method of constraint handler for arbitrary primal solutions */
    5067static
    5069{ /*lint --e{715}*/
    5070 SCIP_CONSHDLRDATA* conshdlrdata;
    5071 SCIP_Bool separated;
    5072 SCIP_Bool cutoff;
    5073 int c;
    5074
    5075 *result = SCIP_DIDNOTFIND;
    5076
    5077 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    5078 assert(conshdlrdata != NULL);
    5079
    5080 /* separate all useful constraints */
    5081 for( c = 0; c < nusefulconss; ++c )
    5082 {
    5083 SCIP_CALL( separateCons(scip, conss[c], sol, conshdlrdata->separateparity, &separated, &cutoff) );
    5084 if( cutoff )
    5085 *result = SCIP_CUTOFF;
    5086 else if( separated )
    5087 *result = SCIP_SEPARATED;
    5088 }
    5089
    5090 /* combine constraints to get more cuts */
    5091 /**@todo combine constraints to get further cuts */
    5092
    5093 return SCIP_OKAY;
    5094}
    5095
    5096
    5097/** constraint enforcing method of constraint handler for LP solutions */
    5098static
    5100{ /*lint --e{715}*/
    5101 SCIP_CONSHDLRDATA* conshdlrdata;
    5102 SCIP_Bool violated;
    5103 SCIP_Bool cutoff;
    5104 int i;
    5105
    5106 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    5107 assert(conshdlrdata != NULL);
    5108
    5109 /* method is called only for integral solutions, because the enforcing priority is negative */
    5110 for( i = 0; i < nconss; i++ )
    5111 {
    5112 SCIP_CALL( checkCons(scip, conss[i], NULL, FALSE, FALSE, &violated) );
    5113 if( violated )
    5114 {
    5115 SCIP_Bool separated;
    5116
    5117 SCIP_CALL( separateCons(scip, conss[i], NULL, conshdlrdata->separateparity, &separated, &cutoff) );
    5118 if( cutoff )
    5119 *result = SCIP_CUTOFF;
    5120 else
    5121 {
    5122 assert(separated); /* because the solution is integral, the separation always finds a cut */
    5123 *result = SCIP_SEPARATED;
    5124 }
    5125 return SCIP_OKAY;
    5126 }
    5127 }
    5128 *result = SCIP_FEASIBLE;
    5129
    5130 return SCIP_OKAY;
    5131}
    5132
    5133
    5134/** constraint enforcing method of constraint handler for relaxation solutions */
    5135static
    5137{ /*lint --e{715}*/
    5138 SCIP_CONSHDLRDATA* conshdlrdata;
    5139 SCIP_Bool violated;
    5140 SCIP_Bool cutoff;
    5141 int i;
    5142
    5143 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    5144 assert(conshdlrdata != NULL);
    5145
    5146 /* method is called only for integral solutions, because the enforcing priority is negative */
    5147 for( i = 0; i < nconss; i++ )
    5148 {
    5149 SCIP_CALL( checkCons(scip, conss[i], sol, FALSE, FALSE, &violated) );
    5150 if( violated )
    5151 {
    5152 SCIP_Bool separated;
    5153
    5154 SCIP_CALL( separateCons(scip, conss[i], sol, conshdlrdata->separateparity, &separated, &cutoff) );
    5155 if( cutoff )
    5156 *result = SCIP_CUTOFF;
    5157 else
    5158 {
    5159 assert(separated); /* because the solution is integral, the separation always finds a cut */
    5160 *result = SCIP_SEPARATED;
    5161 }
    5162 return SCIP_OKAY;
    5163 }
    5164 }
    5165 *result = SCIP_FEASIBLE;
    5166
    5167 return SCIP_OKAY;
    5168}
    5169
    5170
    5171/** constraint enforcing method of constraint handler for pseudo solutions */
    5172static
    5174{ /*lint --e{715}*/
    5175 SCIP_Bool violated;
    5176 int i;
    5177
    5178 /* method is called only for integral solutions, because the enforcing priority is negative */
    5179 for( i = 0; i < nconss; i++ )
    5180 {
    5181 SCIP_CALL( checkCons(scip, conss[i], NULL, TRUE, FALSE, &violated) );
    5182 if( violated )
    5183 {
    5184 *result = SCIP_INFEASIBLE;
    5185 return SCIP_OKAY;
    5186 }
    5187 }
    5188 *result = SCIP_FEASIBLE;
    5189
    5190 return SCIP_OKAY;
    5191}
    5192
    5193/** feasibility check method of constraint handler xor */
    5194static
    5196{ /*lint --e{715}*/
    5197 SCIP_Bool violated;
    5198 int i;
    5199
    5200 *result = SCIP_FEASIBLE;
    5201
    5202 for( i = 0; i < nconss && ( *result == SCIP_FEASIBLE || completely ); ++i )
    5203 {
    5204 SCIP_CALL( checkCons(scip, conss[i], sol, checklprows, printreason, &violated) );
    5205 if( violated )
    5206 *result = SCIP_INFEASIBLE;
    5207 }
    5208
    5209 return SCIP_OKAY;
    5210}
    5211
    5212/** domain propagation method of constraint handler */
    5213static
    5215{ /*lint --e{715}*/
    5216 SCIP_CONSHDLRDATA* conshdlrdata;
    5217 SCIP_Bool cutoff;
    5218 int nfixedvars;
    5219 int nchgbds;
    5220 int c;
    5221
    5222 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    5223 assert(conshdlrdata != NULL);
    5224
    5225 cutoff = FALSE;
    5226 nfixedvars = 0;
    5227 nchgbds = 0;
    5228
    5229 /* propagate all useful constraints */
    5230 for( c = 0; c < nusefulconss && !cutoff; ++c )
    5231 {
    5232 SCIP_CALL( propagateCons(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &nfixedvars, &nchgbds) );
    5233 }
    5234
    5235 /* return the correct result */
    5236 if( cutoff )
    5237 *result = SCIP_CUTOFF;
    5238 else if( nfixedvars > 0 || nchgbds > 0 )
    5239 *result = SCIP_REDUCEDDOM;
    5240 else
    5241 {
    5242 *result = SCIP_DIDNOTFIND;
    5243 if( !SCIPinProbing(scip) )
    5244 {
    5245 int depth;
    5246 int freq;
    5247
    5248 depth = SCIPgetDepth(scip);
    5249 freq = conshdlrdata->gausspropfreq;
    5250 if( (depth == 0 && freq == 0) || (freq > 0 && depth % freq == 0) )
    5251 {
    5252 /* take useful constraints only - might improve success rate to take all */
    5253 SCIP_CALL( checkSystemGF2(scip, conss, nusefulconss, NULL, result) );
    5254 }
    5255 }
    5256 }
    5257
    5258 return SCIP_OKAY;
    5259}
    5260
    5261/** presolving initialization method of constraint handler (called when presolving is about to begin) */
    5262static
    5264{ /*lint --e{715}*/
    5265 SCIP_CONSHDLRDATA* conshdlrdata;
    5266 SCIP_CONSDATA* consdata;
    5267 int c;
    5268 int v;
    5269
    5270 assert(conshdlr != NULL);
    5271 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    5272 assert(conshdlrdata != NULL);
    5273
    5274 /* catch all variable event for deleted variables, which is only used in presolving */
    5275 for( c = nconss - 1; c >= 0; --c )
    5276 {
    5277 consdata = SCIPconsGetData(conss[c]);
    5278 assert(consdata != NULL);
    5279
    5280 for( v = consdata->nvars - 1; v >= 0; --v )
    5281 {
    5282 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
    5283 (SCIP_EVENTDATA*)consdata, NULL) );
    5284 }
    5285 }
    5286
    5287 return SCIP_OKAY;
    5288}
    5289
    5290/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
    5291static
    5293{ /*lint --e{715}*/
    5294 SCIP_CONSHDLRDATA* conshdlrdata;
    5295 SCIP_CONSDATA* consdata;
    5296 int c;
    5297 int v;
    5298
    5299 assert(conshdlr != NULL);
    5300 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    5301 assert(conshdlrdata != NULL);
    5302
    5303 /* drop all variable event for deleted variables, which was only used in presolving */
    5304 for( c = 0; c < nconss; ++c )
    5305 {
    5306 consdata = SCIPconsGetData(conss[c]);
    5307 assert(consdata != NULL);
    5308
    5309 if( !SCIPconsIsDeleted(conss[c]) )
    5310 {
    5311 for( v = 0; v < consdata->nvars; ++v )
    5312 {
    5313 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
    5314 (SCIP_EVENTDATA*)consdata, -1) );
    5315 }
    5316 }
    5317 }
    5318
    5319 return SCIP_OKAY;
    5320}
    5321
    5322/** presolving method of constraint handler */
    5323static
    5325{ /*lint --e{715}*/
    5326 SCIP_CONSHDLRDATA* conshdlrdata;
    5327 SCIP_CONS* cons;
    5328 SCIP_CONSDATA* consdata;
    5329 SCIP_Bool cutoff;
    5330 SCIP_Bool redundant;
    5331 SCIP_Bool aggregated;
    5332 int oldnfixedvars;
    5333 int oldnchgbds;
    5334 int oldnaggrvars;
    5335 int oldndelconss;
    5336 int oldnchgcoefs;
    5337 int firstchange;
    5338 int c;
    5339
    5340 assert(result != NULL);
    5341
    5342 oldnfixedvars = *nfixedvars;
    5343 oldnchgbds = *nchgbds;
    5344 oldnaggrvars = *naggrvars;
    5345 oldndelconss = *ndelconss;
    5346 oldnchgcoefs = *nchgcoefs;
    5347
    5348 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    5349 assert(conshdlrdata != NULL);
    5350
    5351 /* process constraints */
    5352 cutoff = FALSE;
    5353 firstchange = INT_MAX;
    5354 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
    5355 {
    5356 cons = conss[c];
    5357 assert(cons != NULL);
    5358 consdata = SCIPconsGetData(cons);
    5359 assert(consdata != NULL);
    5360
    5361 /* force presolving the constraint in the initial round */
    5362 if( nrounds == 0 )
    5363 consdata->propagated = FALSE;
    5364
    5365 /* remember the first changed constraint to begin the next aggregation round with */
    5366 if( firstchange == INT_MAX && consdata->changed )
    5367 firstchange = c;
    5368
    5369 /* remove all variables that are fixed to zero and all pairs of variables fixed to one;
    5370 * merge multiple entries of the same or negated variables
    5371 */
    5372 SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, nchgcoefs, naggrvars, naddconss, &cutoff) );
    5373
    5374 if( cutoff )
    5375 break;
    5376
    5377 /* propagate constraint */
    5378 SCIP_CALL( propagateCons(scip, cons, conshdlrdata->eventhdlr, &cutoff, nfixedvars, nchgbds) );
    5379
    5380 if( !cutoff && !SCIPconsIsDeleted(cons) && !SCIPconsIsModifiable(cons) )
    5381 {
    5382 assert(consdata->nvars >= 2); /* otherwise, propagateCons() has deleted the constraint */
    5383
    5384 /* if only two variables are left, both have to be equal or opposite, depending on the rhs */
    5385 if( consdata->nvars == 2 )
    5386 {
    5387 SCIPdebugMsg(scip, "xor constraint <%s> has only two unfixed variables, rhs=%u\n",
    5388 SCIPconsGetName(cons), consdata->rhs);
    5389
    5390 assert(consdata->vars != NULL);
    5391 assert(SCIPisEQ(scip, SCIPvarGetLbGlobal(consdata->vars[0]), 0.0));
    5392 assert(SCIPisEQ(scip, SCIPvarGetUbGlobal(consdata->vars[0]), 1.0));
    5393 assert(SCIPisEQ(scip, SCIPvarGetLbGlobal(consdata->vars[1]), 0.0));
    5394 assert(SCIPisEQ(scip, SCIPvarGetUbGlobal(consdata->vars[1]), 1.0));
    5395
    5396 if( !consdata->rhs )
    5397 {
    5398 /* aggregate variables: vars[0] - vars[1] == 0 */
    5399 SCIPdebugMsg(scip, " -> aggregate <%s> == <%s>\n", SCIPvarGetName(consdata->vars[0]),
    5400 SCIPvarGetName(consdata->vars[1]));
    5401 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], 1.0, -1.0, 0.0,
    5402 &cutoff, &redundant, &aggregated) );
    5403 }
    5404 else
    5405 {
    5406 /* aggregate variables: vars[0] + vars[1] == 1 */
    5407 SCIPdebugMsg(scip, " -> aggregate <%s> == 1 - <%s>\n", SCIPvarGetName(consdata->vars[0]),
    5408 SCIPvarGetName(consdata->vars[1]));
    5409 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], 1.0, 1.0, 1.0,
    5410 &cutoff, &redundant, &aggregated) );
    5411 }
    5412 assert(redundant || SCIPdoNotAggr(scip));
    5413
    5414 if( aggregated )
    5415 {
    5416 assert(redundant);
    5417 ++(*naggrvars);
    5418 }
    5419
    5420 /* the constraint can be deleted if the intvar is fixed or NULL */
    5421 if( redundant )
    5422 {
    5423 SCIP_Bool fixedintvar;
    5424
    5425 fixedintvar = consdata->intvar == NULL ? TRUE : SCIPisEQ(scip, SCIPvarGetLbGlobal(consdata->intvar), SCIPvarGetUbGlobal(consdata->intvar));
    5426
    5427 if( fixedintvar )
    5428 {
    5429 /* if there is an integer variable then the following
    5430 * must hold:
    5431 *
    5432 * if consdata->rhs == 1 then the integer variable needs
    5433 * to be fixed to zero, otherwise the constraint is
    5434 * infeasible,
    5435 *
    5436 * if consdata->rhs == 0 then the integer variable needs
    5437 * to be aggregated to one of the binary variables
    5438 */
    5439 assert(consdata->intvar == NULL || (consdata->rhs && SCIPvarGetUbGlobal(consdata->intvar) < 0.5));
    5440
    5441 /* delete constraint */
    5442 SCIP_CALL( SCIPdelCons(scip, cons) );
    5443 (*ndelconss)++;
    5444 }
    5445 }
    5446 }
    5447 else if( (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0 )
    5448 {
    5449 /* try to use clique information to upgrade the constraint to a set-partitioning constraint or fix
    5450 * variables
    5451 */
    5452 SCIP_CALL( cliquePresolve(scip, cons, nfixedvars, naggrvars, nchgcoefs, ndelconss, naddconss, &cutoff) );
    5453 }
    5454 }
    5455 }
    5456
    5457 /* process pairs of constraints: check them for equal operands;
    5458 * only apply this expensive procedure, if the single constraint preprocessing did not find any reductions
    5459 */
    5460 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
    5461 {
    5462 if( firstchange < nconss && conshdlrdata->presolusehashing )
    5463 {
    5464 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
    5465 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, nchgcoefs,
    5466 nfixedvars, naggrvars, ndelconss, naddconss, &cutoff) );
    5467 }
    5468 if( conshdlrdata->presolpairwise )
    5469 {
    5470 SCIP_Longint npaircomparisons;
    5471 int lastndelconss;
    5472 npaircomparisons = 0;
    5473 lastndelconss = *ndelconss;
    5474
    5475 for( c = firstchange; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
    5476 {
    5477 if( SCIPconsIsActive(conss[c]) && !SCIPconsIsModifiable(conss[c]) )
    5478 {
    5479 npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? (SCIP_Longint) c : ((SCIP_Longint) c - (SCIP_Longint) firstchange);
    5480
    5481 SCIP_CALL( preprocessConstraintPairs(scip, conss, firstchange, c,
    5482 &cutoff, nfixedvars, naggrvars, ndelconss, naddconss, nchgcoefs) );
    5483
    5484 if( npaircomparisons > NMINCOMPARISONS )
    5485 {
    5486 if( ((SCIP_Real) (*ndelconss - lastndelconss)) / ((SCIP_Real) npaircomparisons) < MINGAINPERNMINCOMPARISONS )
    5487 break;
    5488 lastndelconss = *ndelconss;
    5489 npaircomparisons = 0;
    5490 }
    5491 }
    5492 }
    5493 }
    5494 }
    5495
    5496 /* return the correct result code */
    5497 if( cutoff )
    5498 *result = SCIP_CUTOFF;
    5499 else if( *nfixedvars > oldnfixedvars || *nchgbds > oldnchgbds || *naggrvars > oldnaggrvars
    5500 || *ndelconss > oldndelconss || *nchgcoefs > oldnchgcoefs )
    5501 *result = SCIP_SUCCESS;
    5502 else
    5503 *result = SCIP_DIDNOTFIND;
    5504
    5505 /* add extended formulation at the end of presolving if required */
    5506 if( conshdlrdata->addextendedform && *result == SCIP_DIDNOTFIND && SCIPisPresolveFinished(scip) )
    5507 {
    5508 for( c = 0; c < nconss && !SCIPisStopped(scip); ++c )
    5509 {
    5510 int naddedconss = 0;
    5511
    5512 cons = conss[c];
    5513 assert(cons != NULL);
    5514 consdata = SCIPconsGetData(cons);
    5515 assert(consdata != NULL);
    5516
    5517 if( consdata->extvars != NULL )
    5518 break;
    5519
    5520 if( conshdlrdata->addflowextended )
    5521 {
    5522 SCIP_CALL( addExtendedFlowFormulation(scip, cons, naggrvars, &naddedconss) );
    5523 }
    5524 else
    5525 {
    5526 SCIP_CALL( addExtendedAsymmetricFormulation(scip, cons, naggrvars, &naddedconss) );
    5527 }
    5528 (*naddconss) += naddedconss;
    5529 }
    5530 }
    5531
    5532 return SCIP_OKAY;
    5533}
    5534
    5535
    5536/** propagation conflict resolving method of constraint handler */
    5537static
    5539{ /*lint --e{715}*/
    5540 SCIP_CALL( resolvePropagation(scip, cons, infervar, (PROPRULE)inferinfo, bdchgidx, result) );
    5541
    5542 return SCIP_OKAY;
    5543}
    5544
    5545
    5546/** variable rounding lock method of constraint handler */
    5547static
    5549{ /*lint --e{715}*/
    5550 SCIP_CONSDATA* consdata;
    5551 int i;
    5552
    5553 consdata = SCIPconsGetData(cons);
    5554 assert(consdata != NULL);
    5555
    5556 /* external variables */
    5557 for( i = 0; i < consdata->nvars; ++i )
    5558 {
    5559 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos + nlocksneg, nlockspos + nlocksneg) );
    5560 }
    5561
    5562 /* internal variable */
    5563 if( consdata->intvar != NULL )
    5564 {
    5565 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->intvar, locktype, nlockspos + nlocksneg, nlockspos + nlocksneg) );
    5566 }
    5567
    5568 return SCIP_OKAY;
    5569}
    5570
    5571
    5572/** constraint display method of constraint handler */
    5573static
    5575{ /*lint --e{715}*/
    5576 assert(scip != NULL);
    5577 assert(conshdlr != NULL);
    5578 assert(cons != NULL);
    5579
    5581
    5582 return SCIP_OKAY;
    5583}
    5584
    5585/** constraint copying method of constraint handler */
    5586static
    5588{ /*lint --e{715}*/
    5589 SCIP_CONSDATA* sourceconsdata;
    5590 SCIP_VAR** sourcevars;
    5591 SCIP_VAR** targetvars;
    5592 SCIP_VAR* intvar;
    5593 SCIP_VAR* targetintvar;
    5594 const char* consname;
    5595 int nvars;
    5596 int v;
    5597
    5598 assert(scip != NULL);
    5599 assert(sourcescip != NULL);
    5600 assert(sourcecons != NULL);
    5601
    5602 (*valid) = TRUE;
    5603
    5604 sourceconsdata = SCIPconsGetData(sourcecons);
    5605 assert(sourceconsdata != NULL);
    5606
    5607 /* get variables and coefficients of the source constraint */
    5608 sourcevars = sourceconsdata->vars;
    5609 nvars = sourceconsdata->nvars;
    5610 intvar = sourceconsdata->intvar;
    5611 targetintvar = NULL;
    5612
    5613 if( name != NULL )
    5614 consname = name;
    5615 else
    5616 consname = SCIPconsGetName(sourcecons);
    5617
    5618 if( nvars == 0 )
    5619 {
    5620 if( intvar != NULL )
    5621 {
    5622 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, intvar, &targetintvar, varmap, consmap, global, valid) );
    5623 assert(!(*valid) || targetintvar != NULL);
    5624
    5625 if( targetintvar != NULL )
    5626 {
    5627 SCIPdebugMsg(scip, "Copied integral variable <%s> (bounds: [%g,%g])\n", SCIPvarGetName(targetintvar),
    5628 global ? SCIPvarGetLbGlobal(intvar) : SCIPvarGetLbLocal(intvar),
    5629 global ? SCIPvarGetUbGlobal(intvar) : SCIPvarGetUbLocal(intvar));
    5630 }
    5631 }
    5632
    5633 if( *valid )
    5634 {
    5635 SCIP_CALL( createConsXorIntvar(scip, cons, consname, SCIPgetRhsXor(sourcescip, sourcecons), 0, NULL,
    5636 targetintvar, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable,
    5637 stickingatnode) );
    5638 }
    5639
    5640 return SCIP_OKAY;
    5641 }
    5642
    5643 /* duplicate variable array */
    5644 SCIP_CALL( SCIPallocBufferArray(scip, &targetvars, nvars) );
    5645
    5646 /* map variables of the source constraint to variables of the target SCIP */
    5647 for( v = 0; v < nvars && *valid; ++v )
    5648 {
    5649 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &targetvars[v], varmap, consmap, global, valid) );
    5650 assert(!(*valid) || targetvars[v] != NULL);
    5651 }
    5652
    5653 /* map artificial relaxation variable of the source constraint to variable of the target SCIP */
    5654 if( *valid && intvar != NULL )
    5655 {
    5656 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, intvar, &targetintvar, varmap, consmap, global, valid) );
    5657 assert(!(*valid) || targetintvar != NULL);
    5658
    5659 SCIPdebugMsg(scip, "Copied integral variable <%s> (bounds: [%g,%g])\n", SCIPvarGetName(targetintvar),
    5660 global ? SCIPvarGetLbGlobal(intvar) : SCIPvarGetLbLocal(intvar),
    5661 global ? SCIPvarGetUbGlobal(intvar) : SCIPvarGetUbLocal(intvar));
    5662 }
    5663
    5664 /* only create the target constraints, if all variables could be copied */
    5665 if( *valid )
    5666 {
    5667 SCIP_CALL( createConsXorIntvar(scip, cons, consname, SCIPgetRhsXor(sourcescip, sourcecons), nvars, targetvars,
    5668 targetintvar, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable,
    5669 stickingatnode) );
    5670 }
    5671
    5672 /* free buffer array */
    5673 SCIPfreeBufferArray(scip, &targetvars);
    5674
    5675 return SCIP_OKAY;
    5676}
    5677
    5678
    5679/** constraint parsing method of constraint handler */
    5680static
    5682{ /*lint --e{715}*/
    5683 SCIP_VAR** vars;
    5684 char* endptr;
    5685 int requiredsize;
    5686 int varssize;
    5687 int nvars;
    5688
    5689 SCIPdebugMsg(scip, "parse <%s> as xor constraint\n", str);
    5690
    5691 varssize = 100;
    5692 nvars = 0;
    5693
    5694 /* allocate buffer array for variables */
    5695 SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
    5696
    5697 /* parse string */
    5698 SCIP_CALL( SCIPparseVarsList(scip, str, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
    5699
    5700 if( *success )
    5701 {
    5702 SCIP_Real rhs;
    5703
    5704 /* check if the size of the variable array was big enough */
    5705 if( varssize < requiredsize )
    5706 {
    5707 /* reallocate memory */
    5708 varssize = requiredsize;
    5709 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
    5710
    5711 /* parse string again with the correct size of the variable array */
    5712 SCIP_CALL( SCIPparseVarsList(scip, str, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
    5713 }
    5714
    5715 assert(*success);
    5716 assert(varssize >= requiredsize);
    5717
    5718 SCIPdebugMsg(scip, "successfully parsed %d variables\n", nvars);
    5719
    5720 /* find "==" */
    5721 endptr = strchr(endptr, '=');
    5722
    5723 /* if the string end has been reached without finding the "==" */
    5724 if( endptr == NULL )
    5725 {
    5726 SCIPerrorMessage("Could not find terminating '='.\n");
    5727 *success = FALSE;
    5728 goto TERMINATE;
    5729 }
    5730
    5731 str = endptr;
    5732
    5733 /* skip "==" */
    5734 str += *(str+1) == '=' ? 2 : 1;
    5735
    5736 if( SCIPparseReal(scip, str, &rhs, &endptr) )
    5737 {
    5738 SCIP_VAR* intvar = NULL;
    5739
    5740 assert(SCIPisZero(scip, rhs) || SCIPisEQ(scip, rhs, 1.0));
    5741
    5742 str = endptr;
    5743
    5744 /* skip white spaces */
    5745 SCIP_CALL( SCIPskipSpace((char**)&str) );
    5746
    5747 /* check for integer variable, should look like (intvar = var) */
    5748 if( *str == '(' )
    5749 {
    5750 str = strchr(str+1, '=');
    5751
    5752 if( str == NULL )
    5753 {
    5754 SCIPerrorMessage("Parsing integer variable of XOR constraint\n");
    5755 *success = FALSE;
    5756 goto TERMINATE;
    5757 }
    5758
    5759 ++str;
    5760
    5761 /* parse variable name */
    5762 SCIP_CALL( SCIPparseVarName(scip, str, &intvar, &endptr) );
    5763
    5764 if( intvar == NULL )
    5765 {
    5766 SCIPerrorMessage("Integer variable of XOR not found\n");
    5767 *success = FALSE;
    5768 goto TERMINATE;
    5769 }
    5770
    5771 /* skip last ')' */
    5772 endptr = strchr(endptr, ')');
    5773
    5774 if( endptr == NULL )
    5775 {
    5776 SCIPerrorMessage("Closing ')' missing\n");
    5777 *success = FALSE;
    5778 goto TERMINATE;
    5779 }
    5780 }
    5781
    5782 if( intvar != NULL )
    5783 {
    5784 /* create or constraint */
    5785 SCIP_CALL( createConsXorIntvar(scip, cons, name, (rhs > 0.5 ? TRUE : FALSE), nvars, vars, intvar,
    5786 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    5787 }
    5788 else
    5789 {
    5790 /* create or constraint */
    5791 SCIP_CALL( SCIPcreateConsXor(scip, cons, name, (rhs > 0.5 ? TRUE : FALSE), nvars, vars,
    5792 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    5793 }
    5794
    5795 SCIPdebugPrintCons(scip, *cons, NULL);
    5796 }
    5797 else
    5798 *success = FALSE;
    5799 }
    5800
    5801 TERMINATE:
    5802 /* free variable buffer */
    5803 SCIPfreeBufferArray(scip, &vars);
    5804
    5805 return SCIP_OKAY;
    5806}
    5807
    5808/** constraint method of constraint handler which returns the variables (if possible) */
    5809static
    5811{ /*lint --e{715}*/
    5812 SCIP_CONSDATA* consdata;
    5813 int nintvar = 0;
    5814 int cnt;
    5815 int j;
    5816
    5817 consdata = SCIPconsGetData(cons);
    5818 assert(consdata != NULL);
    5819
    5820 if( consdata->intvar != NULL )
    5821 nintvar = 1;
    5822
    5823 if( varssize < consdata->nvars + nintvar + consdata->nextvars )
    5824 (*success) = FALSE;
    5825 else
    5826 {
    5827 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
    5828
    5829 if( consdata->intvar != NULL )
    5830 vars[consdata->nvars] = consdata->intvar;
    5831
    5832 if( consdata->nextvars > 0 )
    5833 {
    5834 assert(consdata->extvars != NULL);
    5835 cnt = consdata->nvars + nintvar;
    5836 for( j = 0; j < consdata->extvarssize; ++j )
    5837 {
    5838 if( consdata->extvars[j] != NULL )
    5839 vars[cnt++] = consdata->extvars[j];
    5840 }
    5841 assert(cnt == consdata->nvars + nintvar + consdata->nextvars);
    5842 }
    5843
    5844 (*success) = TRUE;
    5845 }
    5846
    5847 return SCIP_OKAY;
    5848}
    5849
    5850/** constraint method of constraint handler which returns the number of variable (if possible) */
    5851static
    5853{ /*lint --e{715}*/
    5854 SCIP_CONSDATA* consdata;
    5855
    5856 assert(cons != NULL);
    5857
    5858 consdata = SCIPconsGetData(cons);
    5859 assert(consdata != NULL);
    5860
    5861 if( consdata->intvar == NULL )
    5862 (*nvars) = consdata->nvars + consdata->nextvars;
    5863 else
    5864 (*nvars) = consdata->nvars + 1 + consdata->nextvars;
    5865
    5866 (*success) = TRUE;
    5867
    5868 return SCIP_OKAY;
    5869}
    5870
    5871/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
    5872static
    5873SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphXor)
    5874{ /*lint --e{715}*/
    5875 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
    5876
    5877 return SCIP_OKAY;
    5878}
    5879
    5880/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
    5881static
    5882SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphXor)
    5883{ /*lint --e{715}*/
    5884 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
    5885
    5886 return SCIP_OKAY;
    5887}
    5888
    5889/*
    5890 * Callback methods of event handler
    5891 */
    5892
    5893static
    5895{ /*lint --e{715}*/
    5896 SCIP_CONSDATA* consdata;
    5897
    5898 assert(eventhdlr != NULL);
    5899 assert(eventdata != NULL);
    5900 assert(event != NULL);
    5901
    5902 consdata = (SCIP_CONSDATA*)eventdata;
    5903 assert(consdata != NULL);
    5904
    5906 {
    5907 /* we only catch this event in presolving stage */
    5909 assert(SCIPeventGetVar(event) != NULL);
    5910
    5911 consdata->sorted = FALSE;
    5912 }
    5913
    5914 consdata->propagated = FALSE;
    5915
    5916 return SCIP_OKAY;
    5917}
    5918
    5919
    5920/*
    5921 * constraint specific interface methods
    5922 */
    5923
    5924/** creates the handler for xor constraints and includes it in SCIP */
    5926 SCIP* scip /**< SCIP data structure */
    5927 )
    5928{
    5929 SCIP_CONSHDLRDATA* conshdlrdata;
    5930 SCIP_CONSHDLR* conshdlr;
    5931 SCIP_EVENTHDLR* eventhdlr;
    5932
    5933 /* create event handler for events on variables */
    5935 eventExecXor, NULL) );
    5936
    5937 /* create constraint handler data */
    5938 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
    5939
    5940 /* include constraint handler */
    5943 consEnfolpXor, consEnfopsXor, consCheckXor, consLockXor,
    5944 conshdlrdata) );
    5945 assert(conshdlr != NULL);
    5946
    5947 /* set non-fundamental callbacks via specific setter functions */
    5948 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyXor, consCopyXor) );
    5949 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteXor) );
    5950 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolXor) );
    5951 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeXor) );
    5952 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsXor) );
    5953 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsXor) );
    5954 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpXor) );
    5955 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseXor) );
    5956 SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreXor) );
    5957 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreXor) );
    5959 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintXor) );
    5962 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropXor) );
    5963 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpXor, consSepasolXor, CONSHDLR_SEPAFREQ,
    5965 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransXor) );
    5966 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxXor) );
    5967 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphXor) );
    5968 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphXor) );
    5969
    5970 if( SCIPfindConshdlr(scip, "linear") != NULL )
    5971 {
    5972 /* include the linear constraint upgrade in the linear constraint handler */
    5974 }
    5975
    5976 /* add xor constraint handler parameters */
    5978 "constraints/xor/presolpairwise",
    5979 "should pairwise constraint comparison be performed in presolving?",
    5980 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
    5981
    5983 "constraints/xor/presolusehashing",
    5984 "should hash table be used for detecting redundant constraints in advance?",
    5985 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
    5986
    5988 "constraints/xor/addextendedform",
    5989 "should the extended formulation be added in presolving?",
    5990 &conshdlrdata->addextendedform, TRUE, DEFAULT_ADDEXTENDEDFORM, NULL, NULL) );
    5991
    5993 "constraints/xor/addflowextended",
    5994 "should the extended flow formulation be added (nonsymmetric formulation otherwise)?",
    5995 &conshdlrdata->addflowextended, TRUE, DEFAULT_ADDFLOWEXTENDED, NULL, NULL) );
    5996
    5998 "constraints/xor/separateparity",
    5999 "should parity inequalities be separated?",
    6000 &conshdlrdata->separateparity, TRUE, DEFAULT_SEPARATEPARITY, NULL, NULL) );
    6001
    6003 "constraints/xor/gausspropfreq",
    6004 "frequency for applying the Gauss propagator",
    6005 &conshdlrdata->gausspropfreq, TRUE, DEFAULT_GAUSSPROPFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
    6006
    6007 return SCIP_OKAY;
    6008}
    6009
    6010/** creates and captures a xor constraint x_0 xor ... xor x_{k-1} = rhs
    6011 *
    6012 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    6013 */
    6015 SCIP* scip, /**< SCIP data structure */
    6016 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    6017 const char* name, /**< name of constraint */
    6018 SCIP_Bool rhs, /**< right hand side of the constraint */
    6019 int nvars, /**< number of operator variables in the constraint */
    6020 SCIP_VAR** vars, /**< array with operator variables of constraint */
    6021 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
    6022 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    6023 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
    6024 * Usually set to TRUE. */
    6025 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    6026 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    6027 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    6028 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    6029 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
    6030 * Usually set to TRUE. */
    6031 SCIP_Bool local, /**< is constraint only valid locally?
    6032 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    6033 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
    6034 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
    6035 * adds coefficients to this constraint. */
    6036 SCIP_Bool dynamic, /**< is constraint subject to aging?
    6037 * Usually set to FALSE. Set to TRUE for own cuts which
    6038 * are separated as constraints. */
    6039 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
    6040 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
    6041 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    6042 * if it may be moved to a more global node?
    6043 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
    6044 )
    6045{
    6046 SCIP_CONSHDLR* conshdlr;
    6047 SCIP_CONSDATA* consdata;
    6048 int i;
    6049
    6050 /* find the xor constraint handler */
    6051 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    6052 if( conshdlr == NULL )
    6053 {
    6054 SCIPerrorMessage("xor constraint handler not found\n");
    6055 return SCIP_PLUGINNOTFOUND;
    6056 }
    6057
    6058 /* check whether all variables are binary */
    6059 assert(vars != NULL || nvars == 0);
    6060 for( i = 0; i < nvars; ++i )
    6061 {
    6062 if( !SCIPvarIsBinary(vars[i]) )
    6063 {
    6064 SCIPerrorMessage("operand <%s> is not binary\n", SCIPvarGetName(vars[i]));
    6065 return SCIP_INVALIDDATA;
    6066 }
    6067 }
    6068
    6069 /* create constraint data */
    6070 SCIP_CALL( consdataCreate(scip, &consdata, rhs, nvars, vars, NULL) );
    6071
    6072 /* create constraint */
    6073 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
    6074 local, modifiable, dynamic, removable, stickingatnode) );
    6075
    6076 return SCIP_OKAY;
    6077}
    6078
    6079/** creates and captures a xor constraint x_0 xor ... xor x_{k-1} = rhs
    6080 * with all constraint flags set to their default values
    6081 *
    6082 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    6083 */
    6085 SCIP* scip, /**< SCIP data structure */
    6086 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    6087 const char* name, /**< name of constraint */
    6088 SCIP_Bool rhs, /**< right hand side of the constraint */
    6089 int nvars, /**< number of operator variables in the constraint */
    6090 SCIP_VAR** vars /**< array with operator variables of constraint */
    6091 )
    6092{
    6093 SCIP_CALL( SCIPcreateConsXor(scip,cons, name, rhs, nvars, vars,
    6095
    6096 return SCIP_OKAY;
    6097}
    6098
    6099/** gets number of variables in xor constraint */
    6101 SCIP* scip, /**< SCIP data structure */
    6102 SCIP_CONS* cons /**< constraint data */
    6103 )
    6104{
    6105 SCIP_CONSDATA* consdata;
    6106
    6107 assert(scip != NULL);
    6108
    6109 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    6110 {
    6111 SCIPerrorMessage("constraint is not an xor constraint\n");
    6112 SCIPABORT();
    6113 return -1; /*lint !e527*/
    6114 }
    6115
    6116 consdata = SCIPconsGetData(cons);
    6117 assert(consdata != NULL);
    6118
    6119 return consdata->nvars;
    6120}
    6121
    6122/** gets array of variables in xor constraint */
    6124 SCIP* scip, /**< SCIP data structure */
    6125 SCIP_CONS* cons /**< constraint data */
    6126 )
    6127{
    6128 SCIP_CONSDATA* consdata;
    6129
    6130 assert(scip != NULL);
    6131
    6132 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    6133 {
    6134 SCIPerrorMessage("constraint is not an xor constraint\n");
    6135 SCIPABORT();
    6136 return NULL; /*lint !e527*/
    6137 }
    6138
    6139 consdata = SCIPconsGetData(cons);
    6140 assert(consdata != NULL);
    6141
    6142 return consdata->vars;
    6143}
    6144
    6145/** gets integer variable in xor constraint */
    6147 SCIP* scip, /**< SCIP data structure */
    6148 SCIP_CONS* cons /**< constraint data */
    6149 )
    6150{
    6151 SCIP_CONSDATA* consdata;
    6152
    6153 assert(scip != NULL);
    6154
    6155 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    6156 {
    6157 SCIPerrorMessage("constraint is not an xor constraint\n");
    6158 SCIPABORT();
    6159 return NULL; /*lint !e527*/
    6160 }
    6161
    6162 consdata = SCIPconsGetData(cons);
    6163 assert(consdata != NULL);
    6164
    6165 return consdata->intvar;
    6166}
    6167
    6168/** gets the right hand side of the xor constraint */
    6170 SCIP* scip, /**< SCIP data structure */
    6171 SCIP_CONS* cons /**< constraint data */
    6172 )
    6173{
    6174 SCIP_CONSDATA* consdata;
    6175
    6176 assert(scip != NULL);
    6177
    6178 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    6179 {
    6180 SCIPerrorMessage("constraint is not an xor constraint\n");
    6181 SCIPABORT();
    6182 }
    6183
    6184 consdata = SCIPconsGetData(cons);
    6185 assert(consdata != NULL);
    6186
    6187 return consdata->rhs;
    6188}
    SCIP_VAR * h
    Definition: circlepacking.c:68
    SCIP_VAR ** b
    Definition: circlepacking.c:65
    SCIP_Real * r
    Definition: circlepacking.c:59
    SCIP_VAR ** x
    Definition: circlepacking.c:63
    enum Proprule PROPRULE
    Definition: cons_and.c:173
    Proprule
    Definition: cons_and.c:166
    Constraint handler for linear constraints in their most general form, .
    Constraint handler for the set partitioning / packing / covering constraints .
    static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
    Definition: cons_xor.c:1776
    enum Proprule PROPRULE
    Definition: cons_xor.c:180
    static SCIP_DECL_CONSDELETE(consDeleteXor)
    Definition: cons_xor.c:4965
    static SCIP_DECL_CONSGETVARS(consGetVarsXor)
    Definition: cons_xor.c:5810
    static SCIP_RETCODE consdataFreeRows(SCIP *scip, SCIP_CONSDATA *consdata)
    Definition: cons_xor.c:417
    static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_xor.c:586
    static SCIP_DECL_CONSSEPASOL(consSepasolXor)
    Definition: cons_xor.c:5068
    static SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphXor)
    Definition: cons_xor.c:5873
    #define DEFAULT_SEPARATEPARITY
    Definition: cons_xor.c:114
    static SCIP_RETCODE consdataSwitchWatchedvars(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int watchedvar1, int watchedvar2)
    Definition: cons_xor.c:254
    #define CONSHDLR_NEEDSCONS
    Definition: cons_xor.c:101
    #define CONSHDLR_SEPAFREQ
    Definition: cons_xor.c:94
    static SCIP_RETCODE addExtendedAsymmetricFormulation(SCIP *scip, SCIP_CONS *cons, int *naggrvars, int *naddedconss)
    Definition: cons_xor.c:1460
    static SCIP_DECL_CONSLOCK(consLockXor)
    Definition: cons_xor.c:5548
    static SCIP_DECL_HASHKEYEQ(hashKeyEqXorcons)
    Definition: cons_xor.c:805
    static SCIP_RETCODE checkSystemGF2(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_SOL *currentsol, SCIP_RESULT *result)
    Definition: cons_xor.c:2359
    static SCIP_DECL_EVENTEXEC(eventExecXor)
    Definition: cons_xor.c:5894
    static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
    Definition: cons_xor.c:652
    #define CONSHDLR_CHECKPRIORITY
    Definition: cons_xor.c:93
    static SCIP_RETCODE setIntvar(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_xor.c:534
    #define CONSHDLR_DESC
    Definition: cons_xor.c:90
    static SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphXor)
    Definition: cons_xor.c:5882
    static SCIP_DECL_CONSEXITSOL(consExitsolXor)
    Definition: cons_xor.c:4947
    #define DEFAULT_ADDFLOWEXTENDED
    Definition: cons_xor.c:113
    static SCIP_RETCODE createRelaxation(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_xor.c:1643
    static SCIP_DECL_CONSPRINT(consPrintXor)
    Definition: cons_xor.c:5574
    #define CONSHDLR_PROP_TIMING
    Definition: cons_xor.c:103
    static SCIP_DECL_CONSINITPRE(consInitpreXor)
    Definition: cons_xor.c:5263
    static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
    Definition: cons_xor.c:241
    #define DEFAULT_GAUSSPROPFREQ
    Definition: cons_xor.c:115
    static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_xor.c:205
    #define HASHSIZE_XORCONS
    Definition: cons_xor.c:116
    #define CONSHDLR_MAXPREROUNDS
    Definition: cons_xor.c:98
    static SCIP_DECL_CONSCHECK(consCheckXor)
    Definition: cons_xor.c:5195
    #define DEFAULT_PRESOLPAIRWISE
    Definition: cons_xor.c:111
    static SCIP_DECL_HASHKEYVAL(hashKeyValXorcons)
    Definition: cons_xor.c:847
    static SCIP_DECL_CONSGETNVARS(consGetNVarsXor)
    Definition: cons_xor.c:5852
    #define CONSHDLR_SEPAPRIORITY
    Definition: cons_xor.c:91
    static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, PROPRULE proprule)
    Definition: cons_xor.c:2953
    static SCIP_Bool allRowsInLP(SCIP_CONSDATA *consdata)
    Definition: cons_xor.c:1808
    #define MAXXORCONSSSYSTEM
    Definition: cons_xor.c:120
    static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_Bool rhs, int nvars, SCIP_VAR **vars, SCIP_VAR *intvar)
    Definition: cons_xor.c:342
    static SCIP_DECL_CONSENFOPS(consEnfopsXor)
    Definition: cons_xor.c:5173
    static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
    Definition: cons_xor.c:4838
    static SCIP_DECL_CONSPARSE(consParseXor)
    Definition: cons_xor.c:5681
    static SCIP_DECL_CONSINITLP(consInitlpXor)
    Definition: cons_xor.c:5017
    static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_xor.c:189
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyXor)
    Definition: cons_xor.c:4914
    static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
    Definition: cons_xor.c:318
    @ PROPRULE_1
    Definition: cons_xor.c:175
    @ PROPRULE_INTUB
    Definition: cons_xor.c:177
    @ PROPRULE_0
    Definition: cons_xor.c:174
    @ PROPRULE_INTLB
    Definition: cons_xor.c:176
    @ PROPRULE_INVALID
    Definition: cons_xor.c:178
    static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool *violated)
    Definition: cons_xor.c:1830
    #define DEFAULT_PRESOLUSEHASHING
    Definition: cons_xor.c:117
    static void solveRowEchelonGF2(int m, int n, int r, int *p, int *s, Type **A, Type *b, Type *x)
    Definition: cons_xor.c:2298
    static SCIP_DECL_CONSENFOLP(consEnfolpXor)
    Definition: cons_xor.c:5099
    static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_EVENTHDLR *eventhdlr)
    Definition: cons_xor.c:439
    static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds)
    Definition: cons_xor.c:2984
    static SCIP_DECL_CONSENFORELAX(consEnforelaxXor)
    Definition: cons_xor.c:5136
    #define MINGAINPERNMINCOMPARISONS
    Definition: cons_xor.c:119
    static SCIP_RETCODE addExtendedFlowFormulation(SCIP *scip, SCIP_CONS *cons, int *naggrvars, int *naddedconss)
    Definition: cons_xor.c:1131
    static SCIP_DECL_CONSFREE(consFreeXor)
    Definition: cons_xor.c:4930
    static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, PROPRULE proprule)
    Definition: cons_xor.c:2845
    #define CONSHDLR_PROPFREQ
    Definition: cons_xor.c:95
    static SCIP_DECL_CONSEXITPRE(consExitpreXor)
    Definition: cons_xor.c:5292
    static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool separateparity, SCIP_Bool *separated, SCIP_Bool *cutoff)
    Definition: cons_xor.c:1976
    #define NMINCOMPARISONS
    Definition: cons_xor.c:118
    #define CONSHDLR_PRESOLTIMING
    Definition: cons_xor.c:104
    static SCIP_RETCODE detectRedundantConstraints(SCIP *scip, BMS_BLKMEM *blkmem, SCIP_CONS **conss, int nconss, int *firstchange, int *nchgcoefs, int *nfixedvars, int *naggrvars, int *ndelconss, int *naddconss, SCIP_Bool *cutoff)
    Definition: cons_xor.c:3737
    #define MAXXORVARSSYSTEM
    Definition: cons_xor.c:121
    static void consdataSort(SCIP_CONSDATA *consdata)
    Definition: cons_xor.c:713
    static SCIP_RETCODE preprocessConstraintPairs(SCIP *scip, SCIP_CONS **conss, int firstchange, int chkind, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss, int *naddconss, int *nchgcoefs)
    Definition: cons_xor.c:3934
    #define CONSHDLR_EAGERFREQ
    Definition: cons_xor.c:96
    #define DEFAULT_ADDEXTENDEDFORM
    Definition: cons_xor.c:112
    unsigned short Type
    Definition: cons_xor.c:131
    #define EVENTHDLR_DESC
    Definition: cons_xor.c:107
    static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
    Definition: cons_xor.c:221
    static SCIP_RETCODE createConsXorIntvar(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_Bool rhs, int nvars, SCIP_VAR **vars, SCIP_VAR *intvar, 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: cons_xor.c:4515
    static SCIP_DECL_HASHGETKEY(hashGetKeyXorcons)
    Definition: cons_xor.c:797
    #define NROWS
    Definition: cons_xor.c:123
    static SCIP_DECL_CONSCOPY(consCopyXor)
    Definition: cons_xor.c:5587
    #define CONSHDLR_ENFOPRIORITY
    Definition: cons_xor.c:92
    static SCIP_DECL_LINCONSUPGD(linconsUpgdXor)
    Definition: cons_xor.c:4635
    static SCIP_RETCODE cliquePresolve(SCIP *scip, SCIP_CONS *cons, int *nfixedvars, int *naggrvars, int *nchgcoefs, int *ndelconss, int *naddconss, SCIP_Bool *cutoff)
    Definition: cons_xor.c:3426
    static SCIP_DECL_CONSPRESOL(consPresolXor)
    Definition: cons_xor.c:5324
    #define LINCONSUPGD_PRIORITY
    Definition: cons_xor.c:109
    static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, PROPRULE proprule, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
    Definition: cons_xor.c:3405
    #define CONSHDLR_DELAYSEPA
    Definition: cons_xor.c:99
    static int computeRowEchelonGF2(SCIP *scip, int m, int n, int *p, int *s, Type **A, Type *b)
    Definition: cons_xor.c:2189
    static SCIP_DECL_CONSRESPROP(consRespropXor)
    Definition: cons_xor.c:5538
    static SCIP_DECL_CONSTRANS(consTransXor)
    Definition: cons_xor.c:4991
    #define CONSHDLR_NAME
    Definition: cons_xor.c:89
    #define EVENTHDLR_NAME
    Definition: cons_xor.c:106
    static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int *nchgcoefs, int *naggrvars, int *naddconss, SCIP_Bool *cutoff)
    Definition: cons_xor.c:879
    static SCIP_DECL_CONSSEPALP(consSepalpXor)
    Definition: cons_xor.c:5037
    #define CONSHDLR_DELAYPROP
    Definition: cons_xor.c:100
    static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file, SCIP_Bool endline)
    Definition: cons_xor.c:500
    static SCIP_DECL_CONSPROP(consPropXor)
    Definition: cons_xor.c:5214
    Constraint handler for XOR constraints, .
    methods for debugging
    #define SCIPdebugGetSolVal(scip, var, val)
    Definition: debug.h:312
    #define SCIPdebugAddSolVal(scip, var, val)
    Definition: debug.h:311
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_MAXTREEDEPTH
    Definition: def.h:297
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIPABORT()
    Definition: def.h:327
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
    int SCIPgetNVarsXor(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_xor.c:6100
    SCIP_RETCODE SCIPcreateConsBasicXor(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_Bool rhs, int nvars, SCIP_VAR **vars)
    Definition: cons_xor.c:6084
    SCIP_VAR * SCIPgetIntVarXor(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_xor.c:6146
    SCIP_RETCODE SCIPcreateConsXor(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_Bool rhs, int nvars, SCIP_VAR **vars, 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: cons_xor.c:6014
    SCIP_RETCODE SCIPaddCoefSetppc(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_setppc.c:9573
    SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_RETCODE SCIPcreateConsSetpart(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, 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: cons_setppc.c:9402
    SCIP_Bool SCIPgetRhsXor(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_xor.c:6169
    SCIP_VAR ** SCIPgetVarsXor(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_xor.c:6123
    SCIP_RETCODE SCIPincludeConshdlrXor(SCIP *scip)
    Definition: cons_xor.c:5925
    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 SCIPisPresolveFinished(SCIP *scip)
    Definition: scip_general.c:668
    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
    SCIP_RETCODE SCIPaddConsUpgrade(SCIP *scip, SCIP_CONS *oldcons, SCIP_CONS **newcons)
    Definition: scip_prob.c:3368
    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
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3304
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3466
    SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
    Definition: misc.c:3179
    void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
    Definition: misc.c:2348
    #define SCIPhashFour(a, b, c, d)
    Definition: pub_misc.h:573
    SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
    Definition: misc.c:2298
    void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
    Definition: misc.c:2596
    SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2535
    SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:4067
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPheurPassSolAddSol(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *sol)
    Definition: heur_trysol.c:296
    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 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
    void SCIPswapPointers(void **pointer1, void **pointer2)
    Definition: misc.c:10511
    SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
    SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
    SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
    SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
    SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
    SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
    SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
    Definition: scip_cons.c:808
    void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: cons.c:4346
    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 SCIPsetConshdlrInitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITPRE((*consinitpre)))
    Definition: scip_cons.c:492
    SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
    Definition: scip_cons.c:235
    SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
    Definition: scip_cons.c:281
    SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: scip_cons.c:181
    SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)))
    Definition: scip_cons.c:900
    SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
    Definition: scip_cons.c:578
    SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
    Definition: scip_cons.c:372
    SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
    Definition: scip_cons.c:323
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4316
    SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
    Definition: scip_cons.c:516
    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:4336
    SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
    Definition: scip_cons.c:601
    SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
    Definition: scip_cons.c:647
    SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
    Definition: scip_cons.c:854
    SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
    Definition: scip_cons.c:785
    SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
    Definition: cons.c:8419
    int SCIPconsGetPos(SCIP_CONS *cons)
    Definition: cons.c:8399
    SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
    Definition: cons.c:8648
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8409
    SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
    Definition: cons.c:8558
    SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
    Definition: scip_cons.c:2536
    int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
    Definition: cons.c:8841
    SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8588
    SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
    Definition: cons.c:8518
    SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
    Definition: cons.c:8698
    SCIP_Bool SCIPconsIsLockedType(SCIP_CONS *cons, SCIP_LOCKTYPE locktype)
    Definition: cons.c:8782
    SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
    Definition: cons.c:8578
    SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
    Definition: cons.c:8450
    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:8608
    SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
    Definition: cons.c:8628
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8389
    SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1812
    SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
    Definition: cons.c:8638
    SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
    Definition: scip_cons.c:1524
    SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
    Definition: cons.c:8668
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8568
    SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1784
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8658
    SCIP_Bool SCIPisEfficacious(SCIP *scip, SCIP_Real efficacy)
    Definition: scip_cut.c:135
    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
    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_VAR * SCIPeventGetVar(SCIP_EVENT *event)
    Definition: event.c:1217
    SCIP_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
    Definition: scip_heur.c:263
    #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 SCIPreallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:128
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    #define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:105
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1581
    SCIP_Real SCIPgetRowLPActivity(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1957
    SCIP_RETCODE SCIPaddVarsToRowSameCoef(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real val)
    Definition: scip_lp.c:1718
    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 SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1604
    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_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
    Definition: scip_lp.c:2131
    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 SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:516
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
    Definition: scip_sol.c:2349
    void SCIPupdateSolConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
    Definition: scip_sol.c:453
    SCIP_RETCODE SCIPcheckSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *feasible)
    Definition: scip_sol.c:4312
    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_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
    SCIP_Bool SCIPinRepropagation(SCIP *scip)
    Definition: scip_tree.c:146
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
    Definition: var.c:23514
    int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
    Definition: var.c:17236
    SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:6401
    SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
    Definition: scip_var.c:5210
    SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
    Definition: var.c:23868
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23478
    SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
    Definition: scip_var.c:2119
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4386
    SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
    Definition: var.c:23771
    SCIP_Bool SCIPdoNotAggr(SCIP *scip)
    Definition: scip_var.c:10909
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
    Definition: var.c:23430
    SCIP_RETCODE SCIPparseVarsList(SCIP *scip, const char *str, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize, char **endptr, char delimiter, SCIP_Bool *success)
    Definition: scip_var.c:805
    SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
    Definition: scip_var.c:10550
    SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:7069
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
    Definition: var.c:23748
    SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
    Definition: var.c:17550
    SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:6651
    SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
    Definition: scip_var.c:728
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    int SCIPvarGetIndex(SCIP_VAR *var)
    Definition: var.c:23652
    SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
    Definition: scip_var.c:5118
    SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
    Definition: scip_var.c:5296
    SCIP_RETCODE SCIPcreateVarImpl(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_IMPLINTTYPE impltype, 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:225
    SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2872
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
    Definition: scip_var.c:2166
    SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
    Definition: var.c:23524
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
    Definition: var.c:23443
    SCIP_Real SCIPcomputeVarLbLocal(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:8417
    SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
    Definition: var.c:23878
    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:24120
    SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
    Definition: scip_var.c:10318
    SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:6964
    SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2736
    SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
    Definition: var.c:23463
    int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
    Definition: var.c:17274
    SCIP_RETCODE SCIPprintVar(SCIP *scip, SCIP_VAR *var, FILE *file)
    Definition: scip_var.c:12465
    SCIP_RETCODE SCIPinferBinvarCons(SCIP *scip, SCIP_VAR *var, SCIP_Bool fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:7412
    SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
    Definition: scip_var.c:361
    SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
    Definition: scip_var.c:2236
    SCIP_RETCODE SCIPwriteVarsList(SCIP *scip, FILE *file, SCIP_VAR **vars, int nvars, SCIP_Bool type, char delimiter)
    Definition: scip_var.c:423
    SCIP_Real SCIPcomputeVarUbLocal(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:8462
    SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
    Definition: var.c:16807
    int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4328
    SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
    Definition: scip_var.c:2078
    SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:1853
    SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
    Definition: var.c:23736
    void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
    void SCIPsortRealIntPtr(SCIP_Real *realarray, int *intarray, void **ptrarray, int len)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    SCIP_RETCODE SCIPskipSpace(char **s)
    Definition: misc.c:10816
    SCIP_RETCODE SCIPaddSymgraphEdge(SCIP *scip, SYM_GRAPH *graph, int first, int second, SCIP_Bool hasval, SCIP_Real val)
    SCIP_RETCODE SCIPaddSymgraphOpnode(SCIP *scip, SYM_GRAPH *graph, int op, int *nodeidx)
    SCIP_RETCODE SCIPgetSymActiveVariables(SCIP *scip, SYM_SYMTYPE symtype, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
    SCIP_RETCODE 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)
    primal heuristic that tries a given solution
    memory allocation routines
    #define BMScopyMemoryArray(ptr, source, num)
    Definition: memory.h:134
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    struct BMS_BlkMem BMS_BLKMEM
    Definition: memory.h:437
    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
    #define SCIPdebugPrintCons(x, y, z)
    Definition: pub_message.h:102
    public data structures and miscellaneous methods
    methods for sorting joint arrays of various types
    public methods for problem variables
    public methods for conflict handler plugins and conflict analysis
    public methods for constraint handler plugins and constraints
    public methods for problem copies
    public methods for cuts and aggregation rows
    public methods for event handler plugins and event handlers
    general public methods
    public methods for primal heuristic plugins and divesets
    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 the probing mode
    public methods for solutions
    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
    @ SCIP_CONFTYPE_PROPAGATION
    Definition: type_conflict.h:62
    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
    struct SCIP_EventData SCIP_EVENTDATA
    Definition: type_event.h:179
    #define SCIP_EVENTTYPE_VARFIXED
    Definition: type_event.h:72
    @ 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_SEPARATED
    Definition: type_result.h:49
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    @ SCIP_INFEASIBLE
    Definition: type_result.h:46
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_PLUGINNOTFOUND
    Definition: type_retcode.h:54
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_INITPRESOLVE
    Definition: type_set.h:48
    @ SCIP_STAGE_PRESOLVING
    Definition: type_set.h:49
    @ SCIP_STAGE_EXITPRESOLVE
    Definition: type_set.h:50
    @ SCIP_STAGE_SOLVING
    Definition: type_set.h:53
    enum SYM_Symtype SYM_SYMTYPE
    Definition: type_symmetry.h:64
    @ SYM_CONSOPTYPE_XORINT
    Definition: type_symmetry.h:94
    @ SYM_SYMTYPE_SIGNPERM
    Definition: type_symmetry.h:62
    @ SYM_SYMTYPE_PERM
    Definition: type_symmetry.h:61
    #define SCIP_PRESOLTIMING_MEDIUM
    Definition: type_timing.h:53
    #define SCIP_PRESOLTIMING_EXHAUSTIVE
    Definition: type_timing.h:54
    @ SCIP_IMPLINTTYPE_WEAK
    Definition: type_var.h:91
    @ SCIP_VARTYPE_INTEGER
    Definition: type_var.h:65
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64
    @ SCIP_VARSTATUS_FIXED
    Definition: type_var.h:54
    @ SCIP_VARSTATUS_MULTAGGR
    Definition: type_var.h:56
    @ SCIP_VARSTATUS_NEGATED
    Definition: type_var.h:57
    @ SCIP_VARSTATUS_AGGREGATED
    Definition: type_var.h:55
    @ SCIP_LOCKTYPE_CONFLICT
    Definition: type_var.h:142
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141
    enum SCIP_Vartype SCIP_VARTYPE
    Definition: type_var.h:73