SCIP

    Solving Constraint Integer Programs

    cons_logicor.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file cons_logicor.c
    26 * @ingroup DEFPLUGINS_CONS
    27 * @brief Constraint handler for logic or constraints \f$1^T x \ge 1\f$
    28 * (equivalent to set covering, but algorithms are suited for depth first search).
    29 * @author Tobias Achterberg
    30 * @author Michael Winkler
    31 */
    32
    33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    34
    36#include "scip/cons_linear.h"
    37#include "scip/cons_logicor.h"
    38#include "scip/cons_setppc.h"
    39#include "scip/presolve.h"
    40#include "scip/pub_conflict.h"
    41#include "scip/pub_cons.h"
    42#include "scip/pub_event.h"
    43#include "scip/pub_lp.h"
    44#include "scip/pub_message.h"
    45#include "scip/pub_misc.h"
    46#include "scip/pub_misc_sort.h"
    47#include "scip/pub_var.h"
    48#include "scip/scip_conflict.h"
    49#include "scip/scip_cons.h"
    50#include "scip/scip_cut.h"
    51#include "scip/scip_event.h"
    52#include "scip/scip_general.h"
    53#include "scip/scip_lp.h"
    54#include "scip/scip_mem.h"
    55#include "scip/scip_message.h"
    56#include "scip/scip_nlp.h"
    57#include "scip/scip_numerics.h"
    58#include "scip/scip_param.h"
    59#include "scip/scip_prob.h"
    60#include "scip/scip_probing.h"
    61#include "scip/scip_sol.h"
    63#include "scip/scip_tree.h"
    64#include "scip/scip_var.h"
    65#include "scip/symmetry_graph.h"
    67
    68
    69#define CONSHDLR_NAME "logicor"
    70#define CONSHDLR_DESC "logic or constraints"
    71#define CONSHDLR_SEPAPRIORITY +10000 /**< priority of the constraint handler for separation */
    72#define CONSHDLR_ENFOPRIORITY -2000000 /**< priority of the constraint handler for constraint enforcing */
    73#define CONSHDLR_CHECKPRIORITY -2000000 /**< priority of the constraint handler for checking feasibility */
    74#define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
    75#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
    76#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
    77 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    78#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
    79#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
    80#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
    81#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
    82
    83#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_ALWAYS
    84#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
    85
    86#define LINCONSUPGD_PRIORITY +800000 /**< priority of the constraint handler for upgrading of linear constraints */
    87
    88#define EVENTHDLR_NAME "logicor"
    89#define EVENTHDLR_DESC "event handler for logic or constraints"
    90
    91#define CONFLICTHDLR_NAME "logicor"
    92#define CONFLICTHDLR_DESC "conflict handler creating logic or constraints"
    93#define CONFLICTHDLR_PRIORITY LINCONSUPGD_PRIORITY
    94
    95#define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
    96#define DEFAULT_STRENGTHEN TRUE /**< should pairwise constraint comparison try to strengthen constraints by removing superflous non-zeros? */
    97
    98#define HASHSIZE_LOGICORCONS 500 /**< minimal size of hash table in logicor constraint tables */
    99#define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
    100#define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
    101#define DEFAULT_NEGATEDCLIQUE TRUE /**< should negated clique information be used in presolving */
    102#define DEFAULT_COPYTYPEDCONS FALSE /**< should logicor constraints be copied as logicor instead of linear? */
    103#define DEFAULT_IMPLICATIONS TRUE /**< should we try to shrink the variables and derive global boundchanges by
    104 * using cliques and implications */
    105
    106/* @todo make this a parameter setting */
    107#if 1 /* @todo test which AGEINCREASE formula is better! */
    108#define AGEINCREASE(n) (1.0 + 0.2 * (n))
    109#else
    110#define AGEINCREASE(n) (0.1 * (n))
    111#endif
    112
    113
    114/* @todo maybe use event SCIP_EVENTTYPE_VARUNLOCKED to decide for another dual-presolving run on a constraint */
    115
    116/*
    117 * Data structures
    118 */
    119
    120/** constraint handler data */
    121struct SCIP_ConshdlrData
    122{
    123 SCIP_EVENTHDLR* eventhdlr; /**< event handler for events on watched variables */
    124 SCIP_CONSHDLR* conshdlrlinear; /**< pointer to linear constraint handler or NULL if not included */
    125 SCIP_CONSHDLR* conshdlrsetppc; /**< pointer to setppc constraint handler or NULL if not included */
    126 SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
    127 SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in
    128 * advance */
    129 SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
    130 SCIP_Bool usenegatedclique; /**< should negated clique information be used in presolving */
    131 SCIP_Bool useimplications; /**< should we try to shrink the variables and derive global boundchanges
    132 * by using clique and implications */
    133 SCIP_Bool usestrengthening; /**< should pairwise constraint comparison try to strengthen constraints by
    134 * removing superflous non-zeros? */
    135 SCIP_Bool copytypedcons; /**< should logicor constraints be copied as logicor instead of linear? */
    136 int nlastcliquesneg; /**< number of cliques after last negated clique presolving round */
    137 int nlastimplsneg; /**< number of implications after last negated clique presolving round */
    138 int nlastcliquesshorten;/**< number of cliques after last shortening of constraints */
    139 int nlastimplsshorten; /**< number of implications after last shortening of constraints */
    140};
    141
    142/* @todo it might speed up exit-presolve to remember all positions for variables when catching the varfixed event, or we
    143 * change catching and dropping the events like it is done in cons_setppc, which probably makes the code more
    144 * clear
    145 */
    146
    147/** logic or constraint data */
    148struct SCIP_ConsData
    149{
    150 SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
    151 SCIP_NLROW* nlrow; /**< NLP row, if constraint has been added to NLP relaxation */
    152 SCIP_VAR** vars; /**< variables of the constraint */
    153 int varssize; /**< size of vars array */
    154 int nvars; /**< number of variables in the constraint */
    155 int watchedvar1; /**< position of the first watched variable */
    156 int watchedvar2; /**< position of the second watched variable */
    157 int filterpos1; /**< event filter position of first watched variable */
    158 int filterpos2; /**< event filter position of second watched variable */
    159 unsigned int signature; /**< constraint signature which is need for pairwise comparison */
    160 unsigned int presolved:1; /**< flag indicates if we have some fixed, aggregated or multi-aggregated
    161 * variables
    162 */
    163 unsigned int impladded:1; /**< was the 2-variable logic or constraint already added as implication? */
    164 unsigned int sorted:1; /**< are the constraint's variables sorted? */
    165 unsigned int changed:1; /**< was constraint changed since last redundancy round in preprocessing? */
    166 unsigned int merged:1; /**< are the constraint's equal/negated variables already merged? */
    167 unsigned int existmultaggr:1; /**< does this constraint contain aggregations */
    168 unsigned int validsignature:1; /**< is the signature valid */
    169};
    170
    171
    172/*
    173 * Local methods
    174 */
    175
    176/** installs rounding locks for the given variable in the given logic or constraint */
    177static
    179 SCIP* scip, /**< SCIP data structure */
    180 SCIP_CONS* cons, /**< logic or constraint */
    181 SCIP_VAR* var /**< variable of constraint entry */
    182 )
    183{
    184 SCIP_CALL( SCIPlockVarCons(scip, var, cons, TRUE, FALSE) );
    185
    186 return SCIP_OKAY;
    187}
    188
    189/** removes rounding locks for the given variable in the given logic or constraint */
    190static
    192 SCIP* scip, /**< SCIP data structure */
    193 SCIP_CONS* cons, /**< logic or constraint */
    194 SCIP_VAR* var /**< variable of constraint entry */
    195 )
    196{
    197 SCIP_CALL( SCIPunlockVarCons(scip, var, cons, TRUE, FALSE) );
    198
    199 return SCIP_OKAY;
    200}
    201
    202/** creates constraint handler data for logic or constraint handler */
    203static
    205 SCIP* scip, /**< SCIP data structure */
    206 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
    207 SCIP_EVENTHDLR* eventhdlr /**< event handler */
    208 )
    209{
    210 assert(scip != NULL);
    211 assert(conshdlrdata != NULL);
    212 assert(eventhdlr != NULL);
    213
    214 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
    215
    216 (*conshdlrdata)->nlastcliquesneg = 0;
    217 (*conshdlrdata)->nlastimplsneg = 0;
    218 (*conshdlrdata)->nlastcliquesshorten = 0;
    219 (*conshdlrdata)->nlastimplsshorten = 0;
    220
    221 /* set event handler for catching events on watched variables */
    222 (*conshdlrdata)->eventhdlr = eventhdlr;
    223
    224 return SCIP_OKAY;
    225}
    226
    227/** frees constraint handler data for logic or constraint handler */
    228static
    230 SCIP* scip, /**< SCIP data structure */
    231 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
    232 )
    233{
    234 assert(conshdlrdata != NULL);
    235 assert(*conshdlrdata != NULL);
    236
    237 SCIPfreeBlockMemory(scip, conshdlrdata);
    238}
    239
    240/** ensures, that the vars array can store at least num entries */
    241static
    243 SCIP* scip, /**< SCIP data structure */
    244 SCIP_CONSDATA* consdata, /**< logicor constraint data */
    245 int num /**< minimum number of entries to store */
    246 )
    247{
    248 assert(consdata != NULL);
    249 assert(consdata->nvars <= consdata->varssize);
    250
    251 if( num > consdata->varssize )
    252 {
    253 int newsize;
    254
    255 newsize = SCIPcalcMemGrowSize(scip, num);
    256 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
    257 consdata->varssize = newsize;
    258 }
    259 assert(num <= consdata->varssize);
    260
    261 return SCIP_OKAY;
    262}
    263
    264/** creates a logic or constraint data object */
    265static
    267 SCIP* scip, /**< SCIP data structure */
    268 SCIP_CONSDATA** consdata, /**< pointer to store the logic or constraint data */
    269 int nvars, /**< number of variables in the constraint */
    270 SCIP_VAR** vars /**< variables of the constraint */
    271 )
    272{
    273 int v;
    274
    275 assert(consdata != NULL);
    276 assert(nvars == 0 || vars != NULL);
    277
    278 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
    279
    280 (*consdata)->row = NULL;
    281 (*consdata)->nlrow = NULL;
    282 if( nvars > 0 )
    283 {
    284 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
    285 (*consdata)->varssize = nvars;
    286 (*consdata)->nvars = nvars;
    287 }
    288 else
    289 {
    290 (*consdata)->vars = NULL;
    291 (*consdata)->varssize = 0;
    292 (*consdata)->nvars = 0;
    293 }
    294 (*consdata)->watchedvar1 = -1;
    295 (*consdata)->watchedvar2 = -1;
    296 (*consdata)->filterpos1 = -1;
    297 (*consdata)->filterpos2 = -1;
    298 (*consdata)->presolved = FALSE;
    299 (*consdata)->impladded = FALSE;
    300 (*consdata)->changed = TRUE;
    301 (*consdata)->sorted = (nvars <= 1);
    302 (*consdata)->merged = (nvars <= 1);
    303 (*consdata)->existmultaggr = FALSE;
    304 (*consdata)->validsignature = FALSE;
    305
    306 /* get transformed variables, if we are in the transformed problem */
    308 {
    309 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
    310
    311 /* check for multi-aggregations and capture variables */
    312 for( v = 0; v < (*consdata)->nvars; v++ )
    313 {
    314 SCIP_VAR* var = SCIPvarGetProbvar((*consdata)->vars[v]);
    315 assert(var != NULL);
    316 (*consdata)->existmultaggr = (*consdata)->existmultaggr || (SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
    317 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
    318 }
    319 }
    320 else
    321 {
    322 /* capture variables */
    323 for( v = 0; v < (*consdata)->nvars; v++ )
    324 {
    325 assert((*consdata)->vars[v] != NULL);
    326 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
    327 }
    328 }
    329
    330 return SCIP_OKAY;
    331}
    332
    333/** frees a logic or constraint data */
    334static
    336 SCIP* scip, /**< SCIP data structure */
    337 SCIP_CONSDATA** consdata /**< pointer to the logic or constraint */
    338 )
    339{
    340 int v;
    341
    342 assert(consdata != NULL);
    343 assert(*consdata != NULL);
    344
    345 /* release the row */
    346 if( (*consdata)->row != NULL )
    347 {
    348 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
    349 }
    350
    351 /* release the nlrow */
    352 if( (*consdata)->nlrow != NULL )
    353 {
    354 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
    355 }
    356
    357 /* release variables */
    358 for( v = 0; v < (*consdata)->nvars; v++ )
    359 {
    360 assert((*consdata)->vars[v] != NULL);
    361 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
    362 }
    363
    364 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
    365 SCIPfreeBlockMemory(scip, consdata);
    366
    367 return SCIP_OKAY;
    368}
    369
    370/** prints logic or constraint to file stream */
    371static
    373 SCIP* scip, /**< SCIP data structure */
    374 SCIP_CONSDATA* consdata, /**< logic or constraint data */
    375 FILE* file, /**< output file (or NULL for standard output) */
    376 SCIP_Bool endline /**< should an endline be set? */
    377 )
    378{
    379 assert(consdata != NULL);
    380
    381 /* print constraint type */
    382 SCIPinfoMessage(scip, file, "logicor(");
    383
    384 /* print variable list */
    385 SCIP_CALL( SCIPwriteVarsList(scip, file, consdata->vars, consdata->nvars, TRUE, ',') );
    386
    387 /* close bracket */
    388 SCIPinfoMessage(scip, file, ")");
    389
    390 if( endline )
    391 SCIPinfoMessage(scip, file, "\n");
    392
    393 return SCIP_OKAY;
    394}
    395
    396/** stores the given variable numbers as watched variables, and updates the event processing */
    397static
    399 SCIP* scip, /**< SCIP data structure */
    400 SCIP_CONS* cons, /**< logic or constraint */
    401 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    402 int watchedvar1, /**< new first watched variable */
    403 int watchedvar2 /**< new second watched variable */
    404 )
    405{
    406 SCIP_CONSDATA* consdata;
    407
    408 consdata = SCIPconsGetData(cons);
    409 assert(consdata != NULL);
    410 assert(watchedvar1 == -1 || watchedvar1 != watchedvar2);
    411 assert(watchedvar1 != -1 || watchedvar2 == -1);
    412 assert(watchedvar1 == -1 || (0 <= watchedvar1 && watchedvar1 < consdata->nvars));
    413 assert(watchedvar2 == -1 || (0 <= watchedvar2 && watchedvar2 < consdata->nvars));
    414
    415 /* if one watched variable is equal to the old other watched variable, just switch positions */
    416 if( watchedvar1 == consdata->watchedvar2 || watchedvar2 == consdata->watchedvar1 )
    417 {
    418 int tmp;
    419
    420 tmp = consdata->watchedvar1;
    421 consdata->watchedvar1 = consdata->watchedvar2;
    422 consdata->watchedvar2 = tmp;
    423 tmp = consdata->filterpos1;
    424 consdata->filterpos1 = consdata->filterpos2;
    425 consdata->filterpos2 = tmp;
    426 }
    427 assert(watchedvar1 == -1 || watchedvar1 != consdata->watchedvar2);
    428 assert(watchedvar2 == -1 || watchedvar2 != consdata->watchedvar1);
    429
    430 /* drop events on old watched variables */
    431 if( consdata->watchedvar1 != -1 && consdata->watchedvar1 != watchedvar1 )
    432 {
    433 assert(consdata->filterpos1 != -1);
    434 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar1],
    436 consdata->filterpos1) );
    437 }
    438 if( consdata->watchedvar2 != -1 && consdata->watchedvar2 != watchedvar2 )
    439 {
    440 assert(consdata->filterpos2 != -1);
    441 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar2],
    443 consdata->filterpos2) );
    444 }
    445
    446 /* catch events on new watched variables */
    447 if( watchedvar1 != -1 && watchedvar1 != consdata->watchedvar1 )
    448 {
    449 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[watchedvar1],
    451 &consdata->filterpos1) );
    452 }
    453 if( watchedvar2 != -1 && watchedvar2 != consdata->watchedvar2 )
    454 {
    455 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[watchedvar2],
    457 &consdata->filterpos2) );
    458 }
    459
    460 /* set the new watched variables */
    461 consdata->watchedvar1 = watchedvar1;
    462 consdata->watchedvar2 = watchedvar2;
    463
    464 return SCIP_OKAY;
    465}
    466
    467/** adds coefficient in logicor constraint */
    468static
    470 SCIP* scip, /**< SCIP data structure */
    471 SCIP_CONS* cons, /**< logicor constraint */
    472 SCIP_VAR* var /**< variable to add to the constraint */
    473 )
    474{
    475 SCIP_CONSDATA* consdata;
    476 SCIP_Bool transformed;
    477
    478 assert(var != NULL);
    479
    480 consdata = SCIPconsGetData(cons);
    481 assert(consdata != NULL);
    482
    483 /* are we in the transformed problem? */
    484 transformed = SCIPconsIsTransformed(cons);
    485
    486 /* always use transformed variables in transformed constraints */
    487 if( transformed )
    488 {
    489 SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
    490
    491 if( !consdata->existmultaggr && SCIPvarGetStatus(SCIPvarGetProbvar(var)) == SCIP_VARSTATUS_MULTAGGR )
    492 consdata->existmultaggr = TRUE;
    493
    494 consdata->presolved = FALSE;
    495 }
    496 assert(var != NULL);
    497 assert(transformed == SCIPvarIsTransformed(var));
    498
    499 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars + 1) );
    500 consdata->vars[consdata->nvars] = var;
    501 SCIP_CALL( SCIPcaptureVar(scip, consdata->vars[consdata->nvars]) );
    502 consdata->nvars++;
    503
    504 /* we only catch this event in presolving stage */
    506 {
    507 SCIP_CONSHDLRDATA* conshdlrdata;
    508 SCIP_CONSHDLR* conshdlr;
    509
    511 assert(conshdlr != NULL);
    512 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    513 assert(conshdlrdata != NULL);
    514
    515 SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
    516 (SCIP_EVENTDATA*)cons, NULL) );
    517 }
    518
    519 consdata->sorted = (consdata->nvars == 1);
    520 consdata->changed = TRUE;
    521 consdata->validsignature = FALSE;
    522
    523 /* install the rounding locks for the new variable */
    524 SCIP_CALL( lockRounding(scip, cons, var) );
    525
    526 /* add the new coefficient to the LP row */
    527 if( consdata->row != NULL )
    528 {
    529 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, 1.0) );
    530 }
    531
    532 consdata->merged = FALSE;
    533
    534 return SCIP_OKAY;
    535}
    536
    537/** deletes coefficient at given position from logic or constraint data */
    538static
    540 SCIP* scip, /**< SCIP data structure */
    541 SCIP_CONS* cons, /**< logic or constraint */
    542 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    543 int pos /**< position of coefficient to delete */
    544 )
    545{
    546 SCIP_CONSDATA* consdata;
    547
    548 assert(eventhdlr != NULL);
    549
    550 consdata = SCIPconsGetData(cons);
    551 assert(consdata != NULL);
    552 assert(0 <= pos && pos < consdata->nvars);
    553 assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(consdata->vars[pos]));
    554
    555 /* remove the rounding locks of variable */
    556 SCIP_CALL( unlockRounding(scip, cons, consdata->vars[pos]) );
    557
    558 /* we only catch this event in presolving stage, so we need to only drop it there */
    560 {
    561 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos], SCIP_EVENTTYPE_VARFIXED, eventhdlr,
    562 (SCIP_EVENTDATA*)cons, -1) );
    563 }
    564
    565 if( SCIPconsIsTransformed(cons) )
    566 {
    567 /* if the position is watched, stop watching the position */
    568 if( consdata->watchedvar1 == pos )
    569 {
    570 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar2, -1) );
    571 }
    572 if( consdata->watchedvar2 == pos )
    573 {
    574 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar1, -1) );
    575 }
    576 }
    577 assert(pos != consdata->watchedvar1);
    578 assert(pos != consdata->watchedvar2);
    579
    580 /* release variable */
    581 SCIP_CALL( SCIPreleaseVar(scip, &consdata->vars[pos]) );
    582
    583 /* move the last variable to the free slot */
    584 if( pos != consdata->nvars - 1 )
    585 {
    586 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
    587 consdata->sorted = FALSE;
    588 }
    589 consdata->nvars--;
    590
    591 /* if the last variable (that moved) was watched, update the watched position */
    592 if( consdata->watchedvar1 == consdata->nvars )
    593 consdata->watchedvar1 = pos;
    594 if( consdata->watchedvar2 == consdata->nvars )
    595 consdata->watchedvar2 = pos;
    596
    597 consdata->changed = TRUE;
    598 consdata->validsignature = FALSE;
    599
    601
    602 return SCIP_OKAY;
    603}
    604
    605/** in case a part (more than one variable) in the logic or constraint is independent of every else, we can perform dual
    606 * reductions;
    607 * - fix the variable with the smallest object coefficient to one if the constraint is not modifiable and all
    608 * variable are independant
    609 * - fix all independant variables with negative object coefficient to one
    610 * - fix all remaining independant variables to zero
    611 *
    612 * also added the special case were exactly one variable is locked by this constraint and another variable without any
    613 * uplocks has a better objective value than this single variable
    614 * - here we fix the variable to 0.0 (if the objective contribution is non-negative)
    615 *
    616 * Moreover, if there exists a variable that is only locked by a constraint with two variables, one can aggregate variables.
    617 *
    618 * Note: the following dual reduction for logic or constraints is already performed by the presolver "dualfix"
    619 * - if a variable in a set covering constraint is only locked by that constraint and has negative or zero
    620 * objective coefficient than it can be fixed to one
    621 */
    622static
    624 SCIP* scip, /**< SCIP data structure */
    625 SCIP_CONS* cons, /**< setppc constraint */
    626 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    627 int* nfixedvars, /**< pointer to count number of fixings */
    628 int* ndelconss, /**< pointer to count number of deleted constraints */
    629 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
    630 int* naggrvars, /**< pointer to count number of variables aggregated */
    631 SCIP_RESULT* result /**< pointer to store the result SCIP_SUCCESS, if presolving was performed */
    632 )
    633{
    634 SCIP_CONSDATA* consdata;
    635 SCIP_VAR** vars;
    636 SCIP_VAR* var;
    637 SCIP_VAR* activevar;
    638 SCIP_Real bestobjval;
    639 SCIP_Real bestobjvalnouplocks;
    640 SCIP_Real objval;
    641 SCIP_Real fixval;
    642 SCIP_Bool infeasible;
    643 SCIP_Bool fixed;
    644 SCIP_Bool negated;
    645 int nfixables;
    646 int nvars;
    647 int idx;
    648 int indepidx = -1;
    649 int idxnouplocks;
    650 int v;
    651
    652 assert(scip != NULL);
    653 assert(cons != NULL);
    654 assert(eventhdlr != NULL);
    655 assert(nfixedvars != NULL);
    656 assert(ndelconss != NULL);
    657 assert(nchgcoefs != NULL);
    658 assert(result != NULL);
    659
    660 /* constraints for which the check flag is set to FALSE, did not contribute to the lock numbers; therefore, we cannot
    661 * use the locks to decide for a dual reduction using this constraint; for example after a restart the cuts which are
    662 * added to the problems have the check flag set to FALSE
    663 */
    664 if( !SCIPconsIsChecked(cons) )
    665 return SCIP_OKAY;
    666
    667 assert(SCIPconsIsActive(cons));
    668
    669 consdata = SCIPconsGetData(cons);
    670 assert(consdata != NULL);
    671
    672 nvars = consdata->nvars;
    673
    674 /* we don't want to consider small constraints (note that the constraints can be modifiable, so we can't delete this
    675 * constraint)
    676 */
    677 if( nvars < 2 )
    678 return SCIP_OKAY;
    679
    680 vars = consdata->vars;
    681 idx = -1;
    682 idxnouplocks = -1;
    683 bestobjval = SCIP_INVALID;
    684 bestobjvalnouplocks = SCIP_INVALID;
    685
    686 nfixables = 0;
    687
    688 /* check if we can apply the dual reduction; therefore count the number of variables where the logic or has the only
    689 * locks on
    690 */
    691 for( v = nvars - 1; v >= 0; --v )
    692 {
    693 var = vars[v];
    694 assert(var != NULL);
    695
    696 /* variables with varstatus not equal to SCIP_VARSTATUS_FIXED can also have fixed bounds, but were not removed yet */
    697 if( SCIPvarGetUbGlobal(var) < 0.5 )
    698 {
    699#ifndef NDEBUG
    700 SCIP_VAR* bestvar = NULL;
    701#endif
    702 if( idx == consdata->nvars - 1 )
    703 {
    704#ifndef NDEBUG
    705 bestvar = consdata->vars[idx];
    706#endif
    707 idx = v;
    708 }
    709
    710 if( idxnouplocks == consdata->nvars - 1 )
    711 idxnouplocks = v;
    712
    713 if( indepidx == consdata->nvars - 1 )
    714 indepidx = v;
    715
    716 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    717 ++(*nchgcoefs);
    718
    719 assert(bestvar == NULL || bestvar == consdata->vars[v]);
    720
    721 continue;
    722 }
    723 if( SCIPvarGetLbGlobal(var) > 0.5 )
    724 {
    725 /* remove constraint since it is redundant */
    726 SCIP_CALL( SCIPdelCons(scip, cons) );
    727 ++(*ndelconss);
    728
    729 return SCIP_OKAY;
    730 }
    731
    732 /* remember best variable with no uplocks, this variable dominates all other with exactly one downlock */
    735 {
    736 SCIP_CALL( SCIPvarGetAggregatedObj(var, &objval) );
    737
    738 /* check if the current variable has a smaller objective coefficient then the best one */
    739 if( SCIPisLT(scip, objval, bestobjval) )
    740 {
    741 idxnouplocks = v;
    742 bestobjvalnouplocks = objval;
    743 }
    744 }
    745
    746 /* in case an other constraints has also locks on that variable we cannot perform a dual reduction on these
    747 * variables
    748 */
    751 continue;
    752
    753 ++nfixables;
    754 negated = FALSE;
    755
    756 /* get the active variable */
    757 SCIP_CALL( SCIPvarGetProbvarBinary(&var, &negated) );
    758 assert(SCIPvarIsActive(var));
    759
    760 if( negated )
    761 objval = -SCIPvarGetObj(var);
    762 else
    763 objval = SCIPvarGetObj(var);
    764
    765 /* check if the current variable has a smaller objective coefficient */
    766 if( SCIPisLT(scip, objval, bestobjval) )
    767 {
    768 idx = v;
    769 bestobjval = objval;
    770 }
    771
    772 if ( objval >= 0.0 )
    773 indepidx = v;
    774 }
    775
    776 nvars = consdata->nvars;
    777
    778 /* In the special case of two variables, where one variable is independent and is minimized, we can aggregate variables:
    779 * We have var1 + var2 >= 1 and var1 is independent with positive objective. Then var1 + var2 == 1 holds. */
    780 if( nvars == 2 && indepidx >= 0 )
    781 {
    782 SCIP_Bool redundant;
    783 SCIP_Bool aggregated;
    784 int idx2;
    785
    786 idx2 = 1 - indepidx;
    787 assert(0 <= idx2 && idx2 < 2);
    788
    789 SCIP_CALL( SCIPaggregateVars(scip, vars[indepidx], vars[idx2], 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
    790 assert(!infeasible);
    791 assert(redundant);
    792 assert(aggregated);
    793 ++(*naggrvars);
    794
    795 /* remove constraint since it is now redundant */
    796 SCIP_CALL( SCIPdelCons(scip, cons) );
    797 ++(*ndelconss);
    798
    799 *result = SCIP_SUCCESS;
    800
    801 return SCIP_OKAY;
    802 }
    803
    804 /* check if we have a single variable dominated by another */
    805 if( nfixables == 1 && idxnouplocks >= 0 )
    806 {
    807 assert(bestobjvalnouplocks != SCIP_INVALID); /*lint !e777*/
    808
    809 for( v = nvars - 1; v >= 0; --v )
    810 {
    811 var = vars[v];
    812 assert(var != NULL);
    813
    814 /* check if a variable only appearing in this constraint is dominated by another */
    817 {
    818 assert(idxnouplocks != v);
    819
    820 SCIP_CALL( SCIPvarGetAggregatedObj(var, &objval) );
    821
    822 if( SCIPisGE(scip, objval, bestobjvalnouplocks) && !SCIPisNegative(scip, objval) )
    823 {
    824 SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) );
    825 assert(!infeasible);
    826 assert(fixed);
    827
    828 SCIPdebugMsg(scip, " -> dual fixing <%s> == 0.0\n", SCIPvarGetName(var));
    829 ++(*nfixedvars);
    830 }
    831
    832 break;
    833 }
    834 }
    835 }
    836
    837 if( nfixables < 2 )
    838 return SCIP_OKAY;
    839
    840 nvars = consdata->nvars;
    841
    842 assert(idx >= 0 && idx < nvars);
    843 assert(bestobjval < SCIPinfinity(scip));
    844
    845 *result = SCIP_SUCCESS;
    846
    847 /* fix all redundant variables to their best bound */
    848
    849 /* first part of all variables */
    850 for( v = 0; v < nvars; ++v )
    851 {
    852 var = vars[v];
    853 assert(var != NULL);
    854
    855 /* in case an other constraints has also locks on that variable we cannot perform a dual reduction on these
    856 * variables
    857 */
    860 continue;
    861
    862 if( v == idx )
    863 continue;
    864
    865 activevar = var;
    866 negated = FALSE;
    867
    868 /* get the active variable */
    869 SCIP_CALL( SCIPvarGetProbvarBinary(&activevar, &negated) );
    870 assert(SCIPvarIsActive(activevar));
    871
    872 if( negated )
    873 objval = -SCIPvarGetObj(activevar);
    874 else
    875 objval = SCIPvarGetObj(activevar);
    876
    877 if( objval > 0.0 )
    878 fixval = 0.0;
    879 else
    880 fixval = 1.0;
    881
    882 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
    883 assert(!infeasible);
    884 assert(fixed);
    885
    886 SCIPdebugMsg(scip, " -> dual fixing <%s> == %g\n", SCIPvarGetName(var), fixval);
    887 ++(*nfixedvars);
    888 }
    889
    890 /* if all variable have our appreciated number of locks and the constraint is not modifiable, or if the bestobjval is
    891 * less than or equal to zero, we can fix the variable with the smallest objective coefficient to one and the
    892 * constraint gets redundant
    893 */
    894 if( (nfixables == nvars && !SCIPconsIsModifiable(cons)) || bestobjval <= 0.0 )
    895 {
    896 SCIP_CALL( SCIPfixVar(scip, vars[idx], 1.0, &infeasible, &fixed) );
    897 assert(!infeasible);
    898 assert(fixed);
    899
    900 SCIPdebugMsg(scip, " -> fixed <%s> == 1.0\n", SCIPvarGetName(vars[idx]));
    901 ++(*nfixedvars);
    902
    903 /* remove constraint since it is now redundant */
    904 SCIP_CALL( SCIPdelCons(scip, cons) );
    905 ++(*ndelconss);
    906 }
    907
    908 return SCIP_OKAY;
    909}
    910
    911/** deletes all zero-fixed variables, checks for variables fixed to one, replace all variables which are not active or
    912 * not a negation of an active variable by their active or negation of an active counterpart
    913 */
    914static
    916 SCIP* scip, /**< SCIP data structure */
    917 SCIP_CONS* cons, /**< logic or constraint */
    918 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    919 SCIP_Bool* redundant, /**< returns whether a variable fixed to one exists in the constraint */
    920 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
    921 int* naddconss, /**< pointer to count number of added constraints, or NULL indicating we
    922 * can not resolve multi-aggregations
    923 */
    924 int* ndelconss /**< pointer to count number of deleted constraints, or NULL indicating we
    925 * can not resolve multi-aggregations
    926 */
    927 )
    928{
    929 SCIP_CONSDATA* consdata;
    930 SCIP_VAR* var;
    931 int v;
    932 SCIP_VAR** vars;
    933 SCIP_Bool* negarray;
    934 int nvars;
    935
    936 assert(eventhdlr != NULL);
    937 assert(redundant != NULL);
    938
    939 consdata = SCIPconsGetData(cons);
    940 assert(consdata != NULL);
    941 assert(consdata->nvars == 0 || consdata->vars != NULL);
    942
    943 *redundant = FALSE;
    944 v = 0;
    945
    946 /* all multi-aggregations should be resolved */
    947 consdata->existmultaggr = FALSE;
    948 consdata->presolved = TRUE;
    949
    950 /* remove zeros and mark constraint redundant when found one variable fixed to one */
    951 while( v < consdata->nvars )
    952 {
    953 var = consdata->vars[v];
    954 assert(SCIPvarIsBinary(var));
    955
    956 if( SCIPvarGetLbGlobal(var) > 0.5 )
    957 {
    958 assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(var), 1.0));
    959 *redundant = TRUE;
    960
    961 return SCIP_OKAY;
    962 }
    963 else if( SCIPvarGetUbGlobal(var) < 0.5 )
    964 {
    965 assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), 0.0));
    966 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    967 ++(*nchgcoefs);
    968 }
    969 else
    970 ++v;
    971 }
    972
    973 if( consdata->nvars == 0 )
    974 return SCIP_OKAY;
    975
    976 nvars = consdata->nvars;
    977
    978 /* allocate temporary memory */
    979 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    980 SCIP_CALL( SCIPallocBufferArray(scip, &negarray, nvars) );
    981
    982 /* get active or negation of active variables */
    983 SCIP_CALL( SCIPgetBinvarRepresentatives(scip, nvars, consdata->vars, vars, negarray) );
    984
    985 /* renew all variables, important that we do a backwards loop because deletion only affects rear items */
    986 for( v = nvars - 1; v >= 0; --v )
    987 {
    988 var = vars[v];
    989
    990 /* resolve multi-aggregation */
    992 {
    993 SCIP_VAR** consvars;
    994 SCIP_Real* consvals;
    995 SCIP_Real constant = 0.0;
    996 SCIP_Bool easycase;
    997 int nconsvars;
    998 int requiredsize;
    999 int size = 1;
    1000 int v2;
    1001
    1002 nconsvars = 1;
    1003 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 1) );
    1004 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 1) );
    1005 consvars[0] = var;
    1006 consvals[0] = 1.0;
    1007
    1008 /* get active variables for new constraint */
    1009 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize) );
    1010 /* if space was not enough we need to resize the buffers */
    1011 if( requiredsize > size )
    1012 {
    1013 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
    1014 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
    1015 size = requiredsize;
    1016
    1017 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize) );
    1018 assert(requiredsize <= size);
    1019 }
    1020 assert(requiredsize == nconsvars);
    1021
    1022 easycase = FALSE;
    1023
    1024 if( SCIPisZero(scip, constant) )
    1025 {
    1026 /* add active representation */
    1027 for( v2 = nconsvars - 1; v2 >= 0; --v2 )
    1028 {
    1029 if( !SCIPvarIsBinary(consvars[v2]) )
    1030 break;
    1031
    1032 if( !SCIPisEQ(scip, consvals[v2], 1.0) )
    1033 break;
    1034 }
    1035
    1036 if( v2 < 0 )
    1037 easycase = TRUE;
    1038 }
    1039
    1040 /* we can easily add the coefficients and still have a logicor constraint */
    1041 if( easycase )
    1042 {
    1043 /* delete old (multi-aggregated) variable */
    1044 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    1045 ++(*nchgcoefs);
    1046
    1047 /* add active representation */
    1048 for( v2 = nconsvars - 1; v2 >= 0; --v2 )
    1049 {
    1050 assert(SCIPvarIsBinary(consvars[v2]));
    1051 assert(SCIPvarIsActive(consvars[v2]) || (SCIPvarGetStatus(consvars[v2]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(consvars[v2]))));
    1052
    1053 SCIP_CALL( addCoef(scip, cons, consvars[v2]) );
    1054 ++(*nchgcoefs);
    1055 }
    1056 }
    1057 /* we need to degrade this logicor constraint to a linear constraint */
    1058 else if( (ndelconss != NULL && naddconss != NULL) || SCIPconsIsAdded(cons) )
    1059 {
    1060 char name[SCIP_MAXSTRLEN];
    1061 SCIP_CONS* newcons;
    1062 SCIP_Real lhs;
    1063 SCIP_Real rhs;
    1064 int k;
    1065
    1066 /* it might happen that there is more than one multi-aggregated variable, so we need to get the whole probvar sum over all variables */
    1067
    1068 size = MAX(nconsvars, 1) + nvars - 1;
    1069
    1070 /* memory needed is at least old number of variables - 1 + number of variables in first multi-aggregation */
    1071 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, size) );
    1072 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, size) );
    1073
    1074 nconsvars = nvars;
    1075
    1076 /* add constraint variables to new linear variables */
    1077 for( k = nvars - 1; k >= 0; --k )
    1078 {
    1079 consvars[k] = vars[k];
    1080 consvals[k] = 1.0;
    1081 }
    1082
    1083 constant = 0.0;
    1084
    1085 /* get active variables for new constraint */
    1086 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize) );
    1087
    1088 /* if space was not enough (we found another multi-aggregation), we need to resize the buffers */
    1089 if( requiredsize > size )
    1090 {
    1091 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
    1092 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
    1093 size = requiredsize;
    1094
    1095 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize) );
    1096 assert(requiredsize <= size);
    1097 }
    1098 assert(requiredsize == nconsvars);
    1099
    1100 lhs = 1.0 - constant;
    1101 rhs = SCIPinfinity(scip);
    1102
    1103 /* create linear constraint */
    1104 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s", SCIPconsGetName(cons));
    1105 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, nconsvars, consvars, consvals, lhs, rhs,
    1106 SCIPconsIsInitial(cons),
    1110
    1111 /* add the downgraded constraint to the problem */
    1112 SCIPdebugMsg(scip, "adding linear constraint: ");
    1113 SCIPdebugPrintCons(scip, newcons, NULL);
    1114 SCIP_CALL( SCIPaddCons(scip, newcons) );
    1115 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    1116
    1117 /* free constraint arrays */
    1118 SCIPfreeBufferArray(scip, &consvals);
    1119 SCIPfreeBufferArray(scip, &consvars);
    1120
    1121 /* delete old constraint */
    1122 SCIP_CALL( SCIPdelCons(scip, cons) );
    1123 if( ndelconss != NULL && naddconss != NULL )
    1124 {
    1125 assert( naddconss != NULL ); /* for lint */
    1126 ++(*ndelconss);
    1127 ++(*naddconss);
    1128 }
    1129
    1130 goto TERMINATE;
    1131 }
    1132 /* we need to degrade this logicor constraint to a linear constraint */
    1133 else
    1134 {
    1135 if( var != consdata->vars[v] )
    1136 {
    1137 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    1138 SCIP_CALL( addCoef(scip, cons, var) );
    1139 }
    1140
    1141 SCIPwarningMessage(scip, "logicor constraint <%s> has a multi-aggregated variable, which was not resolved and therefore could lead to aborts\n", SCIPconsGetName(cons));
    1142 }
    1143
    1144 SCIPfreeBufferArray(scip, &consvals);
    1145 SCIPfreeBufferArray(scip, &consvars);
    1146 }
    1147 else if( var != consdata->vars[v] )
    1148 {
    1149 assert(SCIPvarIsBinary(var));
    1150
    1151 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    1152
    1153 /* the binvar representative might be fixed:
    1154 * - if fixed to 1, the constraint is redundant
    1155 * - if fixed to 0, the representative does not need to be added to the constraint
    1156 * - if not fixed, we add the representative to the constraint
    1157 */
    1158 if( SCIPvarGetLbGlobal(var) > 0.5 )
    1159 {
    1160 assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(var), 1.0));
    1161 *redundant = TRUE;
    1162
    1163 goto TERMINATE;
    1164 }
    1165 else if( SCIPvarGetUbGlobal(var) < 0.5 )
    1166 {
    1167 assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), 0.0));
    1168 ++(*nchgcoefs);
    1169 }
    1170 else
    1171 {
    1172 SCIP_CALL( addCoef(scip, cons, var) );
    1173 }
    1174 }
    1175 }
    1176
    1177 SCIPdebugMsg(scip, "after fixings: ");
    1178 SCIPdebug( SCIP_CALL( consdataPrint(scip, consdata, NULL, TRUE) ) );
    1179
    1180 TERMINATE:
    1181 /* free temporary memory */
    1182 SCIPfreeBufferArray(scip, &negarray);
    1183 SCIPfreeBufferArray(scip, &vars);
    1184
    1185 consdata->presolved = TRUE;
    1186
    1187 return SCIP_OKAY;
    1188}
    1189
    1190/** analyzes conflicting assignment on given constraint, and adds conflict constraint to problem */
    1191static
    1193 SCIP* scip, /**< SCIP data structure */
    1194 SCIP_CONS* cons /**< logic or constraint that detected the conflict */
    1195 )
    1196{
    1197 SCIP_CONSDATA* consdata;
    1198 int v;
    1199
    1200 /* conflict analysis can only be applied in solving stage and if it is applicable */
    1202 return SCIP_OKAY;
    1203
    1204 consdata = SCIPconsGetData(cons);
    1205 assert(consdata != NULL);
    1206
    1207 /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
    1209
    1210 for( v = 0; v < consdata->nvars; ++v )
    1211 {
    1212 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
    1213 }
    1214
    1215 /* analyze the conflict */
    1217
    1218 return SCIP_OKAY;
    1219}
    1220
    1221/** disables or deletes the given constraint, depending on the current depth */
    1222static
    1224 SCIP* scip, /**< SCIP data structure */
    1225 SCIP_CONS* cons /**< bound disjunction constraint to be disabled */
    1226 )
    1227{
    1228 assert(SCIPconsGetValidDepth(cons) <= SCIPgetDepth(scip));
    1229
    1230 /* in case the logic or constraint is satisfied in the depth where it is also valid, we can delete it */
    1232 {
    1233 SCIP_CALL( SCIPdelCons(scip, cons) );
    1234 }
    1235 else
    1236 {
    1237 SCIPdebugMsg(scip, "disabling constraint cons <%s> at depth %d\n", SCIPconsGetName(cons), SCIPgetDepth(scip));
    1238 SCIP_CALL( SCIPdisableCons(scip, cons) );
    1239 }
    1240
    1241 return SCIP_OKAY;
    1242}
    1243
    1244/** find pairs of negated variables in constraint: constraint is redundant */
    1245/** find sets of equal variables in constraint: multiple entries of variable can be replaced by single entry */
    1246static
    1248 SCIP* scip, /**< SCIP data structure */
    1249 SCIP_CONS* cons, /**< logic or constraint */
    1250 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    1251 unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
    1252 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
    1253 SCIP_Bool* redundant, /**< returns whether a variable fixed to one exists in the constraint */
    1254 int* nchgcoefs /**< pointer to count number of changed/deleted coefficients */
    1255 )
    1256{
    1257 SCIP_CONSDATA* consdata;
    1258 SCIP_VAR** vars;
    1259 int nvars;
    1260 SCIP_Bool* negarray;
    1261 SCIP_VAR* var;
    1262 int v;
    1263 int pos;
    1264#ifndef NDEBUG
    1265 int nbinvars;
    1266 int nintvars;
    1267 int nimplvars;
    1268#endif
    1269
    1270 assert(scip != NULL);
    1271 assert(cons != NULL);
    1272 assert(eventhdlr != NULL);
    1273 assert(*entries != NULL);
    1274 assert(nentries != NULL);
    1275 assert(redundant != NULL);
    1276 assert(nchgcoefs != NULL);
    1277
    1278 consdata = SCIPconsGetData(cons);
    1279 assert(consdata != NULL);
    1280
    1281 nvars = consdata->nvars;
    1282
    1283 *redundant = FALSE;
    1284
    1285 if( consdata->merged )
    1286 return SCIP_OKAY;
    1287
    1288 if( consdata->nvars <= 1 )
    1289 {
    1290 consdata->merged = TRUE;
    1291 return SCIP_OKAY;
    1292 }
    1293
    1294 assert(consdata->vars != NULL && nvars > 0);
    1295
    1296#ifndef NDEBUG
    1297 nbinvars = SCIPgetNBinVars(scip);
    1298 nintvars = SCIPgetNIntVars(scip);
    1299 nimplvars = SCIPgetNImplVars(scip);
    1300 assert(*nentries >= nbinvars + nintvars + nimplvars);
    1301
    1302 /* all variables should be active or negative active variables, otherwise something went wrong with applyFixings()
    1303 * called before mergeMultiples()
    1304 */
    1305 assert(consdata->presolved);
    1306#endif
    1307
    1308 /* allocate temporary memory */
    1309 SCIP_CALL( SCIPallocBufferArray(scip, &negarray, nvars) );
    1310
    1311 vars = consdata->vars;
    1312
    1313 /* initialize entries array */
    1314 for( v = nvars - 1; v >= 0; --v )
    1315 {
    1316 /* all variables should be active or negative active variables, otherwise something went wrong with applyFixings()
    1317 * called before mergeMultiples()
    1318 */
    1319 assert(SCIPvarIsActive(vars[v]) ||
    1321 negarray[v] = SCIPvarIsNegated(vars[v]);
    1322 var = negarray[v] ? SCIPvarGetNegationVar(vars[v]) : vars[v];
    1323 assert(SCIPvarIsActive(var));
    1324
    1325 pos = SCIPvarGetProbindex(var);
    1326
    1327 /* check variable type, either pure binary or an integer/implicit integer variable with 0/1 bounds */
    1328 assert((pos < nbinvars && SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(var))
    1329 || (SCIPvarIsBinary(var) &&
    1330 ((pos >= nbinvars && pos < nbinvars + nintvars && SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER
    1331 && !SCIPvarIsImpliedIntegral(var)) ||
    1332 (pos >= nbinvars + nintvars && pos < nbinvars + nintvars + nimplvars &&
    1333 SCIPvarIsImpliedIntegral(var)))));
    1334
    1335 /* var is not active yet */
    1336 (*entries)[pos] = 0;
    1337 }
    1338
    1339 /* check all vars for multiple entries, do necessary backwards loop because deletion only affect rear items */
    1340 for( v = nvars - 1; v >= 0; --v )
    1341 {
    1342 var = negarray[v] ? SCIPvarGetNegationVar(vars[v]) : vars[v];
    1343 assert(SCIPvarIsActive(var));
    1344
    1345 pos = SCIPvarGetProbindex(var);
    1346
    1347 /* if var occurs first time in constraint init entries array */
    1348 if( (*entries)[pos] == 0 )
    1349 (*entries)[pos] = negarray[v] ? 2 : 1;
    1350 /* if var occurs second time in constraint, first time it was not negated */
    1351 else if( (*entries)[pos] == 1 )
    1352 {
    1353 if( negarray[v] )
    1354 {
    1355 SCIPdebugMsg(scip, "logicor constraint <%s> redundant: variable <%s> and its negation are present\n",
    1356 SCIPconsGetName(cons), SCIPvarGetName(var));
    1357
    1358 *redundant = TRUE;
    1359 goto TERMINATE;
    1360 }
    1361 else
    1362 {
    1363 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    1364 ++(*nchgcoefs);
    1365 }
    1366 }
    1367 /* if var occurs second time in constraint, first time it was negated */
    1368 else
    1369 {
    1370 if( !negarray[v] )
    1371 {
    1372 SCIPdebugMsg(scip, "logicor constraint <%s> redundant: variable <%s> and its negation are present\n",
    1373 SCIPconsGetName(cons), SCIPvarGetName(var));
    1374
    1375 *redundant = TRUE;
    1376 goto TERMINATE;
    1377 }
    1378 else
    1379 {
    1380 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    1381 ++(*nchgcoefs);
    1382 }
    1383 }
    1384 }
    1385
    1386 TERMINATE:
    1387 /* free temporary memory */
    1388 SCIPfreeBufferArray(scip, &negarray);
    1389
    1390 consdata->merged = TRUE;
    1391
    1392 return SCIP_OKAY;
    1393}
    1394
    1395/** checks constraint for violation only looking at the watched variables, applies fixings if possible */
    1396static
    1398 SCIP* scip, /**< SCIP data structure */
    1399 SCIP_CONS* cons, /**< logic or constraint to be processed */
    1400 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    1401 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    1402 SCIP_Bool* reduceddom, /**< pointer to store TRUE, if a domain reduction was found */
    1403 SCIP_Bool* addcut, /**< pointer to store whether this constraint must be added as a cut */
    1404 SCIP_Bool* mustcheck /**< pointer to store whether this constraint must be checked for feasibility */
    1405 )
    1406{
    1407 SCIP_CONSDATA* consdata;
    1408 SCIP_VAR** vars;
    1409 SCIP_Longint nbranchings1;
    1410 SCIP_Longint nbranchings2;
    1411 int nvars;
    1412 int watchedvar1;
    1413 int watchedvar2;
    1414
    1415 assert(cons != NULL);
    1416 assert(SCIPconsGetHdlr(cons) != NULL);
    1417 assert(cutoff != NULL);
    1418 assert(reduceddom != NULL);
    1419 assert(addcut != NULL);
    1420 assert(mustcheck != NULL);
    1421
    1423
    1424 consdata = SCIPconsGetData(cons);
    1425 assert(consdata != NULL);
    1426 assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
    1427
    1428 *addcut = FALSE;
    1429 *mustcheck = FALSE;
    1430
    1431 SCIPdebugMsg(scip, "processing watched variables of constraint <%s>\n", SCIPconsGetName(cons));
    1432
    1433 vars = consdata->vars;
    1434 nvars = consdata->nvars;
    1435 assert(nvars == 0 || vars != NULL);
    1436
    1437 /* check watched variables if they are fixed to one */
    1438 if( consdata->watchedvar1 >= 0 && SCIPvarGetLbLocal(vars[consdata->watchedvar1]) > 0.5 )
    1439 {
    1440 /* the variable is fixed to one, making the constraint redundant -> disable the constraint */
    1441 SCIPdebugMsg(scip, " -> disabling constraint <%s> (watchedvar1 fixed to 1.0)\n", SCIPconsGetName(cons));
    1442 SCIP_CALL( disableCons(scip, cons) );
    1443 return SCIP_OKAY;
    1444 }
    1445 if( consdata->watchedvar2 >= 0 && SCIPvarGetLbLocal(vars[consdata->watchedvar2]) > 0.5 )
    1446 {
    1447 /* the variable is fixed to one, making the constraint redundant -> disable the constraint */
    1448 SCIPdebugMsg(scip, " -> disabling constraint <%s> (watchedvar2 fixed to 1.0)\n", SCIPconsGetName(cons));
    1449 SCIP_CALL( disableCons(scip, cons) );
    1450 return SCIP_OKAY;
    1451 }
    1452
    1453 /* check if watched variables are still unfixed */
    1454 watchedvar1 = -1;
    1455 watchedvar2 = -1;
    1456 nbranchings1 = SCIP_LONGINT_MAX;
    1457 nbranchings2 = SCIP_LONGINT_MAX;
    1458 if( consdata->watchedvar1 >= 0 && SCIPvarGetUbLocal(vars[consdata->watchedvar1]) > 0.5 )
    1459 {
    1460 watchedvar1 = consdata->watchedvar1;
    1461 nbranchings1 = -1; /* prefer keeping the watched variable */
    1462 }
    1463 if( consdata->watchedvar2 >= 0 && SCIPvarGetUbLocal(vars[consdata->watchedvar2]) > 0.5 )
    1464 {
    1465 if( watchedvar1 == -1 )
    1466 {
    1467 watchedvar1 = consdata->watchedvar2;
    1468 nbranchings1 = -1; /* prefer keeping the watched variable */
    1469 }
    1470 else
    1471 {
    1472 watchedvar2 = consdata->watchedvar2;
    1473 nbranchings2 = -1; /* prefer keeping the watched variable */
    1474 }
    1475 }
    1476 assert(watchedvar1 >= 0 || watchedvar2 == -1);
    1477 assert(nbranchings1 <= nbranchings2);
    1478
    1479 /* search for new watched variables */
    1480 if( watchedvar2 == -1 )
    1481 {
    1482 int v;
    1483
    1484 for( v = 0; v < nvars; ++v )
    1485 {
    1486 SCIP_Longint nbranchings;
    1487
    1488 /* don't process the watched variables again */
    1489 if( v == consdata->watchedvar1 || v == consdata->watchedvar2 )
    1490 continue;
    1491
    1492 /* check, if the variable is fixed */
    1493 if( SCIPvarGetUbLocal(vars[v]) < 0.5 )
    1494 continue;
    1495
    1496 /* check, if the literal is satisfied */
    1497 if( SCIPvarGetLbLocal(vars[v]) > 0.5 )
    1498 {
    1499 assert(v != consdata->watchedvar1);
    1500 assert(v != consdata->watchedvar2);
    1501
    1502 /* the variable is fixed to one, making the constraint redundant;
    1503 * make sure, the feasible variable is watched and disable the constraint
    1504 */
    1505 SCIPdebugMsg(scip, " -> disabling constraint <%s> (variable <%s> fixed to 1.0)\n",
    1506 SCIPconsGetName(cons), SCIPvarGetName(vars[v]));
    1507 if( consdata->watchedvar1 != -1 )
    1508 {
    1509 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar1, v) );
    1510 }
    1511 else
    1512 {
    1513 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, v, consdata->watchedvar2) );
    1514 }
    1515 SCIP_CALL( disableCons(scip, cons) );
    1516 return SCIP_OKAY;
    1517 }
    1518
    1519 /* the variable is unfixed and can be used as watched variable */
    1521 assert(nbranchings >= 0);
    1522 if( nbranchings < nbranchings2 )
    1523 {
    1524 if( nbranchings < nbranchings1 )
    1525 {
    1526 watchedvar2 = watchedvar1;
    1527 nbranchings2 = nbranchings1;
    1528 watchedvar1 = v;
    1529 nbranchings1 = nbranchings;
    1530 }
    1531 else
    1532 {
    1533 watchedvar2 = v;
    1534 nbranchings2 = nbranchings;
    1535 }
    1536 }
    1537 }
    1538 }
    1539 assert(nbranchings1 <= nbranchings2);
    1540 assert(watchedvar1 >= 0 || watchedvar2 == -1);
    1541
    1542 if( watchedvar1 == -1 )
    1543 {
    1544 /* there is no unfixed variable left -> the constraint is infeasible
    1545 * - a modifiable constraint must be added as a cut and further pricing must be performed in the LP solving loop
    1546 * - an unmodifiable constraint is infeasible and the node can be cut off
    1547 */
    1548 assert(watchedvar2 == -1);
    1549
    1550 SCIPdebugMsg(scip, " -> constraint <%s> is infeasible\n", SCIPconsGetName(cons));
    1551
    1553 if( SCIPconsIsModifiable(cons) )
    1554 *addcut = TRUE;
    1555 else
    1556 {
    1557 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
    1558 SCIP_CALL( analyzeConflict(scip, cons) );
    1559
    1560 /* mark the node to be cut off */
    1561 *cutoff = TRUE;
    1562 }
    1563 }
    1564 else if( watchedvar2 == -1 )
    1565 {
    1566 /* there is only one unfixed variable:
    1567 * - a modifiable constraint must be checked manually
    1568 * - an unmodifiable constraint is feasible and can be disabled after the remaining variable is fixed to one
    1569 */
    1570 assert(0 <= watchedvar1 && watchedvar1 < nvars);
    1571 assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(vars[watchedvar1]), 0.0));
    1572 assert(SCIPisFeasEQ(scip, SCIPvarGetUbLocal(vars[watchedvar1]), 1.0));
    1573 if( SCIPconsIsModifiable(cons) )
    1574 *mustcheck = TRUE;
    1575 else
    1576 {
    1577 SCIP_Bool infbdchg;
    1578
    1579 /* fixed remaining variable to one and disable constraint; make sure, the fixed-to-one variable is watched */
    1580 SCIPdebugMsg(scip, " -> single-literal constraint <%s> (fix <%s> to 1.0) at depth %d\n",
    1581 SCIPconsGetName(cons), SCIPvarGetName(vars[watchedvar1]), SCIPgetDepth(scip));
    1582 SCIP_CALL( SCIPinferBinvarCons(scip, vars[watchedvar1], TRUE, cons, 0, &infbdchg, NULL) );
    1583 assert(!infbdchg);
    1585 if( watchedvar1 != consdata->watchedvar1 ) /* keep one of the watched variables */
    1586 {
    1587 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, watchedvar1, consdata->watchedvar1) );
    1588 }
    1589 SCIP_CALL( disableCons(scip, cons) );
    1590 *reduceddom = TRUE;
    1591 }
    1592 }
    1593 else
    1594 {
    1595 SCIPdebugMsg(scip, " -> new watched variables <%s> and <%s> of constraint <%s> are still unfixed\n",
    1596 SCIPvarGetName(vars[watchedvar1]), SCIPvarGetName(vars[watchedvar2]), SCIPconsGetName(cons));
    1597
    1598 /* switch to the new watched variables */
    1599 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, watchedvar1, watchedvar2) );
    1600
    1601 /* there are at least two unfixed variables -> the constraint must be checked manually */
    1602 *mustcheck = TRUE;
    1603
    1604 /* disable propagation of constraint until a watched variable gets fixed */
    1606
    1607 /* increase aging counter */
    1608 SCIP_CALL( SCIPaddConsAge(scip, cons, AGEINCREASE(consdata->nvars)) );
    1609 }
    1610
    1611 return SCIP_OKAY;
    1612}
    1613
    1614/** checks constraint for violation, returns TRUE iff constraint is feasible */
    1615static
    1617 SCIP* scip, /**< SCIP data structure */
    1618 SCIP_CONS* cons, /**< logic or constraint to be checked */
    1619 SCIP_SOL* sol /**< primal CIP solution */
    1620 )
    1621{
    1622 SCIP_CONSDATA* consdata;
    1623 SCIP_VAR** vars;
    1624 SCIP_Real solval;
    1625 SCIP_Real sum;
    1626 int nvars;
    1627 int v;
    1628
    1629 consdata = SCIPconsGetData(cons);
    1630 assert(consdata != NULL);
    1631
    1632 vars = consdata->vars;
    1633 nvars = consdata->nvars;
    1634
    1635 /* calculate the constraint's activity */
    1636 sum = 0.0;
    1637 for( v = 0; v < nvars && sum < 1.0; ++v )
    1638 {
    1639 assert(SCIPvarIsBinary(vars[v]));
    1640
    1641 solval = SCIPgetSolVal(scip, sol, vars[v]);
    1642 assert(SCIPisFeasGE(scip, solval, 0.0) && SCIPisFeasLE(scip, solval, 1.0));
    1643
    1644 sum += solval;
    1645 }
    1646
    1647 /* calculate constraint violation and update it in solution */
    1648 if( sol != NULL ){
    1649 SCIP_Real absviol = 1.0 - sum;
    1650 SCIP_Real relviol = SCIPrelDiff(1.0, sum);
    1651 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
    1652 }
    1653
    1654 return SCIPisFeasLT(scip, sum, 1.0);
    1655}
    1656
    1657/** creates an LP row in a logic or constraint data object */
    1658static
    1660 SCIP* scip, /**< SCIP data structure */
    1661 SCIP_CONS* cons /**< logic or constraint */
    1662 )
    1663{
    1664 SCIP_CONSDATA* consdata;
    1665
    1666 consdata = SCIPconsGetData(cons);
    1667 assert(consdata != NULL);
    1668 assert(consdata->row == NULL);
    1669
    1670 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), 1.0, SCIPinfinity(scip),
    1672
    1673 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->row, consdata->nvars, consdata->vars, 1.0) );
    1674
    1675 return SCIP_OKAY;
    1676}
    1677
    1678/** adds logicor constraint as row to the NLP, if not added yet */
    1679static
    1681 SCIP* scip, /**< SCIP data structure */
    1682 SCIP_CONS* cons /**< logicor constraint */
    1683 )
    1684{
    1685 SCIP_CONSDATA* consdata;
    1686
    1687 assert(SCIPisNLPConstructed(scip));
    1688
    1689 /* skip deactivated, redundant, or local constraints (the NLP does not allow for local rows at the moment) */
    1690 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
    1691 return SCIP_OKAY;
    1692
    1693 consdata = SCIPconsGetData(cons);
    1694 assert(consdata != NULL);
    1695
    1696 if( consdata->nlrow == NULL )
    1697 {
    1698 SCIP_Real* coefs;
    1699 int i;
    1700
    1701 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, consdata->nvars) );
    1702 for( i = 0; i < consdata->nvars; ++i )
    1703 coefs[i] = 1.0;
    1704
    1705 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
    1706 0.0, consdata->nvars, consdata->vars, coefs, NULL, 1.0, SCIPinfinity(scip), SCIP_EXPRCURV_LINEAR) );
    1707 assert(consdata->nlrow != NULL);
    1708
    1709 SCIPfreeBufferArray(scip, &coefs);
    1710 }
    1711
    1712 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
    1713 {
    1714 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
    1715 }
    1716
    1717 return SCIP_OKAY;
    1718}
    1719
    1720/** adds logic or constraint as cut to the LP */
    1721static
    1723 SCIP* scip, /**< SCIP data structure */
    1724 SCIP_CONS* cons, /**< logic or constraint */
    1725 SCIP_Bool* cutoff /**< whether a cutoff has been detected */
    1726 )
    1727{
    1728 SCIP_CONSDATA* consdata;
    1729
    1730 assert( cutoff != NULL );
    1731 *cutoff = FALSE;
    1732
    1733 consdata = SCIPconsGetData(cons);
    1734 assert(consdata != NULL);
    1735
    1736 if( consdata->row == NULL )
    1737 {
    1738 /* convert logic or constraint data into LP row */
    1739 SCIP_CALL( createRow(scip, cons) );
    1740 }
    1741 assert(consdata->row != NULL);
    1742
    1743 /* insert LP row as cut */
    1744 if( !SCIProwIsInLP(consdata->row) )
    1745 {
    1746 SCIPdebugMsg(scip, "adding constraint <%s> as cut to the LP\n", SCIPconsGetName(cons));
    1747 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
    1748 }
    1749
    1750 return SCIP_OKAY;
    1751}
    1752
    1753/** checks constraint for violation, and adds it as a cut if possible */
    1754static
    1756 SCIP* scip, /**< SCIP data structure */
    1757 SCIP_CONS* cons, /**< logic or constraint to be separated */
    1758 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
    1759 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    1760 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    1761 SCIP_Bool* separated, /**< pointer to store TRUE, if a cut was found */
    1762 SCIP_Bool* reduceddom /**< pointer to store TRUE, if a domain reduction was found */
    1763 )
    1764{
    1765 SCIP_Bool addcut;
    1766 SCIP_Bool mustcheck;
    1767
    1768 assert(cons != NULL);
    1769 assert(SCIPconsGetHdlr(cons) != NULL);
    1770 assert(cutoff != NULL);
    1771 assert(separated != NULL);
    1772 assert(reduceddom != NULL);
    1773
    1775
    1776 *cutoff = FALSE;
    1777 SCIPdebugMsg(scip, "separating constraint <%s>\n", SCIPconsGetName(cons));
    1778
    1779 /* update and check the watched variables, if they were changed since last processing */
    1780 if( sol == NULL && SCIPconsIsPropagationEnabled(cons) )
    1781 {
    1782 SCIP_CALL( processWatchedVars(scip, cons, eventhdlr, cutoff, reduceddom, &addcut, &mustcheck) );
    1783 }
    1784 else
    1785 {
    1786 addcut = FALSE;
    1787 mustcheck = TRUE;
    1788 }
    1789
    1790 if( mustcheck )
    1791 {
    1792 SCIP_CONSDATA* consdata;
    1793
    1794 assert(!addcut);
    1795
    1796 consdata = SCIPconsGetData(cons);
    1797 assert(consdata != NULL);
    1798
    1799 /* variable's fixings didn't give us any information -> we have to check the constraint */
    1800 if( sol == NULL && consdata->row != NULL )
    1801 {
    1802 /* skip constraints already in the LP */
    1803 if( SCIProwIsInLP(consdata->row) )
    1804 return SCIP_OKAY;
    1805 else
    1806 {
    1807 SCIP_Real feasibility;
    1808
    1809 assert(!SCIProwIsInLP(consdata->row));
    1810 feasibility = SCIPgetRowLPFeasibility(scip, consdata->row);
    1811 addcut = SCIPisFeasNegative(scip, feasibility);
    1812 }
    1813 }
    1814 else
    1815 {
    1816 addcut = isConsViolated(scip, cons, sol);
    1817 }
    1818 }
    1819
    1820 if( addcut )
    1821 {
    1822 /* insert LP row as cut */
    1823 SCIP_CALL( addCut(scip, cons, cutoff) );
    1825 *separated = TRUE;
    1826 }
    1827
    1828 return SCIP_OKAY;
    1829}
    1830
    1831/** enforces the pseudo solution on the given constraint */
    1832static
    1834 SCIP* scip, /**< SCIP data structure */
    1835 SCIP_CONS* cons, /**< logic or constraint to be separated */
    1836 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    1837 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    1838 SCIP_Bool* infeasible, /**< pointer to store TRUE, if the constraint was infeasible */
    1839 SCIP_Bool* reduceddom, /**< pointer to store TRUE, if a domain reduction was found */
    1840 SCIP_Bool* solvelp /**< pointer to store TRUE, if the LP has to be solved */
    1841 )
    1842{
    1843 SCIP_Bool addcut;
    1844 SCIP_Bool mustcheck;
    1845
    1846 assert(!SCIPhasCurrentNodeLP(scip));
    1847 assert(cons != NULL);
    1848 assert(SCIPconsGetHdlr(cons) != NULL);
    1849 assert(cutoff != NULL);
    1850 assert(infeasible != NULL);
    1851 assert(reduceddom != NULL);
    1852 assert(solvelp != NULL);
    1853
    1855
    1856 /* update and check the watched variables, if they were changed since last processing */
    1858 {
    1859 SCIP_CALL( processWatchedVars(scip, cons, eventhdlr, cutoff, reduceddom, &addcut, &mustcheck) );
    1860 }
    1861 else
    1862 {
    1863 addcut = FALSE;
    1864 mustcheck = TRUE;
    1865 }
    1866
    1867 if( mustcheck )
    1868 {
    1869 assert(!addcut);
    1870
    1871 if( isConsViolated(scip, cons, NULL) )
    1872 {
    1873 /* constraint was infeasible -> reset age */
    1875 *infeasible = TRUE;
    1876 }
    1877 }
    1878 else if( addcut )
    1879 {
    1880 /* a cut must be added to the LP -> we have to solve the LP immediately */
    1882 *solvelp = TRUE;
    1883 }
    1884
    1885 return SCIP_OKAY;
    1886}
    1887
    1888/** sorts logicor constraint's variables by non-decreasing variable index */
    1889static
    1891 SCIP_CONSDATA* consdata /**< linear constraint data */
    1892 )
    1893{
    1894 assert(consdata != NULL);
    1895
    1896 if( !consdata->sorted )
    1897 {
    1898 if( consdata->nvars <= 1 )
    1899 consdata->sorted = TRUE;
    1900 else
    1901 {
    1902 SCIP_VAR* var1 = NULL;
    1903 SCIP_VAR* var2 = NULL;
    1904
    1905 /* remember watch variables */
    1906 if( consdata->watchedvar1 != -1 )
    1907 {
    1908 var1 = consdata->vars[consdata->watchedvar1];
    1909 assert(var1 != NULL);
    1910 consdata->watchedvar1 = -1;
    1911 if( consdata->watchedvar2 != -1 )
    1912 {
    1913 var2 = consdata->vars[consdata->watchedvar2];
    1914 assert(var2 != NULL);
    1915 consdata->watchedvar2 = -1;
    1916 }
    1917 }
    1918 assert(consdata->watchedvar1 == -1);
    1919 assert(consdata->watchedvar2 == -1);
    1920 assert(var1 != NULL || var2 == NULL);
    1921
    1922 /* sort variables after index */
    1923 SCIPsortPtr((void**)consdata->vars, SCIPvarComp, consdata->nvars);
    1924 consdata->sorted = TRUE;
    1925
    1926 /* correct watched variables */
    1927 if( var1 != NULL )
    1928 {
    1929 int pos;
    1930#ifndef NDEBUG
    1931 SCIP_Bool found;
    1932
    1933 found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var1, consdata->nvars, &pos);
    1934 assert(found);
    1935#else
    1936 (void) SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var1, consdata->nvars, &pos);
    1937#endif
    1938 assert(pos >= 0 && pos < consdata->nvars);
    1939 consdata->watchedvar1 = pos;
    1940
    1941 if( var2 != NULL )
    1942 {
    1943#ifndef NDEBUG
    1944 found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var2, consdata->nvars, &pos);
    1945 assert(found);
    1946#else
    1947 (void) SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var2, consdata->nvars, &pos);
    1948#endif
    1949 assert(pos >= 0 && pos < consdata->nvars);
    1950 consdata->watchedvar2 = pos;
    1951 }
    1952 }
    1953 }
    1954 }
    1955
    1956#ifdef SCIP_DEBUG
    1957 /* check sorting */
    1958 {
    1959 int v;
    1960
    1961 for( v = consdata->nvars - 1; v > 0; --v )
    1962 {
    1963 assert(SCIPvarCompare(consdata->vars[v], consdata->vars[v - 1]) >= 0);
    1964 }
    1965 }
    1966#endif
    1967}
    1968
    1969/** gets the key of the given element */
    1970static
    1971SCIP_DECL_HASHGETKEY(hashGetKeyLogicorcons)
    1972{ /*lint --e{715}*/
    1973 /* the key is the element itself */
    1974 return elem;
    1975}
    1976
    1977/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables */
    1978static
    1979SCIP_DECL_HASHKEYEQ(hashKeyEqLogicorcons)
    1980{
    1981 SCIP_CONSDATA* consdata1;
    1982 SCIP_CONSDATA* consdata2;
    1983 SCIP_Bool coefsequal;
    1984 int i;
    1985#ifndef NDEBUG
    1986 SCIP* scip;
    1987
    1988 scip = (SCIP*)userptr;
    1989 assert(scip != NULL);
    1990#endif
    1991
    1992 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
    1993 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
    1994
    1995 /* checks trivial case */
    1996 if( consdata1->nvars != consdata2->nvars )
    1997 return FALSE;
    1998
    1999 /* sorts the constraints */
    2000 consdataSort(consdata1);
    2001 consdataSort(consdata2);
    2002 assert(consdata1->sorted);
    2003 assert(consdata2->sorted);
    2004
    2005 coefsequal = TRUE;
    2006
    2007 for( i = 0; i < consdata1->nvars ; ++i )
    2008 {
    2009 /* tests if variables are equal */
    2010 if( consdata1->vars[i] != consdata2->vars[i] )
    2011 {
    2012 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
    2013 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
    2014 coefsequal = FALSE;
    2015 break;
    2016 }
    2017 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
    2018 }
    2019
    2020 return coefsequal;
    2021}
    2022
    2023/** returns the hash value of the key */
    2024static
    2025SCIP_DECL_HASHKEYVAL(hashKeyValLogicorcons)
    2026{ /*lint --e{715}*/
    2027 SCIP_CONSDATA* consdata;
    2028 int minidx;
    2029 int mididx;
    2030 int maxidx;
    2031
    2032 consdata = SCIPconsGetData((SCIP_CONS*)key);
    2033 assert(consdata != NULL);
    2034 assert(consdata->sorted);
    2035 assert(consdata->nvars > 0);
    2036
    2037 minidx = SCIPvarGetIndex(consdata->vars[0]);
    2038 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
    2039 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
    2040 assert(minidx >= 0 && minidx <= maxidx);
    2041
    2042 return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
    2043}
    2044
    2045/** compares each constraint with all other constraints for a possible duplication and removes duplicates using a hash
    2046 * table; also @see removeRedundantConssAndNonzeros()
    2047 */
    2048static
    2050 SCIP* scip, /**< SCIP data structure */
    2051 BMS_BLKMEM* blkmem, /**< block memory */
    2052 SCIP_CONS** conss, /**< constraint set */
    2053 int nconss, /**< number of constraints in constraint set */
    2054 int* firstchange, /**< pointer to store first changed constraint */
    2055 int* ndelconss /**< pointer to count number of deleted constraints */
    2056 )
    2057{
    2058 SCIP_HASHTABLE* hashtable;
    2059 int hashtablesize;
    2060 int c;
    2061
    2062 assert(conss != NULL);
    2063 assert(ndelconss != NULL);
    2064
    2065 /* create a hash table for the constraint set */
    2066 hashtablesize = nconss;
    2067 hashtablesize = MAX(hashtablesize, HASHSIZE_LOGICORCONS);
    2068 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
    2069 hashGetKeyLogicorcons, hashKeyEqLogicorcons, hashKeyValLogicorcons, (void*) scip) );
    2070
    2071 /* check all constraints in the given set for redundancy */
    2072 for( c = 0; c < nconss; ++c )
    2073 {
    2074 SCIP_CONS* cons0;
    2075 SCIP_CONS* cons1;
    2076 SCIP_CONSDATA* consdata0;
    2077
    2078 cons0 = conss[c];
    2079
    2080 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
    2081 continue;
    2082
    2083 consdata0 = SCIPconsGetData(cons0);
    2084 /* sort the constraint */
    2085 consdataSort(consdata0);
    2086 assert(consdata0->sorted);
    2087
    2088 /* get constraint from current hash table with same variables as cons0 */
    2089 cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
    2090
    2091 if( cons1 != NULL )
    2092 {
    2093#ifndef NDEBUG
    2094 SCIP_CONSDATA* consdata1;
    2095#endif
    2096
    2097 assert(SCIPconsIsActive(cons1));
    2098 assert(!SCIPconsIsModifiable(cons1));
    2099
    2100#ifndef NDEBUG
    2101 consdata1 = SCIPconsGetData(cons1);
    2102#endif
    2103 assert(consdata1 != NULL);
    2104 assert(consdata0->nvars >= 1 && consdata0->nvars == consdata1->nvars);
    2105
    2106 assert(consdata0->sorted && consdata1->sorted);
    2107 assert(consdata0->vars[0] == consdata1->vars[0]);
    2108
    2109 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
    2110 /* coverity[swapped_arguments] */
    2111 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
    2112
    2113 /* delete consdel */
    2114 SCIP_CALL( SCIPdelCons(scip, cons0) );
    2115 (*ndelconss)++;
    2116
    2117 /* update the first changed constraint to begin the next aggregation round with */
    2118 if( consdata0->changed && SCIPconsGetPos(cons1) < *firstchange )
    2119 *firstchange = SCIPconsGetPos(cons1);
    2120
    2121 assert(SCIPconsIsActive(cons1));
    2122 }
    2123 else
    2124 {
    2125 /* no such constraint in current hash table: insert cons0 into hash table */
    2126 SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
    2127 }
    2128 }
    2129
    2130 /* free hash table */
    2131 SCIPhashtableFree(&hashtable);
    2132
    2133 return SCIP_OKAY;
    2134}
    2135
    2136/** removes the redundant second constraint and updates the flags of the first one */
    2137static
    2139 SCIP* scip, /**< SCIP data structure */
    2140 SCIP_CONS* cons0, /**< constraint that should stay */
    2141 SCIP_CONS* cons1, /**< constraint that should be deleted */
    2142 int* ndelconss /**< pointer to count number of deleted constraints */
    2143 )
    2144{
    2145 assert(ndelconss != NULL);
    2146
    2147 SCIPdebugMsg(scip, " -> removing logicor constraint <%s> which is redundant to <%s>\n",
    2148 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
    2149 SCIPdebugPrintCons(scip, cons0, NULL);
    2150 SCIPdebugPrintCons(scip, cons1, NULL);
    2151
    2152 /* update flags of cons0 */
    2153 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
    2154
    2155 /* delete cons1 */
    2156 SCIP_CALL( SCIPdelCons(scip, cons1) );
    2157 (*ndelconss)++;
    2158
    2159 return SCIP_OKAY;
    2160}
    2161
    2162
    2163/** compute and return a signature for given variables */
    2164static
    2165unsigned int calcSignature(
    2166 SCIP_VAR** vars, /**< variables to calculate the signature for */
    2167 int nvars /**< number of variables to calculate the signature for */
    2168 )
    2169{
    2170 unsigned int signature = 0;
    2171 int v;
    2172
    2173 assert(vars != NULL);
    2174 assert(nvars >= 1);
    2175
    2176 for( v = nvars - 1; v >= 0; --v )
    2177 {
    2178 signature |= ((unsigned int)1 << ((unsigned int)SCIPvarGetIndex(vars[v]) % (sizeof(unsigned int) * 8)));
    2179 }
    2180
    2181 return signature;
    2182}
    2183
    2184/** compute the constraint signature which is used to detect constraints, that contain potentially the same set of
    2185 * variables
    2186 */
    2187static
    2189 SCIP_CONSDATA* consdata /**< logicor constraint data */
    2190 )
    2191{
    2192 if( consdata->validsignature )
    2193 return;
    2194
    2195 consdata->signature = calcSignature(consdata->vars, consdata->nvars);
    2196 consdata->validsignature = TRUE;
    2197}
    2198
    2199/** remove a constraint from the column representation */
    2200static
    2202 SCIP_CONS* cons, /**< logicor constraint */
    2203 SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
    2204 SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
    2205 int* noccurlistentries, /**< arrray with number of constraints for each variable in the occurlist */
    2206 int occurlistlength /**< number of columns in the occurlist */
    2207 )
    2208{
    2209 SCIP_VAR** vars;
    2210 SCIP_VAR* var;
    2211 SCIP_CONSDATA* consdata;
    2212 int nvars;
    2213 int pos;
    2214 int v;
    2215 int l;
    2216
    2217 assert(cons != NULL);
    2218 assert(SCIPconsIsActive(cons));
    2219 assert(varstopos != NULL);
    2220 assert(occurlist != NULL);
    2221 assert(noccurlistentries != NULL);
    2222
    2223 consdata = SCIPconsGetData(cons);
    2224 assert(consdata != NULL);
    2225
    2226 nvars = consdata->nvars;
    2227 assert(nvars >= 1);
    2228 vars = consdata->vars;
    2229 assert(vars != NULL);
    2230
    2231 /* remove constraint from list */
    2232 for( v = nvars - 1; v >= 0; --v )
    2233 {
    2234 var = vars[v];
    2235
    2236 assert(SCIPhashmapExists(varstopos, (void*) var));
    2237
    2238 pos = SCIPhashmapGetImageInt(varstopos, (void*)var);
    2239 assert(0 < pos && pos <= occurlistlength);
    2240
    2241 --pos;
    2242
    2243 /* remove for each variable one corresponding entry */
    2244 for( l = noccurlistentries[pos] - 1; l >= 0; --l )
    2245 {
    2246 if( occurlist[pos][l] == cons )
    2247 {
    2248 --noccurlistentries[pos];
    2249 assert(noccurlistentries[pos] >= 0);
    2250
    2251 occurlist[pos][l] = occurlist[pos][noccurlistentries[pos]];
    2252 break;
    2253 }
    2254 }
    2255 assert(l >= 0);
    2256 }
    2257}
    2258
    2259/** determine shortest constraint list in column representation */
    2260static
    2262 SCIP_VAR** vars, /**< variables to find the shortestlist for */
    2263 int nvars, /**< number of variables */
    2264 SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
    2265 SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
    2266 int* noccurlistentries, /**< arrray with number of constraints for each variable in the occurlist */
    2267 int occurlistlength, /**< number of columns in the occurlist */
    2268 int* nentries, /**< pointer to store the number of entries in the shortest list */
    2269 SCIP_CONS*** shortestlist /**< pointer to store smallest array with constraints */
    2270 )
    2271{
    2272 SCIP_VAR* var;
    2273 int pos;
    2274 int v;
    2275
    2276 assert(vars != 0);
    2277 assert(nvars >= 1);
    2278 assert(varstopos != NULL);
    2279 assert(occurlist != NULL);
    2280 assert(noccurlistentries != NULL);
    2281 assert(nentries != NULL);
    2282 assert(shortestlist != NULL);
    2283
    2284 *nentries = INT_MAX;
    2285 *shortestlist = NULL;
    2286
    2287 /* find the shortest list */
    2288 for( v = nvars - 1; v >= 0; --v )
    2289 {
    2290 var = vars[v];
    2291 assert(var != NULL);
    2292
    2293 /* it might be that a variable is not yet put into the occurlist, then this constraint cannot cover another */
    2294 if( !SCIPhashmapExists(varstopos, (void*) var) )
    2295 {
    2296 *nentries = 0;
    2297 return;
    2298 }
    2299
    2300 pos = SCIPhashmapGetImageInt(varstopos, (void*)var);
    2301 assert(0 < pos && pos <= occurlistlength);
    2302
    2303 --pos;
    2304
    2305 /* remember the shortest list */
    2306 if( noccurlistentries[pos] < *nentries )
    2307 {
    2308 *nentries = noccurlistentries[pos];
    2309 *shortestlist = occurlist[pos];
    2310 }
    2311 }
    2312}
    2313
    2314/** run a pairwise comparison for detecting subset-constraints of other constraint while using a signature */
    2315static
    2317 SCIP* scip, /**< SCIP data structure */
    2318 SCIP_CONS* cons, /**< logicor constraint to check if it covers another */
    2319 SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
    2320 SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
    2321 int* noccurlistentries, /**< arrray with number of constraints for each variable in the occurlist */
    2322 int occurlistlength, /**< number of columns in the occurlist */
    2323 int* ndelconss /**< pointer to store the number of deleted constraints */
    2324 )
    2325{
    2326 SCIP_CONS** shortestlist;
    2327 SCIP_VAR** vars;
    2328 SCIP_CONS* cons1;
    2329 SCIP_VAR* var;
    2330 SCIP_CONSDATA* consdata;
    2331 int nentries;
    2332 int c;
    2333 int v;
    2334
    2335 assert(scip != NULL);
    2336 assert(cons != NULL);
    2337 assert(SCIPconsIsActive(cons));
    2338 assert(!SCIPconsIsModifiable(cons));
    2339 assert(varstopos != NULL);
    2340 assert(occurlist != NULL);
    2341 assert(noccurlistentries != NULL);
    2342 assert(ndelconss != NULL);
    2343
    2344 consdata = SCIPconsGetData(cons);
    2345 assert(consdata != NULL);
    2346 assert(consdata->nvars > 1);
    2347 assert(consdata->validsignature);
    2348 assert(consdata->sorted);
    2349
    2350 vars = consdata->vars;
    2351 assert(vars != NULL);
    2352
    2353 /* determine shortest column */
    2354 findShortestOccurlist(vars, consdata->nvars, varstopos, occurlist, noccurlistentries, occurlistlength, &nentries, &shortestlist);
    2355
    2356 /* one variable which does not appear in the column representation anymore */
    2357 if( nentries == 0 )
    2358 return SCIP_OKAY;
    2359
    2360 assert(shortestlist != NULL);
    2361 assert(0 < nentries);
    2362
    2363 /* check all constraints in the shortest list for coverage */
    2364 for( c = nentries - 1; c >= 0; --c )
    2365 {
    2366 cons1 = shortestlist[c];
    2367 assert(cons1 != NULL);
    2368 assert(!SCIPconsIsModifiable(cons1));
    2369 assert(SCIPconsIsActive(cons1));
    2370
    2371 if( cons != cons1 )
    2372 {
    2373 SCIP_CONSDATA* consdata1 = SCIPconsGetData(cons1);
    2374 assert(consdata1 != NULL);
    2375 assert(consdata1->nvars >= consdata->nvars);
    2376
    2377 /* constraints with the same length cannot be covered and same constraints are removed in
    2378 * detectRedundantConstraints()
    2379 */
    2380 if( consdata1->nvars == consdata->nvars )
    2381 continue;
    2382
    2383 assert(consdata->validsignature);
    2384 assert(consdata->sorted);
    2385 assert(consdata1->validsignature);
    2386 assert(consdata1->sorted);
    2387
    2388 if( (consdata->signature & (~consdata1->signature)) == 0 )
    2389 {
    2390 SCIP_VAR* var1;
    2391 int v1;
    2392
    2393 v = 0;
    2394 v1 = 0;
    2395
    2396 while( v < consdata->nvars && v1 < consdata1->nvars )
    2397 {
    2398 int comp;
    2399
    2400 var = vars[v];
    2401 var1 = consdata1->vars[v1];
    2402
    2403 comp = SCIPvarCompare(var, var1);
    2404
    2405 if( comp == 0 )
    2406 {
    2407 ++v;
    2408 ++v1;
    2409 }
    2410 else if( comp > 0 )
    2411 ++v1;
    2412 else
    2413 break;
    2414 }
    2415
    2416 /* cons1 is covered by cons */
    2417 if( v == consdata->nvars )
    2418 {
    2419 /* remove cons1 from columns representation */
    2420 removeConsFromOccurList(cons1, varstopos, occurlist, noccurlistentries, occurlistlength);
    2421
    2422 /* delete redundant constraint and update constraint flags if necessary */
    2423 SCIP_CALL( removeRedundantCons(scip, cons, cons1, ndelconss) );
    2424 }
    2425 }
    2426 }
    2427 }
    2428
    2429 return SCIP_OKAY;
    2430}
    2431
    2432/** compararer for sorting constraints after their number of variables */
    2433static
    2434SCIP_DECL_SORTPTRCOMP(conssLogicorComp)
    2435{
    2436 SCIP_CONSDATA* consdata1;
    2437 SCIP_CONSDATA* consdata2;
    2438
    2439 assert(elem1 != NULL);
    2440 assert(elem2 != NULL);
    2441
    2442 consdata1 = SCIPconsGetData((SCIP_CONS*) elem1);
    2443 consdata2 = SCIPconsGetData((SCIP_CONS*) elem2);
    2444
    2445 assert(consdata1 != NULL);
    2446 assert(consdata2 != NULL);
    2447
    2448 return consdata1->nvars - consdata2->nvars;
    2449}
    2450
    2451/** add a constraint to the column representation */
    2452static
    2454 SCIP* scip, /**< SCIP data structure */
    2455 SCIP_CONS* cons, /**< logicor constraint */
    2456 SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
    2457 SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
    2458 int* noccurlistentries, /**< arrray with number of constraints for each variable in the occurlist */
    2459 int* occurlistsizes, /**< array of sizes for each variable in the occurlist */
    2460 int* occurlistlength, /**< number of columns in the occurlist */
    2461 int occurlistsize /**< size of occurlist */
    2462 )
    2463{
    2464 SCIP_VAR** vars;
    2465 SCIP_VAR* var;
    2466 SCIP_CONSDATA* consdata;
    2467 int pos;
    2468 int v;
    2469
    2470 assert(scip != NULL);
    2471 assert(cons != NULL);
    2472 assert(SCIPconsIsActive(cons));
    2473 assert(varstopos != NULL);
    2474 assert(occurlist != NULL);
    2475 assert(noccurlistentries != NULL);
    2476 assert(occurlistsizes != NULL);
    2477 assert(occurlistlength != NULL);
    2478 assert(*occurlistlength <= occurlistsize);
    2479
    2480 consdata = SCIPconsGetData(cons);
    2481 assert(consdata != NULL);
    2482 assert(consdata->nvars > 1);
    2483
    2484 vars = consdata->vars;
    2485 assert(vars != NULL);
    2486
    2487 for( v = consdata->nvars - 1; v >= 0; --v )
    2488 {
    2489 var = vars[v];
    2490 assert(var != NULL);
    2492
    2493 /* check if the variable is not yet put into the occurlist */
    2494 if( !SCIPhashmapExists(varstopos, (void*) var) )
    2495 {
    2496 pos = *occurlistlength;
    2497 assert(pos <= occurlistsize);
    2498
    2499 /* occurlist values need to be clear */
    2500 assert(occurlist[pos] == NULL);
    2501 assert(noccurlistentries[pos] == 0);
    2502 assert(occurlistsizes[pos] == 0);
    2503
    2504 /* allocate memory */
    2506 occurlistsizes[pos] = SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) + 1;
    2507 SCIP_CALL( SCIPallocBufferArray(scip, &(occurlist[pos]), occurlistsizes[pos]) ); /*lint !e866*/
    2508
    2509 /* put constraint in list of current variable */
    2510 occurlist[pos][noccurlistentries[pos]] = cons;
    2511 ++(noccurlistentries[pos]);
    2512
    2513 /* add new variable to map */
    2514 SCIP_CALL( SCIPhashmapInsertInt(varstopos, var, pos + 1) );
    2515
    2516 ++(*occurlistlength);
    2517 }
    2518 else
    2519 {
    2520 pos = SCIPhashmapGetImageInt(varstopos, (void*)var);
    2521 assert(0 < pos && pos <= *occurlistlength);
    2522
    2523 --pos;
    2524
    2525 assert(occurlist[pos] != NULL);
    2526 assert(occurlistsizes[pos] > 0);
    2527
    2528 /* do we need to resize the array */
    2529 if( noccurlistentries[pos] == occurlistsizes[pos] )
    2530 {
    2531 occurlistsizes[pos] = SCIPcalcMemGrowSize(scip, occurlistsizes[pos] + 1);
    2532 assert(occurlistsizes[pos] > noccurlistentries[pos] && occurlistsizes[pos] < INT_MAX);
    2533
    2534 /* resize occurlist for current variable */
    2535 SCIP_CALL( SCIPreallocBufferArray(scip, &(occurlist[pos]), occurlistsizes[pos]) ); /*lint !e866*/
    2536 }
    2537 assert(noccurlistentries[pos] < occurlistsizes[pos]);
    2538
    2539 /* put constraint in list of current variable */
    2540 occurlist[pos][noccurlistentries[pos]] = cons;
    2541 ++(noccurlistentries[pos]);
    2542 }
    2543 }
    2544
    2545 return SCIP_OKAY;
    2546}
    2547
    2548/** run a pairwise comparison for the given variables against all constraits to detect redundant non-zeros in these
    2549 * constraints
    2550 */
    2551static
    2553 SCIP* scip, /**< SCIP data structure */
    2554 SCIP_CONS* cons, /**< logicor constraint to check if it covers another */
    2555 SCIP_VAR* artvar, /**< artificial negated variable of constraint */
    2556 int artpos, /**< position to replace constraint variable with artvar */
    2557 SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
    2558 SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
    2559 int* noccurlistentries, /**< number of constraints for each variable in the occurlist */
    2560 int occurlistlength, /**< number of columns in the occurlist */
    2561 SCIP_EVENTHDLR* eventhdlr, /**< event handler */
    2562 int* nchgcoefs, /**< pointer to store the number of deleted non-zeros */
    2563 SCIP_Bool* deleted /**< pointer to store if cons will be deleted */
    2564 )
    2565{
    2566 SCIP_CONS** shortestlist;
    2567 SCIP_VAR** vars;
    2568 SCIP_CONS* cons1;
    2569 SCIP_VAR* oldvar;
    2570 SCIP_VAR* var;
    2571 SCIP_CONSDATA* consdata;
    2572 unsigned int signature;
    2573 int nentries;
    2574 int nvars;
    2575 int c;
    2576 int v;
    2577 int pos;
    2578
    2579 assert(scip != NULL);
    2580 assert(cons != NULL);
    2581 assert(artvar != NULL);
    2582 assert(SCIPconsIsActive(cons));
    2583 assert(!SCIPconsIsModifiable(cons));
    2584 assert(varstopos != NULL);
    2585 assert(SCIPhashmapExists(varstopos, (void*) artvar));
    2586 assert(occurlist != NULL);
    2587 assert(noccurlistentries != NULL);
    2588 assert(nchgcoefs != NULL);
    2589 assert(deleted != NULL);
    2590
    2591 consdata = SCIPconsGetData(cons);
    2592 assert(consdata != NULL);
    2593 assert(consdata->sorted);
    2594
    2595 nvars = consdata->nvars;
    2596 assert(nvars > 1);
    2597 assert(0 <= artpos && artpos < nvars);
    2598
    2599 vars = consdata->vars;
    2600 assert(vars != NULL);
    2601
    2602 *deleted = FALSE;
    2603
    2604 /* temporary exchange the variable for finding the shortest list */
    2605 oldvar = vars[artpos];
    2606 assert(oldvar == SCIPvarGetNegatedVar(artvar));
    2607 vars[artpos] = artvar;
    2608
    2609 /* determine shortest column */
    2610 findShortestOccurlist(vars, nvars, varstopos, occurlist, noccurlistentries, occurlistlength, &nentries, &shortestlist);
    2611
    2612 /* correct exchanged variable with constraint variables */
    2613 vars[artpos] = oldvar;
    2614
    2615 /* one variable which does not appear in the column representation anymore */
    2616 if( nentries == 0 )
    2617 return SCIP_OKAY;
    2618
    2619 assert(shortestlist != NULL);
    2620 assert(0 < nentries);
    2621
    2622 /* temporary exchange the variable for calculating a valid signature */
    2623 vars[artpos] = artvar;
    2624 signature = calcSignature(vars, nvars);
    2625
    2626 /* correct exchanged variable with constraint variables */
    2627 vars[artpos] = oldvar;
    2628
    2629 /* check all constraints in the shortest list for coverage */
    2630 for( c = nentries - 1; c >= 0; --c )
    2631 {
    2632 cons1 = shortestlist[c];
    2633 assert(cons1 != NULL);
    2634 assert(!SCIPconsIsModifiable(cons1));
    2635
    2636 if( !SCIPconsIsActive(cons1) )
    2637 continue;
    2638
    2639 if( cons != cons1 )
    2640 {
    2641 SCIP_CONSDATA* consdata1 = SCIPconsGetData(cons1);
    2642 assert(consdata1 != NULL);
    2643
    2644 /* constraints with the less variables cannot be covered */
    2645 if( consdata1->nvars < nvars )
    2646 continue;
    2647
    2648 pos = -1;
    2649
    2650 assert(consdata->sorted);
    2651 assert(consdata->merged);
    2652 assert(consdata1->validsignature);
    2653 assert(consdata1->sorted);
    2654 assert(consdata1->merged);
    2655
    2656 if( (signature & (~consdata1->signature)) == 0 )
    2657 {
    2658 SCIP_VAR* var1;
    2659 int v1;
    2660
    2661 v = 0;
    2662 v1 = 0;
    2663
    2664 while( v < nvars && v1 < consdata1->nvars )
    2665 {
    2666 int comp;
    2667
    2668 /* skip position of artificial variable */
    2669 if( artpos == v )
    2670 {
    2671 ++v;
    2672 continue;
    2673 }
    2674
    2675 var1 = consdata1->vars[v1];
    2676
    2677 /* did we find the artificial variable in cons1 */
    2678 if( artvar == var1 )
    2679 {
    2680 /* remember of possible redundant variable */
    2681 assert(pos == -1);
    2682 pos = v1;
    2683
    2684 ++v1;
    2685 continue;
    2686 }
    2687
    2688 var = vars[v];
    2689 comp = SCIPvarCompare(var, var1);
    2690
    2691 /* check if the cons1 can still be covered */
    2692 if( comp == 0 )
    2693 {
    2694 ++v;
    2695 ++v1;
    2696 }
    2697 else if( comp > 0 )
    2698 ++v1;
    2699 else
    2700 break;
    2701 }
    2702
    2703 /* cons1 is might be covered by the changed constraints cons, meaning that we might remove the artvar from
    2704 * cons1
    2705 */
    2706 if( v == nvars )
    2707 {
    2708 int l;
    2709
    2710 /* if the artificial variable was not yet found, search over the rear variables in constraint cons1 */
    2711 if( pos == -1 )
    2712 {
    2713 while( v1 < consdata1->nvars )
    2714 {
    2715 if( artvar == consdata1->vars[v1] )
    2716 {
    2717 /* remember of possible redundant variable */
    2718 pos = v1;
    2719 break;
    2720 }
    2721 ++v1;
    2722 }
    2723 }
    2724
    2725 if( pos >= 0 )
    2726 {
    2727 int conspos;
    2728
    2729 assert(pos < consdata1->nvars);
    2730 assert(artvar == consdata1->vars[pos]);
    2731
    2732 /* remove redudant entry in cons1 */
    2733 SCIPdebugMsg(scip, "variable %s in logicor constraint <%s> is redundant and will be removed (used constraint %s)\n",
    2734 SCIPvarGetName(artvar), SCIPconsGetName(cons1), SCIPconsGetName(cons));
    2735 SCIPdebugPrintCons(scip, cons1, NULL);
    2736 conspos = pos;
    2737
    2738 if( consdata1->nvars > nvars )
    2739 {
    2740 pos = SCIPhashmapGetImageInt(varstopos, (void*)artvar);
    2741 assert(0 < pos && pos <= occurlistlength);
    2742
    2743 --pos;
    2744
    2745 /* remove corresponding entry in column representation */
    2746 for( l = noccurlistentries[pos] - 1; l >= 0; --l )
    2747 {
    2748 if( occurlist[pos][l] == cons1 )
    2749 {
    2750 --noccurlistentries[pos];
    2751 assert(noccurlistentries[pos] >= 0);
    2752
    2753 occurlist[pos][l] = occurlist[pos][noccurlistentries[pos]];
    2754 break;
    2755 }
    2756 }
    2757 assert(l >= 0);
    2758 }
    2759 else
    2760 {
    2761 assert(consdata1->nvars == nvars);
    2762
    2763 /* delete cons */
    2764 SCIPdebugMsg(scip, "logicor constraint <%s> is redundant due to constraint <%s> after removing variable <%s>\n",
    2765 SCIPconsGetName(cons), SCIPconsGetName(cons1), SCIPvarGetName(artvar));
    2766
    2767 /* remove cons from columns representation */
    2768 removeConsFromOccurList(cons, varstopos, occurlist, noccurlistentries, occurlistlength);
    2769
    2770 /* update flags of cons1 */
    2771 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons) );
    2772
    2773 SCIP_CALL( SCIPdelCons(scip, cons) );
    2774 *deleted = TRUE;
    2775 }
    2776
    2777 /* remove variable */
    2778 SCIP_CALL( delCoefPos(scip, cons1, eventhdlr, conspos) );
    2779 ++(*nchgcoefs);
    2780 consdataSort(consdata1);
    2781 consdataCalcSignature(consdata1);
    2782
    2783 if( *deleted )
    2784 return SCIP_OKAY;
    2785 }
    2786 }
    2787 }
    2788 }
    2789 }
    2790
    2791 return SCIP_OKAY;
    2792}
    2793
    2794/** find and remove redundant non-zero entries */
    2795static
    2797 SCIP* scip, /**< SCIP data structure */
    2798 SCIP_CONS** conss, /**< sorted array of logicor constraint */
    2799 int nconss, /**< number of sorted constraints */
    2800 SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
    2801 SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
    2802 int* noccurlistentries, /**< number of constraints for each variable in the occurlist */
    2803 int occurlistlength, /**< number of columns in the occurlist */
    2804 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    2805 int* ndelconss, /**< pointer to store the number of deleted constraints */
    2806 int* nchgcoefs /**< pointer to store the number of remove coefficients */
    2807 )
    2808{
    2809 SCIP_VAR** vars;
    2810 SCIP_CONSDATA* consdata;
    2811 SCIP_CONS* cons;
    2812 SCIP_VAR* artvar;
    2813 int nvars;
    2814 int c;
    2815 int v;
    2816
    2817 assert(scip != NULL);
    2818 assert(conss != NULL || nconss == 0);
    2819 assert(varstopos != NULL);
    2820 assert(occurlist != NULL);
    2821 assert(noccurlistentries != NULL);
    2822 assert(eventhdlr != NULL);
    2823 assert(ndelconss != NULL);
    2824 assert(nchgcoefs != NULL);
    2825
    2826 if( nconss == 0 )
    2827 return SCIP_OKAY;
    2828
    2829 assert(conss != NULL);
    2830
    2831 for( c = 0; c < nconss; ++c )
    2832 {
    2833 cons = conss[c];
    2834 assert(cons != NULL);
    2835 assert(!SCIPconsIsModifiable(cons));
    2836
    2837 if( !SCIPconsIsActive(cons) )
    2838 continue;
    2839
    2840 consdata = SCIPconsGetData(cons);
    2841 assert(consdata != NULL);
    2842
    2843 nvars = consdata->nvars;
    2844 assert(nvars >= 1);
    2845
    2846 if( nvars == 1 )
    2847 continue;
    2848
    2849 vars = consdata->vars;
    2850 assert(vars != NULL);
    2851
    2852 for( v = nvars - 1; v >= 0; --v )
    2853 {
    2854 artvar = SCIPvarGetNegatedVar(vars[v]);
    2855
    2856 if( artvar != NULL && SCIPhashmapExists(varstopos, (void*) artvar) )
    2857 {
    2858 SCIP_Bool deleted;
    2859
    2860 /* detect and remove redundant non-zero entries */
    2861 /* @todo: improve this algorithm by using the information that a constraint variables does not appaer in any
    2862 * other constraint, which means that only this variable needs to be negated to check for redundant
    2863 * non-zeros, therefor change also findShortestOccurlist() to return the corresponding
    2864 * variable/position
    2865 */
    2866 SCIP_CALL( removeRedundantNonZeros(scip, cons, artvar, v, varstopos, occurlist, noccurlistentries,
    2867 occurlistlength, eventhdlr, nchgcoefs, &deleted) );
    2868
    2869 if( deleted )
    2870 {
    2871 assert(SCIPconsIsDeleted(cons));
    2872 ++(*ndelconss);
    2873 break;
    2874 }
    2875 else
    2876 assert(SCIPconsIsActive(cons));
    2877 }
    2878 }
    2879 }
    2880
    2881 return SCIP_OKAY;
    2882}
    2883
    2884
    2885/** prepares a constraint by removing fixings and merge it */
    2886static
    2888 SCIP* scip, /**< SCIP data structure */
    2889 SCIP_CONS* cons, /**< logic or constraint */
    2890 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    2891 unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
    2892 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
    2893 SCIP_Bool* redundant, /**< returns whether a variable fixed to one exists in the constraint */
    2894 int* nfixedvars, /**< pointer to count number of fixings */
    2895 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
    2896 int* ndelconss, /**< pointer to count number of deleted constraints */
    2897 SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
    2898 )
    2899{
    2900 SCIP_CONSDATA* consdata;
    2901
    2902 assert(scip != NULL);
    2903 assert(cons != NULL);
    2904 assert(!SCIPconsIsDeleted(cons));
    2905 assert(eventhdlr != NULL);
    2906 assert(*entries != NULL);
    2907 assert(nentries != NULL);
    2908 assert(redundant != NULL);
    2909 assert(nfixedvars != NULL);
    2910 assert(nchgcoefs != NULL);
    2911 assert(ndelconss != NULL);
    2912 assert(redundant != NULL);
    2913
    2914 consdata = SCIPconsGetData(cons);
    2915 assert(consdata != NULL);
    2916 assert(consdata->nvars > 0);
    2917
    2918 *redundant = FALSE;
    2919
    2920 /* remove old fixings */
    2921 if( !consdata->presolved )
    2922 {
    2923 /* remove all variables that are fixed to zero, check redundancy due to fixed-to-one variable */
    2924 SCIP_CALL( applyFixings(scip, cons, eventhdlr, redundant, nchgcoefs, NULL, NULL) );
    2925 }
    2926
    2927 if( !*redundant )
    2928 {
    2929 /* merge constraint */
    2930 SCIP_CALL( mergeMultiples(scip, cons, eventhdlr, entries, nentries, redundant, nchgcoefs) );
    2931 }
    2932
    2933 if( *redundant )
    2934 {
    2935 SCIP_CALL( SCIPdelCons(scip, cons) );
    2936 ++(*ndelconss);
    2937
    2938 return SCIP_OKAY;
    2939 }
    2940
    2941 if( consdata->nvars == 0 )
    2942 {
    2943 *cutoff = TRUE;
    2944 }
    2945 else if( consdata->nvars == 1 )
    2946 {
    2947 SCIP_Bool infeasible;
    2948 SCIP_Bool fixed;
    2949
    2950 SCIPdebugMsg(scip, " -> fix last remaining variable and delete constraint\n");
    2951
    2952 SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], 1.0, &infeasible, &fixed) );
    2953 assert(!infeasible);
    2954 assert(fixed);
    2955 ++(*nfixedvars);
    2956
    2957 SCIP_CALL( SCIPdelCons(scip, cons) );
    2958 ++(*ndelconss);
    2959
    2960 *redundant = TRUE;
    2961 }
    2962 consdata->presolved = TRUE;
    2963
    2964 return SCIP_OKAY;
    2965}
    2966
    2967
    2968/** find covered/subsumed constraints and redundant non-zero entries
    2969 *
    2970 * covered:
    2971 * e.g.: c1: x1 + x2 + x3 >= 1
    2972 * c2: x1 + x2 + x3 + x4 >= 1
    2973 *
    2974 * strengthen:
    2975 * e.g.: c1: x1 + x2 + x3 >= 1
    2976 * c2: x1 + x2 + ~x3 + x4 >= 1
    2977 *
    2978 * => c2: x1 + x2 + x4 >= 1
    2979 *
    2980 * @see "Effective Preprocessing in SAT through Variable and Clause Elimination" by Niklas En and Armin Biere
    2981 */
    2982static
    2984 SCIP* scip, /**< SCIP data structure */
    2985 SCIP_CONS** conss, /**< array of logicor constraints */
    2986 int nconss, /**< number of logicor constraints */
    2987 unsigned char** entries, /**< array to store whether two positions in constraints represent the same
    2988 * variable */
    2989 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
    2990 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    2991 SCIP_Bool usestrengthening, /**< should we try to strengthen constraints by removing superflous
    2992 * non-zeros? */
    2993 int* firstchange, /**< pointer to store first changed constraint */
    2994 int* nfixedvars, /**< pointer to count number of fixings */
    2995 int* ndelconss, /**< pointer to store the number of deleted constraints */
    2996 int* nchgcoefs, /**< pointer to store the number of deleted coefficients */
    2997 SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
    2998 )
    2999{
    3000 SCIP_CONS*** occurlist;
    3001 SCIP_CONS** myconss;
    3002 SCIP_HASHMAP* varstopos;
    3003 SCIP_CONS* cons;
    3004 SCIP_CONSDATA* consdata;
    3005 int* noccurlistentries;
    3006 int* occurlistsizes;
    3007 SCIP_Bool redundant;
    3008 SCIP_Bool conschanged;
    3009 int lastnfixedvars;
    3010 int nbinvars;
    3011 int occurlistlength;
    3012 int occurlistsize;
    3013 int nmyconss;
    3014 int nmaxvars;
    3015 int c;
    3016
    3017 assert(scip != NULL);
    3018 assert(conss != NULL || nconss == 0);
    3019 assert(entries != NULL);
    3020 assert(*entries != NULL);
    3021 assert(nentries != NULL);
    3022 assert(eventhdlr != NULL);
    3023 assert(firstchange != NULL);
    3024 assert(0 <= *firstchange);
    3025 assert(nfixedvars != NULL);
    3026 assert(ndelconss != NULL);
    3027 assert(nchgcoefs != NULL);
    3028
    3029 if( *firstchange > nconss || nconss < 2 )
    3030 return SCIP_OKAY;
    3031
    3032 SCIPdebugMsg(scip, "starting removeRedundantConssAndNonzeros(), pairwise comparison to detect covered logicor constraints\n");
    3033
    3034 /* copy constraints to re-order them */
    3035 SCIP_CALL( SCIPduplicateBufferArray(scip, &myconss, conss, nconss) );
    3036
    3037 nmyconss = nconss;
    3038 lastnfixedvars = -1;
    3039 while( *nfixedvars != lastnfixedvars )
    3040 {
    3041 lastnfixedvars = *nfixedvars;
    3042 for( c = nconss - 1; c >= 0; --c )
    3043 {
    3044 cons = myconss[c];
    3045 assert(cons != NULL);
    3046
    3047 if( SCIPconsIsDeleted(cons) || SCIPconsIsModifiable(cons) )
    3048 {
    3049 myconss[c] = myconss[nmyconss - 1];
    3050 --nmyconss;
    3051
    3052 continue;
    3053 }
    3054
    3055 /* prepare constraint by removing fixings and merge it */
    3056 SCIP_CALL( prepareCons(scip, cons, eventhdlr, entries, nentries, &redundant, nfixedvars, nchgcoefs, ndelconss, cutoff) );
    3057
    3058 if( redundant )
    3059 {
    3060 assert(SCIPconsIsDeleted(cons));
    3061 assert(!(*cutoff));
    3062
    3063 myconss[c] = myconss[nmyconss - 1];
    3064 --nmyconss;
    3065
    3066 continue;
    3067 }
    3068
    3069 if( *cutoff )
    3070 {
    3071 SCIPfreeBufferArray(scip, &myconss);
    3072
    3073 return SCIP_OKAY;
    3074 }
    3075
    3076 consdata = SCIPconsGetData(cons);
    3077
    3078 /* sort the constraint */
    3079 consdataSort(consdata);
    3080
    3081 assert(consdata->nvars >= 2);
    3082 }
    3083 }
    3084
    3085 SCIPsortPtr((void**)myconss, conssLogicorComp, nmyconss);
    3086 assert(myconss[0] != NULL && myconss[nmyconss - 1] != NULL);
    3087 assert(SCIPconsGetData(myconss[0]) != NULL && SCIPconsGetData(myconss[nmyconss - 1]) != NULL);
    3088 assert(SCIPconsGetData(myconss[0])->nvars <= SCIPconsGetData(myconss[nmyconss - 1])->nvars);
    3089
    3090 /* we can stop if strengthening is disabled and all constraints have the same amount of variables */
    3091 if( !usestrengthening && SCIPconsGetData(myconss[0])->nvars == SCIPconsGetData(myconss[nmyconss - 1])->nvars )
    3092 {
    3093 SCIPfreeBufferArray(scip, &myconss);
    3094
    3095 return SCIP_OKAY;
    3096 }
    3097
    3098 /* @note: in the following we have at least number of nonzeros in logicor constraints + three times two the number of
    3099 * binary variables memory consumption + a map for variables to positions, we need this to get a column base
    3100 * representation
    3101 */
    3102
    3103 /* get number of all possible(incl. implicit) binary variables and their negation */
    3104 nbinvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
    3105 occurlistsize = 2 * nbinvars;
    3106
    3107 /* allocate memory for the column representation for each variable */
    3108 SCIP_CALL( SCIPallocBufferArray(scip, &occurlist, occurlistsize) );
    3109 BMSclearMemoryArray(occurlist, occurlistsize);
    3110 SCIP_CALL( SCIPallocBufferArray(scip, &noccurlistentries, occurlistsize) );
    3111 BMSclearMemoryArray(noccurlistentries, occurlistsize);
    3112 SCIP_CALL( SCIPallocBufferArray(scip, &occurlistsizes, occurlistsize) );
    3113 BMSclearMemoryArray(occurlistsizes, occurlistsize);
    3114
    3115 /* create hashmap to map all occuring variables to a position in the list */
    3116 SCIP_CALL( SCIPhashmapCreate(&varstopos, SCIPblkmem(scip), nmyconss) );
    3117
    3118 /* get maximal number of variables over all logicor constraints */
    3119 c = nmyconss - 1;
    3120 cons = myconss[c];
    3121 assert(cons != NULL);
    3122 assert(SCIPconsIsActive(cons));
    3123 consdata = SCIPconsGetData(cons);
    3124 assert(consdata != NULL);
    3125 nmaxvars = consdata->nvars;
    3126
    3127 occurlistlength = 0;
    3128 conschanged = FALSE;
    3129
    3130 /* determine all constraints with the maximal number of variables and add them to the column representation */
    3131 do
    3132 {
    3133 /* calculate hash-signature */
    3134 consdataCalcSignature(consdata);
    3135 assert(consdata->validsignature);
    3136 conschanged = conschanged || consdata->changed;
    3137 consdata->changed = FALSE;
    3138
    3139 /* add constraint to column data structure */
    3140 SCIP_CALL( addConsToOccurList(scip, cons, varstopos, occurlist, noccurlistentries, occurlistsizes, &occurlistlength, occurlistsize) );
    3141
    3142 --c;
    3143 if( c < 0 )
    3144 break;
    3145
    3146 cons = myconss[c];
    3147 assert(cons != NULL);
    3148 assert(SCIPconsIsActive(cons));
    3149 consdata = SCIPconsGetData(cons);
    3150 assert(consdata != NULL);
    3151 }
    3152 while( consdata->nvars == nmaxvars );
    3153
    3154 /* remove covered constraints and left over constraints to the column representation */
    3155 while( c >= 0 )
    3156 {
    3157 cons = myconss[c];
    3158 assert(cons != NULL);
    3159 assert(SCIPconsIsActive(cons));
    3160 consdata = SCIPconsGetData(cons);
    3161 assert(consdata != NULL);
    3162
    3163 /* calculate hash-signature */
    3164 consdataCalcSignature(consdata);
    3165 assert(consdata->validsignature);
    3166
    3167 /* search for covered constraints */
    3168 if( conschanged || consdata->changed )
    3169 {
    3170 /* detect covered constraints
    3171 *
    3172 * e.g.: c1: x1 + x2 + x3 >= 1
    3173 * c2: x1 + x2 + x3 + x4 >= 1
    3174 *
    3175 * => delete c2
    3176 */
    3177 SCIP_CALL( removeRedundantConss(scip, cons, varstopos, occurlist, noccurlistentries, occurlistlength, ndelconss) );
    3178 assert(SCIPconsIsActive(cons));
    3179
    3180 consdata->changed = FALSE;
    3181 conschanged = TRUE;
    3182 }
    3183
    3184 /* add constraint to column data structure */
    3185 SCIP_CALL( addConsToOccurList(scip, cons, varstopos, occurlist, noccurlistentries, occurlistsizes, &occurlistlength, occurlistsize) );
    3186
    3187 --c;
    3188 }
    3189
    3190 /* strengthen constraint while removing non-zeros
    3191 *
    3192 * e.g.: c1: x1 + x2 + x3 >= 1
    3193 * c2: x1 + x2 + ~x3 + x4 >= 1
    3194 *
    3195 * => c2: x1 + x2 + x4 >= 1
    3196 *
    3197 * special case:
    3198 *
    3199 * e.g.: c1: x1 + x2 + x3 >= 1
    3200 * c2: x1 + x2 + ~x3 >= 1
    3201 *
    3202 * => delete c1; c2: x1 + x2 >= 1
    3203 *
    3204 */
    3205 SCIP_CALL( strengthenConss(scip, myconss, nmyconss, varstopos, occurlist, noccurlistentries, occurlistlength, eventhdlr, ndelconss, nchgcoefs) );
    3206
    3207 /* delete temporary memory in occurlist */
    3208 for( --occurlistsize ; occurlistsize >= 0; --occurlistsize )
    3209 {
    3210 assert((occurlistsizes[occurlistsize] == 0) == (occurlist[occurlistsize] == NULL));
    3211 SCIPfreeBufferArrayNull(scip, &(occurlist[occurlistsize]));
    3212 }
    3213
    3214 /* delete temporary memory */
    3215 SCIPhashmapFree(&varstopos);
    3216 SCIPfreeBufferArray(scip, &occurlistsizes);
    3217 SCIPfreeBufferArray(scip, &noccurlistentries);
    3218 SCIPfreeBufferArray(scip, &occurlist);
    3219 SCIPfreeBufferArray(scip, &myconss);
    3220
    3221 return SCIP_OKAY;
    3222}
    3223
    3224#define MAX_CONSLENGTH 200
    3225
    3226/** try to tighten constraints by reducing the number of variables in the constraints using implications and cliques,
    3227 * also derive fixations through them, @see SCIPshrinkDisjunctiveVarSet()
    3228 */
    3229static
    3231 SCIP* scip, /**< SCIP data structure */
    3232 SCIP_CONSHDLRDATA* conshdlrdata, /**< logic or constraint handler data */
    3233 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    3234 SCIP_CONS** conss, /**< all constraints */
    3235 int nconss, /**< number of constraints */
    3236 unsigned char** entries, /**< array to store whether two positions in constraints represent the same
    3237 * variable */
    3238 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
    3239 int* nfixedvars, /**< pointer to count number of fixings */
    3240 int* ndelconss, /**< pointer to count number of deleted constraints */
    3241 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
    3242 SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
    3243 )
    3244{
    3245 SCIP_VAR** probvars;
    3246 SCIP_VAR* var;
    3247 SCIP_Real* bounds;
    3248 SCIP_Bool* boundtypes;
    3249 SCIP_Bool* redundants;
    3250 int nbinprobvars;
    3251 int nredvars;
    3252 int c;
    3253 int v;
    3254
    3255 assert(scip != NULL);
    3256 assert(eventhdlr != NULL);
    3257 assert(conss != NULL || nconss == 0);
    3258 assert(entries != NULL);
    3259 assert(*entries != NULL);
    3260 assert(nentries != NULL);
    3261 assert(nfixedvars != NULL);
    3262 assert(ndelconss != NULL);
    3263 assert(nchgcoefs != NULL);
    3264
    3265 if( nconss == 0 )
    3266 return SCIP_OKAY;
    3267
    3268 assert(conss != NULL);
    3269
    3270 if( SCIPgetNCliques(scip) == conshdlrdata->nlastcliquesshorten
    3271 && SCIPgetNImplications(scip) == conshdlrdata->nlastimplsshorten )
    3272 return SCIP_OKAY;
    3273
    3274 conshdlrdata->nlastcliquesshorten = SCIPgetNCliques(scip);
    3275 conshdlrdata->nlastimplsshorten = SCIPgetNImplications(scip);
    3276
    3277 nbinprobvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
    3278
    3279 /* allocate temporary memory */
    3280 SCIP_CALL( SCIPallocBufferArray(scip, &probvars, nbinprobvars) );
    3281 SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nbinprobvars) );
    3282 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nbinprobvars) );
    3283 SCIP_CALL( SCIPallocCleanBufferArray(scip, &redundants, nbinprobvars) );
    3284
    3285 for( c = nconss - 1; c >= 0; --c )
    3286 {
    3287 SCIP_Bool redundant = FALSE;
    3288 SCIP_CONS* cons = conss[c];
    3289 SCIP_CONSDATA* consdata;
    3290
    3291 assert(cons != NULL);
    3292
    3293 if( SCIPconsIsDeleted(cons) )
    3294 continue;
    3295
    3296 consdata = SCIPconsGetData(cons);
    3297 assert(consdata != NULL);
    3298
    3299 /* prepare constraint by removing fixings and merge it; we invalidate the presolved flag, because the calls to
    3300 * SCIPcleanupCliques() in this loop may have lead to fixed variables that are not yet removed */
    3301 consdata->presolved = FALSE;
    3302 SCIP_CALL( prepareCons(scip, cons, eventhdlr, entries, nentries, &redundant, nfixedvars, nchgcoefs, ndelconss, cutoff) );
    3303
    3304 if( redundant )
    3305 {
    3306 assert(SCIPconsIsDeleted(cons));
    3307 continue;
    3308 }
    3309
    3310 if( *cutoff )
    3311 goto TERMINATE;
    3312
    3313 assert(consdata->nvars >= 2);
    3314
    3315 /* do not try to shorten too long constraints */
    3316 if( consdata->nvars > MAX_CONSLENGTH )
    3317 continue;
    3318
    3319 /* form necessary data */
    3320 for( v = consdata->nvars - 1; v >= 0; --v)
    3321 {
    3322 var = consdata->vars[v];
    3323 assert(var != NULL);
    3325
    3326 if( SCIPvarIsActive(var) )
    3327 {
    3328 probvars[v] = var;
    3329 bounds[v] = 1.0;
    3330 boundtypes[v] = FALSE;
    3331 }
    3332 else
    3333 {
    3334 probvars[v] = SCIPvarGetNegationVar(var);
    3335 bounds[v] = 0.0;
    3336 boundtypes[v] = TRUE;
    3337 }
    3338 }
    3339
    3340 SCIP_CALL( SCIPcleanupCliques(scip, cutoff) );
    3341
    3342 if( *cutoff )
    3343 goto TERMINATE;
    3344
    3345 /* use implications and cliques to derive global fixings and to shrink the number of variables in this constraints */
    3346 SCIP_CALL( SCIPshrinkDisjunctiveVarSet(scip, probvars, bounds, boundtypes, redundants, consdata->nvars, &nredvars,
    3347 nfixedvars, &redundant, cutoff, TRUE) );
    3348
    3349 if( *cutoff )
    3350 {
    3351 /* reset redundants array to FALSE */
    3352 BMSclearMemoryArray(redundants, nbinprobvars);
    3353 goto TERMINATE;
    3354 }
    3355
    3356 /* remove redundant constraint */
    3357 if( redundant )
    3358 {
    3359 SCIP_CALL( SCIPdelCons(scip, cons) );
    3360 ++(*ndelconss);
    3361
    3362 /* reset redundants array to FALSE */
    3363 BMSclearMemoryArray(redundants, consdata->nvars);
    3364 continue;
    3365 }
    3366
    3367 /* remove redundant variables */
    3368 if( nredvars > 0 )
    3369 {
    3370 for( v = consdata->nvars - 1; v >= 0; --v )
    3371 {
    3372 if( redundants[v] )
    3373 {
    3374 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    3375
    3376 /* reset entry to FALSE */
    3377 redundants[v] = FALSE;
    3378 }
    3379 }
    3380 *nchgcoefs += nredvars;
    3381
    3382 /* if only one variable is left over fix it */
    3383 if( consdata->nvars == 1 )
    3384 {
    3385 SCIP_Bool infeasible;
    3386 SCIP_Bool fixed;
    3387
    3388 SCIPdebugMsg(scip, " -> fix last remaining variable and delete constraint\n");
    3389
    3390 SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], 1.0, &infeasible, &fixed) );
    3391 assert(!infeasible);
    3392 assert(fixed);
    3393 ++(*nfixedvars);
    3394
    3395 SCIP_CALL( SCIPdelCons(scip, cons) );
    3396 ++(*ndelconss);
    3397 }
    3398 /* @todo might also upgrade a two variable constraint to a set-packing constraint */
    3399 }
    3400 }
    3401
    3402 /* invalidate the presolved flags, because the calls to SCIPcleanupCliques() may have lead to fixed variables that
    3403 * are not yet removed */
    3404 for( c = nconss - 1; c >= 0; --c )
    3405 {
    3406 SCIP_CONS* cons = conss[c];
    3407 SCIP_CONSDATA* consdata;
    3408
    3409 assert(cons != NULL);
    3410
    3411 consdata = SCIPconsGetData(cons);
    3412 assert(consdata != NULL);
    3413
    3414 consdata->presolved = FALSE;
    3415 }
    3416
    3417 TERMINATE:
    3418 /* free temporary memory */
    3419 SCIPfreeCleanBufferArray(scip, &redundants);
    3420 SCIPfreeBufferArray(scip, &boundtypes);
    3421 SCIPfreeBufferArray(scip, &bounds);
    3422 SCIPfreeBufferArray(scip, &probvars);
    3423
    3424 return SCIP_OKAY;
    3425}
    3426
    3427#define MAXCOMPARISONS 1000000
    3428
    3429/** try to find a negated clique in a constraint which makes this constraint redundant but we need to keep the negated
    3430 * clique information alive, so we create a corresponding set-packing constraint
    3431 */
    3432static
    3434 SCIP* scip, /**< SCIP data structure */
    3435 SCIP_CONSHDLR* conshdlr, /**< logicor constraint handler */
    3436 SCIP_CONSHDLR* conshdlrsetppc, /**< setppc constraint handler, or NULL */
    3437 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    3438 SCIP_CONS** conss, /**< all constraints */
    3439 int nconss, /**< number of constraints */
    3440 unsigned char** entries, /**< array to store whether two positions in constraints represent the same
    3441 * variable */
    3442 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
    3443 int* nfixedvars, /**< pointer to count number of fixings */
    3444 int* ndelconss, /**< pointer to count number of deleted constraints */
    3445 int* nupgdconss, /**< pointer to count number of upgraded constraints */
    3446 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
    3447 SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
    3448 )
    3449{
    3450 SCIP_CONSHDLRDATA* conshdlrdata;
    3451 SCIP_CONS* cons;
    3452 SCIP_CONSDATA* consdata;
    3453 SCIP_VAR** repvars;
    3454 SCIP_Bool* negated;
    3455 SCIP_VAR* var1;
    3456 SCIP_Bool redundant;
    3457 int c;
    3458 int size;
    3459 int maxcomppercons;
    3460 int comppercons;
    3461
    3462 assert(scip != NULL);
    3463 assert(conshdlr != NULL);
    3464 assert(eventhdlr != NULL);
    3465 assert(conss != NULL || nconss == 0);
    3466 assert(entries != NULL);
    3467 assert(*entries != NULL);
    3468 assert(nentries != NULL);
    3469 assert(nfixedvars != NULL);
    3470 assert(ndelconss != NULL);
    3471 assert(nupgdconss != NULL);
    3472 assert(nchgcoefs != NULL);
    3473 assert(cutoff != NULL);
    3474
    3475 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3476 assert(conshdlrdata != NULL);
    3477
    3478 if( nconss == 0 )
    3479 return SCIP_OKAY;
    3480
    3481 if( SCIPgetNCliques(scip) == conshdlrdata->nlastcliquesneg && SCIPgetNImplications(scip) == conshdlrdata->nlastimplsneg )
    3482 return SCIP_OKAY;
    3483
    3484 conshdlrdata->nlastcliquesneg = SCIPgetNCliques(scip);
    3485 conshdlrdata->nlastimplsneg = SCIPgetNImplications(scip);
    3486
    3487 /* estimate the maximal number of variables in a logicor constraint */
    3489 if( size <= 0 )
    3490 return SCIP_OKAY;
    3491
    3492 /* temporary memory for active/negation of active variables */
    3493 SCIP_CALL( SCIPallocBufferArray(scip, &repvars, size) );
    3494 SCIP_CALL( SCIPallocBufferArray(scip, &negated, size) );
    3495
    3496 /* iterate over all constraints and try to find negated cliques in logicors */
    3497 for( c = nconss - 1; c >= 0; --c )
    3498 {
    3499 int v;
    3500
    3501 assert(conss != NULL); /* for flexelint */
    3502
    3503 cons = conss[c];
    3504 assert(cons != NULL);
    3505
    3506 if( !SCIPconsIsActive(cons) )
    3507 continue;
    3508
    3509 /* prepare constraint by removing fixings and merge it */
    3510 SCIP_CALL( prepareCons(scip, cons, eventhdlr, entries, nentries, &redundant, nfixedvars, nchgcoefs, ndelconss, cutoff) );
    3511
    3512 if( redundant )
    3513 {
    3514 assert(SCIPconsIsDeleted(cons));
    3515 continue;
    3516 }
    3517
    3518 if( *cutoff )
    3519 goto TERMINATE;
    3520
    3521 consdata = SCIPconsGetData(cons);
    3522 assert(consdata != NULL);
    3523 assert(consdata->nvars >= 2);
    3524 assert(consdata->nvars <= size);
    3525 assert(consdata->presolved);
    3526
    3527 if( SCIPconsIsModifiable(cons) && consdata->nvars == 2 )
    3528 continue;
    3529
    3530 if( c % 100 == 0 && SCIPisStopped(scip) )
    3531 break;
    3532
    3533 maxcomppercons = MAXCOMPARISONS / nconss;
    3534 comppercons = 0;
    3535
    3536 BMScopyMemoryArray(repvars, consdata->vars, consdata->nvars);
    3537
    3538 /* all variables should be active or negative active variables, otherwise something went wrong with applyFixings()
    3539 * called before mergeMultiples()
    3540 */
    3541 for( v = consdata->nvars - 1; v >= 0; --v )
    3542 {
    3543 assert(SCIPvarIsActive(repvars[v]) || (SCIPvarGetStatus(repvars[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v]))));
    3544 negated[v] = SCIPvarIsNegated(repvars[v]);
    3545 }
    3546
    3547 for( v = consdata->nvars - 1; v > 0; --v )
    3548 {
    3549 SCIP_Bool breakloop;
    3550 SCIP_Bool neg1;
    3551 int w;
    3552
    3553 var1 = repvars[v];
    3554
    3555 /* if there is no negated variable, there can't be a negated clique */
    3556 if( SCIPvarGetNegatedVar(var1) == NULL )
    3557 continue;
    3558
    3559 /* get active counterpart to check for common cliques */
    3561 {
    3562 var1 = SCIPvarGetNegatedVar(var1);
    3563 neg1 = TRUE;
    3564 }
    3565 else
    3566 neg1 = FALSE;
    3567
    3568 if( !SCIPvarIsActive(var1) )
    3569 continue;
    3570
    3571 /* no cliques available */
    3572 if( SCIPvarGetNCliques(var1, neg1) == 0 && SCIPvarGetNImpls(var1, neg1) == 0 )
    3573 continue;
    3574
    3575 comppercons += (v - 1);
    3576
    3577 breakloop = FALSE;
    3578
    3579 for( w = v - 1; w >= 0; --w )
    3580 {
    3581 SCIP_VAR* var2;
    3582 SCIP_Bool neg2;
    3583
    3584 var2 = repvars[w];
    3585
    3586 /* if there is no negated variable, there can't be a negated clique */
    3587 if( SCIPvarGetNegatedVar(var2) == NULL )
    3588 continue;
    3589
    3591 {
    3592 var2 = SCIPvarGetNegatedVar(var2);
    3593 neg2 = TRUE;
    3594 }
    3595 else
    3596 neg2 = FALSE;
    3597
    3598 if( !SCIPvarIsActive(var2) )
    3599 continue;
    3600
    3601 /* no cliques available */
    3602 if( SCIPvarGetNCliques(var2, neg2) == 0 && SCIPvarGetNImpls(var2, neg2) == 0 )
    3603 continue;
    3604
    3605 /* check if both active variable are the same */
    3606 if( var1 == var2 )
    3607 {
    3608 if( neg1 != neg2 )
    3609 {
    3610 SCIPdebugMsg(scip, "logicor constraint <%s> is redundant, because variable <%s> and its negation <%s> exist\n",
    3611 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
    3612
    3613 SCIP_CALL( SCIPdelCons(scip, cons) );
    3614
    3615 breakloop = TRUE;
    3616 }
    3617 else
    3618 {
    3619 #ifndef NDEBUG
    3620 SCIP_VAR* lastvar = consdata->vars[consdata->nvars - 1];
    3621 #endif
    3622 SCIPdebugMsg(scip, "in logicor constraint <%s>, active variable of <%s> and active variable of <%s> are the same, removing the first\n",
    3623 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[v]), SCIPvarGetName(consdata->vars[w]));
    3624
    3625 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    3626
    3627 if( v < consdata->nvars )
    3628 {
    3629 /* delCoefPos replaces the variable on position v with the last one, so w also need to correct the
    3630 * negated array the same way, and because of deletion the number of variables is already decreased
    3631 */
    3632 assert(consdata->vars[v] == lastvar);
    3633 negated[v] = negated[consdata->nvars];
    3634 }
    3635 ++(*nchgcoefs);
    3636 }
    3637 break;
    3638 }
    3639
    3640 if( conshdlrsetppc != NULL && SCIPconsGetNUpgradeLocks(cons) == 0
    3641 && SCIPvarsHaveCommonClique(var1, neg1, var2, neg2, TRUE) )
    3642 {
    3643 SCIP_CONS* newcons;
    3644 SCIP_VAR* vars[2];
    3645
    3646 /* this negated clique information could be created out of this logicor constraint even if there are more
    3647 * than two variables left (, for example by probing), we need to keep this information by creating a
    3648 * setppc constraint instead
    3649 */
    3650
    3651 /* get correct variables */
    3652 if( !neg1 )
    3653 vars[0] = SCIPvarGetNegatedVar(var1);
    3654 else
    3655 vars[0] = var1;
    3656
    3657 if( !neg2 )
    3658 vars[1] = SCIPvarGetNegatedVar(var2);
    3659 else
    3660 vars[1] = var2;
    3661
    3662 SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, SCIPconsGetName(cons), 2, vars,
    3667
    3668 SCIPdebugPrintCons(scip, newcons, NULL);
    3669 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &newcons) );
    3670
    3671 SCIPdebugMsg(scip, "logicor constraint <%s> is redundant due to negated clique information and will be replaced by a setppc constraint \n",
    3672 SCIPconsGetName(cons));
    3673 SCIPdebugMsg(scip, "variable <%s> and variable <%s> are in a negated clique\n", SCIPvarGetName(consdata->vars[v]), SCIPvarGetName(consdata->vars[w]));
    3674
    3675 SCIP_CALL( SCIPdelCons(scip, cons) );
    3676 ++(*nupgdconss);
    3677
    3678 breakloop = TRUE;
    3679 break;
    3680 }
    3681 }
    3682 if( breakloop )
    3683 break;
    3684
    3685 /* do not do to many comparisons */
    3686 if( comppercons > maxcomppercons )
    3687 break;
    3688 }
    3689 }
    3690
    3691 TERMINATE:
    3692 /* free temporary memory */
    3693 SCIPfreeBufferArray(scip, &negated);
    3694 SCIPfreeBufferArray(scip, &repvars);
    3695
    3696 return SCIP_OKAY;
    3697}
    3698
    3699/** handle all cases with less than three variables in a logicor constraint
    3700 *
    3701 * in case a constraint has zero variables left, we detected infeasibility
    3702 * in case a constraint has one variables left, we will fix it to one
    3703 * in case a constraint has two variables left, we will add the implication and upgrade it to a set-packing constraint
    3704 */
    3705static
    3707 SCIP* scip, /**< SCIP data structure */
    3708 SCIP_CONS* cons, /**< logic or constraint */
    3709 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    3710 SCIP_CONSHDLR* conshdlrlinear, /**< linear constraint handler, or NULL */
    3711 SCIP_CONSHDLR* conshdlrsetppc, /**< setppc constraint handler, or NULL */
    3712 int* nfixedvars, /**< pointer to count number of fixings */
    3713 int* nchgbds, /**< pointer to count number of tightened bounds */
    3714 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
    3715 int* ndelconss, /**< pointer to count number of deleted constraints */
    3716 int* naddconss, /**< pointer to count number of added constraints */
    3717 int* nupgdconss, /**< pointer to count number of upgraded constraints */
    3718 SCIP_Bool* cutoff /**< pointer to store TRUE, if the node can be cut off */
    3719 )
    3720{
    3721 SCIP_CONSDATA* consdata;
    3722 SCIP_Bool infeasible;
    3723 SCIP_Bool fixed;
    3724
    3725 assert(scip != NULL);
    3726 assert(cons != NULL);
    3727 assert(eventhdlr != NULL);
    3728 assert(nfixedvars != NULL);
    3729 assert(nchgbds != NULL);
    3730 assert(nchgcoefs != NULL);
    3731 assert(ndelconss != NULL);
    3732 assert(naddconss != NULL);
    3733 assert(nupgdconss != NULL);
    3734 assert(cutoff != NULL);
    3735
    3736 *cutoff = FALSE;
    3737
    3738 if( SCIPconsIsModifiable(cons) )
    3739 return SCIP_OKAY;
    3740
    3741 consdata = SCIPconsGetData(cons);
    3742 assert(consdata != NULL);
    3743
    3744 /* if an unmodifiable logicor constraint has only two variables, we can add an implication and we will upgrade this
    3745 * constraint to a set-packing constraint
    3746 */
    3747 if( consdata->nvars == 2 )
    3748 {
    3749 /* add implication if not yet done */
    3750 if( !consdata->impladded )
    3751 {
    3752 SCIP_Bool implinfeasible;
    3753 int nimplbdchgs;
    3754 SCIP_Bool values[2];
    3755
    3756 values[0] = FALSE;
    3757 values[1] = FALSE;
    3758 /* a two-variable logicor constraint x + y >= 1 yields the implication x == 0 -> y == 1, and is represented
    3759 * by the clique inequality ~x + ~y <= 1
    3760 */
    3761 SCIP_CALL( SCIPaddClique(scip, consdata->vars, values, consdata->nvars, FALSE, &implinfeasible, &nimplbdchgs) );
    3762 *nchgbds += nimplbdchgs;
    3763 if( implinfeasible )
    3764 {
    3765 *cutoff = TRUE;
    3766 return SCIP_OKAY;
    3767 }
    3768
    3769 /* adding the above implication could lead to fixings, which render the constraint redundant */
    3770 if ( nimplbdchgs > 0 )
    3771 {
    3772 SCIP_Bool redundant;
    3773
    3774 /* remove all variables that are fixed to zero, check redundancy due to fixed-to-one variable */
    3775 SCIP_CALL( applyFixings(scip, cons, eventhdlr, &redundant, nchgcoefs, naddconss, ndelconss) );
    3776 assert(!SCIPconsIsDeleted(cons));
    3777
    3778 if( redundant )
    3779 {
    3780 SCIPdebugMsg(scip, "logic or constraint <%s> is redundant\n", SCIPconsGetName(cons));
    3781
    3782 SCIP_CALL( SCIPdelCons(scip, cons) );
    3783 (*ndelconss)++;
    3784
    3785 return SCIP_OKAY;
    3786 }
    3787 }
    3788 consdata->impladded = TRUE;
    3789 }
    3790
    3791 /* still we have two variables left, we will upgrade this constraint */
    3792 if( conshdlrsetppc != NULL && SCIPconsGetNUpgradeLocks(cons) == 0 && consdata->nvars == 2 )
    3793 {
    3794 SCIP_CONS* newcons;
    3795 SCIP_VAR* vars[2];
    3796
    3797 /* get correct variables */
    3798 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[0], &vars[0]) );
    3799 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[1], &vars[1]) );
    3800
    3801 SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, SCIPconsGetName(cons), 2, vars,
    3806
    3807 SCIPdebugPrintCons(scip, newcons, NULL);
    3808 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &newcons) );
    3809
    3810 SCIPdebugMsg(scip, "logicor constraint <%s> was upgraded to a set-packing constraint\n", SCIPconsGetName(cons));
    3811
    3812 SCIP_CALL( SCIPdelCons(scip, cons) );
    3813 ++(*nupgdconss);
    3814 }
    3815 }
    3816
    3817 /* if unmodifiable constraint has no variables, it is infeasible,
    3818 * if unmodifiable constraint has only one variable, this one can be fixed and the constraint deleted
    3819 */
    3820 if( consdata->nvars == 0 )
    3821 {
    3822 SCIPdebugMsg(scip, "logic or constraint <%s> is infeasible\n", SCIPconsGetName(cons));
    3823
    3824 *cutoff = TRUE;
    3825 }
    3826 else if( consdata->nvars == 1 )
    3827 {
    3828 SCIPdebugMsg(scip, "logic or constraint <%s> has only one variable not fixed to 0.0\n",
    3829 SCIPconsGetName(cons));
    3830
    3831 assert(consdata->vars != NULL);
    3832 assert(consdata->vars[0] != NULL);
    3833
    3834 if( SCIPvarGetStatus(consdata->vars[0]) != SCIP_VARSTATUS_MULTAGGR )
    3835 {
    3836 SCIPdebugMsg(scip, " -> fix variable and delete constraint\n");
    3837
    3838 SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], 1.0, &infeasible, &fixed) );
    3839 if( infeasible )
    3840 {
    3841 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    3842
    3843 *cutoff = TRUE;
    3844 return SCIP_OKAY;
    3845 }
    3846 if( fixed )
    3847 (*nfixedvars)++;
    3848
    3849 SCIP_CALL( SCIPdelCons(scip, cons) );
    3850 (*ndelconss)++;
    3851 }
    3852 else if( conshdlrlinear != NULL )
    3853 {
    3854 SCIP_Real coef;
    3855 SCIP_CONS* conslinear;
    3856 char consname[SCIP_MAXSTRLEN];
    3857
    3858 SCIPdebugMsg(scip, " -> variable is multi-aggregated, convert to linear constraint <%s> == 1 \n",
    3859 SCIPvarGetName(consdata->vars[0]));
    3860
    3861 coef = 1.0;
    3862 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "fixmaggr_%s_%s", SCIPconsGetName(cons),SCIPvarGetName(consdata->vars[0]) );
    3863 SCIP_CALL( SCIPcreateConsLinear(scip, &conslinear, consname, 1, consdata->vars, &coef, 1.0, 1.0,
    3867 SCIPconsIsStickingAtNode(cons)) );
    3868
    3869 /* add the downgraded constraint to the problem */
    3870 SCIP_CALL( SCIPaddCons(scip, conslinear) );
    3871 SCIP_CALL( SCIPreleaseCons(scip, &conslinear) );
    3872 SCIP_CALL( SCIPdelCons(scip, cons) );
    3873
    3874 (*ndelconss)++;
    3875 (*naddconss)++;
    3876 }
    3877 }
    3878
    3879 return SCIP_OKAY;
    3880}
    3881
    3882
    3883/*
    3884 * upgrading of linear constraints
    3885 */
    3886
    3887/** creates and captures a normalized (with all coefficients +1) logic or constraint */
    3888static
    3890 SCIP* scip, /**< SCIP data structure */
    3891 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    3892 const char* name, /**< name of constraint */
    3893 int nvars, /**< number of variables in the constraint */
    3894 SCIP_VAR** vars, /**< array with variables of constraint entries */
    3895 SCIP_Real* vals, /**< array with coefficients (+1.0 or -1.0) */
    3896 int mult, /**< multiplier on the coefficients(+1 or -1) */
    3897 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
    3898 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    3899 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
    3900 * Usually set to TRUE. */
    3901 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    3902 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    3903 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    3904 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    3905 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
    3906 * Usually set to TRUE. */
    3907 SCIP_Bool local, /**< is constraint only valid locally?
    3908 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    3909 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
    3910 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
    3911 * adds coefficients to this constraint. */
    3912 SCIP_Bool dynamic, /**< is constraint subject to aging?
    3913 * Usually set to FALSE. Set to TRUE for own cuts which
    3914 * are separated as constraints. */
    3915 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
    3916 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
    3917 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    3918 * if it may be moved to a more global node?
    3919 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
    3920 )
    3921{
    3922 SCIP_VAR** transvars;
    3923 int v;
    3924
    3925 assert(nvars == 0 || vars != NULL);
    3926 assert(nvars == 0 || vals != NULL);
    3927 assert(mult == +1 || mult == -1);
    3928
    3929 /* get temporary memory */
    3930 SCIP_CALL( SCIPallocBufferArray(scip, &transvars, nvars) );
    3931
    3932 /* negate positive or negative variables */
    3933 for( v = 0; v < nvars; ++v )
    3934 {
    3935 if( mult * vals[v] > 0.0 )
    3936 transvars[v] = vars[v];
    3937 else
    3938 {
    3939 SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &transvars[v]) );
    3940 }
    3941 assert(transvars[v] != NULL);
    3942 }
    3943
    3944 /* create the constraint */
    3945 SCIP_CALL( SCIPcreateConsLogicor(scip, cons, name, nvars, transvars,
    3946 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    3947
    3948 /* free temporary memory */
    3949 SCIPfreeBufferArray(scip, &transvars);
    3950
    3951 return SCIP_OKAY;
    3952}
    3953
    3954static
    3955SCIP_DECL_LINCONSUPGD(linconsUpgdLogicor)
    3956{ /*lint --e{715}*/
    3957 assert(upgdcons != NULL);
    3958
    3959 /* check, if linear constraint can be upgraded to logic or constraint
    3960 * - logic or constraints consist only of binary variables with a
    3961 * coefficient of +1.0 or -1.0 (variables with -1.0 coefficients can be negated):
    3962 * lhs <= x1 + ... + xp - y1 - ... - yn <= rhs
    3963 * - negating all variables y = (1-Y) with negative coefficients gives:
    3964 * lhs + n <= x1 + ... + xp + Y1 + ... + Yn <= rhs + n
    3965 * - negating all variables x = (1-X) with positive coefficients and multiplying with -1 gives:
    3966 * p - rhs <= X1 + ... + Xp + y1 + ... + yn <= p - lhs
    3967 * - logic or constraints have left hand side of +1.0, and right hand side of +infinity: x(S) >= 1.0
    3968 * -> without negations: (lhs == 1 - n and rhs == +inf) or (lhs == -inf and rhs = p - 1)
    3969 */
    3970 if( nvars > 2 && nposbin + nnegbin + nposimplbin + nnegimplbin == nvars && ncoeffspone + ncoeffsnone == nvars
    3971 && ((SCIPisEQ(scip, lhs, 1.0 - ncoeffsnone) && SCIPisInfinity(scip, rhs))
    3972 || (SCIPisInfinity(scip, -lhs) && SCIPisEQ(scip, rhs, ncoeffspone - 1.0))) )
    3973 {
    3974 int mult;
    3975
    3976 SCIPdebugMsg(scip, "upgrading constraint <%s> to logic or constraint\n", SCIPconsGetName(cons));
    3977
    3978 /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
    3979 mult = SCIPisInfinity(scip, rhs) ? +1 : -1;
    3980
    3981 /* create the logic or constraint (an automatically upgraded constraint is always unmodifiable) */
    3982 assert(!SCIPconsIsModifiable(cons));
    3983 SCIP_CALL( createNormalizedLogicor(scip, upgdcons, SCIPconsGetName(cons), nvars, vars, vals, mult,
    3988 }
    3989
    3990 return SCIP_OKAY;
    3991}
    3992
    3993/** helper function to enforce constraints */
    3994static
    3996 SCIP* scip, /**< SCIP data structure */
    3997 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    3998 SCIP_CONS** conss, /**< constraints to process */
    3999 int nconss, /**< number of constraints */
    4000 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
    4001 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
    4002 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
    4003 )
    4004{
    4005 SCIP_CONSHDLRDATA* conshdlrdata;
    4006 SCIP_Bool cutoff;
    4007 SCIP_Bool separated;
    4008 SCIP_Bool reduceddom;
    4009 int c;
    4010
    4011 assert(conshdlr != NULL);
    4012 assert(nconss == 0 || conss != NULL);
    4013 assert(result != NULL);
    4014
    4016
    4017 SCIPdebugMsg(scip, "Enforcing %d logic or constraints for %s solution\n", nconss, sol == NULL ? "LP" : "relaxation");
    4018
    4019 *result = SCIP_FEASIBLE;
    4020
    4021 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4022 assert(conshdlrdata != NULL);
    4023
    4024 cutoff = FALSE;
    4025 separated = FALSE;
    4026 reduceddom = FALSE;
    4027
    4028 /* check all useful logic or constraints for feasibility */
    4029 for( c = 0; c < nusefulconss && !cutoff && !reduceddom; ++c )
    4030 {
    4031 SCIP_CALL( separateCons(scip, conss[c], sol, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
    4032 }
    4033
    4034 /* check all obsolete logic or constraints for feasibility */
    4035 for( c = nusefulconss; c < nconss && !cutoff && !separated && !reduceddom; ++c )
    4036 {
    4037 SCIP_CALL( separateCons(scip, conss[c], sol, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
    4038 }
    4039
    4040 /* return the correct result */
    4041 if( cutoff )
    4042 *result = SCIP_CUTOFF;
    4043 else if( separated )
    4044 *result = SCIP_SEPARATED;
    4045 else if( reduceddom )
    4046 *result = SCIP_REDUCEDDOM;
    4047
    4048 return SCIP_OKAY;
    4049}
    4050
    4051/** adds symmetry information of constraint to a symmetry detection graph */
    4052static
    4054 SCIP* scip, /**< SCIP pointer */
    4055 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
    4056 SCIP_CONS* cons, /**< constraint */
    4057 SYM_GRAPH* graph, /**< symmetry detection graph */
    4058 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
    4059 )
    4060{
    4061 SCIP_CONSDATA* consdata;
    4062 SCIP_VAR** logicorvars;
    4063 SCIP_VAR** vars;
    4064 SCIP_Real* vals;
    4065 SCIP_Real constant = 0.0;
    4066 int nlocvars;
    4067 int nvars;
    4068 int i;
    4069
    4070 assert(scip != NULL);
    4071 assert(cons != NULL);
    4072 assert(graph != NULL);
    4073 assert(success != NULL);
    4074
    4075 consdata = SCIPconsGetData(cons);
    4076 assert(consdata != NULL);
    4077
    4078 /* get active variables of the constraint */
    4079 nvars = SCIPgetNVars(scip);
    4080 nlocvars = SCIPgetNVarsLogicor(scip, cons);
    4081
    4082 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    4083 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
    4084
    4085 logicorvars = SCIPgetVarsLogicor(scip, cons);
    4086 for( i = 0; i < consdata->nvars; ++i )
    4087 {
    4088 vars[i] = logicorvars[i];
    4089 vals[i] = 1.0;
    4090 }
    4091
    4092 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
    4093
    4094 SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars,
    4095 cons, 1.0 - constant, SCIPinfinity(scip), success) );
    4096
    4097 SCIPfreeBufferArray(scip, &vals);
    4098 SCIPfreeBufferArray(scip, &vars);
    4099
    4100 return SCIP_OKAY;
    4101}
    4102
    4103/*
    4104 * Callback methods of constraint handler
    4105 */
    4106
    4107/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    4108static
    4109SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLogicor)
    4110{ /*lint --e{715}*/
    4111 assert(scip != NULL);
    4112 assert(conshdlr != NULL);
    4113
    4115
    4116 /* call inclusion method of constraint handler */
    4118
    4119 *valid = TRUE;
    4120
    4121 return SCIP_OKAY;
    4122}
    4123
    4124/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
    4125static
    4126SCIP_DECL_CONSFREE(consFreeLogicor)
    4127{ /*lint --e{715}*/
    4128 SCIP_CONSHDLRDATA* conshdlrdata;
    4129
    4130 assert(conshdlr != NULL);
    4131 assert(scip != NULL);
    4132
    4134
    4135 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4136 assert(conshdlrdata != NULL);
    4137
    4138 /* free constraint handler data */
    4139 conshdlrdataFree(scip, &conshdlrdata);
    4140
    4141 SCIPconshdlrSetData(conshdlr, NULL);
    4142
    4143 return SCIP_OKAY;
    4144}
    4145
    4146
    4147/** presolving initialization method of constraint handler (called when presolving is about to begin) */
    4148static
    4149SCIP_DECL_CONSINITPRE(consInitpreLogicor)
    4150{ /*lint --e{715}*/
    4151 SCIP_CONSHDLRDATA* conshdlrdata;
    4152 SCIP_CONSDATA* consdata;
    4153 int c;
    4154 int v;
    4155
    4156 assert(conshdlr != NULL);
    4157 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4158 assert(conshdlrdata != NULL);
    4159
    4160 conshdlrdata->nlastcliquesneg = 0;
    4161 conshdlrdata->nlastimplsneg = 0;
    4162 conshdlrdata->nlastcliquesshorten = 0;
    4163 conshdlrdata->nlastimplsshorten = 0;
    4164
    4165 /* catch all variable event for deleted variables, which is only used in presolving */
    4166 for( c = nconss - 1; c >= 0; --c )
    4167 {
    4168 consdata = SCIPconsGetData(conss[c]);
    4169 assert(consdata != NULL);
    4170
    4171 for( v = consdata->nvars - 1; v >= 0; --v )
    4172 {
    4173 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
    4174 (SCIP_EVENTDATA*)conss[c], NULL) );
    4175 }
    4176 }
    4177
    4178 return SCIP_OKAY;
    4179}
    4180
    4181/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
    4182static
    4183SCIP_DECL_CONSEXITPRE(consExitpreLogicor)
    4184{ /*lint --e{715}*/
    4185 SCIP_CONSHDLRDATA* conshdlrdata;
    4186 SCIP_CONSDATA* consdata;
    4187 int nchgcoefs = 0;
    4188 int c;
    4189 int v;
    4190
    4191 assert(conshdlr != NULL);
    4192 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4193 assert(conshdlrdata != NULL);
    4194
    4195 /* drop all variable event for deleted variables, which was only used in presolving */
    4196 for( c = 0; c < nconss; ++c )
    4197 {
    4198 consdata = SCIPconsGetData(conss[c]);
    4199 assert(consdata != NULL);
    4200
    4201 for( v = 0; v < consdata->nvars; ++v )
    4202 {
    4203 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
    4204 (SCIP_EVENTDATA*)conss[c], -1) );
    4205 }
    4206
    4207 if( !SCIPconsIsDeleted(conss[c]) && !consdata->presolved )
    4208 {
    4209 SCIP_Bool redundant;
    4210
    4211 /* we are not allowed to detect infeasibility in the exitpre stage */
    4212 SCIP_CALL( applyFixings(scip, conss[c], conshdlrdata->eventhdlr, &redundant, &nchgcoefs, NULL, NULL) );
    4213
    4214 /* it may happen that a constraint still contains variables that are fixed to one; for example, this happens
    4215 * when variable fixings have been detected in the last presolving round by some other plugins (see #2941)
    4216 */
    4217 if( redundant )
    4218 {
    4219 SCIPdebugMsg(scip, "logic or constraint <%s> is redundant (detected during EXITPRE)\n", SCIPconsGetName(conss[c]));
    4220
    4221 if( SCIPconsIsAdded(conss[c]) )
    4222 {
    4223 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
    4224 }
    4225 else
    4226 {
    4227 /* we set the presolved flag to FALSE since not all fixing are removed if redundancy is detected */
    4228 consdata->presolved = FALSE;
    4229 }
    4230 }
    4231 }
    4232 }
    4233
    4234 return SCIP_OKAY;
    4235}
    4236
    4237/** solving process initialization method of constraint handler */
    4238static
    4239SCIP_DECL_CONSINITSOL(consInitsolLogicor)
    4240{ /*lint --e{715}*/
    4241 /* add nlrow representation to NLP, if NLP had been constructed */
    4243 {
    4244 int c;
    4245 for( c = 0; c < nconss; ++c )
    4246 {
    4247 SCIP_CALL( addNlrow(scip, conss[c]) );
    4248 }
    4249 }
    4250
    4251 return SCIP_OKAY;
    4252}
    4253
    4254/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
    4255static
    4256SCIP_DECL_CONSEXITSOL(consExitsolLogicor)
    4257{ /*lint --e{715}*/
    4258 SCIP_CONSDATA* consdata;
    4259 int c;
    4260
    4261 /* release the rows and nlrows of all constraints */
    4262 for( c = 0; c < nconss; ++c )
    4263 {
    4264 consdata = SCIPconsGetData(conss[c]);
    4265 assert(consdata != NULL);
    4266
    4267 if( consdata->row != NULL )
    4268 {
    4269 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
    4270 }
    4271
    4272 if( consdata->nlrow != NULL )
    4273 {
    4274 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
    4275 }
    4276 }
    4277
    4278 return SCIP_OKAY;
    4279}
    4280
    4281
    4282/** frees specific constraint data */
    4283static
    4284SCIP_DECL_CONSDELETE(consDeleteLogicor)
    4285{ /*lint --e{715}*/
    4286 assert(conshdlr != NULL);
    4287 assert(consdata != NULL);
    4288 assert(*consdata != NULL);
    4289
    4291
    4293 {
    4294 SCIP_CONSHDLRDATA* conshdlrdata;
    4295 int v;
    4296
    4297 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4298 assert(conshdlrdata != NULL);
    4299
    4300 for( v = (*consdata)->nvars - 1; v >= 0; --v )
    4301 {
    4302 SCIP_CALL( SCIPdropVarEvent(scip, (*consdata)->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
    4303 (SCIP_EVENTDATA*)cons, -1) );
    4304 }
    4305 }
    4306
    4307 /* free LP row and logic or constraint */
    4308 SCIP_CALL( consdataFree(scip, consdata) );
    4309
    4310 return SCIP_OKAY;
    4311}
    4312
    4313
    4314/** transforms constraint data into data belonging to the transformed problem */
    4315static
    4316SCIP_DECL_CONSTRANS(consTransLogicor)
    4317{ /*lint --e{715}*/
    4318 SCIP_CONSDATA* sourcedata;
    4319 SCIP_CONSDATA* targetdata;
    4320
    4321 /*debugMsg(scip, "Trans method of logic or constraints\n");*/
    4322
    4323 assert(conshdlr != NULL);
    4325 assert(sourcecons != NULL);
    4326 assert(targetcons != NULL);
    4327
    4329
    4330 sourcedata = SCIPconsGetData(sourcecons);
    4331 assert(sourcedata != NULL);
    4332 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
    4333
    4334 /* create constraint data for target constraint */
    4335 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars) );
    4336
    4337 /* create target constraint */
    4338 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
    4339 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
    4340 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
    4341 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
    4342 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
    4343
    4344 return SCIP_OKAY;
    4345}
    4346
    4347
    4348/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
    4349static
    4350SCIP_DECL_CONSINITLP(consInitlpLogicor)
    4351{ /*lint --e{715}*/
    4352 int c;
    4353
    4354 *infeasible = FALSE;
    4355
    4356 for( c = 0; c < nconss && !(*infeasible); ++c )
    4357 {
    4358 assert(SCIPconsIsInitial(conss[c]));
    4359 SCIP_CALL( addCut(scip, conss[c], infeasible) );
    4360 }
    4361
    4362 return SCIP_OKAY;
    4363}
    4364
    4365
    4366/** separation method of constraint handler for LP solutions */
    4367static
    4368SCIP_DECL_CONSSEPALP(consSepalpLogicor)
    4369{ /*lint --e{715}*/
    4370 SCIP_CONSHDLRDATA* conshdlrdata;
    4371 SCIP_Bool cutoff;
    4372 SCIP_Bool separated;
    4373 SCIP_Bool reduceddom;
    4374 int c;
    4375
    4376 assert(conshdlr != NULL);
    4377 assert(nconss == 0 || conss != NULL);
    4378 assert(result != NULL);
    4379
    4381
    4382 SCIPdebugMsg(scip, "separating %d/%d logic or constraints\n", nusefulconss, nconss);
    4383
    4384 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4385 assert(conshdlrdata != NULL);
    4386
    4387 cutoff = FALSE;
    4388 separated = FALSE;
    4389 reduceddom = FALSE;
    4390
    4391 /* check all useful logic or constraints for feasibility */
    4392 for( c = 0; c < nusefulconss && !cutoff; ++c )
    4393 {
    4394 SCIP_CALL( separateCons(scip, conss[c], NULL, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
    4395 }
    4396
    4397 /* combine logic or constraints to get more cuts */
    4398 /**@todo further cuts of logic or constraints */
    4399
    4400 /* return the correct result */
    4401 if( cutoff )
    4402 *result = SCIP_CUTOFF;
    4403 else if( reduceddom )
    4404 *result = SCIP_REDUCEDDOM;
    4405 else if( separated )
    4406 *result = SCIP_SEPARATED;
    4407 else
    4408 *result = SCIP_DIDNOTFIND;
    4409
    4410 return SCIP_OKAY;
    4411}
    4412
    4413
    4414/** separation method of constraint handler for arbitrary primal solutions */
    4415static
    4416SCIP_DECL_CONSSEPASOL(consSepasolLogicor)
    4417{ /*lint --e{715}*/
    4418 SCIP_CONSHDLRDATA* conshdlrdata;
    4419 SCIP_Bool cutoff;
    4420 SCIP_Bool separated;
    4421 SCIP_Bool reduceddom;
    4422 int c;
    4423
    4424 assert(conshdlr != NULL);
    4425 assert(nconss == 0 || conss != NULL);
    4426 assert(result != NULL);
    4427
    4429
    4430 SCIPdebugMsg(scip, "separating %d/%d logic or constraints\n", nusefulconss, nconss);
    4431
    4432 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4433 assert(conshdlrdata != NULL);
    4434
    4435 cutoff = FALSE;
    4436 separated = FALSE;
    4437 reduceddom = FALSE;
    4438
    4439 /* check all useful logic or constraints for feasibility */
    4440 for( c = 0; c < nusefulconss && !cutoff; ++c )
    4441 {
    4442 SCIP_CALL( separateCons(scip, conss[c], sol, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
    4443 }
    4444
    4445 /* combine logic or constraints to get more cuts */
    4446 /**@todo further cuts of logic or constraints */
    4447
    4448 /* return the correct result */
    4449 if( cutoff )
    4450 *result = SCIP_CUTOFF;
    4451 else if( reduceddom )
    4452 *result = SCIP_REDUCEDDOM;
    4453 else if( separated )
    4454 *result = SCIP_SEPARATED;
    4455 else
    4456 *result = SCIP_DIDNOTFIND;
    4457
    4458 return SCIP_OKAY;
    4459}
    4460
    4461
    4462/** constraint enforcing method of constraint handler for LP solutions */
    4463static
    4464SCIP_DECL_CONSENFOLP(consEnfolpLogicor)
    4465{ /*lint --e{715}*/
    4466 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
    4467
    4468 return SCIP_OKAY;
    4469}
    4470
    4471
    4472/** constraint enforcing method of constraint handler for relaxation solutions */
    4473static
    4474SCIP_DECL_CONSENFORELAX(consEnforelaxLogicor)
    4475{ /*lint --e{715}*/
    4476 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
    4477
    4478 return SCIP_OKAY;
    4479}
    4480
    4481
    4482/** constraint enforcing method of constraint handler for pseudo solutions */
    4483static
    4484SCIP_DECL_CONSENFOPS(consEnfopsLogicor)
    4485{ /*lint --e{715}*/
    4486 SCIP_CONSHDLRDATA* conshdlrdata;
    4487 SCIP_Bool cutoff;
    4488 SCIP_Bool infeasible;
    4489 SCIP_Bool reduceddom;
    4490 SCIP_Bool solvelp;
    4491 int c;
    4492
    4493 assert(conshdlr != NULL);
    4494 assert(nconss == 0 || conss != NULL);
    4495 assert(result != NULL);
    4496
    4498
    4499 SCIPdebugMsg(scip, "pseudo enforcing %d logic or constraints\n", nconss);
    4500
    4501 *result = SCIP_FEASIBLE;
    4502
    4503 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4504 assert(conshdlrdata != NULL);
    4505
    4506 cutoff = FALSE;
    4507 infeasible = FALSE;
    4508 reduceddom = FALSE;
    4509 solvelp = FALSE;
    4510
    4511 /* check all logic or constraints for feasibility */
    4512 for( c = 0; c < nconss && !cutoff && !reduceddom && !solvelp; ++c )
    4513 {
    4514 SCIP_CALL( enforcePseudo(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &infeasible, &reduceddom, &solvelp) );
    4515 }
    4516
    4517 if( cutoff )
    4518 *result = SCIP_CUTOFF;
    4519 else if( reduceddom )
    4520 *result = SCIP_REDUCEDDOM;
    4521 else if( solvelp )
    4522 *result = SCIP_SOLVELP;
    4523 else if( infeasible )
    4524 *result = SCIP_INFEASIBLE;
    4525
    4526 return SCIP_OKAY;
    4527}
    4528
    4529
    4530/** feasibility check method of constraint handler for integral solutions */
    4531static
    4532SCIP_DECL_CONSCHECK(consCheckLogicor)
    4533{ /*lint --e{715}*/
    4534 SCIP_CONS* cons;
    4535 SCIP_CONSDATA* consdata;
    4536 int c;
    4537
    4538 assert(conshdlr != NULL);
    4539 assert(nconss == 0 || conss != NULL);
    4540 assert(result != NULL);
    4541
    4543
    4544 *result = SCIP_FEASIBLE;
    4545
    4546 /* check all logic or constraints for feasibility */
    4547 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
    4548 {
    4549 cons = conss[c];
    4550 consdata = SCIPconsGetData(cons);
    4551 assert(consdata != NULL);
    4552 if( checklprows || consdata->row == NULL || !SCIProwIsInLP(consdata->row) )
    4553 {
    4554 if( isConsViolated(scip, cons, sol) )
    4555 {
    4556 /* constraint is violated */
    4557 *result = SCIP_INFEASIBLE;
    4558
    4559 if( printreason )
    4560 {
    4561#ifndef NDEBUG
    4562 int v;
    4563 for( v = 0; v < consdata->nvars; ++v )
    4564 {
    4565 assert( consdata->vars[v] != NULL);
    4566 assert( SCIPvarIsBinary(consdata->vars[v]) );
    4567 assert( SCIPisFeasLT(scip, SCIPgetSolVal(scip, sol, consdata->vars[v]), 1.0) );
    4568 }
    4569#endif
    4570 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
    4571 SCIPinfoMessage(scip, NULL, ";\n");
    4572 SCIPinfoMessage(scip, NULL, "violation: all variables are set to zero\n");
    4573 }
    4574 }
    4575 }
    4576 }
    4577
    4578 return SCIP_OKAY;
    4579}
    4580
    4581
    4582/** domain propagation method of constraint handler */
    4583static
    4584SCIP_DECL_CONSPROP(consPropLogicor)
    4585{ /*lint --e{715}*/
    4586 SCIP_CONSHDLRDATA* conshdlrdata;
    4587 SCIP_Bool cutoff;
    4588 SCIP_Bool reduceddom;
    4589 SCIP_Bool addcut;
    4590 SCIP_Bool mustcheck;
    4591 int c;
    4592#ifndef NDEBUG
    4594#endif
    4595
    4596 assert(conshdlr != NULL);
    4597 assert(nconss == 0 || conss != NULL);
    4598 assert(result != NULL);
    4599
    4601
    4602 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4603 assert(conshdlrdata != NULL);
    4604
    4605 cutoff = FALSE;
    4606 reduceddom = FALSE;
    4607
    4608 /* propagate all useful logic or constraints */
    4609 for( c = 0; c < nusefulconss && !cutoff; ++c )
    4610 {
    4611 assert(inpresolve || !(SCIPconsGetData(conss[c])->existmultaggr));
    4612
    4613 SCIPdebugMsg(scip, " propagate constraint %s\n", SCIPconsGetName(conss[c]));
    4614 SCIP_CALL( processWatchedVars(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &reduceddom, &addcut, &mustcheck) );
    4615 }
    4616
    4617 /* return the correct result */
    4618 if( cutoff )
    4619 *result = SCIP_CUTOFF;
    4620 else if( reduceddom )
    4621 *result = SCIP_REDUCEDDOM;
    4622 else
    4623 *result = SCIP_DIDNOTFIND;
    4624
    4625 return SCIP_OKAY; /*lint !e438*/
    4626}
    4627
    4628/** presolving method of constraint handler */
    4629static
    4630SCIP_DECL_CONSPRESOL(consPresolLogicor)
    4631{ /*lint --e{715}*/
    4632 SCIP_CONSHDLRDATA* conshdlrdata;
    4633 SCIP_CONS* cons;
    4634 SCIP_CONSDATA* consdata;
    4635 unsigned char* entries;
    4636 SCIP_Bool redundant;
    4637 int c;
    4638 int firstchange;
    4639 int nentries;
    4640 int oldnfixedvars;
    4641 int oldnchgbds;
    4642 int oldndelconss;
    4643 int oldnupgdconss;
    4644 int oldnchgcoefs;
    4645
    4646 assert(conshdlr != NULL);
    4647 assert(scip != NULL);
    4648 assert(result != NULL);
    4649
    4651
    4652 *result = SCIP_DIDNOTFIND;
    4653
    4654 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4655 assert(conshdlrdata != NULL);
    4656
    4657 nentries = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
    4658
    4659 oldnfixedvars = *nfixedvars;
    4660 oldnchgbds = *nchgbds;
    4661 oldndelconss = *ndelconss;
    4662 oldnupgdconss = *nupgdconss;
    4663 oldnchgcoefs = *nchgcoefs;
    4664
    4665 firstchange = INT_MAX;
    4666
    4667 SCIP_CALL( SCIPallocBufferArray(scip, &entries, nentries) );
    4668
    4669 /* process constraints */
    4670 for( c = 0; c < nconss && *result != SCIP_CUTOFF && !SCIPisStopped(scip); ++c )
    4671 {
    4672 cons = conss[c];
    4673 assert(cons != NULL);
    4674 consdata = SCIPconsGetData(cons);
    4675 assert(consdata != NULL);
    4676
    4677 SCIPdebugMsg(scip, "presolving logic or constraint <%s>\n", SCIPconsGetName(cons));
    4678
    4679 /* force presolving the constraint in the initial round */
    4680 if( nrounds == 0 )
    4681 {
    4683 }
    4684
    4685 redundant = FALSE;
    4686 if( !consdata->presolved )
    4687 {
    4688 /* remove all variables that are fixed to zero, check redundancy due to fixed-to-one variable */
    4689 SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, &redundant, nchgcoefs, naddconss, ndelconss) );
    4690 }
    4691
    4692 if( SCIPconsIsDeleted(cons) )
    4693 continue;
    4694
    4695 /* find pairs of negated variables in constraint: constraint is redundant */
    4696 /* find sets of equal variables in constraint: multiple entries of variable can be replaced by single entry */
    4697 if( !redundant )
    4698 {
    4699 SCIP_CALL( mergeMultiples(scip, cons, conshdlrdata->eventhdlr, &entries, &nentries, &redundant, nchgcoefs) );
    4700 }
    4701
    4702 if( redundant )
    4703 {
    4704 SCIPdebugMsg(scip, "logic or constraint <%s> is redundant\n", SCIPconsGetName(cons));
    4705 SCIP_CALL( SCIPdelCons(scip, cons) );
    4706 (*ndelconss)++;
    4707 *result = SCIP_SUCCESS;
    4708 continue;
    4709 }
    4710 else if( !SCIPconsIsModifiable(cons) )
    4711 {
    4712 if( consdata->nvars <= 2 )
    4713 {
    4714 SCIP_Bool cutoff;
    4715
    4716 /* handle all cases with less than three variables in a logicor constraint */
    4717 SCIP_CALL( fixDeleteOrUpgradeCons(scip, cons, conshdlrdata->eventhdlr, conshdlrdata->conshdlrlinear,
    4718 conshdlrdata->conshdlrsetppc, nfixedvars, nchgbds, nchgcoefs, ndelconss, naddconss, nupgdconss, &cutoff) );
    4719
    4720 if( cutoff )
    4721 {
    4722 *result = SCIP_CUTOFF;
    4723 goto TERMINATE;
    4724 }
    4725 else if( *nfixedvars > oldnfixedvars || *nchgbds > oldnchgbds || *nchgcoefs > oldnchgcoefs
    4726 || *ndelconss > oldndelconss || *nupgdconss > oldnupgdconss )
    4727 *result = SCIP_SUCCESS;
    4728
    4729 if( SCIPconsIsDeleted(cons) )
    4730 continue;
    4731 }
    4732 }
    4733
    4734 /* perform dual reductions */
    4735 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
    4736 {
    4737 SCIP_CALL( dualPresolving(scip, cons, conshdlrdata->eventhdlr, nfixedvars, ndelconss, nchgcoefs, naggrvars, result) );
    4738
    4739 /* if dual reduction deleted the constraint we take the next */
    4740 if( !SCIPconsIsActive(cons) )
    4741 continue;
    4742
    4743 /* in dualpresolving we may have removed variables, so we need to take care of special cases */
    4744 if( consdata->nvars <= 2 )
    4745 {
    4746 SCIP_Bool cutoff;
    4747
    4748 /* handle all cases with less than three variables in a logicor constraint */
    4749 SCIP_CALL( fixDeleteOrUpgradeCons(scip, cons, conshdlrdata->eventhdlr, conshdlrdata->conshdlrlinear,
    4750 conshdlrdata->conshdlrsetppc, nfixedvars, nchgbds, nchgcoefs, ndelconss, naddconss, nupgdconss, &cutoff) );
    4751
    4752 if( cutoff )
    4753 {
    4754 *result = SCIP_CUTOFF;
    4755 goto TERMINATE;
    4756 }
    4757 else if( *nfixedvars > oldnfixedvars || *nchgbds > oldnchgbds || *nchgcoefs > oldnchgcoefs
    4758 || *ndelconss > oldndelconss || *nupgdconss > oldnupgdconss )
    4759 *result = SCIP_SUCCESS;
    4760
    4761 if( SCIPconsIsDeleted(cons) )
    4762 continue;
    4763 }
    4764 }
    4765
    4766 /* remember the first changed constraint to begin the next redundancy round with */
    4767 if( firstchange == INT_MAX && consdata->changed )
    4768 firstchange = c;
    4769
    4770 assert(consdata->nvars >= 2 || SCIPconsIsModifiable(cons));
    4771 }
    4772
    4773 assert(*result != SCIP_CUTOFF);
    4774
    4775 /* fast preprocessing of pairs of logic or constraints, used for equal constraints */
    4776 if( firstchange < nconss && conshdlrdata->presolusehashing )
    4777 {
    4778 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
    4779 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, ndelconss) );
    4780 }
    4781
    4782 /* preprocess pairs of logic or constraints and apply negated clique presolving */
    4784 {
    4785 SCIP_Bool cutoff = FALSE;
    4786
    4787 /* check constraints for redundancy */
    4788 if( conshdlrdata->presolpairwise && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
    4789 {
    4790 SCIP_CALL( removeRedundantConssAndNonzeros(scip, conss, nconss, &entries, &nentries, conshdlrdata->eventhdlr,
    4791 conshdlrdata->usestrengthening, &firstchange, nfixedvars, ndelconss, nchgcoefs, &cutoff) );
    4792
    4793 if( cutoff )
    4794 {
    4795 *result = SCIP_CUTOFF;
    4796 goto TERMINATE;
    4797 }
    4798 }
    4799
    4801 {
    4802 /* try to tighten constraints by reducing the number of variables in the constraints using implications and
    4803 * cliques, also derive fixations through them, @see SCIPshrinkDisjunctiveVarSet()
    4804 */
    4805 if( conshdlrdata->useimplications && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
    4806 {
    4807 SCIP_CALL( shortenConss(scip, conshdlrdata, conshdlrdata->eventhdlr, conss, nconss,
    4808 &entries, &nentries, nfixedvars, ndelconss, nchgcoefs, &cutoff) );
    4809
    4810 if( cutoff )
    4811 {
    4812 *result = SCIP_CUTOFF;
    4813 goto TERMINATE;
    4814 }
    4815 }
    4816
    4817 /* check for redundant constraints due to negated clique information */
    4818 if( conshdlrdata->usenegatedclique && (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0 )
    4819 {
    4820 SCIP_CALL( removeConstraintsDueToNegCliques(scip, conshdlr, conshdlrdata->conshdlrsetppc,
    4821 conshdlrdata->eventhdlr, conss, nconss, &entries, &nentries, nfixedvars, ndelconss,
    4822 nupgdconss, nchgcoefs, &cutoff) );
    4823
    4824 if( cutoff )
    4825 {
    4826 *result = SCIP_CUTOFF;
    4827 goto TERMINATE;
    4828 }
    4829 }
    4830 }
    4831 }
    4832
    4833 TERMINATE:
    4834
    4835 SCIPfreeBufferArray(scip, &entries);
    4836
    4837 return SCIP_OKAY;
    4838}
    4839
    4840
    4841/** propagation conflict resolving method of constraint handler */
    4842static
    4843SCIP_DECL_CONSRESPROP(consRespropLogicor)
    4844{ /*lint --e{715}*/
    4845 SCIP_CONSDATA* consdata;
    4846#ifndef NDEBUG
    4847 SCIP_Bool infervarfound;
    4848#endif
    4849 int v;
    4850
    4851 assert(conshdlr != NULL);
    4852 assert(cons != NULL);
    4853 assert(infervar != NULL);
    4854 assert(result != NULL);
    4855
    4857
    4858 consdata = SCIPconsGetData(cons);
    4859 assert(consdata != NULL);
    4860
    4861 SCIPdebugMsg(scip, "conflict resolving method of logic or constraint handler\n");
    4862
    4863 /* the only deductions are variables inferred to 1.0 on logic or constraints where all other variables
    4864 * are assigned to zero
    4865 */
    4866 assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5); /* the inference variable must be assigned to one */
    4867
    4868#ifndef NDEBUG
    4869 infervarfound = FALSE;
    4870#endif
    4871 for( v = 0; v < consdata->nvars; ++v )
    4872 {
    4873 if( consdata->vars[v] != infervar )
    4874 {
    4875 /* the reason variable must have been assigned to zero */
    4876 assert(SCIPgetVarUbAtIndex(scip, consdata->vars[v], bdchgidx, FALSE) < 0.5);
    4877 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
    4878 }
    4879#ifndef NDEBUG
    4880 else
    4881 {
    4882 assert(!infervarfound);
    4883 infervarfound = TRUE;
    4884 }
    4885#endif
    4886 }
    4887 assert(infervarfound);
    4888
    4889 *result = SCIP_SUCCESS;
    4890
    4891 return SCIP_OKAY;
    4892}
    4893
    4894
    4895/** variable rounding lock method of constraint handler */
    4896static
    4897SCIP_DECL_CONSLOCK(consLockLogicor)
    4898{ /*lint --e{715}*/
    4899 SCIP_CONSDATA* consdata;
    4900 int i;
    4901
    4902 consdata = SCIPconsGetData(cons);
    4903 assert(consdata != NULL);
    4904
    4905 /* lock every single coefficient */
    4906 for( i = 0; i < consdata->nvars; ++i )
    4907 {
    4908 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
    4909 }
    4910
    4911 return SCIP_OKAY;
    4912}
    4913
    4914
    4915/** constraint activation notification method of constraint handler */
    4916static
    4917SCIP_DECL_CONSACTIVE(consActiveLogicor)
    4918{ /*lint --e{715}*/
    4919 SCIP_CONSHDLRDATA* conshdlrdata;
    4920 SCIP_CONSDATA* consdata;
    4921
    4922 assert(conshdlr != NULL);
    4923 assert(cons != NULL);
    4924 assert(SCIPconsIsTransformed(cons));
    4925
    4927
    4928 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4929 assert(conshdlrdata != NULL);
    4930 consdata = SCIPconsGetData(cons);
    4931 assert(consdata != NULL);
    4932 assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
    4933
    4934 SCIPdebugMsg(scip, "activating information for logic or constraint <%s>\n", SCIPconsGetName(cons));
    4935 SCIPdebug( SCIP_CALL( consdataPrint(scip, consdata, NULL, TRUE) ) );
    4936
    4937 /* catch events on watched variables */
    4938 if( consdata->watchedvar1 != -1 )
    4939 {
    4940 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[consdata->watchedvar1],
    4941 SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
    4942 &consdata->filterpos1) );
    4943 }
    4944 if( consdata->watchedvar2 != -1 )
    4945 {
    4946 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[consdata->watchedvar2],
    4947 SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
    4948 &consdata->filterpos2) );
    4949 }
    4950
    4952 {
    4953 SCIP_CALL( addNlrow(scip, cons) );
    4954 }
    4955
    4956 return SCIP_OKAY;
    4957}
    4958
    4959
    4960/** constraint deactivation notification method of constraint handler */
    4961static
    4962SCIP_DECL_CONSDEACTIVE(consDeactiveLogicor)
    4963{ /*lint --e{715}*/
    4964 SCIP_CONSHDLRDATA* conshdlrdata;
    4965 SCIP_CONSDATA* consdata;
    4966
    4967 assert(conshdlr != NULL);
    4968 assert(cons != NULL);
    4969 assert(SCIPconsIsTransformed(cons));
    4970
    4972
    4973 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4974 assert(conshdlrdata != NULL);
    4975 consdata = SCIPconsGetData(cons);
    4976 assert(consdata != NULL);
    4977 assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
    4978
    4979 SCIPdebugMsg(scip, "deactivating information for logic or constraint <%s>\n", SCIPconsGetName(cons));
    4980 SCIPdebug( SCIP_CALL( consdataPrint(scip, consdata, NULL, TRUE) ) );
    4981
    4982 /* drop events on watched variables */
    4983 if( consdata->watchedvar1 != -1 )
    4984 {
    4985 assert(consdata->filterpos1 != -1);
    4986 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar1],
    4987 SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
    4988 consdata->filterpos1) );
    4989 consdata->watchedvar1 = -1;
    4990 consdata->filterpos1 = -1;
    4991 }
    4992 if( consdata->watchedvar2 != -1 )
    4993 {
    4994 assert(consdata->filterpos2 != -1);
    4995 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar2],
    4996 SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
    4997 consdata->filterpos2) );
    4998 consdata->watchedvar2 = -1;
    4999 consdata->filterpos2 = -1;
    5000 }
    5001
    5002 /* remove row from NLP, if still in solving
    5003 * if we are in exitsolve, the whole NLP will be freed anyway
    5004 */
    5005 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
    5006 {
    5007 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
    5008 }
    5009
    5010 return SCIP_OKAY;
    5011}
    5012
    5013
    5014/** constraint display method of constraint handler */
    5015static
    5016SCIP_DECL_CONSPRINT(consPrintLogicor)
    5017{ /*lint --e{715}*/
    5018 assert( scip != NULL );
    5019 assert( conshdlr != NULL );
    5020 assert( cons != NULL );
    5021
    5023
    5024 return SCIP_OKAY;
    5025}
    5026
    5027/** constraint copying method of constraint handler */
    5028static
    5029SCIP_DECL_CONSCOPY(consCopyLogicor)
    5030{ /*lint --e{715}*/
    5031 SCIP_CONSHDLRDATA* conshdlrdata;
    5032 SCIP_VAR** sourcevars;
    5033 const char* consname;
    5034 int nvars;
    5035
    5036 assert(scip != NULL);
    5037 assert(sourcescip != NULL);
    5038 assert(sourcecons != NULL);
    5039 assert(valid != NULL);
    5040
    5041 conshdlrdata = SCIPconshdlrGetData(sourceconshdlr);
    5042 assert(conshdlrdata != NULL);
    5043
    5044 /* get variables of the source constraint */
    5045 sourcevars = SCIPgetVarsLogicor(sourcescip, sourcecons);
    5046 nvars = SCIPgetNVarsLogicor(sourcescip, sourcecons);
    5047
    5048 if( conshdlrdata->copytypedcons )
    5049 {
    5050 SCIP_VAR** targetvars;
    5051 int v;
    5052
    5053 *valid = TRUE;
    5054 assert(nvars >= 0);
    5055
    5056 /* allocate target variable array */
    5057 SCIP_CALL( SCIPallocBufferArray(scip, &targetvars, nvars) );
    5058
    5059 /* map source variables to target variables */
    5060 for( v = 0; v < nvars && *valid; ++v )
    5061 {
    5062 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &targetvars[v], varmap, consmap, global, valid) );
    5063 assert(!(*valid) || targetvars[v] != NULL);
    5064 }
    5065
    5066 /* only create the target constraint if all variables were successfully copied */
    5067 if( *valid )
    5068 {
    5069 if( name != NULL )
    5070 consname = name;
    5071 else
    5072 consname = SCIPconsGetName(sourcecons);
    5073
    5074 SCIP_CALL( SCIPcreateConsLogicor(scip, cons, consname, nvars, targetvars,
    5075 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    5076 }
    5077
    5078 SCIPfreeBufferArray(scip, &targetvars);
    5079 }
    5080 else
    5081 {
    5082 if( name != NULL )
    5083 consname = name;
    5084 else
    5085 consname = SCIPconsGetName(sourcecons);
    5086
    5087 /* copy the logic using the linear constraint copy method */
    5088 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, NULL,
    5089 1.0, SCIPinfinity(scip), varmap, consmap,
    5090 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
    5091 assert(cons != NULL);
    5092 }
    5093
    5094 return SCIP_OKAY;
    5095}
    5096
    5097/** constraint parsing method of constraint handler */
    5098static
    5099SCIP_DECL_CONSPARSE(consParseLogicor)
    5100{ /*lint --e{715}*/
    5101 SCIP_VAR** vars;
    5102 char* strcopy;
    5103 char* endptr;
    5104 char* startptr;
    5105 int requiredsize;
    5106 int varssize;
    5107 int nvars;
    5108
    5109 SCIPdebugMsg(scip, "parse <%s> as logicor constraint\n", str);
    5110
    5111 *success = FALSE;
    5112
    5113 /* cutoff "logicor" from the constraint string */
    5114 startptr = strchr((char*)str, '(');
    5115
    5116 if( startptr == NULL )
    5117 {
    5118 SCIPerrorMessage("missing starting character '(' parsing logicor\n");
    5119 return SCIP_OKAY;
    5120 }
    5121
    5122 /* skip '(' */
    5123 ++startptr;
    5124
    5125 /* find end character ')' */
    5126 endptr = strrchr(startptr, ')');
    5127
    5128 if( endptr == NULL )
    5129 {
    5130 SCIPerrorMessage("missing ending character ')' parsing logicor\n");
    5131 return SCIP_OKAY;
    5132 }
    5133 assert(endptr >= startptr);
    5134
    5135 if( endptr > startptr )
    5136 {
    5137 /* copy string for parsing; note that SCIPskipSpace() in SCIPparseVarsList() requires that strcopy ends with '\0' */
    5138 SCIP_CALL( SCIPduplicateBufferArray(scip, &strcopy, startptr, (int)(endptr-startptr+1)) );
    5139 strcopy[endptr-startptr] = '\0';
    5140 varssize = 100;
    5141 nvars = 0;
    5142
    5143 /* allocate buffer array for variables */
    5144 SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
    5145
    5146 /* parse string */
    5147 SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
    5148
    5149 if( *success )
    5150 {
    5151 /* check if the size of the variable array was great enough */
    5152 if( varssize < requiredsize )
    5153 {
    5154 /* reallocate memory */
    5155 varssize = requiredsize;
    5156 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
    5157
    5158 /* parse string again with the correct size of the variable array */
    5159 SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
    5160 }
    5161
    5162 assert(*success);
    5163 assert(varssize >= requiredsize);
    5164
    5165 /* create logicor constraint */
    5166 SCIP_CALL( SCIPcreateConsLogicor(scip, cons, name, nvars, vars,
    5167 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    5168 }
    5169
    5170 /* free buffers */
    5171 SCIPfreeBufferArray(scip, &vars);
    5172 SCIPfreeBufferArray(scip, &strcopy);
    5173 }
    5174 else
    5175 {
    5176 if( !modifiable )
    5177 {
    5178 SCIPerrorMessage("cannot create empty logicor constraint\n");
    5179 return SCIP_OKAY;
    5180 }
    5181
    5182 /* create empty logicor constraint */
    5183 SCIP_CALL( SCIPcreateConsLogicor(scip, cons, name, 0, NULL,
    5184 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    5185
    5186 *success = TRUE;
    5187 }
    5188
    5189 return SCIP_OKAY;
    5190}
    5191
    5192/** constraint method of constraint handler which returns the variables (if possible) */
    5193static
    5194SCIP_DECL_CONSGETVARS(consGetVarsLogicor)
    5195{ /*lint --e{715}*/
    5196 SCIP_CONSDATA* consdata;
    5197
    5198 consdata = SCIPconsGetData(cons);
    5199 assert(consdata != NULL);
    5200
    5201 if( varssize < consdata->nvars )
    5202 (*success) = FALSE;
    5203 else
    5204 {
    5205 assert(vars != NULL);
    5206
    5207 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
    5208 (*success) = TRUE;
    5209 }
    5210
    5211 return SCIP_OKAY;
    5212}
    5213
    5214/** constraint method of constraint handler which returns the number of variables (if possible) */
    5215static
    5216SCIP_DECL_CONSGETNVARS(consGetNVarsLogicor)
    5217{ /*lint --e{715}*/
    5218 SCIP_CONSDATA* consdata;
    5219
    5220 consdata = SCIPconsGetData(cons);
    5221 assert(consdata != NULL);
    5222
    5223 (*nvars) = consdata->nvars;
    5224 (*success) = TRUE;
    5225
    5226 return SCIP_OKAY;
    5227}
    5228
    5229/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
    5230static
    5231SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLogicor)
    5232{ /*lint --e{715}*/
    5233 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
    5234
    5235 return SCIP_OKAY;
    5236}
    5237
    5238/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
    5239static
    5240SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLogicor)
    5241{ /*lint --e{715}*/
    5242 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
    5243
    5244 return SCIP_OKAY;
    5245}
    5246
    5247/*
    5248 * Callback methods of event handler
    5249 */
    5250
    5251static
    5252SCIP_DECL_EVENTEXEC(eventExecLogicor)
    5253{ /*lint --e{715}*/
    5254 assert(eventhdlr != NULL);
    5255 assert(eventdata != NULL);
    5256 assert(event != NULL);
    5257
    5259
    5260 SCIPdebugMsg(scip, "exec method of event handler for logic or constraints\n");
    5261
    5263 {
    5264 SCIPdebugMsg(scip, "enabling constraint cons <%s> at depth %d\n", SCIPconsGetName((SCIP_CONS*)eventdata), SCIPgetDepth(scip));
    5265
    5266 SCIP_CALL( SCIPenableCons(scip, (SCIP_CONS*)eventdata) );
    5268 }
    5269 else if( SCIPeventGetType(event) == SCIP_EVENTTYPE_UBTIGHTENED )
    5270 {
    5272 }
    5273
    5275 {
    5276 SCIP_VAR* var = SCIPeventGetVar(event);
    5277 SCIP_CONS* cons = (SCIP_CONS*)eventdata;
    5278 SCIP_CONSDATA* consdata;
    5279
    5280 assert(cons != NULL);
    5281 consdata = SCIPconsGetData(cons);
    5282 assert(consdata != NULL);
    5283
    5284 /* we only catch this event in presolving stage */
    5286 assert(var != NULL);
    5287
    5288 consdata->presolved = FALSE;
    5289
    5291 {
    5292 if( SCIPconsIsActive(cons) )
    5293 {
    5294 if( SCIPvarGetLbGlobal(var) < 0.5 && SCIPvarGetUbGlobal(var) > 0.5 )
    5295 consdata->merged = FALSE;
    5296
    5297 if( !consdata->existmultaggr )
    5298 {
    5300 consdata->existmultaggr = TRUE;
    5301 }
    5302 }
    5303 }
    5304 }
    5305
    5306 return SCIP_OKAY;
    5307}
    5308
    5309
    5310/*
    5311 * Callback methods of conflict handler
    5312 */
    5313
    5314/** conflict processing method of conflict handler (called when conflict was found) */
    5315static
    5316SCIP_DECL_CONFLICTEXEC(conflictExecLogicor)
    5317{ /*lint --e{715}*/
    5318 SCIP_VAR** vars;
    5319 int i;
    5320
    5321 assert(conflicthdlr != NULL);
    5322 assert(bdchginfos != NULL || nbdchginfos == 0);
    5323 assert(result != NULL);
    5324
    5326
    5327 *result = SCIP_DIDNOTRUN;
    5328
    5329 /* don't process already resolved conflicts */
    5330 if( resolved )
    5331 return SCIP_OKAY;
    5332
    5333 /* if the conflict consists of only two (binary) variables, it will be handled by the setppc conflict handler */
    5334 if( nbdchginfos == 2 )
    5335 return SCIP_OKAY;
    5336
    5337 *result = SCIP_DIDNOTFIND;
    5338
    5339 /* create array of variables in conflict constraint */
    5340 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
    5341 for( i = 0; i < nbdchginfos; ++i )
    5342 {
    5343 assert(bdchginfos != NULL); /* for flexelint */
    5344 assert(bdchginfos[i] != NULL);
    5345
    5346 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
    5347
    5348 /* we can only treat binary variables */
    5349 if( !SCIPvarIsBinary(vars[i]) )
    5350 break;
    5351
    5352 /* if the variable is fixed to one in the conflict set, we have to use its negation */
    5353 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) > 0.5 )
    5354 {
    5355 SCIP_CALL( SCIPgetNegatedVar(scip, vars[i], &vars[i]) );
    5356 }
    5357 }
    5358
    5359 if( i == nbdchginfos )
    5360 {
    5361 SCIP_CONS* cons;
    5362 char consname[SCIP_MAXSTRLEN];
    5363
    5364 /* create a constraint out of the conflict set */
    5366 SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, consname, nbdchginfos, vars,
    5367 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
    5368
    5369 /* add conflict to SCIP */
    5370 SCIP_CALL( SCIPaddConflict(scip, node, &cons, validnode, conftype, cutoffinvolved) );
    5371
    5372 *result = SCIP_CONSADDED;
    5373 }
    5374
    5375 /* free temporary memory */
    5376 SCIPfreeBufferArray(scip, &vars);
    5377
    5378 return SCIP_OKAY;
    5379}
    5380
    5381
    5382/*
    5383 * constraint specific interface methods
    5384 */
    5385
    5386/** creates the handler for logic or constraints and includes it in SCIP */
    5388 SCIP* scip /**< SCIP data structure */
    5389 )
    5390{
    5391 SCIP_CONSHDLRDATA* conshdlrdata;
    5392 SCIP_CONSHDLR* conshdlr;
    5393 SCIP_CONFLICTHDLR* conflicthdlr;
    5394 SCIP_EVENTHDLR* eventhdlr;
    5395
    5396 /* create event handler for events on watched variables */
    5398 eventExecLogicor, NULL) );
    5399
    5400 /* create conflict handler for logic or constraints */
    5402 conflictExecLogicor, NULL) );
    5403
    5404 /* create constraint handler data */
    5405 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
    5406
    5407 /* include constraint handler */
    5410 consEnfolpLogicor, consEnfopsLogicor, consCheckLogicor, consLockLogicor,
    5411 conshdlrdata) );
    5412 assert(conshdlr != NULL);
    5413
    5414 /* set non-fundamental callbacks via specific setter functions */
    5415 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLogicor) );
    5416 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLogicor, consCopyLogicor) );
    5417 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLogicor) );
    5418 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLogicor) );
    5419 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLogicor) );
    5420 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLogicor) );
    5421 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLogicor) );
    5422 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLogicor) );
    5423 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLogicor) );
    5424 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLogicor) );
    5425 SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreLogicor) );
    5426 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLogicor) );
    5427 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLogicor) );
    5429 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLogicor) );
    5432 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLogicor) );
    5433 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLogicor, consSepasolLogicor, CONSHDLR_SEPAFREQ,
    5435 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLogicor) );
    5436 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLogicor) );
    5437 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLogicor) );
    5438 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLogicor) );
    5439
    5440 conshdlrdata->conshdlrlinear = SCIPfindConshdlr(scip, "linear");
    5441 conshdlrdata->conshdlrsetppc = SCIPfindConshdlr(scip, "setppc");
    5442
    5443 if( conshdlrdata->conshdlrlinear != NULL )
    5444 {
    5445 /* include the linear constraint to logicor constraint upgrade in the linear constraint handler */
    5447 }
    5448
    5449 /* logic or constraint handler parameters */
    5451 "constraints/logicor/presolpairwise",
    5452 "should pairwise constraint comparison be performed in presolving?",
    5453 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
    5455 "constraints/logicor/presolusehashing",
    5456 "should hash table be used for detecting redundant constraints in advance",
    5457 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
    5459 "constraints/logicor/dualpresolving",
    5460 "should dual presolving steps be performed?",
    5461 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
    5463 "constraints/logicor/negatedclique",
    5464 "should negated clique information be used in presolving",
    5465 &conshdlrdata->usenegatedclique, TRUE, DEFAULT_NEGATEDCLIQUE, NULL, NULL) );
    5467 "constraints/logicor/implications",
    5468 "should implications/cliques be used in presolving",
    5469 &conshdlrdata->useimplications, TRUE, DEFAULT_IMPLICATIONS, NULL, NULL) );
    5471 "constraints/logicor/strengthen",
    5472 "should pairwise constraint comparison try to strengthen constraints by removing superflous non-zeros?",
    5473 &conshdlrdata->usestrengthening, TRUE, DEFAULT_STRENGTHEN, NULL, NULL) );
    5475 "constraints/" CONSHDLR_NAME "/copytypedcons",
    5476 "should logicor constraints be copied as logicor instead of as linear constraints?",
    5477 &conshdlrdata->copytypedcons, TRUE, DEFAULT_COPYTYPEDCONS, NULL, NULL) );
    5478
    5479 return SCIP_OKAY;
    5480}
    5481
    5482
    5483/** creates and captures a logic or constraint
    5484 *
    5485 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    5486 */
    5488 SCIP* scip, /**< SCIP data structure */
    5489 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    5490 const char* name, /**< name of constraint */
    5491 int nvars, /**< number of variables in the constraint */
    5492 SCIP_VAR** vars, /**< array with variables of constraint entries */
    5493 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
    5494 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    5495 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
    5496 * Usually set to TRUE. */
    5497 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    5498 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    5499 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    5500 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    5501 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
    5502 * Usually set to TRUE. */
    5503 SCIP_Bool local, /**< is constraint only valid locally?
    5504 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    5505 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
    5506 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
    5507 * adds coefficients to this constraint. */
    5508 SCIP_Bool dynamic, /**< is constraint subject to aging?
    5509 * Usually set to FALSE. Set to TRUE for own cuts which
    5510 * are separated as constraints. */
    5511 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
    5512 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
    5513 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    5514 * if it may be moved to a more global node?
    5515 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
    5516 )
    5517{
    5518 SCIP_CONSHDLR* conshdlr;
    5519 SCIP_CONSDATA* consdata;
    5520 int i;
    5521
    5522 assert(scip != NULL);
    5523
    5524 /* find the logicor constraint handler */
    5525 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    5526 if( conshdlr == NULL )
    5527 {
    5528 SCIPerrorMessage("logic or constraint handler not found\n");
    5529 return SCIP_INVALIDCALL;
    5530 }
    5531
    5532 /* check whether all variables are binary */
    5533 assert(vars != NULL || nvars == 0);
    5534 for( i = 0; i < nvars; ++i )
    5535 {
    5536 if( !SCIPvarIsBinary(vars[i]) )
    5537 {
    5538 SCIPerrorMessage("operand <%s> is not binary\n", SCIPvarGetName(vars[i]));
    5539 return SCIP_INVALIDDATA;
    5540 }
    5541 }
    5542
    5543 /* create the constraint specific data */
    5544 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars) );
    5545
    5546 /* create constraint */
    5547 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
    5548 local, modifiable, dynamic, removable, stickingatnode) );
    5549
    5551 {
    5552 SCIP_CONSHDLRDATA* conshdlrdata;
    5553 int v;
    5554
    5555 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    5556 assert(conshdlrdata != NULL);
    5557
    5558 for( v = consdata->nvars - 1; v >= 0; --v )
    5559 {
    5560 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
    5561 (SCIP_EVENTDATA*)(*cons), NULL) );
    5562 }
    5563 }
    5564
    5565 return SCIP_OKAY;
    5566}
    5567
    5568/** creates and captures a logicor constraint
    5569 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
    5570 * method SCIPcreateConsLogicor(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
    5571 *
    5572 * @see SCIPcreateConsLogicor() for information about the basic constraint flag configuration
    5573 *
    5574 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    5575 */
    5577 SCIP* scip, /**< SCIP data structure */
    5578 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    5579 const char* name, /**< name of constraint */
    5580 int nvars, /**< number of variables in the constraint */
    5581 SCIP_VAR** vars /**< array with variables of constraint entries */
    5582 )
    5583{
    5584 assert(scip != NULL);
    5585
    5586 SCIP_CALL( SCIPcreateConsLogicor(scip, cons, name, nvars, vars,
    5588
    5589 return SCIP_OKAY;
    5590}
    5591
    5592/** adds coefficient in logic or constraint */
    5594 SCIP* scip, /**< SCIP data structure */
    5595 SCIP_CONS* cons, /**< logicor constraint */
    5596 SCIP_VAR* var /**< variable to add to the constraint */
    5597 )
    5598{
    5599 assert(var != NULL);
    5600
    5601 /*debugMsg(scip, "adding variable <%s> to logicor constraint <%s>\n",
    5602 SCIPvarGetName(var), SCIPconsGetName(cons));*/
    5603
    5605
    5606 SCIP_CALL( addCoef(scip, cons, var) );
    5607
    5608 return SCIP_OKAY;
    5609}
    5610
    5611/** gets number of variables in logic or constraint */
    5613 SCIP* scip, /**< SCIP data structure */
    5614 SCIP_CONS* cons /**< constraint data */
    5615 )
    5616{
    5617 SCIP_CONSDATA* consdata;
    5618
    5619 assert(scip != NULL);
    5620
    5622
    5623 consdata = SCIPconsGetData(cons);
    5624 assert(consdata != NULL);
    5625
    5626 return consdata->nvars;
    5627}
    5628
    5629/** gets array of variables in logic or constraint */
    5631 SCIP* scip, /**< SCIP data structure */
    5632 SCIP_CONS* cons /**< constraint data */
    5633 )
    5634{
    5635 SCIP_CONSDATA* consdata;
    5636
    5637 assert(scip != NULL);
    5638
    5640
    5641 consdata = SCIPconsGetData(cons);
    5642 assert(consdata != NULL);
    5643
    5644 return consdata->vars;
    5645}
    5646
    5647/** gets the dual solution of the logic or constraint in the current LP */
    5649 SCIP* scip, /**< SCIP data structure */
    5650 SCIP_CONS* cons /**< constraint data */
    5651 )
    5652{
    5653 SCIP_CONSDATA* consdata;
    5654
    5655 assert(scip != NULL);
    5656
    5658
    5659 consdata = SCIPconsGetData(cons);
    5660 assert(consdata != NULL);
    5661
    5662 if( consdata->row != NULL )
    5663 return SCIProwGetDualsol(consdata->row);
    5664 else
    5665 return 0.0;
    5666}
    5667
    5668/** gets the dual Farkas value of the logic or constraint in the current infeasible LP */
    5670 SCIP* scip, /**< SCIP data structure */
    5671 SCIP_CONS* cons /**< constraint data */
    5672 )
    5673{
    5674 SCIP_CONSDATA* consdata;
    5675
    5676 assert(scip != NULL);
    5677
    5679
    5680 consdata = SCIPconsGetData(cons);
    5681 assert(consdata != NULL);
    5682
    5683 if( consdata->row != NULL )
    5684 return SCIProwGetDualfarkas(consdata->row);
    5685 else
    5686 return 0.0;
    5687}
    5688
    5689/** returns the linear relaxation of the given logic or constraint; may return NULL if no LP row was yet created;
    5690 * the user must not modify the row!
    5691 */
    5693 SCIP* scip, /**< SCIP data structure */
    5694 SCIP_CONS* cons /**< constraint data */
    5695 )
    5696{
    5697 SCIP_CONSDATA* consdata;
    5698
    5699 assert(scip != NULL);
    5700
    5702
    5703 consdata = SCIPconsGetData(cons);
    5704 assert(consdata != NULL);
    5705
    5706 return consdata->row;
    5707}
    5708
    5709/** creates and returns the row of the given logicor constraint */
    5711 SCIP* scip, /**< SCIP data structure */
    5712 SCIP_CONS* cons /**< constraint data */
    5713 )
    5714{
    5715 SCIP_CONSDATA* consdata;
    5716
    5717 assert(scip != NULL);
    5718
    5720
    5721 consdata = SCIPconsGetData(cons);
    5722 assert(consdata != NULL);
    5723 assert(consdata->row == NULL);
    5724
    5725 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), 1.0, SCIPinfinity(scip),
    5727
    5728 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->row, consdata->nvars, consdata->vars, 1.0) );
    5729
    5730 return SCIP_OKAY;
    5731}
    5732
    5733/** cleans up (multi-)aggregations and fixings from logicor constraints */
    5735 SCIP* scip, /**< SCIP data structure */
    5736 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
    5737 int* naddconss, /**< pointer to count number of added (linear) constraints */
    5738 int* ndelconss, /**< pointer to count number of deleted (logicor) constraints */
    5739 int* nchgcoefs /**< pointer to count number of changed coefficients */
    5740 )
    5741{
    5742 SCIP_CONSHDLR* conshdlr;
    5743 SCIP_EVENTHDLR* eventhdlr;
    5744 SCIP_CONS** conss;
    5745 unsigned char* entries;
    5746 int nconss;
    5747 int nentries;
    5748 int i;
    5749
    5750 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    5751 if( conshdlr == NULL )
    5752 return SCIP_OKAY;
    5753
    5754 assert(naddconss != NULL);
    5755 assert(ndelconss != NULL);
    5756 assert(nchgcoefs != NULL);
    5757
    5758 eventhdlr = SCIPconshdlrGetData(conshdlr)->eventhdlr;
    5759 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
    5760 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
    5761
    5762 nentries = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
    5763 SCIP_CALL( SCIPallocBufferArray(scip, &entries, nentries) );
    5764
    5765 /* loop backwards since then deleted constraints do not interfere with the loop */
    5766 for( i = nconss - 1; i >= 0; --i )
    5767 {
    5768 SCIP_CONS* cons;
    5769 SCIP_Bool redundant;
    5770
    5771 cons = conss[i];
    5772 redundant = FALSE;
    5773
    5774 SCIP_CALL( applyFixings(scip, cons, eventhdlr, &redundant, nchgcoefs, naddconss, ndelconss) );
    5775
    5776 if( SCIPconsIsDeleted(cons) )
    5777 continue;
    5778
    5779 /* merge constraint */
    5780 if( !redundant )
    5781 {
    5782 SCIP_CALL( mergeMultiples(scip, cons, eventhdlr, &entries, &nentries, &redundant, nchgcoefs) );
    5783 }
    5784
    5785 if( redundant )
    5786 {
    5787 SCIP_CALL( SCIPdelCons(scip, cons) );
    5788 ++(*ndelconss);
    5789 }
    5790 }
    5791
    5792 SCIPfreeBufferArray(scip, &entries);
    5793
    5794 return SCIP_OKAY;
    5795}
    SCIP_VAR * w
    Definition: circlepacking.c:67
    Constraint handler for linear constraints in their most general form, .
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLogicor)
    static SCIP_Bool isConsViolated(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
    static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_logicor.c:469
    static SCIP_DECL_HASHKEYVAL(hashKeyValLogicorcons)
    #define MAXCOMPARISONS
    #define DEFAULT_DUALPRESOLVING
    Definition: cons_logicor.c:100
    static SCIP_DECL_CONSENFOLP(consEnfolpLogicor)
    #define DEFAULT_IMPLICATIONS
    Definition: cons_logicor.c:103
    #define AGEINCREASE(n)
    Definition: cons_logicor.c:108
    #define CONSHDLR_NEEDSCONS
    Definition: cons_logicor.c:81
    #define CONSHDLR_SEPAFREQ
    Definition: cons_logicor.c:74
    #define CONFLICTHDLR_PRIORITY
    Definition: cons_logicor.c:93
    static void consdataCalcSignature(SCIP_CONSDATA *consdata)
    #define CONFLICTHDLR_NAME
    Definition: cons_logicor.c:91
    static SCIP_DECL_CONSEXITSOL(consExitsolLogicor)
    static SCIP_RETCODE addCut(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
    static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
    Definition: cons_logicor.c:539
    #define CONSHDLR_CHECKPRIORITY
    Definition: cons_logicor.c:73
    #define CONSHDLR_DESC
    Definition: cons_logicor.c:70
    #define DEFAULT_COPYTYPEDCONS
    Definition: cons_logicor.c:102
    static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
    static SCIP_RETCODE processWatchedVars(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, SCIP_Bool *reduceddom, SCIP_Bool *addcut, SCIP_Bool *mustcheck)
    static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons)
    static SCIP_DECL_CONSRESPROP(consRespropLogicor)
    static SCIP_DECL_CONSLOCK(consLockLogicor)
    #define CONSHDLR_PROP_TIMING
    Definition: cons_logicor.c:84
    static SCIP_RETCODE addConsToOccurList(SCIP *scip, SCIP_CONS *cons, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int *occurlistsizes, int *occurlistlength, int occurlistsize)
    #define CONFLICTHDLR_DESC
    Definition: cons_logicor.c:92
    static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
    Definition: cons_logicor.c:229
    static SCIP_RETCODE removeConstraintsDueToNegCliques(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLR *conshdlrsetppc, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS **conss, int nconss, unsigned char **entries, int *nentries, int *nfixedvars, int *ndelconss, int *nupgdconss, int *nchgcoefs, SCIP_Bool *cutoff)
    static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_logicor.c:191
    #define DEFAULT_STRENGTHEN
    Definition: cons_logicor.c:96
    static SCIP_DECL_CONSPRESOL(consPresolLogicor)
    static SCIP_DECL_CONSENFOPS(consEnfopsLogicor)
    #define MAX_CONSLENGTH
    static SCIP_DECL_CONSCHECK(consCheckLogicor)
    static SCIP_RETCODE removeRedundantConss(SCIP *scip, SCIP_CONS *cons, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int occurlistlength, int *ndelconss)
    #define CONSHDLR_MAXPREROUNDS
    Definition: cons_logicor.c:78
    static void findShortestOccurlist(SCIP_VAR **vars, int nvars, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int occurlistlength, int *nentries, SCIP_CONS ***shortestlist)
    static SCIP_RETCODE removeRedundantConssAndNonzeros(SCIP *scip, SCIP_CONS **conss, int nconss, unsigned char **entries, int *nentries, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool usestrengthening, int *firstchange, int *nfixedvars, int *ndelconss, int *nchgcoefs, SCIP_Bool *cutoff)
    static SCIP_RETCODE prepareCons(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, unsigned char **entries, int *nentries, SCIP_Bool *redundant, int *nfixedvars, int *nchgcoefs, int *ndelconss, SCIP_Bool *cutoff)
    #define DEFAULT_PRESOLPAIRWISE
    Definition: cons_logicor.c:95
    #define CONSHDLR_SEPAPRIORITY
    Definition: cons_logicor.c:71
    static SCIP_DECL_CONSPARSE(consParseLogicor)
    static SCIP_RETCODE enforcePseudo(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, SCIP_Bool *infeasible, SCIP_Bool *reduceddom, SCIP_Bool *solvelp)
    #define DEFAULT_NEGATEDCLIQUE
    Definition: cons_logicor.c:101
    static SCIP_DECL_CONSSEPALP(consSepalpLogicor)
    static SCIP_RETCODE createNormalizedLogicor(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, int mult, 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)
    static SCIP_DECL_CONSGETVARS(consGetVarsLogicor)
    static SCIP_RETCODE dualPresolving(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int *nfixedvars, int *ndelconss, int *nchgcoefs, int *naggrvars, SCIP_RESULT *result)
    Definition: cons_logicor.c:623
    static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
    static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_logicor.c:178
    static SCIP_RETCODE shortenConss(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS **conss, int nconss, unsigned char **entries, int *nentries, int *nfixedvars, int *ndelconss, int *nchgcoefs, SCIP_Bool *cutoff)
    static SCIP_DECL_CONSEXITPRE(consExitpreLogicor)
    static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
    Definition: cons_logicor.c:242
    static SCIP_DECL_CONSDEACTIVE(consDeactiveLogicor)
    static SCIP_DECL_CONSCOPY(consCopyLogicor)
    static SCIP_DECL_CONSDELETE(consDeleteLogicor)
    #define DEFAULT_PRESOLUSEHASHING
    Definition: cons_logicor.c:99
    static SCIP_DECL_CONSINITLP(consInitlpLogicor)
    static SCIP_RETCODE switchWatchedvars(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int watchedvar1, int watchedvar2)
    Definition: cons_logicor.c:398
    static SCIP_DECL_EVENTEXEC(eventExecLogicor)
    static SCIP_RETCODE fixDeleteOrUpgradeCons(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_CONSHDLR *conshdlrlinear, SCIP_CONSHDLR *conshdlrsetppc, int *nfixedvars, int *nchgbds, int *nchgcoefs, int *ndelconss, int *naddconss, int *nupgdconss, SCIP_Bool *cutoff)
    static SCIP_DECL_CONSINITPRE(consInitpreLogicor)
    #define HASHSIZE_LOGICORCONS
    Definition: cons_logicor.c:98
    static unsigned int calcSignature(SCIP_VAR **vars, int nvars)
    static SCIP_DECL_CONSSEPASOL(consSepasolLogicor)
    static SCIP_DECL_HASHKEYEQ(hashKeyEqLogicorcons)
    #define CONSHDLR_PROPFREQ
    Definition: cons_logicor.c:75
    static SCIP_DECL_CONSPRINT(consPrintLogicor)
    static SCIP_RETCODE detectRedundantConstraints(SCIP *scip, BMS_BLKMEM *blkmem, SCIP_CONS **conss, int nconss, int *firstchange, int *ndelconss)
    static SCIP_DECL_CONSPROP(consPropLogicor)
    static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, SCIP_Bool *separated, SCIP_Bool *reduceddom)
    #define CONSHDLR_PRESOLTIMING
    Definition: cons_logicor.c:83
    static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
    static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
    Definition: cons_logicor.c:335
    static SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLogicor)
    static SCIP_DECL_CONSGETNVARS(consGetNVarsLogicor)
    static SCIP_DECL_CONSENFORELAX(consEnforelaxLogicor)
    static void consdataSort(SCIP_CONSDATA *consdata)
    static SCIP_DECL_CONFLICTEXEC(conflictExecLogicor)
    static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
    static SCIP_RETCODE strengthenConss(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int occurlistlength, SCIP_EVENTHDLR *eventhdlr, int *ndelconss, int *nchgcoefs)
    #define CONSHDLR_EAGERFREQ
    Definition: cons_logicor.c:76
    static SCIP_DECL_LINCONSUPGD(linconsUpgdLogicor)
    #define EVENTHDLR_DESC
    Definition: cons_logicor.c:89
    static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
    Definition: cons_logicor.c:204
    static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, unsigned char **entries, int *nentries, SCIP_Bool *redundant, int *nchgcoefs)
    #define CONSHDLR_ENFOPRIORITY
    Definition: cons_logicor.c:72
    #define LINCONSUPGD_PRIORITY
    Definition: cons_logicor.c:86
    #define CONSHDLR_DELAYSEPA
    Definition: cons_logicor.c:79
    static void removeConsFromOccurList(SCIP_CONS *cons, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int occurlistlength)
    static SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLogicor)
    static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars)
    Definition: cons_logicor.c:266
    #define CONSHDLR_NAME
    Definition: cons_logicor.c:69
    static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *redundant, int *nchgcoefs, int *naddconss, int *ndelconss)
    Definition: cons_logicor.c:915
    #define EVENTHDLR_NAME
    Definition: cons_logicor.c:88
    static SCIP_RETCODE disableCons(SCIP *scip, SCIP_CONS *cons)
    static SCIP_DECL_SORTPTRCOMP(conssLogicorComp)
    static SCIP_DECL_CONSACTIVE(consActiveLogicor)
    static SCIP_RETCODE removeRedundantCons(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1, int *ndelconss)
    static SCIP_DECL_CONSINITSOL(consInitsolLogicor)
    static SCIP_DECL_CONSTRANS(consTransLogicor)
    #define CONSHDLR_DELAYPROP
    Definition: cons_logicor.c:80
    static SCIP_DECL_CONSFREE(consFreeLogicor)
    static SCIP_RETCODE removeRedundantNonZeros(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *artvar, int artpos, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int occurlistlength, SCIP_EVENTHDLR *eventhdlr, int *nchgcoefs, SCIP_Bool *deleted)
    static SCIP_DECL_HASHGETKEY(hashGetKeyLogicorcons)
    static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file, SCIP_Bool endline)
    Definition: cons_logicor.c:372
    Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
    Constraint handler for the set partitioning / packing / covering constraints .
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_INVALID
    Definition: def.h:187
    #define SCIP_Bool
    Definition: def.h:100
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:157
    #define SCIP_LONGINT_MAX
    Definition: def.h:151
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
    int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
    SCIP_Real SCIPgetDualsolLogicor(SCIP *scip, SCIP_CONS *cons)
    SCIP_ROW * SCIPgetRowLogicor(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcreateConsSetpack(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    Definition: cons_setppc.c:9551
    SCIP_RETCODE SCIPcleanupConssLogicor(SCIP *scip, SCIP_Bool onlychecked, int *naddconss, int *ndelconss, int *nchgcoefs)
    SCIP_RETCODE SCIPcreateRowLogicor(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcopyConsLinear(SCIP *scip, SCIP_CONS **cons, SCIP *sourcescip, const char *name, int nvars, SCIP_VAR **sourcevars, SCIP_Real *sourcecoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, 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)
    SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcreateConsBasicLogicor(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars)
    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_Real SCIPgetDualfarkasLogicor(SCIP *scip, SCIP_CONS *cons)
    SCIP_RETCODE SCIPaddCoefLogicor(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    SCIP_RETCODE SCIPincludeConshdlrLogicor(SCIP *scip)
    SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
    Definition: scip_copy.c:713
    SCIP_Bool SCIPisTransformed(SCIP *scip)
    Definition: scip_general.c:655
    SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
    Definition: scip_general.c:676
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    int SCIPgetNIntVars(SCIP *scip)
    Definition: scip_prob.c:2340
    SCIP_RETCODE SCIPaddConsUpgrade(SCIP *scip, SCIP_CONS *oldcons, SCIP_CONS **newcons)
    Definition: scip_prob.c:3368
    int SCIPgetNImplVars(SCIP *scip)
    Definition: scip_prob.c:2387
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    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 SCIPgetNBinVars(SCIP *scip)
    Definition: scip_prob.c:2293
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3304
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3466
    SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
    Definition: misc.c:3179
    void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
    Definition: misc.c:2348
    #define SCIPhashFour(a, b, c, d)
    Definition: pub_misc.h:573
    SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
    Definition: misc.c:2298
    void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
    Definition: misc.c:2596
    SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2535
    SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS **cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
    Definition: scip_prob.c:3806
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #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 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 SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
    const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
    SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
    SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
    SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
    SCIP_RETCODE SCIPincludeConflicthdlrBasic(SCIP *scip, SCIP_CONFLICTHDLR **conflicthdlrptr, const char *name, const char *desc, int priority, SCIP_DECL_CONFLICTEXEC((*conflictexec)), SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
    int SCIPconshdlrGetNCheckConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4802
    SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
    Definition: scip_cons.c:808
    void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: cons.c:4350
    SCIP_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4759
    SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
    Definition: scip_cons.c:540
    SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
    Definition: scip_cons.c:831
    SCIP_RETCODE SCIPsetConshdlrInitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITPRE((*consinitpre)))
    Definition: scip_cons.c:492
    SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
    Definition: scip_cons.c:235
    SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
    Definition: scip_cons.c:281
    SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: scip_cons.c:181
    SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDEACTIVE((*consdeactive)))
    Definition: scip_cons.c:693
    SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)))
    Definition: scip_cons.c:900
    SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
    Definition: scip_cons.c:578
    SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
    Definition: scip_cons.c:372
    SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
    Definition: scip_cons.c:323
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4320
    SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
    Definition: scip_cons.c:516
    SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
    Definition: scip_cons.c:347
    SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
    Definition: scip_cons.c:940
    SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH((*consgetsignedpermsymgraph)))
    Definition: scip_cons.c:924
    SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
    Definition: scip_cons.c:468
    SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
    Definition: scip_cons.c:624
    SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
    Definition: scip_cons.c:444
    SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4340
    SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
    Definition: scip_cons.c:601
    SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
    Definition: scip_cons.c:647
    int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4816
    SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
    Definition: scip_cons.c:854
    SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4739
    SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSACTIVE((*consactive)))
    Definition: scip_cons.c:670
    SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
    Definition: scip_cons.c:785
    SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
    Definition: cons.c:8423
    int SCIPconsGetPos(SCIP_CONS *cons)
    Definition: cons.c:8403
    SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
    Definition: cons.c:8652
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8413
    SCIP_RETCODE SCIPenableCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1837
    SCIP_Bool SCIPconsIsPropagationEnabled(SCIP_CONS *cons)
    Definition: cons.c:8511
    SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
    Definition: cons.c:8562
    SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
    Definition: scip_cons.c:2536
    int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
    Definition: cons.c:8845
    SCIP_RETCODE SCIPenableConsPropagation(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1951
    int SCIPconsGetValidDepth(SCIP_CONS *cons)
    Definition: cons.c:8476
    SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8592
    SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
    Definition: cons.c:8522
    SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
    Definition: cons.c:8702
    SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
    Definition: cons.c:8582
    SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
    Definition: cons.c:8454
    SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    Definition: scip_cons.c:997
    SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
    Definition: cons.c:8612
    SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
    Definition: cons.c:8632
    SCIP_RETCODE SCIPdisableCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1871
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8393
    SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1812
    SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
    Definition: cons.c:8642
    SCIP_Bool SCIPconsIsAdded(SCIP_CONS *cons)
    Definition: cons.c:8822
    SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
    Definition: scip_cons.c:1524
    SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
    Definition: cons.c:8672
    SCIP_RETCODE SCIPdisableConsPropagation(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1981
    SCIP_RETCODE SCIPaddConsAge(SCIP *scip, SCIP_CONS *cons, SCIP_Real deltaage)
    Definition: scip_cons.c:1755
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8572
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8662
    SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
    Definition: scip_cut.c:225
    SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: scip_event.c:111
    const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:396
    SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
    Definition: event.c:1194
    SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
    Definition: scip_event.c:367
    SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
    Definition: scip_event.c:413
    SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
    Definition: event.c:1217
    SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
    Definition: scip_lp.c:87
    #define SCIPfreeCleanBufferArray(scip, ptr)
    Definition: scip_mem.h:146
    #define SCIPallocCleanBufferArray(scip, ptr, num)
    Definition: scip_mem.h:142
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    int SCIPcalcMemGrowSize(SCIP *scip, int num)
    Definition: scip_mem.c:139
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPreallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:128
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPduplicateBufferArray(scip, ptr, source, num)
    Definition: scip_mem.h:132
    #define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    #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
    SCIP_RETCODE SCIPdelNlRow(SCIP *scip, SCIP_NLROW *nlrow)
    Definition: scip_nlp.c:424
    SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
    Definition: scip_nlp.c:396
    SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
    Definition: scip_nlp.c:110
    SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
    Definition: scip_nlp.c:1058
    SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
    Definition: nlp.c:1953
    SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
    Definition: scip_nlp.c:954
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    SCIP_RETCODE SCIPaddVarsToRowSameCoef(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real val)
    Definition: scip_lp.c:1718
    SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
    Definition: scip_lp.c:1398
    SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_lp.c:1646
    SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
    Definition: scip_lp.c:1508
    SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
    Definition: lp.c:17719
    SCIP_Real SCIPgetRowLPFeasibility(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1974
    SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
    Definition: lp.c:17917
    SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
    Definition: lp.c:17706
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
    Definition: scip_sol.c:467
    int SCIPgetNImplications(SCIP *scip)
    int SCIPgetNRuns(SCIP *scip)
    SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
    SCIP_RETCODE SCIPshrinkDisjunctiveVarSet(SCIP *scip, SCIP_VAR **vars, SCIP_Real *bounds, SCIP_Bool *boundtypes, SCIP_Bool *redundants, int nvars, int *nredvars, int *nglobalred, SCIP_Bool *setredundant, SCIP_Bool *glbinfeas, SCIP_Bool fullshortening)
    Definition: presolve.c:995
    SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
    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)
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
    Definition: scip_var.c:5210
    SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23674
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23510
    SCIP_RETCODE SCIPaddClique(SCIP *scip, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
    Definition: scip_var.c:8882
    SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
    Definition: scip_var.c:2119
    int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24600
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23418
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4380
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23530
    SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
    Definition: var.c:23976
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_RETCODE SCIPgetBinvarRepresentatives(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **repvars, SCIP_Bool *negated)
    Definition: scip_var.c:2283
    SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
    Definition: var.c:23462
    SCIP_RETCODE SCIPparseVarsList(SCIP *scip, const char *str, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize, char **endptr, char delimiter, SCIP_Bool *success)
    Definition: scip_var.c:805
    SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
    Definition: scip_var.c:10550
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23932
    SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
    Definition: var.c:17595
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23485
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24174
    int SCIPvarGetIndex(SCIP_VAR *var)
    Definition: var.c:23684
    SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
    Definition: scip_var.c:5118
    SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
    Definition: scip_var.c:5296
    SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2872
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23694
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:24961
    SCIP_RETCODE SCIPcleanupCliques(SCIP *scip, SCIP_Bool *infeasible)
    Definition: scip_var.c:9469
    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_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
    Definition: scip_var.c:2166
    int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
    Definition: var.c:24674
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
    Definition: var.c:23475
    SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
    Definition: var.c:23910
    int SCIPgetNCliques(SCIP *scip)
    Definition: scip_var.c:9512
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
    Definition: scip_var.c:10318
    SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2736
    int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
    Definition: var.c:17319
    SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
    Definition: var.c:17687
    SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
    Definition: var.c:21825
    SCIP_RETCODE SCIPinferBinvarCons(SCIP *scip, SCIP_VAR *var, SCIP_Bool fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:7412
    SCIP_RETCODE SCIPwriteVarsList(SCIP *scip, FILE *file, SCIP_VAR **vars, int nvars, SCIP_Bool type, char delimiter)
    Definition: scip_var.c:423
    SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
    Definition: var.c:16852
    SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:24951
    int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4322
    SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
    Definition: scip_var.c:2078
    SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:1853
    SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
    Definition: scip_var.c:10984
    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)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    SCIP_RETCODE SCIPgetSymActiveVariables(SCIP *scip, SYM_SYMTYPE symtype, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
    SCIP_RETCODE SCIPextendPermsymDetectionGraphLinear(SCIP *scip, SYM_GRAPH *graph, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_CONS *cons, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool *success)
    memory allocation routines
    #define BMScopyMemoryArray(ptr, source, num)
    Definition: memory.h:134
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    struct BMS_BlkMem BMS_BLKMEM
    Definition: memory.h:437
    methods commonly used for presolving
    public methods for conflict analysis handlers
    public methods for managing constraints
    public methods for managing events
    public methods for LP management
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    #define SCIPdebugPrintCons(x, y, z)
    Definition: pub_message.h:102
    public data structures and miscellaneous methods
    methods for sorting joint arrays of various types
    public methods for problem variables
    public methods for conflict handler plugins and conflict analysis
    public methods for constraint handler plugins and constraints
    public methods for cuts and aggregation rows
    public methods for event handler plugins and event handlers
    general public methods
    public methods for the LP relaxation, rows and columns
    public methods for memory management
    public methods for message handling
    public methods for nonlinear relaxation
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for the probing mode
    public methods for solutions
    public methods for querying solving statistics
    public methods for the branch-and-bound tree
    public methods for SCIP variables
    static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
    Main separation function.
    Definition: sepa_flower.c:1219
    structs for symmetry computations
    methods for dealing with symmetry detection graphs
    @ SCIP_CONFTYPE_PROPAGATION
    Definition: type_conflict.h:62
    struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
    Definition: type_cons.h:64
    struct SCIP_ConsData SCIP_CONSDATA
    Definition: type_cons.h:65
    struct SCIP_EventData SCIP_EVENTDATA
    Definition: type_event.h:179
    #define SCIP_EVENTTYPE_UBTIGHTENED
    Definition: type_event.h:79
    #define SCIP_EVENTTYPE_VARFIXED
    Definition: type_event.h:72
    #define SCIP_EVENTTYPE_LBRELAXED
    Definition: type_event.h:78
    @ SCIP_EXPRCURV_LINEAR
    Definition: type_expr.h:65
    @ SCIP_BRANCHDIR_DOWNWARDS
    Definition: type_history.h:43
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_FEASIBLE
    Definition: type_result.h:45
    @ SCIP_REDUCEDDOM
    Definition: type_result.h:51
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_CONSADDED
    Definition: type_result.h:52
    @ SCIP_SEPARATED
    Definition: type_result.h:49
    @ SCIP_SOLVELP
    Definition: type_result.h:55
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    @ SCIP_INFEASIBLE
    Definition: type_result.h:46
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    @ SCIP_ERROR
    Definition: type_retcode.h:43
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_INITPRESOLVE
    Definition: type_set.h:48
    @ SCIP_STAGE_PRESOLVING
    Definition: type_set.h:49
    @ SCIP_STAGE_INITSOLVE
    Definition: type_set.h:52
    @ SCIP_STAGE_SOLVING
    Definition: type_set.h:53
    @ SCIP_STAGE_TRANSFORMING
    Definition: type_set.h:46
    enum SYM_Symtype SYM_SYMTYPE
    Definition: type_symmetry.h:64
    @ SYM_SYMTYPE_SIGNPERM
    Definition: type_symmetry.h:62
    @ SYM_SYMTYPE_PERM
    Definition: type_symmetry.h:61
    #define SCIP_PRESOLTIMING_MEDIUM
    Definition: type_timing.h:53
    #define SCIP_PRESOLTIMING_EXHAUSTIVE
    Definition: type_timing.h:54
    @ SCIP_VARTYPE_INTEGER
    Definition: type_var.h:65
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64
    @ SCIP_VARSTATUS_FIXED
    Definition: type_var.h:54
    @ SCIP_VARSTATUS_MULTAGGR
    Definition: type_var.h:56
    @ SCIP_VARSTATUS_NEGATED
    Definition: type_var.h:57
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141