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