SCIP

    Solving Constraint Integer Programs

    cons_pseudoboolean.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_pseudoboolean.c
    26 * @ingroup DEFPLUGINS_CONS
    27 * @brief constraint handler for pseudo Boolean constraints
    28 * @author Gerald Gamrath
    29 * @author Stefan Heinz
    30 * @author Michael Winkler
    31 * @author Dominik Kamp
    32 *
    33 * The constraint handler deals with pseudo Boolean constraints. These are constraints of the form
    34 * \f[
    35 * \mbox{lhs} \leq \sum_{k=0}^m c_k \cdot x_k + \sum_{i=0}^n c_i \cdot \prod_{j \in I_i} x_j \leq \mbox{rhs}
    36 * \f]
    37 * where all x are binary and all c are integer
    38 *
    39 * @todo Add eventhandling.
    40 */
    41
    42/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    43
    45#include "scip/cons_and.h"
    46#include "scip/cons_indicator.h"
    47#include "scip/cons_knapsack.h"
    48#include "scip/cons_linear.h"
    49#include "scip/cons_logicor.h"
    51#include "scip/cons_setppc.h"
    52#include "scip/cons_xor.h"
    53#include "scip/debug.h"
    54#include "scip/pub_cons.h"
    55#include "scip/pub_message.h"
    56#include "scip/pub_misc.h"
    57#include "scip/pub_misc_sort.h"
    58#include "scip/pub_var.h"
    59#include "scip/scip_cons.h"
    60#include "scip/scip_copy.h"
    61#include "scip/scip_general.h"
    62#include "scip/scip_mem.h"
    63#include "scip/scip_message.h"
    64#include "scip/scip_numerics.h"
    65#include "scip/scip_param.h"
    66#include "scip/scip_prob.h"
    67#include "scip/scip_sol.h"
    68#include "scip/scip_var.h"
    69#include "scip/symmetry_graph.h"
    70#ifdef WITHEQKNAPSACK
    71#include "scip/cons_eqknapsack.h" /* cppcheck-suppress missingInclude */
    72#endif
    73
    74/* constraint handler properties */
    75#define CONSHDLR_NAME "pseudoboolean"
    76#define CONSHDLR_DESC "constraint handler dealing with pseudo Boolean constraints"
    77#define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */
    78#define CONSHDLR_CHECKPRIORITY -5000000 /**< priority of the constraint handler for checking feasibility */
    79#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
    80 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    81#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
    82#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
    83
    84#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_MEDIUM /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
    85
    86#define DEFAULT_DECOMPOSENORMALPBCONS FALSE /**< decompose every normal pseudo boolean constraint into a "linear" constraint and "and" constraints */
    87#define DEFAULT_DECOMPOSEINDICATORPBCONS TRUE /**< decompose every soft pseudo boolean constraint into "indicator" constraints and "and" constraints */
    88
    89#define DEFAULT_SEPARATENONLINEAR TRUE /**< if decomposed, should the nonlinear constraints be separated during LP processing */
    90#define DEFAULT_PROPAGATENONLINEAR TRUE /**< if decomposed, should the nonlinear constraints be propagated during node processing */
    91#define DEFAULT_REMOVABLENONLINEAR TRUE /**< if decomposed, should the nonlinear constraints be removable */
    92#define NONLINCONSUPGD_PRIORITY 60000 /**< priority of upgrading nonlinear constraints */
    93
    94/* remove this line to compile the upgrade from nonlinear to pseudoboolean constraints */
    95#undef NONLINCONSUPGD_PRIORITY /*lint !e750*/
    96
    97/*
    98 * Data structures
    99 */
    100#define HASHSIZE_PSEUDOBOOLEANNONLINEARTERMS 500 /**< minimal size of hash table in and constraint tables */
    101
    102
    103/* - create special linear(knapsack, setppc, logicor, (eqknapsack)) and and-constraints with check flags FALSE, to
    104 * get smaller amount of locks on the term variables, do all presolving ...?! in these constraint handlers
    105 *
    106 * - do the checking here, lock and-resultants in both directions and all and-variables according to their
    107 * coefficients and sides of the constraint,
    108 * @note this only works if the and-resultant has no objective cofficient, otherwise we need to lock variables also in both directions
    109 *
    110 * - need to keep and constraint pointer for special propagations like if two ands are due to their variables in
    111 * one clique, add this cliques of and-resultants
    112 *
    113 * - do special presolving like on instance :
    114 * check/IP/PseudoBoolean/normalized-PB07/OPT-SMALLINT-NLC/submittedPB07/manquinho/bsg/normalized-bsg_1000_25_1.opb.gz
    115 *
    116 * there exist constraint like: 1 x1 x2 + 1 x1 x3 + 1 x1 x4 + 1 x1 x5 <= 1 ;
    117 * which "equals" a linear constraint: 3 x1 + x2 + x3 + x4 + x5 <= 4 ;
    118 *
    119 * in more general terms: 1 x1 x2 x3 x4 + 1 x1 x2 x5 x6 x7 + 1 x1 x2 x8 x9 <= 1 ;
    120 * which "equals" a pseudoboolean constraint: 2 x1 + 2 x2 + 1 x3 x4 + 1 x5 x6 x7 + 1 x8 x9 <= 5 ;
    121 *
    122 * in an even more general terms: 5 x1 x2 x3 x4 + 1 x1 x2 x5 x6 x7 + 1 x1 x2 x8 x9 <= 6 ;
    123 * equals(should the knapsack do) 1 x1 x2 x3 x4 + 1 x1 x2 x5 x6 x7 + 1 x1 x2 x8 x9 <= 2 ;
    124 * which "equals" a pseudoboolean constraint: 2 x1 + 2 x2 + 1 x3 x4 + 1 x5 x6 x7 + 1 x8 x9 <= 6 ;
    125 * ( without knapsack 7 x1 + 7 x2 + 5 x3 x4 + 1 x5 x6 x7 + 1 x8 x9 <= 20 ; )
    126 *
    127 * another special case : 1 x1 x2 x3 + 1 x1 x2 x4 + 1 x5 x6 <= 1 ;
    128 * which "equals" a pseudoboolean constraint: 2 x1 + 2 x2 + 1 x3 + 1 x4 + 1 x5 x6 <= 5 ;
    129 * which "equals" a pseudoboolean constraint: 4 x1 + 4 x2 + 2 x3 + 2 x4 + 1 x5 + 1 x6 <= 10 ;
    130 *
    131 * another special case : 1 x1 x2 + 1 x1 x3 + 2 x4 x5 <= 3 ;
    132 * which "equals" a pseudoboolean constraint: 2 x1 + 1 x2 + 1 x3 + 2 x4 x5 <= 5 ;
    133 * which "equals" a pseudoboolean constraint: 2 x1 + 1 x2 + 1 x3 + 1 x4 + 1 x5 <= 5 ;
    134 */
    135/* @todo - in and-constraint better count nfixed zeros in both directions and maybe nfixedones for better propagation
    136 *
    137 * - do better conflict analysis by choosing the earliest fixed variable which led to a conflict instead of maybe
    138 * best coefficient or create more conflicts by using all to zero fixed variables one by one
    139 *
    140 * - how to make sure that we aggregate in a right way, when aggregating a resultant and a "normal" variable,
    141 * maybe add in SCIPaggregateVars a check for original variables, to prefer them if the variable type is the
    142 * same; probably it would be better too if we would aggregate two resultants that the one with less variables
    143 * inside the and-constraint will stay active
    144 *
    145 * @note since product resultants are artificial, we do not care for their solution value, but this can lead to fixation
    146 * of the resultant not representing the product, in 'optimization mode' we do not care, but this might make
    147 * solution debugging complicated
    148 */
    149
    150/** and-constraint data object */
    152{
    153 SCIP_CONS* cons; /**< pointer to the and-constraint of this 'term' of variables */
    154 SCIP_CONS* origcons; /**< pointer to the original and-constraint of this 'term' of variables
    155 * only after problem was transformed, NULL otherwise */
    156 SCIP_VAR** vars; /**< all and-constraint variables */
    157 int nvars; /**< number of all and-constraint variables */
    158 int svars; /**< size for all and-constraint variables */
    159 SCIP_VAR** newvars; /**< new variables in this presolving round */
    160 int nnewvars; /**< number of new variables in this presolving round */
    161 int snewvars; /**< size of new variables in this presolving round */
    162 int noriguses; /**< how often is this data in used by original constraints */
    163 int nuses; /**< how often is this data in used by transformed constraints */
    164 unsigned int istransformed:1; /**< is transformed data active */
    165 unsigned int isoriginal:1; /**< is original data active */
    166};
    168
    169/** constraint data for pseudoboolean constraints */
    170struct SCIP_ConsData
    171{
    172 SCIP_Real lhs; /**< left hand side of constraint */
    173 SCIP_Real rhs; /**< right hand side of constraint */
    174
    175 SCIP_CONS* lincons; /**< linear constraint which represents this pseudoboolean constraint */
    176 SCIP_LINEARCONSTYPE linconstype; /**< type of linear constraint which represents this pseudoboolean constraint */
    177 int nlinvars; /**< number of linear variables (without and-resultants) */
    178
    179 CONSANDDATA** consanddatas; /**< array of and-constraints-data-objects sorted after problem index of
    180 * and-resultant of corresponding and-constraint */
    181 SCIP_Real* andcoefs; /**< array of coefficients for and-constraints of
    182 * and-constraints-data-objects
    183 * (changes during presolving, needs to be updated in every presolving
    184 * round) */
    185 SCIP_Bool* andnegs; /**< array of negation status for and-constraints of
    186 * and-constraints-data-objects
    187 * (changes during presolving, needs to be updated in every presolving
    188 * round) */
    189 int nconsanddatas; /**< number of and-constraints-data-objects */
    190 int sconsanddatas; /**< size of and-constraints-data-objects array */
    191
    192 SCIP_VAR* indvar; /**< indicator variable if it's a soft constraint, or NULL */
    193 SCIP_Real weight; /**< weight of the soft constraint, if it is one */
    194
    195 unsigned int issoftcons:1; /**< is this a soft constraint */
    196 unsigned int changed:1; /**< was constraint changed? */
    197 unsigned int propagated:1; /**< is constraint already propagated? */
    198 unsigned int presolved:1; /**< is constraint already presolved? */
    199 unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */
    200 unsigned int upgradetried:1; /**< was constraint upgrading already tried */
    201};
    202
    203/** constraint handler data */
    204struct SCIP_ConshdlrData
    205{
    206 CONSANDDATA** allconsanddatas; /**< array of all and-constraint data objects inside the whole problem,
    207 * created via this constraint handler */
    208 int nallconsanddatas; /**< number of all and-constraint data objects inside the whole problem,
    209 * created via this constraint handler */
    210 int sallconsanddatas; /**< size of all and-constraint data objects inside the whole problem,
    211 * created via this constraint handler */
    212 SCIP_HASHTABLE* hashtable; /**< hash table for all and-constraint data objects */
    213 int hashtablesize; /**< size for hash table for all and-constraint data objects */
    214
    215 SCIP_HASHMAP* hashmap; /**< hash map for mapping all resultant to and-constraint */
    216 int hashmapsize; /**< size for hash map for mapping all resultant to and-constraint */
    217
    218 SCIP_Bool decomposenormalpbcons; /**< decompose every normal pseudo boolean constraint into a "linear" constraint and "and" constraints */
    219 SCIP_Bool decomposeindicatorpbcons; /**< decompose every soft pseudo boolean constraint into "indicator" constraints and "and" constraints */
    220 SCIP_Bool inithashmapandtable;/**< flag to store if the hashmap and -table is initialized */
    221 int nlinconss; /**< for counting number of created linear constraints */
    222 int noriguses; /**< how many consanddata objects are used by original constraints */
    223};
    224
    225
    226/*
    227 * Local methods
    228 */
    229
    230/** comparison method for sorting and-resultants according to their problem index, which is used instead of the
    231 * original index because the implicit resultants are shuffled when creating the constraints that otherwise results in
    232 * shuffled problem copies,
    233 * if an and-resultant is fixed, it will be put in front with respect to its original index
    234 * if an and-resultant is negated, it will be put in front of its negation counterpart
    235 */
    236static
    238{
    239 SCIP_VAR* var1 = elem1;
    240 SCIP_VAR* var2 = elem2;
    241 SCIP_Bool varneg1 = SCIPvarIsNegated(var1);
    242 SCIP_Bool varneg2 = SCIPvarIsNegated(var2);
    243
    244 if( varneg1 )
    245 var1 = SCIPvarGetNegatedVar(var1);
    246
    247 if( varneg2 )
    248 var2 = SCIPvarGetNegatedVar(var2);
    249
    250 int varind1 = SCIPvarGetProbindex(var1);
    251 int varind2 = SCIPvarGetProbindex(var2);
    252
    253 if( varind1 == -1 && varind2 == -1 )
    254 {
    255 varind1 = SCIPvarGetIndex(var1);
    256 varind2 = SCIPvarGetIndex(var2);
    257 }
    258
    259 if( varind1 < varind2 )
    260 return -1;
    261 if( varind1 > varind2 )
    262 return +1;
    263
    264 if( varneg1 && !varneg2 )
    265 return -1;
    266 if( !varneg1 && varneg2 )
    267 return +1;
    268
    269 assert(elem1 == elem2);
    270 return 0;
    271}
    272
    273/** comparison method for sorting consanddatas according to the problem index of their corresponding and-resultants,
    274 * if a consanddata object is deleted, it is handled like it has an inactive resultant, so this will be put
    275 * in front while sorting
    276 */
    277static
    278SCIP_DECL_SORTPTRCOMP(resvarCompWithInactive)
    279{
    280 CONSANDDATA* consanddata1 = (CONSANDDATA*)elem1;
    281 CONSANDDATA* consanddata2 = (CONSANDDATA*)elem2;
    282
    283 assert(consanddata1 != NULL);
    284 assert(consanddata2 != NULL);
    285
    286 /* consider that constraint data object can be only original */
    287 if( consanddata1->istransformed != consanddata2->istransformed )
    288 return consanddata1->istransformed ? +1 : -1;
    289
    290 SCIP_CONS* consand1;
    291 SCIP_CONS* consand2;
    292
    293 if( consanddata1->istransformed )
    294 {
    295 consand1 = consanddata1->cons;
    296 consand2 = consanddata2->cons;
    297 }
    298 else
    299 {
    300 consand1 = consanddata1->origcons;
    301 consand2 = consanddata2->origcons;
    302 }
    303
    304 /* check if and-constraint is still active */
    305 if( SCIPconsIsDeleted(consand1) )
    306 {
    307 if( SCIPconsIsDeleted(consand2) )
    308 return 0;
    309 else
    310 return -1;
    311 }
    312 else if( SCIPconsIsDeleted(consand2) )
    313 return +1;
    314
    315 /* hack with setting the scip pointer to NULL */
    316 return resvarComp((void*)SCIPgetResultantAnd(NULL, consand1), (void*)SCIPgetResultantAnd(NULL, consand2));
    317}
    318
    319/** gets the key of the given element */
    320static
    321SCIP_DECL_HASHGETKEY(hashGetKeyAndConsDatas)
    322{ /*lint --e{715}*/
    323 /* the key is the element itself */
    324 return elem;
    325}
    326
    327/** returns TRUE iff both keys are equal; two non-linear terms are equal if they have the same variables */
    328static
    329SCIP_DECL_HASHKEYEQ(hashKeyEqAndConsDatas)
    330{
    331#ifndef NDEBUG
    332 SCIP* scip;
    333#endif
    334 CONSANDDATA* cdata1;
    335 CONSANDDATA* cdata2;
    336 int v;
    337
    338 cdata1 = (CONSANDDATA*)key1;
    339 cdata2 = (CONSANDDATA*)key2;
    340
    341#ifndef NDEBUG
    342 scip = (SCIP*)userptr;
    343#endif
    344 assert(scip != NULL);
    345 assert(cdata1 != NULL);
    346 assert(cdata2 != NULL);
    347 assert(cdata1->vars != NULL);
    348 assert(cdata1->nvars > 1);
    349 assert(cdata2->vars != NULL);
    350 assert(cdata2->nvars > 1);
    351
    352#ifndef NDEBUG
    353 /* check that cdata1 variables are sorted */
    354 for( v = cdata1->nvars - 1; v > 0; --v )
    355 assert(SCIPvarGetIndex(cdata1->vars[v]) >= SCIPvarGetIndex(cdata1->vars[v - 1]));
    356 /* check that cdata2 variables are sorted */
    357 for( v = cdata2->nvars - 1; v > 0; --v )
    358 assert(SCIPvarGetIndex(cdata2->vars[v]) >= SCIPvarGetIndex(cdata2->vars[v - 1]));
    359#endif
    360
    361 /* checks trivial case */
    362 if( cdata1->nvars != cdata2->nvars )
    363 return FALSE;
    364
    365 /* checks trivial case */
    366 if( cdata1->cons != NULL && cdata2->cons != NULL && cdata1->cons != cdata2->cons )
    367 return FALSE;
    368
    369 /* check each variable in both cdatas for equality */
    370 for( v = cdata1->nvars - 1; v >= 0; --v )
    371 {
    372 assert(cdata1->vars[v] != NULL);
    373 assert(cdata2->vars[v] != NULL);
    374
    375 /* tests if variables are equal */
    376 if( cdata1->vars[v] != cdata2->vars[v] )
    377 {
    378 assert(SCIPvarCompare(cdata1->vars[v], cdata2->vars[v]) == 1 ||
    379 SCIPvarCompare(cdata1->vars[v], cdata2->vars[v]) == -1);
    380 return FALSE;
    381 }
    382 assert(SCIPvarCompare(cdata1->vars[v], cdata2->vars[v]) == 0);
    383 }
    384
    385 return TRUE;
    386}
    387
    388/** returns the hash value of the key */
    389static
    390SCIP_DECL_HASHKEYVAL(hashKeyValAndConsDatas)
    391{ /*lint --e{715}*/
    392 CONSANDDATA* cdata;
    393 int minidx;
    394 int mididx;
    395 int maxidx;
    396
    397 cdata = (CONSANDDATA*)key;
    398
    399 assert(cdata != NULL);
    400 assert(cdata->vars != NULL);
    401 assert(cdata->nvars > 1);
    402#ifndef NDEBUG
    403 {
    404 /* check that these variables are sorted */
    405 int v;
    406 for( v = cdata->nvars - 1; v > 0; --v )
    407 assert(SCIPvarGetIndex(cdata->vars[v]) >= SCIPvarGetIndex(cdata->vars[v - 1]));
    408 }
    409#endif
    410
    411 minidx = SCIPvarGetIndex(cdata->vars[0]);
    412 mididx = SCIPvarGetIndex(cdata->vars[cdata->nvars / 2]);
    413 maxidx = SCIPvarGetIndex(cdata->vars[cdata->nvars - 1]);
    414 assert(minidx >= 0 && minidx <= maxidx);
    415
    416 return SCIPhashFour(cdata->nvars, minidx, mididx, maxidx);
    417}
    418
    419/** initializes the hashmap and -table used in this constraint handler data for artificial variables and specific
    420 * and-constraint data objects
    421 */
    422static
    424 SCIP*const scip, /**< SCIP data structure */
    425 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to store the constraint handler data */
    426 )
    427{
    428 if( ((*conshdlrdata)->inithashmapandtable) )
    429 {
    430 assert((*conshdlrdata)->hashtable != NULL);
    431 assert((*conshdlrdata)->hashmap != NULL);
    432
    433 return SCIP_OKAY;
    434 }
    435
    436 assert((*conshdlrdata)->hashtable == NULL);
    437 assert((*conshdlrdata)->hashmap == NULL);
    438
    439 /* create a hash table for and-constraint data objects */
    440 (*conshdlrdata)->hashtablesize = HASHSIZE_PSEUDOBOOLEANNONLINEARTERMS;
    441 SCIP_CALL( SCIPhashtableCreate(&((*conshdlrdata)->hashtable), SCIPblkmem(scip), (*conshdlrdata)->hashtablesize,
    442 hashGetKeyAndConsDatas, hashKeyEqAndConsDatas, hashKeyValAndConsDatas, (void*) scip) );
    443
    444 /* create a hash table for and-resultant to and-constraint data objects */
    445 (*conshdlrdata)->hashmapsize = HASHSIZE_PSEUDOBOOLEANNONLINEARTERMS;
    446 SCIP_CALL( SCIPhashmapCreate(&((*conshdlrdata)->hashmap), SCIPblkmem(scip), (*conshdlrdata)->hashmapsize) );
    447
    448 (*conshdlrdata)->inithashmapandtable = TRUE;
    449
    450 return SCIP_OKAY;
    451}
    452
    453/** creates constraint handler data for pseudo boolean constraint handler */
    454static
    456 SCIP*const scip, /**< SCIP data structure */
    457 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to store the constraint handler data */
    458 )
    459{
    460 assert(scip != NULL);
    461 assert(conshdlrdata != NULL);
    462
    463 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
    464
    465 (*conshdlrdata)->allconsanddatas = NULL;
    466 (*conshdlrdata)->nallconsanddatas = 0;
    467 (*conshdlrdata)->sallconsanddatas = 10;
    468
    469 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*conshdlrdata)->allconsanddatas), (*conshdlrdata)->sallconsanddatas ) );
    470
    471 /* set hashmap and -table to NULL, mark them as uninitialized */
    472 (*conshdlrdata)->inithashmapandtable = FALSE;
    473 (*conshdlrdata)->hashtable = NULL;
    474 (*conshdlrdata)->hashtablesize = 0;
    475 (*conshdlrdata)->hashmap = NULL;
    476 (*conshdlrdata)->hashmapsize = 0;
    477
    478 /* for constraint names count number of created constraints */
    479 (*conshdlrdata)->nlinconss = 0;
    480
    481 /* initializes how many consanddata objects are used by original constraints */
    482 (*conshdlrdata)->noriguses = 0;
    483
    484 return SCIP_OKAY;
    485}
    486
    487
    488/** frees constraint handler data for pseudo boolean constraint handler */
    489static
    491 SCIP*const scip, /**< SCIP data structure */
    492 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
    493 )
    494{
    495 assert(scip != NULL);
    496 assert(conshdlrdata != NULL);
    497 assert(*conshdlrdata != NULL);
    498 assert((*conshdlrdata)->nallconsanddatas == 0);
    499
    500 /* free hash table if necessary */
    501 if( (*conshdlrdata)->inithashmapandtable )
    502 {
    503 SCIPhashmapFree(&((*conshdlrdata)->hashmap));
    504 (*conshdlrdata)->hashmapsize = 0;
    505 SCIPhashtableFree(&((*conshdlrdata)->hashtable));
    506 (*conshdlrdata)->hashtablesize = 0;
    507 }
    508 else
    509 {
    510 assert((*conshdlrdata)->hashmap == NULL);
    511 assert((*conshdlrdata)->hashtable == NULL);
    512 }
    513 (*conshdlrdata)->inithashmapandtable = FALSE;
    514
    515 /* clear array for all consanddata objects */
    516 SCIPfreeBlockMemoryArray(scip, &((*conshdlrdata)->allconsanddatas), (*conshdlrdata)->sallconsanddatas );
    517
    518 (*conshdlrdata)->allconsanddatas = NULL;
    519 (*conshdlrdata)->nallconsanddatas = 0;
    520 (*conshdlrdata)->sallconsanddatas = 0;
    521
    522 SCIPfreeBlockMemory(scip, conshdlrdata);
    523
    524 return SCIP_OKAY;
    525}
    526
    527/** gets number of variables in linear constraint */
    528static
    530 SCIP*const scip, /**< SCIP data structure */
    531 SCIP_CONS*const cons, /**< linear constraint */
    532 SCIP_LINEARCONSTYPE const constype, /**< linear constraint type */
    533 int*const nvars /**< pointer to store number variables of linear constraint */
    534 )
    535{
    536 assert(scip != NULL);
    537 assert(cons != NULL);
    538 assert(nvars != NULL);
    539
    540 /* determine for each special linear constranit all variables and coefficients */
    541 switch( constype )
    542 {
    544 *nvars = SCIPgetNVarsLinear(scip, cons);
    545 break;
    547 *nvars = SCIPgetNVarsLogicor(scip, cons);
    548 break;
    550 *nvars = SCIPgetNVarsKnapsack(scip, cons);
    551 break;
    553 *nvars = SCIPgetNVarsSetppc(scip, cons);
    554 break;
    555#ifdef WITHEQKNAPSACK
    556 case SCIP_LINEARCONSTYPE_EQKNAPSACK:
    557 *nvars = SCIPgetNVarsEQKnapsack(scip, cons);
    558 break;
    559#endif
    561 default:
    562 SCIPerrorMessage("unknown linear constraint type\n");
    563 return SCIP_INVALIDDATA;
    564 }
    565
    566 return SCIP_OKAY;
    567}
    568
    569
    570/** gets sides of linear constraint */
    571static
    573 SCIP*const scip, /**< SCIP data structure */
    574 SCIP_CONS*const cons, /**< linear constraint */
    575 SCIP_LINEARCONSTYPE const constype, /**< linear constraint type */
    576 SCIP_Real*const lhs, /**< pointer to store left hand side of linear constraint */
    577 SCIP_Real*const rhs /**< pointer to store right hand side of linear constraint */
    578 )
    579{
    580 SCIP_SETPPCTYPE type;
    581
    582 switch( constype )
    583 {
    585 *lhs = SCIPgetLhsLinear(scip, cons);
    586 *rhs = SCIPgetRhsLinear(scip, cons);
    587 break;
    589 *lhs = 1.0;
    590 *rhs = SCIPinfinity(scip);
    591 break;
    593 *lhs = -SCIPinfinity(scip);
    594 *rhs = SCIPgetCapacityKnapsack(scip, cons);
    595 break;
    597 type = SCIPgetTypeSetppc(scip, cons);
    598
    599 switch( type )
    600 {
    602 *lhs = 1.0;
    603 *rhs = 1.0;
    604 break;
    606 *lhs = -SCIPinfinity(scip);
    607 *rhs = 1.0;
    608 break;
    610 *lhs = 1.0;
    611 *rhs = SCIPinfinity(scip);
    612 break;
    613 default:
    614 SCIPerrorMessage("unknown setppc type\n");
    615 return SCIP_INVALIDDATA;
    616 }
    617 break;
    618#ifdef WITHEQKNAPSACK
    619 case SCIP_LINEARCONSTYPE_EQKNAPSACK:
    620 *lhs = SCIPgetCapacityEQKnapsack(scip, cons);
    621 *rhs = *lhs;
    622 break;
    623#endif
    625 default:
    626 SCIPerrorMessage("unknown linear constraint type\n");
    627 return SCIP_INVALIDDATA;
    628 }
    629
    630 return SCIP_OKAY;
    631}
    632
    633/** gets variables and coefficients of linear constraint */
    634static
    636 SCIP*const scip, /**< SCIP data structure */
    637 SCIP_CONS*const cons, /**< linear constraint */
    638 SCIP_LINEARCONSTYPE const constype, /**< linear constraint type */
    639 SCIP_VAR**const vars, /**< array to store variables of linear constraint */
    640 SCIP_Real*const coefs, /**< array to store coefficient of linear constraint, or NULL */
    641 int*const nvars /**< pointer to store number variables of linear constraint */
    642 )
    643{
    644 SCIP_VAR** linvars;
    645 int v;
    646
    647 assert(scip != NULL);
    648 assert(cons != NULL);
    649 assert(vars != NULL);
    650 assert(nvars != NULL);
    651
    652 /* determine for each special linear constrait all variables and coefficients */
    653 switch( constype )
    654 {
    656 {
    657 SCIP_Real* lincoefs;
    658
    659 *nvars = SCIPgetNVarsLinear(scip, cons);
    660 linvars = SCIPgetVarsLinear(scip, cons);
    661
    662 if( coefs != NULL )
    663 {
    664 lincoefs = SCIPgetValsLinear(scip, cons);
    665
    666 for( v = 0; v < *nvars; ++v )
    667 {
    668 vars[v] = linvars[v];
    669 coefs[v] = lincoefs[v];
    670 }
    671 }
    672 else
    673 {
    674 for( v = 0; v < *nvars; ++v )
    675 vars[v] = linvars[v];
    676 }
    677
    678 break;
    679 }
    681 *nvars = SCIPgetNVarsLogicor(scip, cons);
    682 linvars = SCIPgetVarsLogicor(scip, cons);
    683 assert( linvars != NULL );
    684
    685 if( coefs != NULL )
    686 {
    687 for( v = 0; v < *nvars; ++v )
    688 {
    689 vars[v] = linvars[v];
    690 coefs[v] = 1.0;
    691 }
    692 }
    693 else
    694 {
    695 for( v = 0; v < *nvars; ++v )
    696 vars[v] = linvars[v];
    697 }
    698
    699 break;
    701 {
    702 SCIP_Longint* weights;
    703
    704 *nvars = SCIPgetNVarsKnapsack(scip, cons);
    705 linvars = SCIPgetVarsKnapsack(scip, cons);
    706 assert( linvars != NULL );
    707
    708 if( coefs != NULL )
    709 {
    710 weights = SCIPgetWeightsKnapsack(scip, cons);
    711
    712 for( v = 0; v < *nvars; ++v )
    713 {
    714 vars[v] = linvars[v];
    715 coefs[v] = (SCIP_Real) weights[v];
    716 }
    717 }
    718 else
    719 {
    720 for( v = 0; v < *nvars; ++v )
    721 vars[v] = linvars[v];
    722 }
    723
    724 break;
    725 }
    727 *nvars = SCIPgetNVarsSetppc(scip, cons);
    728 linvars = SCIPgetVarsSetppc(scip, cons);
    729 assert( linvars != NULL );
    730
    731 if( coefs != NULL )
    732 {
    733 for( v = 0; v < *nvars; ++v )
    734 {
    735 vars[v] = linvars[v];
    736 coefs[v] = 1.0;
    737 }
    738 }
    739 else
    740 {
    741 for( v = 0; v < *nvars; ++v )
    742 vars[v] = linvars[v];
    743 }
    744
    745 break;
    746#ifdef WITHEQKNAPSACK
    747 case SCIP_LINEARCONSTYPE_EQKNAPSACK:
    748 {
    749 SCIP_Longint* weights;
    750
    751 *nvars = SCIPgetNVarsEQKnapsack(scip, cons);
    752 linvars = SCIPgetVarsEQKnapsack(scip, cons);
    753 assert( linvars != NULL );
    754
    755 if( coefs != NULL )
    756 {
    757 weights = SCIPgetWeightsEQKnapsack(scip, cons);
    758
    759 for( v = 0; v < *nvars; ++v )
    760 {
    761 vars[v] = linvars[v];
    762 coefs[v] = (SCIP_Real) weights[v];
    763 }
    764 }
    765 else
    766 {
    767 for( v = 0; v < *nvars; ++v )
    768 vars[v] = linvars[v];
    769 }
    770
    771 break;
    772 }
    773#endif
    775 default:
    776 SCIPerrorMessage("unknown linear constraint type\n");
    777 return SCIP_INVALIDDATA;
    778 }
    779
    780 return SCIP_OKAY;
    781}
    782
    783/** splits up into original linear variables and artificial and-resultants */
    784static
    786 SCIP*const scip, /**< SCIP data structure */
    787 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    788 SCIP_VAR**const vars, /**< all variables of linear constraint */
    789 SCIP_Real*const coefs, /**< all coefficients of linear constraint, or NULL */
    790 int const nvars, /**< number of all variables of linear constraint */
    791 SCIP_VAR**const linvars, /**< array to store not and-resultant variables of linear constraint, or NULL */
    792 SCIP_Real*const lincoefs, /**< array to store coefficients of not and-resultant variables of linear
    793 * constraint, or NULL */
    794 int*const nlinvars, /**< pointer to store number of not and-resultant variables, or NULL */
    795 SCIP_VAR**const andress, /**< array to store and-resultant variables of linear constraint, or NULL */
    796 SCIP_Real*const andcoefs, /**< array to store coefficients of and-resultant variables of linear
    797 * constraint, or NULL */
    798 SCIP_Bool*const andnegs, /**< array to store negation status of and-resultant variables of linear
    799 * constraint, or NULL */
    800 int*const nandress /**< pointer to store number of and-resultant variables, or NULL */
    801 )
    802{
    803 SCIP_CONSHDLR* conshdlr;
    804 SCIP_CONSHDLRDATA* conshdlrdata;
    805 int v;
    806
    807 assert(scip != NULL);
    808 assert(cons != NULL);
    809 assert(vars != NULL);
    810 assert((linvars != NULL) == (nlinvars != NULL));
    811 assert((andress == NULL) || (nandress != NULL));
    812 assert((andcoefs != NULL) == (andnegs != NULL));
    813 assert((coefs != NULL) == ((lincoefs != NULL) || (andcoefs != NULL)));
    814 assert(linvars != NULL || andress != NULL);
    815
    816 if( nlinvars != NULL )
    817 *nlinvars = 0;
    818 if( nandress != NULL )
    819 *nandress = 0;
    820
    821 conshdlr = SCIPconsGetHdlr(cons);
    822 assert(conshdlr != NULL);
    823 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    824 assert(conshdlrdata != NULL);
    825 assert(conshdlrdata->hashmap != NULL);
    826
    827 /* split variables into original and artificial variables */
    828 for( v = 0; v < nvars; ++v )
    829 {
    830 SCIP_Bool hashmapentryexists;
    831 SCIP_VAR* hashmapvar;
    832
    833 assert(vars[v] != NULL);
    834
    835 hashmapentryexists = SCIPhashmapExists(conshdlrdata->hashmap, (void*)(vars[v]));
    836
    837 if( !hashmapentryexists && SCIPvarIsNegated(vars[v]) )
    838 {
    839 hashmapvar = SCIPvarGetNegationVar(vars[v]);
    840 hashmapentryexists = SCIPhashmapExists(conshdlrdata->hashmap, (void*)(hashmapvar));
    841 }
    842 else
    843 hashmapvar = vars[v];
    844
    845 /* if and resultant is not a resultant anymore (meaning the corresponding and-constraint was deleted/upgraded),
    846 * correct the flag and count this variable as normal linear variable
    847 */
    848 if( hashmapentryexists )
    849 {
    850 if( !SCIPconsIsOriginal(cons) )
    851 {
    852 CONSANDDATA* consanddata = (CONSANDDATA*) SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)(hashmapvar));
    853 assert(consanddata != NULL);
    854
    855 hashmapentryexists = (consanddata->istransformed);
    856
    857 if( hashmapentryexists )
    858 {
    859 assert(consanddata->cons != NULL);
    860 hashmapentryexists = !SCIPconsIsDeleted(consanddata->cons);
    861 }
    862 }
    863 }
    864
    865 if( !hashmapentryexists && linvars != NULL && nlinvars != NULL )
    866 {
    867 linvars[*nlinvars] = vars[v];
    868 if( lincoefs != NULL )
    869 {
    870 assert(coefs != NULL);
    871 lincoefs[*nlinvars] = coefs[v];
    872 }
    873 ++(*nlinvars);
    874 }
    875 else if( hashmapentryexists && nandress != NULL )
    876 {
    877 if( andress != NULL )
    878 {
    879 andress[*nandress] = hashmapvar;
    880
    881 if( andcoefs != NULL )
    882 {
    883 assert(andnegs != NULL);
    884 assert(coefs != NULL);
    885 andcoefs[*nandress] = coefs[v];
    886 andnegs[*nandress] = (vars[v] != hashmapvar);
    887 }
    888 }
    889 ++(*nandress);
    890 }
    891 }
    892
    893 return SCIP_OKAY;
    894}
    895
    896
    897#ifdef CHECK_CONSISTENCY
    898/** check constraint consistency */
    899static
    901 SCIP*const scip, /**< SCIP data structure */
    902 SCIP_CONS*const cons /**< pseudoboolean constraint */
    903 )
    904{
    905 SCIP_CONSDATA* consdata;
    906 SCIP_VAR** vars;
    907 SCIP_Real* coefs;
    908 int nvars;
    909 SCIP_VAR** linvars;
    910 SCIP_Real* lincoefs;
    911 int nlinvars;
    912 SCIP_VAR** andress;
    913 SCIP_Real* andcoefs;
    914 SCIP_Bool* andnegs;
    915 int nandress;
    916 SCIP_Bool* alreadyfound;
    917 SCIP_VAR* res;
    918 int c;
    919 int v;
    920 SCIP_Real newlhs;
    921 SCIP_Real newrhs;
    922
    923 assert(scip != NULL);
    924 assert(cons != NULL);
    925
    927 return;
    928
    929 consdata = SCIPconsGetData(cons);
    930 assert(consdata != NULL);
    931
    932 /* check standard pointers and sizes */
    933 assert(consdata->lincons != NULL);
    934 assert(!SCIPconsIsDeleted(consdata->lincons));
    935 assert(consdata->linconstype > SCIP_LINEARCONSTYPE_INVALIDCONS);
    936 assert(consdata->consanddatas != NULL);
    937 assert(consdata->nconsanddatas > 0);
    938 assert(consdata->nconsanddatas <= consdata->sconsanddatas);
    939
    940 /* get sides of linear constraint */
    941 SCIP_CALL_ABORT( getLinearConsSides(scip, consdata->lincons, consdata->linconstype, &newlhs, &newrhs) );
    942 assert(!SCIPisInfinity(scip, newlhs));
    943 assert(!SCIPisInfinity(scip, -newrhs));
    944 assert(SCIPisLE(scip, newlhs, newrhs));
    945 assert(SCIPisEQ(scip, newrhs, consdata->rhs) || SCIPisEQ(scip, newrhs, -consdata->lhs));
    946 assert(SCIPisEQ(scip, newlhs, consdata->lhs) || SCIPisEQ(scip, newlhs, -consdata->rhs));
    947
    948 /* check number of linear variables */
    949 SCIP_CALL_ABORT( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
    950 assert(nvars == consdata->nlinvars + consdata->nconsanddatas);
    951
    952 /* get temporary memory */
    953 SCIP_CALL_ABORT( SCIPallocBufferArray(scip, &vars, nvars) );
    954 SCIP_CALL_ABORT( SCIPallocBufferArray(scip, &coefs, nvars) );
    955 SCIP_CALL_ABORT( SCIPallocBufferArray(scip, &linvars, nvars) );
    956 SCIP_CALL_ABORT( SCIPallocBufferArray(scip, &lincoefs, nvars) );
    957 SCIP_CALL_ABORT( SCIPallocBufferArray(scip, &andress, nvars) );
    958 SCIP_CALL_ABORT( SCIPallocBufferArray(scip, &andcoefs, nvars) );
    959 SCIP_CALL_ABORT( SCIPallocBufferArray(scip, &andnegs, nvars) );
    960 SCIP_CALL_ABORT( SCIPallocClearBufferArray(scip, &alreadyfound, nvars) );
    961
    962 /* get variables and coefficients */
    963 SCIP_CALL_ABORT( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) );
    964 assert(coefs != NULL || nvars == 0);
    965
    966 /* calculate all not artificial linear variables and all artificial and-resultants */
    967 SCIP_CALL_ABORT( getLinVarsAndAndRess(scip, cons, vars, coefs, nvars, linvars, lincoefs, &nlinvars,
    968 andress, andcoefs, andnegs, &nandress) );
    969 assert(nlinvars == consdata->nlinvars);
    970 assert(nandress == consdata->nconsanddatas);
    971
    972 for( v = nandress - 1; v >= 0; --v )
    973 {
    974 SCIP_VAR* andresultant = andress[v];
    975 int nfound = 0;
    976
    977 for( c = consdata->nconsanddatas - 1; c >= 0; --c )
    978 {
    979 assert(consdata->consanddatas[c] != NULL);
    980 if( consdata->consanddatas[c]->cons != NULL )
    981 {
    982 res = SCIPgetResultantAnd(scip, consdata->consanddatas[c]->cons);
    983 assert(res != NULL);
    984
    985 if( res == andresultant && consdata->andnegs[c] == andnegs[v] && consdata->andcoefs[c] == andcoefs[v] )
    986 {
    987 /* resultant should be either active or a negated variable of an active one */
    989 assert(!alreadyfound[c]);
    990
    991 /* all and-resultants should be merged, so it is only allowed that each variable exists one time */
    992 alreadyfound[c] = TRUE;
    993 ++nfound;
    994 break;
    995 }
    996 }
    997 }
    998 assert(nfound == 1);
    999 }
    1000
    1001 for( c = consdata->nconsanddatas - 1; c >= 0; --c )
    1002 {
    1003 assert(alreadyfound[c]);
    1004 }
    1005
    1006 /* free temporary memory */
    1007 SCIPfreeBufferArray(scip, &alreadyfound);
    1008 SCIPfreeBufferArray(scip, &andnegs);
    1009 SCIPfreeBufferArray(scip, &andcoefs);
    1010 SCIPfreeBufferArray(scip, &andress);
    1011 SCIPfreeBufferArray(scip, &lincoefs);
    1012 SCIPfreeBufferArray(scip, &linvars);
    1013 SCIPfreeBufferArray(scip, &coefs);
    1014 SCIPfreeBufferArray(scip, &vars);
    1015}
    1016#else
    1017#define checkConsConsistency(scip, cons) /**/
    1018#endif
    1019
    1020
    1021/** transforming transformed consanddata object back to original space, if an corresponding original constraint exists,
    1022 * also clearing all transformed data, i.e. releasing transformed variables
    1023 */
    1024static
    1026 SCIP*const scip, /**< SCIP data structure */
    1027 CONSANDDATA* consanddata, /**< consanddata object */
    1028 SCIP_CONSHDLRDATA* conshdlrdata /**< constraint handler data */
    1029 )
    1030{
    1031 SCIP_VAR** tmpvars;
    1032 SCIP_Bool origdata;
    1033 int ntmpvars;
    1034 int v;
    1035
    1036 assert(scip != NULL);
    1037 assert(consanddata != NULL);
    1038 assert(conshdlrdata != NULL);
    1039
    1040 origdata = TRUE;
    1041
    1042 tmpvars = consanddata->vars;
    1043 ntmpvars = consanddata->nvars;
    1044
    1045 /* release all transformed variables */
    1046 for( v = ntmpvars - 1; v >= 0; --v )
    1047 {
    1048 assert(tmpvars[v] != NULL);
    1049 if( SCIPvarIsTransformed(tmpvars[v]) )
    1050 {
    1051 SCIP_CALL( SCIPreleaseVar(scip, &tmpvars[v]) );
    1052 origdata = FALSE;
    1053 }
    1054 }
    1055
    1056 tmpvars = consanddata->newvars;
    1057 ntmpvars = consanddata->nnewvars;
    1058
    1059 /* release all variables */
    1060 for( v = ntmpvars - 1; v >= 0; --v )
    1061 {
    1062 assert(tmpvars[v] != NULL);
    1063 if( SCIPvarIsTransformed(tmpvars[v]) )
    1064 {
    1065 SCIP_CALL( SCIPreleaseVar(scip, &tmpvars[v]) );
    1066 origdata = FALSE;
    1067 }
    1068 }
    1069
    1070 /* reinstall original data */
    1071 if( !origdata || consanddata->nvars == 0 )
    1072 {
    1073 SCIPfreeBlockMemoryArrayNull(scip, &(consanddata->vars), consanddata->svars);
    1074 SCIPfreeBlockMemoryArrayNull(scip, &(consanddata->newvars), consanddata->snewvars);
    1075
    1076 consanddata->nuses = 0;
    1077 consanddata->nvars = 0;
    1078 consanddata->svars = 0;
    1079 consanddata->nnewvars = 0;
    1080 consanddata->snewvars = 0;
    1081 consanddata->istransformed = FALSE;
    1082
    1083 if( consanddata->noriguses > 0 )
    1084 {
    1085 assert(consanddata->origcons != NULL);
    1086 assert(consanddata->isoriginal);
    1087
    1088 assert(SCIPgetNVarsAnd(scip, consanddata->origcons) > 0);
    1089 assert(SCIPgetVarsAnd(scip, consanddata->origcons) != NULL);
    1090 consanddata->nvars = SCIPgetNVarsAnd(scip, consanddata->origcons);
    1091 consanddata->svars = consanddata->nvars;
    1092
    1093 if( consanddata->nvars > 0 )
    1094 {
    1095 SCIP_VAR** andvars = SCIPgetVarsAnd(scip, consanddata->origcons);
    1096
    1097 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(consanddata->vars), andvars, consanddata->nvars) );
    1098
    1099 /* sort variables */
    1100 SCIPsortPtr((void**)(consanddata->vars), SCIPvarComp, consanddata->nvars);
    1101 }
    1102
    1103 /* check that the hash map and tabkle are still having all information */
    1104 if( conshdlrdata->inithashmapandtable )
    1105 {
    1106 assert(conshdlrdata->hashmap != NULL);
    1107 assert(conshdlrdata->hashtable != NULL);
    1108 assert(SCIPgetResultantAnd(scip, consanddata->origcons) != NULL);
    1109 assert(SCIPhashtableExists(conshdlrdata->hashtable, (void*)consanddata));
    1110 assert(consanddata == (CONSANDDATA*)(SCIPhashtableRetrieve(conshdlrdata->hashtable, (void*)consanddata)));
    1111 assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddata->origcons)));
    1112 assert(consanddata == (CONSANDDATA*)(SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddata->origcons))));
    1113 }
    1114 }
    1115 else
    1116 assert(consanddata->origcons == NULL);
    1117 }
    1118 else
    1119 {
    1120 assert(consanddata->nuses == 0);
    1121 assert(consanddata->nnewvars == 0);
    1122 assert(consanddata->snewvars == 0);
    1123 assert(consanddata->newvars == NULL);
    1124
    1125 consanddata->istransformed = FALSE;
    1126
    1127 if( consanddata->noriguses > 0 )
    1128 {
    1129 assert(consanddata->origcons != NULL);
    1130 assert(consanddata->nvars > 0);
    1131 assert(consanddata->svars > 0);
    1132 assert(consanddata->vars != NULL);
    1133 assert(consanddata->isoriginal);
    1134
    1135 /* check that the hash map and tabkle are still having all information */
    1136 if( conshdlrdata->inithashmapandtable )
    1137 {
    1138 assert(conshdlrdata->hashmap != NULL);
    1139 assert(conshdlrdata->hashtable != NULL);
    1140 assert(SCIPgetResultantAnd(scip, consanddata->origcons) != NULL);
    1141 assert(SCIPhashtableExists(conshdlrdata->hashtable, (void*)consanddata));
    1142 assert(consanddata == (CONSANDDATA*)(SCIPhashtableRetrieve(conshdlrdata->hashtable, (void*)consanddata)));
    1143 assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddata->origcons)));
    1144 assert(consanddata == (CONSANDDATA*)(SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddata->origcons))));
    1145 }
    1146 }
    1147 }
    1148
    1149 return SCIP_OKAY;
    1150}
    1151
    1152
    1153
    1154/** creates a pseudo boolean constraint data */
    1155static
    1157 SCIP*const scip, /**< SCIP data structure */
    1158 SCIP_CONSHDLR*const conshdlr, /**< pseudoboolean constraint handler */
    1159 SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
    1160 SCIP_CONS*const lincons, /**< linear constraint with artificial and-resultants representing this pseudoboolean constraint */
    1161 SCIP_LINEARCONSTYPE const linconstype, /**< type of linear constraint */
    1162 SCIP_CONS**const andconss, /**< array of and-constraints which occur in this pseudoboolean constraint */
    1163 SCIP_Real*const andcoefs, /**< coefficients of and-constraints */
    1164 SCIP_Bool*const andnegs, /**< negation status of and-constraints (or NULL, if no negated resultants) */
    1165 int const nandconss, /**< number of and-constraints */
    1166 SCIP_VAR*const indvar, /**< indicator variable if it's a soft constraint, or NULL */
    1167 SCIP_Real const weight, /**< weight of the soft constraint, if it is one */
    1168 SCIP_Bool const issoftcons, /**< is this a soft constraint */
    1169 SCIP_Real lhs, /**< left hand side of row */
    1170 SCIP_Real rhs, /**< right hand side of row */
    1171 SCIP_Bool check, /**< is the new constraint a check constraint? */
    1172 SCIP_Bool transforming /**< are we called by CONSTRANS */
    1173 )
    1174{
    1175 SCIP_Bool transformed;
    1176 int nvars;
    1177
    1178 assert(scip != NULL);
    1179 assert(conshdlr != NULL);
    1180 assert(consdata != NULL);
    1181 assert(lincons != NULL && linconstype > SCIP_LINEARCONSTYPE_INVALIDCONS);
    1182 assert(andconss != NULL || nandconss == 0);
    1183 assert(andcoefs != NULL || nandconss == 0);
    1184 assert(!issoftcons || (!SCIPisZero(scip, weight) && indvar != NULL));
    1185
    1186 /* adjust right hand side */
    1187 if( SCIPisInfinity(scip, rhs) )
    1188 rhs = SCIPinfinity(scip);
    1189 else if( SCIPisInfinity(scip, -rhs) )
    1190 rhs = -SCIPinfinity(scip);
    1191
    1192 /* adjust left hand side */
    1193 if( SCIPisInfinity(scip, -lhs) )
    1194 lhs = -SCIPinfinity(scip);
    1195 else if( SCIPisInfinity(scip, lhs) )
    1196 lhs = SCIPinfinity(scip);
    1197
    1198 /* check left and right side */
    1199 if( SCIPisGT(scip, lhs, rhs) )
    1200 {
    1201 SCIPerrorMessage("left hand side of pseudo boolean constraint greater than right hand side\n");
    1202 SCIPerrorMessage(" -> lhs=%g, rhs=%g\n", lhs, rhs);
    1203 return SCIP_INVALIDDATA;
    1204 }
    1205
    1206 transformed = SCIPisTransformed(scip);
    1207
    1208 /* allocate memory for the constraint data */
    1209 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
    1210
    1211 /* initialize the weights for soft constraints */
    1212 (*consdata)->issoftcons = issoftcons;
    1213 if( issoftcons )
    1214 {
    1215 (*consdata)->weight = weight;
    1216 if( transformed )
    1217 {
    1218 SCIP_CALL( SCIPgetTransformedVar(scip, indvar, &((*consdata)->indvar)) );
    1219 }
    1220 else
    1221 (*consdata)->indvar = indvar;
    1222 }
    1223 else
    1224 (*consdata)->indvar = NULL;
    1225
    1226 /* copy linear constraint */
    1227 (*consdata)->lincons = lincons;
    1228 (*consdata)->linconstype = linconstype;
    1229
    1230 /* get transformed linear constraint and capture it if necessary */
    1231 if( transforming )
    1232 {
    1233 /* do not capture the and constraint when scip is in transformed mode; this automatically happens in
    1234 * SCIPtransformCons()
    1235 */
    1236 SCIP_CALL( SCIPtransformCons(scip, (*consdata)->lincons, &((*consdata)->lincons)) );
    1237 assert((*consdata)->lincons != NULL);
    1238 }
    1239
    1240 if( transforming || transformed )
    1241 {
    1242 assert(SCIPconsIsTransformed((*consdata)->lincons));
    1243
    1244 /* we want to check all necessary transformed linear constraints */
    1245 SCIP_CALL( SCIPsetConsChecked(scip, (*consdata)->lincons, check) );
    1246 }
    1247
    1248 /* get number of non-linear terms in pseudoboolean constraint */
    1249 SCIP_CALL( getLinearConsNVars(scip, (*consdata)->lincons, (*consdata)->linconstype, &nvars) );
    1250 (*consdata)->nlinvars = nvars - nandconss;
    1251
    1252 /* copy and-constraints */
    1253 if( nandconss > 0 )
    1254 {
    1255 SCIP_CONSHDLRDATA* conshdlrdata;
    1256 SCIP_VAR** andress;
    1257 int c;
    1258
    1259 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*consdata)->consanddatas), nandconss) );
    1260 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &((*consdata)->andcoefs), andcoefs, nandconss) );
    1261 if( andnegs != NULL )
    1262 {
    1263 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &((*consdata)->andnegs), andnegs, nandconss) );
    1264 }
    1265 else
    1266 {
    1267 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &((*consdata)->andnegs), nandconss) );
    1268 }
    1269 (*consdata)->nconsanddatas = nandconss;
    1270 (*consdata)->sconsanddatas = nandconss;
    1271
    1272 /* allocate temporary memory */
    1273 SCIP_CALL( SCIPallocBufferArray(scip, &andress, nandconss) );
    1274
    1275 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    1276 assert(conshdlrdata != NULL);
    1277 assert(conshdlrdata->hashmap != NULL);
    1278
    1279 /* get all and-resultants for sorting */
    1280 for( c = nandconss - 1; c >= 0; --c )
    1281 {
    1282 assert(andconss[c] != NULL);
    1283
    1284 andress[c] = SCIPgetResultantAnd(scip, andconss[c]);
    1285 assert(andress[c] != NULL);
    1286
    1287 (*consdata)->consanddatas[c] = (CONSANDDATA*) SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)andress[c]);
    1288 assert((*consdata)->consanddatas[c] != NULL);
    1289 assert((*consdata)->consanddatas[c]->origcons == andconss[c] || (*consdata)->consanddatas[c]->cons == andconss[c]);
    1290
    1291 if( transforming )
    1292 {
    1293 /* if we perform a new transformation, we need to capture the transformed constraint */
    1294 if( (*consdata)->consanddatas[c]->origcons != NULL && (*consdata)->consanddatas[c]->cons == NULL )
    1295 {
    1296 SCIP_VAR** vars;
    1297 int ncvars;
    1298 int v;
    1299
    1300 /* do not capture the and constraint when scip is in transformed mode; this automatically happens in
    1301 * SCIPtransformCons()
    1302 */
    1303 SCIP_CALL( SCIPtransformCons(scip, (*consdata)->consanddatas[c]->origcons, &((*consdata)->consanddatas[c]->cons)) );
    1304 assert((*consdata)->consanddatas[c]->cons != NULL);
    1305 assert((*consdata)->consanddatas[c]->newvars == NULL);
    1306 assert((*consdata)->consanddatas[c]->isoriginal);
    1307
    1308 (*consdata)->consanddatas[c]->istransformed = TRUE;
    1309
    1310 /* lock upgrade to keep control */
    1311 SCIPconsAddUpgradeLocks((*consdata)->consanddatas[c]->cons, +1);
    1312
    1313 vars = (*consdata)->consanddatas[c]->vars;
    1314 ncvars = (*consdata)->consanddatas[c]->nvars;
    1315 assert(vars != NULL || ncvars == 0);
    1316
    1317 /* get transformed variables */
    1318 SCIP_CALL( SCIPgetTransformedVars(scip, ncvars, vars, vars) );
    1319
    1320 /* resort variables in transformed problem, because the order might change while tranforming */
    1321 SCIPsortPtr((void**)vars, SCIPvarComp, ncvars);
    1322
    1323 /* capture all transformed variables */
    1324 for( v = ncvars - 1; v >= 0; --v )
    1325 {
    1326 SCIP_CALL( SCIPcaptureVar(scip, vars[v]) ); /*lint !e613*/
    1327 }
    1328 }
    1329 else if( (*consdata)->consanddatas[c]->cons != NULL )
    1330 assert((*consdata)->consanddatas[c]->istransformed);
    1331
    1332 ++((*consdata)->consanddatas[c]->nuses);
    1333 }
    1334 else if( transformed )
    1335 {
    1336 assert((*consdata)->consanddatas[c]->cons == andconss[c]);
    1337 assert(SCIPconsIsTransformed(andconss[c]));
    1338 assert((*consdata)->consanddatas[c]->istransformed);
    1339 }
    1340 }
    1341
    1342 /* sort and-constraints after problem indices of corresponding and-resultants */
    1343 SCIPsortPtrPtrRealBool((void**)andress, (void**)((*consdata)->consanddatas), (*consdata)->andcoefs, (*consdata)->andnegs, resvarComp, nandconss);
    1344
    1345 /* free temporary memory */
    1346 SCIPfreeBufferArray(scip, &andress);
    1347 }
    1348 else
    1349 {
    1350 (*consdata)->consanddatas = NULL;
    1351 (*consdata)->andcoefs = NULL;
    1352 (*consdata)->andnegs = NULL;
    1353 (*consdata)->nconsanddatas = 0;
    1354 (*consdata)->sconsanddatas = 0;
    1355 }
    1356
    1357 /* copy left and right hand side */
    1358 (*consdata)->lhs = lhs;
    1359 (*consdata)->rhs = rhs;
    1360
    1361 (*consdata)->changed = TRUE;
    1362 (*consdata)->propagated = FALSE;
    1363 (*consdata)->presolved = FALSE;
    1364 (*consdata)->cliquesadded = FALSE;
    1365 (*consdata)->upgradetried = TRUE;
    1366
    1367 /* count number of used consanddata objects in original problem */
    1369 {
    1370 SCIP_CONSHDLRDATA* conshdlrdata;
    1371 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    1372 assert(conshdlrdata != NULL);
    1373
    1374 conshdlrdata->noriguses += (*consdata)->nconsanddatas;
    1375 }
    1376
    1377 return SCIP_OKAY;
    1378}
    1379
    1380/** free a pseudo boolean constraint data */
    1381static
    1383 SCIP*const scip, /**< SCIP data structure */
    1384 SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
    1385 SCIP_Bool isorig, /**< are we freeing an original constraint? */
    1386 SCIP_CONSHDLRDATA* conshdlrdata /**< constraint handler data */
    1387 )
    1388{
    1389 CONSANDDATA** consanddatas;
    1390 int nconsanddatas;
    1391 int c;
    1392
    1393 assert(scip != NULL);
    1394 assert(consdata != NULL);
    1395 assert(*consdata != NULL);
    1396 assert((*consdata)->consanddatas != NULL || (*consdata)->nconsanddatas == 0);
    1397 assert(conshdlrdata != NULL);
    1398
    1399 /* release linear constraint */
    1400 if( (*consdata)->lincons != NULL )
    1401 {
    1402 SCIP_CALL( SCIPreleaseCons(scip, &((*consdata)->lincons)) );
    1403 }
    1404
    1405 nconsanddatas = (*consdata)->nconsanddatas;
    1406 consanddatas = (*consdata)->consanddatas;
    1407
    1408 /* count down uses and if necessary release constraints and delete data from hashtable and -map */
    1409 for( c = nconsanddatas - 1; c >= 0; --c )
    1410 {
    1411 assert((consanddatas[c]->origcons == NULL) == (consanddatas[c]->noriguses == 0));
    1412 assert((consanddatas[c]->cons == NULL) == (consanddatas[c]->nuses == 0));
    1413 assert(consanddatas[c]->nuses >= 0);
    1414 assert(consanddatas[c]->noriguses >= 0);
    1415 assert(isorig ? consanddatas[c]->cons == NULL : TRUE);
    1416
    1417 /* are we deleteing a transformed constraint */
    1418 if( !isorig && consanddatas[c]->cons != NULL )
    1419 {
    1420 assert(!SCIPconsIsOriginal(consanddatas[c]->cons));
    1421
    1422 --(consanddatas[c]->nuses);
    1423
    1424 /* if the consanddata is not used anymore, release the constraint and clear the hashmap- and table */
    1425 if( consanddatas[c]->nuses == 0 )
    1426 {
    1427 if( conshdlrdata->inithashmapandtable )
    1428 {
    1429 assert(conshdlrdata->hashmap != NULL);
    1430 assert(conshdlrdata->hashtable != NULL);
    1431
    1432 /* remove consanddata from hashtable, if it existed only in transformed space */
    1433 if( consanddatas[c]->origcons == NULL )
    1434 {
    1435 assert(SCIPhashtableExists(conshdlrdata->hashtable, (void*)consanddatas[c]));
    1436 SCIP_CALL( SCIPhashtableRemove(conshdlrdata->hashtable, (void*)consanddatas[c]) );
    1437 }
    1438 assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddatas[c]->cons)));
    1439 SCIP_CALL( SCIPhashmapRemove(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddatas[c]->cons)) );
    1440 }
    1441
    1442 /* unlock upgrade to provide control */
    1443 SCIPconsAddUpgradeLocks(consanddatas[c]->cons, -1);
    1444
    1445 /* release and-constraint */
    1446 SCIP_CALL( SCIPreleaseCons(scip, &consanddatas[c]->cons) );
    1447
    1448 /* if the consanddata object was only used in transformed space, delete the memory block */
    1449 if( consanddatas[c]->origcons == NULL )
    1450 {
    1451 int d;
    1452
    1453 assert(conshdlrdata->nallconsanddatas > 0);
    1454
    1455 for( d = conshdlrdata->nallconsanddatas - 1; d >= 0; --d )
    1456 {
    1457 if( conshdlrdata->allconsanddatas[d] == consanddatas[c] )
    1458 {
    1459 --conshdlrdata->nallconsanddatas;
    1460
    1461 SCIPfreeBlockMemory(scip, &(conshdlrdata->allconsanddatas[d])); /*lint !e866*/
    1462
    1463 conshdlrdata->allconsanddatas[d] = conshdlrdata->allconsanddatas[conshdlrdata->nallconsanddatas];
    1464 break;
    1465 }
    1466 }
    1467 assert(d >= 0);
    1468 continue;
    1469 }
    1470 }
    1471 }
    1472 /* are we deleteing an original constraint */
    1473 else if( isorig && consanddatas[c]->origcons != NULL )
    1474 {
    1475 assert(SCIPconsIsOriginal(consanddatas[c]->origcons));
    1476 assert(consanddatas[c]->nuses == 0);
    1477 assert(consanddatas[c]->nnewvars == 0);
    1478 assert(consanddatas[c]->snewvars == 0);
    1479 assert(consanddatas[c]->newvars == NULL);
    1480
    1481 --(consanddatas[c]->noriguses);
    1482
    1483 /* if the consanddata is not used anymore, release the constraint and clear the hashmap- and table */
    1484 if( consanddatas[c]->noriguses == 0 )
    1485 {
    1486 int d;
    1487
    1488 if( conshdlrdata->inithashmapandtable )
    1489 {
    1490 assert(conshdlrdata->hashmap != NULL);
    1491 assert(conshdlrdata->hashtable != NULL);
    1492
    1493 assert(SCIPhashtableExists(conshdlrdata->hashtable, (void*)consanddatas[c]));
    1494 SCIP_CALL( SCIPhashtableRemove(conshdlrdata->hashtable, (void*)consanddatas[c]) );
    1495
    1496 assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddatas[c]->origcons)));
    1497 SCIP_CALL( SCIPhashmapRemove(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddatas[c]->origcons)) );
    1498 }
    1499
    1500 if( consanddatas[c]->vars != NULL )
    1501 {
    1502 assert(consanddatas[c]->nvars > 0);
    1503 assert(consanddatas[c]->svars > 0);
    1504 assert(consanddatas[c]->svars >= consanddatas[c]->nvars);
    1505
    1506 SCIPfreeBlockMemoryArrayNull(scip, &(consanddatas[c]->vars), consanddatas[c]->svars);
    1507 consanddatas[c]->nvars = 0;
    1508 consanddatas[c]->svars = 0;
    1509 }
    1510 else
    1511 {
    1512 assert(consanddatas[c]->nvars == 0);
    1513 assert(consanddatas[c]->svars == 0);
    1514 }
    1515
    1516 /* release original and-constraint */
    1517 SCIP_CALL( SCIPreleaseCons(scip, &consanddatas[c]->origcons) );
    1518 assert(consanddatas[c]->origcons == NULL);
    1519
    1520 /* delete consanddata object */
    1521 assert(conshdlrdata->nallconsanddatas > 0);
    1522 for( d = conshdlrdata->nallconsanddatas - 1; d >= 0; --d )
    1523 {
    1524 if( conshdlrdata->allconsanddatas[d] == consanddatas[c] )
    1525 {
    1526 --conshdlrdata->nallconsanddatas;
    1527
    1528 SCIPfreeBlockMemory(scip, &(conshdlrdata->allconsanddatas[d])); /*lint !e866*/
    1529
    1530 conshdlrdata->allconsanddatas[d] = conshdlrdata->allconsanddatas[conshdlrdata->nallconsanddatas];
    1531 break;
    1532 }
    1533 }
    1534 assert(d >= 0);
    1535
    1536 continue;
    1537 }
    1538 }
    1539 else
    1540 {
    1541 assert(!consanddatas[c]->istransformed);
    1542 assert(consanddatas[c]->cons == NULL);
    1543 }
    1544
    1545 /* clear and remove capture of transformed consanddata */
    1546 if( consanddatas[c]->nuses == 0 && consanddatas[c]->istransformed )
    1547 {
    1548 SCIP_CALL( transformToOrig(scip, consanddatas[c], conshdlrdata) );
    1549 }
    1550#ifndef NDEBUG
    1551 else if( consanddatas[c]->nuses == 0 )
    1552 {
    1553 SCIP_VAR** tmpvars;
    1554 int ntmpvars;
    1555 int v;
    1556
    1557 assert(consanddatas[c]->nnewvars == 0);
    1558 assert(consanddatas[c]->snewvars == 0);
    1559 assert(consanddatas[c]->newvars == NULL);
    1560
    1561 tmpvars = consanddatas[c]->vars;
    1562 ntmpvars = consanddatas[c]->nvars;
    1563
    1564 /* release all variables */
    1565 for( v = ntmpvars - 1; v >= 0; --v )
    1566 {
    1567 assert(tmpvars[v] != NULL);
    1568 assert(SCIPvarIsOriginal(tmpvars[v]));
    1569 }
    1570 }
    1571#endif
    1572
    1573 /* restore original data */
    1574 if( !consanddatas[c]->istransformed && consanddatas[c]->noriguses > 0 )
    1575 {
    1576 assert(consanddatas[c]->origcons != NULL);
    1577 assert(consanddatas[c]->nuses == 0);
    1578 assert(consanddatas[c]->nnewvars == 0);
    1579 assert(consanddatas[c]->snewvars == 0);
    1580 assert(consanddatas[c]->newvars == NULL);
    1581 assert(consanddatas[c]->nvars > 0);
    1582 assert(consanddatas[c]->svars > 0);
    1583 assert(consanddatas[c]->svars >= consanddatas[c]->nvars);
    1584 assert(consanddatas[c]->vars != NULL);
    1585 assert(consanddatas[c]->isoriginal);
    1586
    1587 assert(consanddatas[c]->nvars == SCIPgetNVarsAnd(scip, consanddatas[c]->origcons));
    1588 assert(SCIPgetVarsAnd(scip, consanddatas[c]->origcons) != NULL);
    1589
    1590 /* check that the hash map and tabkle are still having all information */
    1591 if( conshdlrdata->inithashmapandtable )
    1592 {
    1593 assert(conshdlrdata->hashmap != NULL);
    1594 assert(conshdlrdata->hashtable != NULL);
    1595 assert(SCIPgetResultantAnd(scip, consanddatas[c]->origcons) != NULL);
    1596 assert(SCIPhashtableExists(conshdlrdata->hashtable, (void*)consanddatas[c]));
    1597 assert(consanddatas[c] == (CONSANDDATA*)(SCIPhashtableRetrieve(conshdlrdata->hashtable, (void*)consanddatas[c])));
    1598 assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddatas[c]->origcons)));
    1599 assert(consanddatas[c] == (CONSANDDATA*)(SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddatas[c]->origcons))));
    1600 }
    1601 }
    1602 }
    1603
    1604 /* free array of and-constraints */
    1605 SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->andnegs), (*consdata)->sconsanddatas);
    1606 SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->andcoefs), (*consdata)->sconsanddatas);
    1607 SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->consanddatas), (*consdata)->sconsanddatas);
    1608
    1609 SCIPfreeBlockMemory(scip, consdata);
    1610
    1611 return SCIP_OKAY;
    1612}
    1613
    1614/** check the locks of an AND resultant and removes it from all global structures if the resultant is not locked anymore */
    1615static
    1617 SCIP*const scip, /**< SCIP data structure */
    1618 SCIP_VAR* res /**< resultant of AND constraint */
    1619 )
    1620{
    1621 assert(scip != NULL);
    1622 assert(res != NULL);
    1623
    1624 /* the resultant has no locks left and might be dual fixed now, we need to delete all its cliques */
    1627 {
    1629 }
    1630
    1631 return SCIP_OKAY;
    1632}
    1633
    1634/** installs rounding locks for the given and-constraint associated with given coefficient */
    1635static
    1637 SCIP*const scip, /**< SCIP data structure */
    1638 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    1639 CONSANDDATA*const consanddata, /**< CONSANDDATA object for which we want to add the locks */
    1640 SCIP_Real const coef, /**< coefficient which led to old locks */
    1641 SCIP_Real const lhs, /**< left hand side */
    1642 SCIP_Real const rhs /**< right hand side */
    1643 )
    1644{
    1645 SCIP_VAR** vars;
    1646 int nvars;
    1647 SCIP_VAR* res;
    1648 SCIP_Bool haslhs;
    1649 SCIP_Bool hasrhs;
    1650 int v;
    1651
    1652 assert(scip != NULL);
    1653 assert(cons != NULL);
    1655 assert(consanddata != NULL);
    1656 assert(!SCIPisInfinity(scip, coef) && !SCIPisInfinity(scip, -coef));
    1657 assert(!SCIPisInfinity(scip, lhs));
    1658 assert(!SCIPisInfinity(scip, -rhs));
    1659 assert(SCIPisLE(scip, lhs, rhs));
    1660
    1661 /* choose correct variable array to add locks for, we only add locks for now valid variables */
    1662 if( consanddata->nnewvars > 0 )
    1663 {
    1664 vars = consanddata->newvars;
    1665 nvars = consanddata->nnewvars;
    1666 }
    1667 else
    1668 {
    1669 vars = consanddata->vars;
    1670 nvars = consanddata->nvars;
    1671 }
    1672 assert(vars != NULL || nvars == 0);
    1673
    1674 res = SCIPgetResultantAnd(scip, consanddata->cons);
    1675 assert(res != NULL);
    1676
    1677 /* check which sites are infinity */
    1678 haslhs = !SCIPisInfinity(scip, -lhs);
    1679 hasrhs = !SCIPisInfinity(scip, rhs);
    1680
    1681 if( SCIPconsIsLocked(cons) )
    1682 {
    1683 /* locking variables */
    1684 if( SCIPisPositive(scip, coef) )
    1685 {
    1686 for( v = nvars - 1; v >= 0; --v )
    1687 {
    1688 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, haslhs, hasrhs) );
    1689 }
    1690 }
    1691 else
    1692 {
    1693 for( v = nvars - 1; v >= 0; --v )
    1694 {
    1695 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, hasrhs, haslhs) );
    1696 }
    1697 }
    1698 SCIP_CALL( SCIPlockVarCons(scip, res, cons, TRUE, TRUE) );
    1699 }
    1700
    1701 return SCIP_OKAY;
    1702}
    1703
    1704/** removes rounding locks for the given and-constraint associated with given coefficient */
    1705static
    1707 SCIP*const scip, /**< SCIP data structure */
    1708 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    1709 CONSANDDATA*const consanddata, /**< CONSANDDATA object for which we want to delete the locks */
    1710 SCIP_Real const coef, /**< coefficient which led to old locks */
    1711 SCIP_Real const lhs, /**< left hand side which led to old locks */
    1712 SCIP_Real const rhs /**< right hand side which led to old locks */
    1713 )
    1714{
    1715 SCIP_VAR** vars;
    1716 int nvars;
    1717 SCIP_VAR* res;
    1718 SCIP_Bool haslhs;
    1719 SCIP_Bool hasrhs;
    1720 int v;
    1721
    1722 assert(scip != NULL);
    1723 assert(cons != NULL);
    1725 assert(consanddata != NULL);
    1726 assert(!SCIPisInfinity(scip, coef) && !SCIPisInfinity(scip, -coef));
    1727 assert(!SCIPisInfinity(scip, lhs));
    1728 assert(!SCIPisInfinity(scip, -rhs));
    1729 assert(SCIPisLE(scip, lhs, rhs));
    1730
    1731 vars = consanddata->vars;
    1732 nvars = consanddata->nvars;
    1733 assert(vars != NULL || nvars == 0);
    1734
    1735 if( consanddata->cons != NULL )
    1736 res = SCIPgetResultantAnd(scip, consanddata->cons);
    1737 else
    1738 res = NULL;
    1739 assert(res != NULL || nvars == 0);
    1740
    1741 /* check which sites are infinity */
    1742 haslhs = !SCIPisInfinity(scip, -lhs);
    1743 hasrhs = !SCIPisInfinity(scip, rhs);
    1744
    1745 if( SCIPconsIsLocked(cons) )
    1746 {
    1747 /* unlock variables */
    1748 if( SCIPisPositive(scip, coef) )
    1749 {
    1750 for( v = nvars - 1; v >= 0; --v )
    1751 {
    1752 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, haslhs, hasrhs) );
    1753 }
    1754 }
    1755 else
    1756 {
    1757 for( v = nvars - 1; v >= 0; --v )
    1758 {
    1759 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, hasrhs, haslhs) );
    1760 }
    1761 }
    1762
    1763 if( res != NULL )
    1764 {
    1765 SCIP_CALL( SCIPunlockVarCons(scip, res, cons, TRUE, TRUE) );
    1766
    1768 }
    1769 }
    1770
    1771 return SCIP_OKAY;
    1772}
    1773
    1774/** prints pseudoboolean constraint in CIP format to file stream */
    1775static
    1777 SCIP*const scip, /**< SCIP data structure */
    1778 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    1779 FILE*const file /**< output file (or NULL for standard output) */
    1780 )
    1781{
    1782 SCIP_CONSHDLR* conshdlr;
    1783 SCIP_CONSHDLRDATA* conshdlrdata;
    1784 SCIP_CONSDATA* consdata;
    1785 SCIP_VAR*** monomialvars;
    1786 SCIP_VAR** vars;
    1787 SCIP_Real* coefs;
    1788 SCIP_Real* monomialcoefs;
    1789 SCIP_Real lhs;
    1790 SCIP_Real rhs;
    1791 int* monomialnvars;
    1792 int nvars;
    1793 int nmonomials;
    1794 int v;
    1795
    1796 assert(scip != NULL);
    1797 assert(cons != NULL);
    1798
    1799 consdata = SCIPconsGetData(cons);
    1800 assert(consdata != NULL);
    1801 assert(consdata->lincons != NULL);
    1802
    1803 /* gets number of variables in linear constraint */
    1804 SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
    1805
    1806 /* every variable in the linear constraint is either a linear variable or a term variable
    1807 * but there can be additional fixed or negation-paired and-resultants with relevant and-constraints
    1808 * whose values are already resolved in the linear constraint
    1809 */
    1810 assert(consdata->nlinvars + consdata->nconsanddatas >= nvars);
    1811
    1812 /* initialize buffers for storing the terms and coefficients */
    1813 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    1814 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
    1815 SCIP_CALL( SCIPallocBufferArray(scip, &monomialvars, nvars) );
    1816 SCIP_CALL( SCIPallocBufferArray(scip, &monomialcoefs, nvars) );
    1817 SCIP_CALL( SCIPallocBufferArray(scip, &monomialnvars, nvars) );
    1818
    1819 /* get sides of linear constraint */
    1820 SCIP_CALL( getLinearConsSides(scip, consdata->lincons, consdata->linconstype, &lhs, &rhs) );
    1821 assert(!SCIPisInfinity(scip, lhs));
    1822 assert(!SCIPisInfinity(scip, -rhs));
    1823 assert(SCIPisLE(scip, lhs, rhs));
    1824
    1825 /* get variables and coefficient of linear constraint */
    1826 SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) );
    1827 assert(coefs != NULL || nvars == 0);
    1828
    1829 /* get and-data hashmap */
    1830 conshdlr = SCIPconsGetHdlr(cons);
    1831 assert(conshdlr != NULL);
    1832 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    1833 assert(conshdlrdata != NULL);
    1834 assert(conshdlrdata->hashmap != NULL);
    1835 nmonomials = 0;
    1836
    1837 /* collect all terms */
    1838 for( v = 0; v < nvars; ++v )
    1839 {
    1840 CONSANDDATA* consanddata = NULL;
    1841 SCIP_VAR** andvars = NULL;
    1842 SCIP_VAR* var = vars[v];
    1843 int nandvars = 0;
    1844
    1845 assert(SCIPvarIsBinary(var));
    1846
    1847 /* find and-constraint to standard or negated and-resultant */
    1848 do
    1849 {
    1850 /* @todo: drop indicator variable */
    1851 assert(!consdata->issoftcons || var != consdata->indvar);
    1852 consanddata = (CONSANDDATA*)SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)var);
    1853
    1854 if( consanddata != NULL )
    1855 {
    1856 SCIP_CONS* andcons = SCIPconsIsOriginal(cons) ? consanddata->origcons : consanddata->cons;
    1857
    1858 andvars = SCIPgetVarsAnd(scip, andcons);
    1859 nandvars = SCIPgetNVarsAnd(scip, andcons);
    1860
    1861 break;
    1862 }
    1863
    1864 var = var == vars[v] ? SCIPvarGetNegatedVar(var) : vars[v];
    1865 }
    1866 while( var != vars[v] );
    1867
    1868 if( consanddata == NULL )
    1869 {
    1870 assert(var != NULL);
    1871 assert(var == vars[v]);
    1872 monomialvars[nmonomials] = vars + v;
    1873 monomialnvars[nmonomials] = 1;
    1874 }
    1875 else
    1876 {
    1877 SCIP_Bool fixed = nandvars == 0;
    1878 SCIP_Bool negated = var != vars[v];
    1879
    1880 if( fixed != negated )
    1881 {
    1882 if( !SCIPisInfinity(scip, -lhs) )
    1883 lhs -= coefs[v];
    1884
    1885 if( !SCIPisInfinity(scip, rhs) )
    1886 rhs -= coefs[v];
    1887 }
    1888
    1889 if( fixed )
    1890 continue;
    1891
    1892 if( negated )
    1893 coefs[v] *= -1.0;
    1894
    1895 assert(andvars != NULL);
    1896 monomialvars[nmonomials] = andvars;
    1897 assert(nandvars >= 1);
    1898 monomialnvars[nmonomials] = nandvars;
    1899 }
    1900
    1901 assert(!SCIPisZero(scip, coefs[v]));
    1902 monomialcoefs[nmonomials] = coefs[v];
    1903 ++nmonomials;
    1904 }
    1905
    1906 /* print left side */
    1907 if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && lhs != rhs ) /*lint !e777*/
    1908 SCIPinfoMessage(scip, file, "%.15g <= ", lhs);
    1909
    1910 /* print pseudoboolean polynomial */
    1911 SCIP_CALL( SCIPwriteVarsPolynomial(scip, file, monomialvars, NULL, monomialcoefs, monomialnvars, nmonomials, TRUE) );
    1912
    1913 /* print right side */
    1914 if( lhs == rhs ) /*lint !e777*/
    1915 SCIPinfoMessage(scip, file, " == %.15g", rhs);
    1916 else if( !SCIPisInfinity(scip, rhs) )
    1917 SCIPinfoMessage(scip, file, " <= %.15g", rhs);
    1918 else if( !SCIPisInfinity(scip, -lhs) )
    1919 SCIPinfoMessage(scip, file, " >= %.15g", lhs);
    1920 else
    1921 SCIPinfoMessage(scip, file, " [free]");
    1922
    1923 /* free buffers for storing the terms and coefficients */
    1924 SCIPfreeBufferArray(scip, &monomialnvars);
    1925 SCIPfreeBufferArray(scip, &monomialcoefs);
    1926 SCIPfreeBufferArray(scip, &monomialvars);
    1927 SCIPfreeBufferArray(scip, &coefs);
    1928 SCIPfreeBufferArray(scip, &vars);
    1929
    1930 /* print indicator variable if soft constraint */
    1931 if( consdata->issoftcons )
    1932 {
    1933 SCIPinfoMessage(scip, file, " (indvar = ");
    1934 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->indvar, TRUE) );
    1935 SCIPinfoMessage(scip, file, ")");
    1936 assert(consdata->weight == SCIPvarGetObj(consdata->indvar)); /*lint !e777*/
    1937 }
    1938
    1939 return SCIP_OKAY;
    1940}
    1941
    1942/** creates and/or adds the resultant for a given term */
    1943static
    1945 SCIP*const scip, /**< SCIP data structure */
    1946 SCIP_CONSHDLR*const conshdlr, /**< pseudoboolean constraint handler */
    1947 SCIP_VAR**const vars, /**< array of variables to get and-constraints for */
    1948 int const nvars, /**< number of variables to get and-constraints for */
    1949 SCIP_Bool const initial, /**< should the LP relaxation of constraint be in the initial LP?
    1950 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    1951 SCIP_Bool const enforce, /**< should the constraint be enforced during node processing?
    1952 * TRUE for model constraints, FALSE for additional, redundant
    1953 * constraints. */
    1954 SCIP_Bool const check, /**< should the constraint be checked for feasibility?
    1955 * TRUE for model constraints, FALSE for additional, redundant
    1956 * constraints. */
    1957 SCIP_Bool const local, /**< is constraint only valid locally?
    1958 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching
    1959 * constraints. */
    1960 SCIP_Bool const modifiable, /**< is constraint modifiable (subject to column generation)?
    1961 * Usually set to FALSE. In column generation applications, set to TRUE
    1962 * if pricing adds coefficients to this constraint. */
    1963 SCIP_Bool const dynamic, /**< is constraint subject to aging?
    1964 * Usually set to FALSE. Set to TRUE for own cuts which
    1965 * are seperated as constraints. */
    1966 SCIP_Bool const stickingatnode, /**< should the constraint always be kept at the node where it was added, even
    1967 * if it may be moved to a more global node?
    1968 * Usually set to FALSE. Set to TRUE to for constraints that represent
    1969 * node data. */
    1970 SCIP_CONS**const andcons /**< pointer to store and-constraint */
    1971 )
    1972{
    1973 CONSANDDATA* newdata;
    1974 CONSANDDATA* tmpdata;
    1975 SCIP_CONSHDLRDATA* conshdlrdata;
    1977 SCIP_Bool propagate;
    1978 SCIP_Bool removable;
    1979 SCIP_Bool transformed;
    1980 char name[SCIP_MAXSTRLEN];
    1981 int v;
    1982
    1983 assert(scip != NULL);
    1984 assert(conshdlr != NULL);
    1985 assert(vars != NULL);
    1986 assert(nvars >= 1);
    1987 assert(andcons != NULL);
    1988
    1989 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    1990 assert(conshdlrdata != NULL);
    1991 assert(conshdlrdata->hashtable != NULL);
    1992
    1993 transformed = SCIPisTransformed(scip);
    1994
    1995 /* allocate memory for a possible new consanddata object */
    1996 SCIP_CALL( SCIPallocBlockMemory(scip, &newdata) );
    1997 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(newdata->vars), vars, nvars) );
    1998 newdata->nvars = nvars;
    1999 newdata->svars = nvars;
    2000 newdata->newvars = NULL;
    2001 newdata->nnewvars = 0;
    2002 newdata->snewvars = 0;
    2003 newdata->noriguses = 0;
    2004 newdata->nuses = 0;
    2005 newdata->istransformed = transformed;
    2006 newdata->isoriginal = !transformed;
    2007 newdata->cons = NULL;
    2008 newdata->origcons = NULL;
    2009
    2010 /* sort variables */
    2011 SCIPsortPtr((void**)(newdata->vars), SCIPvarComp, nvars);
    2012
    2013 /* get constraint from current hash table with same variables as cons0 */
    2014 tmpdata = (CONSANDDATA*)(SCIPhashtableRetrieve(conshdlrdata->hashtable, (void*)newdata));
    2015
    2016 /* if there is already the same and constraint created use this resultant */
    2017 if( tmpdata != NULL )
    2018 {
    2019#ifndef NDEBUG
    2020 SCIP_VAR* res;
    2021#endif
    2022 if( transformed )
    2023 {
    2024 assert(tmpdata->cons != NULL);
    2025 *andcons = tmpdata->cons;
    2026
    2027 assert(tmpdata->nuses > 0);
    2028 /* increase usage of data object */
    2029 ++(tmpdata->nuses);
    2030 }
    2031 else
    2032 {
    2033 assert(tmpdata->origcons != NULL);
    2034 *andcons = tmpdata->origcons;
    2035
    2036 assert(tmpdata->noriguses > 0);
    2037 /* increase usage of data object */
    2038 ++(tmpdata->noriguses);
    2039 }
    2040 assert(*andcons != NULL);
    2041
    2042#ifndef NDEBUG
    2043 res = SCIPgetResultantAnd(scip, *andcons);
    2044 assert(res != NULL);
    2045
    2046 /* check that we already have added this resultant to and-constraint entry */
    2047 assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)res));
    2048#endif
    2049 }
    2050 else
    2051 {
    2052 /* create new and-constraint */
    2053 SCIP_CONS* newcons;
    2054 SCIP_VAR* resultant;
    2056
    2057 /* get resultant implied integral type */
    2058 for( v = 0; v < nvars; ++v )
    2059 {
    2061 {
    2062 impltype = SCIP_IMPLINTTYPE_WEAK;
    2063 break;
    2064 }
    2065 }
    2066
    2067 /* create auxiliary variable */
    2068 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, ARTIFICIALVARNAMEPREFIX"%d", conshdlrdata->nallconsanddatas);
    2069 SCIP_CALL( SCIPcreateVarImpl(scip, &resultant, name, 0.0, 1.0, 0.0,
    2070 SCIP_VARTYPE_CONTINUOUS, impltype, TRUE, TRUE, NULL, NULL, NULL, NULL, NULL) );
    2071
    2072 /* add auxiliary variable to the problem */
    2073 SCIP_CALL( SCIPaddVar(scip, resultant) );
    2074
    2075 /* @todo: keep and-resultants defined to check debug solution */
    2076#ifdef SCIP_DISABLED_CODE
    2077#ifdef WITH_DEBUG_SOLUTION
    2078 if( SCIPdebugIsMainscip(scip) )
    2079 {
    2080 SCIP_Real val = 1.0;
    2081 SCIP_Real debugsolval;
    2082
    2083 assert(nvars >= 1);
    2084 for( v = nvars - 1; v >= 0; --v )
    2085 {
    2086 SCIP_CALL( SCIPdebugGetSolVal(scip, vars[v], &val) );
    2087 assert(SCIPisFeasZero(scip, val) || SCIPisFeasEQ(scip, val, 1.0));
    2088
    2089 if( val < 0.5 )
    2090 break;
    2091 }
    2092 val = ((val < 0.5) ? 0.0 : 1.0);
    2093
    2094 SCIP_CALL( SCIPdebugGetSolVal(scip, resultant, &debugsolval) );
    2095 if( (SCIPvarIsOriginal(resultant) || SCIPvarIsTransformedOrigvar(resultant)) && !SCIPisFeasEQ(scip, debugsolval, val) )
    2096 {
    2097 SCIPerrorMessage("computed solution value %g for resultant <%s> violates debug solution value %g\n", val, SCIPvarGetName(resultant), debugsolval);
    2098 SCIPABORT();
    2099 return SCIP_ERROR; /*lint !e527*/
    2100 }
    2101 else if( !SCIPvarIsOriginal(resultant) && !SCIPvarIsTransformedOrigvar(resultant) )
    2102 {
    2103 SCIP_CALL( SCIPdebugAddSolVal(scip, resultant, val) );
    2104 }
    2105 }
    2106#endif
    2107#endif
    2108
    2109 SCIP_CALL( SCIPgetBoolParam(scip, "constraints/" CONSHDLR_NAME "/nlcseparate", &separate) );
    2110 SCIP_CALL( SCIPgetBoolParam(scip, "constraints/" CONSHDLR_NAME "/nlcpropagate", &propagate) );
    2111 SCIP_CALL( SCIPgetBoolParam(scip, "constraints/" CONSHDLR_NAME "/nlcremovable", &removable) );
    2112
    2113 /* we do not want to check the and constraints, so the check flag will be FALSE */
    2114
    2115 /* create and add "and" constraint for the multiplication of the binary variables */
    2116 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "andcons_%d", conshdlrdata->nallconsanddatas);
    2117 SCIP_CALL( SCIPcreateConsAnd(scip, &newcons, name, resultant, newdata->nvars, newdata->vars,
    2118 initial, separate, enforce, check && FALSE, propagate,
    2119 local, modifiable, dynamic, removable, stickingatnode) ); /*lint !e506*/
    2120 SCIP_CALL( SCIPaddCons(scip, newcons) );
    2121 SCIPdebugPrintCons(scip, newcons, NULL);
    2122
    2123 *andcons = newcons;
    2124 assert(*andcons != NULL);
    2125
    2126 /* resize data for all and-constraints if necessary */
    2127 if( conshdlrdata->nallconsanddatas == conshdlrdata->sallconsanddatas )
    2128 {
    2129 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &(conshdlrdata->allconsanddatas), &(conshdlrdata->sallconsanddatas), SCIPcalcMemGrowSize(scip, conshdlrdata->sallconsanddatas + 1)) );
    2130 }
    2131
    2132 /* add new data object to global hash table */
    2133 conshdlrdata->allconsanddatas[conshdlrdata->nallconsanddatas] = newdata;
    2134 ++(conshdlrdata->nallconsanddatas);
    2135
    2136 if( transformed )
    2137 {
    2138 newdata->cons = newcons;
    2139 SCIP_CALL( SCIPcaptureCons(scip, newdata->cons) );
    2140
    2141 /* lock upgrade to keep control */
    2142 SCIPconsAddUpgradeLocks(newcons, +1);
    2143
    2144 /* initialize usage of data object */
    2145 newdata->nuses = 1;
    2146
    2147 /* capture all variables */
    2148 for( v = newdata->nvars - 1; v >= 0; --v )
    2149 {
    2150 SCIP_CALL( SCIPcaptureVar(scip, newdata->vars[v]) ); /*lint !e613*/
    2151 }
    2152 }
    2153 else
    2154 {
    2155 newdata->origcons = newcons;
    2156 SCIP_CALL( SCIPcaptureCons(scip, newdata->origcons) );
    2157
    2158 /* initialize usage of data object */
    2159 newdata->noriguses = 1;
    2160 }
    2161
    2162 /* no such and-constraint in current hash table: insert the new object into hash table */
    2163 SCIP_CALL( SCIPhashtableInsert(conshdlrdata->hashtable, (void*)newdata) );
    2164
    2165 /* insert new mapping */
    2166 assert(!SCIPhashmapExists(conshdlrdata->hashmap, (void*)resultant));
    2167 SCIP_CALL( SCIPhashmapInsert(conshdlrdata->hashmap, (void*)resultant, (void*)newdata) );
    2168
    2169 /* release and-resultant and -constraint */
    2170 SCIP_CALL( SCIPreleaseVar(scip, &resultant) );
    2171 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    2172
    2173 return SCIP_OKAY;
    2174 }
    2175
    2176 /* free memory */
    2177 SCIPfreeBlockMemoryArray(scip, &(newdata->vars), newdata->svars);
    2178 SCIPfreeBlockMemory(scip, &newdata);
    2179
    2180 return SCIP_OKAY;
    2181}
    2182
    2183/** adds a term to the given pseudoboolean constraint */
    2184static
    2186 SCIP*const scip, /**< SCIP data structure */
    2187 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    2188 SCIP_VAR**const vars, /**< variables of the nonlinear term */
    2189 int const nvars, /**< number of variables of the nonlinear term */
    2190 SCIP_Real const val /**< coefficient of constraint entry */
    2191 )
    2192{
    2193 SCIP_CONSHDLR* conshdlr;
    2194 SCIP_CONSHDLRDATA* conshdlrdata;
    2195 SCIP_CONS* andcons;
    2196 SCIP_CONSDATA* consdata;
    2197 SCIP_VAR* res;
    2198
    2199 assert(scip != NULL);
    2200 assert(cons != NULL);
    2201
    2202 if( SCIPisZero(scip, val) )
    2203 return SCIP_OKAY;
    2204
    2205 assert(vars != NULL);
    2206 assert(nvars >= 1);
    2207
    2208 consdata = SCIPconsGetData(cons);
    2209 assert(consdata != NULL);
    2210
    2211 conshdlr = SCIPconsGetHdlr(cons);
    2212 assert(conshdlr != NULL);
    2213
    2214 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2215 assert(conshdlrdata != NULL);
    2216
    2217 /* create (and add) and-constraint */
    2218 SCIP_CALL( createAndAddAndCons(scip, conshdlr, vars, nvars,
    2221 &andcons) );
    2222 assert(andcons != NULL);
    2223
    2224 /* ensure memory size */
    2225 if( consdata->nconsanddatas == consdata->sconsanddatas )
    2226 {
    2227 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &(consdata->consanddatas), &(consdata->sconsanddatas), consdata->sconsanddatas + 1) );
    2228 }
    2229
    2230 res = SCIPgetResultantAnd(scip, andcons);
    2231 assert(res != NULL);
    2232 assert(SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res) != NULL);
    2233
    2234 consdata->consanddatas[consdata->nconsanddatas] = (CONSANDDATA*) SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res);
    2235 ++(consdata->nconsanddatas);
    2236
    2237 /* add auxiliary variables to linear constraint */
    2238 switch( consdata->linconstype )
    2239 {
    2241 SCIP_CALL( SCIPaddCoefLinear(scip, consdata->lincons, res, val) );
    2242 break;
    2244 if( !SCIPisEQ(scip, val, 1.0) )
    2245 return SCIP_INVALIDDATA;
    2246
    2247 SCIP_CALL( SCIPaddCoefLogicor(scip, consdata->lincons, res) );
    2248 break;
    2250 if( !SCIPisIntegral(scip, val) || !SCIPisPositive(scip, val) )
    2251 return SCIP_INVALIDDATA;
    2252
    2253 SCIP_CALL( SCIPaddCoefKnapsack(scip, consdata->lincons, res, (SCIP_Longint) val) );
    2254 break;
    2256 if( !SCIPisEQ(scip, val, 1.0) )
    2257 return SCIP_INVALIDDATA;
    2258
    2259 SCIP_CALL( SCIPaddCoefSetppc(scip, consdata->lincons, res) );
    2260 break;
    2261#ifdef WITHEQKNAPSACK
    2262 case SCIP_LINEARCONSTYPE_EQKNAPSACK:
    2263 if( !SCIPisIntegral(scip, val) || !SCIPisPositive(scip, val) )
    2264 return SCIP_INVALIDDATA;
    2265
    2266 SCIP_CALL( SCIPaddCoefEQKnapsack(scip, consdata->lincons, res, (SCIP_Longint) val) );
    2267 break;
    2268#endif
    2270 default:
    2271 SCIPerrorMessage("unknown linear constraint type\n");
    2272 return SCIP_INVALIDDATA;
    2273 }
    2274
    2275 /* install rounding locks for all new variable */
    2276 SCIP_CALL( lockRoundingAndCons(scip, cons, consdata->consanddatas[consdata->nconsanddatas - 1], val, consdata->lhs, consdata->rhs) );
    2277
    2278 /* change flags */
    2279 consdata->changed = TRUE;
    2280 consdata->propagated = FALSE;
    2281 consdata->presolved = FALSE;
    2282 consdata->cliquesadded = FALSE;
    2283 consdata->upgradetried = FALSE;
    2284
    2285 return SCIP_OKAY;
    2286}
    2287
    2288/** changes left hand side of linear constraint */
    2289static
    2291 SCIP*const scip, /**< SCIP data structure */
    2292 SCIP_CONS*const cons, /**< linear constraint */
    2293 SCIP_LINEARCONSTYPE const constype, /**< linear constraint type */
    2294 SCIP_Real const lhs /**< new left hand side of linear constraint */
    2295 )
    2296{
    2297 switch( constype )
    2298 {
    2300 SCIP_CALL( SCIPchgLhsLinear(scip, cons, lhs) );
    2301 break;
    2305 SCIPerrorMessage("changing left hand side only allowed on standard lienar constraint \n");
    2306 return SCIP_INVALIDDATA;
    2307#ifdef WITHEQKNAPSACK
    2308 case SCIP_LINEARCONSTYPE_EQKNAPSACK:
    2309#endif
    2311 default:
    2312 SCIPerrorMessage("unknown linear constraint type\n");
    2313 return SCIP_INVALIDDATA;
    2314 }
    2315
    2316 return SCIP_OKAY;
    2317}
    2318
    2319/** changes right hand side of linear constraint */
    2320static
    2322 SCIP*const scip, /**< SCIP data structure */
    2323 SCIP_CONS*const cons, /**< linear constraint */
    2324 SCIP_LINEARCONSTYPE const constype, /**< linear constraint type */
    2325 SCIP_Real const rhs /**< new right hand side of linear constraint */
    2326 )
    2327{
    2328 switch( constype )
    2329 {
    2331 SCIP_CALL( SCIPchgRhsLinear(scip, cons, rhs) );
    2332 break;
    2336 SCIPerrorMessage("changing left hand side only allowed on standard lienar constraint \n");
    2337 return SCIP_INVALIDDATA;
    2338#ifdef WITHEQKNAPSACK
    2339 case SCIP_LINEARCONSTYPE_EQKNAPSACK:
    2340#endif
    2342 default:
    2343 SCIPerrorMessage("unknown linear constraint type\n");
    2344 return SCIP_INVALIDDATA;
    2345 }
    2346
    2347 return SCIP_OKAY;
    2348}
    2349
    2350/** sets left hand side of linear constraint */
    2351static
    2353 SCIP*const scip, /**< SCIP data structure */
    2354 SCIP_CONS*const cons, /**< linear constraint */
    2355 SCIP_Real lhs /**< new left hand side */
    2356 )
    2357{
    2358 SCIP_CONSDATA* consdata;
    2359 SCIP_VAR** vars;
    2360 SCIP_Real* coefs;
    2361 int nvars;
    2362 SCIP_VAR** linvars;
    2363 SCIP_Real* lincoefs;
    2364 int nlinvars;
    2365 SCIP_VAR** andress;
    2366 SCIP_Real* andcoefs;
    2367 SCIP_Bool* andnegs;
    2368 int nandress;
    2369 SCIP_Real oldlhs;
    2370 SCIP_Real oldrhs;
    2371
    2372 assert(scip != NULL);
    2373 assert(cons != NULL);
    2375 assert(!SCIPisInfinity(scip, lhs));
    2376
    2377 /* adjust value to not be smaller than -inf */
    2378 if ( SCIPisInfinity(scip, -lhs) )
    2379 lhs = -SCIPinfinity(scip);
    2380
    2381 consdata = SCIPconsGetData(cons);
    2382 assert(consdata != NULL);
    2383
    2384 /* get sides of linear constraint */
    2385 SCIP_CALL( getLinearConsSides(scip, consdata->lincons, consdata->linconstype, &oldlhs, &oldrhs) );
    2386 assert(!SCIPisInfinity(scip, oldlhs));
    2387 assert(!SCIPisInfinity(scip, -oldrhs));
    2388 assert(SCIPisLE(scip, oldlhs, oldrhs));
    2389
    2390 /* check whether the side is not changed */
    2391 if( SCIPisEQ(scip, oldlhs, lhs) )
    2392 return SCIP_OKAY;
    2393
    2394 /* gets number of variables in linear constraint */
    2395 SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
    2396
    2397 /* allocate temporary memory */
    2398 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    2399 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
    2400 SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nvars) );
    2401 SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nvars) );
    2402 SCIP_CALL( SCIPallocBufferArray(scip, &andress, nvars) );
    2403 SCIP_CALL( SCIPallocBufferArray(scip, &andcoefs, nvars) );
    2404 SCIP_CALL( SCIPallocBufferArray(scip, &andnegs, nvars) );
    2405
    2406 /* get variables and coefficient of linear constraint */
    2407 SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) );
    2408 assert(coefs != NULL || nvars == 0);
    2409
    2410 /* calculate all not artificial linear variables and all artificial and-resultants */
    2411 SCIP_CALL( getLinVarsAndAndRess(scip, cons, vars, coefs, nvars, linvars, lincoefs, &nlinvars, andress, andcoefs, andnegs, &nandress) );
    2412 assert(consdata->nconsanddatas == nandress);
    2413
    2414 /* if necessary, update the rounding locks of variables */
    2415 if( SCIPconsIsLocked(cons) )
    2416 {
    2417 SCIP_VAR** andvars;
    2418 int nandvars;
    2419 SCIP_Real val;
    2420 int v;
    2421 int c;
    2422
    2423 assert(SCIPconsIsTransformed(cons));
    2424
    2425 if( SCIPisInfinity(scip, -oldlhs) && !SCIPisInfinity(scip, -lhs) )
    2426 {
    2427 /* non-linear part */
    2428 for( c = consdata->nconsanddatas - 1; c >= 0; --c )
    2429 {
    2430 CONSANDDATA* consanddata;
    2431 SCIP_CONS* andcons;
    2432
    2433 consanddata = consdata->consanddatas[c];
    2434 assert(consanddata != NULL);
    2435
    2436 andcons = consanddata->cons;
    2437 assert(andcons != NULL);
    2438
    2439 andvars = SCIPgetVarsAnd(scip, andcons);
    2440 nandvars = SCIPgetNVarsAnd(scip, andcons);
    2441 val = andnegs[c] ? -andcoefs[c] : andcoefs[c];
    2442
    2443 /* lock variables */
    2444 if( SCIPisPositive(scip, val) )
    2445 {
    2446 for( v = nandvars - 1; v >= 0; --v )
    2447 {
    2448 SCIP_CALL( SCIPlockVarCons(scip, andvars[v], cons, TRUE, FALSE) );
    2449 }
    2450 }
    2451 else
    2452 {
    2453 for( v = nandvars - 1; v >= 0; --v )
    2454 {
    2455 SCIP_CALL( SCIPlockVarCons(scip, andvars[v], cons, FALSE, TRUE) );
    2456 }
    2457 }
    2458 }
    2459 }
    2460 else if( !SCIPisInfinity(scip, -oldlhs) && SCIPisInfinity(scip, -lhs) )
    2461 {
    2462 /* non-linear part */
    2463 for( c = consdata->nconsanddatas - 1; c >= 0; --c )
    2464 {
    2465 CONSANDDATA* consanddata;
    2466 SCIP_CONS* andcons;
    2467
    2468 consanddata = consdata->consanddatas[c];
    2469 assert(consanddata != NULL);
    2470
    2471 andcons = consanddata->cons;
    2472 assert(andcons != NULL);
    2473
    2474 andvars = SCIPgetVarsAnd(scip, andcons);
    2475 nandvars = SCIPgetNVarsAnd(scip, andcons);
    2476 val = andnegs[c] ? -andcoefs[c] : andcoefs[c];
    2477
    2478 /* lock variables */
    2479 if( SCIPisPositive(scip, val) )
    2480 {
    2481 for( v = nandvars - 1; v >= 0; --v )
    2482 {
    2483 SCIP_CALL( SCIPunlockVarCons(scip, andvars[v], cons, TRUE, FALSE) );
    2484 }
    2485 }
    2486 else
    2487 {
    2488 for( v = nandvars - 1; v >= 0; --v )
    2489 {
    2490 SCIP_CALL( SCIPunlockVarCons(scip, andvars[v], cons, FALSE, TRUE) );
    2491 }
    2492 }
    2493 }
    2494 }
    2495 }
    2496
    2497 /* check whether the left hand side is increased, if and only if that's the case we maybe can propagate, tighten and add more cliques */
    2498 if( SCIPisLT(scip, oldlhs, lhs) )
    2499 {
    2500 consdata->propagated = FALSE;
    2501 }
    2502
    2503 /* set new left hand side and update constraint data */
    2504 SCIP_CALL( chgLhsLinearCons(scip, consdata->lincons, consdata->linconstype, lhs) );
    2505 consdata->lhs = lhs;
    2506 consdata->presolved = FALSE;
    2507 consdata->changed = TRUE;
    2508
    2509 /* free temporary memory */
    2510 SCIPfreeBufferArray(scip, &andnegs);
    2511 SCIPfreeBufferArray(scip, &andcoefs);
    2512 SCIPfreeBufferArray(scip, &andress);
    2513 SCIPfreeBufferArray(scip, &lincoefs);
    2514 SCIPfreeBufferArray(scip, &linvars);
    2515 SCIPfreeBufferArray(scip, &coefs);
    2516 SCIPfreeBufferArray(scip, &vars);
    2517
    2518 return SCIP_OKAY;
    2519}
    2520
    2521/** sets right hand side of pseudoboolean constraint */
    2522static
    2524 SCIP*const scip, /**< SCIP data structure */
    2525 SCIP_CONS*const cons, /**< linear constraint */
    2526 SCIP_Real rhs /**< new right hand side */
    2527 )
    2528{
    2529 SCIP_CONSDATA* consdata;
    2530 SCIP_VAR** vars;
    2531 SCIP_Real* coefs;
    2532 int nvars;
    2533 SCIP_VAR** linvars;
    2534 SCIP_Real* lincoefs;
    2535 int nlinvars;
    2536 SCIP_VAR** andress;
    2537 SCIP_Real* andcoefs;
    2538 SCIP_Bool* andnegs;
    2539 int nandress;
    2540 SCIP_Real oldlhs;
    2541 SCIP_Real oldrhs;
    2542
    2543 assert(scip != NULL);
    2544 assert(cons != NULL);
    2546 assert(!SCIPisInfinity(scip, -rhs));
    2547
    2548 /* adjust value to not be larger than inf */
    2549 if( SCIPisInfinity(scip, rhs) )
    2550 rhs = SCIPinfinity(scip);
    2551
    2552 consdata = SCIPconsGetData(cons);
    2553 assert(consdata != NULL);
    2554
    2555 /* get sides of linear constraint */
    2556 SCIP_CALL( getLinearConsSides(scip, consdata->lincons, consdata->linconstype, &oldlhs, &oldrhs) );
    2557 assert(!SCIPisInfinity(scip, oldlhs));
    2558 assert(!SCIPisInfinity(scip, -oldrhs));
    2559 assert(SCIPisLE(scip, oldlhs, oldrhs));
    2560
    2561 /* check whether the side is not changed */
    2562 if( SCIPisEQ(scip, oldrhs, rhs) )
    2563 return SCIP_OKAY;
    2564
    2565 /* gets number of variables in linear constraint */
    2566 SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
    2567
    2568 /* allocate temporary memory */
    2569 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    2570 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
    2571 SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nvars) );
    2572 SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nvars) );
    2573 SCIP_CALL( SCIPallocBufferArray(scip, &andress, nvars) );
    2574 SCIP_CALL( SCIPallocBufferArray(scip, &andcoefs, nvars) );
    2575 SCIP_CALL( SCIPallocBufferArray(scip, &andnegs, nvars) );
    2576
    2577 /* get variables and coefficient of linear constraint */
    2578 SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) );
    2579 assert(coefs != NULL || nvars == 0);
    2580
    2581 /* calculate all not artificial linear variables and all artificial and-resultants */
    2582 SCIP_CALL( getLinVarsAndAndRess(scip, cons, vars, coefs, nvars, linvars, lincoefs, &nlinvars, andress, andcoefs, andnegs, &nandress) );
    2583 assert(consdata->nconsanddatas == nandress);
    2584
    2585 /* if necessary, update the rounding locks of variables */
    2586 if( SCIPconsIsLocked(cons) )
    2587 {
    2588 SCIP_VAR** andvars;
    2589 int nandvars;
    2590 SCIP_Real val;
    2591 int v;
    2592 int c;
    2593
    2594 assert(SCIPconsIsTransformed(cons));
    2595
    2596 if( SCIPisInfinity(scip, oldrhs) && !SCIPisInfinity(scip, rhs) )
    2597 {
    2598 /* non-linear part */
    2599 for( c = consdata->nconsanddatas - 1; c >= 0; --c )
    2600 {
    2601 CONSANDDATA* consanddata;
    2602 SCIP_CONS* andcons;
    2603
    2604 consanddata = consdata->consanddatas[c];
    2605 assert(consanddata != NULL);
    2606
    2607 andcons = consanddata->cons;
    2608 assert(andcons != NULL);
    2609
    2610 andvars = SCIPgetVarsAnd(scip, andcons);
    2611 nandvars = SCIPgetNVarsAnd(scip, andcons);
    2612 val = andnegs[c] ? -andcoefs[c] : andcoefs[c];
    2613
    2614 /* lock variables */
    2615 if( SCIPisPositive(scip, val) )
    2616 {
    2617 for( v = nandvars - 1; v >= 0; --v )
    2618 {
    2619 SCIP_CALL( SCIPlockVarCons(scip, andvars[v], cons, FALSE, TRUE) );
    2620 }
    2621 }
    2622 else
    2623 {
    2624 for( v = nandvars - 1; v >= 0; --v )
    2625 {
    2626 SCIP_CALL( SCIPlockVarCons(scip, andvars[v], cons, TRUE, FALSE) );
    2627 }
    2628 }
    2629 }
    2630 }
    2631 else if( !SCIPisInfinity(scip, oldrhs) && SCIPisInfinity(scip, rhs) )
    2632 {
    2633 /* non-linear part */
    2634 for( c = consdata->nconsanddatas - 1; c >= 0; --c )
    2635 {
    2636 CONSANDDATA* consanddata;
    2637 SCIP_CONS* andcons;
    2638
    2639 consanddata = consdata->consanddatas[c];
    2640 assert(consanddata != NULL);
    2641
    2642 andcons = consanddata->cons;
    2643 assert(andcons != NULL);
    2644
    2645 andvars = SCIPgetVarsAnd(scip, andcons);
    2646 nandvars = SCIPgetNVarsAnd(scip, andcons);
    2647 val = andnegs[c] ? -andcoefs[c] : andcoefs[c];
    2648
    2649 /* lock variables */
    2650 if( SCIPisPositive(scip, val) )
    2651 {
    2652 for( v = nandvars - 1; v >= 0; --v )
    2653 {
    2654 SCIP_CALL( SCIPunlockVarCons(scip, andvars[v], cons, FALSE, TRUE) );
    2655 }
    2656 }
    2657 else
    2658 {
    2659 for( v = nandvars - 1; v >= 0; --v )
    2660 {
    2661 SCIP_CALL( SCIPunlockVarCons(scip, andvars[v], cons, TRUE, FALSE) );
    2662 }
    2663 }
    2664 }
    2665 }
    2666 }
    2667
    2668 /* check whether the right hand side is decreased, if and only if that's the case we maybe can propagate, tighten and add more cliques */
    2669 if( SCIPisGT(scip, oldrhs, rhs) )
    2670 {
    2671 consdata->propagated = FALSE;
    2672 }
    2673
    2674 /* set new right hand side and update constraint data */
    2675 SCIP_CALL( chgRhsLinearCons(scip, consdata->lincons, consdata->linconstype, rhs) );
    2676 consdata->rhs = rhs;
    2677 consdata->presolved = FALSE;
    2678 consdata->changed = TRUE;
    2679
    2680 /* free temporary memory */
    2681 SCIPfreeBufferArray(scip, &andnegs);
    2682 SCIPfreeBufferArray(scip, &andcoefs);
    2683 SCIPfreeBufferArray(scip, &andress);
    2684 SCIPfreeBufferArray(scip, &lincoefs);
    2685 SCIPfreeBufferArray(scip, &linvars);
    2686 SCIPfreeBufferArray(scip, &coefs);
    2687 SCIPfreeBufferArray(scip, &vars);
    2688
    2689 return SCIP_OKAY;
    2690}
    2691
    2692/** create and-constraints and get all and-resultants */
    2693static
    2695 SCIP*const scip, /**< SCIP data structure */
    2696 SCIP_CONSHDLR*const conshdlr, /**< pseudoboolean constraint handler */
    2697 SCIP_VAR**const*const terms, /**< array of term variables to get and-constraints for */
    2698 SCIP_Real*const termcoefs, /**< array of coefficients for and-constraints */
    2699 int const nterms, /**< number of terms to get and-constraints for */
    2700 int const*const ntermvars, /**< array of number of variable in each term */
    2701 SCIP_Bool const initial, /**< should the LP relaxation of constraint be in the initial LP?
    2702 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    2703 SCIP_Bool const enforce, /**< should the constraint be enforced during node processing?
    2704 * TRUE for model constraints, FALSE for additional, redundant
    2705 * constraints. */
    2706 SCIP_Bool const check, /**< should the constraint be checked for feasibility?
    2707 * TRUE for model constraints, FALSE for additional, redundant
    2708 * constraints. */
    2709 SCIP_Bool const local, /**< is constraint only valid locally?
    2710 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching
    2711 * constraints. */
    2712 SCIP_Bool const modifiable, /**< is constraint modifiable (subject to column generation)?
    2713 * Usually set to FALSE. In column generation applications, set to TRUE
    2714 * if pricing adds coefficients to this constraint. */
    2715 SCIP_Bool const dynamic, /**< is constraint subject to aging?
    2716 * Usually set to FALSE. Set to TRUE for own cuts which
    2717 * are seperated as constraints. */
    2718 SCIP_Bool const stickingatnode, /**< should the constraint always be kept at the node where it was added, even
    2719 * if it may be moved to a more global node?
    2720 * Usually set to FALSE. Set to TRUE to for constraints that represent
    2721 * node data. */
    2722 SCIP_CONS**const andconss, /**< array to store all created and-constraints for given terms */
    2723 SCIP_Real*const andvals, /**< array to store all coefficients of and-constraints */
    2724 SCIP_Bool*const andnegs, /**< array to store negation status of and-constraints */
    2725 int*const nandconss /**< number of created and constraints */
    2726 )
    2727{
    2728 int t;
    2729
    2730 assert(scip != NULL);
    2731 assert(conshdlr != NULL);
    2732 assert(terms != NULL || nterms == 0);
    2733 assert(ntermvars != NULL || nterms == 0);
    2734 assert(andconss != NULL);
    2735 assert(andvals != NULL);
    2736 assert(nandconss != NULL);
    2737
    2738 (*nandconss) = 0;
    2739
    2740 /* loop over all terms and create/get all and constraints */
    2741 for( t = 0; t < nterms; ++t )
    2742 {
    2743 if( !SCIPisZero(scip, termcoefs[t]) )
    2744 {
    2745 SCIP_CALL( createAndAddAndCons(scip, conshdlr, terms[t], ntermvars[t],
    2746 initial, enforce, check, local, modifiable, dynamic, stickingatnode,
    2747 &(andconss[*nandconss])) );
    2748 assert(andconss[*nandconss] != NULL);
    2749 andvals[*nandconss] = termcoefs[t];
    2750 andnegs[*nandconss] = FALSE;
    2751 ++(*nandconss);
    2752 }
    2753 }
    2754
    2755 return SCIP_OKAY;
    2756}
    2757
    2758/** created linear constraint of pseudo boolean constraint */
    2759static
    2761 SCIP*const scip, /**< SCIP data structure */
    2762 SCIP_CONSHDLR*const conshdlr, /**< pseudoboolean constraint handler */
    2763 SCIP_VAR**const linvars, /**< linear variables */
    2764 int const nlinvars, /**< number of linear variables */
    2765 SCIP_Real*const linvals, /**< linear coefficients */
    2766 SCIP_VAR**const andress, /**< and-resultant variables */
    2767 int const nandress, /**< number of and-resultant variables */
    2768 SCIP_Real const*const andvals, /**< and-resultant coefficients */
    2769 SCIP_Bool*const andnegs, /**< and-resultant negation status */
    2770 SCIP_Real*const lhs, /**< pointer to left hand side of linear constraint */
    2771 SCIP_Real*const rhs, /**< pointer to right hand side of linear constraint */
    2772 SCIP_Bool const issoftcons, /**< is this a soft constraint */
    2773 SCIP_Bool const initial, /**< should the LP relaxation of constraint be in the initial LP?
    2774 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    2775 SCIP_Bool const separate, /**< should the constraint be separated during LP processing?
    2776 * Usually set to TRUE. */
    2777 SCIP_Bool const enforce, /**< should the constraint be enforced during node processing?
    2778 * TRUE for model constraints, FALSE for additional, redundant
    2779 * constraints. */
    2780 SCIP_Bool const check, /**< should the constraint be checked for feasibility?
    2781 * TRUE for model constraints, FALSE for additional, redundant
    2782 * constraints. */
    2783 SCIP_Bool const propagate, /**< should the constraint be propagated during node processing?
    2784 * Usually set to TRUE. */
    2785 SCIP_Bool const local, /**< is constraint only valid locally?
    2786 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching
    2787 * constraints. */
    2788 SCIP_Bool const modifiable, /**< is constraint modifiable (subject to column generation)?
    2789 * Usually set to FALSE. In column generation applications, set to TRUE
    2790 * if pricing adds coefficients to this constraint. */
    2791 SCIP_Bool const dynamic, /**< is constraint subject to aging?
    2792 * Usually set to FALSE. Set to TRUE for own cuts which
    2793 * are seperated as constraints. */
    2794 SCIP_Bool const removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
    2795 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user
    2796 * cuts'. */
    2797 SCIP_Bool const stickingatnode, /**< should the constraint always be kept at the node where it was added, even
    2798 * if it may be moved to a more global node?
    2799 * Usually set to FALSE. Set to TRUE to for constraints that represent
    2800 * node data. */
    2801 SCIP_CONS**const lincons, /**< pointer to store created linear constraint */
    2802 SCIP_LINEARCONSTYPE*const linconstype /**< pointer to store the type of the linear constraint */
    2803 )
    2804{
    2805 SCIP_CONSHDLRDATA* conshdlrdata;
    2806 SCIP_CONSHDLR* upgrconshdlr;
    2807 SCIP_CONS* cons;
    2808 char name[SCIP_MAXSTRLEN];
    2809 int v;
    2810 SCIP_Bool created;
    2811 SCIP_Bool integral;
    2812 int nzero;
    2813 int ncoeffspone;
    2814 int ncoeffsnone;
    2815 int ncoeffspint;
    2816 int ncoeffsnint;
    2817
    2818 assert(scip != NULL);
    2819 assert(conshdlr != NULL);
    2820 assert(linvars != NULL || nlinvars == 0);
    2821 assert(linvals != NULL || nlinvars == 0);
    2822 assert(andress != NULL || nandress == 0);
    2823 assert(andvals != NULL || nandress == 0);
    2824 assert(lhs != NULL);
    2825 assert(rhs != NULL);
    2826 assert(lincons != NULL);
    2827 assert(linconstype != NULL);
    2828 assert(nlinvars > 0 || nandress > 0);
    2829
    2830 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2831 assert(conshdlrdata != NULL);
    2832
    2833 (*linconstype) = SCIP_LINEARCONSTYPE_INVALIDCONS;
    2834 (*lincons) = NULL;
    2835 cons = NULL;
    2836
    2837 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "pseudoboolean_linear%d", conshdlrdata->nlinconss);
    2838 ++(conshdlrdata->nlinconss);
    2839
    2840 created = FALSE;
    2841
    2842 if( !modifiable )
    2843 {
    2844 SCIP_Real val;
    2845 int nvars;
    2846
    2847 /* calculate some statistics for upgrading on linear constraint */
    2848 nzero = 0;
    2849 ncoeffspone = 0;
    2850 ncoeffsnone = 0;
    2851 ncoeffspint = 0;
    2852 ncoeffsnint = 0;
    2853 integral = TRUE;
    2854 nvars = nlinvars + nandress;
    2855
    2856 /* calculate information over linear part */
    2857 for( v = nlinvars - 1; v >= 0; --v )
    2858 {
    2859 val = linvals[v];
    2860
    2861 if( SCIPisZero(scip, val) )
    2862 {
    2863 ++nzero;
    2864 continue;
    2865 }
    2866 if( SCIPisEQ(scip, val, 1.0) )
    2867 ++ncoeffspone;
    2868 else if( SCIPisEQ(scip, val, -1.0) )
    2869 ++ncoeffsnone;
    2870 else if( SCIPisIntegral(scip, val) )
    2871 {
    2872 if( SCIPisPositive(scip, val) )
    2873 ++ncoeffspint;
    2874 else
    2875 ++ncoeffsnint;
    2876 }
    2877 else
    2878 {
    2879 integral = FALSE;
    2880 break;
    2881 }
    2882 }
    2883
    2884 if( integral )
    2885 {
    2886 /* calculate information over and-resultants */
    2887 for( v = nandress - 1; v >= 0; --v )
    2888 {
    2889 val = andvals[v];
    2890
    2891 if( SCIPisZero(scip, val) )
    2892 {
    2893 ++nzero;
    2894 continue;
    2895 }
    2896 if( SCIPisEQ(scip, val, 1.0) )
    2897 ++ncoeffspone;
    2898 else if( SCIPisEQ(scip, val, -1.0) )
    2899 ++ncoeffsnone;
    2900 else if( SCIPisIntegral(scip, val) )
    2901 {
    2902 if( SCIPisPositive(scip, val) )
    2903 ++ncoeffspint;
    2904 else
    2905 ++ncoeffsnint;
    2906 }
    2907 else
    2908 {
    2909 integral = FALSE;
    2910 break;
    2911 }
    2912 }
    2913 }
    2914
    2915 SCIPdebugMsg(scip, "While creating the linear constraint of the pseudoboolean constraint we found %d zero coefficients that were removed\n", nzero);
    2916
    2917 /* try to upgrade to a special linear constraint */
    2918 if( integral )
    2919 {
    2920 upgrconshdlr = SCIPfindConshdlr(scip, "logicor");
    2921
    2922 /* check, if linear constraint can be upgraded to logic or constraint
    2923 * - logic or constraints consist only of binary variables with a
    2924 * coefficient of +1.0 or -1.0 (variables with -1.0 coefficients can be negated):
    2925 * lhs <= x1 + ... + xp - y1 - ... - yn <= rhs
    2926 * - negating all variables y = (1-Y) with negative coefficients gives:
    2927 * lhs + n <= x1 + ... + xp + Y1 + ... + Yn <= rhs + n
    2928 * - negating all variables x = (1-X) with positive coefficients and multiplying with -1 gives:
    2929 * p - rhs <= X1 + ... + Xp + y1 + ... + yn <= p - lhs
    2930 * - logic or constraints have left hand side of +1.0, and right hand side of +infinity: x(S) >= 1.0
    2931 * -> without negations: (lhs == 1 - n and rhs == +inf) or (lhs == -inf and rhs = p - 1)
    2932 */
    2933 if( upgrconshdlr != NULL && nvars > 2 && ncoeffspone + ncoeffsnone == nvars
    2934 && ((SCIPisEQ(scip, *lhs, 1.0 - ncoeffsnone) && SCIPisInfinity(scip, *rhs))
    2935 || (SCIPisInfinity(scip, -*lhs) && SCIPisEQ(scip, *rhs, ncoeffspone - 1.0))) )
    2936 {
    2937 SCIP_VAR** transvars;
    2938 int mult;
    2939
    2940 SCIPdebugMsg(scip, "linear constraint will be logic-or constraint\n");
    2941
    2942 /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
    2943 mult = SCIPisInfinity(scip, *rhs) ? +1 : -1;
    2944
    2945 /* get temporary memory */
    2946 SCIP_CALL( SCIPallocBufferArray(scip, &transvars, nvars) );
    2947
    2948 /* negate positive or negative variables */
    2949 for( v = 0; v < nlinvars; ++v )
    2950 {
    2951 if( mult * linvals[v] > 0.0 )
    2952 transvars[v] = linvars[v];
    2953 else
    2954 {
    2955 SCIP_CALL( SCIPgetNegatedVar(scip, linvars[v], &transvars[v]) );
    2956 }
    2957 assert(transvars[v] != NULL);
    2958 }
    2959
    2960 /* negate positive or negative variables */
    2961 for( v = 0; v < nandress; ++v )
    2962 {
    2963 if( mult * andvals[v] > 0.0 )
    2964 transvars[nlinvars + v] = andress[v];
    2965 else
    2966 {
    2967 SCIP_CALL( SCIPgetNegatedVar(scip, andress[v], &transvars[nlinvars + v]) );
    2968 andnegs[v] = TRUE;
    2969 }
    2970 assert(transvars[nlinvars + v] != NULL);
    2971 }
    2972
    2973 assert(!modifiable);
    2974 /* create the constraint */
    2975 SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, nvars, transvars,
    2976 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    2977
    2978 created = TRUE;
    2979 (*linconstype) = SCIP_LINEARCONSTYPE_LOGICOR;
    2980
    2981 /* free temporary memory */
    2982 SCIPfreeBufferArray(scip, &transvars);
    2983
    2984 *lhs = 1.0;
    2985 *rhs = SCIPinfinity(scip);
    2986 }
    2987
    2988 upgrconshdlr = SCIPfindConshdlr(scip, "setppc");
    2989
    2990 /* check, if linear constraint can be upgraded to set partitioning, packing, or covering constraint
    2991 * - all set partitioning / packing / covering constraints consist only of binary variables with a
    2992 * coefficient of +1.0 or -1.0 (variables with -1.0 coefficients can be negated):
    2993 * lhs <= x1 + ... + xp - y1 - ... - yn <= rhs
    2994 * - negating all variables y = (1-Y) with negative coefficients gives:
    2995 * lhs + n <= x1 + ... + xp + Y1 + ... + Yn <= rhs + n
    2996 * - negating all variables x = (1-X) with positive coefficients and multiplying with -1 gives:
    2997 * p - rhs <= X1 + ... + Xp + y1 + ... + yn <= p - lhs
    2998 * - a set partitioning constraint has left hand side of +1.0, and right hand side of +1.0 : x(S) == 1.0
    2999 * -> without negations: lhs == rhs == 1 - n or lhs == rhs == p - 1
    3000 * - a set packing constraint has left hand side of -infinity, and right hand side of +1.0 : x(S) <= 1.0
    3001 * -> without negations: (lhs == -inf and rhs == 1 - n) or (lhs == p - 1 and rhs = +inf)
    3002 * - a set covering constraint has left hand side of +1.0, and right hand side of +infinity: x(S) >= 1.0
    3003 * -> without negations: (lhs == 1 - n and rhs == +inf) or (lhs == -inf and rhs = p - 1)
    3004 */
    3005 if( upgrconshdlr != NULL && !created && ncoeffspone + ncoeffsnone == nvars )
    3006 {
    3007 SCIP_VAR** transvars;
    3008 int mult;
    3009
    3010 if( SCIPisEQ(scip, *lhs, *rhs) && (SCIPisEQ(scip, *lhs, 1.0 - ncoeffsnone) || SCIPisEQ(scip, *lhs, ncoeffspone - 1.0)) )
    3011 {
    3012 SCIPdebugMsg(scip, "linear pseudoboolean constraint will be a set partitioning constraint\n");
    3013
    3014 /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
    3015 mult = SCIPisEQ(scip, *lhs, 1.0 - ncoeffsnone) ? +1 : -1;
    3016
    3017 /* get temporary memory */
    3018 SCIP_CALL( SCIPallocBufferArray(scip, &transvars, nvars) );
    3019
    3020 /* negate positive or negative variables for linear variables */
    3021 for( v = 0; v < nlinvars; ++v )
    3022 {
    3023 if( mult * linvals[v] > 0.0 )
    3024 transvars[v] = linvars[v];
    3025 else
    3026 {
    3027 SCIP_CALL( SCIPgetNegatedVar(scip, linvars[v], &transvars[v]) );
    3028 }
    3029 assert(transvars[v] != NULL);
    3030 }
    3031
    3032 /* negate positive or negative variables for and-resultants */
    3033 for( v = 0; v < nandress; ++v )
    3034 {
    3035 if( mult * andvals[v] > 0.0 )
    3036 transvars[nlinvars + v] = andress[v];
    3037 else
    3038 {
    3039 SCIP_CALL( SCIPgetNegatedVar(scip, andress[v], &transvars[nlinvars + v]) );
    3040 andnegs[v] = TRUE;
    3041 }
    3042 assert(transvars[nlinvars + v] != NULL);
    3043 }
    3044
    3045 /* create the constraint */
    3046 assert(!modifiable);
    3047 SCIP_CALL( SCIPcreateConsSetpart(scip, &cons, name, nvars, transvars,
    3048 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    3049
    3050 created = TRUE;
    3051 (*linconstype) = SCIP_LINEARCONSTYPE_SETPPC;
    3052
    3053 /* release temporary memory */
    3054 SCIPfreeBufferArray(scip, &transvars);
    3055
    3056 *lhs = 1.0;
    3057 *rhs = 1.0;
    3058 }
    3059 else if( (SCIPisInfinity(scip, -*lhs) && SCIPisEQ(scip, *rhs, 1.0 - ncoeffsnone))
    3060 || (SCIPisEQ(scip, *lhs, ncoeffspone - 1.0) && SCIPisInfinity(scip, *rhs)) )
    3061 {
    3062 SCIPdebugMsg(scip, "linear pseudoboolean constraint will be a set packing constraint\n");
    3063
    3064 /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
    3065 mult = SCIPisInfinity(scip, -*lhs) ? +1 : -1;
    3066
    3067 /* get temporary memory */
    3068 SCIP_CALL( SCIPallocBufferArray(scip, &transvars, nvars) );
    3069
    3070 /* negate positive or negative variables for linear variables */
    3071 for( v = 0; v < nlinvars; ++v )
    3072 {
    3073 if( mult * linvals[v] > 0.0 )
    3074 transvars[v] = linvars[v];
    3075 else
    3076 {
    3077 SCIP_CALL( SCIPgetNegatedVar(scip, linvars[v], &transvars[v]) );
    3078 }
    3079 assert(transvars[v] != NULL);
    3080 }
    3081
    3082 /* negate positive or negative variables for and-resultants*/
    3083 for( v = 0; v < nandress; ++v )
    3084 {
    3085 if( mult * andvals[v] > 0.0 )
    3086 transvars[nlinvars + v] = andress[v];
    3087 else
    3088 {
    3089 SCIP_CALL( SCIPgetNegatedVar(scip, andress[v], &transvars[nlinvars + v]) );
    3090 andnegs[v] = TRUE;
    3091 }
    3092 assert(transvars[nlinvars + v] != NULL);
    3093 }
    3094
    3095 /* create the constraint */
    3096 assert(!modifiable);
    3097 SCIP_CALL( SCIPcreateConsSetpack(scip, &cons, name, nvars, transvars,
    3098 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    3099
    3100 created = TRUE;
    3101 (*linconstype) = SCIP_LINEARCONSTYPE_SETPPC;
    3102
    3103 /* release temporary memory */
    3104 SCIPfreeBufferArray(scip, &transvars);
    3105
    3106 *lhs = -SCIPinfinity(scip);
    3107 *rhs = 1.0;
    3108 }
    3109 else if( (SCIPisEQ(scip, *lhs, 1.0 - ncoeffsnone) && SCIPisInfinity(scip, *rhs))
    3110 || (SCIPisInfinity(scip, -*lhs) && SCIPisEQ(scip, *rhs, ncoeffspone - 1.0)) )
    3111 {
    3112 if( nvars != 1 )
    3113 {
    3114 if( nvars == 2 )
    3115 {
    3116 SCIPwarningMessage(scip, "Does not expect this, because this constraint should be a set packing constraint.\n");
    3117 }
    3118 else
    3119 {
    3120 SCIPwarningMessage(scip, "Does not expect this, because this constraint should be a logicor constraint.\n");
    3121 }
    3122 }
    3123 SCIPdebugMsg(scip, "linear pseudoboolean constraint will be a set covering constraint\n");
    3124
    3125 /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
    3126 mult = SCIPisInfinity(scip, *rhs) ? +1 : -1;
    3127
    3128 /* get temporary memory */
    3129 SCIP_CALL( SCIPallocBufferArray(scip, &transvars, nvars) );
    3130
    3131 /* negate positive or negative variables for linear variables */
    3132 for( v = 0; v < nlinvars; ++v )
    3133 {
    3134 if( mult * linvals[v] > 0.0 )
    3135 transvars[v] = linvars[v];
    3136 else
    3137 {
    3138 SCIP_CALL( SCIPgetNegatedVar(scip, linvars[v], &transvars[v]) );
    3139 }
    3140 assert(transvars[v] != NULL);
    3141 }
    3142
    3143 /* negate positive or negative variables for and-resultants*/
    3144 for( v = 0; v < nandress; ++v )
    3145 {
    3146 if( mult * andvals[v] > 0.0 )
    3147 transvars[nlinvars + v] = andress[v];
    3148 else
    3149 {
    3150 SCIP_CALL( SCIPgetNegatedVar(scip, andress[v], &transvars[nlinvars + v]) );
    3151 andnegs[v] = TRUE;
    3152 }
    3153 assert(transvars[nlinvars + v] != NULL);
    3154 }
    3155
    3156 /* create the constraint */
    3157 assert(!modifiable);
    3158 SCIP_CALL( SCIPcreateConsSetcover(scip, &cons, name, nvars, transvars,
    3159 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    3160
    3161 created = TRUE;
    3162 (*linconstype) = SCIP_LINEARCONSTYPE_SETPPC;
    3163
    3164 /* release temporary memory */
    3165 SCIPfreeBufferArray(scip, &transvars);
    3166
    3167 *lhs = 1.0;
    3168 *rhs = SCIPinfinity(scip);
    3169 }
    3170 }
    3171
    3172 upgrconshdlr = SCIPfindConshdlr(scip, "knapsack");
    3173
    3174 /* check, if linear constraint can be upgraded to a knapsack constraint
    3175 * - all variables must be binary
    3176 * - all coefficients must be integral
    3177 * - exactly one of the sides must be infinite
    3178 */
    3179 if( upgrconshdlr != NULL && !created && (ncoeffspone + ncoeffsnone + ncoeffspint + ncoeffsnint == nvars) && (SCIPisInfinity(scip, -*lhs) != SCIPisInfinity(scip, *rhs)) )
    3180 {
    3181 SCIP_VAR** transvars;
    3182 SCIP_Longint* weights;
    3183 SCIP_Longint capacity;
    3184 SCIP_Longint weight;
    3185 int mult;
    3186
    3187 SCIPdebugMsg(scip, "linear pseudoboolean constraint will be a knapsack constraint\n");
    3188
    3189 /* get temporary memory */
    3190 SCIP_CALL( SCIPallocBufferArray(scip, &transvars, nvars) );
    3191 SCIP_CALL( SCIPallocBufferArray(scip, &weights, nvars) );
    3192
    3193 /* if the right hand side is non-infinite, we have to negate all variables with negative coefficient;
    3194 * otherwise, we have to negate all variables with positive coefficient and multiply the row with -1
    3195 */
    3196 if( SCIPisInfinity(scip, *rhs) )
    3197 {
    3198 mult = -1;
    3199 capacity = (SCIP_Longint)SCIPfeasFloor(scip, -*lhs);
    3200 }
    3201 else
    3202 {
    3203 mult = +1;
    3204 capacity = (SCIP_Longint)SCIPfeasFloor(scip, *rhs);
    3205 }
    3206
    3207 /* negate positive or negative variables for linear variables */
    3208 for( v = 0; v < nlinvars; ++v )
    3209 {
    3210 assert(SCIPisFeasIntegral(scip, linvals[v]));
    3211 weight = mult * (SCIP_Longint)SCIPfeasFloor(scip, linvals[v]);
    3212 if( weight > 0 )
    3213 {
    3214 transvars[v] = linvars[v];
    3215 weights[v] = weight;
    3216 }
    3217 else
    3218 {
    3219 SCIP_CALL( SCIPgetNegatedVar(scip, linvars[v], &transvars[v]) );
    3220 weights[v] = -weight;
    3221 capacity -= weight;
    3222 }
    3223 assert(transvars[v] != NULL);
    3224 }
    3225 /* negate positive or negative variables for and-resultants */
    3226 for( v = 0; v < nandress; ++v )
    3227 {
    3228 assert(SCIPisFeasIntegral(scip, andvals[v]));
    3229 weight = mult * (SCIP_Longint)SCIPfeasFloor(scip, andvals[v]);
    3230 if( weight > 0 )
    3231 {
    3232 transvars[nlinvars + v] = andress[v];
    3233 weights[nlinvars + v] = weight;
    3234 }
    3235 else
    3236 {
    3237 SCIP_CALL( SCIPgetNegatedVar(scip, andress[v], &transvars[nlinvars + v]) );
    3238 andnegs[v] = TRUE;
    3239 weights[nlinvars + v] = -weight;
    3240 capacity -= weight;
    3241 }
    3242 assert(transvars[nlinvars + v] != NULL);
    3243 }
    3244
    3245 /* create the constraint */
    3246 SCIP_CALL( SCIPcreateConsKnapsack(scip, &cons, name, nvars, transvars, weights, capacity,
    3247 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    3248
    3249 created = TRUE;
    3250 (*linconstype) = SCIP_LINEARCONSTYPE_KNAPSACK;
    3251
    3252 /* free temporary memory */
    3253 SCIPfreeBufferArray(scip, &weights);
    3254 SCIPfreeBufferArray(scip, &transvars);
    3255
    3256 *lhs = -SCIPinfinity(scip);
    3257 *rhs = capacity;
    3258 }
    3259#ifdef WITHEQKNAPSACK
    3260
    3261 upgrconshdlr = SCIPfindConshdlr(scip, "eqknapsack");
    3262
    3263 /* check, if linear constraint can be upgraded to a knapsack constraint
    3264 * - all variables must be binary
    3265 * - all coefficients must be integral
    3266 * - both sides must be infinite
    3267 */
    3268 if( upgrconshdlr != NULL && !created && (ncoeffspone + ncoeffsnone + ncoeffspint + ncoeffsnint == nvars) && SCIPisEQ(scip, *lhs, *rhs) )
    3269 {
    3270 SCIP_VAR** transvars;
    3271 SCIP_Longint* weights;
    3272 SCIP_Longint capacity;
    3273 SCIP_Longint weight;
    3274 int mult;
    3275
    3276 assert(!SCIPisInfinity(scip, *rhs));
    3277
    3278 SCIPdebugMsg(scip, "linear pseudoboolean constraint will be a equality-knapsack constraint\n");
    3279
    3280 /* get temporary memory */
    3281 SCIP_CALL( SCIPallocBufferArray(scip, &transvars, nvars) );
    3282 SCIP_CALL( SCIPallocBufferArray(scip, &weights, nvars) );
    3283
    3284 if( SCIPisPositive(scip, *rhs) )
    3285 {
    3286 mult = +1;
    3287 capacity = (SCIP_Longint)SCIPfeasFloor(scip, *rhs);
    3288 }
    3289 else
    3290 {
    3291 mult = -1;
    3292 capacity = (SCIP_Longint)SCIPfeasFloor(scip, -*rhs);
    3293 }
    3294
    3295 /* negate positive or negative variables for linear variables */
    3296 for( v = 0; v < nlinvars; ++v )
    3297 {
    3298 assert(SCIPisFeasIntegral(scip, linvals[v]));
    3299 weight = mult * (SCIP_Longint)SCIPfeasFloor(scip, linvals[v]);
    3300 if( weight > 0 )
    3301 {
    3302 transvars[v] = linvars[v];
    3303 weights[v] = weight;
    3304 }
    3305 else
    3306 {
    3307 SCIP_CALL( SCIPgetNegatedVar(scip, linvars[v], &transvars[v]) );
    3308 weights[v] = -weight;
    3309 capacity -= weight;
    3310 }
    3311 assert(transvars[v] != NULL);
    3312 }
    3313 /* negate positive or negative variables for and-resultants */
    3314 for( v = 0; v < nandress; ++v )
    3315 {
    3316 assert(SCIPisFeasIntegral(scip, andvals[v]));
    3317 weight = mult * (SCIP_Longint)SCIPfeasFloor(scip, andvals[v]);
    3318 if( weight > 0 )
    3319 {
    3320 transvars[nlinvars + v] = andress[v];
    3321 weights[nlinvars + v] = weight;
    3322 }
    3323 else
    3324 {
    3325 SCIP_CALL( SCIPgetNegatedVar(scip, andress[v], &transvars[nlinvars + v]) );
    3326 andnegs[v] = TRUE;
    3327 weights[nlinvars + v] = -weight;
    3328 capacity -= weight;
    3329 }
    3330 assert(transvars[nlinvars + v] != NULL);
    3331 }
    3332
    3333 /* create the constraint */
    3334 SCIP_CALL( SCIPcreateConsEqKnapsack(scip, &cons, name, nvars, transvars, weights, capacity,
    3335 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    3336
    3337 created = TRUE;
    3338 (*linconstype) = SCIP_LINEARCONSTYPE_EQKNAPSACK;
    3339
    3340 /* free temporary memory */
    3341 SCIPfreeBufferArray(scip, &weights);
    3342 SCIPfreeBufferArray(scip, &transvars);
    3343
    3344 *lhs = capacity;
    3345 *rhs = capacity;
    3346 }
    3347#endif
    3348 }
    3349 }
    3350
    3351 upgrconshdlr = SCIPfindConshdlr(scip, "linear");
    3352 assert(created || upgrconshdlr != NULL);
    3353
    3354 if( !created )
    3355 {
    3356 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, name, nlinvars, linvars, linvals, *lhs, *rhs,
    3357 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    3358
    3359 (*linconstype) = SCIP_LINEARCONSTYPE_LINEAR;
    3360
    3361 /* add all and-resultants */
    3362 for( v = 0; v < nandress; ++v )
    3363 {
    3364 assert(andress[v] != NULL);
    3365
    3366 /* add auxiliary variables to linear constraint */
    3367 SCIP_CALL( SCIPaddCoefLinear(scip, cons, andress[v], andvals[v]) );
    3368 }
    3369 }
    3370
    3371 assert(cons != NULL && *linconstype > SCIP_LINEARCONSTYPE_INVALIDCONS);
    3373 *lincons = cons;
    3374
    3375 /* @todo: add indicator variable */
    3376 /* add hard constraint */
    3377 if( !issoftcons )
    3378 {
    3379 SCIP_CALL( SCIPaddCons(scip, cons) );
    3380
    3381 /* mark linear constraint not to be upgraded - otherwise we loose control over it */
    3382 SCIPconsAddUpgradeLocks(cons, +1);
    3383 }
    3384
    3385 return SCIP_OKAY;
    3386}
    3387
    3388/** checks one original pseudoboolean constraint for feasibility of given solution */
    3389static
    3391 SCIP*const scip, /**< SCIP data structure */
    3392 SCIP_CONS*const cons, /**< pseudo boolean constraint */
    3393 SCIP_SOL*const sol, /**< solution to be checked, or NULL for current solution */
    3394 SCIP_Bool*const violated, /**< pointer to store whether the constraint is violated */
    3395 SCIP_Bool const printreason /**< should violation of constraint be printed */
    3396 )
    3397{
    3398 SCIP_CONSDATA* consdata;
    3399 SCIP_CONSHDLR* conshdlr;
    3400 SCIP_CONSHDLRDATA* conshdlrdata;
    3401
    3402 SCIP_VAR** vars;
    3403 SCIP_Real* coefs;
    3404 SCIP_Real lhs;
    3405 SCIP_Real rhs;
    3406 SCIP_Real activity;
    3407 int nvars;
    3408 int v;
    3409
    3410 SCIP_Real lhsviol;
    3411 SCIP_Real rhsviol;
    3412 SCIP_Real absviol;
    3413 SCIP_Real relviol;
    3414
    3415 assert(scip != NULL);
    3416 assert(cons != NULL);
    3417 assert(SCIPconsIsOriginal(cons));
    3418 assert(violated != NULL);
    3419
    3420 *violated = FALSE;
    3421
    3422 SCIPdebugMsg(scip, "checking original pseudo boolean constraint <%s>\n", SCIPconsGetName(cons));
    3424
    3425 consdata = SCIPconsGetData(cons);
    3426 assert(consdata != NULL);
    3427 assert(consdata->lincons != NULL);
    3428 assert(consdata->linconstype > SCIP_LINEARCONSTYPE_INVALIDCONS);
    3429 assert(SCIPconsIsOriginal(consdata->lincons));
    3430
    3431 /* gets number of variables in linear constraint */
    3432 SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
    3433
    3434 /* allocate temporary memory */
    3435 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    3436 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
    3437
    3438 /* get sides of linear constraint */
    3439 SCIP_CALL( getLinearConsSides(scip, consdata->lincons, consdata->linconstype, &lhs, &rhs) );
    3440 assert(!SCIPisInfinity(scip, lhs));
    3441 assert(!SCIPisInfinity(scip, -rhs));
    3442 assert(SCIPisLE(scip, lhs, rhs));
    3443
    3444 /* get variables and coefficient of linear constraint */
    3445 SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) );
    3446 assert(coefs != NULL || nvars == 0);
    3447
    3448 /* every variable in the linear constraint is either a linear variable or a term variable
    3449 * but there can be additional fixed or negation-paired and-resultants with relevant and-constraints
    3450 * whose values are already resolved in the linear constraint
    3451 */
    3452 assert(consdata->nlinvars + consdata->nconsanddatas >= nvars);
    3453
    3454 conshdlr = SCIPconsGetHdlr(cons);
    3455 assert(conshdlr != NULL);
    3456
    3457 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3458 assert(conshdlrdata != NULL);
    3459 assert(conshdlrdata->hashmap != NULL);
    3460
    3461 activity = 0.0;
    3462
    3463 /* compute pseudoboolean activity */
    3464 for( v = 0; v < nvars; ++v )
    3465 {
    3466 CONSANDDATA* consanddata = NULL;
    3467 SCIP_VAR* var = vars[v];
    3468 SCIP_Real solval;
    3469
    3470 /* find and-constraint to standard or negated and-resultant */
    3471 do
    3472 {
    3473 consanddata = (CONSANDDATA*)SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)var);
    3474
    3475 if( consanddata != NULL )
    3476 break;
    3477
    3478 var = var == vars[v] ? SCIPvarGetNegatedVar(var) : vars[v];
    3479 }
    3480 while( var != vars[v] );
    3481
    3482 /* get linear solution */
    3483 if( consanddata == NULL )
    3484 solval = SCIPgetSolVal(scip, sol, vars[v]);
    3485 /* get term solution */
    3486 else
    3487 {
    3488 SCIP_CONS* andcons = consanddata->origcons;
    3489 SCIP_VAR** andvars;
    3490 int nandvars;
    3491 int i;
    3492
    3493 /* use transformed constraint if no original constraint exists */
    3494 if( andcons == NULL )
    3495 andcons = consanddata->cons;
    3496
    3497 assert(SCIPgetResultantAnd(scip, andcons) == var);
    3498
    3499 andvars = SCIPgetVarsAnd(scip, andcons);
    3500 nandvars = SCIPgetNVarsAnd(scip, andcons);
    3501 assert(andvars != NULL || nandvars == 0);
    3502
    3503 solval = 1.0;
    3504
    3505 for( i = 0; i < nandvars; ++i )
    3506 solval *= SCIPgetSolVal(scip, sol, andvars[i]);
    3507
    3508 if( var != vars[v] )
    3509 solval = 1.0 - solval;
    3510 }
    3511
    3512 /* add activity contribution */
    3513 activity += coefs[v] * solval;
    3514 }
    3515
    3516 SCIPdebugMsg(scip, "lhs = %g, activity = %g, rhs = %g\n", lhs, activity, rhs);
    3517
    3518 /* calculate absolute and relative violation */
    3519 lhsviol = lhs - activity;
    3520 rhsviol = activity - rhs;
    3521
    3522 if(lhsviol > rhsviol)
    3523 {
    3524 absviol = lhsviol;
    3525 relviol = SCIPrelDiff(lhs, activity);
    3526 }
    3527 else
    3528 {
    3529 absviol = rhsviol;
    3530 relviol = SCIPrelDiff(activity, rhs);
    3531 }
    3532
    3533 /* update absolute and relative violation of the solution */
    3534 if( sol != NULL )
    3535 SCIPupdateSolConsViolation(scip, sol, absviol, relviol);
    3536
    3537 /* check left hand side for violation */
    3538 if( SCIPisFeasLT(scip, activity, lhs) )
    3539 {
    3540 if( printreason )
    3541 {
    3542 SCIP_CALL( SCIPprintCons(scip, cons, NULL ) );
    3543 SCIPinfoMessage(scip, NULL, ";\n");
    3544 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", lhs - activity);
    3545
    3546 /* print linear constraint in SCIP_DEBUG mode too */
    3547 SCIPdebugPrintCons(scip, SCIPconsGetData(cons)->lincons, NULL);
    3548 }
    3549
    3550 *violated = TRUE;
    3551 }
    3552
    3553 /* check right hand side for violation */
    3554 if( SCIPisFeasGT(scip, activity, rhs) )
    3555 {
    3556 if( printreason )
    3557 {
    3558 SCIP_CALL( SCIPprintCons(scip, cons, NULL ) );
    3559 SCIPinfoMessage(scip, NULL, ";\n");
    3560 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - rhs);
    3561 }
    3562
    3563 *violated = TRUE;
    3564 }
    3565
    3566 /* free temporary memory */
    3567 SCIPfreeBufferArray(scip, &coefs);
    3568 SCIPfreeBufferArray(scip, &vars);
    3569
    3570 return SCIP_OKAY;
    3571}
    3572
    3573/** checks all and-constraints inside the pseudoboolean constraint handler for feasibility of given solution or current
    3574 * solution
    3575 */
    3576static
    3578 SCIP*const scip, /**< SCIP data structure */
    3579 SCIP_CONSHDLR*const conshdlr, /**< pseudo boolean constraint handler */
    3580 SCIP_SOL*const sol, /**< solution to be checked, or NULL for current solution */
    3581 SCIP_Bool*const violated /**< pointer to store whether the constraint is violated */
    3582 )
    3583{
    3584 SCIP_CONSHDLRDATA* conshdlrdata;
    3585 SCIP_CONS* andcons;
    3586 SCIP_VAR** vars;
    3587 SCIP_VAR* res;
    3588 int nvars;
    3589 int c;
    3590 int v;
    3591
    3592 assert(scip != NULL);
    3593 assert(conshdlr != NULL);
    3594 assert(violated != NULL);
    3595
    3596 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3597 assert(conshdlrdata != NULL);
    3598
    3599 *violated = FALSE;
    3600
    3601 for( c = conshdlrdata->nallconsanddatas - 1; c >= 0; --c )
    3602 {
    3603 SCIP_Real solval;
    3604 SCIP_Real minsolval;
    3605 SCIP_Real sumsolval;
    3606 SCIP_Real viol;
    3607
    3608 if( !conshdlrdata->allconsanddatas[c]->istransformed )
    3609 continue;
    3610
    3611 andcons = conshdlrdata->allconsanddatas[c]->cons;
    3612
    3613 /* need to check even locally deleted constraints */
    3614 if( andcons == NULL ) /*|| !SCIPconsIsActive(andcons) )*/
    3615 continue;
    3616
    3617 vars = SCIPgetVarsAnd(scip, andcons);
    3618 nvars = SCIPgetNVarsAnd(scip, andcons);
    3619 assert(vars != NULL || nvars == 0);
    3620
    3621 res = SCIPgetResultantAnd(scip, andcons);
    3622 assert(res != NULL);
    3623
    3624 /* check if the and-constraint is violated */
    3625 minsolval = 1.0;
    3626 sumsolval = 0.0;
    3627 for( v = nvars - 1; v >= 0; --v )
    3628 {
    3629 solval = SCIPgetSolVal(scip, sol, vars[v]);
    3630
    3631 if( solval < minsolval )
    3632 minsolval = solval;
    3633
    3634 sumsolval += solval;
    3635 }
    3636
    3637 /* the resultant must be at most as large as every operator
    3638 * and at least as large as one minus the sum of negated operators
    3639 */
    3640 solval = SCIPgetSolVal(scip, sol, res);
    3641 viol = MAX3(0.0, solval - minsolval, sumsolval - (nvars - 1.0 + solval));
    3642
    3643 if( SCIPisFeasPositive(scip, viol) )
    3644 {
    3645 /* only reset constraint age if we are in enforcement */
    3646 if( sol == NULL )
    3647 {
    3648 SCIP_CALL( SCIPresetConsAge(scip, andcons) );
    3649 }
    3650
    3651 *violated = TRUE;
    3652 break;
    3653 }
    3654 else if( sol == NULL )
    3655 {
    3656 SCIP_CALL( SCIPincConsAge(scip, andcons) );
    3657 }
    3658 }
    3659
    3660 return SCIP_OKAY;
    3661}
    3662
    3663/** creates by copying and captures a linear constraint */
    3664static
    3666 SCIP*const targetscip, /**< target SCIP data structure */
    3667 SCIP_CONS** targetcons, /**< pointer to store the created target constraint */
    3668 SCIP*const sourcescip, /**< source SCIP data structure */
    3669 SCIP_CONS*const sourcecons, /**< source constraint which will be copied */
    3670 const char* name, /**< name of constraint */
    3671 SCIP_HASHMAP*const varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
    3672 * variables of the target SCIP */
    3673 SCIP_HASHMAP*const consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
    3674 * target constraints */
    3675 SCIP_Bool const initial, /**< should the LP relaxation of constraint be in the initial LP? */
    3676 SCIP_Bool const separate, /**< should the constraint be separated during LP processing? */
    3677 SCIP_Bool const enforce, /**< should the constraint be enforced during node processing? */
    3678 SCIP_Bool const check, /**< should the constraint be checked for feasibility? */
    3679 SCIP_Bool const propagate, /**< should the constraint be propagated during node processing? */
    3680 SCIP_Bool const local, /**< is constraint only valid locally? */
    3681 SCIP_Bool const modifiable, /**< is constraint modifiable (subject to column generation)? */
    3682 SCIP_Bool const dynamic, /**< is constraint subject to aging? */
    3683 SCIP_Bool const removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
    3684 SCIP_Bool const stickingatnode, /**< should the constraint always be kept at the node where it was added, even
    3685 * if it may be moved to a more global node? */
    3686 SCIP_Bool const global, /**< create a global or a local copy? */
    3687 SCIP_Bool*const valid /**< pointer to store if the copying was valid */
    3688 )
    3689{
    3690 SCIP_CONSDATA* sourceconsdata;
    3691 SCIP_CONS* sourcelincons;
    3692
    3693 assert(targetscip != NULL);
    3694 assert(targetcons != NULL);
    3695 assert(sourcescip != NULL);
    3696 assert(sourcecons != NULL);
    3697 assert(valid != NULL);
    3698
    3700
    3701 *valid = TRUE;
    3702
    3703 sourceconsdata = SCIPconsGetData(sourcecons);
    3704 assert(sourceconsdata != NULL);
    3705
    3706 /* get linear constraint */
    3707 sourcelincons = sourceconsdata->lincons;
    3708 assert(sourcelincons != NULL);
    3709
    3710 /* get copied version of linear constraint */
    3711 if( !SCIPconsIsDeleted(sourcelincons) )
    3712 {
    3713 SCIP_CONSHDLR* conshdlrlinear;
    3714 SCIP_CONS* targetlincons;
    3715 SCIP_CONS** targetandconss;
    3716 SCIP_Real* targetandcoefs;
    3717 int ntargetandconss;
    3718 SCIP_LINEARCONSTYPE targetlinconstype;
    3719
    3720 targetlinconstype = sourceconsdata->linconstype;
    3721
    3722 switch( targetlinconstype )
    3723 {
    3725 conshdlrlinear = SCIPfindConshdlr(sourcescip, "linear");
    3726 assert(conshdlrlinear != NULL);
    3727 break;
    3729 conshdlrlinear = SCIPfindConshdlr(sourcescip, "logicor");
    3730 assert(conshdlrlinear != NULL);
    3731 break;
    3733 conshdlrlinear = SCIPfindConshdlr(sourcescip, "knapsack");
    3734 assert(conshdlrlinear != NULL);
    3735 break;
    3737 conshdlrlinear = SCIPfindConshdlr(sourcescip, "setppc");
    3738 assert(conshdlrlinear != NULL);
    3739 break;
    3740#ifdef WITHEQKNAPSACK
    3741 case SCIP_LINEARCONSTYPE_EQKNAPSACK:
    3742 conshdlrlinear = SCIPfindConshdlr(sourcescip, "eqknapsack");
    3743 assert(conshdlrlinear != NULL);
    3744 break;
    3745#endif
    3747 default:
    3748 SCIPerrorMessage("unknown linear constraint type\n");
    3749 return SCIP_INVALIDDATA;
    3750 }
    3751
    3752 if( conshdlrlinear == NULL ) /*lint !e774*/
    3753 {
    3754 SCIPerrorMessage("linear constraint handler not found\n");
    3755 return SCIP_INVALIDDATA;
    3756 }
    3757
    3758 targetlincons = NULL;
    3759
    3760 /* copy linear constraint */
    3761 SCIP_CALL( SCIPgetConsCopy(sourcescip, targetscip, sourcelincons, &targetlincons, conshdlrlinear, varmap, consmap, SCIPconsGetName(sourcelincons),
    3762 SCIPconsIsInitial(sourcelincons), SCIPconsIsSeparated(sourcelincons), SCIPconsIsEnforced(sourcelincons), SCIPconsIsChecked(sourcelincons),
    3763 SCIPconsIsPropagated(sourcelincons), SCIPconsIsLocal(sourcelincons), SCIPconsIsModifiable(sourcelincons), SCIPconsIsDynamic(sourcelincons),
    3764 SCIPconsIsRemovable(sourcelincons), SCIPconsIsStickingAtNode(sourcelincons), global, valid) );
    3765
    3766 if( *valid )
    3767 {
    3768 assert(targetlincons != NULL);
    3769 assert(SCIPconsGetHdlr(targetlincons) != NULL);
    3770 /* @note due to copying special linear constraints, now leads only to simple linear constraints, we check that
    3771 * our target constraint handler is the same as our source constraint handler of the linear constraint,
    3772 * if copying was not valid
    3773 */
    3774 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(targetlincons)), "linear") == 0 )
    3775 targetlinconstype = SCIP_LINEARCONSTYPE_LINEAR;
    3776 }
    3777
    3778 targetandconss = NULL;
    3779 targetandcoefs = NULL;
    3780 ntargetandconss = 0;
    3781
    3782 if( *valid )
    3783 {
    3784 SCIP_CONSHDLR* conshdlrand;
    3785 int c;
    3786 int nsourceandconss;
    3787 SCIP_HASHTABLE* linconsvarsmap;
    3788 SCIP_VAR** targetlinvars;
    3789 SCIP_Real* targetlincoefs;
    3790 int ntargetlinvars;
    3791
    3792 conshdlrand = SCIPfindConshdlr(sourcescip, "and");
    3793 assert(conshdlrand != NULL);
    3794
    3795 nsourceandconss = sourceconsdata->nconsanddatas;
    3796
    3797 /* allocate temporary memory */
    3798 SCIP_CALL( SCIPallocBufferArray(sourcescip, &targetandconss, nsourceandconss) );
    3799 SCIP_CALL( SCIPallocBufferArray(sourcescip, &targetandcoefs, nsourceandconss) );
    3800
    3801 /* get the number of vars in the copied linear constraint and allocate buffers
    3802 * for the variables and the coefficients
    3803 */
    3804 SCIP_CALL( getLinearConsNVars(targetscip, targetlincons, targetlinconstype, &ntargetlinvars) );
    3805 SCIP_CALL( SCIPallocBufferArray(sourcescip, &targetlinvars, ntargetlinvars) );
    3806 SCIP_CALL( SCIPallocBufferArray(sourcescip, &targetlincoefs, ntargetlinvars) );
    3807
    3808 /* retrieve the variables of the copied linear constraint */
    3809 SCIP_CALL( getLinearConsVarsData(targetscip, targetlincons, targetlinconstype,
    3810 targetlinvars, targetlincoefs, &ntargetlinvars) );
    3811
    3812 /* now create a hashtable and insert the variables into it, so that it
    3813 * can be checked in constant time if a variable was removed due to
    3814 * compressed copying when looping over the and resultants
    3815 */
    3816 SCIP_CALL( SCIPhashtableCreate(&linconsvarsmap, SCIPblkmem(targetscip), ntargetlinvars, SCIPvarGetHashkey,
    3817 SCIPvarIsHashkeyEq, SCIPvarGetHashkeyVal, NULL) );
    3818
    3819 for( c = 0 ; c < ntargetlinvars; ++c )
    3820 {
    3821 SCIP_CALL( SCIPhashtableInsert(linconsvarsmap, targetlinvars[c]) );
    3822 }
    3823
    3824 /* free the buffer arrays that were only required for building the hastable */
    3825 SCIPfreeBufferArray(sourcescip, &targetlincoefs);
    3826 SCIPfreeBufferArray(sourcescip, &targetlinvars);
    3827
    3828 for( c = 0 ; c < nsourceandconss; ++c )
    3829 {
    3830 CONSANDDATA* consanddata;
    3831 SCIP_CONS* oldcons;
    3832 SCIP_VAR* targetandresultant;
    3833 SCIP_Bool validand;
    3834
    3835 consanddata = sourceconsdata->consanddatas[c];
    3836 assert(consanddata != NULL);
    3837 oldcons = SCIPconsIsOriginal(sourcecons) ? consanddata->origcons : consanddata->cons;
    3838 targetandresultant = (SCIP_VAR*) SCIPhashmapGetImage(varmap, SCIPgetResultantAnd(sourcescip, oldcons));
    3839
    3840 /* if compressed copying is active, the resultant might have been fixed or not required by the linear
    3841 * constraint so that we do not need to add it to the pseudo boolean constraint in these cases
    3842 */
    3843 if( targetandresultant == NULL || !SCIPhashtableExists(linconsvarsmap, targetandresultant) )
    3844 continue;
    3845
    3846 validand = TRUE;
    3847
    3848 targetandconss[ntargetandconss] = NULL;
    3849
    3850 /* copy and-constraints */
    3851 SCIP_CALL( SCIPgetConsCopy(sourcescip, targetscip, oldcons, &targetandconss[ntargetandconss], conshdlrand, varmap, consmap, SCIPconsGetName(oldcons),
    3852 SCIPconsIsInitial(oldcons), SCIPconsIsSeparated(oldcons), SCIPconsIsEnforced(oldcons), SCIPconsIsChecked(oldcons),
    3853 SCIPconsIsPropagated(oldcons), SCIPconsIsLocal(oldcons), SCIPconsIsModifiable(oldcons), SCIPconsIsDynamic(oldcons),
    3854 SCIPconsIsRemovable(oldcons), SCIPconsIsStickingAtNode(oldcons), global, &validand) );
    3855
    3856 *valid &= validand;
    3857
    3858 if( validand )
    3859 {
    3860 targetandcoefs[ntargetandconss] = sourceconsdata->andcoefs[c];
    3861 ++ntargetandconss;
    3862 }
    3863 }
    3864
    3865 SCIPhashtableFree(&linconsvarsmap);
    3866 assert(ntargetandconss <= ntargetlinvars);
    3867 }
    3868
    3869 if( *valid )
    3870 {
    3871 SCIP_Real targetrhs;
    3872 SCIP_Real targetlhs;
    3873
    3874 SCIP_VAR* indvar;
    3875 const char* consname;
    3876
    3877 /* third the indicator and artificial integer variable part */
    3878 assert(sourceconsdata->issoftcons == (sourceconsdata->indvar != NULL));
    3879 indvar = sourceconsdata->indvar;
    3880
    3881 /* copy indicator variable */
    3882 if( indvar != NULL )
    3883 {
    3884 assert(*valid);
    3885 SCIP_CALL( SCIPgetVarCopy(sourcescip, targetscip, indvar, &indvar, varmap, consmap, global, valid) );
    3886 assert(!(*valid) || indvar != NULL);
    3887 }
    3888
    3889 if( *valid )
    3890 {
    3891 if( name != NULL )
    3892 consname = name;
    3893 else
    3894 consname = SCIPconsGetName(sourcecons);
    3895
    3896 /* get new left and right hand sides of copied linear constraint since
    3897 * they might have changed if compressed copying is used
    3898 */
    3899 SCIP_CALL( getLinearConsSides(targetscip, targetlincons, targetlinconstype, &targetlhs, &targetrhs) );
    3900
    3901 /* create new pseudoboolean constraint */
    3902 /* coverity[var_deref_op] */
    3903 /* coverity[var_deref_model] */
    3904 /* Note that due to compression the and constraints might have disappeared in which case ntargetandconss == 0. */
    3905 SCIP_CALL( SCIPcreateConsPseudobooleanWithConss(targetscip, targetcons, consname, targetlincons,
    3906 targetlinconstype, targetandconss, targetandcoefs, ntargetandconss, indvar, sourceconsdata->weight,
    3907 sourceconsdata->issoftcons, targetlhs, targetrhs, initial, separate, enforce, check, propagate,
    3908 local, modifiable, dynamic, removable, stickingatnode) );
    3909 }
    3910 }
    3911
    3912 if( !(*valid) && !SCIPisConsCompressionEnabled(sourcescip) )
    3913 {
    3914 SCIPverbMessage(sourcescip, SCIP_VERBLEVEL_MINIMAL, NULL, "could not copy constraint <%s>\n", SCIPconsGetName(sourcecons));
    3915 }
    3916
    3917 /* release copied linear constraint */
    3918 if( targetlincons != NULL )
    3919 {
    3920 SCIP_CALL( SCIPreleaseCons(targetscip, &targetlincons) );
    3921 }
    3922
    3923 /* release copied and constraint */
    3924 if( targetandconss != NULL )
    3925 {
    3926 int c;
    3927
    3928 assert(ntargetandconss <= sourceconsdata->nconsanddatas);
    3929
    3930 for( c = 0 ; c < ntargetandconss; ++c )
    3931 {
    3932 if( targetandconss[c] != NULL )
    3933 {
    3934 SCIP_CALL( SCIPreleaseCons(targetscip, &targetandconss[c]) );
    3935 }
    3936 }
    3937 }
    3938
    3939 /* free temporary memory */
    3940 SCIPfreeBufferArrayNull(sourcescip, &targetandcoefs);
    3941 SCIPfreeBufferArrayNull(sourcescip, &targetandconss);
    3942 }
    3943 else
    3944 *valid = FALSE;
    3945
    3946 return SCIP_OKAY;
    3947}
    3948
    3949/** compute all changes in consanddatas array */
    3950static
    3952 SCIP*const scip, /**< SCIP data structure */
    3953 SCIP_CONSHDLRDATA*const conshdlrdata /**< pseudoboolean constraint handler data */
    3954 )
    3955{
    3956 CONSANDDATA** allconsanddatas;
    3957 CONSANDDATA* consanddata;
    3958 int c;
    3959
    3960 assert(scip != NULL);
    3961 assert(conshdlrdata != NULL);
    3962
    3963 allconsanddatas = conshdlrdata->allconsanddatas;
    3964 assert(allconsanddatas != NULL);
    3965 assert(conshdlrdata->nallconsanddatas >= 0);
    3966 assert(conshdlrdata->nallconsanddatas <= conshdlrdata->sallconsanddatas);
    3967
    3968 for( c = conshdlrdata->nallconsanddatas - 1; c >= 0; --c )
    3969 {
    3970 SCIP_CONS* cons;
    3971 SCIP_VAR** vars;
    3972 int nvars;
    3973 SCIP_VAR** newvars;
    3974 int nnewvars;
    3975 int v;
    3976
    3977 consanddata = allconsanddatas[c];
    3978
    3979 if( !consanddata->istransformed )
    3980 continue;
    3981
    3982 if( consanddata->nuses == 0 )
    3983 continue;
    3984
    3985 vars = consanddata->vars;
    3986 nvars = consanddata->nvars;
    3987 assert(vars != NULL || nvars == 0);
    3988 assert(consanddata->nnewvars == 0 && ((consanddata->snewvars > 0) == (consanddata->newvars != NULL)));
    3989
    3990 if( nvars == 0 )
    3991 {
    3992#ifndef NDEBUG
    3993 /* if an old consanddata-object has no variables left there should be no new variables */
    3994 if( consanddata->cons != NULL )
    3995 assert(SCIPgetNVarsAnd(scip, consanddata->cons) == 0);
    3996#endif
    3997 continue;
    3998 }
    3999
    4000 cons = consanddata->cons;
    4001 assert(cons != NULL);
    4002
    4003 if( SCIPconsIsDeleted(cons) )
    4004 continue;
    4005
    4006 /* sort and-variables */
    4007 if( !SCIPisAndConsSorted(scip, consanddata->cons) )
    4008 {
    4009 SCIP_CALL( SCIPsortAndCons(scip, consanddata->cons) );
    4010 assert(SCIPisAndConsSorted(scip, consanddata->cons));
    4011 }
    4012
    4013 /* get new and-variables */
    4014 nnewvars = SCIPgetNVarsAnd(scip, consanddata->cons);
    4015 newvars = SCIPgetVarsAnd(scip, consanddata->cons);
    4016
    4017 /* stop if the constraint has no variables or there was an error (coverity issue) */
    4018 if( nnewvars <= 0 )
    4019 continue;
    4020
    4021#ifndef NDEBUG
    4022 /* check that old variables are sorted */
    4023 for( v = nvars - 1; v > 0; --v )
    4024 assert(SCIPvarGetIndex(vars[v]) >= SCIPvarGetIndex(vars[v - 1]));
    4025 /* check that new variables are sorted */
    4026 for( v = nnewvars - 1; v > 0; --v )
    4027 assert(SCIPvarGetIndex(newvars[v]) >= SCIPvarGetIndex(newvars[v - 1]));
    4028#endif
    4029
    4030 /* check for changings, if and-constraint did not change we do not need to copy all variables */
    4031 if( nvars == nnewvars )
    4032 {
    4033 SCIP_Bool changed;
    4034
    4035 changed = FALSE;
    4036
    4037 /* check each variable */
    4038 for( v = nvars - 1; v >= 0; --v )
    4039 {
    4040 if( vars[v] != newvars[v] )
    4041 {
    4042 changed = TRUE;
    4043 break;
    4044 }
    4045 }
    4046
    4047 if( !changed )
    4048 continue;
    4049 }
    4050
    4051 /* resize newvars array if necessary */
    4052 if( nnewvars > consanddata->snewvars )
    4053 {
    4054 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &(consanddata->newvars), &(consanddata->snewvars), nnewvars) );
    4055 }
    4056
    4057 /* copy all variables */
    4058 BMScopyMemoryArray(consanddata->newvars, newvars, nnewvars);
    4059 consanddata->nnewvars = nnewvars;
    4060
    4061 /* capture all variables */
    4062 for( v = consanddata->nnewvars - 1; v >= 0; --v )
    4063 {
    4064 /* in original problem the variables was already deleted */
    4065 assert(consanddata->newvars[v] != NULL);
    4066 SCIP_CALL( SCIPcaptureVar(scip, consanddata->newvars[v]) );
    4067 }
    4068 }
    4069
    4070 return SCIP_OKAY;
    4071}
    4072
    4073/** remove old locks */
    4074static
    4076 SCIP*const scip, /**< SCIP data structure */
    4077 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    4078 CONSANDDATA*const consanddata, /**< CONSANDDATA object for which we want to delete the locks and the
    4079 * capture of the corresponding and-constraint */
    4080 SCIP_Real const coef, /**< coefficient which led to old locks */
    4081 SCIP_Real const lhs, /**< left hand side which led to old locks */
    4082 SCIP_Real const rhs /**< right hand side which led to old locks */
    4083 )
    4084{
    4085 assert(scip != NULL);
    4086 assert(cons != NULL);
    4087 assert(consanddata != NULL);
    4088 assert(!SCIPisInfinity(scip, coef) && !SCIPisInfinity(scip, -coef));
    4089 assert(!SCIPisInfinity(scip, lhs));
    4090 assert(!SCIPisInfinity(scip, -rhs));
    4091 assert(SCIPisLE(scip, lhs, rhs));
    4092
    4093 /* remove rounding locks */
    4094 SCIP_CALL( unlockRoundingAndCons(scip, cons, consanddata, coef, lhs, rhs) );
    4095
    4096 assert(consanddata->cons != NULL);
    4097
    4098 return SCIP_OKAY;
    4099}
    4100
    4101/** add new locks */
    4102static
    4104 SCIP*const scip, /**< SCIP data structure */
    4105 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    4106 CONSANDDATA*const consanddata, /**< CONSANDDATA object for which we want to delete the locks and the
    4107 * capture of the corresponding and-constraint */
    4108 SCIP_Real const coef, /**< coefficient which lead to new locks */
    4109 SCIP_Real const lhs, /**< left hand side which lead to new locks */
    4110 SCIP_Real const rhs /**< right hand side which lead to new locks */
    4111 )
    4112{
    4113 assert(scip != NULL);
    4114 assert(cons != NULL);
    4115 assert(consanddata != NULL);
    4116 assert(!SCIPisInfinity(scip, coef) && !SCIPisInfinity(scip, -coef));
    4117 assert(!SCIPisInfinity(scip, lhs));
    4118 assert(!SCIPisInfinity(scip, -rhs));
    4119 assert(SCIPisLE(scip, lhs, rhs));
    4120
    4121 /* add rounding locks due to old variables in consanddata object */
    4122 SCIP_CALL( lockRoundingAndCons(scip, cons, consanddata, coef, lhs, rhs) );
    4123
    4124 assert(consanddata->cons != NULL);
    4125
    4126 return SCIP_OKAY;
    4127}
    4128
    4129/** update all locks inside this constraint and all captures on all and-constraints */
    4130static
    4132 SCIP*const scip, /**< SCIP data structure */
    4133 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    4134 SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
    4135 SCIP_Real const newlhs, /**< new left hand side of pseudoboolean constraint */
    4136 SCIP_Real const newrhs, /**< new right hand side of pseudoboolean constraint */
    4137 SCIP_VAR**const andress, /**< new and-resultants in pseudoboolean constraint */
    4138 SCIP_Real*const andcoefs, /**< new and-resultants-coeffcients in pseudoboolean constraint */
    4139 SCIP_Bool*const andnegs, /**< new negation status of and-resultants in pseudoboolean constraint */
    4140 int const nandress /**< number of current and-resultants in pseudoboolean constraint */
    4141 )
    4142{
    4143 CONSANDDATA** newconsanddatas;
    4144 int nnewconsanddatas;
    4145 int snewconsanddatas;
    4146 SCIP_Real* newandcoefs;
    4147 SCIP_Real* oldandcoefs;
    4148 SCIP_Bool* newandnegs;
    4149 SCIP_Bool* oldandnegs;
    4150 CONSANDDATA** consanddatas;
    4151 int nconsanddatas;
    4152 SCIP_CONSDATA* consdata;
    4153 int oldnvars;
    4154 int c;
    4155 int c1;
    4156
    4157 assert(scip != NULL);
    4158 assert(cons != NULL);
    4159 assert(conshdlrdata != NULL);
    4160 assert(conshdlrdata->hashmap != NULL);
    4161 assert(andress != NULL || nandress == 0);
    4162 assert(andcoefs != NULL || nandress == 0);
    4163 assert(!SCIPisInfinity(scip, newlhs));
    4164 assert(!SCIPisInfinity(scip, -newrhs));
    4165 assert(SCIPisLE(scip, newlhs, newrhs));
    4166
    4167 consdata = SCIPconsGetData(cons);
    4168 assert(consdata != NULL);
    4169
    4170 /* sort and-constraints by the problem indices of corresponding and-resultants */
    4171 SCIPsortPtrRealBool((void**)(consdata->consanddatas), consdata->andcoefs, consdata->andnegs, resvarCompWithInactive, consdata->nconsanddatas);
    4172
    4173 /* sort and-resultants by their problem indices */
    4174 SCIPsortPtrRealBool((void**)andress, andcoefs, andnegs, resvarComp, nandress);
    4175
    4176 consanddatas = consdata->consanddatas;
    4177 oldandcoefs = consdata->andcoefs;
    4178 oldandnegs = consdata->andnegs;
    4179 nconsanddatas = consdata->nconsanddatas;
    4180 assert(consanddatas != NULL || nconsanddatas == 0);
    4181 assert(oldandcoefs != NULL || nconsanddatas == 0);
    4182
    4183 snewconsanddatas = nconsanddatas + nandress;
    4184
    4185 /* allocate new block memory arrays */
    4186 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &newconsanddatas, snewconsanddatas) );
    4187 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &newandcoefs, snewconsanddatas) );
    4188 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &newandnegs, snewconsanddatas) );
    4189
    4190 nnewconsanddatas = 0;
    4191
    4192 /* collect new consanddata objects and update locks and captures */
    4193 for( c = 0, c1 = 0; c < nconsanddatas && c1 < nandress; )
    4194 {
    4195 SCIP_CONS* andcons;
    4196 SCIP_VAR* res1;
    4197 SCIP_VAR* res2;
    4198 int compval;
    4199
    4200 assert(consanddatas[c] != NULL);
    4201
    4202 /* consanddata object could have been deleted in the last presolving round */
    4203 if( !consanddatas[c]->istransformed )
    4204 {
    4205 ++c;
    4206 consdata->changed = TRUE;
    4207 consdata->upgradetried = FALSE;
    4208 continue;
    4209 }
    4210
    4211 andcons = consanddatas[c]->cons;
    4212 assert(andcons != NULL);
    4213
    4214 if( andcons == NULL ) /*lint !e774*/
    4215 {
    4216 ++c;
    4217 consdata->changed = TRUE;
    4218 consdata->upgradetried = FALSE;
    4219 continue;
    4220 }
    4221 else if( SCIPconsIsDeleted(andcons) )
    4222 {
    4223 /* remove rounding locks, because the and constraint was deleted */
    4224 SCIP_CALL( unlockRoundingAndCons(scip, cons, consanddatas[c],
    4225 oldandnegs[c] ? -oldandcoefs[c] : oldandcoefs[c], consdata->lhs, consdata->rhs) );
    4226 ++c;
    4227 consdata->changed = TRUE;
    4228 consdata->upgradetried = FALSE;
    4229 continue;
    4230 }
    4231 assert(andcons != NULL);
    4232
    4233 /* get and-resultants of consanddata object in constraint data */
    4234 res1 = SCIPgetResultantAnd(scip, andcons);
    4235 assert(res1 != NULL);
    4236 assert(SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res1) == consanddatas[c]);
    4237
    4238 /* get and-resultants in new corresponding linear constraint */
    4239 res2 = andress[c1];
    4240 assert(res2 != NULL);
    4241 assert(SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res2) != NULL);
    4242
    4243 /* get comparison value */
    4244 compval = resvarComp((void*)res1, (void*)res2);
    4245
    4246 /* collect new consanddata objects sorted with respect to the problem index of corresponding and-resultants */
    4247 if( compval == -1 )
    4248 {
    4249 assert(!SCIPisZero(scip, oldandcoefs[c]));
    4250 assert(consanddatas[c]->nuses > 0);
    4251 --(consanddatas[c]->nuses);
    4252
    4253 /* remove old locks */
    4254 SCIP_CALL( removeOldLocks(scip, cons, consanddatas[c], oldandnegs[c] ? -oldandcoefs[c] : oldandcoefs[c],
    4255 consdata->lhs, consdata->rhs) );
    4256 ++c;
    4257 consdata->changed = TRUE;
    4258 consdata->upgradetried = FALSE;
    4259 consdata->propagated = FALSE;
    4260 consdata->presolved = FALSE;
    4261 }
    4262 else if( compval == +1 )
    4263 {
    4264 assert(!SCIPisZero(scip, andcoefs[c1]));
    4265 assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)res2));
    4266 newconsanddatas[nnewconsanddatas] = (CONSANDDATA*) SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res2);
    4267 newandcoefs[nnewconsanddatas] = andcoefs[c1];
    4268 newandnegs[nnewconsanddatas] = andnegs[c1];
    4269 ++(newconsanddatas[nnewconsanddatas]->nuses);
    4270
    4271 /* add new locks */
    4272 SCIP_CALL( addNewLocks(scip, cons, newconsanddatas[nnewconsanddatas], newandnegs[nnewconsanddatas] ?
    4273 -newandcoefs[nnewconsanddatas] : newandcoefs[nnewconsanddatas], newlhs, newrhs) );
    4274 ++c1;
    4275 consdata->changed = TRUE;
    4276 consdata->upgradetried = FALSE;
    4277 consdata->cliquesadded = FALSE;
    4278 consdata->propagated = FALSE;
    4279 consdata->presolved = FALSE;
    4280
    4281 ++nnewconsanddatas;
    4282 }
    4283 else
    4284 {
    4285 SCIP_Bool coefsignchanged;
    4286 SCIP_Bool lhschanged;
    4287 SCIP_Bool rhschanged;
    4288
    4289 assert(!SCIPisZero(scip, oldandcoefs[c]));
    4290 assert(!SCIPisZero(scip, andcoefs[c1]));
    4291 assert(SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res2) == consanddatas[c]);
    4292
    4293 /* copy old consanddata object and new coefficent */
    4294 newconsanddatas[nnewconsanddatas] = consanddatas[c];
    4295
    4296 newandcoefs[nnewconsanddatas] = andcoefs[c1];
    4297 newandnegs[nnewconsanddatas] = andnegs[c1];
    4298
    4299 if( ((oldandnegs[c] == andnegs[c1]) && !SCIPisEQ(scip, oldandcoefs[c], newandcoefs[c1]))
    4300 || ((oldandnegs[c] != newandnegs[c1]) && !SCIPisEQ(scip, oldandcoefs[c], -newandcoefs[c1])) )
    4301 consdata->upgradetried = FALSE;
    4302
    4303 coefsignchanged = (oldandnegs[c] == andnegs[c1]) &&
    4304 ((oldandcoefs[c] < 0 && andcoefs[c1] > 0) || (oldandcoefs[c] > 0 && andcoefs[c1] < 0));
    4305 coefsignchanged = coefsignchanged || ((oldandnegs[c] != andnegs[c1]) &&
    4306 ((oldandcoefs[c] < 0 && andcoefs[c1] < 0) || (oldandcoefs[c] > 0 && andcoefs[c1] > 0)));
    4307 lhschanged = (SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -newlhs)) || (!SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -newlhs))
    4308 || (consdata->lhs < 0 && newlhs > 0) || (consdata->lhs > 0 && newlhs < 0);
    4309 rhschanged = (SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, newrhs)) || (!SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, newrhs))
    4310 || (consdata->rhs < 0 && newrhs > 0) || (consdata->rhs > 0 && newrhs < 0);
    4311
    4312 /* update or renew locks */
    4313 if( coefsignchanged || lhschanged || rhschanged || newconsanddatas[nnewconsanddatas]->nnewvars > 0)
    4314 {
    4315 /* renew locks */
    4316 SCIP_CALL( removeOldLocks(scip, cons, newconsanddatas[nnewconsanddatas], oldandnegs[c] ?
    4317 -oldandcoefs[c] : oldandcoefs[c], consdata->lhs, consdata->rhs) );
    4318 SCIP_CALL( addNewLocks(scip, cons, newconsanddatas[nnewconsanddatas], newandnegs[nnewconsanddatas] ?
    4319 -newandcoefs[nnewconsanddatas] : newandcoefs[nnewconsanddatas], newlhs, newrhs) );
    4320
    4321 consdata->changed = TRUE;
    4322 consdata->upgradetried = FALSE;
    4323 consdata->cliquesadded = FALSE;
    4324 consdata->propagated = FALSE;
    4325 consdata->presolved = FALSE;
    4326 }
    4327
    4328 ++c;
    4329 ++c1;
    4330 ++nnewconsanddatas;
    4331 }
    4332 }
    4333
    4334 /* add all remaining consanddatas and update locks and captures */
    4335 if( c < nconsanddatas )
    4336 {
    4337 assert(c1 == nandress);
    4338
    4339 for( ; c < nconsanddatas; ++c )
    4340 {
    4341 SCIP_CONS* andcons;
    4342#ifndef NDEBUG
    4343 SCIP_VAR* res1;
    4344
    4345 assert(consanddatas[c] != NULL);
    4346#endif
    4347 andcons = consanddatas[c]->cons;
    4348#ifndef NDEBUG
    4349 if( andcons != NULL )
    4350 {
    4351 res1 = SCIPgetResultantAnd(scip, andcons);
    4352 assert(res1 != NULL);
    4353 assert(SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res1) == consanddatas[c]);
    4354 }
    4355#endif
    4356 if( andcons == NULL )
    4357 {
    4358 consdata->changed = TRUE;
    4359 consdata->upgradetried = FALSE;
    4360 continue;
    4361 }
    4362
    4363 assert(consanddatas[c]->nuses > 0);
    4364 --(consanddatas[c]->nuses);
    4365
    4366 /* remove old locks */
    4367 SCIP_CALL( removeOldLocks(scip, cons, consanddatas[c], oldandnegs[c] ? -oldandcoefs[c] : oldandcoefs[c],
    4368 consdata->lhs, consdata->rhs) );
    4369 consdata->changed = TRUE;
    4370 consdata->upgradetried = FALSE;
    4371 consdata->propagated = FALSE;
    4372 consdata->presolved = FALSE;
    4373 }
    4374 }
    4375 else if( c1 < nandress )
    4376 {
    4377 for( ; c1 < nandress; ++c1 )
    4378 {
    4379 SCIP_VAR* res2;
    4380
    4381 res2 = andress[c1];
    4382 assert(res2 != NULL);
    4383 assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)res2));
    4384 newconsanddatas[nnewconsanddatas] = (CONSANDDATA*) SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res2);
    4385 newandcoefs[nnewconsanddatas] = andcoefs[c1];
    4386 newandnegs[nnewconsanddatas] = andnegs[c1];
    4387 ++(newconsanddatas[nnewconsanddatas]->nuses);
    4388
    4389 /* add new locks */
    4390 SCIP_CALL( addNewLocks(scip, cons, newconsanddatas[nnewconsanddatas], newandnegs[nnewconsanddatas] ?
    4391 -newandcoefs[nnewconsanddatas] : newandcoefs[nnewconsanddatas], newlhs, newrhs) );
    4392
    4393 ++nnewconsanddatas;
    4394 consdata->changed = TRUE;
    4395 consdata->upgradetried = FALSE;
    4396 consdata->cliquesadded = FALSE;
    4397 consdata->propagated = FALSE;
    4398 consdata->presolved = FALSE;
    4399 }
    4400 }
    4401 assert(c == nconsanddatas && c1 == nandress);
    4402
    4403 /* delete old and-coefficients and consanddata objects */
    4404 SCIPfreeBlockMemoryArray(scip, &(consdata->andcoefs), consdata->sconsanddatas);
    4405 SCIPfreeBlockMemoryArray(scip, &(consdata->andnegs), consdata->sconsanddatas);
    4406 SCIPfreeBlockMemoryArray(scip, &(consdata->consanddatas), consdata->sconsanddatas);
    4407
    4408 if( !SCIPisEQ(scip, consdata->lhs, newlhs) || !SCIPisEQ(scip, consdata->rhs, newrhs) )
    4409 {
    4410 consdata->upgradetried = FALSE;
    4411 consdata->lhs = newlhs;
    4412 consdata->rhs = newrhs;
    4413 }
    4414
    4415 consdata->consanddatas = newconsanddatas;
    4416 consdata->andcoefs = newandcoefs;
    4417 consdata->andnegs = newandnegs;
    4418 consdata->nconsanddatas = nnewconsanddatas;
    4419 consdata->sconsanddatas = snewconsanddatas;
    4420
    4421 oldnvars = consdata->nlinvars;
    4422 /* update number of linear variables without and-resultants */
    4423 SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &(consdata->nlinvars)) );
    4424 consdata->nlinvars -= nnewconsanddatas;
    4425
    4426 if( oldnvars != consdata->nlinvars )
    4427 {
    4428 consdata->changed = TRUE;
    4429 consdata->upgradetried = FALSE;
    4430 consdata->cliquesadded = FALSE;
    4431 consdata->propagated = FALSE;
    4432 consdata->presolved = FALSE;
    4433 }
    4434
    4435#ifndef NDEBUG
    4436 consanddatas = consdata->consanddatas;
    4437 nconsanddatas = consdata->nconsanddatas;
    4438 assert(consanddatas != NULL || nconsanddatas == 0);
    4439
    4440 /* check that consanddata objects are sorted with respect to the problem index of the corresponding resultants */
    4441 for( c = nconsanddatas - 1; c > 0; --c )
    4442 {
    4443 SCIP_VAR* res1;
    4444 SCIP_VAR* res2;
    4445 SCIP_Bool resneg1;
    4446 SCIP_Bool resneg2;
    4447 int resind1;
    4448 int resind2;
    4449
    4450 assert(consanddatas[c] != NULL);
    4451 assert(consanddatas[c]->cons != NULL);
    4452 res1 = SCIPgetResultantAnd(scip, consanddatas[c]->cons);
    4453 assert(res1 != NULL);
    4454 assert(consanddatas[c - 1] != NULL);
    4455 assert(consanddatas[c - 1]->cons != NULL);
    4456 res2 = SCIPgetResultantAnd(scip, consanddatas[c - 1]->cons);
    4457 assert(res2 != NULL);
    4458 resneg1 = SCIPvarIsNegated(res1);
    4459 if( resneg1 )
    4460 {
    4461 res1 = SCIPvarGetNegatedVar(res1);
    4462 assert(res1 != NULL);
    4463 }
    4464 resneg2 = SCIPvarIsNegated(res2);
    4465 if( resneg2 )
    4466 {
    4467 res2 = SCIPvarGetNegatedVar(res2);
    4468 assert(res2 != NULL);
    4469 }
    4470 resind1 = SCIPvarGetProbindex(res1);
    4471 resind2 = SCIPvarGetProbindex(res2);
    4472 if( resind1 == -1 && resind2 == -1 )
    4473 {
    4474 resind1 = SCIPvarGetIndex(res1);
    4475 resind2 = SCIPvarGetIndex(res2);
    4476 }
    4477
    4478 if( resind1 <= resind2 )
    4479 {
    4480 assert(resind1 == resind2);
    4481 assert(!resneg1);
    4482 assert(resneg2);
    4483 }
    4484 }
    4485#endif
    4486
    4487 return SCIP_OKAY;
    4488}
    4489
    4490/** adds cliques of the pseudoboolean constraint to the global clique table */
    4491static
    4493 SCIP*const scip, /**< SCIP data structure */
    4494 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    4495 SCIP_Bool*const cutoff, /**< pointer to store whether the node can be cut off */
    4496 int*const naggrvars, /**< pointer to count the number of aggregated variables */
    4497 int*const nchgbds /**< pointer to count the number of performed bound changes */
    4498 )
    4499{
    4500 SCIP_CONSDATA* consdata;
    4501 SCIP_VAR** vars;
    4502 int nvars;
    4503 SCIP_VAR** linvars;
    4504 SCIP_VAR* andres;
    4505 SCIP_VAR* andres2;
    4506 int nlinvars;
    4507 int nandress;
    4508 int c;
    4509 int v2;
    4510 int v1;
    4511 int nchgbdslocal;
    4512
    4513 assert(scip != NULL);
    4514 assert(cons != NULL);
    4515 assert(cutoff != NULL);
    4516 assert(naggrvars != NULL);
    4517 assert(nchgbds != NULL);
    4518 assert(SCIPconsIsActive(cons));
    4519
    4520 *cutoff = FALSE;
    4521
    4522 consdata = SCIPconsGetData(cons);
    4523 assert(consdata != NULL);
    4524 /* if we have no and-constraints left, we should not be here and this constraint should be deleted (only the linaer should survive) */
    4525 assert(consdata->nconsanddatas > 0);
    4526
    4527 /* check whether the cliques have already been added */
    4528 if( consdata->cliquesadded )
    4529 return SCIP_OKAY;
    4530
    4531 consdata->cliquesadded = TRUE;
    4532
    4534
    4535 /* check standard pointers and sizes */
    4536 assert(consdata->lincons != NULL);
    4537 assert(SCIPconsIsActive(consdata->lincons));
    4538 assert(consdata->linconstype > SCIP_LINEARCONSTYPE_INVALIDCONS);
    4539 assert(consdata->consanddatas != NULL);
    4540 assert(consdata->nconsanddatas > 0);
    4541 assert(consdata->nconsanddatas <= consdata->sconsanddatas);
    4542
    4543 /* check number of linear variables */
    4544 SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
    4545 assert(nvars == consdata->nlinvars + consdata->nconsanddatas);
    4546
    4547 /* get temporary memory */
    4548 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    4549 SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nvars) );
    4550
    4551 /* get variables and coefficients */
    4552 SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, NULL, &nvars) );
    4553
    4554 /* calculate all not artificial linear variables and all artificial and-resultants
    4555 * @todo should we take into accout the negation status of the cliques?
    4556 */
    4557 SCIP_CALL( getLinVarsAndAndRess(scip, cons, vars, NULL, nvars, linvars, NULL, &nlinvars,
    4558 NULL, NULL, NULL, &nandress) );
    4559
    4560 assert(nandress == consdata->nconsanddatas);
    4561 assert(consdata->consanddatas != NULL);
    4562
    4563 /* find cliques from linear variable to and-resultant */
    4564 for( c = nandress - 1; c >= 0; --c )
    4565 {
    4566 CONSANDDATA* consanddata;
    4567 SCIP_VAR** andvars;
    4568 int nandvars;
    4569
    4570 consanddata = consdata->consanddatas[c];
    4571 assert(consanddata != NULL);
    4572
    4573 andres = SCIPgetResultantAnd(scip, consanddata->cons);
    4574
    4575 /* choose correct variable array */
    4576 if( consanddata->nnewvars > 0 )
    4577 {
    4578 andvars = consanddata->newvars;
    4579 nandvars = consanddata->nnewvars;
    4580 }
    4581 else
    4582 {
    4583 andvars = consanddata->vars;
    4584 nandvars = consanddata->nvars;
    4585 }
    4586
    4587 for( v1 = nandvars - 1; v1 >= 0; --v1 )
    4588 {
    4589 SCIP_VAR* var1;
    4590 SCIP_Bool values[2];
    4591
    4592 var1 = andvars[v1];
    4593 if( !SCIPvarIsActive(var1) && (!SCIPvarIsNegated(var1) || !SCIPvarIsActive(SCIPvarGetNegationVar(var1))) )
    4594 continue;
    4595
    4596 /* get active counterpart to check for common cliques */
    4598 {
    4599 var1 = SCIPvarGetNegationVar(var1);
    4600 values[0] = FALSE;
    4601 }
    4602 else
    4603 values[0] = TRUE;
    4604
    4605 for( v2 = nlinvars - 1; v2 >= 0; --v2 )
    4606 {
    4607 SCIP_VAR* var2;
    4608
    4609 var2 = linvars[v2];
    4610 if( !SCIPvarIsActive(var2) && (!SCIPvarIsNegated(var2) || !SCIPvarIsActive(SCIPvarGetNegationVar(var2))) )
    4611 continue;
    4612
    4613 /* get active counterpart to check for common cliques */
    4615 {
    4616 var2 = SCIPvarGetNegationVar(var2);
    4617 values[1] = FALSE;
    4618 }
    4619 else
    4620 values[1] = TRUE;
    4621
    4622 /* if variable in and-constraint1 is the negated variable of a normal linear variable, than we can add a
    4623 * clique between the and-resultant and the normal linear variable, negated variables are not save in
    4624 * cliquetables
    4625 *
    4626 * set r_1 = var1 * z; (z is some product)
    4627 * var1 == ~var2
    4628 *
    4629 * if:
    4630 * var1 + ~var1 <= 1; r_1
    4631 * 0 + 1 <= 1 0 \
    4632 * 1 + 0 <= 1 ==> 1 or 0 > ==> r_1 + var2 <= 1
    4633 * 0 + 0 <= 1 0 /
    4634 */
    4635 if( values[0] != values[1] && var1 == var2 )
    4636 {
    4637 SCIP_CONS* newcons;
    4638 SCIP_VAR* clqvars[2];
    4639 char consname[SCIP_MAXSTRLEN];
    4640
    4641 clqvars[0] = andres;
    4642 clqvars[1] = values[1] ? var2 : SCIPvarGetNegatedVar(var2);
    4643 assert(clqvars[1] != NULL);
    4644
    4645 /* @todo: check whether it is better to only add the clique or to add the setppc constraint or do both */
    4646
    4647 /* add clique */
    4648 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, 2, FALSE, cutoff, &nchgbdslocal) );
    4649 if( *cutoff )
    4650 goto TERMINATE;
    4651
    4652 *nchgbds += nchgbdslocal;
    4653
    4654 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_clq_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(clqvars[0]), SCIPvarGetName(clqvars[1]) );
    4655 SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, consname, 2, clqvars,
    4660
    4661 SCIP_CALL( SCIPaddCons(scip, newcons) );
    4662 SCIPdebugMsg(scip, "added a clique/setppc constraint <%s> \n", SCIPconsGetName(newcons));
    4663 SCIPdebugPrintCons(scip, newcons, NULL);
    4664
    4665 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    4666 }
    4667 /* if a variable in an and-constraint is in a clique with another normal linear variable, we can add the
    4668 * clique between the linear variable and the and-resultant
    4669 *
    4670 * set r_1 = var1 * z; (z is some product)
    4671 *
    4672 * if:
    4673 * var1 + var2 <= 1; r_1
    4674 * 0 + 1 <= 1 0 \
    4675 * 1 + 0 <= 1 ==> 1 or 0 > ==> r_1 + var2 <= 1
    4676 * 0 + 0 <= 1 0 /
    4677 */
    4678 if( (var1 != var2) && SCIPvarsHaveCommonClique(var1, values[0], var2, values[1], TRUE) )
    4679 {
    4680 SCIP_CONS* newcons;
    4681 SCIP_VAR* clqvars[2];
    4682 char consname[SCIP_MAXSTRLEN];
    4683
    4684 clqvars[0] = andres;
    4685 clqvars[1] = values[1] ? var2 : SCIPvarGetNegatedVar(var2);
    4686 assert(clqvars[1] != NULL);
    4687
    4688 /* @todo: check whether it is better to only add the clique or to add the setppc constraint or do both */
    4689
    4690 /* add clique */
    4691 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, 2, FALSE, cutoff, &nchgbdslocal) );
    4692 if( *cutoff )
    4693 goto TERMINATE;
    4694
    4695 *nchgbds += nchgbdslocal;
    4696
    4697 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_clq_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(clqvars[0]), SCIPvarGetName(clqvars[1]) );
    4698 SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, consname, 2, clqvars,
    4703
    4704 SCIP_CALL( SCIPaddCons(scip, newcons) );
    4705 SCIPdebugMsg(scip, "added a clique/setppc constraint <%s> \n", SCIPconsGetName(newcons));
    4706 SCIPdebugPrintCons(scip, newcons, NULL);
    4707
    4708 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    4709 }
    4710 }
    4711 }
    4712 }
    4713
    4714 /* find cliques over variables which are in different and-constraints */
    4715 for( c = nandress - 1; c > 0; --c )
    4716 {
    4717 CONSANDDATA* consanddata1;
    4718 CONSANDDATA* consanddata2;
    4719 SCIP_VAR** andvars1;
    4720 int nandvars1;
    4721 SCIP_VAR** andvars2;
    4722 int nandvars2;
    4723
    4724 consanddata1 = consdata->consanddatas[c];
    4725 assert(consanddata1 != NULL);
    4726 consanddata2 = consdata->consanddatas[c - 1];
    4727 assert(consanddata2 != NULL);
    4728
    4729 andres = SCIPgetResultantAnd(scip, consanddata1->cons);
    4730 andres2 = SCIPgetResultantAnd(scip, consanddata2->cons);
    4731
    4732 /* choose correct variable array of consanddata object 1 */
    4733 if( consanddata1->nnewvars > 0 )
    4734 {
    4735 andvars1 = consanddata1->newvars;
    4736 nandvars1 = consanddata1->nnewvars;
    4737 }
    4738 else
    4739 {
    4740 andvars1 = consanddata1->vars;
    4741 nandvars1 = consanddata1->nvars;
    4742 }
    4743
    4744 /* choose correct variable array of consanddata object 2 */
    4745 if( consanddata2->nnewvars > 0 )
    4746 {
    4747 andvars2 = consanddata2->newvars;
    4748 nandvars2 = consanddata2->nnewvars;
    4749 }
    4750 else
    4751 {
    4752 andvars2 = consanddata2->vars;
    4753 nandvars2 = consanddata2->nvars;
    4754 }
    4755
    4756 /* compare both terms for finding new aggregated variables and new cliques */
    4757 for( v1 = nandvars1 - 1; v1 >= 0; --v1 )
    4758 {
    4759 SCIP_VAR* var1;
    4760 SCIP_Bool values[2];
    4761
    4762 var1 = andvars1[v1];
    4763 if( !SCIPvarIsActive(var1) && (!SCIPvarIsNegated(var1) || !SCIPvarIsActive(SCIPvarGetNegationVar(var1))) )
    4764 continue;
    4765
    4766 /* get active counterpart to check for common cliques */
    4768 {
    4769 var1 = SCIPvarGetNegationVar(var1);
    4770 values[0] = FALSE;
    4771 }
    4772 else
    4773 values[0] = TRUE;
    4774
    4775 for( v2 = nandvars2 - 1; v2 >= 0; --v2 )
    4776 {
    4777 SCIP_VAR* var2;
    4778
    4779 var2 = andvars2[v2];
    4780 if( !SCIPvarIsActive(var2) && (!SCIPvarIsNegated(var2) || !SCIPvarIsActive(SCIPvarGetNegationVar(var2))) )
    4781 continue;
    4782
    4783 /* get active counterpart to check for common cliques */
    4785 {
    4786 var2 = SCIPvarGetNegationVar(var2);
    4787 values[1] = FALSE;
    4788 }
    4789 else
    4790 values[1] = TRUE;
    4791
    4792 /* if a variable in and-constraint1 is the negated variable of a variable in and-constraint2, than we can
    4793 * add a clique between both and-resultants, negated variables are not save in cliquetables
    4794 *
    4795 * set r_1 = var1 * z_1; (z_1 is some product)
    4796 * set r_2 = var2 * z_2; (z_2 is some product)
    4797 * var1 == ~var2
    4798 *
    4799 * if:
    4800 * var1 + ~var1 <= 1; r_1 r_2
    4801 * 0 + 1 <= 1 0 1 or 0 \
    4802 * 1 + 0 <= 1 ==> 1 or 0 0 > ==> r_1 + r_2 <= 1
    4803 * 0 + 0 <= 1 0 0 /
    4804 */
    4805 if( values[0] != values[1] && var1 == var2 )
    4806 {
    4807 SCIP_CONS* newcons;
    4808 SCIP_VAR* clqvars[2];
    4809 char consname[SCIP_MAXSTRLEN];
    4810
    4811 clqvars[0] = andres;
    4812 clqvars[1] = andres2;
    4813
    4814 /* @todo: check whether it is better to only add the clique or to add the setppc constraint or do both */
    4815
    4816 /* add clique */
    4817 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, 2, FALSE, cutoff, &nchgbdslocal) );
    4818 if( *cutoff )
    4819 goto TERMINATE;
    4820
    4821 *nchgbds += nchgbdslocal;
    4822
    4823 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_clq_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(clqvars[0]), SCIPvarGetName(clqvars[1]) );
    4824 SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, consname, 2, clqvars,
    4829
    4830 SCIP_CALL( SCIPaddCons(scip, newcons) );
    4831 SCIPdebugMsg(scip, "added a clique/setppc constraint <%s> \n", SCIPconsGetName(newcons));
    4832 SCIPdebugPrintCons(scip, newcons, NULL);
    4833
    4834 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    4835 }
    4836 /* if a variable in an and-constraint is in a clique with a variable in another and-constraint, we can add
    4837 * the clique between both and-resultant
    4838 *
    4839 * let r_1 = var1 * z_1; (z_1 is some product)
    4840 * let r_2 = var2 * z_2; (z_2 is some product)
    4841 *
    4842 * if:
    4843 * var1 + var2 <= 1; r_1 r_2
    4844 * 0 + 1 <= 1 0 1 or 0 \
    4845 * 1 + 0 <= 1 ==> 1 or 0 0 > ==> r_1 + r_2 <= 1
    4846 * 0 + 0 <= 1 0 0 /
    4847 */
    4848 else if( SCIPvarsHaveCommonClique(var1, values[0], var2, values[1], TRUE) && (var1 != var2) )
    4849 {
    4850 SCIP_CONS* newcons;
    4851 SCIP_VAR* clqvars[2];
    4852 char consname[SCIP_MAXSTRLEN];
    4853
    4854 clqvars[0] = andres;
    4855 clqvars[1] = values[1] ? var2 : SCIPvarGetNegatedVar(var2);
    4856 assert(clqvars[1] != NULL);
    4857
    4858 /* @todo: check whether it is better to only add the clique or to add the setppc constraint or do both */
    4859
    4860 /* add clique */
    4861 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, 2, FALSE, cutoff, &nchgbdslocal) );
    4862 if( *cutoff )
    4863 goto TERMINATE;
    4864
    4865 *nchgbds += nchgbdslocal;
    4866
    4867 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_clq_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(clqvars[0]), SCIPvarGetName(clqvars[1]) );
    4868 SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, consname, 2, clqvars,
    4873
    4874 SCIP_CALL( SCIPaddCons(scip, newcons) );
    4875 SCIPdebugMsg(scip, "added a clique/setppc constraint <%s> \n", SCIPconsGetName(newcons));
    4876 SCIPdebugPrintCons(scip, newcons, NULL);
    4877
    4878 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    4879 }
    4880 }
    4881 }
    4882 }
    4883
    4884 TERMINATE:
    4885 /* free temporary memory */
    4886 SCIPfreeBufferArray(scip, &linvars);
    4887 SCIPfreeBufferArray(scip, &vars);
    4888
    4889 return SCIP_OKAY;
    4890}
    4891
    4892/** propagation method for pseudoboolean constraints */
    4893static
    4895 SCIP*const scip, /**< SCIP data structure */
    4896 SCIP_CONS*const cons, /**< knapsack constraint */
    4897 SCIP_Bool*const cutoff, /**< pointer to store whether the node can be cut off */
    4898 int*const ndelconss /**< pointer to count number of deleted constraints */
    4899 )
    4900{
    4901 SCIP_CONSDATA* consdata;
    4902
    4903 assert(scip != NULL);
    4904 assert(cons != NULL);
    4905 assert(cutoff != NULL);
    4906 assert(ndelconss != NULL);
    4907
    4908 *cutoff = FALSE;
    4909
    4910 consdata = SCIPconsGetData(cons);
    4911 assert(consdata != NULL);
    4912 assert(consdata->lincons != NULL);
    4913
    4914 /* if linear constraint is redundant, than pseudoboolean constraint is redundant too */
    4915 if( SCIPconsIsDeleted(consdata->lincons) )
    4916 {
    4918 ++(*ndelconss);
    4919 }
    4920
    4921 /* check if the constraint was already propagated */
    4922 if( consdata->propagated )
    4923 return SCIP_OKAY;
    4924
    4925 /* mark the constraint propagated */
    4926 consdata->propagated = TRUE;
    4927
    4928 return SCIP_OKAY;
    4929}
    4930
    4931/** update and-constraint flags due to pseudoboolean constraint flags */
    4932static
    4934 SCIP*const scip, /**< SCIP data structure */
    4935 SCIP_CONS*const cons /**< pseudoboolean constraint */
    4936 )
    4937{
    4938 CONSANDDATA** consanddatas;
    4939 int nconsanddatas;
    4940 SCIP_CONSDATA* consdata;
    4941 int c;
    4942
    4943 assert(scip != NULL);
    4944 assert(cons != NULL);
    4945
    4946 consdata = SCIPconsGetData(cons);
    4947 assert(consdata != NULL);
    4948
    4949 consanddatas = consdata->consanddatas;
    4950 nconsanddatas = consdata->nconsanddatas;
    4951 assert(consanddatas != NULL || nconsanddatas == 0);
    4952
    4953 if( !SCIPconsIsActive(cons) )
    4954 return SCIP_OKAY;
    4955
    4956 /* release and-constraints and change check flag of and-constraint */
    4957 for( c = nconsanddatas - 1; c >= 0; --c )
    4958 {
    4959 SCIP_CONS* andcons;
    4960
    4961 assert(consanddatas[c] != NULL);
    4962
    4963 if( !consanddatas[c]->istransformed )
    4964 continue;
    4965
    4966 andcons = consanddatas[c]->cons;
    4967 assert(andcons != NULL);
    4968
    4970 }
    4971
    4972 return SCIP_OKAY;
    4973}
    4974
    4975/** delete unused information in constraint handler data */
    4976static
    4978 SCIP*const scip, /**< SCIP data structure */
    4979 SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
    4980 int*const ndelconss /**< pointer to count number of deleted constraints */
    4981 )
    4982{
    4983 CONSANDDATA** allconsanddatas;
    4984 CONSANDDATA* consanddata;
    4985 SCIP_VAR** fixedvars = SCIPgetFixedVars(scip);
    4986 SCIP_VAR** activevars;
    4987 SCIP_Real* activescalars;
    4988 SCIP_Real activeconstant;
    4989 int nvars = SCIPgetNVars(scip);
    4990 int nfixedvars = SCIPgetNFixedVars(scip);
    4991 int c;
    4992
    4993 assert(scip != NULL);
    4994 assert(conshdlrdata != NULL);
    4995 assert(ndelconss != NULL);
    4996
    4997 if( conshdlrdata->nallconsanddatas == 0 )
    4998 return SCIP_OKAY;
    4999
    5000 allconsanddatas = conshdlrdata->allconsanddatas;
    5001 assert(allconsanddatas != NULL);
    5002 assert(conshdlrdata->nallconsanddatas >= 1);
    5003 assert(conshdlrdata->nallconsanddatas <= conshdlrdata->sallconsanddatas);
    5004
    5005 if( nfixedvars >= 1 && nvars >= 1 )
    5006 {
    5007 SCIP_CALL( SCIPallocBufferArray(scip, &activevars, nvars) );
    5008 SCIP_CALL( SCIPallocBufferArray(scip, &activescalars, nvars) );
    5009 }
    5010 else
    5011 {
    5012 activevars = NULL;
    5013 activescalars = NULL;
    5014 }
    5015
    5016 for( c = conshdlrdata->nallconsanddatas - 1; c >= 0; --c )
    5017 {
    5018 SCIP_VAR** tmpvars;
    5019 int stmpvars;
    5020 SCIP_CONS* cons;
    5021 int v;
    5022
    5023 consanddata = allconsanddatas[c];
    5024
    5025 assert(consanddata->nvars == 0 || (consanddata->vars != NULL && consanddata->svars > 0));
    5026 assert(consanddata->nnewvars == 0 || (consanddata->newvars != NULL && consanddata->snewvars > 0));
    5027
    5028 if( !consanddata->istransformed )
    5029 {
    5030 assert(consanddata->vars == NULL || consanddata->origcons != NULL);
    5031 assert(consanddata->nvars == 0 || consanddata->origcons != NULL);
    5032 assert(consanddata->svars == 0 || consanddata->origcons != NULL);
    5033 assert(consanddata->newvars == NULL);
    5034 assert(consanddata->nnewvars == 0);
    5035 assert(consanddata->snewvars == 0);
    5036
    5037 continue;
    5038 }
    5039
    5040 /* if no variables are left, delete variables arrays */
    5041 if( consanddata->nvars == 0 )
    5042 {
    5043 SCIP_VAR* resvar = SCIPgetResultantAnd(scip, consanddata->cons);
    5044
    5045 /* if we have no old variables, than also no new variables */
    5046 assert(consanddata->nnewvars == 0);
    5047 assert(consanddata->nuses > 0);
    5048 assert(resvar != NULL);
    5049
    5050 /* delete and-constraint */
    5051 SCIP_CALL( SCIPdelCons(scip, consanddata->cons) );
    5052 ++(*ndelconss);
    5053
    5054 SCIP_CALL( transformToOrig(scip, consanddata, conshdlrdata) );
    5055
    5056 consanddata->nuses = 0;
    5057
    5058 /* remove consanddata from hashtable, if it existed only in transformed space */
    5059 if( consanddata->origcons == NULL )
    5060 {
    5061 assert(SCIPhashtableExists(conshdlrdata->hashtable, (void*)consanddata));
    5062 SCIP_CALL( SCIPhashtableRemove(conshdlrdata->hashtable, (void*)consanddata) );
    5063 }
    5064 assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)resvar));
    5065 SCIP_CALL( SCIPhashmapRemove(conshdlrdata->hashmap, (void*)resvar) );
    5066
    5067 /* unlock upgrade to provide control */
    5068 SCIPconsAddUpgradeLocks(consanddata->cons, -1);
    5069
    5070 /* release and-constraint */
    5071 SCIP_CALL( SCIPreleaseCons(scip, &consanddata->cons) );
    5072
    5073 continue;
    5074 }
    5075
    5076 /* the consanddata object is not used anymore, so extract the and constraint and delete other data */
    5077 if( consanddata->nuses == 0 )
    5078 {
    5079 SCIP_Bool looseorcolumn;
    5080 SCIP_VARSTATUS varstatus;
    5081
    5082 if( consanddata->cons == NULL )
    5083 {
    5084 assert(!consanddata->istransformed || consanddata->noriguses > 0);
    5085 assert((consanddata->noriguses > 0) == (consanddata->origcons != NULL));
    5086 assert(consanddata->vars == NULL || consanddata->origcons != NULL);
    5087 assert(consanddata->nvars == 0 || consanddata->origcons != NULL);
    5088 assert(consanddata->svars == 0 || consanddata->origcons != NULL);
    5089 assert(consanddata->newvars == NULL);
    5090 assert(consanddata->nnewvars == 0);
    5091 assert(consanddata->snewvars == 0);
    5092
    5093 continue;
    5094 }
    5095
    5096 SCIP_CALL( transformToOrig(scip, consanddata, conshdlrdata) );
    5097
    5098 varstatus = SCIPvarGetStatus(SCIPgetResultantAnd(scip, consanddata->cons));
    5099 looseorcolumn = (varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN);
    5100
    5101 /* @note due to aggregations or fixings the resultant may need to be propagated later on, so we can only
    5102 * delete the and-constraint if the resultant is of column or loose status
    5103 * and is not an active variable of another (multi-)aggregated/negated variable
    5104 */
    5105 if( looseorcolumn )
    5106 {
    5107 SCIP_VAR* resvar = SCIPgetResultantAnd(scip, consanddata->cons);
    5108 SCIP_Bool del = TRUE;
    5109 int w;
    5110
    5111 assert(nvars >= 1);
    5112
    5113 /* we need to check all active representatives */
    5114 for( w = 0; w < nfixedvars && del; ++w )
    5115 {
    5116 int nactivevars;
    5117 int requiredsize;
    5118 int i;
    5119
    5120 assert(fixedvars != NULL);
    5121 assert(activevars != NULL);
    5122 assert(activescalars != NULL);
    5123 activevars[0] = fixedvars[w];
    5124 activescalars[0] = 1.0;
    5125 activeconstant = 0.0;
    5126 nactivevars = 1;
    5127 SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activescalars, &nactivevars, nvars, &activeconstant, &requiredsize) );
    5128 assert(requiredsize == nactivevars);
    5129
    5130 for( i = 0; i < nactivevars && del; ++i )
    5131 {
    5132 assert(SCIPvarGetStatus(activevars[i]) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(activevars[i]) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(activevars[i]) == SCIP_VARSTATUS_FIXED);
    5133
    5134 if( activevars[i] == resvar )
    5135 del = FALSE;
    5136 }
    5137 }
    5138
    5139 if( del )
    5140 {
    5141 SCIP_CALL( SCIPdelCons(scip, consanddata->cons) );
    5142 }
    5143 }
    5144
    5145 if( !SCIPconsIsDeleted(consanddata->cons) )
    5146 {
    5147 /* change flags */
    5148 if( !looseorcolumn )
    5149 {
    5150 SCIP_CALL( SCIPsetConsInitial(scip, consanddata->cons, FALSE) );
    5151 }
    5152 SCIP_CALL( SCIPsetConsChecked(scip, consanddata->cons, TRUE) );
    5153 }
    5154
    5155 /* remove consanddata from hashtable, if it existed only in transformed space */
    5156 if( consanddata->origcons == NULL )
    5157 {
    5158 assert(SCIPhashtableExists(conshdlrdata->hashtable, (void*)consanddata));
    5159 SCIP_CALL( SCIPhashtableRemove(conshdlrdata->hashtable, (void*)consanddata) );
    5160 }
    5161 assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddata->cons)));
    5162 SCIP_CALL( SCIPhashmapRemove(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddata->cons)) );
    5163
    5164 /* unlock upgrade to provide control */
    5165 SCIPconsAddUpgradeLocks(consanddata->cons, -1);
    5166
    5167 /* release and-constraint */
    5168 SCIP_CALL( SCIPreleaseCons(scip, &consanddata->cons) );
    5169 ++(*ndelconss);
    5170
    5171 continue;
    5172 }
    5173
    5174 cons = consanddata->cons;
    5175 assert(cons != NULL);
    5176
    5177 /* if and-constraint is deleted, delete variables arrays */
    5178 if( SCIPconsIsDeleted(cons) )
    5179 {
    5180 SCIP_VAR* resvar = SCIPgetResultantAnd(scip, consanddata->cons);
    5181
    5182 assert(consanddata->nuses > 0);
    5183 assert(resvar != NULL);
    5184
    5185 SCIP_CALL( transformToOrig(scip, consanddata, conshdlrdata) );
    5186
    5187 /* release and-constraint */
    5188 consanddata->nuses = 0;
    5189
    5190 /* remove consanddata from hashtable, if it existed only in transformed space */
    5191 if( consanddata->origcons == NULL )
    5192 {
    5193 assert(SCIPhashtableExists(conshdlrdata->hashtable, (void*)consanddata));
    5194 SCIP_CALL( SCIPhashtableRemove(conshdlrdata->hashtable, (void*)consanddata) );
    5195 }
    5196 assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)resvar));
    5197 SCIP_CALL( SCIPhashmapRemove(conshdlrdata->hashmap, (void*)resvar) );
    5198
    5199 /* unlock upgrade to provide control */
    5200 SCIPconsAddUpgradeLocks(consanddata->cons, -1);
    5201
    5202 /* release and-constraint */
    5203 SCIP_CALL( SCIPreleaseCons(scip, &consanddata->cons) );
    5204
    5205 continue;
    5206 }
    5207
    5208 /* if no new variables exist, we do not need to do anything here */
    5209 if( consanddata->nnewvars == 0 )
    5210 continue;
    5211
    5212 tmpvars = consanddata->vars;
    5213 /* release all variables */
    5214 for( v = consanddata->nvars - 1; v >= 0; --v )
    5215 {
    5216 /* in original problem the variables was already deleted */
    5217 assert(tmpvars[v] != NULL);
    5218 SCIP_CALL( SCIPreleaseVar(scip, &tmpvars[v]) );
    5219 }
    5220
    5221 /* exchange newvars with old vars array */
    5222 tmpvars = consanddata->vars;
    5223 stmpvars = consanddata->svars;
    5224 consanddata->vars = consanddata->newvars;
    5225 consanddata->svars = consanddata->snewvars;
    5226 consanddata->nvars = consanddata->nnewvars;
    5227 consanddata->newvars = tmpvars;
    5228 consanddata->snewvars = stmpvars;
    5229 /* reset number of variables in newvars array */
    5230 consanddata->nnewvars = 0;
    5231 }
    5232
    5233 if( activevars != NULL )
    5234 {
    5235 SCIPfreeBufferArray(scip, &activescalars);
    5236 SCIPfreeBufferArray(scip, &activevars);
    5237 }
    5238
    5239 return SCIP_OKAY;
    5240}
    5241
    5242/** update the uses counter of consandata objects which are used in pseudoboolean constraint, that were deleted and
    5243 * probably delete and-constraints
    5244 */
    5245static
    5247 SCIP*const scip, /**< SCIP data structure */
    5248 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    5249 SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
    5250 int*const ndelconss /**< pointer to store number of deleted constraints */
    5251 )
    5252{
    5253 CONSANDDATA** consanddatas;
    5254 int nconsanddatas;
    5255 SCIP_CONSDATA* consdata;
    5256 int c;
    5257
    5258 assert(scip != NULL);
    5259 assert(cons != NULL);
    5260 assert(conshdlrdata != NULL);
    5261 assert(ndelconss != NULL);
    5262
    5263 /* can only be called when constraint was deleted */
    5264 assert(SCIPconsIsDeleted(cons));
    5265
    5266 consdata = SCIPconsGetData(cons);
    5267 assert(consdata != NULL);
    5268
    5269 consanddatas = consdata->consanddatas;
    5270 nconsanddatas = consdata->nconsanddatas;
    5271 assert(nconsanddatas > 0 && consanddatas != NULL);
    5272 assert(consdata->andcoefs != NULL);
    5273
    5274 /* remove old locks */
    5275 for( c = nconsanddatas - 1; c >= 0; --c )
    5276 {
    5277 CONSANDDATA* consanddata;
    5278
    5279 consanddata = consanddatas[c];
    5280 assert(consanddata != NULL);
    5281
    5282 if( !consanddata->istransformed )
    5283 continue;
    5284
    5285 SCIP_CALL( removeOldLocks(scip, cons, consanddata, consdata->andcoefs[c], consdata->lhs, consdata->rhs) );
    5286 }
    5287
    5288 /* correct consandata usage counters and data */
    5289 for( c = nconsanddatas - 1; c >= 0; --c )
    5290 {
    5291 CONSANDDATA* consanddata;
    5292
    5293 consanddata = consanddatas[c];
    5294 assert(consanddata != NULL);
    5295 assert(consanddatas[c]->istransformed);
    5296
    5297 assert(consanddata->nuses > 0);
    5298
    5299 if( consanddata->nuses > 0 )
    5300 --(consanddata->nuses);
    5301
    5302 /* if data object is not used anymore, delete it */
    5303 if( consanddata->nuses == 0 )
    5304 {
    5305 SCIP_VAR* resvar;
    5306 SCIP_VARSTATUS varstatus;
    5307 SCIP_Bool looseorcolumn;
    5308
    5309 SCIP_CALL( transformToOrig(scip, consanddata, conshdlrdata) );
    5310
    5311 resvar = SCIPgetResultantAnd(scip, consanddata->cons);
    5312 assert(resvar != NULL);
    5313
    5314 varstatus = SCIPvarGetStatus(resvar);
    5315 looseorcolumn = (varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN);
    5316
    5317 /* @note due to aggregations or fixings the resultant may need to be propagated later on, so we can only
    5318 * delete the and-constraint if the resultant is of column or loose status
    5319 * and is not an active variable of another (multi-)aggregated/negated variable
    5320 */
    5321 if( looseorcolumn )
    5322 {
    5323 /* we can only delete and constraints if the resultant is an artificial variable and also active, because
    5324 * then the assigned value is not of interest and the artificial and constraint does not need to be
    5325 * fulfilled
    5326 *
    5327 * if this variable is not such an artificial variable we need the IRRELEVANT vartype which should be the
    5328 * correct way to fix this
    5329 */
    5330
    5331 assert(!SCIPconsIsChecked(consanddata->cons));
    5332 SCIP_CALL( SCIPdelCons(scip, consanddata->cons) );
    5333 }
    5334
    5335 if( !SCIPconsIsDeleted(consanddata->cons) )
    5336 {
    5337 /* change flags */
    5338 if( !looseorcolumn )
    5339 {
    5340 SCIP_CALL( SCIPsetConsInitial(scip, consanddata->cons, FALSE) );
    5341 }
    5342 SCIP_CALL( SCIPsetConsChecked(scip, consanddata->cons, TRUE) );
    5343 }
    5344
    5345 /* remove consanddata from hashtable, if it existed only in transformed space */
    5346 if( consanddata->origcons == NULL )
    5347 {
    5348 assert(SCIPhashtableExists(conshdlrdata->hashtable, (void*)consanddata));
    5349 SCIP_CALL( SCIPhashtableRemove(conshdlrdata->hashtable, (void*)consanddata) );
    5350 }
    5351 assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddata->cons)));
    5352 SCIP_CALL( SCIPhashmapRemove(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddata->cons)) );
    5353
    5354 /* unlock upgrade to provide control */
    5355 SCIPconsAddUpgradeLocks(consanddata->cons, -1);
    5356
    5357 /* release and-constraint */
    5358 SCIP_CALL( SCIPreleaseCons(scip, &consanddata->cons) );
    5359 ++(*ndelconss);
    5360 }
    5361 }
    5362
    5363 consdata->nconsanddatas = 0;
    5364
    5365 return SCIP_OKAY;
    5366}
    5367
    5368
    5369/* maximal number to enumerate solutions for one pseudoboolean constraint to check for an upgrade to an XOR constraint */
    5370#define MAXNVARS 10 /* note that this cannot be bigger than 31 */
    5371
    5372/** calculate result for a given pseudoboolean constraint with given values, this is used to decide whether a
    5373 * pseudoboolean constraint can be upgrade to an XOR constraint
    5374 */
    5375static
    5377 SCIP*const scip, /**< SCIP data structure */
    5378 SCIP_VAR**const vars, /**< all variables which occur */
    5379 int const nvars, /**< number of all variables which appear in the pseudoboolean
    5380 * constraint
    5381 */
    5382 SCIP_Bool*const values, /**< values of all variables which appear in the pseudoboolean
    5383 * constraint
    5384 */
    5385 SCIP_VAR**const linvars, /**< linear variables */
    5386 SCIP_Real*const lincoefs, /**< linear coefficients */
    5387 int const nlinvars, /**< number of linear variables */
    5388 SCIP_Real const constant, /**< offset to the linear part */
    5389 SCIP_Real const side, /**< side of pseudoboolean constraint */
    5390 CONSANDDATA**const consanddatas, /**< all consanddata objects in a constraint */
    5391 SCIP_Real*const consanddatacoefs, /**< nonlinear coefficients */
    5392 SCIP_Bool*const consanddatanegs, /**< negation status of and resultants in pseudo-boolean constraint */
    5393 int const nconsanddatas, /**< number of all consanddata objects */
    5394 int const cnt, /**< number of variables set to 1 */
    5395 int*const xortype /**< pointer to save the possible xor type if a solution was valid and does
    5396 * not violate the old xortype
    5397 */
    5398 )
    5399{
    5400 CONSANDDATA* consanddata;
    5401 SCIP_VAR** termvars;
    5402 SCIP_VAR** repvars;
    5403 int ntermvars;
    5404 SCIP_Bool* negated;
    5405 SCIP_Real value;
    5406 int pos;
    5407 int v;
    5408 int c;
    5409
    5410 assert(scip != NULL);
    5411 assert(vars != NULL);
    5412 assert(nvars > 0);
    5413 assert(values != NULL);
    5414 assert(linvars != NULL || nlinvars == 0);
    5415 assert(lincoefs != NULL || nlinvars == 0);
    5416 assert(nvars >= nlinvars);
    5417 assert(SCIPisEQ(scip, side, 1.0) || SCIPisZero(scip, side));
    5418 assert(consanddatas != NULL);
    5419 assert(consanddatacoefs != NULL);
    5420 assert(nconsanddatas > 0);
    5421 assert(*xortype >= -1 && *xortype <= 1);
    5422
    5423 /* order the variables after index, to compare them easier */
    5424 SCIPsortPtr((void**)linvars, SCIPvarCompActiveAndNegated, nlinvars);
    5425 SCIPsortPtr((void**)vars, SCIPvarCompActiveAndNegated, nvars);
    5426
    5427 value = constant;
    5428 for( v = nlinvars - 1; v >= 0; --v )
    5429 {
    5430 if( SCIPsortedvecFindPtr((void**)vars, SCIPvarCompActiveAndNegated, linvars[v], nvars, &pos) ) /*lint !e613*/
    5431 {
    5432 if( values[pos] )
    5433 value += lincoefs[v]; /*lint !e613*/
    5434 }
    5435 else
    5436 {
    5437 /* this cannot happen, all linear variables should be a part of 'vars' */
    5438 SCIPABORT();
    5439
    5440 *xortype = -1; /*lint !e527*/
    5441 return SCIP_OKAY;
    5442 }
    5443 }
    5444
    5447
    5448 for( c = nconsanddatas - 1; c >= 0; --c )
    5449 {
    5450 SCIP_Bool val = TRUE;
    5451
    5452 consanddata = consanddatas[c];
    5453 assert(consanddata != NULL);
    5454 assert(consanddata->istransformed);
    5455
    5456 /* choose correct variable array to add locks for, we only add locks for now valid variables */
    5457 if( consanddata->nnewvars > 0 )
    5458 {
    5459 termvars = consanddata->newvars;
    5460 ntermvars = consanddata->nnewvars;
    5461 }
    5462 else
    5463 {
    5464 termvars = consanddata->vars;
    5465 ntermvars = consanddata->nvars;
    5466 }
    5467 assert(ntermvars > 0 && termvars != NULL);
    5468
    5469 BMSclearMemoryArray(negated, MAXNVARS);
    5470
    5471 /* get linear active representation */
    5472 SCIP_CALL( SCIPgetBinvarRepresentatives(scip, ntermvars, termvars, repvars, negated) );
    5473 SCIPsortPtrBool((void**)repvars, negated, SCIPvarCompActiveAndNegated, ntermvars);
    5474
    5475 for( v = ntermvars - 1; v >= 0; --v )
    5476 {
    5477 SCIP_VAR* var;
    5478
    5479 assert(!negated[v] || (SCIPvarIsNegated(repvars[v]) && SCIPvarGetNegatedVar(repvars[v]) != NULL));
    5480
    5481 var = ( negated[v] ? SCIPvarGetNegationVar(repvars[v]) : repvars[v]);
    5482 if( SCIPsortedvecFindPtr((void**)vars, SCIPvarCompActiveAndNegated, var, nvars, &pos) )
    5483 {
    5484 if( (negated[v] && values[pos]) || (!negated[v] && !values[pos]) )
    5485 {
    5486 val = FALSE;
    5487 break;
    5488 }
    5489 }
    5490 else
    5491 {
    5492 /* this cannot happen, all non-linear variables should be a part of 'vars' */
    5493 SCIPABORT();
    5494
    5495 *xortype = -1; /*lint !e527*/
    5496 goto TERMINATE;
    5497 }
    5498 }
    5499
    5500 if( val != consanddatanegs[c] )
    5501 value += consanddatacoefs[c];
    5502 }
    5503
    5504 if( SCIPisEQ(scip, value, side) )
    5505 {
    5506 /* first solution is checked, so determine the possible xor upgrade */
    5507 if( *xortype == -1 )
    5508 {
    5509 if( cnt % 2 == 0 )
    5510 *xortype = 0;
    5511 else
    5512 *xortype = 1;
    5513 }
    5514 /* check if this solution does not fit in all possible xor solutions */
    5515 else if( *xortype == 1 && cnt % 2 == 0 )
    5516 *xortype = -1;
    5517 else if( *xortype == 0 && cnt % 2 == 1 )
    5518 *xortype = -1;
    5519 }
    5520 else
    5521 {
    5522 /* first not-solution is checked, so determine the possible xor upgrade */
    5523 if( *xortype == -1 )
    5524 {
    5525 if( cnt % 2 == 0 )
    5526 *xortype = 1;
    5527 else
    5528 *xortype = 0;
    5529 }
    5530 /* check if this had to be a solution for an upgrade to an xor */
    5531 else if( *xortype == 1 && cnt % 2 == 1 )
    5532 *xortype = -1;
    5533 else if( *xortype == 0 && cnt % 2 == 0 )
    5534 *xortype = -1;
    5535 }
    5536
    5537 TERMINATE:
    5538 SCIPfreeBufferArray(scip, &negated);
    5539 SCIPfreeBufferArray(scip, &repvars);
    5540
    5541 return SCIP_OKAY;
    5542}
    5543
    5544/** try upgrading pseudoboolean linear constraint to an XOR constraint and/or remove possible and-constraints
    5545 *
    5546 * @note An XOR(x_1,..,x_n) = 1 <=> XOR(x1,..,~x_j,..,x_n) = 0, for j in {1,..,n}, which is not yet checked while
    5547 * trying to upgrade
    5548 */
    5549static
    5551 SCIP*const scip, /**< SCIP data structure */
    5552 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    5553 SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
    5554 int*const ndelconss, /**< pointer to store number of deleted constraints */
    5555 int*const naddconss, /**< pointer to count number of added constraints */
    5556 int*const nfixedvars, /**< pointer to store number of fixed variables */
    5557 int*const nchgcoefs, /**< pointer to store number of changed coefficients constraints */
    5558 int*const nchgsides, /**< pointer to store number of changed sides constraints */
    5559 SCIP_Bool*const cutoff /**< pointer to store if a cutoff happened */
    5560 )
    5561{
    5562 SCIP_CONSDATA* consdata;
    5563 CONSANDDATA** consanddatas;
    5564 int nconsanddatas;
    5565 CONSANDDATA* consanddata;
    5566 SCIP_VAR** allvars;
    5567 SCIP_Real* allcoefs;
    5568 int nallvars;
    5569 SCIP_VAR** linvars;
    5570 SCIP_Real* lincoefs;
    5571 int nlinvars;
    5572 SCIP_Real* andcoefs;
    5573 SCIP_Bool* andnegs;
    5574 int nandress;
    5575 SCIP_VAR** vars;
    5576 int nvars;
    5577 SCIP_VAR** repvars;
    5578 SCIP_Bool* negated;
    5579 SCIP_VAR** activelinvars;
    5580 SCIP_Bool* values;
    5581 SCIP_CONS* lincons;
    5582 SCIP_CONS* newcons;
    5583 char newname[SCIP_MAXSTRLEN];
    5584 SCIP_Real constant;
    5585 int requiredsize;
    5586 int firstnlinvars;
    5587 int oldnlinvars;
    5588 int xortype;
    5589 int v;
    5590 int v1;
    5591 int c;
    5592
    5593 assert(scip != NULL);
    5594 assert(cons != NULL);
    5595 assert(conshdlrdata != NULL);
    5596 assert(ndelconss != NULL);
    5597 assert(nfixedvars != NULL);
    5598 assert(nchgcoefs != NULL);
    5599 assert(nchgsides != NULL);
    5600 assert(cutoff != NULL);
    5601 assert(SCIPconsIsActive(cons));
    5602
    5603 consdata = SCIPconsGetData(cons);
    5604 assert(consdata != NULL);
    5605
    5606 consanddatas = consdata->consanddatas;
    5607 andcoefs = consdata->andcoefs;
    5608 andnegs = consdata->andnegs;
    5609 nconsanddatas = consdata->nconsanddatas;
    5610 assert(nconsanddatas > 0 && consanddatas != NULL);
    5611
    5612 assert(consdata->lincons != NULL);
    5613 assert(consdata->linconstype == SCIP_LINEARCONSTYPE_LINEAR || consdata->linconstype == SCIP_LINEARCONSTYPE_SETPPC);
    5614
    5615 /* only equations can be updated */
    5616 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || (!SCIPisEQ(scip, consdata->lhs, 1.0) && !SCIPisZero(scip, consdata->lhs)) )
    5617 return SCIP_OKAY;
    5618
    5619 assert(consanddatas[0] != NULL);
    5620 assert(consanddatas[0]->cons != NULL);
    5621
    5622 lincons = consdata->lincons;
    5623
    5624 /* check number of linear variables */
    5625 SCIP_CALL( getLinearConsNVars(scip, lincons, consdata->linconstype, &nallvars) );
    5626 assert(nallvars - nconsanddatas == consdata->nlinvars);
    5627 nlinvars = consdata->nlinvars;
    5628
    5629 if( nlinvars > MAXNVARS )
    5630 return SCIP_OKAY;
    5631
    5633
    5634 /* allocate temporary memory */
    5635 SCIP_CALL( SCIPallocBufferArray(scip, &allvars, nallvars) );
    5636 SCIP_CALL( SCIPallocBufferArray(scip, &allcoefs, nallvars) );
    5641
    5642 /* get variables and coefficients */
    5643 SCIP_CALL( getLinearConsVarsData(scip, lincons, consdata->linconstype, allvars, allcoefs, &nallvars) );
    5644 assert(nallvars > 0);
    5645
    5646 /* calculate all not artificial linear variables */
    5647 SCIP_CALL( getLinVarsAndAndRess(scip, cons, allvars, allcoefs, nallvars, linvars, lincoefs, &nlinvars,
    5648 NULL, NULL, NULL, &nandress) );
    5649 assert(nlinvars == consdata->nlinvars);
    5650 assert(nandress == nallvars-nlinvars);
    5651
    5652 constant = 0;
    5653
    5654 /* get linear active representation */
    5655 SCIP_CALL( SCIPgetProbvarLinearSum(scip, linvars, lincoefs, &nlinvars, MAXNVARS, &constant, &requiredsize) );
    5656 assert(requiredsize == nlinvars);
    5657 SCIP_CALL( SCIPduplicateBufferArray(scip, &activelinvars, linvars, nlinvars) );
    5658
    5659 if( requiredsize > MAXNVARS )
    5660 goto TERMINATE;
    5661
    5662 firstnlinvars = nlinvars;
    5663
    5664 /* order the variables after index, to compare them easier */
    5665 SCIPsortPtr((void**)linvars, SCIPvarCompActiveAndNegated, nlinvars);
    5666
    5667 for( c = nconsanddatas - 1; c >= 0; --c )
    5668 {
    5669 consanddata = consanddatas[c];
    5670 assert(consanddata != NULL);
    5671 assert(consanddata->istransformed);
    5672
    5673 /* choose correct variable array */
    5674 if( consanddata->nnewvars > 0 )
    5675 {
    5676 vars = consanddata->newvars;
    5677 nvars = consanddata->nnewvars;
    5678 }
    5679 else
    5680 {
    5681 vars = consanddata->vars;
    5682 nvars = consanddata->nvars;
    5683 }
    5684 assert(nvars > 0 && vars != NULL);
    5685
    5686 if( nvars > MAXNVARS )
    5687 goto TERMINATE;
    5688
    5689 BMSclearMemoryArray(negated, MAXNVARS);
    5690
    5691 /* get linear active representation */
    5692 SCIP_CALL( SCIPgetBinvarRepresentatives(scip, nvars, vars, repvars, negated) );
    5693 SCIPsortPtr((void**)repvars, SCIPvarCompActiveAndNegated, nvars);
    5694
    5695 oldnlinvars = nlinvars;
    5696
    5697 /* determine all different variables over the linear variables and all variables in all and constraints */
    5698 for( v = nvars - 1, v1 = nlinvars - 1; v >= 0 && v1 >= 0; )
    5699 {
    5700 SCIP_VAR* var;
    5701
    5702 /* it appears that some fixed variables were not yet deleted */
    5703 if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 )
    5704 goto TERMINATE;
    5705
    5706 assert(SCIPvarIsActive(linvars[v1]));
    5707 assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v]))));
    5708
    5709 if( SCIPvarIsActive(repvars[v]) )
    5710 var = repvars[v];
    5711 else
    5712 var = SCIPvarGetNegationVar(repvars[v]);
    5713
    5714 if( SCIPvarGetIndex(var) > SCIPvarGetIndex(linvars[v1]) )
    5715 {
    5716 if( nlinvars + 1 < MAXNVARS )
    5717 {
    5718 linvars[nlinvars] = var;
    5719 ++nlinvars;
    5720 }
    5721 else
    5722 goto TERMINATE;
    5723
    5724 --v;
    5725 }
    5726 else if( SCIPvarGetIndex(var) < SCIPvarGetIndex(linvars[v1]) )
    5727 --v1;
    5728 else
    5729 {
    5730 --v;
    5731 --v1;
    5732 }
    5733 }
    5734
    5735 /* add the rest of variables */
    5736 if( v >= 0 )
    5737 {
    5738 SCIP_VAR* var;
    5739
    5740 for( ; v >= 0; --v )
    5741 {
    5742 /* it appears that some fixed variables were not yet deleted */
    5743 if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 )
    5744 goto TERMINATE;
    5745
    5746 assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v]))));
    5747
    5748 if( SCIPvarIsActive(repvars[v]) )
    5749 var = repvars[v];
    5750 else
    5751 var = SCIPvarGetNegationVar(repvars[v]);
    5752
    5753 if( nlinvars + 1 < MAXNVARS )
    5754 {
    5755 linvars[nlinvars] = var;
    5756 ++nlinvars;
    5757 }
    5758 else
    5759 goto TERMINATE;
    5760 }
    5761 }
    5762
    5763 /* if some new variables were inserted we need to reorder the array */
    5764 if( nlinvars > oldnlinvars )
    5765 {
    5766 /* order the variables after index, to compare them easier */
    5767 SCIPsortPtr((void**)linvars, SCIPvarCompActiveAndNegated, nlinvars);
    5768 }
    5769 }
    5770
    5771 SCIP_CALL( SCIPallocBufferArray(scip, &values, nlinvars) );
    5772 xortype = -1;
    5773
    5774 /* check values for variables which result in solutions which in the end lead to an XOR upgrade */
    5775 for( v = (1 << nlinvars) - 1; v >= 0; --v ) /*lint !e701*/
    5776 {
    5777 int cnt = 0;
    5778 for( v1 = nlinvars - 1; v1 >= 0; --v1 )
    5779 if( v & (1 << v1) ) /*lint !e701*/
    5780 {
    5781 values[v1] = TRUE;
    5782 ++cnt;
    5783 }
    5784 else
    5785 values[v1] = FALSE;
    5786
    5787 /* at maximum nlinvars values could be set to TRUE */
    5788 assert(cnt <= nlinvars);
    5789
    5790 SCIP_CALL( checkSolution(scip, linvars, nlinvars, values, activelinvars, lincoefs, firstnlinvars, constant,
    5791 consdata->lhs, consanddatas, andcoefs, andnegs, nconsanddatas, cnt, &xortype) );
    5792 if( xortype == -1 )
    5793 break;
    5794 }
    5795
    5796 SCIPfreeBufferArray(scip, &values);
    5797
    5798 assert(xortype >= -1 && xortype <= 1);
    5799
    5800 if( xortype >= 0 )
    5801 {
    5802 (void) SCIPsnprintf(newname, SCIP_MAXSTRLEN, "%s_upgraded", SCIPconsGetName(lincons));
    5803
    5804 SCIP_CALL( SCIPcreateConsXor(scip, &newcons, newname, (SCIP_Bool) xortype, nlinvars, linvars,
    5805 SCIPconsIsInitial(lincons), SCIPconsIsSeparated(lincons), SCIPconsIsEnforced(lincons), SCIPconsIsChecked(lincons),
    5806 SCIPconsIsPropagated(lincons), SCIPconsIsLocal(lincons), SCIPconsIsModifiable(lincons),
    5807 SCIPconsIsDynamic(lincons), SCIPconsIsRemovable(lincons), SCIPconsIsStickingAtNode(lincons)) );
    5808
    5809 /* add and release new constraint */
    5810 SCIP_CALL( SCIPaddCons(scip, newcons) );
    5811
    5812 SCIPdebugMsg(scip, "created upgraded XOR constraint:\n");
    5813 SCIPdebugMsg(scip, "old -> ");
    5814 SCIPdebugPrintCons(scip, lincons, NULL);
    5815 SCIPdebugMsg(scip, "new -> ");
    5816 SCIPdebugPrintCons(scip, newcons, NULL);
    5817
    5818 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    5819 ++(*naddconss);
    5820
    5821 /* delete old constraints */
    5822 SCIP_CALL( SCIPdelCons(scip, lincons) );
    5823 SCIP_CALL( SCIPdelCons(scip, cons) );
    5824 (*ndelconss) += 2;
    5825 }
    5826
    5827 TERMINATE:
    5828 /* delete temporary memory */
    5829 SCIPfreeBufferArray(scip, &activelinvars);
    5830 SCIPfreeBufferArray(scip, &negated);
    5831 SCIPfreeBufferArray(scip, &repvars);
    5832 SCIPfreeBufferArray(scip, &lincoefs);
    5833 SCIPfreeBufferArray(scip, &linvars);
    5834 SCIPfreeBufferArray(scip, &allcoefs);
    5835 SCIPfreeBufferArray(scip, &allvars);
    5836
    5837 return SCIP_OKAY;
    5838}
    5839
    5840/** try upgrading pseudoboolean logicor constraint to a linear constraint and/or remove possible and-constraints */
    5841static
    5843 SCIP*const scip, /**< SCIP data structure */
    5844 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    5845 SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
    5846 int*const ndelconss, /**< pointer to store number of deleted constraints */
    5847 int*const naddconss, /**< pointer to count number of added constraints */
    5848 int*const nfixedvars, /**< pointer to store number of fixed variables */
    5849 int*const nchgcoefs, /**< pointer to store number of changed coefficients constraints */
    5850 int*const nchgsides, /**< pointer to store number of changed sides constraints */
    5851 SCIP_Bool*const cutoff /**< pointer to store if a cutoff happened */
    5852 )
    5853{
    5854 CONSANDDATA** consanddatas;
    5855 int nconsanddatas;
    5856 SCIP_CONSDATA* consdata;
    5857 int c;
    5858 int v;
    5859 int v2;
    5860 SCIP_VAR** eqvars;
    5861 int neqvars;
    5862 int nminvars;
    5863 int nmaxvars;
    5864
    5865 assert(scip != NULL);
    5866 assert(cons != NULL);
    5867 assert(conshdlrdata != NULL);
    5868 assert(ndelconss != NULL);
    5869 assert(nfixedvars != NULL);
    5870 assert(nchgcoefs != NULL);
    5871 assert(nchgsides != NULL);
    5872 assert(cutoff != NULL);
    5873 assert(SCIPconsIsActive(cons));
    5874
    5875 consdata = SCIPconsGetData(cons);
    5876 assert(consdata != NULL);
    5877
    5878 consanddatas = consdata->consanddatas;
    5879 nconsanddatas = consdata->nconsanddatas;
    5880 assert(nconsanddatas > 0 && consanddatas != NULL);
    5881
    5882 assert(consdata->lincons != NULL);
    5883 assert(consdata->linconstype == SCIP_LINEARCONSTYPE_LOGICOR);
    5884
    5885 assert(consanddatas[0] != NULL);
    5886 assert(consanddatas[0]->cons != NULL);
    5887
    5888 if( nconsanddatas == 1 )
    5889 {
    5890 CONSANDDATA* consanddata;
    5891 SCIP_VAR** allvars;
    5892 SCIP_Real* allcoefs;
    5893 int nallvars;
    5894 SCIP_VAR** linvars;
    5895 SCIP_Real* lincoefs;
    5896 int nlinvars;
    5897 SCIP_VAR** vars;
    5898 int nvars;
    5899 SCIP_CONS* lincons;
    5900 SCIP_CONS* newcons;
    5901 char newname[SCIP_MAXSTRLEN];
    5902 SCIP_Real lhs;
    5903 SCIP_Real rhs;
    5904
    5905 /* if we have only one term left in the logicor constraint, the presolving should be done by the logicor
    5906 * constraint handler
    5907 */
    5908 if( consdata->nlinvars == 0 )
    5909 {
    5910 return SCIP_OKAY;
    5911 }
    5912
    5913 /* for every old logicor constraint: sum_i (x_i) + res >= 1 , with an and-constraint of res as the resultant,
    5914 * which looks like 'res = y_1 * ... * y_n' => sum_i (n * x_i) + sum_j=1^n y_j >= n
    5915 *
    5916 * i.e. x_1 + x_2 + x_3 + x_4 * x_5 * x_6 >= 1
    5917 * => 3x_1 + 3x_2 + 3x_3 + x_4 + x_5 + x_6 >= 3
    5918 */
    5919
    5920 lincons = consdata->lincons;
    5921
    5922 consanddata = consanddatas[0];
    5923 assert(consanddata != NULL);
    5924 assert(consanddata->istransformed);
    5925
    5926 /* choose correct variable array to add locks for, we only add locks for now valid variables */
    5927 if( consanddata->nnewvars > 0 )
    5928 {
    5929 vars = consanddata->newvars;
    5930 nvars = consanddata->nnewvars;
    5931 }
    5932 else
    5933 {
    5934 vars = consanddata->vars;
    5935 nvars = consanddata->nvars;
    5936 }
    5937 assert(nvars > 0 && vars != NULL);
    5938
    5939 lhs = nvars;
    5940 rhs = SCIPinfinity(scip);
    5941
    5942 (void) SCIPsnprintf(newname, SCIP_MAXSTRLEN, "%s_upgraded", SCIPconsGetName(lincons));
    5943
    5944 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, newname, 0, NULL, NULL, lhs, rhs,
    5945 SCIPconsIsInitial(lincons), SCIPconsIsSeparated(lincons), SCIPconsIsEnforced(lincons), SCIPconsIsChecked(lincons),
    5946 SCIPconsIsPropagated(lincons), SCIPconsIsLocal(lincons), SCIPconsIsModifiable(lincons),
    5947 SCIPconsIsDynamic(lincons), SCIPconsIsRemovable(lincons), SCIPconsIsStickingAtNode(lincons)) );
    5948
    5949 /* check number of linear variables */
    5950 SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nallvars) );
    5951 assert(nallvars == consdata->nlinvars + 1);
    5952
    5953 nlinvars = consdata->nlinvars;
    5954
    5955 /* allocate temporary memory */
    5956 SCIP_CALL( SCIPallocBufferArray(scip, &allvars, nallvars) );
    5957 SCIP_CALL( SCIPallocBufferArray(scip, &allcoefs, nallvars) );
    5958 SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nlinvars) );
    5959 SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nlinvars) );
    5960
    5961 /* get variables and coefficients */
    5962 SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, allvars, allcoefs, &nallvars) );
    5963 assert(allcoefs != NULL);
    5964
    5965 /* calculate all not artificial linear variables */
    5966 SCIP_CALL( getLinVarsAndAndRess(scip, cons, allvars, allcoefs, nallvars, linvars, lincoefs, &nlinvars,
    5967 NULL, NULL, NULL, NULL) );
    5968 assert(nlinvars == consdata->nlinvars);
    5969
    5970 /* add linear part to new constraint */
    5971 for( v = 0; v < nlinvars; ++v )
    5972 {
    5973 SCIP_CALL( SCIPaddCoefLinear(scip, newcons, linvars[v], (SCIP_Real) nvars) );
    5974 }
    5975
    5976 /* add non-linear part to new constraint */
    5977 for( v = 0; v < nvars; ++v )
    5978 {
    5979 SCIP_CALL( SCIPaddCoefLinear(scip, newcons, vars[v], 1.0) );
    5980 }
    5981
    5982 /* add and release new constraint */
    5983 SCIP_CALL( SCIPaddCons(scip, newcons) );
    5984
    5985 SCIPdebugMsg(scip, "created upgraded linear constraint:\n");
    5986 SCIPdebugMsg(scip, "old -> ");
    5987 SCIPdebugPrintCons(scip, lincons, NULL);
    5988 SCIPdebugMsg(scip, "new -> ");
    5989 SCIPdebugPrintCons(scip, newcons, NULL);
    5990
    5991 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    5992 ++(*naddconss);
    5993
    5994 /* delete old constraints */
    5995 SCIP_CALL( SCIPdelCons(scip, lincons) );
    5996 SCIP_CALL( SCIPdelCons(scip, cons) );
    5997 (*ndelconss) += 2;
    5998
    5999 /* delete temporary memory */
    6000 SCIPfreeBufferArray(scip, &lincoefs);
    6001 SCIPfreeBufferArray(scip, &linvars);
    6002 SCIPfreeBufferArray(scip, &allcoefs);
    6003 SCIPfreeBufferArray(scip, &allvars);
    6004
    6005 return SCIP_OKAY;
    6006 }
    6007
    6008 /* initializing array for variables which can appear in all consanddata objects */
    6009 c = nconsanddatas - 1;
    6010 assert(consanddatas[c]->istransformed);
    6011
    6012 /* choose correct variable array */
    6013 if( consanddatas[c]->nnewvars > 0 )
    6014 {
    6015 neqvars = consanddatas[c]->nnewvars;
    6016 /* allocate temporary memory */
    6017 SCIP_CALL( SCIPduplicateBufferArray(scip, &eqvars, consanddatas[c]->newvars, neqvars) );
    6018 }
    6019 else
    6020 {
    6021 neqvars = consanddatas[c]->nvars;
    6022 /* allocate temporary memory */
    6023 SCIP_CALL( SCIPduplicateBufferArray(scip, &eqvars, consanddatas[c]->vars, neqvars) );
    6024 }
    6025 nminvars = neqvars;
    6026 nmaxvars = neqvars;
    6027 assert(neqvars > 0 && eqvars != NULL);
    6028
    6029#ifndef NDEBUG
    6030 /* check that variables are sorted */
    6031 for( v = neqvars - 1; v > 0; --v )
    6032 assert(SCIPvarGetIndex(eqvars[v]) > SCIPvarGetIndex(eqvars[v - 1]));
    6033#endif
    6034 /* computing all variables which appear in all consanddata objects */
    6035 for( --c ; c >= 0; --c )
    6036 {
    6037 CONSANDDATA* consanddata;
    6038 SCIP_VAR** vars;
    6039 int nvars;
    6040 int nneweqvars;
    6041
    6042 consanddata = consanddatas[c];
    6043 assert(consanddata != NULL);
    6044 assert(consanddatas[c]->istransformed);
    6045
    6046 /* choose correct variable array to add locks for, we only add locks for now valid variables */
    6047 if( consanddata->nnewvars > 0 )
    6048 {
    6049 vars = consanddata->newvars;
    6050 nvars = consanddata->nnewvars;
    6051 }
    6052 else
    6053 {
    6054 vars = consanddata->vars;
    6055 nvars = consanddata->nvars;
    6056 }
    6057 assert(nvars > 0 && vars != NULL);
    6058
    6059#ifndef NDEBUG
    6060 /* check that variables are sorted */
    6061 for( v = nvars - 1; v > 0; --v )
    6062 assert(SCIPvarGetIndex(vars[v]) > SCIPvarGetIndex(vars[v - 1]));
    6063#endif
    6064
    6065 /* update minimal number of variables in and-constraint */
    6066 if( nvars < nminvars )
    6067 nminvars = nvars;
    6068 /* update maximal number of variables in and-constraint */
    6069 else if( nvars > nmaxvars )
    6070 nmaxvars = nvars;
    6071 assert(nminvars > 0);
    6072 assert(nminvars <= nmaxvars);
    6073
    6074 nneweqvars = 0;
    6075 for( v = 0, v2 = 0; v < neqvars && v2 < nvars; )
    6076 {
    6077 int index1;
    6078 int index2;
    6079
    6080 assert(eqvars[v] != NULL);
    6081 assert(vars[v2] != NULL);
    6082 index1 = SCIPvarGetIndex(eqvars[v]);
    6083 index2 = SCIPvarGetIndex(vars[v2]);
    6084
    6085 /* check which variables are still in all and-constraints */
    6086 if( index1 < index2 )
    6087 ++v;
    6088 else if( index1 > index2 )
    6089 ++v2;
    6090 else
    6091 {
    6092 assert(index1 == index2);
    6093 assert(nneweqvars <= v);
    6094
    6095 if( nneweqvars < v )
    6096 eqvars[nneweqvars] = eqvars[v];
    6097 ++nneweqvars;
    6098 ++v;
    6099 ++v2;
    6100 }
    6101 }
    6102 neqvars = nneweqvars;
    6103
    6104 /* now we only want to handle the easy case where nminvars == neqvars + 1
    6105 * @todo: implement for the othercase too
    6106 */
    6107 if( nminvars > neqvars + 1 )
    6108 break;
    6109
    6110 /* if no variables overlap we have to stop */
    6111 if( neqvars == 0 )
    6112 break;
    6113 }
    6114
    6115 /* if all and-constraints in pseudoboolean constraint have some equal variables we can extract them and create a new
    6116 * linear constraint; iff the number of equal variables is equal to the number of variables - 1 in all consanddata
    6117 * objects then the new constraint will not contain any products; if no normal linear variables exist we can fix all
    6118 * equal variables to 1
    6119 *
    6120 * e.g. x1 * x2 + x1 * x3 + x1 * x4 >= 1
    6121 * => x1 = 1 /\ x2 + x3 + x4 >= 1
    6122 *
    6123 * e.g. x1 * x2 * x3 + x1 * x2 * x4 + x5 >= 1
    6124 * => 2x1 + 2x2 + x3 + x4 + 5x5 >= 5
    6125 *
    6126 * e.g. x1 * x2 * x3 + x1 * x4 >= 1
    6127 * => x1 = 1 /\ x2 * x3 + x4 >= 1 (constraint is created indirectly, caused by the fixing of x1)
    6128 *
    6129 * @todo: implement the next cases
    6130 *
    6131 * e.g. x1 * x2 * x3 + x1 * x4 + x5 >= 1
    6132 * => 2x1 + x2 * x3 + x4 + 3x5 >= 3 (x2 * x3 will be a new and-constraint)
    6133 *
    6134 * e.g. x1 * x2 + x1 * x2 * x3 + x4 >= 1
    6135 * => x1 + x2 + 2x4 >= 2
    6136 *
    6137 * e.g. x1 * x2 + x1 * x3 + x2 * x3 + sum_i x_i >= 1
    6138 * => x1 + x2 + x3 + 2 * sum_i x_i >= 2
    6139 *
    6140 */
    6141
    6142 /* Extract additional information ???
    6143 *
    6144 * e.g. x1 * x2 * x4 + x1 * x3 * x5 + x2 * x3 * x6 >= 1
    6145 * => extract x1 + x2 + x3 >= 2
    6146 */
    6147
    6148 /* if we have no normal linear variable in the logicor constraint, we can fix all equal variables */
    6149 if( neqvars > 0 && consdata->nlinvars == 0 )
    6150 {
    6151 SCIP_Bool infeasible;
    6152 SCIP_Bool fixed;
    6153
    6154 /* fix all equal variable in logicor constraints which have to be one to fulfill the constraint */
    6155 for( v = 0; v < neqvars; ++v )
    6156 {
    6157 /* fix the variable which cannot be one */
    6158 SCIP_CALL( SCIPfixVar(scip, eqvars[v], 1.0, &infeasible, &fixed) );
    6159 if( infeasible )
    6160 {
    6161 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    6162 *cutoff = TRUE;
    6163 goto TERMINATE;
    6164 }
    6165 if( fixed )
    6166 ++(*nfixedvars);
    6167 }
    6168
    6169 /* if a complete consanddata object have all variables in common with all other consanddata objects, than we can
    6170 * delete this constraint after fixing all equal variables
    6171 */
    6172 if( nminvars == neqvars )
    6173 {
    6174 /* delete old constraints */
    6175 SCIP_CALL( SCIPdelCons(scip, consdata->lincons) );
    6176 SCIP_CALL( SCIPdelCons(scip, cons) );
    6177 (*ndelconss) += 2;
    6178
    6179 goto TERMINATE;
    6180 }
    6181 }
    6182
    6183 /* now the following condition grant us that we can linearize the whole constraint */
    6184 if( neqvars > 0 && nminvars == nmaxvars && nminvars == neqvars + 1 )
    6185 {
    6186 SCIP_CONS* lincons;
    6187 SCIP_CONS* newcons;
    6188 char newname[SCIP_MAXSTRLEN];
    6189 SCIP_Real lhs;
    6190 SCIP_Real rhs;
    6191
    6192 lhs = 1.0;
    6193 rhs = SCIPinfinity(scip);
    6194
    6195 lincons = consdata->lincons;
    6196
    6197 (void) SCIPsnprintf(newname, SCIP_MAXSTRLEN, "%s_upgraded", SCIPconsGetName(lincons));
    6198
    6199 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, newname, 0, NULL, NULL, lhs, rhs,
    6200 SCIPconsIsInitial(lincons), SCIPconsIsSeparated(lincons), SCIPconsIsEnforced(lincons), SCIPconsIsChecked(lincons),
    6201 SCIPconsIsPropagated(lincons), SCIPconsIsLocal(lincons), SCIPconsIsModifiable(lincons),
    6202 SCIPconsIsDynamic(lincons), SCIPconsIsRemovable(lincons), SCIPconsIsStickingAtNode(lincons)) );
    6203
    6204 /* if createcons == TRUE add all variables which are not in the eqvars array to the new constraint with
    6205 * coefficient 1.0
    6206 */
    6207 for( c = nconsanddatas - 1; c >= 0; --c )
    6208 {
    6209 CONSANDDATA* consanddata;
    6210 SCIP_VAR** vars;
    6211 int nvars;
    6212
    6213 consanddata = consanddatas[c];
    6214 assert(consanddata != NULL);
    6215 assert(consanddatas[c]->istransformed);
    6216
    6217 /* choose correct variable array to add locks for, we only add locks for now valid variables */
    6218 if( consanddata->nnewvars > 0 )
    6219 {
    6220 vars = consanddata->newvars;
    6221 nvars = consanddata->nnewvars;
    6222 }
    6223 else
    6224 {
    6225 vars = consanddata->vars;
    6226 nvars = consanddata->nvars;
    6227 }
    6228 assert(nvars > 0 && vars != NULL);
    6229
    6230 for( v = 0, v2 = 0; v < neqvars && v2 < nvars; )
    6231 {
    6232 int index1;
    6233 int index2;
    6234
    6235 assert(eqvars[v] != NULL);
    6236 assert(vars[v2] != NULL);
    6237 index1 = SCIPvarGetIndex(eqvars[v]);
    6238 index2 = SCIPvarGetIndex(vars[v2]);
    6239
    6240 /* all variables in eqvars array must exist in all and-constraints */
    6241 assert(index1 >= index2);
    6242
    6243 if( index1 > index2 )
    6244 {
    6245 SCIP_CALL( SCIPaddCoefLinear(scip, newcons, vars[v2], 1.0) );
    6246 ++v2;
    6247 }
    6248 else
    6249 {
    6250 assert(index1 == index2);
    6251 ++v;
    6252 ++v2;
    6253 }
    6254 }
    6255
    6256 /* if we did not loop over all variables in the and-constraint, go on and fix variables */
    6257 if( v2 < nvars )
    6258 {
    6259 assert(v == neqvars);
    6260 for( ; v2 < nvars; ++v2)
    6261 {
    6262 SCIP_CALL( SCIPaddCoefLinear(scip, newcons, vars[v2], 1.0) );
    6263 }
    6264 }
    6265 assert(v == neqvars && v2 == nvars);
    6266 }
    6267
    6268 /* if we have normal linear variable in the logicor constraint, we did not fix all equal variables and we have to
    6269 * add them with a coefficient of 'nconsanddatas'
    6270 * we have to add also all normal linear variables with a coefficient of 'nconsanddatas * neqvars + 1'
    6271 */
    6272 if( consdata->nlinvars > 0 )
    6273 {
    6274 SCIP_VAR** vars;
    6275 SCIP_Real* coefs;
    6276 int nvars;
    6277 SCIP_VAR** linvars;
    6278 SCIP_Real* lincoefs;
    6279 int nlinvars;
    6280
    6281 /* add all equal variables */
    6282 for( v = 0; v < neqvars; ++v )
    6283 {
    6284 SCIP_CALL( SCIPaddCoefLinear(scip, newcons, eqvars[v], (SCIP_Real)nconsanddatas) );
    6285 }
    6286
    6287 /* check number of linear variables */
    6288 SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
    6289 assert(nvars == consdata->nlinvars + consdata->nconsanddatas);
    6290
    6291 /* allocate temporary memory */
    6292 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    6293 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
    6294 SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nvars) );
    6295 SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nvars) );
    6296
    6297 /* get variables and coefficients */
    6298 SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) );
    6299 assert(coefs != NULL || nvars == 0);
    6300
    6301#ifndef NDEBUG
    6302 /* all coefficients have to be 1 */
    6303 for( v = 0; v < nvars; ++v )
    6304 assert(SCIPisEQ(scip, coefs[v], 1.0));
    6305#endif
    6306 /* calculate all not artificial linear variables */
    6307 SCIP_CALL( getLinVarsAndAndRess(scip, cons, vars, coefs, nvars, linvars, lincoefs, &nlinvars,
    6308 NULL, NULL, NULL, NULL) );
    6309 assert(nlinvars == consdata->nlinvars);
    6310
    6311 /* add all old normal linear variables */
    6312 for( v = 0; v < nlinvars; ++v )
    6313 {
    6314 SCIP_CALL( SCIPaddCoefLinear(scip, newcons, linvars[v], (SCIP_Real)(nconsanddatas * neqvars + 1)) ); /*lint !e732 !e790*/
    6315 }
    6316
    6317 /* reset left hand side to correct value */
    6318 SCIP_CALL( SCIPchgLhsLinear(scip, newcons, (SCIP_Real)(nconsanddatas * neqvars + 1)) ); /*lint !e732 !e790*/
    6319
    6320 /* free temporary memory */
    6321 SCIPfreeBufferArray(scip, &lincoefs);
    6322 SCIPfreeBufferArray(scip, &linvars);
    6323 SCIPfreeBufferArray(scip, &coefs);
    6324 SCIPfreeBufferArray(scip, &vars);
    6325 }
    6326
    6327 /* add and release new constraint */
    6328 SCIP_CALL( SCIPaddCons(scip, newcons) );
    6329
    6330 SCIPdebugMsg(scip, "created upgraded linear constraint:\n");
    6331 SCIPdebugMsg(scip, "old -> ");
    6332 SCIPdebugPrintCons(scip, lincons, NULL);
    6333 SCIPdebugMsg(scip, "new -> ");
    6334 SCIPdebugPrintCons(scip, newcons, NULL);
    6335
    6336 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    6337 ++(*naddconss);
    6338
    6339 /* delete old constraints */
    6340 SCIP_CALL( SCIPdelCons(scip, lincons) );
    6341 SCIP_CALL( SCIPdelCons(scip, cons) );
    6342 (*ndelconss) += 2;
    6343 }
    6344
    6345 TERMINATE:
    6346 /* free temporary memory */
    6347 SCIPfreeBufferArray(scip, &eqvars);
    6348
    6349 return SCIP_OKAY;
    6350}
    6351
    6352/** try upgrading pseudoboolean setppc constraint to a linear constraint and/or remove possible and-constraints */
    6353static
    6355 SCIP*const scip, /**< SCIP data structure */
    6356 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    6357 SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
    6358 int*const ndelconss, /**< pointer to store number of deleted constraints */
    6359 int*const naddconss, /**< pointer to count number of added constraints */
    6360 int*const nfixedvars, /**< pointer to store number of fixed variables */
    6361 int*const nchgcoefs, /**< pointer to store number of changed coefficients constraints */
    6362 int*const nchgsides, /**< pointer to store number of changed sides constraints */
    6363 SCIP_Bool*const cutoff /**< pointer to store if a cutoff happened */
    6364 )
    6365{
    6366 CONSANDDATA** consanddatas;
    6367 int nconsanddatas;
    6368 SCIP_CONSDATA* consdata;
    6369 SCIP_SETPPCTYPE type;
    6370 int c;
    6371 int v;
    6372 int v2;
    6373 SCIP_VAR** eqvars;
    6374 int neqvars;
    6375 int nminvars;
    6376 int nmaxvars;
    6377
    6378 assert(scip != NULL);
    6379 assert(cons != NULL);
    6380 assert(conshdlrdata != NULL);
    6381 assert(ndelconss != NULL);
    6382 assert(nfixedvars != NULL);
    6383 assert(nchgcoefs != NULL);
    6384 assert(nchgsides != NULL);
    6385 assert(cutoff != NULL);
    6386 assert(SCIPconsIsActive(cons));
    6387
    6388 consdata = SCIPconsGetData(cons);
    6389 assert(consdata != NULL);
    6390
    6391 consanddatas = consdata->consanddatas;
    6392 nconsanddatas = consdata->nconsanddatas;
    6393 assert(nconsanddatas > 0 && consanddatas != NULL);
    6394
    6395 assert(consdata->lincons != NULL);
    6396 assert(consdata->linconstype == SCIP_LINEARCONSTYPE_SETPPC);
    6397
    6398 type = SCIPgetTypeSetppc(scip, consdata->lincons);
    6399
    6400 switch( type )
    6401 {
    6404 break;
    6406 return SCIP_OKAY;
    6407 default:
    6408 SCIPerrorMessage("unknown setppc type\n");
    6409 return SCIP_INVALIDDATA;
    6410 }
    6411
    6412 assert(consanddatas[0] != NULL);
    6413 assert(consanddatas[0]->cons != NULL);
    6414
    6415 if( nconsanddatas == 1 )
    6416 {
    6417 /* if we have only one term left in the setppc constraint, the presolving should be done by the setppc constraint handler */
    6418 if( consdata->nlinvars == 0 )
    6419 {
    6420 return SCIP_OKAY;
    6421 }
    6422
    6423 /* @todo: implement the following */
    6424
    6425 /* for each set packing constraint:
    6426 * sum_i (x_i) + res <= 1 , with and-constraint of res as the resultant like res = y_1 * ... * y_n
    6427 * => sum_i (n * x_i) + sum_j=1^n y_j <= n + n-1
    6428 *
    6429 * i.e. x_1 + x_2 + x_3 + x_4*x_5*x_6 <= 1
    6430 * => 3x_1 + 3x_2 + 3x_3 + x_4 + x_5 + x_6 <= 5
    6431 */
    6432
    6433 /* for each set partitioning constraint:
    6434 * sum_i (x_i) + res = 1 , with the corresponding and-constraint of res like
    6435 * res = y_1 * ... * y_n
    6436 *
    6437 * => n <= sum_i (n * x_i) + sum_j=1^n y_j <= 2 * n - 1
    6438 *
    6439 * i.e. x_1 + x_2 + x_3 + x_4*x_5*x_6 = 1
    6440 * => 3 <= 3x_1 + 3x_2 + 3x_3 + x_4 + x_5 + x_6 <= 5
    6441 *
    6442 */
    6443
    6444 return SCIP_OKAY;
    6445 }
    6446
    6447 if( consdata->nlinvars > 0 )
    6448 {
    6449 /* @todo: */
    6450 return SCIP_OKAY;
    6451 }
    6452 assert(consdata->nlinvars == 0 && nconsanddatas > 1);
    6453
    6454 c = nconsanddatas - 1;
    6455 assert(consanddatas[c]->istransformed);
    6456
    6457 /* initializing array for variables which can appear in all consanddata objects */
    6458 if( consanddatas[c]->nnewvars > 0 )
    6459 {
    6460 neqvars = consanddatas[c]->nnewvars;
    6461 /* allocate temporary memory */
    6462 SCIP_CALL( SCIPduplicateBufferArray(scip, &eqvars, consanddatas[c]->newvars, neqvars) );
    6463 }
    6464 else
    6465 {
    6466 neqvars = consanddatas[c]->nvars;
    6467 /* allocate temporary memory */
    6468 SCIP_CALL( SCIPduplicateBufferArray(scip, &eqvars, consanddatas[c]->vars, neqvars) );
    6469 }
    6470 nminvars = neqvars;
    6471 nmaxvars = neqvars;
    6472 assert(neqvars > 0 && eqvars != NULL);
    6473
    6474#ifndef NDEBUG
    6475 /* check that variables are sorted */
    6476 for( v = neqvars - 1; v > 0; --v )
    6477 assert(SCIPvarGetIndex(eqvars[v]) > SCIPvarGetIndex(eqvars[v - 1]));
    6478#endif
    6479
    6480 for( --c ; c >= 0; --c )
    6481 {
    6482 CONSANDDATA* consanddata;
    6483 SCIP_VAR** vars;
    6484 int nvars;
    6485 int nneweqvars;
    6486
    6487 consanddata = consanddatas[c];
    6488 assert(consanddata != NULL);
    6489 assert(consanddatas[c]->istransformed);
    6490
    6491 /* choose correct variable array to add locks for, we only add locks for now valid variables */
    6492 if( consanddata->nnewvars > 0 )
    6493 {
    6494 vars = consanddata->newvars;
    6495 nvars = consanddata->nnewvars;
    6496 }
    6497 else
    6498 {
    6499 vars = consanddata->vars;
    6500 nvars = consanddata->nvars;
    6501 }
    6502 assert(nvars > 0 && vars != NULL);
    6503
    6504#ifndef NDEBUG
    6505 /* check that variables are sorted */
    6506 for( v = nvars - 1; v > 0; --v )
    6507 assert(SCIPvarGetIndex(vars[v]) > SCIPvarGetIndex(vars[v - 1]));
    6508#endif
    6509
    6510 /* update minimal number of variables in and-constraint */
    6511 if( nvars < nminvars )
    6512 nminvars = nvars;
    6513 /* update maximal number of variables in and-constraint */
    6514 else if( nvars > nmaxvars )
    6515 nmaxvars = nvars;
    6516 assert(nminvars > 0);
    6517 assert(nminvars <= nmaxvars);
    6518
    6519 nneweqvars = 0;
    6520 for( v = 0, v2 = 0; v < neqvars && v2 < nvars; )
    6521 {
    6522 int index1;
    6523 int index2;
    6524
    6525 assert(eqvars[v] != NULL);
    6526 assert(vars[v2] != NULL);
    6527 index1 = SCIPvarGetIndex(eqvars[v]);
    6528 index2 = SCIPvarGetIndex(vars[v2]);
    6529
    6530 /* check which variables are still in all and-constraints */
    6531 if( index1 < index2 )
    6532 ++v;
    6533 else if( index1 > index2 )
    6534 ++v2;
    6535 else
    6536 {
    6537 assert(index1 == index2);
    6538 assert(nneweqvars <= v);
    6539
    6540 if( nneweqvars < v )
    6541 eqvars[nneweqvars] = eqvars[v];
    6542 ++nneweqvars;
    6543 ++v;
    6544 ++v2;
    6545 }
    6546 }
    6547 neqvars = nneweqvars;
    6548
    6549 /* now we only want to handle the easy case where nminvars == neqvars + 1
    6550 * @todo: implement for the othercase too
    6551 */
    6552 if( nminvars > neqvars + 1 && type != SCIP_SETPPCTYPE_PARTITIONING)
    6553 break;
    6554
    6555 if( neqvars == 0 )
    6556 break;
    6557 }
    6558
    6559 /* if all and-constraints in pseudoboolean constraint have the same length and some equal variables we can upgrade
    6560 * the linear constraint and fix some variables in setpartitioning case
    6561 *
    6562 * e.g. x1 * x2 + x1 * x3 + x1 * x4 <= 1
    6563 * => 3x1 + x2 + x3 + x4 <= 4
    6564 *
    6565 * e.g. x1 * x2 * x3 + x1 * x2 * x4 <= 1
    6566 * => 2x1 + 2x2 + x3 + x4 <= 5
    6567 *
    6568 * e.g. x1 * x2 + x1 * x2 * x3 + x1 * x2 * x4 <= 1
    6569 * => 3x1 + 3x2 + x3 + x4 <= 6
    6570 *
    6571 * e.g. x1 * x2 + x1 * x3 == 1
    6572 * => x1 = 1 /\ x2 + x3 == 1
    6573 *
    6574 * e.g. x1 * x2 * x3 + x1 * x4 == 1
    6575 * => x1 = 1 /\ x2 * x3 + x4 == 1 (constraint is created indirectly, caused by the fixing of x1)
    6576 *
    6577 * e.g. x1 * x2 + x1 * x2 * x3 + x1 * x2 * x4 == 1
    6578 * => x1 = 1, x2 = 1, x3 = 0, x4 = 0
    6579 *
    6580 * e.g. x1 * x2 + x1 * x2 * x3 + x1 * x2 * x4 * x5 == 1
    6581 * => x1 = 1, x2 = 1, x3 = 0 /\ x4 * x5 == 0
    6582 *
    6583 * @todo: implement the next cases
    6584 *
    6585 * e.g. x1 * x2 * x3 + x1 * x2 * x4 + x5 <= 1
    6586 * => 2x1 + 2x2 + x3 + x4 + x5 <= 5
    6587 *
    6588 */
    6589 if( neqvars > 0 && ((nminvars == nmaxvars && nminvars == neqvars + 1) || (nminvars == neqvars) || (type == SCIP_SETPPCTYPE_PARTITIONING)) )
    6590 {
    6591 SCIP_CONS* lincons;
    6592 SCIP_CONS* newcons;
    6593 char newname[SCIP_MAXSTRLEN];
    6594 SCIP_Real lhs;
    6595 SCIP_Real rhs;
    6596 SCIP_Bool infeasible;
    6597 SCIP_Bool fixed;
    6598 SCIP_Bool createcons;
    6599 SCIP_Bool deletecons;
    6600
    6601 newcons = NULL;
    6602
    6603 /* determine new sides of linear constraint */
    6604 if( type == SCIP_SETPPCTYPE_PARTITIONING )
    6605 {
    6606 lhs = 1.0;
    6607 rhs = 1.0;
    6608 }
    6609 else
    6610 {
    6611 assert(type == SCIP_SETPPCTYPE_PACKING);
    6612 lhs = -SCIPinfinity(scip);
    6613 rhs = 1.0;
    6614 }
    6615
    6616 /* if one and-constraint was completely contained in all other and-constraints, we have to reduced the right hand
    6617 * side by 1
    6618 */
    6619 if( neqvars == nminvars )
    6620 rhs -= 1.0;
    6621
    6622 createcons = (SCIPisLE(scip, lhs, rhs) && ((nminvars == nmaxvars && nminvars == neqvars + 1) || (nminvars == neqvars)));
    6623 assert(createcons || type == SCIP_SETPPCTYPE_PARTITIONING);
    6624
    6625 deletecons = (type == SCIP_SETPPCTYPE_PARTITIONING && nminvars == neqvars);
    6626
    6627 lincons = consdata->lincons;
    6628
    6629 if( createcons )
    6630 {
    6631 (void) SCIPsnprintf(newname, SCIP_MAXSTRLEN, "%s_upgraded", SCIPconsGetName(lincons));
    6632
    6633 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, newname, 0, NULL, NULL, lhs, rhs,
    6634 SCIPconsIsInitial(lincons), SCIPconsIsSeparated(lincons), SCIPconsIsEnforced(lincons), SCIPconsIsChecked(lincons),
    6635 SCIPconsIsPropagated(lincons), SCIPconsIsLocal(lincons), SCIPconsIsModifiable(lincons),
    6636 SCIPconsIsDynamic(lincons), SCIPconsIsRemovable(lincons), SCIPconsIsStickingAtNode(lincons)) );
    6637 }
    6638
    6639 /* if createcons == TRUE add all variables which are not in the eqvars array to the new constraint with
    6640 * coefficient 1.0
    6641 *
    6642 * otherwise (if createcons == FALSE) fix all variables to zero which are not in the eqvars array and if we have a
    6643 * set partitioning constraint
    6644 */
    6645 for( c = nconsanddatas - 1; c >= 0; --c )
    6646 {
    6647 CONSANDDATA* consanddata;
    6648 SCIP_VAR** vars;
    6649 int nvars;
    6650
    6651 consanddata = consanddatas[c];
    6652 assert(consanddata != NULL);
    6653 assert(consanddatas[c]->istransformed);
    6654
    6655 /* choose correct variable array to add locks for, we only add locks for now valid variables */
    6656 if( consanddata->nnewvars > 0 )
    6657 {
    6658 vars = consanddata->newvars;
    6659 nvars = consanddata->nnewvars;
    6660 }
    6661 else
    6662 {
    6663 vars = consanddata->vars;
    6664 nvars = consanddata->nvars;
    6665 }
    6666 assert(nvars > 0 && vars != NULL);
    6667
    6668 /* if the consanddata object has at least two more different variables then the equal variables we have to fix the resultant to zero */
    6669 if( deletecons && neqvars + 1 < nvars )
    6670 {
    6671 assert(SCIPgetResultantAnd(scip, consanddata->cons) != NULL);
    6672
    6673 /* fix the resultant variable which have to be zero */
    6674 SCIP_CALL( SCIPfixVar(scip, SCIPgetResultantAnd(scip, consanddata->cons), 0.0, &infeasible, &fixed) );
    6675 if( infeasible )
    6676 {
    6677 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    6678 *cutoff = TRUE;
    6679 goto TERMINATE;
    6680 }
    6681 if( fixed )
    6682 ++(*nfixedvars);
    6683
    6684 continue;
    6685 }
    6686
    6687 /* if the consanddata object has at exactly one more different variable then the equal variables we have to fix it to zero */
    6688 for( v = 0, v2 = 0; v < neqvars && v2 < nvars; )
    6689 {
    6690 int index1;
    6691 int index2;
    6692
    6693 assert(eqvars[v] != NULL);
    6694 assert(vars[v2] != NULL);
    6695 index1 = SCIPvarGetIndex(eqvars[v]);
    6696 index2 = SCIPvarGetIndex(vars[v2]);
    6697
    6698 /* all variables in eqvars array must exist in all and-constraints */
    6699 assert(index1 >= index2);
    6700
    6701 if( index1 > index2 )
    6702 {
    6703 if( createcons )
    6704 {
    6705 assert(newcons != NULL);
    6706 SCIP_CALL( SCIPaddCoefLinear(scip, newcons, vars[v2], 1.0) );
    6707 }
    6708 else if( deletecons )
    6709 {
    6710 /* fix the variable which cannot be one */
    6711 SCIP_CALL( SCIPfixVar(scip, vars[v2], 0.0, &infeasible, &fixed) );
    6712 if( infeasible )
    6713 {
    6714 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    6715 *cutoff = TRUE;
    6716 goto TERMINATE;
    6717 }
    6718 if( fixed )
    6719 ++(*nfixedvars);
    6720 }
    6721 ++v2;
    6722 }
    6723 else
    6724 {
    6725 assert(index1 == index2);
    6726
    6727 ++v;
    6728 ++v2;
    6729 }
    6730 }
    6731
    6732 /* if we did not loop over all variables in the and-constraint, go on and fix variables */
    6733 if( v2 < nvars )
    6734 {
    6735 assert(v == neqvars);
    6736 for( ; v2 < nvars; ++v2)
    6737 {
    6738 if( createcons )
    6739 {
    6740 SCIP_CALL( SCIPaddCoefLinear(scip, newcons, vars[v2], 1.0) );
    6741 }
    6742 else if( deletecons )
    6743 {
    6744 /* fix the variable which cannot be one */
    6745 SCIP_CALL( SCIPfixVar(scip, vars[v2], 0.0, &infeasible, &fixed) );
    6746 if( infeasible )
    6747 {
    6748 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    6749 *cutoff = TRUE;
    6750 goto TERMINATE;
    6751 }
    6752 if( fixed )
    6753 ++(*nfixedvars);
    6754 }
    6755 }
    6756 }
    6757 assert(v == neqvars && v2 == nvars);
    6758 }
    6759
    6760 /* fix all equal variable in set-partitioning constraints which have to be one, in set-packing constraint we have
    6761 * to add these variable with a coeffcient as big as (nconsanddatas - 1)
    6762 */
    6763 for( v = 0; v < neqvars; ++v )
    6764 {
    6765 if( type == SCIP_SETPPCTYPE_PARTITIONING )
    6766 {
    6767 /* fix the variable which have to be one */
    6768 SCIP_CALL( SCIPfixVar(scip, eqvars[v], 1.0, &infeasible, &fixed) );
    6769 if( infeasible )
    6770 {
    6771 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    6772 *cutoff = TRUE;
    6773 goto TERMINATE;
    6774 }
    6775 if( fixed )
    6776 ++(*nfixedvars);
    6777 }
    6778 else
    6779 {
    6780 assert(type == SCIP_SETPPCTYPE_PACKING);
    6781 SCIP_CALL( SCIPaddCoefLinear(scip, newcons, eqvars[v], (SCIP_Real)(nconsanddatas - 1)) );
    6782 }
    6783 }
    6784
    6785 /* correct right hand side for set packing constraint */
    6786 if( type == SCIP_SETPPCTYPE_PACKING )
    6787 {
    6788 assert(createcons);
    6789 assert(newcons != NULL);
    6790
    6791 SCIP_CALL( SCIPchgRhsLinear(scip, newcons, rhs + (SCIP_Real)((nconsanddatas - 1) * neqvars)) ); /*lint !e790*/
    6792 }
    6793
    6794 /* add and release new constraint */
    6795 if( createcons )
    6796 {
    6797 SCIP_CALL( SCIPaddCons(scip, newcons) );
    6798
    6799 SCIPdebugMsg(scip, "created upgraded linear constraint:\n");
    6800 SCIPdebugMsg(scip, "old -> ");
    6801 SCIPdebugPrintCons(scip, lincons, NULL);
    6802 SCIPdebugMsg(scip, "new -> ");
    6803 SCIPdebugPrintCons(scip, newcons, NULL);
    6804
    6805 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    6806 ++(*naddconss);
    6807
    6808 assert(!deletecons);
    6809 deletecons = TRUE;
    6810 }
    6811
    6812 if( deletecons )
    6813 {
    6814 /* delete old constraints */
    6815 SCIP_CALL( SCIPdelCons(scip, lincons) );
    6816 SCIP_CALL( SCIPdelCons(scip, cons) );
    6817 (*ndelconss) += 2;
    6818 }
    6819 }
    6820
    6821 TERMINATE:
    6822 /* free temporary memory */
    6823 SCIPfreeBufferArray(scip, &eqvars);
    6824
    6825 return SCIP_OKAY;
    6826}
    6827
    6828/** try upgrading pseudoboolean constraint to a linear constraint and/or remove possible and-constraints */
    6829static
    6831 SCIP*const scip, /**< SCIP data structure */
    6832 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    6833 SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
    6834 int*const ndelconss, /**< pointer to store number of upgraded constraints */
    6835 int*const naddconss, /**< pointer to count number of added constraints */
    6836 int*const nfixedvars, /**< pointer to store number of fixed variables */
    6837 int*const nchgcoefs, /**< pointer to store number of changed coefficients constraints */
    6838 int*const nchgsides, /**< pointer to store number of changed sides constraints */
    6839 SCIP_Bool*const cutoff /**< pointer to store if a cutoff happened */
    6840 )
    6841{
    6842 SCIP_CONSDATA* consdata;
    6843 int nvars;
    6844
    6845 assert(scip != NULL);
    6846 assert(cons != NULL);
    6847 assert(conshdlrdata != NULL);
    6848 assert(ndelconss != NULL);
    6849 assert(nfixedvars != NULL);
    6850 assert(nchgcoefs != NULL);
    6851 assert(nchgsides != NULL);
    6852 assert(cutoff != NULL);
    6853 assert(SCIPconsIsActive(cons));
    6854
    6855 consdata = SCIPconsGetData(cons);
    6856 assert(consdata != NULL);
    6857 assert(consdata->lincons != NULL);
    6858
    6859 /* if no consanddata-objects in pseudoboolean constraint are left, create the corresponding linear constraint */
    6860 if( consdata->nconsanddatas == 0 )
    6861 {
    6862 SCIPconsAddUpgradeLocks(consdata->lincons, -1);
    6863
    6864 /* @todo: maybe it is better to create everytime a standard linear constraint instead of letting the special
    6865 * linear constraint stay
    6866 */
    6867 SCIP_CALL( SCIPdelCons(scip, cons) );
    6868 ++(*ndelconss);
    6869
    6870 return SCIP_OKAY;
    6871 }
    6872
    6873 assert(consdata->consanddatas != NULL);
    6874
    6875 /* check number of linear variables */
    6876 SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
    6877 assert(consdata->nlinvars + consdata->nconsanddatas == nvars);
    6878
    6879 switch( consdata->linconstype )
    6880 {
    6882 SCIP_CALL( tryUpgradingXor(scip, cons, conshdlrdata, ndelconss, naddconss, nfixedvars, nchgcoefs, nchgsides, cutoff) );
    6883 break;
    6885 SCIP_CALL( tryUpgradingLogicor(scip, cons, conshdlrdata, ndelconss, naddconss, nfixedvars, nchgcoefs, nchgsides, cutoff) );
    6886 break;
    6888 break;
    6890 SCIP_CALL( tryUpgradingSetppc(scip, cons, conshdlrdata, ndelconss, naddconss, nfixedvars, nchgcoefs, nchgsides, cutoff) );
    6891 if( !SCIPconsIsDeleted(cons) )
    6892 {
    6893 SCIP_CALL( tryUpgradingXor(scip, cons, conshdlrdata, ndelconss, naddconss, nfixedvars, nchgcoefs, nchgsides, cutoff) );
    6894 }
    6895 break;
    6896#ifdef WITHEQKNAPSACK
    6897 case SCIP_LINEARCONSTYPE_EQKNAPSACK:
    6898 SCIP_CALL( tryUpgradingXor(scip, cons, conshdlrdata, ndelconss, naddconss, nfixedvars, nchgcoefs, nchgsides, cutoff) );
    6899#endif
    6901 default:
    6902 SCIPerrorMessage("unknown linear constraint type\n");
    6903 return SCIP_INVALIDDATA;
    6904 }
    6905
    6906 if( SCIPconsIsDeleted(cons) )
    6907 {
    6908 /* update the uses counter of consandata objects which are used in pseudoboolean constraint, which was deleted and
    6909 * probably delete and-constraints
    6910 */
    6911 SCIP_CALL( updateConsanddataUses(scip, cons, conshdlrdata, ndelconss) );
    6912 }
    6913
    6914 consdata->upgradetried = TRUE;
    6915
    6916 return SCIP_OKAY;
    6917}
    6918
    6919/** check if we can aggregated some variables */
    6920static
    6922 SCIP*const scip, /**< SCIP data structure */
    6923 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    6924 SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
    6925 int*const ndelconss, /**< pointer to store number of upgraded constraints */
    6926 int*const naggrvars, /**< pointer to store number of aggregated variables */
    6927 SCIP_Bool*const cutoff /**< pointer to store if a cutoff happened */
    6928 )
    6929{
    6930 CONSANDDATA** consanddatas;
    6931 SCIP_CONSDATA* consdata;
    6932 SCIP_VAR** allvars;
    6933 int* varcount[2];
    6934 SCIP_VAR** repvars;
    6935 SCIP_Bool* negated;
    6936 SCIP_VAR** vars;
    6937 int nconsanddatas;
    6938 int nvars;
    6939 int zerocount;
    6940 int onecount;
    6941 int twocount;
    6942 int othercount;
    6943 int c;
    6944 int v;
    6945 int i;
    6946
    6947 assert(scip != NULL);
    6948 assert(cons != NULL);
    6949 assert(conshdlrdata != NULL);
    6950 assert(ndelconss != NULL);
    6951 assert(naggrvars != NULL);
    6952 assert(cutoff != NULL);
    6953 assert(SCIPconsIsActive(cons));
    6954
    6955 if( SCIPconsIsModifiable(cons) )
    6956 return SCIP_OKAY;
    6957
    6958 consdata = SCIPconsGetData(cons);
    6959 assert(consdata != NULL);
    6960 assert(consdata->lincons != NULL);
    6961
    6962 consanddatas = consdata->consanddatas;
    6963 nconsanddatas = consdata->nconsanddatas;
    6964 assert(consanddatas != NULL || nconsanddatas == 0);
    6965
    6966 /* we have only one special case for aggregations, a set-partinioning constraint */
    6967 if( consdata->linconstype != SCIP_LINEARCONSTYPE_SETPPC || SCIPgetTypeSetppc(scip, consdata->lincons) != SCIP_SETPPCTYPE_PARTITIONING )
    6968 return SCIP_OKAY;
    6969
    6970 assert(SCIPisEQ(scip, consdata->rhs, consdata->lhs));
    6971 assert(SCIPisEQ(scip, consdata->rhs, 1.0));
    6972
    6973 if( nconsanddatas < 2 || nconsanddatas > 3 )
    6974 return SCIP_OKAY;
    6975
    6976#ifndef NDEBUG
    6977 /* check number of linear variables */
    6978 SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
    6979 assert(consdata->nlinvars + nconsanddatas == nvars);
    6980#endif
    6981
    6982 if( consdata->nlinvars != 1 )
    6983 return SCIP_OKAY;
    6984
    6985 /* check valid number of variables */
    6986 if( consanddatas[0]->nnewvars > 0 )
    6987 nvars = consanddatas[0]->nnewvars;
    6988 else
    6989 nvars = consanddatas[0]->nvars;
    6990
    6991 if( consanddatas[1]->nnewvars > 0 )
    6992 {
    6993 if( nvars != consanddatas[1]->nnewvars )
    6994 return SCIP_OKAY;
    6995 }
    6996 else if( nvars != consanddatas[1]->nvars )
    6997 return SCIP_OKAY;
    6998
    6999 /* allocate temporary memory */
    7000 SCIP_CALL( SCIPallocBufferArray(scip, &allvars, nvars) );
    7001 SCIP_CALL( SCIPallocBufferArray(scip, &(varcount[0]), nvars) );
    7002 BMSclearMemoryArray(varcount[0], nvars);
    7003 SCIP_CALL( SCIPallocBufferArray(scip, &(varcount[1]), nvars) );
    7004 BMSclearMemoryArray(varcount[1], nvars);
    7005
    7006 SCIP_CALL( SCIPallocBufferArray(scip, &repvars, nvars) );
    7007 SCIP_CALL( SCIPallocBufferArray(scip, &negated, nvars) );
    7008 BMSclearMemoryArray(negated, nvars);
    7009
    7010 /* get valid variables */
    7011 if( consanddatas[nconsanddatas - 1]->nnewvars > 0 )
    7012 vars = consanddatas[nconsanddatas - 1]->newvars;
    7013 else
    7014 vars = consanddatas[nconsanddatas - 1]->vars;
    7015
    7016 /* get linear active representation */
    7017 SCIP_CALL( SCIPgetBinvarRepresentatives(scip, nvars, vars, repvars, negated) );
    7018 SCIPsortPtrBool((void**)repvars, negated, SCIPvarCompActiveAndNegated, nvars);
    7019
    7020#ifndef NDEBUG
    7021 /* and-constraints have to be merged in order to check for aggregation */
    7022 for( v = 1; v < nvars; ++v )
    7023 {
    7024 SCIP_VAR* var1;
    7025 SCIP_VAR* var2;
    7026
    7027 /* it appears that some fixed variables were not yet deleted */
    7028 if( SCIPvarGetLbGlobal(repvars[v-1]) > 0.5 || SCIPvarGetUbGlobal(repvars[v-1]) < 0.5 )
    7029 goto TERMINATE;
    7030
    7031 /* it appears that some fixed variables were not yet deleted */
    7032 if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 )
    7033 goto TERMINATE;
    7034
    7035 assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v]))));
    7036 assert(SCIPvarIsActive(repvars[v-1]) || (SCIPvarIsNegated(repvars[v-1]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v-1]))));
    7037 assert(SCIPvarIsActive(repvars[v]) != negated[v]);
    7038 assert(SCIPvarIsActive(repvars[v-1]) != negated[v-1]);
    7039
    7040 var1 = (negated[v-1] ? SCIPvarGetNegationVar(repvars[v-1]) : repvars[v-1]);
    7041 var2 = (negated[v] ? SCIPvarGetNegationVar(repvars[v]) : repvars[v]);
    7042 assert(var1 != var2);
    7043 }
    7044#endif
    7045
    7046 /* initializing the statuses of all appearing variables */
    7047 for( v = nvars - 1; v >= 0; --v )
    7048 {
    7049 /* it appears that some fixed variables were not yet deleted */
    7050 if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 )
    7051 goto TERMINATE;
    7052
    7053 assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v]))));
    7054 assert(SCIPvarIsActive(repvars[v]) != negated[v]);
    7055
    7056 allvars[v] = negated[v] ? SCIPvarGetNegationVar(repvars[v]) : repvars[v];
    7057
    7058 ++(varcount[negated[v]][v]);
    7059 }
    7060
    7061 for( c = nconsanddatas - 2; c >= 0; --c )
    7062 {
    7063 int pos = -1;
    7064
    7065 /* get valid variables */
    7066 if( consanddatas[nconsanddatas - 1]->nnewvars > 0 )
    7067 vars = consanddatas[c]->newvars;
    7068 else
    7069 vars = consanddatas[c]->vars;
    7070
    7071 /* need to reset the negated flags */
    7072 BMSclearMemoryArray(negated, nvars);
    7073
    7074 /* get linear active representation */
    7075 SCIP_CALL( SCIPgetBinvarRepresentatives(scip, nvars, vars, repvars, negated) );
    7076 SCIPsortPtrBool((void**)repvars, negated, SCIPvarCompActiveAndNegated, nvars);
    7077
    7078#ifndef NDEBUG
    7079 /* and-constraints have to be merged in order to check for aggregation */
    7080 for( v = 1; v < nvars; ++v )
    7081 {
    7082 SCIP_VAR* var1;
    7083 SCIP_VAR* var2;
    7084
    7085 /* it appears that some fixed variables were not yet deleted */
    7086 if( SCIPvarGetLbGlobal(repvars[v-1]) > 0.5 || SCIPvarGetUbGlobal(repvars[v-1]) < 0.5 )
    7087 goto TERMINATE;
    7088
    7089 /* it appears that some fixed variables were not yet deleted */
    7090 if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 )
    7091 goto TERMINATE;
    7092
    7093 assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v]))));
    7094 assert(SCIPvarIsActive(repvars[v-1]) || (SCIPvarIsNegated(repvars[v-1]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v-1]))));
    7095 assert(SCIPvarIsActive(repvars[v]) != negated[v]);
    7096 assert(SCIPvarIsActive(repvars[v-1]) != negated[v-1]);
    7097
    7098 var1 = (negated[v-1] ? SCIPvarGetNegationVar(repvars[v-1]) : repvars[v-1]);
    7099 var2 = (negated[v] ? SCIPvarGetNegationVar(repvars[v]) : repvars[v]);
    7100 assert(var1 != var2);
    7101 }
    7102#endif
    7103
    7104 /* update the statuses of all appearing variables */
    7105 for( v = nvars - 1; v >= 0; --v )
    7106 {
    7107 /* it appears that some fixed variables were not yet deleted */
    7108 if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 )
    7109 goto TERMINATE;
    7110
    7111 assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v]))));
    7112 assert(SCIPvarIsActive(repvars[v]) != negated[v]);
    7113
    7114 /* we can only find an aggregation if all and constraints have the same variables */
    7115 if( SCIPsortedvecFindPtr((void**)allvars, SCIPvarCompActiveAndNegated, repvars[v], nvars, &pos) )
    7116 {
    7117 assert(pos >= 0 && pos < nvars);
    7118
    7119 ++(varcount[negated[v]][pos]);
    7120 }
    7121 else
    7122 goto TERMINATE;
    7123 }
    7124 }
    7125
    7126 zerocount = 0;
    7127 onecount = 0;
    7128 twocount = 0;
    7129 othercount = 0;
    7130
    7131 /* count number of multiple appearances of a variable */
    7132 for( i = 1; i >= 0; --i )
    7133 {
    7134 for( v = nvars - 1; v >= 0; --v )
    7135 {
    7136 assert(SCIPvarIsActive(allvars[v]));
    7137
    7138 if( varcount[i][v] == 0 )
    7139 ++zerocount;
    7140 else if( varcount[i][v] == 1 )
    7141 ++onecount;
    7142 else if( varcount[i][v] == 2 )
    7143 ++twocount;
    7144 else
    7145 ++othercount;
    7146 }
    7147 }
    7148
    7149 /* exactly one variable in all and-constraints appears as active and as negated variable */
    7150 if( othercount == 0 )
    7151 {
    7152 /* we have a constraint in the form of: x1 + x2 * x3 * ... * x_n + ~x2 * x3 * ... * x_n == 1
    7153 * this leads to the aggregation x1 = 1 - x3 * ... * x_n
    7154 */
    7155 if( nconsanddatas == 2 && twocount == nvars - 1 && onecount == 2 && zerocount == 1 )
    7156 {
    7157 SCIP_VAR** consvars;
    7158 SCIP_Real* conscoefs;
    7159 int nconsvars;
    7160 SCIP_VAR* linvar;
    7161 SCIP_Real lincoef;
    7162 int nlinvars;
    7163
    7164 /* allocate temporary memory */
    7165 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, consdata->nlinvars + nconsanddatas) );
    7166 SCIP_CALL( SCIPallocBufferArray(scip, &conscoefs, consdata->nlinvars + nconsanddatas) );
    7167
    7168 /* get variables and coefficients */
    7169 SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, consvars, conscoefs, &nconsvars) );
    7170 assert(nconsvars == consdata->nlinvars + nconsanddatas);
    7171 assert(conscoefs != NULL);
    7172
    7173#ifndef NDEBUG
    7174 /* all coefficients have to be 1 */
    7175 for( v = 0; v < nconsvars; ++v )
    7176 assert(SCIPisEQ(scip, conscoefs[v], 1.0));
    7177#endif
    7178 linvar = NULL;
    7179
    7180 /* calculate all not artificial linear variables */
    7181 SCIP_CALL( getLinVarsAndAndRess(scip, cons, consvars, conscoefs, nconsvars, &linvar, &lincoef, &nlinvars,
    7182 NULL, NULL, NULL, NULL) );
    7183 assert(nlinvars == 1);
    7184 assert(linvar != NULL);
    7185
    7186 SCIPfreeBufferArray(scip, &conscoefs);
    7187 SCIPfreeBufferArray(scip, &consvars);
    7188
    7189 /* if all and-constraints have exactly two variables */
    7190 if( nvars == 2 )
    7191 {
    7192 SCIP_VAR* var;
    7193 SCIP_Bool breaked;
    7194 SCIP_Bool redundant;
    7195 SCIP_Bool infeasible;
    7196 SCIP_Bool aggregated;
    7197
    7198 var = NULL;
    7199 breaked = FALSE;
    7200
    7201 /* find necessary variables, which only occur once */
    7202 for( i = 1; i >= 0; --i )
    7203 {
    7204 for( v = nvars - 1; v >= 0; --v )
    7205 {
    7206 assert(i == 1 || SCIPvarGetNegatedVar(allvars[v]) != NULL);
    7207 if( varcount[i][v] == 2 )
    7208 {
    7209 var = i ? SCIPvarGetNegatedVar(allvars[v]) : allvars[v];
    7210
    7211 breaked = TRUE;
    7212 break;
    7213 }
    7214 }
    7215
    7216 if( breaked )
    7217 break;
    7218 }
    7219 assert(var != NULL);
    7220
    7221 SCIPdebugMsg(scip, "aggregating variables <%s> == 1 - <%s> in pseudoboolean <%s>\n", SCIPvarGetName(linvar), SCIPvarGetName(var), SCIPconsGetName(cons));
    7222
    7223 SCIP_CALL( SCIPaggregateVars(scip, linvar, var, 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
    7224
    7226 SCIPdebugMsg(scip, "aggregation of variables: <%s> == 1 - <%s>, infeasible = %u, aggregated = %u\n", SCIPvarGetName(linvar), SCIPvarGetName(var), infeasible, aggregated);
    7227
    7228 if( infeasible )
    7229 *cutoff = TRUE;
    7230 else
    7231 {
    7232 if( aggregated )
    7233 ++(*naggrvars);
    7234
    7235 /* delete old constraints */
    7236 SCIP_CALL( SCIPdelCons(scip, consdata->lincons) );
    7237 SCIP_CALL( SCIPdelCons(scip, cons) );
    7238 (*ndelconss) += 2;
    7239 }
    7240 }
    7241 /* @todo: otherwise delete in this constraint allvars[samepos] from all terms and delete all but one of them
    7242 *
    7243 * it is the same like aggregating linvar with the resultant of the product, which is the same in all and-
    7244 * constraints without allvars[samepos]
    7245 *
    7246 * e.g. x1 + x2*x_3*...x_n + ~x2*x_3*...x_n = 1 => x1 = 1 - x_3*...x_n
    7247 */
    7248 } /*lint !e438*/
    7249 /* we have a constraint in the form of: x1 + x2 * x3 + ~x2 * x3 + ~x2 * ~x3 == 1
    7250 * this leads to the aggregation x1 = x2 * ~x3
    7251 *
    7252 * @todo: implement more general step, that one combination of the variables in the and constraints is missing in
    7253 * the pseudoboolean constraint, which leads to the same result, that the only linear variable is the
    7254 * resultant of the missing and-constraint
    7255 */
    7256 else if( nvars == 2 && nconsanddatas == 3 && twocount == 2 && onecount == 2 && zerocount == 0)
    7257 {
    7258 SCIP_VAR** consvars;
    7259 SCIP_Real* conscoefs;
    7260 int nconsvars;
    7261 SCIP_VAR* linvar;
    7262 SCIP_Real lincoef;
    7263 int nlinvars;
    7264 SCIP_VAR* newandvars[2];
    7265 SCIP_Bool breaked;
    7266 SCIP_CONS* newcons;
    7267 char name[SCIP_MAXSTRLEN];
    7268
    7269 /* allocate temporary memory */
    7270 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, consdata->nlinvars + nconsanddatas) );
    7271 SCIP_CALL( SCIPallocBufferArray(scip, &conscoefs, consdata->nlinvars + nconsanddatas) );
    7272
    7273 /* get variables and coefficients */
    7274 SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, consvars, conscoefs, &nconsvars) );
    7275 assert(nconsvars == consdata->nlinvars + nconsanddatas);
    7276 assert(conscoefs != NULL);
    7277
    7278#ifndef NDEBUG
    7279 /* all coefficients have to be 1 */
    7280 for( v = 0; v < nconsvars; ++v )
    7281 assert(SCIPisEQ(scip, conscoefs[v], 1.0));
    7282#endif
    7283 linvar = NULL;
    7284
    7285 /* calculate all not artificial linear variables */
    7286 SCIP_CALL( getLinVarsAndAndRess(scip, cons, consvars, conscoefs, nconsvars, &linvar, &lincoef, &nlinvars,
    7287 NULL, NULL, NULL, NULL) );
    7288 assert(nlinvars == 1);
    7289 assert(linvar != NULL);
    7290
    7291 SCIPfreeBufferArray(scip, &conscoefs);
    7292 SCIPfreeBufferArray(scip, &consvars);
    7293
    7294 newandvars[0] = NULL;
    7295 newandvars[1] = NULL;
    7296 breaked = FALSE;
    7297
    7298 /* find necessary variables, which only occur once */
    7299 for( i = 1; i >= 0; --i )
    7300 {
    7301 for( v = nvars - 1; v >= 0; --v )
    7302 {
    7303 assert(i == 1 || SCIPvarGetNegatedVar(allvars[v]) != NULL);
    7304 if( varcount[i][v] == 1 )
    7305 {
    7306 if( newandvars[0] == NULL )
    7307 newandvars[0] = i ? SCIPvarGetNegatedVar(allvars[v]) : allvars[v];
    7308 else
    7309 {
    7310 assert(newandvars[1] == NULL);
    7311 newandvars[1] = i ? SCIPvarGetNegatedVar(allvars[v]) : allvars[v];
    7312
    7313 breaked = TRUE;
    7314 break;
    7315 }
    7316 }
    7317 }
    7318
    7319 if( breaked )
    7320 break;
    7321 }
    7322 assert(newandvars[0] != NULL && newandvars[1] != NULL);
    7323
    7324 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "andcons_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(linvar));
    7325 SCIP_CALL( SCIPcreateConsAnd(scip, &newcons, name, linvar, nvars, newandvars,
    7327 SCIP_CALL( SCIPaddCons(scip, newcons) );
    7328 SCIPdebugPrintCons(scip, newcons, NULL);
    7329 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    7330
    7331 /* delete old constraints */
    7332 SCIP_CALL( SCIPdelCons(scip, consdata->lincons) );
    7333 SCIP_CALL( SCIPdelCons(scip, cons) );
    7334 (*ndelconss) += 2;
    7335 } /*lint !e438*/
    7336 }
    7337
    7338 if( SCIPconsIsDeleted(cons) )
    7339 {
    7340 /* update the uses counter of consandata objects which are used in pseudoboolean constraint, which was deleted and
    7341 * probably delete and-constraints
    7342 */
    7343 SCIP_CALL( updateConsanddataUses(scip, cons, conshdlrdata, ndelconss) );
    7344 }
    7345
    7346 TERMINATE:
    7347 /* free temporary memory */
    7348 SCIPfreeBufferArray(scip, &negated);
    7349 SCIPfreeBufferArray(scip, &repvars);
    7350 SCIPfreeBufferArray(scip, &(varcount[1]));
    7351 SCIPfreeBufferArray(scip, &(varcount[0]));
    7352 SCIPfreeBufferArray(scip, &allvars);
    7353
    7354 return SCIP_OKAY;
    7355}
    7356
    7357/** adds symmetry information of constraint to a symmetry detection graph */
    7358static
    7360 SCIP* scip, /**< SCIP pointer */
    7361 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
    7362 SCIP_CONS* cons, /**< constraint */
    7363 SYM_GRAPH* graph, /**< symmetry detection graph */
    7364 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
    7365 )
    7366{
    7367 SCIP_CONSDATA* consdata;
    7368 SCIP_VAR** tmpvars = NULL;
    7369 SCIP_VAR** vars;
    7370 SCIP_CONS* lincons;
    7371 SCIP_LINEARCONSTYPE constype;
    7372 SCIP_Real* tmpvals = NULL;
    7373 SCIP_Real* vals;
    7374 SCIP_Real constant = 0.0;
    7375 SCIP_Real lhs;
    7376 SCIP_Real rhs;
    7377 int tmpnvars;
    7378 int rootnodeidx;
    7379 int nodeidx;
    7380 int nvars;
    7381 int i;
    7382 int c;
    7383
    7384 assert(scip != NULL);
    7385 assert(cons != NULL);
    7386 assert(graph != NULL);
    7387 assert(success != NULL);
    7388
    7389 consdata = SCIPconsGetData(cons);
    7390 assert(consdata != NULL);
    7391
    7392 /* allocate buffer to hold variables for creating of symmetry detection graph */
    7393 nvars = SCIPgetNVars(scip);
    7394 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    7395 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
    7396
    7397 /* add root node to symmetry detection graph */
    7398 lhs = SCIPgetLhsPseudoboolean(scip, cons);
    7399 rhs = SCIPgetRhsPseudoboolean(scip, cons);
    7400 SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, lhs, rhs, &rootnodeidx) );
    7401
    7402 /* possibly add node and edge encoding whether constraint is soft */
    7403 vars[0] = SCIPgetIndVarPseudoboolean(scip, cons);
    7404 if( vars[0] != NULL )
    7405 {
    7406 vals[0] = 1.0;
    7407 tmpnvars = 1;
    7408 constant = 0.0;
    7409
    7411 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, rootnodeidx, nodeidx, TRUE, consdata->weight) );
    7412 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &tmpnvars, &constant,
    7414 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, nodeidx, vars, vals, tmpnvars, constant) );
    7415 }
    7416
    7417 /* add nodes and edges encoding linear part of the pseudoboolean cons */
    7418 lincons = SCIPgetLinearConsPseudoboolean(scip, cons);
    7419 constype = SCIPgetLinearConsTypePseudoboolean(scip, cons);
    7420
    7421 /* collect information about linear constraint */
    7422 tmpnvars = 0;
    7423 switch( constype )
    7424 {
    7426 tmpvars = SCIPgetVarsLinear(scip, lincons);
    7427 tmpnvars = SCIPgetNVarsLinear(scip, lincons);
    7428 tmpvals = SCIPgetValsLinear(scip, lincons);
    7429 for( i = 0; i < tmpnvars; ++i )
    7430 vals[i] = tmpvals[i];
    7431 break;
    7433 tmpvars = SCIPgetVarsLogicor(scip, lincons);
    7434 tmpnvars = SCIPgetNVarsLogicor(scip, lincons);
    7435 for( i = 0; i < tmpnvars; ++i )
    7436 vals[i] = 1.0;
    7437 break;
    7439 tmpvars = SCIPgetVarsKnapsack(scip, lincons);
    7440 tmpnvars = SCIPgetNVarsKnapsack(scip, lincons);
    7441 for( i = 0; i < tmpnvars; ++i )
    7442 vals[i] = (SCIP_Real)SCIPgetWeightsKnapsack(scip, cons)[i];
    7443 break;
    7445 tmpvars = SCIPgetVarsSetppc(scip, lincons);
    7446 tmpnvars = SCIPgetNVarsSetppc(scip, lincons);
    7447 for( i = 0; i < tmpnvars; ++i )
    7448 vals[i] = 1.0;
    7449 break;
    7450 default:
    7451 SCIPfreeBufferArray(scip, &vals);
    7452 SCIPfreeBufferArray(scip, &vars);
    7453 *success = FALSE;
    7454
    7455 return SCIP_OKAY;
    7456 } /*lint !e788*/
    7457 assert(tmpvars != NULL);
    7458 for( i = 0; i < tmpnvars; ++i )
    7459 vars[i] = tmpvars[i];
    7460 constant = 0.0;
    7461
    7462 /* create nodes and edges for linear part */
    7464 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, rootnodeidx, nodeidx, FALSE, 0.0) );
    7465
    7466 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &tmpnvars, &constant,
    7468 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, nodeidx, vars, vals, tmpnvars, constant) );
    7469
    7470 /* create nodes and edges for AND constraints */
    7471 for( c = 0; c < consdata->nconsanddatas; ++c )
    7472 {
    7473 assert(consdata->consanddatas[c] != NULL);
    7474
    7475 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int)SYM_CONSOPTYPE_PB_AND, &nodeidx) );
    7476 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, rootnodeidx, nodeidx, TRUE, consdata->andcoefs[c]) );
    7477
    7478 tmpnvars = consdata->consanddatas[c]->nvars;
    7479 for( i = 0; i < tmpnvars; ++i )
    7480 vars[i] = consdata->consanddatas[c]->vars[i];
    7481 for( i = 0; i < tmpnvars; ++i )
    7482 vals[i] = 1.0;
    7483 constant = 0.0;
    7484
    7485 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &tmpnvars, &constant,
    7487 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, nodeidx, vars, vals, tmpnvars, constant) );
    7488 }
    7489
    7490 SCIPfreeBufferArray(scip, &vals);
    7491 SCIPfreeBufferArray(scip, &vars);
    7492
    7493 *success = TRUE;
    7494
    7495 return SCIP_OKAY;
    7496}
    7497
    7498
    7499/*
    7500 * Callback methods of constraint handler
    7501 */
    7502
    7503#ifdef NONLINCONSUPGD_PRIORITY
    7504#include "scip/cons_nonlinear.h"
    7505/** tries to upgrade a nonlinear constraint into a pseudoboolean constraint */
    7506static
    7507SCIP_DECL_NONLINCONSUPGD(nonlinconsUpgdPseudoboolean)
    7508{
    7509 SCIP_EXPRGRAPH* exprgraph;
    7510 SCIP_EXPRGRAPHNODE* node;
    7511 SCIP_Real lhs;
    7512 SCIP_Real rhs;
    7513 SCIP_VAR* var;
    7514 SCIP_VAR* objvar = NULL;
    7515 SCIP_VAR** linvars = NULL;
    7516 int nlinvars;
    7517 SCIP_VAR*** terms;
    7518 int nterms;
    7519 int* ntermvars;
    7520 SCIP_Real* termvals;
    7521 int i;
    7522 int j;
    7523
    7524 assert(nupgdconss != NULL);
    7525 assert(upgdconss != NULL);
    7526
    7527 *nupgdconss = 0;
    7528
    7529 node = SCIPgetExprgraphNodeNonlinear(scip, cons);
    7530
    7531 /* no interest in linear constraints */
    7532 if( node == NULL )
    7533 return SCIP_OKAY;
    7534
    7535 switch( SCIPexprgraphGetNodeOperator(node) )
    7536 {
    7537 case SCIP_EXPR_VARIDX:
    7538 case SCIP_EXPR_CONST:
    7539 case SCIP_EXPR_PLUS:
    7540 case SCIP_EXPR_MINUS:
    7541 case SCIP_EXPR_SUM:
    7542 case SCIP_EXPR_LINEAR:
    7543 /* these should not appear as exprgraphnodes after constraint presolving */
    7544 return SCIP_OKAY;
    7545
    7546 case SCIP_EXPR_MUL:
    7547 case SCIP_EXPR_DIV:
    7548 case SCIP_EXPR_SQUARE:
    7549 case SCIP_EXPR_SQRT:
    7550 case SCIP_EXPR_REALPOWER:
    7551 case SCIP_EXPR_INTPOWER:
    7552 case SCIP_EXPR_SIGNPOWER:
    7553 case SCIP_EXPR_EXP:
    7554 case SCIP_EXPR_LOG:
    7555 case SCIP_EXPR_SIN:
    7556 case SCIP_EXPR_COS:
    7557 case SCIP_EXPR_TAN:
    7558 /* case SCIP_EXPR_ERF: */
    7559 /* case SCIP_EXPR_ERFI: */
    7560 case SCIP_EXPR_MIN:
    7561 case SCIP_EXPR_MAX:
    7562 case SCIP_EXPR_ABS:
    7563 case SCIP_EXPR_SIGN:
    7564 case SCIP_EXPR_PRODUCT:
    7565 case SCIP_EXPR_USER:
    7566 /* these do not look like a proper pseudoboolean expression (assuming the expression graph simplifier did run) */
    7567 return SCIP_OKAY;
    7568
    7569 case SCIP_EXPR_QUADRATIC: /* let cons_quadratic still handle these for now */
    7570 return SCIP_OKAY;
    7571
    7572 case SCIP_EXPR_POLYNOMIAL:
    7573 /* these mean that we have something polynomial */
    7574 break;
    7575
    7576 case SCIP_EXPR_PARAM:
    7577 case SCIP_EXPR_LAST:
    7578 default:
    7579 SCIPwarningMessage(scip, "unexpected expression operator %d in nonlinear constraint <%s>\n", SCIPexprgraphGetNodeOperator(node), SCIPconsGetName(cons));
    7580 return SCIP_OKAY;
    7581 }
    7582
    7583 lhs = SCIPgetLhsNonlinear(scip, cons);
    7584 rhs = SCIPgetRhsNonlinear(scip, cons);
    7585
    7586 /* we need all linear variables to be binary */
    7587 for( i = 0; i < SCIPgetNLinearVarsNonlinear(scip, cons); ++i )
    7588 {
    7589 var = SCIPgetLinearVarsNonlinear(scip, cons)[i];
    7590 assert(var != NULL);
    7591
    7592 if( SCIPvarIsBinary(var) )
    7593 continue;
    7594
    7595 SCIPdebugMsg(scip, "not pseudoboolean because linear variable <%s> is not binary\n", SCIPvarGetName(var));
    7596 return SCIP_OKAY;
    7597 }
    7598
    7599 /* if simplified, then all children of root node should be variables, we need all of them to be binary */
    7600 exprgraph = SCIPgetExprgraphNonlinear(scip, SCIPconsGetHdlr(cons));
    7601 for( i = 0; i < SCIPexprgraphGetNodeNChildren(node); ++i )
    7602 {
    7603 SCIP_EXPRGRAPHNODE* child;
    7604
    7605 child = SCIPexprgraphGetNodeChildren(node)[i];
    7606 assert(child != NULL);
    7607 if( SCIPexprgraphGetNodeOperator(child) != SCIP_EXPR_VARIDX )
    7608 {
    7609 SCIPdebugMsg(scip, "not pseudoboolean because child %d is not a variable\n", i);
    7610 return SCIP_OKAY;
    7611 }
    7612
    7613 var = (SCIP_VAR*)SCIPexprgraphGetNodeVar(exprgraph, child);
    7614 assert(var != NULL);
    7615 if( !SCIPvarIsBinary(var) )
    7616 {
    7617 SCIPdebugMsg(scip, "not pseudoboolean because nonlinear var <%s> is not binary\n", SCIPvarGetName(var));
    7618 return SCIP_OKAY;
    7619 }
    7620 }
    7621
    7622 /* setup a pseudoboolean constraint */
    7623
    7624 if( upgdconsssize < 1 )
    7625 {
    7626 /* request larger upgdconss array */
    7627 *nupgdconss = -1;
    7628 return SCIP_OKAY;
    7629 }
    7630
    7631 SCIPdebugMsg(scip, "upgrading nonlinear constraint <%s> to pseudo-boolean\n", SCIPconsGetName(cons));
    7632
    7633 if( !SCIPisInfinity(scip, -lhs) )
    7634 lhs -= SCIPexprgraphGetNodePolynomialConstant(node);
    7635 if( !SCIPisInfinity(scip, -rhs) )
    7636 rhs -= SCIPexprgraphGetNodePolynomialConstant(node);
    7637
    7638 /* setup linear part, if not identical */
    7639 if( objvar != NULL )
    7640 {
    7641 SCIP_CALL( SCIPallocBufferArray(scip, &linvars, SCIPgetNLinearVarsNonlinear(scip, cons)-1) );
    7642 nlinvars = 0;
    7643 for( i = 0; i < SCIPgetNLinearVarsNonlinear(scip, cons); ++i )
    7644 {
    7645 var = SCIPgetLinearVarsNonlinear(scip, cons)[i];
    7646 if( var != objvar )
    7647 linvars[nlinvars++] = var;
    7648 }
    7649 }
    7650 else
    7651 nlinvars = SCIPgetNLinearVarsNonlinear(scip, cons);
    7652
    7653 /* setup nonlinear terms */
    7654 nterms = SCIPexprgraphGetNodePolynomialNMonomials(node);
    7656 SCIP_CALL( SCIPallocBufferArray(scip, &ntermvars, nterms) );
    7657 SCIP_CALL( SCIPallocBufferArray(scip, &termvals, nterms) );
    7658
    7659 for( i = 0; i < nterms; ++i )
    7660 {
    7661 SCIP_EXPRDATA_MONOMIAL* monomial;
    7662
    7663 monomial = SCIPexprgraphGetNodePolynomialMonomials(node)[i];
    7664 assert(monomial != NULL);
    7665
    7666 ntermvars[i] = SCIPexprGetMonomialNFactors(monomial);
    7667 SCIP_CALL( SCIPallocBufferArray(scip, &terms[i], ntermvars[i]) );
    7668
    7669 for( j = 0; j < SCIPexprGetMonomialNFactors(monomial); ++j )
    7670 {
    7671 terms[i][j] = (SCIP_VAR*)SCIPexprgraphGetNodeVar(exprgraph, SCIPexprgraphGetNodeChildren(node)[SCIPexprGetMonomialChildIndices(monomial)[j]]);
    7672 assert(SCIPexprGetMonomialExponents(monomial)[j] > 0.0);
    7673 }
    7674
    7675 termvals[i] = SCIPexprGetMonomialCoef(monomial);
    7676 }
    7677
    7678 *nupgdconss = 1;
    7680 objvar != NULL ? linvars : SCIPgetLinearVarsNonlinear(scip, cons), nlinvars, SCIPgetLinearCoefsNonlinear(scip, cons),
    7681 terms, nterms, ntermvars, termvals, NULL, 0.0, FALSE, objvar,
    7682 lhs, rhs,
    7686
    7687 for( i = nterms-1; i >= 0; --i )
    7688 SCIPfreeBufferArray(scip, &terms[i]);
    7689
    7690 SCIPfreeBufferArray(scip, &terms);
    7691 SCIPfreeBufferArray(scip, &ntermvars);
    7692 SCIPfreeBufferArray(scip, &termvals);
    7693 SCIPfreeBufferArrayNull(scip, &linvars);
    7694
    7695 return SCIP_OKAY;
    7696}
    7697#endif
    7698
    7699/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    7700static
    7701SCIP_DECL_CONSHDLRCOPY(conshdlrCopyPseudoboolean)
    7702{ /*lint --e{715}*/
    7703 assert(scip != NULL);
    7704 assert(conshdlr != NULL);
    7705
    7707
    7708 /* call inclusion method of constraint handler */
    7710
    7711 *valid = TRUE;
    7712
    7713 return SCIP_OKAY;
    7714}
    7715
    7716/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
    7717static
    7718SCIP_DECL_CONSFREE(consFreePseudoboolean)
    7719{ /*lint --e{715}*/
    7720 SCIP_CONSHDLRDATA* conshdlrdata;
    7721
    7722 assert(scip != NULL);
    7723 assert(conshdlr != NULL);
    7724
    7726
    7727 /* free constraint handler data */
    7728 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    7729 assert(conshdlrdata != NULL);
    7730
    7731 SCIP_CALL( conshdlrdataFree(scip, &conshdlrdata) );
    7732
    7733 SCIPconshdlrSetData(conshdlr, NULL);
    7734
    7735 return SCIP_OKAY;
    7736}
    7737
    7738
    7739/** initialization method of constraint handler (called after problem was transformed) */
    7740static
    7741SCIP_DECL_CONSINIT(consInitPseudoboolean)
    7742{ /*lint --e{715}*/
    7743 SCIP_CONSHDLRDATA* conshdlrdata;
    7744 int c;
    7745
    7746 assert(scip != NULL);
    7747 assert(conshdlr != NULL);
    7748
    7750
    7751 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    7752 assert(conshdlrdata != NULL);
    7753
    7754 /* check each constraint and get transformed constraints */
    7755 for( c = conshdlrdata->nallconsanddatas - 1; c >= 0; --c )
    7756 {
    7757 SCIP_CONS* andcons;
    7758 SCIP_VAR* resultant;
    7759#ifndef NDEBUG
    7760 SCIP_VAR** vars;
    7761 int nvars;
    7762 int v;
    7763
    7764 assert(conshdlrdata->allconsanddatas[c] != NULL);
    7765 assert(conshdlrdata->allconsanddatas[c]->newvars == NULL);
    7766
    7767 vars = conshdlrdata->allconsanddatas[c]->vars;
    7768 nvars = conshdlrdata->allconsanddatas[c]->nvars;
    7769 assert(vars != NULL || nvars == 0);
    7770
    7771 /* check for correct variables data */
    7772 for( v = nvars - 1; v > 0; --v )
    7773 {
    7774 assert(SCIPvarIsTransformed(vars[v])); /*lint !e613*/
    7775 assert(SCIPvarGetIndex(vars[v]) >= SCIPvarGetIndex(vars[v-1])); /*lint !e613*/
    7776 }
    7777 assert(nvars == 0 || SCIPvarIsTransformed(vars[0])); /*lint !e613*/
    7778#endif
    7779
    7780 andcons = conshdlrdata->allconsanddatas[c]->cons;
    7781 assert(andcons != NULL);
    7782
    7783 assert(SCIPconsIsTransformed(andcons));
    7784
    7785 resultant = SCIPgetResultantAnd(scip, andcons);
    7786 /* insert new mapping */
    7787 assert(!SCIPhashmapExists(conshdlrdata->hashmap, (void*)resultant));
    7788 SCIP_CALL( SCIPhashmapInsert(conshdlrdata->hashmap, (void*)resultant, (void*)(conshdlrdata->allconsanddatas[c])) );
    7789
    7790 SCIPdebugMsg(scip, "insert into hashmap <%s> (%p) -> <%s> (%p/%p)\n", SCIPvarGetName(resultant), (void*)resultant,
    7791 SCIPconsGetName(conshdlrdata->allconsanddatas[c]->cons), (void*)(conshdlrdata->allconsanddatas[c]),
    7792 (void*)(conshdlrdata->allconsanddatas[c]->cons));
    7793 }
    7794
    7795 return SCIP_OKAY;
    7796}
    7797
    7798/** presolving initialization method of constraint handler (called when presolving is about to begin) */
    7799static
    7800SCIP_DECL_CONSINITPRE(consInitprePseudoboolean)
    7801{ /*lint --e{715}*/
    7802 SCIP_CONSHDLRDATA* conshdlrdata;
    7803 int c;
    7804
    7805 assert(scip != NULL);
    7806 assert(conshdlr != NULL);
    7807
    7809
    7810 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    7811 assert(conshdlrdata != NULL);
    7812
    7813 /* decompose all pseudo boolean constraints into a "linear" constraint and "and" constraints */
    7814 for( c = 0; c < nconss; ++c )
    7815 {
    7816 SCIP_CONS* cons;
    7817 SCIP_CONSDATA* consdata;
    7818 SCIP_VAR** vars;
    7819 SCIP_Real* coefs;
    7820 int nvars;
    7821
    7822 cons = conss[c];
    7823 assert(cons != NULL);
    7824
    7825 /* only added constraints can be upgraded */
    7826 if( !SCIPconsIsAdded(cons) )
    7827 continue;
    7828
    7829 consdata = SCIPconsGetData(cons);
    7830 assert(consdata != NULL);
    7831
    7832 /* only keep hard constraints if desired */
    7833 if( !conshdlrdata->decomposenormalpbcons && !consdata->issoftcons )
    7834 continue;
    7835
    7836 /* gets number of variables in linear constraint */
    7837 SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
    7838
    7839 /* allocate temporary memory */
    7840 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    7841 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
    7842
    7843 /* get variables and coefficient of linear constraint */
    7844 SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) );
    7845 assert(coefs != NULL || nvars == 0);
    7846
    7847 /* hard constraint */
    7848 if( !consdata->issoftcons )
    7849 {
    7850 /* @todo: maybe better create a new linear constraint and let scip do the upgrade */
    7851
    7852 /* mark linear constraint not to be upgraded - otherwise we loose control over it */
    7853 SCIPconsAddUpgradeLocks(consdata->lincons, +1);
    7854
    7855 /* update and constraint flags */
    7856 SCIP_CALL( updateAndConss(scip, cons) );
    7857 }
    7858 /* soft constraint */
    7859 else
    7860 {
    7861 SCIP_VAR* negindvar;
    7862 char name[SCIP_MAXSTRLEN];
    7863 SCIP_Real lhs;
    7864 SCIP_Real rhs;
    7865 SCIP_Bool initial;
    7866 SCIP_Bool updateandconss;
    7867 int v;
    7868
    7869 assert(consdata->weight != 0);
    7870 assert(consdata->indvar != NULL);
    7871
    7872 /* get negation of indicator variable */
    7873 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->indvar, &negindvar) );
    7874 assert(negindvar != NULL);
    7875
    7876 /* get sides of linear constraint */
    7877 SCIP_CALL( getLinearConsSides(scip, consdata->lincons, consdata->linconstype, &lhs, &rhs) );
    7878 assert(!SCIPisInfinity(scip, lhs));
    7879 assert(!SCIPisInfinity(scip, -rhs));
    7880 assert(SCIPisLE(scip, lhs, rhs));
    7881
    7882 /* @todo: split up sides into separate soft constraints in advance */
    7883 /* assert(SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs)); */
    7884
    7885 updateandconss = FALSE;
    7886
    7887 /* with indicator */
    7888 if( conshdlrdata->decomposeindicatorpbcons )
    7889 {
    7890 SCIP_CONS* indcons;
    7891
    7892 /* @todo check whether it's better to set the initial flag to false */
    7893 initial = SCIPconsIsInitial(cons); /* FALSE; */
    7894
    7895 if( !SCIPisInfinity(scip, rhs) )
    7896 {
    7897 /* first we are modelling the implication that if the negation of the indicator variable is on, the constraint
    7898 * is enabled */
    7899 /* indvar == 0 => a^T*x <= rhs */
    7900
    7901 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_rhs_ind", SCIPconsGetName(cons));
    7902
    7903 SCIP_CALL( SCIPcreateConsIndicator(scip, &indcons, name, negindvar, nvars, vars, coefs, rhs,
    7904 initial, SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
    7907
    7908 /* update and constraint flags */
    7909 SCIP_CALL( updateAndConss(scip, cons) );
    7910 updateandconss = TRUE;
    7911
    7912 SCIP_CALL( SCIPaddCons(scip, indcons) );
    7913 SCIPdebugPrintCons(scip, indcons, NULL);
    7914 SCIP_CALL( SCIPreleaseCons(scip, &indcons) );
    7915 }
    7916
    7917 if( !SCIPisInfinity(scip, -lhs) )
    7918 {
    7919 /* second we are modelling the implication that if the negation of the indicator variable is on, the constraint
    7920 * is enabled */
    7921 /* change the a^T*x >= lhs to -a^Tx<= -lhs, for indicator constraint */
    7922
    7923 for( v = nvars - 1; v >= 0; --v )
    7924 coefs[v] *= -1;
    7925
    7926 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_lhs_ind", SCIPconsGetName(cons));
    7927
    7928 SCIP_CALL( SCIPcreateConsIndicator(scip, &indcons, name, negindvar, nvars, vars, coefs, -lhs,
    7929 initial, SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
    7932
    7933 if( !updateandconss )
    7934 {
    7935 /* update and constraint flags */
    7936 SCIP_CALL( updateAndConss(scip, cons) );
    7937 }
    7938
    7939 SCIP_CALL( SCIPaddCons(scip, indcons) );
    7940 SCIPdebugPrintCons(scip, indcons, NULL);
    7941 SCIP_CALL( SCIPreleaseCons(scip, &indcons) );
    7942 }
    7943 }
    7944 /* with linear */
    7945 else
    7946 {
    7947 SCIP_CONS* lincons;
    7948 SCIP_Real maxact;
    7949 SCIP_Real minact;
    7950 SCIP_Real lb;
    7951 SCIP_Real ub;
    7952
    7953 maxact = 0.0;
    7954 minact = 0.0;
    7955
    7956 /* adding all linear coefficients up */
    7957 for( v = nvars - 1; v >= 0; --v )
    7958 if( coefs[v] > 0 )
    7959 maxact += coefs[v];
    7960 else
    7961 minact += coefs[v];
    7962
    7963 if( SCIPisInfinity(scip, maxact) )
    7964 {
    7965 SCIPwarningMessage(scip, "maxactivity = %g exceed infinity value.\n", maxact);
    7966 }
    7967 if( SCIPisInfinity(scip, -minact) )
    7968 {
    7969 SCIPwarningMessage(scip, "minactivity = %g exceed -infinity value.\n", minact);
    7970 }
    7971
    7972 /* @todo check whether it's better to set the initial flag to false */
    7973 initial = SCIPconsIsInitial(cons); /* FALSE; */
    7974
    7975 /* first soft constraints for lhs */
    7976 if( !SCIPisInfinity(scip, -lhs) )
    7977 {
    7978 /* first we are modelling the feasibility of the soft constraint by adding a slack variable */
    7979 /* we ensure that if indvar == 1 => (a^T*x + ub*indvar >= lhs) */
    7980 ub = lhs - minact;
    7981
    7982 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_lhs_part1", SCIPconsGetName(cons));
    7983
    7984 SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, name, nvars, vars, coefs, lhs, SCIPinfinity(scip),
    7985 initial, SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
    7988
    7989 /* update and constraint flags */
    7990 SCIP_CALL( updateAndConss(scip, cons) );
    7991 updateandconss = TRUE;
    7992
    7993 /* add artificial indicator variable */
    7994 SCIP_CALL( SCIPaddCoefLinear(scip, lincons, consdata->indvar, ub) );
    7995
    7996 SCIP_CALL( SCIPaddCons(scip, lincons) );
    7997 SCIPdebugPrintCons(scip, lincons, NULL);
    7998 SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
    7999
    8000 /* second we are modelling the implication that if the slack variable is on( negation is off), the constraint
    8001 * is disabled, so only the cost arise if the slack variable is necessary */
    8002 /* indvar == 1 => (a^T*x (+ ub * negindvar) <= lhs - 1) */
    8003 ub = lhs - maxact - 1;
    8004
    8005 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_lhs_part2", SCIPconsGetName(cons));
    8006
    8007 SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, name, nvars, vars, coefs, -SCIPinfinity(scip), lhs - 1,
    8008 initial, SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
    8011
    8012 /* add artificial indicator variable */
    8013 SCIP_CALL( SCIPaddCoefLinear(scip, lincons, negindvar, ub) );
    8014
    8015 SCIP_CALL( SCIPaddCons(scip, lincons) );
    8016 SCIPdebugPrintCons(scip, lincons, NULL);
    8017 SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
    8018 }
    8019
    8020 /* second soft constraints for rhs */
    8021 if( !SCIPisInfinity(scip, rhs) )
    8022 {
    8023 /* first we are modelling the feasibility of the soft-constraint by adding a slack variable */
    8024 /* indvar == 1 => (a^T*x + lb * indvar <= rhs) */
    8025 lb = rhs - maxact;
    8026
    8027 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_rhs_part1", SCIPconsGetName(cons));
    8028
    8029 SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, name, nvars, vars, coefs, -SCIPinfinity(scip), rhs,
    8030 initial, SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
    8033
    8034 if( !updateandconss )
    8035 {
    8036 /* update and constraint flags */
    8037 SCIP_CALL( updateAndConss(scip, cons) );
    8038 }
    8039
    8040 /* add artificial indicator variable */
    8041 SCIP_CALL( SCIPaddCoefLinear(scip, lincons, consdata->indvar, lb) );
    8042
    8043 SCIP_CALL( SCIPaddCons(scip, lincons) );
    8044 SCIPdebugPrintCons(scip, lincons, NULL);
    8045 SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
    8046
    8047 /* second we are modelling the implication that if the slack variable is on( negation is off), the constraint
    8048 * is disabled, so only the cost arise if the slack variable is necessary */
    8049 /* indvar == 1 => (a^T*x (+ lb * negindvar) >= rhs + 1) */
    8050 lb = rhs - minact + 1;
    8051
    8052 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_rhs_part2", SCIPconsGetName(cons));
    8053
    8054 SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, name, nvars, vars, coefs, rhs + 1, SCIPinfinity(scip),
    8055 initial, SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
    8058
    8059 /* add artificial indicator variable */
    8060 SCIP_CALL( SCIPaddCoefLinear(scip, lincons, negindvar, lb) );
    8061
    8062 SCIP_CALL( SCIPaddCons(scip, lincons) );
    8063 SCIPdebugPrintCons(scip, lincons, NULL);
    8064 SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
    8065 }
    8066 }
    8067
    8068 /* release corresponding unadded linear constraint, other constraints were added */
    8069 assert(!SCIPconsIsAdded(consdata->lincons));
    8070 SCIP_CALL( SCIPreleaseCons(scip, &consdata->lincons) );
    8071 }
    8072
    8073 /* free temporary memory */
    8074 SCIPfreeBufferArray(scip, &coefs);
    8075 SCIPfreeBufferArray(scip, &vars);
    8076
    8077 /* @todo: maintain soft inequality constraint if not decomposeindicatorpbcons */
    8078 /* remove pseudo boolean constraint, and-constraints are still active */
    8079 SCIP_CALL( SCIPdelCons(scip, cons) );
    8080 }
    8081
    8082 return SCIP_OKAY;
    8083}
    8084
    8085/** frees specific constraint data */
    8086static
    8087SCIP_DECL_CONSDELETE(consDeletePseudoboolean)
    8088{ /*lint --e{715}*/
    8089 SCIP_CONSHDLRDATA* conshdlrdata;
    8090 SCIP_Bool isorig;
    8091
    8092 assert(scip != NULL);
    8093 assert(conshdlr != NULL);
    8094 assert(cons != NULL);
    8095 assert(consdata != NULL);
    8096 assert(*consdata != NULL);
    8097
    8099
    8100 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    8101 assert(conshdlrdata != NULL);
    8102
    8103 isorig = SCIPconsIsOriginal(cons);
    8104
    8105 /* count number of used consanddata objects in original problem */
    8106 if( isorig )
    8107 {
    8108#ifndef NDEBUG
    8109 int c;
    8110 assert((*consdata)->lincons == NULL || SCIPconsIsOriginal((*consdata)->lincons));
    8111
    8112 for( c = (*consdata)->nconsanddatas - 1; c >= 0; --c )
    8113 {
    8114 assert((*consdata)->consanddatas[c]->nuses == 0);
    8115 assert((*consdata)->consanddatas[c]->cons == NULL);
    8116 assert((*consdata)->consanddatas[c]->noriguses == 0 || ((*consdata)->consanddatas[c]->origcons != NULL && SCIPconsIsOriginal((*consdata)->consanddatas[c]->origcons)));
    8117 }
    8118#endif
    8119 conshdlrdata->noriguses -= (*consdata)->nconsanddatas;
    8120 }
    8121 assert(conshdlrdata->noriguses >= 0);
    8122
    8123 /* free pseudo boolean constraint */
    8124 SCIP_CALL( consdataFree(scip, consdata, isorig, conshdlrdata) );
    8125
    8126 return SCIP_OKAY;
    8127}
    8128
    8129/** transforms constraint data into data belonging to the transformed problem */
    8130static
    8131SCIP_DECL_CONSTRANS(consTransPseudoboolean)
    8132{ /*lint --e{715}*/
    8133 SCIP_CONSDATA* sourcedata;
    8134 SCIP_CONSDATA* targetdata;
    8135 SCIP_CONS** andconss;
    8136 int c;
    8137
    8138 assert(scip != NULL);
    8139 assert(conshdlr != NULL);
    8141 assert(sourcecons != NULL);
    8142 assert(targetcons != NULL);
    8143
    8145
    8146 sourcedata = SCIPconsGetData(sourcecons);
    8147 assert(sourcedata != NULL);
    8148 assert(sourcedata->consanddatas != NULL || sourcedata->nconsanddatas == 0);
    8149
    8150 /* allocate temporary memory */
    8151 SCIP_CALL( SCIPallocBufferArray(scip, &andconss, sourcedata->nconsanddatas) );
    8152
    8153 /* copy and-constraints */
    8154 for( c = sourcedata->nconsanddatas - 1; c >= 0; --c )
    8155 {
    8156 assert(sourcedata->consanddatas[c] != NULL);
    8157 andconss[c] = sourcedata->consanddatas[c]->origcons;
    8158 assert(andconss[c] != NULL);
    8159 assert(SCIPconsIsOriginal(andconss[c]));
    8160 }
    8161
    8162 /* create pseudoboolean constraint data for target constraint */
    8163 SCIP_CALL( consdataCreate(scip, conshdlr, &targetdata, sourcedata->lincons, sourcedata->linconstype, andconss,
    8164 sourcedata->andcoefs, sourcedata->andnegs, sourcedata->nconsanddatas, sourcedata->indvar, sourcedata->weight,
    8165 sourcedata->issoftcons, sourcedata->lhs, sourcedata->rhs, SCIPconsIsChecked(sourcecons), TRUE) );
    8166
    8167 /* free temporary memory */
    8168 SCIPfreeBufferArray(scip, &andconss);
    8169
    8170 /* create target constraint */
    8171 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
    8172 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
    8173 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
    8174 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
    8175 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
    8176
    8177 return SCIP_OKAY;
    8178}
    8179
    8180/** constraint enforcing method of constraint handler for LP solutions */
    8181static
    8182SCIP_DECL_CONSENFOLP(consEnfolpPseudoboolean)
    8183{ /*lint --e{715}*/
    8184 SCIP_Bool violated;
    8185
    8186 assert(scip != NULL);
    8187 assert(conshdlr != NULL);
    8188 assert(result != NULL);
    8189
    8191
    8192 violated = FALSE;
    8193
    8194 /* check all and-constraints */
    8195 SCIP_CALL( checkAndConss(scip, conshdlr, NULL, &violated) );
    8196
    8197 if( violated )
    8198 *result = SCIP_INFEASIBLE;
    8199 else
    8200 *result = SCIP_FEASIBLE;
    8201
    8202 return SCIP_OKAY;
    8203}
    8204
    8205
    8206/** constraint enforcing method of constraint handler for relaxation solutions */
    8207static
    8208SCIP_DECL_CONSENFORELAX(consEnforelaxPseudoboolean)
    8209{ /*lint --e{715}*/
    8210 SCIP_Bool violated;
    8211
    8212 assert(scip != NULL);
    8213 assert(conshdlr != NULL);
    8214 assert(result != NULL);
    8215
    8217
    8218 violated = FALSE;
    8219
    8220 /* check all and-constraints */
    8221 SCIP_CALL( checkAndConss(scip, conshdlr, sol, &violated) );
    8222
    8223 if( violated )
    8224 *result = SCIP_INFEASIBLE;
    8225 else
    8226 *result = SCIP_FEASIBLE;
    8227
    8228 return SCIP_OKAY;
    8229}
    8230
    8231
    8232/** constraint enforcing method of constraint handler for pseudo solutions */
    8233static
    8234SCIP_DECL_CONSENFOPS(consEnfopsPseudoboolean)
    8235{ /*lint --e{715}*/
    8236 SCIP_Bool violated;
    8237
    8238 assert(scip != NULL);
    8239 assert(conshdlr != NULL);
    8240 assert(result != NULL);
    8241
    8243
    8244 violated = FALSE;
    8245
    8246 /* check all and-constraints */
    8247 SCIP_CALL( checkAndConss(scip, conshdlr, NULL, &violated) );
    8248
    8249 if( violated )
    8250 *result = SCIP_INFEASIBLE;
    8251 else
    8252 *result = SCIP_FEASIBLE;
    8253
    8254 return SCIP_OKAY;
    8255}
    8256
    8257
    8258/** feasibility check method of constraint handler for integral solutions */
    8259static
    8260SCIP_DECL_CONSCHECK(consCheckPseudoboolean)
    8261{ /*lint --e{715}*/
    8262 SCIP_Bool violated;
    8263 int c;
    8264
    8265 assert(scip != NULL);
    8266 assert(conshdlr != NULL);
    8267 assert(sol != NULL);
    8268 assert(result != NULL);
    8269
    8271
    8272 *result = SCIP_FEASIBLE;
    8273
    8274 if( nconss > 0 )
    8275 {
    8276 if( SCIPconsIsOriginal(conss[0]) )
    8277 {
    8278 SCIP_CONSDATA* consdata;
    8279
    8280 for( c = nconss - 1; c >= 0 && (*result == SCIP_FEASIBLE || completely); --c )
    8281 {
    8282 consdata = SCIPconsGetData(conss[c]);
    8283 assert(consdata != NULL);
    8284
    8285 if( consdata->issoftcons )
    8286 {
    8287 assert(consdata->indvar != NULL);
    8288
    8289 if( SCIPisEQ(scip, SCIPgetSolVal(scip, sol, consdata->indvar), 1.0) )
    8290 continue;
    8291 }
    8292
    8293 SCIP_CALL( checkOrigPbCons(scip, conss[c], sol, &violated, printreason) );
    8294 if( violated )
    8295 *result = SCIP_INFEASIBLE;
    8296 }
    8297 }
    8298 else
    8299 {
    8300 /* check all and-constraints */
    8301 SCIP_CALL( checkAndConss(scip, conshdlr, sol, &violated) );
    8302 if( violated )
    8303 *result = SCIP_INFEASIBLE;
    8304 }
    8305 }
    8306
    8307 return SCIP_OKAY;
    8308}
    8309
    8310
    8311/** presolving method of constraint handler */
    8312static
    8313SCIP_DECL_CONSPRESOL(consPresolPseudoboolean)
    8314{ /*lint --e{715}*/
    8315 SCIP_CONSHDLRDATA* conshdlrdata;
    8316 SCIP_Bool cutoff;
    8317 int firstchange;
    8318 int firstupgradetry;
    8319 int oldnfixedvars;
    8320 int oldnaggrvars;
    8321 int oldnchgbds;
    8322 int oldndelconss;
    8323 int oldnupgdconss;
    8324 int oldnchgcoefs;
    8325 int oldnchgsides;
    8326 int c;
    8327
    8328 assert(scip != NULL);
    8329 assert(conshdlr != NULL);
    8330 assert(result != NULL);
    8331
    8333
    8334 /* remember old preprocessing counters */
    8335 oldnfixedvars = *nfixedvars;
    8336 oldnaggrvars = *naggrvars;
    8337 oldnchgbds = *nchgbds;
    8338 oldndelconss = *ndelconss;
    8339 oldnupgdconss = *nupgdconss;
    8340 oldnchgcoefs = *nchgcoefs;
    8341 oldnchgsides = *nchgsides;
    8342
    8343 /* get constraint handler data */
    8344 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    8345
    8346 /* compute all changes in consanddata objects */
    8347 SCIP_CALL( computeConsAndDataChanges(scip, conshdlrdata) );
    8348
    8349 firstchange = INT_MAX;
    8350 firstupgradetry = INT_MAX;
    8351 cutoff = FALSE;
    8352
    8353 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
    8354 {
    8355 SCIP_CONS* cons;
    8356 SCIP_CONSDATA* consdata;
    8357 SCIP_VAR** vars;
    8358 SCIP_Real* coefs;
    8359 int nvars;
    8360 SCIP_VAR** linvars;
    8361 SCIP_Real* lincoefs;
    8362 int nlinvars;
    8363 SCIP_VAR** andress;
    8364 SCIP_Real* andcoefs;
    8365 SCIP_Bool* andnegs;
    8366 int nandress;
    8367 SCIP_Real newlhs;
    8368 SCIP_Real newrhs;
    8369
    8370 cons = conss[c];
    8371 assert(cons != NULL);
    8372 assert(SCIPconsIsActive(cons));
    8373
    8374 consdata = SCIPconsGetData(cons);
    8375 assert(consdata != NULL);
    8376 assert(consdata->lincons != NULL);
    8377
    8378 /* get sides of linear constraint */
    8379 SCIP_CALL( getLinearConsSides(scip, consdata->lincons, consdata->linconstype, &newlhs, &newrhs) );
    8380 assert(!SCIPisInfinity(scip, newlhs));
    8381 assert(!SCIPisInfinity(scip, -newrhs));
    8382 assert(SCIPisLE(scip, newlhs, newrhs));
    8383
    8384 /* gets number of variables in linear constraint */
    8385 SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
    8386
    8387 /* allocate temporary memory */
    8388 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    8389 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
    8390 SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nvars) );
    8391 SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nvars) );
    8392 SCIP_CALL( SCIPallocBufferArray(scip, &andress, nvars) );
    8393 SCIP_CALL( SCIPallocBufferArray(scip, &andcoefs, nvars) );
    8394 SCIP_CALL( SCIPallocBufferArray(scip, &andnegs, nvars) );
    8395
    8396 /* get variables and coefficient of linear constraint */
    8397 SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) );
    8398 assert(coefs != NULL || nvars == 0);
    8399
    8400 /* calculate all not artificial linear variables and all artificial and-resultants */
    8401 SCIP_CALL( getLinVarsAndAndRess(scip, cons, vars, coefs, nvars, linvars, lincoefs, &nlinvars,
    8402 andress, andcoefs, andnegs, &nandress) );
    8403
    8404 /* update all locks inside this constraint and all captures on all and-constraints */
    8405 SCIP_CALL( correctLocksAndCaptures(scip, cons, conshdlrdata, newlhs, newrhs, andress, andcoefs, andnegs, nandress) );
    8406
    8407 /* if linear constraint is redundant, pseudoboolean constraint is redundant too */
    8408 if( SCIPconsIsDeleted(consdata->lincons) )
    8409 {
    8410 /* update and-constraint flags */
    8411 SCIP_CALL( updateAndConss(scip, cons) );
    8412
    8413 SCIP_CALL( SCIPdelCons(scip, cons) );
    8414 ++(*ndelconss);
    8415
    8416 goto CONTTERMINATE;
    8417 }
    8418
    8419 /* we can only presolve pseudoboolean constraints, that are not modifiable */
    8420 if( SCIPconsIsModifiable(cons) )
    8421 goto CONTTERMINATE;
    8422
    8423 SCIPdebugMsg(scip, "presolving pseudoboolean constraint <%s>\n", SCIPconsGetName(cons));
    8425
    8426 /* remember the first changed constraint to begin the next aggregation round with */
    8427 if( firstchange == INT_MAX && consdata->changed )
    8428 firstchange = c;
    8429
    8430 if( consdata->changed && !SCIPisStopped(scip) )
    8431 {
    8432 /* check if we can aggregated some variables */
    8433 SCIP_CALL( findAggregation(scip, cons, conshdlrdata, ndelconss, naggrvars, &cutoff) );
    8434 }
    8435
    8436 /* if aggregation also deleted the constraint we can go to the next */
    8437 if( !SCIPconsIsActive(cons) )
    8438 goto CONTTERMINATE;
    8439
    8440 if( consdata->changed )
    8441 {
    8442 /* try upgrading pseudoboolean constraint to a linear constraint and/or remove possible and-constraints */
    8443 SCIP_CALL( tryUpgrading(scip, cons, conshdlrdata, ndelconss, naddconss, nfixedvars, nchgcoefs, nchgsides, &cutoff) );
    8444 if( cutoff )
    8445 goto CONTTERMINATE;
    8446 }
    8447
    8448 /* if upgrading deleted the pseudoboolean constraint we go on */
    8449 if( !SCIPconsIsActive(cons) )
    8450 goto CONTTERMINATE;
    8451
    8452 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
    8453 if( firstupgradetry == INT_MAX && !consdata->upgradetried )
    8454 firstupgradetry = c;
    8455
    8456 while( !consdata->presolved && !SCIPisStopped(scip) )
    8457 {
    8458 /* mark constraint being presolved and propagated */
    8459 consdata->presolved = TRUE;
    8460
    8461 /* add cliques to the clique table */
    8462 SCIP_CALL( addCliques(scip, cons, &cutoff, naggrvars, nchgbds) );
    8463 if( cutoff )
    8464 break;
    8465
    8466 /* propagate constraint */
    8467 SCIP_CALL( propagateCons(scip, cons, &cutoff, ndelconss) );
    8468 if( cutoff )
    8469 break;
    8470 }
    8471
    8472 CONTTERMINATE:
    8473
    8474 /* reset changed flag */
    8475 if( SCIPconsIsActive(cons) )
    8476 {
    8477 consdata->changed = FALSE;
    8478 }
    8479
    8480 /* free temporary memory */
    8481 SCIPfreeBufferArray(scip, &andnegs);
    8482 SCIPfreeBufferArray(scip, &andcoefs);
    8483 SCIPfreeBufferArray(scip, &andress);
    8484 SCIPfreeBufferArray(scip, &lincoefs);
    8485 SCIPfreeBufferArray(scip, &linvars);
    8486 SCIPfreeBufferArray(scip, &coefs);
    8487 SCIPfreeBufferArray(scip, &vars);
    8488 }
    8489
    8490 /* delete unused information in constraint handler data */
    8491 SCIP_CALL( correctConshdlrdata(scip, conshdlrdata, ndelconss) );
    8492
    8493 /* return the correct result code */
    8494 if( cutoff )
    8495 *result = SCIP_CUTOFF;
    8496 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
    8497 || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
    8498 *result = SCIP_SUCCESS;
    8499 else
    8500 *result = SCIP_DIDNOTFIND;
    8501
    8502 return SCIP_OKAY;
    8503}
    8504
    8505/** variable rounding lock method of constraint handler */
    8506static
    8507SCIP_DECL_CONSLOCK(consLockPseudoboolean)
    8508{ /*lint --e{715}*/
    8509 SCIP_CONSDATA* consdata;
    8510 SCIP_Real lhs;
    8511 SCIP_Real rhs;
    8512 SCIP_Bool haslhs;
    8513 SCIP_Bool hasrhs;
    8514 int v;
    8515 int c;
    8516
    8517 assert(scip != NULL);
    8518 assert(cons != NULL);
    8519 assert(conshdlr != NULL);
    8520 assert(locktype == SCIP_LOCKTYPE_MODEL);
    8521
    8523
    8524 consdata = SCIPconsGetData(cons);
    8525 assert(consdata != NULL);
    8526
    8527 lhs = consdata->lhs;
    8528 rhs = consdata->rhs;
    8529 assert(!SCIPisInfinity(scip, lhs));
    8530 assert(!SCIPisInfinity(scip, -rhs));
    8531 assert(SCIPisLE(scip, lhs, rhs));
    8532
    8533 haslhs = !SCIPisInfinity(scip, -lhs);
    8534 hasrhs = !SCIPisInfinity(scip, rhs);
    8535
    8536 SCIPdebugMsg(scip, "%socking constraint <%s> by [%d;%d].\n", (nlocksneg < 0) || (nlockspos < 0) ? "Unl" : "L", SCIPconsGetName(cons), nlocksneg, nlockspos);
    8537
    8538 /* update rounding locks of every single variable corresponding to the and-constraints */
    8539 for( c = consdata->nconsanddatas - 1; c >= 0; --c )
    8540 {
    8541 SCIP_VAR* andres;
    8542 SCIP_VAR** andvars;
    8543 SCIP_Real val;
    8544 int nandvars;
    8545 SCIP_CONS* andcons;
    8546 CONSANDDATA* consanddata;
    8547
    8548 consanddata = consdata->consanddatas[c];
    8549 assert( consanddata != NULL );
    8550
    8551 if( !consanddata->istransformed )
    8552 continue;
    8553
    8554 andcons = consanddata->cons;
    8555
    8556 if( andcons == NULL )
    8557 {
    8558 /* we should have no new variables */
    8559 assert(consanddata->nnewvars == 0);
    8560 assert(consanddata->nvars == 0);
    8561
    8562 SCIPfreeBlockMemoryArrayNull(scip, &(consanddata->vars), consanddata->svars);
    8563 SCIPfreeBlockMemoryArrayNull(scip, &(consanddata->newvars), consanddata->snewvars);
    8564
    8565 consanddata->nvars = 0;
    8566 consanddata->svars = 0;
    8567 consanddata->nnewvars = 0;
    8568 consanddata->snewvars = 0;
    8569 consanddata->istransformed = FALSE;
    8570
    8571 continue;
    8572 }
    8573 assert(andcons != NULL);
    8574 if( consanddata->nnewvars > 0 )
    8575 {
    8576 andvars = consanddata->newvars;
    8577 nandvars = consanddata->nnewvars;
    8578 }
    8579 else
    8580 {
    8581 andvars = consanddata->vars;
    8582 nandvars = consanddata->nvars;
    8583 }
    8584 assert(andvars != NULL || nandvars == 0);
    8585
    8586 /* probably we need to store the resultant too, now it's not possible to remove the resultant from the and-constraint */
    8587 andres = SCIPgetResultantAnd(scip, andcons);
    8588 assert(andres != NULL);
    8589
    8590 val = consdata->andnegs[c] ? -consdata->andcoefs[c] : consdata->andcoefs[c];
    8591
    8592 /* lock variables */
    8593 if( SCIPisPositive(scip, val) )
    8594 {
    8595 if( haslhs )
    8596 {
    8597 for( v = nandvars - 1; v >= 0; --v )
    8598 {
    8599 SCIP_CALL( SCIPaddVarLocksType(scip, andvars[v], locktype, nlockspos, nlocksneg) );
    8600 }
    8601 SCIP_CALL( SCIPaddVarLocksType(scip, andres, locktype, nlocksneg + nlockspos, nlocksneg + nlockspos) );
    8602
    8603 SCIP_CALL( checkLocksAndRes(scip, andres) );
    8604 }
    8605 if( hasrhs )
    8606 {
    8607 for( v = nandvars - 1; v >= 0; --v )
    8608 {
    8609 SCIP_CALL( SCIPaddVarLocksType(scip, andvars[v], locktype, nlocksneg, nlockspos) );
    8610 }
    8611 /* don't double the locks on the and-resultant */
    8612 if( !haslhs )
    8613 {
    8614 SCIP_CALL( SCIPaddVarLocksType(scip, andres, locktype, nlocksneg + nlockspos, nlocksneg + nlockspos) );
    8615
    8616 SCIP_CALL( checkLocksAndRes(scip, andres) );
    8617 }
    8618 }
    8619 }
    8620 else
    8621 {
    8622 if( haslhs )
    8623 {
    8624 for( v = nandvars - 1; v >= 0; --v )
    8625 {
    8626 SCIP_CALL( SCIPaddVarLocksType(scip, andvars[v], locktype, nlocksneg, nlockspos) );
    8627 }
    8628 SCIP_CALL( SCIPaddVarLocksType(scip, andres, locktype, nlocksneg + nlockspos, nlocksneg + nlockspos) );
    8629
    8630 SCIP_CALL( checkLocksAndRes(scip, andres) );
    8631 }
    8632 if( hasrhs )
    8633 {
    8634 for( v = nandvars - 1; v >= 0; --v )
    8635 {
    8636 SCIP_CALL( SCIPaddVarLocksType(scip, andvars[v], locktype, nlockspos, nlocksneg) );
    8637 }
    8638 /* don't double the locks on the and-resultant */
    8639 if( !haslhs )
    8640 {
    8641 SCIP_CALL( SCIPaddVarLocksType(scip, andres, locktype, nlocksneg + nlockspos, nlocksneg + nlockspos) );
    8642
    8643 SCIP_CALL( checkLocksAndRes(scip, andres) );
    8644 }
    8645 }
    8646 }
    8647 }
    8648
    8649 return SCIP_OKAY;
    8650}
    8651
    8652/** constraint display method of constraint handler
    8653 *
    8654 * @warning The linear-and-reformulation is part of the model and is separately printed by other constraint handlers
    8655 */
    8656static
    8657SCIP_DECL_CONSPRINT(consPrintPseudoboolean)
    8658{ /*lint --e{715}*/
    8659 assert(scip != NULL);
    8660 assert(conshdlr != NULL);
    8661 assert(cons != NULL);
    8662
    8664
    8665 SCIP_CALL( consdataPrint(scip, cons, file) );
    8666
    8667 return SCIP_OKAY;
    8668}
    8669
    8670/** constraint copying method of constraint handler */
    8671static
    8672SCIP_DECL_CONSCOPY(consCopyPseudoboolean)
    8673{ /*lint --e{715}*/
    8674 const char* consname;
    8675
    8676 assert(scip != NULL);
    8677 assert(sourcescip != NULL);
    8678 assert(sourcecons != NULL);
    8679
    8680 if( name != NULL )
    8681 consname = name;
    8682 else
    8683 consname = SCIPconsGetName(sourcecons);
    8684
    8685 SCIP_CALL( copyConsPseudoboolean(scip, cons, sourcescip, sourcecons, consname, varmap, consmap,
    8686 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global,
    8687 valid) );
    8688 assert(cons != NULL || *valid == FALSE);
    8689
    8690 return SCIP_OKAY;
    8691}
    8692
    8693/** constraint parsing method of constraint handler
    8694 *
    8695 * @warning The linear-and-reformulation is added even if equivalent variables and constraints are part of the model
    8696 */
    8697static
    8698SCIP_DECL_CONSPARSE(consParsePseudoboolean)
    8699{ /*lint --e{715}*/
    8700 SCIP_VAR*** monomialvars;
    8701 SCIP_VAR*** terms;
    8702 SCIP_VAR** linvars;
    8703 SCIP_VAR* indvar;
    8704 SCIP_Real** monomialexps;
    8705 SCIP_Real* monomialcoefs;
    8706 SCIP_Real* termvals;
    8707 SCIP_Real* linvals;
    8708 SCIP_Real weight;
    8709 SCIP_Real lhs;
    8710 SCIP_Real rhs;
    8711 SCIP_Bool issoftcons;
    8712 const char* endptr;
    8713 const char* firstcomp;
    8714 const char* secondcomp;
    8715 const char* lhsstrptr;
    8716 const char* rhsstrptr;
    8717 const char* varstrptr;
    8718 char* polynomialstr;
    8719 int* monomialnvars;
    8720 int* ntermvars;
    8721 int polynomialsize;
    8722 int nmonomials;
    8723 int nterms;
    8724 int nlinvars;
    8725 int i;
    8726 int j;
    8727
    8728 assert(scip != NULL);
    8729 assert(success != NULL);
    8730 assert(str != NULL);
    8731 assert(name != NULL);
    8732 assert(cons != NULL);
    8733
    8734 *success = FALSE;
    8735
    8736 /* ignore whitespace */
    8737 SCIP_CALL( SCIPskipSpace((char**)&str) );
    8738
    8739 /* return of string empty */
    8740 if( !(*str) )
    8741 return SCIP_OKAY;
    8742
    8743 /* find comparators in the line first, all other remaining parsing depends on occurence of
    8744 * the comparators '<=', '>=', '==', and the special word [free]
    8745 */
    8746 firstcomp = NULL;
    8747 secondcomp = NULL;
    8748 endptr = str;
    8749
    8750 /* loop over the input string to find all comparators */
    8751 while( *endptr )
    8752 {
    8753 SCIP_Bool found = FALSE;
    8754 int increment = 1;
    8755
    8756 /* try if we found a possible comparator */
    8757 switch( endptr[0] )
    8758 {
    8759 case '<':
    8760 case '=':
    8761 case '>':
    8762 /* check if the two characters endptr[0,1] form a comparator together */
    8763 if( endptr[1] == '=' )
    8764 {
    8765 found = TRUE;
    8766
    8767 /* update increment to continue after this comparator */
    8768 increment = 2;
    8769 }
    8770 break;
    8771 case '[':
    8772 if( strncmp(endptr, "[free]", 6) == 0 )
    8773 {
    8774 found = TRUE;
    8775
    8776 /* update increment to continue after this comparator */
    8777 increment = 6;
    8778 }
    8779 break;
    8780 default:
    8781 break;
    8782 }
    8783
    8784 /* assign the found comparator to the first or second pointer and check for syntactical violations */
    8785 if( found )
    8786 {
    8787 if( firstcomp == NULL )
    8788 {
    8789 firstcomp = endptr;
    8790 }
    8791 else
    8792 {
    8793 if( secondcomp != NULL )
    8794 {
    8795 SCIPerrorMessage("Found more than two comparators in line %s\n", str);
    8796 return SCIP_OKAY;
    8797 }
    8798 else if( strncmp(firstcomp, "<=", 2) != 0 )
    8799 {
    8800 SCIPerrorMessage("Two comparators in line that do not range: %s", str);
    8801 return SCIP_OKAY;
    8802 }
    8803 else if( strncmp(endptr, "<=", 2) != 0 )
    8804 {
    8805 SCIPerrorMessage("Bad second comparator, expected ranged specification: %s", str);
    8806 return SCIP_OKAY;
    8807 }
    8808
    8809 secondcomp = endptr;
    8810 }
    8811 }
    8812
    8813 endptr += increment;
    8814 }
    8815
    8816 /* check if we did find at least one comparator */
    8817 if( firstcomp == NULL )
    8818 {
    8819 SCIPerrorMessage("Could not find any comparator in line %s\n", str);
    8820 return SCIP_OKAY;
    8821 }
    8822
    8823 /* initialize side pointers to the free state */
    8824 lhsstrptr = NULL;
    8825 rhsstrptr = NULL;
    8826 varstrptr = str;
    8827
    8828 /* assign the strings for parsing the left hand side, right hand side, and pseudoboolean polynomial */
    8829 switch( *firstcomp )
    8830 {
    8831 case '<':
    8832 assert(firstcomp[1] == '=');
    8833 /* we have ranged row lhs <= ... <= rhs */
    8834 if( secondcomp != NULL )
    8835 {
    8836 assert(secondcomp[0] == '<' && secondcomp[1] == '=');
    8837 lhsstrptr = str;
    8838 rhsstrptr = secondcomp + 2;
    8839 varstrptr = firstcomp + 2;
    8840 }
    8841 /* we have an inequality with infinite left hand side ... <= rhs */
    8842 else
    8843 rhsstrptr = firstcomp + 2;
    8844 break;
    8845 case '>':
    8846 assert(firstcomp[1] == '=');
    8847 assert(secondcomp == NULL);
    8848 /* we have ... >= lhs */
    8849 lhsstrptr = firstcomp + 2;
    8850 break;
    8851 case '=':
    8852 assert(firstcomp[1] == '=');
    8853 assert(secondcomp == NULL);
    8854 /* we have ... == lhs (rhs) */
    8855 rhsstrptr = firstcomp + 2;
    8856 lhsstrptr = firstcomp + 2;
    8857 break;
    8858 case '[':
    8859 assert(strncmp(firstcomp, "[free]", 6) == 0);
    8860 assert(secondcomp == NULL);
    8861 /* we have ... [free] */
    8862 endptr = firstcomp + 6;
    8863 break;
    8864 default:
    8865 /* it should not be possible that a different character appears in that position */
    8866 SCIPerrorMessage("Parsing has wrong comparator character '%c', should be one of <=>[", *firstcomp);
    8867 return SCIP_READERROR;
    8868 }
    8869
    8870 /* initialize sides to the free state */
    8871 lhs = -SCIPinfinity(scip);
    8872 rhs = SCIPinfinity(scip);
    8873
    8874 /* parse left hand side, if necessary */
    8875 if( lhsstrptr != NULL )
    8876 {
    8877 if( !SCIPparseReal(scip, lhsstrptr, &lhs, (char**)&endptr) )
    8878 {
    8879 SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
    8880 return SCIP_OKAY;
    8881 }
    8882
    8883 /* in case of an equation, assign the left also to the right hand side */
    8884 if( rhsstrptr == lhsstrptr )
    8885 rhs = lhs;
    8886 }
    8887
    8888 /* parse right hand side, if different from left hand side */
    8889 if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
    8890 {
    8891 if( !SCIPparseReal(scip, rhsstrptr, &rhs, (char**)&endptr) )
    8892 {
    8893 SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
    8894 return SCIP_OKAY;
    8895 }
    8896 }
    8897
    8898 /* initialize indicator data to the hard state */
    8899 indvar = NULL;
    8900 weight = 0.0;
    8901 issoftcons = FALSE;
    8902
    8903 /* skip white spaces */
    8904 SCIP_CALL( SCIPskipSpace((char**)&endptr) );
    8905 str = endptr;
    8906
    8907 /* parse indicator variable, should look like (indvar = var) */
    8908 if( *endptr == '(' )
    8909 {
    8910 endptr = strchr(endptr + 1, '=');
    8911
    8912 if( endptr == NULL )
    8913 {
    8914 SCIPerrorMessage("variable assignment missing in '%s'\n", str);
    8915 return SCIP_OKAY;
    8916 }
    8917
    8918 /* parse variable name */
    8919 SCIP_CALL( SCIPparseVarName(scip, endptr + 1, &indvar, (char**)&endptr) );
    8920
    8921 if( indvar == NULL )
    8922 {
    8923 SCIPerrorMessage("indicator variable not found in '%s'\n", str);
    8924 return SCIP_OKAY;
    8925 }
    8926
    8927 /* parse closing parenthesis */
    8928 endptr = strchr(endptr, ')');
    8929
    8930 if( endptr == NULL )
    8931 {
    8932 SCIPerrorMessage("closing parenthesis missing in '%s'\n", str);
    8933 return SCIP_OKAY;
    8934 }
    8935
    8936 weight = SCIPvarGetObj(indvar);
    8937 issoftcons = TRUE;
    8938 }
    8939
    8940 /* initialize polynomial string */
    8941 polynomialsize = (int)(MAX(firstcomp, secondcomp) + 1 - varstrptr);
    8942 SCIP_CALL( SCIPallocBufferArray(scip, &polynomialstr, polynomialsize) );
    8943 (void)SCIPstrncpy(polynomialstr, varstrptr, polynomialsize);
    8944
    8945 /* parse pseudoboolean polynomial */
    8946 SCIP_CALL( SCIPparseVarsPolynomial(scip, polynomialstr, &monomialvars, &monomialexps, &monomialcoefs, &monomialnvars, &nmonomials, (char**)&endptr, success) );
    8947
    8948 /* free polynomial string */
    8949 polynomialsize -= (int)(endptr + 1 - polynomialstr);
    8950 SCIPfreeBufferArray(scip, &polynomialstr);
    8951
    8952 /* check polynomial syntax */
    8953 if( !(*success) )
    8954 {
    8955 SCIPerrorMessage("no luck in parsing pseudoboolean polynomial '%s'\n", varstrptr);
    8956 return SCIP_OKAY;
    8957 }
    8958 else if( polynomialsize >= 1 )
    8959 {
    8960 SCIPerrorMessage("no completion of parsing pseudoboolean polynomial '%s'\n", varstrptr);
    8961 SCIPfreeParseVarsPolynomialData(scip, &monomialvars, &monomialexps, &monomialcoefs, &monomialnvars, nmonomials);
    8962 *success = FALSE;
    8963 return SCIP_OKAY;
    8964 }
    8965
    8966 /* initialize buffers for storing the terms and coefficients */
    8967 SCIP_CALL( SCIPallocBufferArray(scip, &terms, nmonomials) );
    8968 SCIP_CALL( SCIPallocBufferArray(scip, &termvals, nmonomials) );
    8969 SCIP_CALL( SCIPallocBufferArray(scip, &ntermvars, nmonomials) );
    8970 SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nmonomials) );
    8971 SCIP_CALL( SCIPallocBufferArray(scip, &linvals, nmonomials) );
    8972
    8973 nterms = 0;
    8974 nlinvars = 0;
    8975
    8976 /* separate linear terms */
    8977 for( i = 0; i < nmonomials; ++i )
    8978 {
    8979 if( SCIPisZero(scip, monomialcoefs[i]) )
    8980 continue;
    8981
    8982 ntermvars[nterms] = 0;
    8983
    8984 /* collect relevant variables */
    8985 for( j = 0; j < monomialnvars[i]; ++j )
    8986 {
    8987 if( monomialexps[i][j] < 0.0 )
    8988 {
    8989 SCIPerrorMessage("invalid exponent '%f' on variable <%s> in pseudoboolean polynomial '%s'\n", monomialexps[i][j], SCIPvarGetName(monomialvars[i][j]), varstrptr);
    8990 goto TERMINATE;
    8991 }
    8992
    8993 if( monomialexps[i][j] == 0.0 )
    8994 continue;
    8995
    8996 monomialvars[i][ntermvars[nterms]++] = monomialvars[i][j];
    8997 }
    8998
    8999 if( ntermvars[nterms] > 1 )
    9000 {
    9001 terms[nterms] = monomialvars[i];
    9002 termvals[nterms] = monomialcoefs[i];
    9003 ++nterms;
    9004 }
    9005 else if( ntermvars[nterms] == 1 )
    9006 {
    9007 if( issoftcons && ( monomialvars[i][0] == indvar || SCIPvarGetNegatedVar(monomialvars[i][0]) == indvar ) )
    9008 {
    9009 SCIPerrorMessage("indicator variable <%s> part of indicated constraint '%s'\n", SCIPvarGetName(indvar), varstrptr);
    9010 goto TERMINATE;
    9011 }
    9012
    9013 linvars[nlinvars] = monomialvars[i][0];
    9014 linvals[nlinvars] = monomialcoefs[i];
    9015 ++nlinvars;
    9016 }
    9017 else
    9018 {
    9019 assert(ntermvars[nterms] == 0);
    9020
    9021 if( !SCIPisInfinity(scip, -lhs) )
    9022 lhs -= monomialcoefs[i];
    9023
    9024 if( !SCIPisInfinity(scip, rhs) )
    9025 rhs -= monomialcoefs[i];
    9026 }
    9027 }
    9028
    9029 /* create pseudoboolean constraint */
    9030 SCIP_CALL( SCIPcreateConsPseudoboolean(scip, cons, name, linvars, nlinvars, linvals, terms, nterms, ntermvars,
    9031 termvals, indvar, weight, issoftcons, lhs, rhs, initial, separate, enforce, check, propagate, local,
    9032 modifiable, dynamic, removable, stickingatnode) );
    9033
    9034TERMINATE:
    9035 /* free buffers for storing the terms and coefficients */
    9036 SCIPfreeBufferArray(scip, &linvals);
    9037 SCIPfreeBufferArray(scip, &linvars);
    9038 SCIPfreeBufferArray(scip, &ntermvars);
    9039 SCIPfreeBufferArray(scip, &termvals);
    9040 SCIPfreeBufferArray(scip, &terms);
    9041
    9042 /* free pseudoboolean polynomial */
    9043 SCIPfreeParseVarsPolynomialData(scip, &monomialvars, &monomialexps, &monomialcoefs, &monomialnvars, nmonomials);
    9044
    9045 return SCIP_OKAY;
    9046}
    9047
    9048/** constraint method of constraint handler which returns the variables (if possible) */
    9049static
    9050SCIP_DECL_CONSGETVARS(consGetVarsPseudoboolean)
    9051{ /*lint --e{715}*/
    9052 SCIP_CONSHDLRDATA* conshdlrdata;
    9053 SCIP_CONSDATA* consdata;
    9054 CONSANDDATA* consanddata;
    9055 SCIP_VAR** linconsvars;
    9056 SCIP_VAR** linvars;
    9057 SCIP_VAR** andress;
    9058 int nlinconsvars;
    9059 int nlinvars;
    9060 int nandress;
    9061 SCIP_Bool transformed;
    9062 int nvars;
    9063 int r;
    9064
    9065 assert(scip != NULL);
    9066 assert(conshdlr != NULL);
    9067 assert(cons != NULL);
    9068 assert(vars != NULL);
    9069 assert(success != NULL);
    9070
    9071 if( varssize < 0 )
    9072 return SCIP_INVALIDDATA;
    9073 assert(varssize >= 0);
    9074
    9075 *success = TRUE;
    9076
    9077 /* pseudoboolean constraint is already deleted */
    9078 if( SCIPconsIsDeleted(cons) )
    9079 {
    9080 vars = NULL;
    9081
    9082 return SCIP_OKAY; /*lint !e438*/
    9083 }
    9084
    9085 consdata = SCIPconsGetData(cons);
    9086 assert(consdata != NULL);
    9087 assert(consdata->lincons != NULL);
    9088
    9089 /* linear constraint of pseudoboolean is already deleted */
    9090 if( SCIPconsIsDeleted(consdata->lincons) )
    9091 {
    9092 vars = NULL;
    9093
    9094 return SCIP_OKAY; /*lint !e438*/
    9095 }
    9096
    9097 /* gets number of variables in linear constraint */
    9098 SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nlinconsvars) );
    9099 assert(nlinconsvars >= 0);
    9100
    9101 /* no variables exist */
    9102 if( nlinconsvars == 0 )
    9103 {
    9104 vars = NULL;
    9105
    9106 return SCIP_OKAY; /*lint !e438*/
    9107 }
    9108 /* not enough space in the variables array */
    9109 else if( varssize < nlinconsvars )
    9110 {
    9111 (*success) = FALSE;
    9112
    9113 return SCIP_OKAY;
    9114 }
    9115
    9116 /* allocate temporary memory */
    9117 SCIP_CALL( SCIPallocBufferArray(scip, &linconsvars, nlinconsvars) );
    9118 SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nlinconsvars) );
    9119 SCIP_CALL( SCIPallocBufferArray(scip, &andress, nlinconsvars) );
    9120
    9121 /* get variables and coefficient of linear constraint */
    9122 SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, linconsvars, NULL, &nlinconsvars) );
    9123
    9124 /* calculate all non-artificial linear variables and all artificial and-resultants */
    9125 SCIP_CALL( getLinVarsAndAndRess(scip, cons, linconsvars, NULL, nlinconsvars, linvars, NULL, &nlinvars,
    9126 andress, NULL, NULL, &nandress) );
    9127 assert(nlinconsvars == nlinvars + nandress);
    9128
    9129 nvars = nlinvars;
    9130
    9131 if( nlinvars > 0 )
    9132 {
    9133 assert(linvars != NULL);
    9134 BMScopyMemoryArray(vars, linvars, nvars);
    9135 }
    9136
    9137 if( nandress == 0 )
    9138 goto TERMINATE;
    9139
    9140 assert(andress != NULL);
    9141
    9142 /* get constraint handler data */
    9143 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    9144 assert(conshdlrdata != NULL);
    9145 assert(conshdlrdata->hashmap != NULL);
    9146
    9147 transformed = SCIPconsIsTransformed(cons);
    9148
    9149 for( r = nandress - 1; r >= 0; --r )
    9150 {
    9151 SCIP_CONS* andcons;
    9152
    9153 assert(andress[r] != NULL);
    9154
    9155 consanddata = (CONSANDDATA*) SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)andress[r]);
    9156
    9157 assert(consanddata != NULL);
    9158 assert(consanddata->istransformed);
    9159
    9160 if( transformed )
    9161 andcons = consanddata->cons;
    9162 else
    9163 andcons = consanddata->origcons;
    9164
    9165 assert(andcons != NULL);
    9166
    9167 /* not enough space for all variables */
    9168 if( varssize <= nvars )
    9169 {
    9170 (*success) = FALSE;
    9171
    9172 goto TERMINATE;
    9173 }
    9174
    9175 /* add the resultant */
    9176 vars[nvars] = andress[r];
    9177 ++nvars;
    9178
    9179 /* add all and-operands and the resultant */
    9180 if( !SCIPconsIsDeleted(andcons) )
    9181 {
    9182 int noperands = SCIPgetNVarsAnd(scip, andcons);
    9183
    9184 assert(noperands >= 0);
    9185
    9186 /* not enough space for all variables */
    9187 if( varssize < nvars + noperands )
    9188 {
    9189 (*success) = FALSE;
    9190
    9191 goto TERMINATE;
    9192 }
    9193
    9194 /* copy operands */
    9195 if( noperands > 0 )
    9196 {
    9197 assert(SCIPgetVarsAnd(scip, andcons) != NULL);
    9198 BMScopyMemoryArray(&(vars[nvars]), SCIPgetVarsAnd(scip, andcons), noperands); /*lint !e866*/
    9199 nvars += noperands;
    9200 }
    9201 }
    9202 }
    9203
    9204 TERMINATE:
    9205
    9206 /* free temporary memory */
    9207 SCIPfreeBufferArray(scip, &andress);
    9208 SCIPfreeBufferArray(scip, &linvars);
    9209 SCIPfreeBufferArray(scip, &linconsvars);
    9210
    9211 return SCIP_OKAY;
    9212}
    9213
    9214/** constraint method of constraint handler which returns the number of variables (if possible) */
    9215static
    9216SCIP_DECL_CONSGETNVARS(consGetNVarsPseudoboolean)
    9217{ /*lint --e{715}*/
    9218 SCIP_CONSHDLRDATA* conshdlrdata;
    9219 SCIP_CONSDATA* consdata;
    9220 CONSANDDATA* consanddata;
    9221 SCIP_VAR** linconsvars;
    9222 SCIP_VAR** linvars;
    9223 SCIP_VAR** andress;
    9224 int nlinconsvars;
    9225 int nlinvars;
    9226 int nandress;
    9227 SCIP_Bool transformed;
    9228 int r;
    9229
    9230 assert(scip != NULL);
    9231 assert(conshdlr != NULL);
    9232 assert(cons != NULL);
    9233 assert(nvars != NULL);
    9234 assert(success != NULL);
    9235
    9236 (*success) = TRUE;
    9237
    9238 /* pseudoboolean constraint is already deleted */
    9239 if( SCIPconsIsDeleted(cons) )
    9240 {
    9241 *nvars = 0;
    9242
    9243 return SCIP_OKAY;
    9244 }
    9245
    9246 consdata = SCIPconsGetData(cons);
    9247 assert(consdata != NULL);
    9248 assert(consdata->lincons != NULL);
    9249
    9250 /* linear constraint of pseudoboolean is already deleted */
    9251 if( SCIPconsIsDeleted(consdata->lincons) )
    9252 {
    9253 *nvars = 0;
    9254
    9255 return SCIP_OKAY;
    9256 }
    9257
    9258 /* gets number of variables in linear constraint */
    9259 SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nlinconsvars) );
    9260 assert(nlinconsvars >= 0);
    9261
    9262 /* no variables exist */
    9263 if( nlinconsvars == 0 )
    9264 {
    9265 *nvars = 0;
    9266
    9267 return SCIP_OKAY;
    9268 }
    9269
    9270 /* allocate temporary memory */
    9271 SCIP_CALL( SCIPallocBufferArray(scip, &linconsvars, nlinconsvars) );
    9272 SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nlinconsvars) );
    9273 SCIP_CALL( SCIPallocBufferArray(scip, &andress, nlinconsvars) );
    9274
    9275 /* get variables and coefficient of linear constraint */
    9276 SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, linconsvars, NULL, &nlinconsvars) );
    9277
    9278 /* calculate all non-artificial linear variables and all artificial and-resultants */
    9279 SCIP_CALL( getLinVarsAndAndRess(scip, cons, linconsvars, NULL, nlinconsvars, linvars, NULL, &nlinvars,
    9280 andress, NULL, NULL, &nandress) );
    9281 assert(nlinconsvars == nlinvars + nandress);
    9282
    9283 *nvars = nlinvars;
    9284
    9285 if( nandress == 0 )
    9286 goto TERMINATE;
    9287
    9288 assert(andress != NULL);
    9289
    9290 /* get constraint handler data */
    9291 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    9292 assert(conshdlrdata != NULL);
    9293 assert(conshdlrdata->hashmap != NULL);
    9294
    9295 transformed = SCIPconsIsTransformed(cons);
    9296
    9297 for( r = nandress - 1; r >= 0; --r )
    9298 {
    9299 SCIP_CONS* andcons;
    9300
    9301 assert(andress[r] != NULL);
    9302
    9303 consanddata = (CONSANDDATA*) SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)andress[r]);
    9304
    9305 assert(consanddata != NULL);
    9306 assert(consanddata->istransformed);
    9307
    9308 if( transformed )
    9309 andcons = consanddata->cons;
    9310 else
    9311 andcons = consanddata->origcons;
    9312
    9313 assert(andcons != NULL);
    9314
    9315 if( SCIPconsIsDeleted(andcons) )
    9316 {
    9317 /* only add one for the resultant */
    9318 ++(*nvars);
    9319 }
    9320 else
    9321 {
    9322 /* add all and-operands and one for the resultant */
    9323 *nvars += SCIPgetNVarsAnd(scip, andcons) + 1;
    9324 }
    9325 }
    9326
    9327 TERMINATE:
    9328 /* free temporary memory */
    9329 SCIPfreeBufferArray(scip, &andress);
    9330 SCIPfreeBufferArray(scip, &linvars);
    9331 SCIPfreeBufferArray(scip, &linconsvars);
    9332
    9333 return SCIP_OKAY;
    9334}
    9335
    9336/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
    9337static
    9338SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphPseudoboolean)
    9339{ /*lint --e{715}*/
    9340 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
    9341
    9342 return SCIP_OKAY;
    9343}
    9344
    9345/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
    9346static
    9347SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphPseudoboolean)
    9348{ /*lint --e{715}*/
    9349 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
    9350
    9351 return SCIP_OKAY;
    9352}
    9353
    9354/*
    9355 * constraint specific interface methods
    9356 */
    9357
    9358/** creates the handler for pseudoboolean constraints and includes it in SCIP */
    9360 SCIP* scip /**< SCIP data structure */
    9361 )
    9362{
    9363 SCIP_CONSHDLR* conshdlr;
    9364 SCIP_CONSHDLRDATA* conshdlrdata;
    9365
    9366 /* create pseudoboolean constraint handler data */
    9367 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata) );
    9368
    9369 /* include constraint handler */
    9372 consEnfolpPseudoboolean, consEnfopsPseudoboolean, consCheckPseudoboolean, consLockPseudoboolean,
    9373 conshdlrdata) );
    9374 assert(conshdlr != NULL);
    9375
    9376 /* set non-fundamental callbacks via specific setter functions */
    9377 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyPseudoboolean, consCopyPseudoboolean) );
    9378 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeletePseudoboolean) );
    9379 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreePseudoboolean) );
    9380 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsPseudoboolean) );
    9381 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsPseudoboolean) );
    9382 SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitPseudoboolean) );
    9383 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParsePseudoboolean) );
    9384 SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitprePseudoboolean) );
    9385 SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolPseudoboolean, CONSHDLR_MAXPREROUNDS,
    9387 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintPseudoboolean) );
    9388 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransPseudoboolean) );
    9389 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxPseudoboolean) );
    9390 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphPseudoboolean) );
    9391 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphPseudoboolean) );
    9392
    9393 /* add pseudoboolean constraint handler parameters */
    9395 "constraints/" CONSHDLR_NAME "/decomposenormal",
    9396 "decompose every normal pseudo boolean constraint into a \"linear\" constraint and \"and\" constraints",
    9397 &conshdlrdata->decomposenormalpbcons, TRUE, DEFAULT_DECOMPOSENORMALPBCONS, NULL, NULL) );
    9399 "constraints/" CONSHDLR_NAME "/decomposeindicator",
    9400 "decompose every soft pseudo boolean constraint into \"indicator\" constraints and \"and\" constraints",
    9401 &conshdlrdata->decomposeindicatorpbcons, TRUE, DEFAULT_DECOMPOSEINDICATORPBCONS, NULL, NULL) );
    9403 "constraints/" CONSHDLR_NAME "/nlcseparate", "should the nonlinear constraints be separated during LP processing?",
    9406 "constraints/" CONSHDLR_NAME "/nlcpropagate", "should the nonlinear constraints be propagated during node processing?",
    9409 "constraints/" CONSHDLR_NAME "/nlcremovable", "should the nonlinear constraints be removable?",
    9411
    9412#ifdef NONLINCONSUPGD_PRIORITY
    9413 /* include the quadratic constraint upgrade in the nonlinear constraint handler */
    9414 SCIP_CALL( SCIPincludeNonlinconsUpgrade(scip, nonlinconsUpgdPseudoboolean, NULL, NONLINCONSUPGD_PRIORITY, TRUE, CONSHDLR_NAME) );
    9415#endif
    9416
    9417 return SCIP_OKAY;
    9418}
    9419
    9420/** creates and captures a pseudoboolean constraint, with given linear and and-constraints */
    9422 SCIP* scip, /**< SCIP data structure */
    9423 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    9424 const char* name, /**< name of constraint */
    9425 SCIP_CONS* lincons, /**< associated linear constraint */
    9426 SCIP_LINEARCONSTYPE linconstype, /**< linear constraint type of associated linear constraint */
    9427 SCIP_CONS** andconss, /**< associated and-constraints */
    9428 SCIP_Real* andcoefs, /**< associated coefficients of and-constraints */
    9429 int nandconss, /**< number of associated and-constraints */
    9430 SCIP_VAR* indvar, /**< indicator variable if it's a soft constraint, or NULL */
    9431 SCIP_Real weight, /**< weight of the soft constraint, if it is one */
    9432 SCIP_Bool issoftcons, /**< is this a soft constraint */
    9433 SCIP_Real lhs, /**< left hand side of constraint */
    9434 SCIP_Real rhs, /**< right hand side of constraint */
    9435 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
    9436 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    9437 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
    9438 * Usually set to TRUE. */
    9439 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    9440 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    9441 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    9442 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    9443 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
    9444 * Usually set to TRUE. */
    9445 SCIP_Bool local, /**< is constraint only valid locally?
    9446 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    9447 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
    9448 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
    9449 * adds coefficients to this constraint. */
    9450 SCIP_Bool dynamic, /**< is constraint subject to aging?
    9451 * Usually set to FALSE. Set to TRUE for own cuts which
    9452 * are seperated as constraints. */
    9453 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
    9454 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
    9455 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    9456 * if it may be moved to a more global node?
    9457 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
    9458 )
    9459{
    9460 CONSANDDATA* newdata;
    9461 CONSANDDATA* tmpdata;
    9462 SCIP_CONSHDLR* conshdlr;
    9463 SCIP_CONSHDLRDATA* conshdlrdata;
    9464 SCIP_CONSDATA* consdata;
    9465 SCIP_VAR** vars;
    9466 SCIP_VAR* res;
    9467 SCIP_Bool memisinvalid;
    9468 SCIP_Bool transformed;
    9469 int nvars;
    9470 int c;
    9471
    9472 assert(scip != NULL);
    9473 assert(cons != NULL);
    9474 assert(lincons != NULL);
    9475 assert(linconstype > SCIP_LINEARCONSTYPE_INVALIDCONS);
    9476 assert(andconss != NULL || nandconss == 0);
    9477 assert(andcoefs != NULL || nandconss == 0);
    9478 assert(issoftcons == (indvar != NULL));
    9479
    9480 /* find the pseudoboolean constraint handler */
    9481 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    9482 if( conshdlr == NULL )
    9483 {
    9484 SCIPerrorMessage("pseudo boolean constraint handler not found\n");
    9485 return SCIP_PLUGINNOTFOUND;
    9486 }
    9487
    9488 if( isnan(lhs) || isnan(rhs) )
    9489 {
    9490 SCIPerrorMessage("%s hand side of pseudo boolean constraint <%s> is nan\n",
    9491 isnan(lhs) ? "left" : "right", name);
    9492 return SCIP_INVALIDDATA;
    9493 }
    9494
    9495 if( issoftcons )
    9496 {
    9497 if( modifiable )
    9498 {
    9499 SCIPerrorMessage("soft pseudo boolean constraint <%s> must not be modifiable because the implemented formulation requires finite activity bounds\n", name);
    9500 return SCIP_INVALIDDATA;
    9501 }
    9502
    9503 if( isnan(weight) )
    9504 {
    9505 SCIPerrorMessage("weight of pseudo boolean constraint <%s> is nan\n", name);
    9506 return SCIP_INVALIDDATA;
    9507 }
    9508 }
    9509
    9510 /* get constraint handler data */
    9511 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    9512 assert(conshdlrdata != NULL);
    9513
    9514 /* initial hashmap and -table */
    9515 SCIP_CALL( inithashmapandtable(scip, &conshdlrdata) );
    9516
    9517 assert(conshdlrdata->hashmap != NULL);
    9518 assert(conshdlrdata->hashtable != NULL);
    9519 assert(conshdlrdata->allconsanddatas != NULL);
    9520 assert(conshdlrdata->nallconsanddatas <= conshdlrdata->sallconsanddatas);
    9521
    9522 memisinvalid = TRUE;
    9523 newdata = NULL;
    9524
    9525 transformed = SCIPconsIsTransformed(lincons);
    9526
    9527 /* create hash map and hash table entries */
    9528 for( c = nandconss - 1; c >= 0; --c )
    9529 {
    9530 assert(andconss[c] != NULL);
    9531 res = SCIPgetResultantAnd(scip, andconss[c]);
    9532 vars = SCIPgetVarsAnd(scip, andconss[c]);
    9533 nvars = SCIPgetNVarsAnd(scip, andconss[c]);
    9534 assert(vars != NULL && nvars > 0);
    9535 assert(res != NULL);
    9536
    9537 /* stop if the constraint has 0 variables or an error occurred (coverity issue) */
    9538 if( nvars <= 0 )
    9539 continue;
    9540
    9541 /* if allocated memory in this for loop was already used, allocate a new block, otherwise we only need to copy the variables */
    9542 if( memisinvalid )
    9543 {
    9544 /* allocate memory for a possible new consanddata object */
    9545 SCIP_CALL( SCIPallocBlockMemory(scip, &newdata) );
    9546 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(newdata->vars), vars, nvars) );
    9547 newdata->svars = nvars;
    9548 newdata->newvars = NULL;
    9549 newdata->nnewvars = 0;
    9550 newdata->snewvars = 0;
    9551 newdata->istransformed = transformed;
    9552 newdata->isoriginal = !transformed;
    9553 newdata->noriguses = 0;
    9554 newdata->nuses = 0;
    9555 newdata->cons = NULL;
    9556 newdata->origcons = NULL;
    9557 }
    9558 else
    9559 {
    9560 assert(newdata != NULL);
    9561 /* resize variable array if necessary */
    9562 if( newdata->svars < nvars )
    9563 {
    9564 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &(newdata->vars), &(newdata->svars), nvars) );
    9565 }
    9566
    9567 /* copy variables in already allocated array */
    9568 BMScopyMemoryArray(newdata->vars, vars, nvars);
    9569 }
    9570
    9571 /* sort variables */
    9572 SCIPsortPtr((void**)(newdata->vars), SCIPvarComp, nvars);
    9573
    9574 newdata->nvars = nvars;
    9575 assert(newdata->vars != NULL && newdata->nvars > 0);
    9576
    9577 if( SCIPconsIsTransformed(andconss[c]) )
    9578 {
    9579 int v;
    9580
    9581 /* either all constraints are transformed or none */
    9582 assert(transformed);
    9583 newdata->cons = andconss[c];
    9584
    9585 /* capture all variables */
    9586 for( v = newdata->nvars - 1; v >= 0; --v )
    9587 {
    9588 SCIP_CALL( SCIPcaptureVar(scip, newdata->vars[v]) ); /*lint !e613*/
    9589 }
    9590 }
    9591 else
    9592 {
    9593 /* either all constraints are transformed or none */
    9594 assert(!transformed);
    9595 newdata->origcons = andconss[c];
    9596 }
    9597
    9598 /* get constraint from current hash table with same variables as andconss[c] */
    9599 tmpdata = (CONSANDDATA*)(SCIPhashtableRetrieve(conshdlrdata->hashtable, (void*)newdata));
    9600 assert(tmpdata == NULL || tmpdata->cons != NULL || tmpdata->origcons != NULL);
    9601
    9602 if( tmpdata == NULL || (tmpdata->cons != andconss[c] && tmpdata->origcons != andconss[c]))
    9603 {
    9604 if( tmpdata != NULL && (tmpdata->cons != NULL || tmpdata->origcons != NULL) )
    9605 {
    9606 SCIPwarningMessage(scip, "Another and-constraint with the same variables but different and-resultant is added to the global and-constraint hashtable of pseudoboolean constraint handler.\n");
    9607 }
    9608
    9609 /* resize data for all and-constraints if necessary */
    9610 if( conshdlrdata->nallconsanddatas == conshdlrdata->sallconsanddatas )
    9611 {
    9612 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &(conshdlrdata->allconsanddatas), &(conshdlrdata->sallconsanddatas), SCIPcalcMemGrowSize(scip, conshdlrdata->sallconsanddatas + 1)) );
    9613 }
    9614
    9615 conshdlrdata->allconsanddatas[conshdlrdata->nallconsanddatas] = newdata;
    9616 ++(conshdlrdata->nallconsanddatas);
    9617
    9618 /* no such and-constraint in current hash table: insert the new object into hash table */
    9619 SCIP_CALL( SCIPhashtableInsert(conshdlrdata->hashtable, (void*)newdata) );
    9620
    9621 /* if newdata object was new we want to allocate new memory in next loop iteration */
    9622 memisinvalid = TRUE;
    9623 assert(!SCIPhashmapExists(conshdlrdata->hashmap, (void*)res));
    9624
    9625 /* capture and-constraint */
    9626 if( transformed )
    9627 {
    9628 SCIP_CALL( SCIPcaptureCons(scip, newdata->cons) );
    9629
    9630 /* lock upgrade to keep control */
    9631 SCIPconsAddUpgradeLocks(newdata->cons, +1);
    9632
    9633 /* initialize usage of data object */
    9634 newdata->nuses = 1;
    9635 }
    9636 else
    9637 {
    9638 SCIP_CALL( SCIPcaptureCons(scip, newdata->origcons) );
    9639
    9640 /* initialize usage of data object */
    9641 newdata->noriguses = 1;
    9642 }
    9643
    9644 /* insert new mapping */
    9645 assert(!SCIPhashmapExists(conshdlrdata->hashmap, (void*)res));
    9646 SCIP_CALL( SCIPhashmapInsert(conshdlrdata->hashmap, (void*)res, (void*)newdata) );
    9647 }
    9648 else
    9649 {
    9650 assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)res));
    9651 memisinvalid = FALSE;
    9652
    9653 if( transformed )
    9654 {
    9655 assert(tmpdata->nuses > 0);
    9656
    9657 /* increase usage of data object */
    9658 ++(tmpdata->nuses);
    9659 }
    9660 else
    9661 {
    9662 assert(tmpdata->noriguses > 0);
    9663
    9664 /* increase usage of data object */
    9665 ++(tmpdata->noriguses);
    9666 }
    9667 }
    9668 }
    9669
    9670 if( !memisinvalid )
    9671 {
    9672 assert(newdata != NULL);
    9673
    9674 /* free temporary memory */
    9675 SCIPfreeBlockMemoryArray(scip, &(newdata->vars), newdata->svars);
    9676 SCIPfreeBlockMemory(scip, &newdata);
    9677 }
    9678
    9679 /* adjust right hand side */
    9680 if( SCIPisInfinity(scip, rhs) )
    9681 rhs = SCIPinfinity(scip);
    9682 else if( SCIPisInfinity(scip, -rhs) )
    9683 rhs = -SCIPinfinity(scip);
    9684
    9685 /* capture linear constraint */
    9686 SCIP_CALL( SCIPcaptureCons(scip, lincons) );
    9687
    9688 /* @todo: make the constraint upgrade flag global, now it works only for the common linear constraint */
    9689 /* mark linear constraint not to be upgraded - otherwise we loose control over it */
    9690 SCIPconsAddUpgradeLocks(lincons, +1);
    9691
    9692 /* create constraint data */
    9693 /* checking for and-constraints will be FALSE, we check all information in this constraint handler */
    9694 SCIP_CALL( consdataCreate(scip, conshdlr, &consdata, lincons, linconstype, andconss, andcoefs, NULL, nandconss,
    9695 indvar, weight, issoftcons, lhs, rhs, check, FALSE) );
    9696 assert(consdata != NULL);
    9697
    9698 /* create constraint */
    9699 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
    9700 local, modifiable, dynamic, removable, stickingatnode) );
    9701
    9702 return SCIP_OKAY;
    9703}
    9704
    9705/** creates and captures a pseudoboolean constraint
    9706 *
    9707 * @note linear and nonlinear terms can be added using SCIPaddCoefPseudoboolean() and SCIPaddTermPseudoboolean(),
    9708 * respectively
    9709 *
    9710 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    9711 */
    9713 SCIP* scip, /**< SCIP data structure */
    9714 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    9715 const char* name, /**< name of constraint */
    9716 SCIP_VAR** linvars, /**< variables of the linear part, or NULL */
    9717 int nlinvars, /**< number of variables of the linear part */
    9718 SCIP_Real* linvals, /**< coefficients of linear part, or NULL */
    9719 SCIP_VAR*** terms, /**< nonlinear terms of variables, or NULL */
    9720 int nterms, /**< number of terms of variables of nonlinear term */
    9721 int* ntermvars, /**< number of variables in nonlinear terms, or NULL */
    9722 SCIP_Real* termvals, /**< coefficients of nonlinear parts, or NULL */
    9723 SCIP_VAR* indvar, /**< indicator variable if it's a soft constraint, or NULL */
    9724 SCIP_Real weight, /**< weight of the soft constraint, if it is one */
    9725 SCIP_Bool issoftcons, /**< is this a soft constraint */
    9726 SCIP_Real lhs, /**< left hand side of constraint */
    9727 SCIP_Real rhs, /**< right hand side of constraint */
    9728 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
    9729 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    9730 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
    9731 * Usually set to TRUE. */
    9732 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    9733 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    9734 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    9735 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    9736 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
    9737 * Usually set to TRUE. */
    9738 SCIP_Bool local, /**< is constraint only valid locally?
    9739 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    9740 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
    9741 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
    9742 * adds coefficients to this constraint. */
    9743 SCIP_Bool dynamic, /**< is constraint subject to aging?
    9744 * Usually set to FALSE. Set to TRUE for own cuts which
    9745 * are separated as constraints. */
    9746 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
    9747 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
    9748 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    9749 * if it may be moved to a more global node?
    9750 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
    9751 )
    9752{
    9753 SCIP_CONSHDLRDATA* conshdlrdata;
    9754 SCIP_CONSHDLR* conshdlr;
    9755 SCIP_CONSDATA* consdata;
    9756 SCIP_VAR** andress;
    9757 SCIP_CONS** andconss;
    9758 SCIP_Real* andcoefs;
    9759 SCIP_Bool* andnegs;
    9760 int nandconss;
    9761 SCIP_CONS* lincons;
    9762 SCIP_LINEARCONSTYPE linconstype;
    9763 int c;
    9764
    9765 assert(scip != NULL);
    9766 assert(cons != NULL);
    9767 assert(linvars != NULL || nlinvars == 0);
    9768 assert(linvals != NULL || nlinvars == 0);
    9769 assert(terms != NULL || nterms == 0);
    9770 assert(termvals != NULL || nterms == 0);
    9771 assert(ntermvars != NULL || nterms == 0);
    9772 assert(issoftcons == (indvar != NULL));
    9773
    9774 /* find the pseudoboolean constraint handler */
    9775 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    9776 if( conshdlr == NULL )
    9777 {
    9778 SCIPerrorMessage("pseudo boolean constraint handler not found\n");
    9779 return SCIP_PLUGINNOTFOUND;
    9780 }
    9781
    9782 if( isnan(lhs) || isnan(rhs) )
    9783 {
    9784 SCIPerrorMessage("%s hand side of pseudo boolean constraint <%s> is nan\n",
    9785 isnan(lhs) ? "left" : "right", name);
    9786 return SCIP_INVALIDDATA;
    9787 }
    9788
    9789 if( issoftcons )
    9790 {
    9791 if( modifiable )
    9792 {
    9793 SCIPerrorMessage("soft pseudo boolean constraint <%s> must not be modifiable because the implemented formulation requires finite activity bounds\n", name);
    9794 return SCIP_INVALIDDATA;
    9795 }
    9796
    9797 if( isnan(weight) )
    9798 {
    9799 SCIPerrorMessage("weight of pseudo boolean constraint <%s> is nan\n", name);
    9800 return SCIP_INVALIDDATA;
    9801 }
    9802 }
    9803
    9804 for( c = 0; c < nlinvars; ++c )
    9805 {
    9806 if( !SCIPisFinite(linvals[c]) || SCIPisInfinity(scip, REALABS(linvals[c])) )
    9807 {
    9808 SCIPerrorMessage("pseudo boolean linear coefficient %lf is %s\n",
    9809 linvals[c], SCIPisFinite(linvals[c]) ? "infinite" : "nan");
    9810 return SCIP_INVALIDDATA;
    9811 }
    9812 }
    9813
    9814 for( c = 0; c < nterms; ++c )
    9815 {
    9816 if( ntermvars[c] == 0 && !SCIPisZero(scip, termvals[c]) )
    9817 {
    9818 SCIPerrorMessage("pseudo boolean term with coefficient %lf without variables\n", termvals[c]);
    9819 return SCIP_INVALIDDATA;
    9820 }
    9821
    9822 if( !SCIPisFinite(termvals[c]) || SCIPisInfinity(scip, REALABS(termvals[c])) )
    9823 {
    9824 SCIPerrorMessage("pseudo boolean term coefficient %lf is %s\n",
    9825 termvals[c], SCIPisFinite(termvals[c]) ? "infinite" : "nan");
    9826 return SCIP_INVALIDDATA;
    9827 }
    9828 }
    9829
    9830 /* get constraint handler data */
    9831 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    9832 assert(conshdlrdata != NULL);
    9833
    9834 /* initial hashmap and -table */
    9835 SCIP_CALL( inithashmapandtable(scip, &conshdlrdata) );
    9836
    9837 /* get temporary memory */
    9838 SCIP_CALL( SCIPallocBufferArray(scip, &andconss, nterms) );
    9840 SCIP_CALL( SCIPallocBufferArray(scip, &andcoefs, nterms) );
    9842
    9843 nandconss = 0;
    9844 /* create and-constraints */
    9845 SCIP_CALL( createAndAddAnds(scip, conshdlr, terms, termvals, nterms, ntermvars,
    9846 initial, enforce, check, local, modifiable, dynamic, stickingatnode,
    9847 andconss, andcoefs, andnegs, &nandconss) );
    9848 assert(nterms >= nandconss);
    9849
    9850 /* get all and-resultants for linear constraint */
    9851 for( c = nandconss - 1; c >= 0; --c )
    9852 {
    9853 assert(andconss[c] != NULL);
    9854 andress[c] = SCIPgetResultantAnd(scip, andconss[c]);
    9855 }
    9856
    9857 linconstype = SCIP_LINEARCONSTYPE_INVALIDCONS;
    9858
    9859 /* adjust right hand side */
    9860 if( SCIPisInfinity(scip, rhs) )
    9861 rhs = SCIPinfinity(scip);
    9862 else if( SCIPisInfinity(scip, -rhs) )
    9863 rhs = -SCIPinfinity(scip);
    9864
    9865 /* create and add linear constraint */
    9866 /* checking for original linear constraint will be FALSE, transformed linear constraints get the check flag like this
    9867 * pseudoboolean constraint, in this constraint handler we only will check all and-constraints
    9868 */
    9869 SCIP_CALL( createAndAddLinearCons(scip, conshdlr, linvars, nlinvars, linvals, andress, nandconss, andcoefs, andnegs,
    9870 &lhs, &rhs, issoftcons, initial, separate, enforce, FALSE/*check*/, propagate, local, modifiable, dynamic,
    9871 removable, stickingatnode, &lincons, &linconstype) );
    9872 assert(lincons != NULL);
    9873 assert(linconstype > SCIP_LINEARCONSTYPE_INVALIDCONS);
    9874
    9875 /* create constraint data */
    9876 /* checking for and-constraints will be FALSE, we check all information in this constraint handler */
    9877 SCIP_CALL( consdataCreate(scip, conshdlr, &consdata, lincons, linconstype, andconss, andcoefs, andnegs, nandconss,
    9878 indvar, weight, issoftcons, lhs, rhs, check, FALSE) );
    9879 assert(consdata != NULL);
    9880
    9881 /* free temporary memory */
    9882 SCIPfreeBufferArray(scip, &andnegs);
    9883 SCIPfreeBufferArray(scip, &andcoefs);
    9884 SCIPfreeBufferArray(scip, &andress);
    9885 SCIPfreeBufferArray(scip, &andconss);
    9886
    9887 /* create constraint */
    9888 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
    9889 local, modifiable, dynamic, removable, stickingatnode) );
    9890
    9891 return SCIP_OKAY;
    9892}
    9893
    9894/** creates and captures a pseudoboolean constraint
    9895 * in its most basic variant, i. e., with all constraint flags set to their default values, which can be set
    9896 * afterwards using SCIPsetConsFLAGNAME() in scip.h
    9897 *
    9898 * @see SCIPcreateConsPseudoboolean() for the default constraint flag configuration
    9899 *
    9900 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    9901 */
    9903 SCIP* scip, /**< SCIP data structure */
    9904 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    9905 const char* name, /**< name of constraint */
    9906 SCIP_VAR** linvars, /**< variables of the linear part, or NULL */
    9907 int nlinvars, /**< number of variables of the linear part */
    9908 SCIP_Real* linvals, /**< coefficients of linear part, or NULL */
    9909 SCIP_VAR*** terms, /**< nonlinear terms of variables, or NULL */
    9910 int nterms, /**< number of terms of variables of nonlinear term */
    9911 int* ntermvars, /**< number of variables in nonlinear terms, or NULL */
    9912 SCIP_Real* termvals, /**< coefficients of nonlinear parts, or NULL */
    9913 SCIP_VAR* indvar, /**< indicator variable if it's a soft constraint, or NULL */
    9914 SCIP_Real weight, /**< weight of the soft constraint, if it is one */
    9915 SCIP_Bool issoftcons, /**< is this a soft constraint */
    9916 SCIP_Real lhs, /**< left hand side of constraint */
    9917 SCIP_Real rhs /**< right hand side of constraint */
    9918 )
    9919{
    9920 SCIP_CALL( SCIPcreateConsPseudoboolean(scip, cons, name, linvars, nlinvars, linvals, terms, nterms, ntermvars,
    9921 termvals, indvar, weight, issoftcons, lhs, rhs, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE,
    9922 FALSE) );
    9923
    9924 return SCIP_OKAY;
    9925}
    9926
    9927/** adds a variable to the pseudo boolean constraint (if it is not zero)
    9928 *
    9929 * @note you can only add a coefficient if the special type of linear constraint won't changed
    9930 *
    9931 * @todo if adding a coefficient would change the type of the special linear constraint, we need to erase it and
    9932 * create a new linear constraint
    9933 */
    9935 SCIP*const scip, /**< SCIP data structure */
    9936 SCIP_CONS*const cons, /**< constraint data */
    9937 SCIP_VAR*const var, /**< variable of constraint entry */
    9938 SCIP_Real const val /**< coefficient of constraint entry */
    9939 )
    9940{
    9941 SCIP_CONSDATA* consdata;
    9942
    9943 assert(scip != NULL);
    9944 assert(cons != NULL);
    9945 assert(var != NULL);
    9946
    9948
    9949 if( !SCIPisFinite(val) || SCIPisInfinity(scip, REALABS(val)) )
    9950 {
    9951 SCIPerrorMessage("pseudo boolean linear coefficient %lf is %s\n",
    9952 val, SCIPisFinite(val) ? "infinite" : "nan");
    9953 return SCIP_INVALIDDATA;
    9954 }
    9955
    9956 if( SCIPisZero(scip, val) )
    9957 return SCIP_OKAY;
    9958
    9959 consdata = SCIPconsGetData(cons);
    9960 assert(consdata != NULL);
    9961
    9962 switch( consdata->linconstype )
    9963 {
    9965 SCIP_CALL( SCIPaddCoefLinear(scip, consdata->lincons, var, val) );
    9966 break;
    9968 if( !SCIPisEQ(scip, val, 1.0) )
    9969 return SCIP_INVALIDDATA;
    9970
    9971 SCIP_CALL( SCIPaddCoefLogicor(scip, consdata->lincons, var) );
    9972 break;
    9974 if( !SCIPisIntegral(scip, val) || !SCIPisPositive(scip, val) )
    9975 return SCIP_INVALIDDATA;
    9976
    9977 SCIP_CALL( SCIPaddCoefKnapsack(scip, consdata->lincons, var, (SCIP_Longint) val) );
    9978 break;
    9980 if( !SCIPisEQ(scip, val, 1.0) )
    9981 return SCIP_INVALIDDATA;
    9982
    9983 SCIP_CALL( SCIPaddCoefSetppc(scip, consdata->lincons, var) );
    9984 break;
    9985#ifdef WITHEQKNAPSACK
    9986 case SCIP_LINEARCONSTYPE_EQKNAPSACK:
    9987 if( !SCIPisIntegral(scip, val) || !SCIPisPositive(scip, val) )
    9988 return SCIP_INVALIDDATA;
    9989
    9990 SCIP_CALL( SCIPaddCoefEQKnapsack(scip, consdata->lincons, var, (SCIP_Longint) val) );
    9991 break;
    9992#endif
    9994 default:
    9995 SCIPerrorMessage("unknown linear constraint type\n");
    9996 return SCIP_INVALIDDATA;
    9997 }
    9998
    9999 consdata->propagated = FALSE;
    10000 consdata->presolved = FALSE;
    10001 consdata->cliquesadded = FALSE;
    10002
    10003 return SCIP_OKAY;
    10004}
    10005
    10006/** adds nonlinear term to pseudo boolean constraint (if it is not zero)
    10007 *
    10008 * @note you can only add a coefficient if the special type of linear constraint won't changed
    10009 *
    10010 * @todo if adding a coefficient would change the type of the special linear constraint, we need to erase it and
    10011 * create a new linear constraint
    10012 */
    10014 SCIP*const scip, /**< SCIP data structure */
    10015 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    10016 SCIP_VAR**const vars, /**< variables of the nonlinear term */
    10017 int const nvars, /**< number of variables of the nonlinear term */
    10018 SCIP_Real const val /**< coefficient of constraint entry */
    10019 )
    10020{
    10021 assert(scip != NULL);
    10022 assert(cons != NULL);
    10023 assert(vars != NULL || nvars == 0);
    10024
    10026
    10027 if( nvars == 0 && !SCIPisZero(scip, val) )
    10028 {
    10029 SCIPerrorMessage("pseudo boolean term with coefficient %lf without variables\n", val);
    10030 return SCIP_INVALIDDATA;
    10031 }
    10032
    10033 if( !SCIPisFinite(val) || SCIPisInfinity(scip, REALABS(val)) )
    10034 {
    10035 SCIPerrorMessage("pseudo boolean term coefficient %lf is %s\n",
    10036 val, SCIPisFinite(val) ? "infinite" : "nan");
    10037 return SCIP_INVALIDDATA;
    10038 }
    10039
    10040 SCIP_CALL( addCoefTerm(scip, cons, vars, nvars, val) );
    10041
    10042 return SCIP_OKAY;
    10043}
    10044
    10045/** gets indicator variable of pseudoboolean constraint, or NULL if there is no */
    10047 SCIP*const scip, /**< SCIP data structure */
    10048 SCIP_CONS*const cons /**< constraint data */
    10049 )
    10050{
    10051 SCIP_CONSDATA* consdata;
    10052
    10053 assert(scip != NULL);
    10054 assert(cons != NULL);
    10055
    10057
    10058 consdata = SCIPconsGetData(cons);
    10059 assert(consdata != NULL);
    10060
    10061 return consdata->indvar;
    10062}
    10063
    10064/** gets linear constraint of pseudoboolean constraint */
    10066 SCIP*const scip, /**< SCIP data structure */
    10067 SCIP_CONS*const cons /**< constraint data */
    10068 )
    10069{
    10070 SCIP_CONSDATA* consdata;
    10071
    10072 assert(scip != NULL);
    10073 assert(cons != NULL);
    10074
    10076
    10077 consdata = SCIPconsGetData(cons);
    10078 assert(consdata != NULL);
    10079
    10080 return consdata->lincons;
    10081}
    10082
    10083/** gets type of linear constraint of pseudoboolean constraint */
    10085 SCIP*const scip, /**< SCIP data structure */
    10086 SCIP_CONS*const cons /**< constraint data */
    10087 )
    10088{
    10089 SCIP_CONSDATA* consdata;
    10090
    10091 assert(scip != NULL);
    10092 assert(cons != NULL);
    10093
    10095
    10096 consdata = SCIPconsGetData(cons);
    10097 assert(consdata != NULL);
    10098
    10099 return consdata->linconstype;
    10100}
    10101
    10102/** gets number of linear variables without artificial terms variables of pseudoboolean constraint */
    10104 SCIP*const scip, /**< SCIP data structure */
    10105 SCIP_CONS*const cons /**< pseudoboolean constraint */
    10106 )
    10107{
    10108 SCIP_CONSDATA* consdata;
    10109
    10110 assert(scip != NULL);
    10111 assert(cons != NULL);
    10112
    10114
    10116
    10117 consdata = SCIPconsGetData(cons);
    10118 assert(consdata != NULL);
    10119
    10120 return consdata->nlinvars;
    10121}
    10122
    10123/** gets linear constraint of pseudoboolean constraint */
    10125 SCIP*const scip, /**< SCIP data structure */
    10126 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    10127 SCIP_VAR**const linvars, /**< array to store and-constraints */
    10128 SCIP_Real*const lincoefs, /**< array to store and-coefficients */
    10129 int*const nlinvars /**< pointer to store the required array size for and-constraints, have to
    10130 * be initialized with size of given array */
    10131 )
    10132{
    10133 SCIP_CONSDATA* consdata;
    10134 SCIP_VAR** vars;
    10135 SCIP_Real* coefs;
    10136 int nvars;
    10137
    10138 assert(scip != NULL);
    10139 assert(cons != NULL);
    10140 assert(nlinvars != NULL);
    10141
    10143
    10144 consdata = SCIPconsGetData(cons);
    10145 assert(consdata != NULL);
    10146
    10148
    10149 if( *nlinvars < consdata->nlinvars )
    10150 {
    10151 *nlinvars = consdata->nlinvars;
    10152 return SCIP_OKAY;
    10153 }
    10154
    10155 /* gets number of variables in linear constraint */
    10156 SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
    10157
    10158 /* allocate temporary memory */
    10159 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    10160 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
    10161
    10162 /* get variables and coefficient of linear constraint */
    10163 SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) );
    10164
    10165 /* calculate all not artificial linear variables */
    10166 SCIP_CALL( getLinVarsAndAndRess(scip, cons, vars, coefs, nvars, linvars, lincoefs, nlinvars, NULL, NULL, NULL, NULL) );
    10167
    10168 /* free temporary memory */
    10169 SCIPfreeBufferArray(scip, &coefs);
    10170 SCIPfreeBufferArray(scip, &vars);
    10171
    10172 return SCIP_OKAY;
    10173}
    10174
    10175
    10176/** gets and-constraints of pseudoboolean constraint */
    10178 SCIP*const scip, /**< SCIP data structure */
    10179 SCIP_CONS*const cons, /**< pseudoboolean constraint */
    10180 SCIP_CONS**const andconss, /**< array to store and-constraints */
    10181 SCIP_Real*const andcoefs, /**< array to store and-coefficients */
    10182 int*const nandconss /**< pointer to store the required array size for and-constraints, have to
    10183 * be initialized with size of given array */
    10184 )
    10185{
    10186 SCIP_CONSDATA* consdata;
    10187 SCIP_Bool isorig;
    10188 int c;
    10189
    10190 assert(scip != NULL);
    10191 assert(cons != NULL);
    10192 assert(nandconss != NULL);
    10193
    10195
    10196 consdata = SCIPconsGetData(cons);
    10197 assert(consdata != NULL);
    10198
    10200
    10201 if( *nandconss < consdata->nconsanddatas )
    10202 {
    10203 *nandconss = consdata->nconsanddatas;
    10204 return SCIP_OKAY;
    10205 }
    10206
    10207 *nandconss = consdata->nconsanddatas;
    10208 assert(consdata->consanddatas != NULL || *nandconss == 0);
    10209
    10210 isorig = SCIPconsIsOriginal(cons);
    10211
    10212 for( c = *nandconss - 1; c >= 0; --c )
    10213 {
    10214 assert(consdata->consanddatas[c] != NULL);
    10215 assert(consdata->consanddatas[c]->istransformed ? (consdata->consanddatas[c]->cons != NULL) : TRUE);
    10216 assert(consdata->consanddatas[c]->isoriginal ? (consdata->consanddatas[c]->origcons != NULL) : TRUE);
    10217 assert(consdata->consanddatas[c]->cons != NULL || consdata->consanddatas[c]->origcons != NULL);
    10218 assert(isorig ? consdata->consanddatas[c]->origcons != NULL : consdata->consanddatas[c]->cons != NULL);
    10219
    10220 andconss[c] = (isorig ? consdata->consanddatas[c]->origcons : consdata->consanddatas[c]->cons);
    10221 assert(andconss[c] != NULL);
    10222
    10223 andcoefs[c] = consdata->andcoefs[c];
    10224 }
    10225
    10226 return SCIP_OKAY;
    10227}
    10228
    10229/** gets number of and constraints of pseudoboolean constraint */
    10231 SCIP*const scip, /**< SCIP data structure */
    10232 SCIP_CONS*const cons /**< constraint data */
    10233 )
    10234{
    10235 SCIP_CONSDATA* consdata;
    10236
    10237 assert(scip != NULL);
    10238 assert(cons != NULL);
    10239
    10241
    10243
    10244 consdata = SCIPconsGetData(cons);
    10245 assert(consdata != NULL);
    10246
    10247 return consdata->nconsanddatas;
    10248}
    10249
    10250/** changes left hand side of pseudoboolean constraint
    10251 *
    10252 * @note you can only change the left hand side if the special type of linear constraint won't changed
    10253 *
    10254 * @todo if changing the left hand side would change the type of the special linear constraint, we need to erase it
    10255 * and create a new linear constraint
    10256 */
    10258 SCIP*const scip, /**< SCIP data structure */
    10259 SCIP_CONS*const cons, /**< constraint data */
    10260 SCIP_Real const lhs /**< new left hand side */
    10261 )
    10262{
    10263 SCIP_CONSDATA* consdata;
    10264
    10265 assert(scip != NULL);
    10266 assert(cons != NULL);
    10267
    10269
    10271
    10272 consdata = SCIPconsGetData(cons);
    10273 assert(consdata != NULL);
    10274
    10275 switch( consdata->linconstype )
    10276 {
    10278 SCIP_CALL( chgLhs(scip, cons, lhs) );
    10279 break;
    10283#ifdef WITHEQKNAPSACK
    10284 case SCIP_LINEARCONSTYPE_EQKNAPSACK:
    10285#endif
    10286 SCIPerrorMessage("changing left hand side only allowed on standard linear constraint \n");
    10287 return SCIP_INVALIDDATA;
    10289 default:
    10290 SCIPerrorMessage("unknown linear constraint type\n");
    10291 return SCIP_INVALIDDATA;
    10292 }
    10293
    10294 return SCIP_OKAY;
    10295}
    10296
    10297/** changes right hand side of pseudoboolean constraint
    10298 *
    10299 * @note you can only change the right hand side if the special type of linear constraint won't changed
    10300 *
    10301 * @todo if changing the right hand side would change the type of the special linear constraint, we need to erase it
    10302 * and create a new linear constraint
    10303 */
    10305 SCIP*const scip, /**< SCIP data structure */
    10306 SCIP_CONS*const cons, /**< constraint data */
    10307 SCIP_Real const rhs /**< new right hand side */
    10308 )
    10309{
    10310 SCIP_CONSDATA* consdata;
    10311
    10313
    10315
    10316 consdata = SCIPconsGetData(cons);
    10317 assert(consdata != NULL);
    10318
    10319 switch( consdata->linconstype )
    10320 {
    10322 SCIP_CALL( chgRhs(scip, cons, rhs) );
    10323 break;
    10327#ifdef WITHEQKNAPSACK
    10328 case SCIP_LINEARCONSTYPE_EQKNAPSACK:
    10329#endif
    10330 SCIPerrorMessage("changing right hand side only allowed on standard linear constraint \n");
    10331 return SCIP_INVALIDDATA;
    10333 default:
    10334 SCIPerrorMessage("unknown linear constraint type\n");
    10335 return SCIP_INVALIDDATA;
    10336 }
    10337
    10338 return SCIP_OKAY;
    10339}
    10340
    10341/** get left hand side of pseudoboolean constraint */
    10343 SCIP*const scip, /**< SCIP data structure */
    10344 SCIP_CONS*const cons /**< pseudoboolean constraint */
    10345 )
    10346{
    10347 SCIP_CONSDATA* consdata;
    10348
    10349 assert(scip != NULL);
    10350
    10352
    10354
    10355 consdata = SCIPconsGetData(cons);
    10356 assert(consdata != NULL);
    10357
    10358 return consdata->lhs;
    10359}
    10360
    10361/** get right hand side of pseudoboolean constraint */
    10363 SCIP*const scip, /**< SCIP data structure */
    10364 SCIP_CONS*const cons /**< pseudoboolean constraint */
    10365 )
    10366{
    10367 SCIP_CONSDATA* consdata;
    10368
    10369 assert(scip != NULL);
    10370
    10372
    10374
    10375 consdata = SCIPconsGetData(cons);
    10376 assert(consdata != NULL);
    10377
    10378 return consdata->rhs;
    10379}
    SCIP_VAR * w
    Definition: circlepacking.c:67
    SCIP_Real * r
    Definition: circlepacking.c:59
    Constraint handler for AND constraints, .
    constraint handler for indicator constraints
    Constraint handler for knapsack constraints of the form , x binary and .
    Constraint handler for linear constraints in their most general form, .
    Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
    constraint handler for nonlinear constraints specified by algebraic expressions
    static SCIP_DECL_CONSENFOPS(consEnfopsPseudoboolean)
    #define CONSHDLR_NEEDSCONS
    static SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphPseudoboolean)
    static SCIP_RETCODE checkAndConss(SCIP *const scip, SCIP_CONSHDLR *const conshdlr, SCIP_SOL *const sol, SCIP_Bool *const violated)
    static SCIP_RETCODE getLinVarsAndAndRess(SCIP *const scip, SCIP_CONS *const cons, SCIP_VAR **const vars, SCIP_Real *const coefs, int const nvars, SCIP_VAR **const linvars, SCIP_Real *const lincoefs, int *const nlinvars, SCIP_VAR **const andress, SCIP_Real *const andcoefs, SCIP_Bool *const andnegs, int *const nandress)
    #define HASHSIZE_PSEUDOBOOLEANNONLINEARTERMS
    static SCIP_RETCODE conshdlrdataCreate(SCIP *const scip, SCIP_CONSHDLRDATA **conshdlrdata)
    static SCIP_RETCODE lockRoundingAndCons(SCIP *const scip, SCIP_CONS *const cons, CONSANDDATA *const consanddata, SCIP_Real const coef, SCIP_Real const lhs, SCIP_Real const rhs)
    #define CONSHDLR_CHECKPRIORITY
    static SCIP_DECL_SORTPTRCOMP(resvarComp)
    static SCIP_RETCODE copyConsPseudoboolean(SCIP *const targetscip, SCIP_CONS **targetcons, SCIP *const sourcescip, SCIP_CONS *const sourcecons, const char *name, SCIP_HASHMAP *const varmap, SCIP_HASHMAP *const consmap, SCIP_Bool const initial, SCIP_Bool const separate, SCIP_Bool const enforce, SCIP_Bool const check, SCIP_Bool const propagate, SCIP_Bool const local, SCIP_Bool const modifiable, SCIP_Bool const dynamic, SCIP_Bool const removable, SCIP_Bool const stickingatnode, SCIP_Bool const global, SCIP_Bool *const valid)
    static SCIP_RETCODE getLinearConsNVars(SCIP *const scip, SCIP_CONS *const cons, SCIP_LINEARCONSTYPE const constype, int *const nvars)
    #define CONSHDLR_DESC
    static SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphPseudoboolean)
    static SCIP_RETCODE checkLocksAndRes(SCIP *const scip, SCIP_VAR *res)
    static SCIP_DECL_CONSPARSE(consParsePseudoboolean)
    static SCIP_DECL_HASHKEYEQ(hashKeyEqAndConsDatas)
    static SCIP_RETCODE propagateCons(SCIP *const scip, SCIP_CONS *const cons, SCIP_Bool *const cutoff, int *const ndelconss)
    static SCIP_DECL_CONSCHECK(consCheckPseudoboolean)
    static SCIP_RETCODE getLinearConsSides(SCIP *const scip, SCIP_CONS *const cons, SCIP_LINEARCONSTYPE const constype, SCIP_Real *const lhs, SCIP_Real *const rhs)
    static SCIP_DECL_CONSTRANS(consTransPseudoboolean)
    #define DEFAULT_DECOMPOSEINDICATORPBCONS
    static SCIP_RETCODE conshdlrdataFree(SCIP *const scip, SCIP_CONSHDLRDATA **conshdlrdata)
    static SCIP_DECL_CONSENFOLP(consEnfolpPseudoboolean)
    static SCIP_RETCODE chgRhsLinearCons(SCIP *const scip, SCIP_CONS *const cons, SCIP_LINEARCONSTYPE const constype, SCIP_Real const rhs)
    #define CONSHDLR_MAXPREROUNDS
    static SCIP_DECL_CONSCOPY(consCopyPseudoboolean)
    static SCIP_DECL_CONSGETNVARS(consGetNVarsPseudoboolean)
    static SCIP_DECL_CONSDELETE(consDeletePseudoboolean)
    static SCIP_DECL_CONSINITPRE(consInitprePseudoboolean)
    static SCIP_RETCODE computeConsAndDataChanges(SCIP *const scip, SCIP_CONSHDLRDATA *const conshdlrdata)
    static SCIP_RETCODE getLinearConsVarsData(SCIP *const scip, SCIP_CONS *const cons, SCIP_LINEARCONSTYPE const constype, SCIP_VAR **const vars, SCIP_Real *const coefs, int *const nvars)
    #define checkConsConsistency(scip, cons)
    static SCIP_RETCODE tryUpgradingLogicor(SCIP *const scip, SCIP_CONS *const cons, SCIP_CONSHDLRDATA *const conshdlrdata, int *const ndelconss, int *const naddconss, int *const nfixedvars, int *const nchgcoefs, int *const nchgsides, SCIP_Bool *const cutoff)
    static SCIP_RETCODE unlockRoundingAndCons(SCIP *const scip, SCIP_CONS *const cons, CONSANDDATA *const consanddata, SCIP_Real const coef, SCIP_Real const lhs, SCIP_Real const rhs)
    static SCIP_RETCODE addCoefTerm(SCIP *const scip, SCIP_CONS *const cons, SCIP_VAR **const vars, int const nvars, SCIP_Real const val)
    static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
    static SCIP_RETCODE consdataCreate(SCIP *const scip, SCIP_CONSHDLR *const conshdlr, SCIP_CONSDATA **consdata, SCIP_CONS *const lincons, SCIP_LINEARCONSTYPE const linconstype, SCIP_CONS **const andconss, SCIP_Real *const andcoefs, SCIP_Bool *const andnegs, int const nandconss, SCIP_VAR *const indvar, SCIP_Real const weight, SCIP_Bool const issoftcons, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool check, SCIP_Bool transforming)
    #define DEFAULT_PROPAGATENONLINEAR
    static SCIP_RETCODE inithashmapandtable(SCIP *const scip, SCIP_CONSHDLRDATA **conshdlrdata)
    static SCIP_DECL_CONSINIT(consInitPseudoboolean)
    static SCIP_DECL_CONSPRINT(consPrintPseudoboolean)
    static SCIP_RETCODE createAndAddAndCons(SCIP *const scip, SCIP_CONSHDLR *const conshdlr, SCIP_VAR **const vars, int const nvars, SCIP_Bool const initial, SCIP_Bool const enforce, SCIP_Bool const check, SCIP_Bool const local, SCIP_Bool const modifiable, SCIP_Bool const dynamic, SCIP_Bool const stickingatnode, SCIP_CONS **const andcons)
    static SCIP_RETCODE consdataPrint(SCIP *const scip, SCIP_CONS *const cons, FILE *const file)
    static SCIP_DECL_CONSENFORELAX(consEnforelaxPseudoboolean)
    #define NONLINCONSUPGD_PRIORITY
    static SCIP_RETCODE addNewLocks(SCIP *const scip, SCIP_CONS *const cons, CONSANDDATA *const consanddata, SCIP_Real const coef, SCIP_Real const lhs, SCIP_Real const rhs)
    static SCIP_DECL_CONSPRESOL(consPresolPseudoboolean)
    static SCIP_RETCODE transformToOrig(SCIP *const scip, CONSANDDATA *consanddata, SCIP_CONSHDLRDATA *conshdlrdata)
    static SCIP_RETCODE addCliques(SCIP *const scip, SCIP_CONS *const cons, SCIP_Bool *const cutoff, int *const naggrvars, int *const nchgbds)
    static SCIP_DECL_HASHKEYVAL(hashKeyValAndConsDatas)
    static SCIP_RETCODE chgLhs(SCIP *const scip, SCIP_CONS *const cons, SCIP_Real lhs)
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyPseudoboolean)
    #define DEFAULT_REMOVABLENONLINEAR
    static SCIP_RETCODE updateConsanddataUses(SCIP *const scip, SCIP_CONS *const cons, SCIP_CONSHDLRDATA *const conshdlrdata, int *const ndelconss)
    static SCIP_DECL_CONSLOCK(consLockPseudoboolean)
    #define DEFAULT_SEPARATENONLINEAR
    static SCIP_RETCODE createAndAddLinearCons(SCIP *const scip, SCIP_CONSHDLR *const conshdlr, SCIP_VAR **const linvars, int const nlinvars, SCIP_Real *const linvals, SCIP_VAR **const andress, int const nandress, SCIP_Real const *const andvals, SCIP_Bool *const andnegs, SCIP_Real *const lhs, SCIP_Real *const rhs, SCIP_Bool const issoftcons, SCIP_Bool const initial, SCIP_Bool const separate, SCIP_Bool const enforce, SCIP_Bool const check, SCIP_Bool const propagate, SCIP_Bool const local, SCIP_Bool const modifiable, SCIP_Bool const dynamic, SCIP_Bool const removable, SCIP_Bool const stickingatnode, SCIP_CONS **const lincons, SCIP_LINEARCONSTYPE *const linconstype)
    static SCIP_DECL_HASHGETKEY(hashGetKeyAndConsDatas)
    static SCIP_RETCODE findAggregation(SCIP *const scip, SCIP_CONS *const cons, SCIP_CONSHDLRDATA *const conshdlrdata, int *const ndelconss, int *const naggrvars, SCIP_Bool *const cutoff)
    #define CONSHDLR_PRESOLTIMING
    static SCIP_RETCODE createAndAddAnds(SCIP *const scip, SCIP_CONSHDLR *const conshdlr, SCIP_VAR **const *const terms, SCIP_Real *const termcoefs, int const nterms, int const *const ntermvars, SCIP_Bool const initial, SCIP_Bool const enforce, SCIP_Bool const check, SCIP_Bool const local, SCIP_Bool const modifiable, SCIP_Bool const dynamic, SCIP_Bool const stickingatnode, SCIP_CONS **const andconss, SCIP_Real *const andvals, SCIP_Bool *const andnegs, int *const nandconss)
    static SCIP_RETCODE tryUpgrading(SCIP *const scip, SCIP_CONS *const cons, SCIP_CONSHDLRDATA *const conshdlrdata, int *const ndelconss, int *const naddconss, int *const nfixedvars, int *const nchgcoefs, int *const nchgsides, SCIP_Bool *const cutoff)
    static SCIP_DECL_CONSGETVARS(consGetVarsPseudoboolean)
    #define MAXNVARS
    #define CONSHDLR_EAGERFREQ
    static SCIP_RETCODE chgLhsLinearCons(SCIP *const scip, SCIP_CONS *const cons, SCIP_LINEARCONSTYPE const constype, SCIP_Real const lhs)
    #define CONSHDLR_ENFOPRIORITY
    #define DEFAULT_DECOMPOSENORMALPBCONS
    static SCIP_RETCODE correctConshdlrdata(SCIP *const scip, SCIP_CONSHDLRDATA *const conshdlrdata, int *const ndelconss)
    static SCIP_RETCODE tryUpgradingSetppc(SCIP *const scip, SCIP_CONS *const cons, SCIP_CONSHDLRDATA *const conshdlrdata, int *const ndelconss, int *const naddconss, int *const nfixedvars, int *const nchgcoefs, int *const nchgsides, SCIP_Bool *const cutoff)
    static SCIP_RETCODE checkSolution(SCIP *const scip, SCIP_VAR **const vars, int const nvars, SCIP_Bool *const values, SCIP_VAR **const linvars, SCIP_Real *const lincoefs, int const nlinvars, SCIP_Real const constant, SCIP_Real const side, CONSANDDATA **const consanddatas, SCIP_Real *const consanddatacoefs, SCIP_Bool *const consanddatanegs, int const nconsanddatas, int const cnt, int *const xortype)
    static SCIP_RETCODE checkOrigPbCons(SCIP *const scip, SCIP_CONS *const cons, SCIP_SOL *const sol, SCIP_Bool *const violated, SCIP_Bool const printreason)
    static SCIP_RETCODE tryUpgradingXor(SCIP *const scip, SCIP_CONS *const cons, SCIP_CONSHDLRDATA *const conshdlrdata, int *const ndelconss, int *const naddconss, int *const nfixedvars, int *const nchgcoefs, int *const nchgsides, SCIP_Bool *const cutoff)
    #define CONSHDLR_NAME
    static SCIP_RETCODE chgRhs(SCIP *const scip, SCIP_CONS *const cons, SCIP_Real rhs)
    static SCIP_RETCODE updateAndConss(SCIP *const scip, SCIP_CONS *const cons)
    static SCIP_RETCODE consdataFree(SCIP *const scip, SCIP_CONSDATA **consdata, SCIP_Bool isorig, SCIP_CONSHDLRDATA *conshdlrdata)
    static SCIP_RETCODE removeOldLocks(SCIP *const scip, SCIP_CONS *const cons, CONSANDDATA *const consanddata, SCIP_Real const coef, SCIP_Real const lhs, SCIP_Real const rhs)
    static SCIP_DECL_CONSFREE(consFreePseudoboolean)
    static SCIP_RETCODE correctLocksAndCaptures(SCIP *const scip, SCIP_CONS *const cons, SCIP_CONSHDLRDATA *const conshdlrdata, SCIP_Real const newlhs, SCIP_Real const newrhs, SCIP_VAR **const andress, SCIP_Real *const andcoefs, SCIP_Bool *const andnegs, int const nandress)
    constraint handler for pseudoboolean constraints
    #define ARTIFICIALVARNAMEPREFIX
    Constraint handler for the set partitioning / packing / covering constraints .
    Constraint handler for XOR constraints, .
    methods for debugging
    #define SCIPdebugGetSolVal(scip, var, val)
    Definition: debug.h:313
    #define SCIPdebugAddSolVal(scip, var, val)
    Definition: debug.h:312
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_INVALID
    Definition: def.h:187
    #define SCIP_Bool
    Definition: def.h:100
    #define MAX3(x, y, z)
    Definition: def.h:237
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_CALL_ABORT(x)
    Definition: def.h:343
    #define SCIPABORT()
    Definition: def.h:336
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_RETCODE SCIPchgLhsPseudoboolean(SCIP *const scip, SCIP_CONS *const cons, SCIP_Real const lhs)
    int SCIPgetNVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcreateConsBasicPseudoboolean(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR **linvars, int nlinvars, SCIP_Real *linvals, SCIP_VAR ***terms, int nterms, int *ntermvars, SCIP_Real *termvals, SCIP_VAR *indvar, SCIP_Real weight, SCIP_Bool issoftcons, SCIP_Real lhs, SCIP_Real rhs)
    #define SCIP_DECL_NONLINCONSUPGD(x)
    int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
    SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcreateConsPseudobooleanWithConss(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONS *lincons, SCIP_LINEARCONSTYPE linconstype, SCIP_CONS **andconss, SCIP_Real *andcoefs, int nandconss, SCIP_VAR *indvar, SCIP_Real weight, SCIP_Bool issoftcons, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
    SCIP_LINEARCONSTYPE SCIPgetLinearConsTypePseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
    SCIP_RETCODE SCIPaddCoefPseudoboolean(SCIP *const scip, SCIP_CONS *const cons, SCIP_VAR *const var, SCIP_Real const val)
    SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
    SCIP_RETCODE SCIPcreateConsAnd(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, 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_and.c:5059
    SCIP_RETCODE SCIPaddCoefKnapsack(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Longint weight)
    SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
    int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_VAR * SCIPgetResultantAnd(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5238
    SCIP_RETCODE SCIPcreateConsIndicator(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *binvar, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    int SCIPgetNAndsPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
    int SCIPgetNLinVarsWithoutAndPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
    int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5199
    SCIP_RETCODE SCIPgetLinDatasWithoutAndPseudoboolean(SCIP *const scip, SCIP_CONS *const cons, SCIP_VAR **const linvars, SCIP_Real *const lincoefs, int *const nlinvars)
    SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
    SCIP_Real SCIPgetLhsPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
    int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_setppc.c:9683
    SCIP_RETCODE SCIPcreateConsSetpack(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:9551
    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:6023
    SCIP_VAR * SCIPgetIndVarPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
    SCIP_RETCODE SCIPcreateConsPseudoboolean(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR **linvars, int nlinvars, SCIP_Real *linvals, SCIP_VAR ***terms, int nterms, int *ntermvars, SCIP_Real *termvals, SCIP_VAR *indvar, SCIP_Real weight, SCIP_Bool issoftcons, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_setppc.c:9701
    SCIP_RETCODE SCIPsortAndCons(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5275
    SCIP_Bool SCIPisAndConsSorted(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5256
    SCIP_Real SCIPgetRhsNonlinear(SCIP_CONS *cons)
    SCIP_RETCODE SCIPaddTermPseudoboolean(SCIP *const scip, SCIP_CONS *const cons, SCIP_VAR **const vars, int const nvars, SCIP_Real const val)
    SCIP_RETCODE SCIPchgRhsPseudoboolean(SCIP *const scip, SCIP_CONS *const cons, SCIP_Real const rhs)
    SCIP_RETCODE SCIPaddCoefSetppc(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_setppc.c:9664
    enum SCIP_SetppcType SCIP_SETPPCTYPE
    Definition: cons_setppc.h:91
    SCIP_RETCODE SCIPcreateConsKnapsack(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Longint *weights, SCIP_Longint capacity, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_Longint * SCIPgetWeightsKnapsack(SCIP *scip, SCIP_CONS *cons)
    SCIP_Longint SCIPgetCapacityKnapsack(SCIP *scip, SCIP_CONS *cons)
    SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_setppc.c:9719
    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:9493
    SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
    SCIP_VAR ** SCIPgetVarsAnd(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5218
    SCIP_VAR ** SCIPgetVarsKnapsack(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcreateConsLogicor(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)
    SCIP_RETCODE SCIPcreateConsSetcover(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:9609
    SCIP_RETCODE SCIPgetAndDatasPseudoboolean(SCIP *const scip, SCIP_CONS *const cons, SCIP_CONS **const andconss, SCIP_Real *const andcoefs, int *const nandconss)
    SCIP_CONS * SCIPgetLinearConsPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
    enum SCIP_LinearConsType SCIP_LINEARCONSTYPE
    SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
    SCIP_Real SCIPgetLhsNonlinear(SCIP_CONS *cons)
    SCIP_Real SCIPgetRhsPseudoboolean(SCIP *const scip, SCIP_CONS *const cons)
    SCIP_RETCODE SCIPaddCoefLogicor(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    @ SCIP_LINEARCONSTYPE_LINEAR
    @ SCIP_LINEARCONSTYPE_INVALIDCONS
    @ SCIP_LINEARCONSTYPE_LOGICOR
    @ SCIP_LINEARCONSTYPE_KNAPSACK
    @ SCIP_LINEARCONSTYPE_SETPPC
    @ SCIP_SETPPCTYPE_PARTITIONING
    Definition: cons_setppc.h:87
    @ SCIP_SETPPCTYPE_COVERING
    Definition: cons_setppc.h:89
    @ SCIP_SETPPCTYPE_PACKING
    Definition: cons_setppc.h:88
    SCIP_RETCODE SCIPincludeConshdlrPseudoboolean(SCIP *scip)
    SCIP_RETCODE SCIPgetConsCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_CONS *sourcecons, SCIP_CONS **targetcons, SCIP_CONSHDLR *sourceconshdlr, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *name, 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_Bool global, SCIP_Bool *valid)
    Definition: scip_copy.c:1581
    SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
    Definition: scip_copy.c:662
    SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
    Definition: scip_copy.c:713
    SCIP_Bool SCIPisTransformed(SCIP *scip)
    Definition: scip_general.c:655
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_prob.c:1907
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3420
    int SCIPgetNFixedVars(SCIP *scip)
    Definition: scip_prob.c:2705
    SCIP_VAR ** SCIPgetFixedVars(SCIP *scip)
    Definition: scip_prob.c:2662
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3284
    SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
    Definition: misc.c:3143
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3466
    SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3482
    void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
    Definition: misc.c:2348
    SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2647
    #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 SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2665
    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
    void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:225
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
    Definition: misc.c:11162
    SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
    Definition: scip_param.c:250
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE 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 SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
    Definition: scip_cons.c:396
    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 SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: scip_cons.c:181
    SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)))
    Definition: scip_cons.c:900
    SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
    Definition: scip_cons.c:578
    SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
    Definition: scip_cons.c:372
    SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
    Definition: scip_cons.c:323
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4320
    SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
    Definition: scip_cons.c:347
    SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
    Definition: scip_cons.c:940
    SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH((*consgetsignedpermsymgraph)))
    Definition: scip_cons.c:924
    SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4340
    SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
    Definition: scip_cons.c:601
    SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
    Definition: scip_cons.c:854
    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
    void SCIPconsAddUpgradeLocks(SCIP_CONS *cons, int nlocks)
    Definition: cons.c:8832
    SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
    Definition: cons.c:8652
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8413
    SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
    Definition: cons.c:8562
    SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
    Definition: scip_cons.c:2536
    SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
    Definition: cons.c:8692
    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_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
    Definition: scip_cons.c:1271
    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_Bool SCIPconsIsLocked(SCIP_CONS *cons)
    Definition: cons.c:8732
    SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1812
    SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
    Definition: cons.c:8642
    SCIP_Bool SCIPconsIsAdded(SCIP_CONS *cons)
    Definition: cons.c:8822
    SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
    Definition: cons.c:8672
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_RETCODE SCIPtransformCons(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **transcons)
    Definition: scip_cons.c:1584
    SCIP_RETCODE SCIPsetConsChecked(SCIP *scip, SCIP_CONS *cons, SCIP_Bool check)
    Definition: scip_cons.c:1346
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8572
    SCIP_RETCODE SCIPcaptureCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1138
    SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1784
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8662
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    #define SCIPensureBlockMemoryArray(scip, ptr, arraysizeptr, minsize)
    Definition: scip_mem.h:107
    #define SCIPallocClearBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:97
    #define SCIPallocClearBufferArray(scip, ptr, num)
    Definition: scip_mem.h:126
    int SCIPcalcMemGrowSize(SCIP *scip, int num)
    Definition: scip_mem.c:139
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPduplicateBufferArray(scip, ptr, source, num)
    Definition: scip_mem.h:132
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
    Definition: scip_mem.h:111
    #define SCIPfreeBufferArrayNull(scip, ptr)
    Definition: scip_mem.h:137
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    #define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:105
    void SCIPupdateSolConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
    Definition: scip_sol.c:451
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
    SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
    Definition: scip_var.c:5210
    SCIP_RETCODE SCIPremoveVarFromGlobalStructures(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:9796
    SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23674
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23510
    SCIP_RETCODE SCIPaddClique(SCIP *scip, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
    Definition: scip_var.c:8882
    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:23418
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4380
    SCIP_RETCODE SCIPgetBinvarRepresentatives(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **repvars, SCIP_Bool *negated)
    Definition: scip_var.c:2283
    SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
    Definition: var.c:23462
    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_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23932
    SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
    Definition: scip_var.c:728
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24174
    int SCIPvarGetIndex(SCIP_VAR *var)
    Definition: var.c:23684
    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
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23694
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    void SCIPfreeParseVarsPolynomialData(SCIP *scip, SCIP_VAR ****monomialvars, SCIP_Real ***monomialexps, SCIP_Real **monomialcoefs, int **monomialnvars, int nmonomials)
    Definition: scip_var.c:1755
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
    Definition: scip_var.c:2378
    SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
    Definition: var.c:18532
    SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
    Definition: scip_var.c:2166
    SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
    Definition: var.c:23475
    SCIP_RETCODE SCIPwriteVarsPolynomial(SCIP *scip, FILE *file, SCIP_VAR ***monomialvars, SCIP_Real **monomialexps, SCIP_Real *monomialcoefs, int *monomialnvars, int nmonomials, SCIP_Bool type)
    Definition: scip_var.c:599
    SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
    Definition: var.c:23910
    SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
    Definition: var.c:23449
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
    Definition: scip_var.c:10318
    SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
    Definition: var.c:23495
    SCIP_RETCODE SCIPparseVarsPolynomial(SCIP *scip, const char *str, SCIP_VAR ****monomialvars, SCIP_Real ***monomialexps, SCIP_Real **monomialcoefs, int **monomialnvars, int *nmonomials, char **endptr, SCIP_Bool *success)
    Definition: scip_var.c:1100
    int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
    Definition: var.c:17319
    SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
    Definition: scip_var.c:361
    SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
    Definition: var.c:16852
    int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4322
    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_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
    void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
    void SCIPsortPtrBool(void **ptrarray, SCIP_Bool *boolarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
    void SCIPsortPtrRealBool(void **ptrarray, SCIP_Real *realarray, SCIP_Bool *boolarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
    void SCIPsortPtrPtrRealBool(void **ptrarray1, void **ptrarray2, SCIP_Real *realarray, SCIP_Bool *boolarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    SCIP_RETCODE SCIPskipSpace(char **s)
    Definition: misc.c:10816
    int SCIPstrncpy(char *t, const char *s, int size)
    Definition: misc.c:10897
    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)
    static volatile int nterms
    Definition: interrupt.c:47
    memory allocation routines
    #define BMScopyMemoryArray(ptr, source, num)
    Definition: memory.h:134
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    public methods for managing constraints
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebugPrintCons(x, y, z)
    Definition: pub_message.h:102
    public data structures and miscellaneous methods
    #define SCIPisFinite(x)
    Definition: pub_misc.h:82
    methods for sorting joint arrays of various types
    public methods for problem variables
    public methods for constraint handler plugins and constraints
    public methods for problem copies
    general public methods
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for solutions
    public methods for SCIP variables
    static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
    Main separation function.
    Definition: sepa_flower.c:1219
    SCIP_CONS * cons
    SCIP_CONS * origcons
    unsigned int isoriginal
    unsigned int istransformed
    SCIP_VAR ** newvars
    SCIP_VAR ** vars
    methods for dealing with symmetry detection graphs
    struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
    Definition: type_cons.h:64
    struct SCIP_ConsData SCIP_CONSDATA
    Definition: type_cons.h:65
    @ SCIP_VERBLEVEL_MINIMAL
    Definition: type_message.h:59
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_FEASIBLE
    Definition: type_result.h:45
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    @ SCIP_INFEASIBLE
    Definition: type_result.h:46
    @ SCIP_READERROR
    Definition: type_retcode.h:45
    @ 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
    @ SCIP_ERROR
    Definition: type_retcode.h:43
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_PROBLEM
    Definition: type_set.h:45
    @ SCIP_STAGE_FREETRANS
    Definition: type_set.h:56
    @ SCIP_STAGE_TRANSFORMING
    Definition: type_set.h:46
    enum SYM_Symtype SYM_SYMTYPE
    Definition: type_symmetry.h:64
    @ SYM_CONSOPTYPE_PB_SOFT
    Definition: type_symmetry.h:90
    @ SYM_CONSOPTYPE_PB_AND
    Definition: type_symmetry.h:88
    @ SYM_CONSOPTYPE_PB_LINEAR
    Definition: type_symmetry.h:89
    @ SYM_SYMTYPE_SIGNPERM
    Definition: type_symmetry.h:62
    @ SYM_SYMTYPE_PERM
    Definition: type_symmetry.h:61
    enum SCIP_ImplintType SCIP_IMPLINTTYPE
    Definition: type_var.h:117
    @ SCIP_IMPLINTTYPE_STRONG
    Definition: type_var.h:106
    @ SCIP_IMPLINTTYPE_WEAK
    Definition: type_var.h:91
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71
    @ SCIP_VARSTATUS_FIXED
    Definition: type_var.h:54
    @ SCIP_VARSTATUS_COLUMN
    Definition: type_var.h:53
    @ SCIP_VARSTATUS_NEGATED
    Definition: type_var.h:57
    @ SCIP_VARSTATUS_LOOSE
    Definition: type_var.h:52
    @ SCIP_LOCKTYPE_CONFLICT
    Definition: type_var.h:142
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141
    enum SCIP_Varstatus SCIP_VARSTATUS
    Definition: type_var.h:59