Scippy

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