Scippy

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