SCIP

    Solving Constraint Integer Programs

    cons_logicor.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file cons_logicor.c
    26 * @ingroup DEFPLUGINS_CONS
    27 * @brief Constraint handler for logic or constraints \f$1^T x \ge 1\f$
    28 * (equivalent to set covering, but algorithms are suited for depth first search).
    29 * @author Tobias Achterberg
    30 * @author Michael Winkler
    31 */
    32
    33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    34
    36#include "scip/cons_linear.h"
    37#include "scip/cons_logicor.h"
    38#include "scip/cons_setppc.h"
    39#include "scip/presolve.h"
    40#include "scip/pub_conflict.h"
    41#include "scip/pub_cons.h"
    42#include "scip/pub_event.h"
    43#include "scip/pub_lp.h"
    44#include "scip/pub_message.h"
    45#include "scip/pub_misc.h"
    46#include "scip/pub_misc_sort.h"
    47#include "scip/pub_var.h"
    48#include "scip/scip_conflict.h"
    49#include "scip/scip_cons.h"
    50#include "scip/scip_cut.h"
    51#include "scip/scip_event.h"
    52#include "scip/scip_general.h"
    53#include "scip/scip_lp.h"
    54#include "scip/scip_mem.h"
    55#include "scip/scip_message.h"
    56#include "scip/scip_nlp.h"
    57#include "scip/scip_numerics.h"
    58#include "scip/scip_param.h"
    59#include "scip/scip_prob.h"
    60#include "scip/scip_probing.h"
    61#include "scip/scip_sol.h"
    63#include "scip/scip_tree.h"
    64#include "scip/scip_var.h"
    65#include "scip/symmetry_graph.h"
    67#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 vars[artpos] = artvar;
    2620 signature = calcSignature(vars, nvars);
    2621
    2622 /* correct exchanged variable with constraint variables */
    2623 vars[artpos] = oldvar;
    2624
    2625 /* check all constraints in the shortest list for coverage */
    2626 for( c = nentries - 1; c >= 0; --c )
    2627 {
    2628 cons1 = shortestlist[c];
    2629 assert(cons1 != NULL);
    2630 assert(!SCIPconsIsModifiable(cons1));
    2631
    2632 if( !SCIPconsIsActive(cons1) )
    2633 continue;
    2634
    2635 if( cons != cons1 )
    2636 {
    2637 SCIP_CONSDATA* consdata1 = SCIPconsGetData(cons1);
    2638 assert(consdata1 != NULL);
    2639
    2640 /* constraints with the less variables cannot be covered */
    2641 if( consdata1->nvars < nvars )
    2642 continue;
    2643
    2644 pos = -1;
    2645
    2646 assert(consdata->sorted);
    2647 assert(consdata->merged);
    2648 assert(consdata1->validsignature);
    2649 assert(consdata1->sorted);
    2650 assert(consdata1->merged);
    2651
    2652 if( (signature & (~consdata1->signature)) == 0 )
    2653 {
    2654 SCIP_VAR* var1;
    2655 int v1;
    2656
    2657 v = 0;
    2658 v1 = 0;
    2659
    2660 while( v < nvars && v1 < consdata1->nvars )
    2661 {
    2662 int comp;
    2663
    2664 /* skip position of artificial variable */
    2665 if( artpos == v )
    2666 {
    2667 ++v;
    2668 continue;
    2669 }
    2670
    2671 var1 = consdata1->vars[v1];
    2672
    2673 /* did we find the artificial variable in cons1 */
    2674 if( artvar == var1 )
    2675 {
    2676 /* remember of possible redundant variable */
    2677 assert(pos == -1);
    2678 pos = v1;
    2679
    2680 ++v1;
    2681 continue;
    2682 }
    2683
    2684 var = vars[v];
    2685 comp = SCIPvarCompare(var, var1);
    2686
    2687 /* check if the cons1 can still be covered */
    2688 if( comp == 0 )
    2689 {
    2690 ++v;
    2691 ++v1;
    2692 }
    2693 else if( comp > 0 )
    2694 ++v1;
    2695 else
    2696 break;
    2697 }
    2698
    2699 /* cons1 is might be covered by the changed constraints cons, meaning that we might remove the artvar from
    2700 * cons1
    2701 */
    2702 if( v == nvars )
    2703 {
    2704 int l;
    2705
    2706 /* if the artificial variable was not yet found, search over the rear variables in constraint cons1 */
    2707 if( pos == -1 )
    2708 {
    2709 while( v1 < consdata1->nvars )
    2710 {
    2711 if( artvar == consdata1->vars[v1] )
    2712 {
    2713 /* remember of possible redundant variable */
    2714 pos = v1;
    2715 break;
    2716 }
    2717 ++v1;
    2718 }
    2719 }
    2720
    2721 if( pos >= 0 )
    2722 {
    2723 int conspos;
    2724
    2725 assert(pos < consdata1->nvars);
    2726 assert(artvar == consdata1->vars[pos]);
    2727
    2728 /* remove redudant entry in cons1 */
    2729 SCIPdebugMsg(scip, "variable %s in logicor constraint <%s> is redundant and will be removed (used constraint %s)\n",
    2730 SCIPvarGetName(artvar), SCIPconsGetName(cons1), SCIPconsGetName(cons));
    2731 SCIPdebugPrintCons(scip, cons1, NULL);
    2732 conspos = pos;
    2733
    2734 if( consdata1->nvars > nvars )
    2735 {
    2736 pos = SCIPhashmapGetImageInt(varstopos, (void*)artvar);
    2737 assert(0 < pos && pos <= occurlistlength);
    2738
    2739 --pos;
    2740
    2741 /* remove corresponding entry in column representation */
    2742 for( l = noccurlistentries[pos] - 1; l >= 0; --l )
    2743 {
    2744 if( occurlist[pos][l] == cons1 )
    2745 {
    2746 --noccurlistentries[pos];
    2747 assert(noccurlistentries[pos] >= 0);
    2748
    2749 occurlist[pos][l] = occurlist[pos][noccurlistentries[pos]];
    2750 break;
    2751 }
    2752 }
    2753 assert(l >= 0);
    2754 }
    2755 else
    2756 {
    2757 assert(consdata1->nvars == nvars);
    2758
    2759 /* delete cons */
    2760 SCIPdebugMsg(scip, "logicor constraint <%s> is redundant due to constraint <%s> after removing variable <%s>\n",
    2761 SCIPconsGetName(cons), SCIPconsGetName(cons1), SCIPvarGetName(artvar));
    2762
    2763 /* remove cons from columns representation */
    2764 removeConsFromOccurList(cons, varstopos, occurlist, noccurlistentries, occurlistlength);
    2765
    2766 /* update flags of cons1 */
    2767 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons) );
    2768
    2769 SCIP_CALL( SCIPdelCons(scip, cons) );
    2770 *deleted = TRUE;
    2771 }
    2772
    2773 /* remove variable */
    2774 SCIP_CALL( delCoefPos(scip, cons1, eventhdlr, conspos) );
    2775 ++(*nchgcoefs);
    2776 consdataSort(consdata1);
    2777 consdataCalcSignature(consdata1);
    2778
    2779 if( *deleted )
    2780 return SCIP_OKAY;
    2781 }
    2782 }
    2783 }
    2784 }
    2785 }
    2786
    2787 return SCIP_OKAY;
    2788}
    2789
    2790/** find and remove redundant non-zero entries */
    2791static
    2793 SCIP* scip, /**< SCIP data structure */
    2794 SCIP_CONS** conss, /**< sorted array of logicor constraint */
    2795 int nconss, /**< number of sorted constraints */
    2796 SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
    2797 SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
    2798 int* noccurlistentries, /**< number of constraints for each variable in the occurlist */
    2799 int occurlistlength, /**< number of columns in the occurlist */
    2800 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    2801 int* ndelconss, /**< pointer to store the number of deleted constraints */
    2802 int* nchgcoefs /**< pointer to store the number of remove coefficients */
    2803 )
    2804{
    2805 SCIP_VAR** vars;
    2806 SCIP_CONSDATA* consdata;
    2807 SCIP_CONS* cons;
    2808 SCIP_VAR* artvar;
    2809 int nvars;
    2810 int c;
    2811 int v;
    2812
    2813 assert(scip != NULL);
    2814 assert(conss != NULL || nconss == 0);
    2815 assert(varstopos != NULL);
    2816 assert(occurlist != NULL);
    2817 assert(noccurlistentries != NULL);
    2818 assert(eventhdlr != NULL);
    2819 assert(ndelconss != NULL);
    2820 assert(nchgcoefs != NULL);
    2821
    2822 if( nconss == 0 )
    2823 return SCIP_OKAY;
    2824
    2825 assert(conss != NULL);
    2826
    2827 for( c = 0; c < nconss; ++c )
    2828 {
    2829 cons = conss[c];
    2830 assert(cons != NULL);
    2831 assert(!SCIPconsIsModifiable(cons));
    2832
    2833 if( !SCIPconsIsActive(cons) )
    2834 continue;
    2835
    2836 consdata = SCIPconsGetData(cons);
    2837 assert(consdata != NULL);
    2838
    2839 nvars = consdata->nvars;
    2840 assert(nvars >= 1);
    2841
    2842 if( nvars == 1 )
    2843 continue;
    2844
    2845 vars = consdata->vars;
    2846 assert(vars != NULL);
    2847
    2848 for( v = nvars - 1; v >= 0; --v )
    2849 {
    2850 artvar = SCIPvarGetNegatedVar(vars[v]);
    2851
    2852 if( artvar != NULL && SCIPhashmapExists(varstopos, (void*) artvar) )
    2853 {
    2854 SCIP_Bool deleted;
    2855
    2856 /* detect and remove redundant non-zero entries */
    2857 /* @todo: improve this algorithm by using the information that a constraint variables does not appaer in any
    2858 * other constraint, which means that only this variable needs to be negated to check for redundant
    2859 * non-zeros, therefor change also findShortestOccurlist() to return the corresponding
    2860 * variable/position
    2861 */
    2862 SCIP_CALL( removeRedundantNonZeros(scip, cons, artvar, v, varstopos, occurlist, noccurlistentries,
    2863 occurlistlength, eventhdlr, nchgcoefs, &deleted) );
    2864
    2865 if( deleted )
    2866 {
    2867 assert(SCIPconsIsDeleted(cons));
    2868 ++(*ndelconss);
    2869 break;
    2870 }
    2871 else
    2872 assert(SCIPconsIsActive(cons));
    2873 }
    2874 }
    2875 }
    2876
    2877 return SCIP_OKAY;
    2878}
    2879
    2880
    2881/** prepares a constraint by removing fixings and merge it */
    2882static
    2884 SCIP* scip, /**< SCIP data structure */
    2885 SCIP_CONS* cons, /**< logic or constraint */
    2886 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    2887 unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
    2888 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
    2889 SCIP_Bool* redundant, /**< returns whether a variable fixed to one exists in the constraint */
    2890 int* nfixedvars, /**< pointer to count number of fixings */
    2891 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
    2892 int* ndelconss, /**< pointer to count number of deleted constraints */
    2893 SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
    2894 )
    2895{
    2896 SCIP_CONSDATA* consdata;
    2897
    2898 assert(scip != NULL);
    2899 assert(cons != NULL);
    2900 assert(!SCIPconsIsDeleted(cons));
    2901 assert(eventhdlr != NULL);
    2902 assert(*entries != NULL);
    2903 assert(nentries != NULL);
    2904 assert(redundant != NULL);
    2905 assert(nfixedvars != NULL);
    2906 assert(nchgcoefs != NULL);
    2907 assert(ndelconss != NULL);
    2908 assert(redundant != NULL);
    2909
    2910 consdata = SCIPconsGetData(cons);
    2911 assert(consdata != NULL);
    2912 assert(consdata->nvars > 0);
    2913
    2914 *redundant = FALSE;
    2915
    2916 /* remove old fixings */
    2917 if( !consdata->presolved )
    2918 {
    2919 /* remove all variables that are fixed to zero, check redundancy due to fixed-to-one variable */
    2920 SCIP_CALL( applyFixings(scip, cons, eventhdlr, redundant, nchgcoefs, NULL, NULL) );
    2921 }
    2922
    2923 if( !*redundant )
    2924 {
    2925 /* merge constraint */
    2926 SCIP_CALL( mergeMultiples(scip, cons, eventhdlr, entries, nentries, redundant, nchgcoefs) );
    2927 }
    2928
    2929 if( *redundant )
    2930 {
    2931 SCIP_CALL( SCIPdelCons(scip, cons) );
    2932 ++(*ndelconss);
    2933
    2934 return SCIP_OKAY;
    2935 }
    2936
    2937 if( consdata->nvars == 0 )
    2938 {
    2939 *cutoff = TRUE;
    2940 }
    2941 else if( consdata->nvars == 1 )
    2942 {
    2943 SCIP_Bool infeasible;
    2944 SCIP_Bool fixed;
    2945
    2946 SCIPdebugMsg(scip, " -> fix last remaining variable and delete constraint\n");
    2947
    2948 SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], 1.0, &infeasible, &fixed) );
    2949 assert(!infeasible);
    2950 assert(fixed);
    2951 ++(*nfixedvars);
    2952
    2953 SCIP_CALL( SCIPdelCons(scip, cons) );
    2954 ++(*ndelconss);
    2955
    2956 *redundant = TRUE;
    2957 }
    2958 consdata->presolved = TRUE;
    2959
    2960 return SCIP_OKAY;
    2961}
    2962
    2963
    2964/** find covered/subsumed constraints and redundant non-zero entries
    2965 *
    2966 * covered:
    2967 * e.g.: c1: x1 + x2 + x3 >= 1
    2968 * c2: x1 + x2 + x3 + x4 >= 1
    2969 *
    2970 * strengthen:
    2971 * e.g.: c1: x1 + x2 + x3 >= 1
    2972 * c2: x1 + x2 + ~x3 + x4 >= 1
    2973 *
    2974 * => c2: x1 + x2 + x4 >= 1
    2975 *
    2976 * @see "Effective Preprocessing in SAT through Variable and Clause Elimination" by Niklas En and Armin Biere
    2977 */
    2978static
    2980 SCIP* scip, /**< SCIP data structure */
    2981 SCIP_CONS** conss, /**< array of logicor constraints */
    2982 int nconss, /**< number of logicor constraints */
    2983 unsigned char** entries, /**< array to store whether two positions in constraints represent the same
    2984 * variable */
    2985 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
    2986 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    2987 SCIP_Bool usestrengthening, /**< should we try to strengthen constraints by removing superflous
    2988 * non-zeros? */
    2989 int* firstchange, /**< pointer to store first changed constraint */
    2990 int* nfixedvars, /**< pointer to count number of fixings */
    2991 int* ndelconss, /**< pointer to store the number of deleted constraints */
    2992 int* nchgcoefs, /**< pointer to store the number of deleted coefficients */
    2993 SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
    2994 )
    2995{
    2996 SCIP_CONS*** occurlist;
    2997 SCIP_CONS** myconss;
    2998 SCIP_HASHMAP* varstopos;
    2999 SCIP_CONS* cons;
    3000 SCIP_CONSDATA* consdata;
    3001 int* noccurlistentries;
    3002 int* occurlistsizes;
    3003 SCIP_Bool redundant;
    3004 SCIP_Bool conschanged;
    3005 int lastnfixedvars;
    3006 int nbinvars;
    3007 int occurlistlength;
    3008 int occurlistsize;
    3009 int nmyconss;
    3010 int nmaxvars;
    3011 int c;
    3012
    3013 assert(scip != NULL);
    3014 assert(conss != NULL || nconss == 0);
    3015 assert(entries != NULL);
    3016 assert(*entries != NULL);
    3017 assert(nentries != NULL);
    3018 assert(eventhdlr != NULL);
    3019 assert(firstchange != NULL);
    3020 assert(0 <= *firstchange);
    3021 assert(nfixedvars != NULL);
    3022 assert(ndelconss != NULL);
    3023 assert(nchgcoefs != NULL);
    3024
    3025 if( *firstchange > nconss || nconss < 2 )
    3026 return SCIP_OKAY;
    3027
    3028 SCIPdebugMsg(scip, "starting removeRedundantConssAndNonzeros(), pairwise comparison to detect covered logicor constraints\n");
    3029
    3030 /* copy constraints to re-order them */
    3031 SCIP_CALL( SCIPduplicateBufferArray(scip, &myconss, conss, nconss) );
    3032
    3033 nmyconss = nconss;
    3034 lastnfixedvars = -1;
    3035 while( *nfixedvars != lastnfixedvars )
    3036 {
    3037 lastnfixedvars = *nfixedvars;
    3038 for( c = nconss - 1; c >= 0; --c )
    3039 {
    3040 cons = myconss[c];
    3041 assert(cons != NULL);
    3042
    3043 if( SCIPconsIsDeleted(cons) || SCIPconsIsModifiable(cons) )
    3044 {
    3045 myconss[c] = myconss[nmyconss - 1];
    3046 --nmyconss;
    3047
    3048 continue;
    3049 }
    3050
    3051 /* prepare constraint by removing fixings and merge it */
    3052 SCIP_CALL( prepareCons(scip, cons, eventhdlr, entries, nentries, &redundant, nfixedvars, nchgcoefs, ndelconss, cutoff) );
    3053
    3054 if( redundant )
    3055 {
    3056 assert(SCIPconsIsDeleted(cons));
    3057 assert(!(*cutoff));
    3058
    3059 myconss[c] = myconss[nmyconss - 1];
    3060 --nmyconss;
    3061
    3062 continue;
    3063 }
    3064
    3065 if( *cutoff )
    3066 {
    3067 SCIPfreeBufferArray(scip, &myconss);
    3068
    3069 return SCIP_OKAY;
    3070 }
    3071
    3072 consdata = SCIPconsGetData(cons);
    3073
    3074 /* sort the constraint */
    3075 consdataSort(consdata);
    3076
    3077 assert(consdata->nvars >= 2);
    3078 }
    3079 }
    3080
    3081 SCIPsortPtr((void**)myconss, conssLogicorComp, nmyconss);
    3082 assert(myconss[0] != NULL && myconss[nmyconss - 1] != NULL);
    3083 assert(SCIPconsGetData(myconss[0]) != NULL && SCIPconsGetData(myconss[nmyconss - 1]) != NULL);
    3084 assert(SCIPconsGetData(myconss[0])->nvars <= SCIPconsGetData(myconss[nmyconss - 1])->nvars);
    3085
    3086 /* we can stop if strengthening is disabled and all constraints have the same amount of variables */
    3087 if( !usestrengthening && SCIPconsGetData(myconss[0])->nvars == SCIPconsGetData(myconss[nmyconss - 1])->nvars )
    3088 {
    3089 SCIPfreeBufferArray(scip, &myconss);
    3090
    3091 return SCIP_OKAY;
    3092 }
    3093
    3094 /* @note: in the following we have at least number of nonzeros in logicor constraints + three times two the number of
    3095 * binary variables memory consumption + a map for variables to positions, we need this to get a column base
    3096 * representation
    3097 */
    3098
    3099 /* get number of all possible(incl. implicit) binary variables and their negation */
    3100 nbinvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
    3101 occurlistsize = 2 * nbinvars;
    3102
    3103 /* allocate memory for the column representation for each variable */
    3104 SCIP_CALL( SCIPallocBufferArray(scip, &occurlist, occurlistsize) );
    3105 BMSclearMemoryArray(occurlist, occurlistsize);
    3106 SCIP_CALL( SCIPallocBufferArray(scip, &noccurlistentries, occurlistsize) );
    3107 BMSclearMemoryArray(noccurlistentries, occurlistsize);
    3108 SCIP_CALL( SCIPallocBufferArray(scip, &occurlistsizes, occurlistsize) );
    3109 BMSclearMemoryArray(occurlistsizes, occurlistsize);
    3110
    3111 /* create hashmap to map all occuring variables to a position in the list */
    3112 SCIP_CALL( SCIPhashmapCreate(&varstopos, SCIPblkmem(scip), nmyconss) );
    3113
    3114 /* get maximal number of variables over all logicor constraints */
    3115 c = nmyconss - 1;
    3116 cons = myconss[c];
    3117 assert(cons != NULL);
    3118 assert(SCIPconsIsActive(cons));
    3119 consdata = SCIPconsGetData(cons);
    3120 assert(consdata != NULL);
    3121 nmaxvars = consdata->nvars;
    3122
    3123 occurlistlength = 0;
    3124 conschanged = FALSE;
    3125
    3126 /* determine all constraints with the maximal number of variables and add them to the column representation */
    3127 do
    3128 {
    3129 /* calculate hash-signature */
    3130 consdataCalcSignature(consdata);
    3131 assert(consdata->validsignature);
    3132 conschanged = conschanged || consdata->changed;
    3133 consdata->changed = FALSE;
    3134
    3135 /* add constraint to column data structure */
    3136 SCIP_CALL( addConsToOccurList(scip, cons, varstopos, occurlist, noccurlistentries, occurlistsizes, &occurlistlength, occurlistsize) );
    3137
    3138 --c;
    3139 if( c < 0 )
    3140 break;
    3141
    3142 cons = myconss[c];
    3143 assert(cons != NULL);
    3144 assert(SCIPconsIsActive(cons));
    3145 consdata = SCIPconsGetData(cons);
    3146 assert(consdata != NULL);
    3147 }
    3148 while( consdata->nvars == nmaxvars );
    3149
    3150 /* remove covered constraints and left over constraints to the column representation */
    3151 while( c >= 0 )
    3152 {
    3153 cons = myconss[c];
    3154 assert(cons != NULL);
    3155 assert(SCIPconsIsActive(cons));
    3156 consdata = SCIPconsGetData(cons);
    3157 assert(consdata != NULL);
    3158
    3159 /* calculate hash-signature */
    3160 consdataCalcSignature(consdata);
    3161 assert(consdata->validsignature);
    3162
    3163 /* search for covered constraints */
    3164 if( conschanged || consdata->changed )
    3165 {
    3166 /* detect covered constraints
    3167 *
    3168 * e.g.: c1: x1 + x2 + x3 >= 1
    3169 * c2: x1 + x2 + x3 + x4 >= 1
    3170 *
    3171 * => delete c2
    3172 */
    3173 SCIP_CALL( removeRedundantConss(scip, cons, varstopos, occurlist, noccurlistentries, occurlistlength, ndelconss) );
    3174 assert(SCIPconsIsActive(cons));
    3175
    3176 consdata->changed = FALSE;
    3177 conschanged = TRUE;
    3178 }
    3179
    3180 /* add constraint to column data structure */
    3181 SCIP_CALL( addConsToOccurList(scip, cons, varstopos, occurlist, noccurlistentries, occurlistsizes, &occurlistlength, occurlistsize) );
    3182
    3183 --c;
    3184 }
    3185
    3186 /* strengthen constraint while removing non-zeros
    3187 *
    3188 * e.g.: c1: x1 + x2 + x3 >= 1
    3189 * c2: x1 + x2 + ~x3 + x4 >= 1
    3190 *
    3191 * => c2: x1 + x2 + x4 >= 1
    3192 *
    3193 * special case:
    3194 *
    3195 * e.g.: c1: x1 + x2 + x3 >= 1
    3196 * c2: x1 + x2 + ~x3 >= 1
    3197 *
    3198 * => delete c1; c2: x1 + x2 >= 1
    3199 *
    3200 */
    3201 SCIP_CALL( strengthenConss(scip, myconss, nmyconss, varstopos, occurlist, noccurlistentries, occurlistlength, eventhdlr, ndelconss, nchgcoefs) );
    3202
    3203 /* delete temporary memory in occurlist */
    3204 for( --occurlistsize ; occurlistsize >= 0; --occurlistsize )
    3205 {
    3206 assert((occurlistsizes[occurlistsize] == 0) == (occurlist[occurlistsize] == NULL));
    3207 SCIPfreeBufferArrayNull(scip, &(occurlist[occurlistsize]));
    3208 }
    3209
    3210 /* delete temporary memory */
    3211 SCIPhashmapFree(&varstopos);
    3212 SCIPfreeBufferArray(scip, &occurlistsizes);
    3213 SCIPfreeBufferArray(scip, &noccurlistentries);
    3214 SCIPfreeBufferArray(scip, &occurlist);
    3215 SCIPfreeBufferArray(scip, &myconss);
    3216
    3217 return SCIP_OKAY;
    3218}
    3219
    3220#define MAX_CONSLENGTH 200
    3221
    3222/** try to tighten constraints by reducing the number of variables in the constraints using implications and cliques,
    3223 * also derive fixations through them, @see SCIPshrinkDisjunctiveVarSet()
    3224 */
    3225static
    3227 SCIP* scip, /**< SCIP data structure */
    3228 SCIP_CONSHDLRDATA* conshdlrdata, /**< logic or constraint handler data */
    3229 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    3230 SCIP_CONS** conss, /**< all constraints */
    3231 int nconss, /**< number of constraints */
    3232 unsigned char** entries, /**< array to store whether two positions in constraints represent the same
    3233 * variable */
    3234 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
    3235 int* nfixedvars, /**< pointer to count number of fixings */
    3236 int* ndelconss, /**< pointer to count number of deleted constraints */
    3237 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
    3238 SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
    3239 )
    3240{
    3241 SCIP_VAR** probvars;
    3242 SCIP_VAR* var;
    3243 SCIP_Real* bounds;
    3244 SCIP_Bool* boundtypes;
    3245 SCIP_Bool* redundants;
    3246 int nbinprobvars;
    3247 int nredvars;
    3248 int c;
    3249 int v;
    3250
    3251 assert(scip != NULL);
    3252 assert(eventhdlr != NULL);
    3253 assert(conss != NULL || nconss == 0);
    3254 assert(entries != NULL);
    3255 assert(*entries != NULL);
    3256 assert(nentries != NULL);
    3257 assert(nfixedvars != NULL);
    3258 assert(ndelconss != NULL);
    3259 assert(nchgcoefs != NULL);
    3260
    3261 if( nconss == 0 )
    3262 return SCIP_OKAY;
    3263
    3264 assert(conss != NULL);
    3265
    3266 if( SCIPgetNCliques(scip) == conshdlrdata->nlastcliquesshorten
    3267 && SCIPgetNImplications(scip) == conshdlrdata->nlastimplsshorten )
    3268 return SCIP_OKAY;
    3269
    3270 conshdlrdata->nlastcliquesshorten = SCIPgetNCliques(scip);
    3271 conshdlrdata->nlastimplsshorten = SCIPgetNImplications(scip);
    3272
    3273 nbinprobvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
    3274
    3275 /* allocate temporary memory */
    3276 SCIP_CALL( SCIPallocBufferArray(scip, &probvars, nbinprobvars) );
    3277 SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nbinprobvars) );
    3278 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nbinprobvars) );
    3279 SCIP_CALL( SCIPallocCleanBufferArray(scip, &redundants, nbinprobvars) );
    3280
    3281 for( c = nconss - 1; c >= 0; --c )
    3282 {
    3283 SCIP_Bool redundant = FALSE;
    3284 SCIP_CONS* cons = conss[c];
    3285 SCIP_CONSDATA* consdata;
    3286
    3287 assert(cons != NULL);
    3288
    3289 if( SCIPconsIsDeleted(cons) )
    3290 continue;
    3291
    3292 consdata = SCIPconsGetData(cons);
    3293 assert(consdata != NULL);
    3294
    3295 /* prepare constraint by removing fixings and merge it; we invalidate the presolved flag, because the calls to
    3296 * SCIPcleanupCliques() in this loop may have lead to fixed variables that are not yet removed */
    3297 consdata->presolved = FALSE;
    3298 SCIP_CALL( prepareCons(scip, cons, eventhdlr, entries, nentries, &redundant, nfixedvars, nchgcoefs, ndelconss, cutoff) );
    3299
    3300 if( redundant )
    3301 {
    3302 assert(SCIPconsIsDeleted(cons));
    3303 continue;
    3304 }
    3305
    3306 if( *cutoff )
    3307 goto TERMINATE;
    3308
    3309 assert(consdata->nvars >= 2);
    3310
    3311 /* do not try to shorten too long constraints */
    3312 if( consdata->nvars > MAX_CONSLENGTH )
    3313 continue;
    3314
    3315 /* form necessary data */
    3316 for( v = consdata->nvars - 1; v >= 0; --v)
    3317 {
    3318 var = consdata->vars[v];
    3319 assert(var != NULL);
    3321
    3322 if( SCIPvarIsActive(var) )
    3323 {
    3324 probvars[v] = var;
    3325 bounds[v] = 1.0;
    3326 boundtypes[v] = FALSE;
    3327 }
    3328 else
    3329 {
    3330 probvars[v] = SCIPvarGetNegationVar(var);
    3331 bounds[v] = 0.0;
    3332 boundtypes[v] = TRUE;
    3333 }
    3334 }
    3335
    3336 SCIP_CALL( SCIPcleanupCliques(scip, cutoff) );
    3337
    3338 if( *cutoff )
    3339 goto TERMINATE;
    3340
    3341 /* use implications and cliques to derive global fixings and to shrink the number of variables in this constraints */
    3342 SCIP_CALL( SCIPshrinkDisjunctiveVarSet(scip, probvars, bounds, boundtypes, redundants, consdata->nvars, &nredvars,
    3343 nfixedvars, &redundant, cutoff, TRUE) );
    3344
    3345 if( *cutoff )
    3346 {
    3347 /* reset redundants array to FALSE */
    3348 BMSclearMemoryArray(redundants, nbinprobvars);
    3349 goto TERMINATE;
    3350 }
    3351
    3352 /* remove redundant constraint */
    3353 if( redundant )
    3354 {
    3355 SCIP_CALL( SCIPdelCons(scip, cons) );
    3356 ++(*ndelconss);
    3357
    3358 /* reset redundants array to FALSE */
    3359 BMSclearMemoryArray(redundants, consdata->nvars);
    3360 continue;
    3361 }
    3362
    3363 /* remove redundant variables */
    3364 if( nredvars > 0 )
    3365 {
    3366 for( v = consdata->nvars - 1; v >= 0; --v )
    3367 {
    3368 if( redundants[v] )
    3369 {
    3370 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    3371
    3372 /* reset entry to FALSE */
    3373 redundants[v] = FALSE;
    3374 }
    3375 }
    3376 *nchgcoefs += nredvars;
    3377
    3378 /* if only one variable is left over fix it */
    3379 if( consdata->nvars == 1 )
    3380 {
    3381 SCIP_Bool infeasible;
    3382 SCIP_Bool fixed;
    3383
    3384 SCIPdebugMsg(scip, " -> fix last remaining variable and delete constraint\n");
    3385
    3386 SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], 1.0, &infeasible, &fixed) );
    3387 assert(!infeasible);
    3388 assert(fixed);
    3389 ++(*nfixedvars);
    3390
    3391 SCIP_CALL( SCIPdelCons(scip, cons) );
    3392 ++(*ndelconss);
    3393 }
    3394 /* @todo might also upgrade a two variable constraint to a set-packing constraint */
    3395 }
    3396 }
    3397
    3398 /* invalidate the presolved flags, because the calls to SCIPcleanupCliques() may have lead to fixed variables that
    3399 * are not yet removed */
    3400 for( c = nconss - 1; c >= 0; --c )
    3401 {
    3402 SCIP_CONS* cons = conss[c];
    3403 SCIP_CONSDATA* consdata;
    3404
    3405 assert(cons != NULL);
    3406
    3407 consdata = SCIPconsGetData(cons);
    3408 assert(consdata != NULL);
    3409
    3410 consdata->presolved = FALSE;
    3411 }
    3412
    3413 TERMINATE:
    3414 /* free temporary memory */
    3415 SCIPfreeCleanBufferArray(scip, &redundants);
    3416 SCIPfreeBufferArray(scip, &boundtypes);
    3417 SCIPfreeBufferArray(scip, &bounds);
    3418 SCIPfreeBufferArray(scip, &probvars);
    3419
    3420 return SCIP_OKAY;
    3421}
    3422
    3423#define MAXCOMPARISONS 1000000
    3424
    3425/** try to find a negated clique in a constraint which makes this constraint redundant but we need to keep the negated
    3426 * clique information alive, so we create a corresponding set-packing constraint
    3427 */
    3428static
    3430 SCIP* scip, /**< SCIP data structure */
    3431 SCIP_CONSHDLR* conshdlr, /**< logicor constraint handler */
    3432 SCIP_CONSHDLR* conshdlrsetppc, /**< setppc constraint handler, or NULL */
    3433 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    3434 SCIP_CONS** conss, /**< all constraints */
    3435 int nconss, /**< number of constraints */
    3436 unsigned char** entries, /**< array to store whether two positions in constraints represent the same
    3437 * variable */
    3438 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
    3439 int* nfixedvars, /**< pointer to count number of fixings */
    3440 int* ndelconss, /**< pointer to count number of deleted constraints */
    3441 int* nupgdconss, /**< pointer to count number of upgraded constraints */
    3442 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
    3443 SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
    3444 )
    3445{
    3446 SCIP_CONSHDLRDATA* conshdlrdata;
    3447 SCIP_CONS* cons;
    3448 SCIP_CONSDATA* consdata;
    3449 SCIP_VAR** repvars;
    3450 SCIP_Bool* negated;
    3451 SCIP_VAR* var1;
    3452 SCIP_Bool redundant;
    3453 int c;
    3454 int size;
    3455 int maxcomppercons;
    3456 int comppercons;
    3457
    3458 assert(scip != NULL);
    3459 assert(conshdlr != NULL);
    3460 assert(eventhdlr != NULL);
    3461 assert(conss != NULL || nconss == 0);
    3462 assert(entries != NULL);
    3463 assert(*entries != NULL);
    3464 assert(nentries != NULL);
    3465 assert(nfixedvars != NULL);
    3466 assert(ndelconss != NULL);
    3467 assert(nupgdconss != NULL);
    3468 assert(nchgcoefs != NULL);
    3469 assert(cutoff != NULL);
    3470
    3471 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3472 assert(conshdlrdata != NULL);
    3473
    3474 if( nconss == 0 )
    3475 return SCIP_OKAY;
    3476
    3477 if( SCIPgetNCliques(scip) == conshdlrdata->nlastcliquesneg && SCIPgetNImplications(scip) == conshdlrdata->nlastimplsneg )
    3478 return SCIP_OKAY;
    3479
    3480 conshdlrdata->nlastcliquesneg = SCIPgetNCliques(scip);
    3481 conshdlrdata->nlastimplsneg = SCIPgetNImplications(scip);
    3482
    3483 /* estimate the maximal number of variables in a logicor constraint */
    3485 if( size <= 0 )
    3486 return SCIP_OKAY;
    3487
    3488 /* temporary memory for active/negation of active variables */
    3489 SCIP_CALL( SCIPallocBufferArray(scip, &repvars, size) );
    3490 SCIP_CALL( SCIPallocBufferArray(scip, &negated, size) );
    3491
    3492 /* iterate over all constraints and try to find negated cliques in logicors */
    3493 for( c = nconss - 1; c >= 0; --c )
    3494 {
    3495 int v;
    3496
    3497 assert(conss != NULL); /* for flexelint */
    3498
    3499 cons = conss[c];
    3500 assert(cons != NULL);
    3501
    3502 if( !SCIPconsIsActive(cons) )
    3503 continue;
    3504
    3505 /* prepare constraint by removing fixings and merge it */
    3506 SCIP_CALL( prepareCons(scip, cons, eventhdlr, entries, nentries, &redundant, nfixedvars, nchgcoefs, ndelconss, cutoff) );
    3507
    3508 if( redundant )
    3509 {
    3510 assert(SCIPconsIsDeleted(cons));
    3511 continue;
    3512 }
    3513
    3514 if( *cutoff )
    3515 goto TERMINATE;
    3516
    3517 consdata = SCIPconsGetData(cons);
    3518 assert(consdata != NULL);
    3519 assert(consdata->nvars >= 2);
    3520 assert(consdata->nvars <= size);
    3521 assert(consdata->presolved);
    3522
    3523 if( SCIPconsIsModifiable(cons) && consdata->nvars == 2 )
    3524 continue;
    3525
    3526 if( c % 100 == 0 && SCIPisStopped(scip) )
    3527 break;
    3528
    3529 maxcomppercons = MAXCOMPARISONS / nconss;
    3530 comppercons = 0;
    3531
    3532 BMScopyMemoryArray(repvars, consdata->vars, consdata->nvars);
    3533
    3534 /* all variables should be active or negative active variables, otherwise something went wrong with applyFixings()
    3535 * called before mergeMultiples()
    3536 */
    3537 for( v = consdata->nvars - 1; v >= 0; --v )
    3538 {
    3539 assert(SCIPvarIsActive(repvars[v]) || (SCIPvarGetStatus(repvars[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v]))));
    3540 negated[v] = SCIPvarIsNegated(repvars[v]);
    3541 }
    3542
    3543 for( v = consdata->nvars - 1; v > 0; --v )
    3544 {
    3545 SCIP_Bool breakloop;
    3546 SCIP_Bool neg1;
    3547 int w;
    3548
    3549 var1 = repvars[v];
    3550
    3551 /* if there is no negated variable, there can't be a negated clique */
    3552 if( SCIPvarGetNegatedVar(var1) == NULL )
    3553 continue;
    3554
    3555 /* get active counterpart to check for common cliques */
    3557 {
    3558 var1 = SCIPvarGetNegatedVar(var1);
    3559 neg1 = TRUE;
    3560 }
    3561 else
    3562 neg1 = FALSE;
    3563
    3564 if( !SCIPvarIsActive(var1) )
    3565 continue;
    3566
    3567 /* no cliques available */
    3568 if( SCIPvarGetNCliques(var1, neg1) == 0 && SCIPvarGetNImpls(var1, neg1) == 0 )
    3569 continue;
    3570
    3571 comppercons += (v - 1);
    3572
    3573 breakloop = FALSE;
    3574
    3575 for( w = v - 1; w >= 0; --w )
    3576 {
    3577 SCIP_VAR* var2;
    3578 SCIP_Bool neg2;
    3579
    3580 var2 = repvars[w];
    3581
    3582 /* if there is no negated variable, there can't be a negated clique */
    3583 if( SCIPvarGetNegatedVar(var2) == NULL )
    3584 continue;
    3585
    3587 {
    3588 var2 = SCIPvarGetNegatedVar(var2);
    3589 neg2 = TRUE;
    3590 }
    3591 else
    3592 neg2 = FALSE;
    3593
    3594 if( !SCIPvarIsActive(var2) )
    3595 continue;
    3596
    3597 /* no cliques available */
    3598 if( SCIPvarGetNCliques(var2, neg2) == 0 && SCIPvarGetNImpls(var2, neg2) == 0 )
    3599 continue;
    3600
    3601 /* check if both active variable are the same */
    3602 if( var1 == var2 )
    3603 {
    3604 if( neg1 != neg2 )
    3605 {
    3606 SCIPdebugMsg(scip, "logicor constraint <%s> is redundant, because variable <%s> and its negation <%s> exist\n",
    3607 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
    3608
    3609 SCIP_CALL( SCIPdelCons(scip, cons) );
    3610
    3611 breakloop = TRUE;
    3612 }
    3613 else
    3614 {
    3615 #ifndef NDEBUG
    3616 SCIP_VAR* lastvar = consdata->vars[consdata->nvars - 1];
    3617 #endif
    3618 SCIPdebugMsg(scip, "in logicor constraint <%s>, active variable of <%s> and active variable of <%s> are the same, removing the first\n",
    3619 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[v]), SCIPvarGetName(consdata->vars[w]));
    3620
    3621 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    3622
    3623 if( v < consdata->nvars )
    3624 {
    3625 /* delCoefPos replaces the variable on position v with the last one, so w also need to correct the
    3626 * negated array the same way, and because of deletion the number of variables is already decreased
    3627 */
    3628 assert(consdata->vars[v] == lastvar);
    3629 negated[v] = negated[consdata->nvars];
    3630 }
    3631 ++(*nchgcoefs);
    3632 }
    3633 break;
    3634 }
    3635
    3636 if( conshdlrsetppc != NULL && SCIPconsGetNUpgradeLocks(cons) == 0
    3637 && SCIPvarsHaveCommonClique(var1, neg1, var2, neg2, TRUE) )
    3638 {
    3639 SCIP_CONS* newcons;
    3640 SCIP_VAR* vars[2];
    3641
    3642 /* this negated clique information could be created out of this logicor constraint even if there are more
    3643 * than two variables left (, for example by probing), we need to keep this information by creating a
    3644 * setppc constraint instead
    3645 */
    3646
    3647 /* get correct variables */
    3648 if( !neg1 )
    3649 vars[0] = SCIPvarGetNegatedVar(var1);
    3650 else
    3651 vars[0] = var1;
    3652
    3653 if( !neg2 )
    3654 vars[1] = SCIPvarGetNegatedVar(var2);
    3655 else
    3656 vars[1] = var2;
    3657
    3658 SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, SCIPconsGetName(cons), 2, vars,
    3663
    3664 SCIPdebugPrintCons(scip, newcons, NULL);
    3665 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &newcons) );
    3666
    3667 SCIPdebugMsg(scip, "logicor constraint <%s> is redundant due to negated clique information and will be replaced by a setppc constraint \n",
    3668 SCIPconsGetName(cons));
    3669 SCIPdebugMsg(scip, "variable <%s> and variable <%s> are in a negated clique\n", SCIPvarGetName(consdata->vars[v]), SCIPvarGetName(consdata->vars[w]));
    3670
    3671 SCIP_CALL( SCIPdelCons(scip, cons) );
    3672 ++(*nupgdconss);
    3673
    3674 breakloop = TRUE;
    3675 break;
    3676 }
    3677 }
    3678 if( breakloop )
    3679 break;
    3680
    3681 /* do not do to many comparisons */
    3682 if( comppercons > maxcomppercons )
    3683 break;
    3684 }
    3685 }
    3686
    3687 TERMINATE:
    3688 /* free temporary memory */
    3689 SCIPfreeBufferArray(scip, &negated);
    3690 SCIPfreeBufferArray(scip, &repvars);
    3691
    3692 return SCIP_OKAY;
    3693}
    3694
    3695/** handle all cases with less than three variables in a logicor constraint
    3696 *
    3697 * in case a constraint has zero variables left, we detected infeasibility
    3698 * in case a constraint has one variables left, we will fix it to one
    3699 * in case a constraint has two variables left, we will add the implication and upgrade it to a set-packing constraint
    3700 */
    3701static
    3703 SCIP* scip, /**< SCIP data structure */
    3704 SCIP_CONS* cons, /**< logic or constraint */
    3705 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    3706 SCIP_CONSHDLR* conshdlrlinear, /**< linear constraint handler, or NULL */
    3707 SCIP_CONSHDLR* conshdlrsetppc, /**< setppc constraint handler, or NULL */
    3708 int* nfixedvars, /**< pointer to count number of fixings */
    3709 int* nchgbds, /**< pointer to count number of tightened bounds */
    3710 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
    3711 int* ndelconss, /**< pointer to count number of deleted constraints */
    3712 int* naddconss, /**< pointer to count number of added constraints */
    3713 int* nupgdconss, /**< pointer to count number of upgraded constraints */
    3714 SCIP_Bool* cutoff /**< pointer to store TRUE, if the node can be cut off */
    3715 )
    3716{
    3717 SCIP_CONSDATA* consdata;
    3718 SCIP_Bool infeasible;
    3719 SCIP_Bool fixed;
    3720
    3721 assert(scip != NULL);
    3722 assert(cons != NULL);
    3723 assert(eventhdlr != NULL);
    3724 assert(nfixedvars != NULL);
    3725 assert(nchgbds != NULL);
    3726 assert(nchgcoefs != NULL);
    3727 assert(ndelconss != NULL);
    3728 assert(naddconss != NULL);
    3729 assert(nupgdconss != NULL);
    3730 assert(cutoff != NULL);
    3731
    3732 *cutoff = FALSE;
    3733
    3734 if( SCIPconsIsModifiable(cons) )
    3735 return SCIP_OKAY;
    3736
    3737 consdata = SCIPconsGetData(cons);
    3738 assert(consdata != NULL);
    3739
    3740 /* if an unmodifiable logicor constraint has only two variables, we can add an implication and we will upgrade this
    3741 * constraint to a set-packing constraint
    3742 */
    3743 if( consdata->nvars == 2 )
    3744 {
    3745 /* add implication if not yet done */
    3746 if( !consdata->impladded )
    3747 {
    3748 SCIP_Bool implinfeasible;
    3749 int nimplbdchgs;
    3750 SCIP_Bool values[2];
    3751
    3752 values[0] = FALSE;
    3753 values[1] = FALSE;
    3754 /* a two-variable logicor constraint x + y >= 1 yields the implication x == 0 -> y == 1, and is represented
    3755 * by the clique inequality ~x + ~y <= 1
    3756 */
    3757 SCIP_CALL( SCIPaddClique(scip, consdata->vars, values, consdata->nvars, FALSE, &implinfeasible, &nimplbdchgs) );
    3758 *nchgbds += nimplbdchgs;
    3759 if( implinfeasible )
    3760 {
    3761 *cutoff = TRUE;
    3762 return SCIP_OKAY;
    3763 }
    3764
    3765 /* adding the above implication could lead to fixings, which render the constraint redundant */
    3766 if ( nimplbdchgs > 0 )
    3767 {
    3768 SCIP_Bool redundant;
    3769
    3770 /* remove all variables that are fixed to zero, check redundancy due to fixed-to-one variable */
    3771 SCIP_CALL( applyFixings(scip, cons, eventhdlr, &redundant, nchgcoefs, naddconss, ndelconss) );
    3772 assert(!SCIPconsIsDeleted(cons));
    3773
    3774 if( redundant )
    3775 {
    3776 SCIPdebugMsg(scip, "logic or constraint <%s> is redundant\n", SCIPconsGetName(cons));
    3777
    3778 SCIP_CALL( SCIPdelCons(scip, cons) );
    3779 (*ndelconss)++;
    3780
    3781 return SCIP_OKAY;
    3782 }
    3783 }
    3784 consdata->impladded = TRUE;
    3785 }
    3786
    3787 /* still we have two variables left, we will upgrade this constraint */
    3788 if( conshdlrsetppc != NULL && SCIPconsGetNUpgradeLocks(cons) == 0 && consdata->nvars == 2 )
    3789 {
    3790 SCIP_CONS* newcons;
    3791 SCIP_VAR* vars[2];
    3792
    3793 /* get correct variables */
    3794 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[0], &vars[0]) );
    3795 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[1], &vars[1]) );
    3796
    3797 SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, SCIPconsGetName(cons), 2, vars,
    3802
    3803 SCIPdebugPrintCons(scip, newcons, NULL);
    3804 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &newcons) );
    3805
    3806 SCIPdebugMsg(scip, "logicor constraint <%s> was upgraded to a set-packing constraint\n", SCIPconsGetName(cons));
    3807
    3808 SCIP_CALL( SCIPdelCons(scip, cons) );
    3809 ++(*nupgdconss);
    3810 }
    3811 }
    3812
    3813 /* if unmodifiable constraint has no variables, it is infeasible,
    3814 * if unmodifiable constraint has only one variable, this one can be fixed and the constraint deleted
    3815 */
    3816 if( consdata->nvars == 0 )
    3817 {
    3818 SCIPdebugMsg(scip, "logic or constraint <%s> is infeasible\n", SCIPconsGetName(cons));
    3819
    3820 *cutoff = TRUE;
    3821 }
    3822 else if( consdata->nvars == 1 )
    3823 {
    3824 SCIPdebugMsg(scip, "logic or constraint <%s> has only one variable not fixed to 0.0\n",
    3825 SCIPconsGetName(cons));
    3826
    3827 assert(consdata->vars != NULL);
    3828 assert(consdata->vars[0] != NULL);
    3829
    3830 if( SCIPvarGetStatus(consdata->vars[0]) != SCIP_VARSTATUS_MULTAGGR )
    3831 {
    3832 SCIPdebugMsg(scip, " -> fix variable and delete constraint\n");
    3833
    3834 SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], 1.0, &infeasible, &fixed) );
    3835 if( infeasible )
    3836 {
    3837 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    3838
    3839 *cutoff = TRUE;
    3840 return SCIP_OKAY;
    3841 }
    3842 if( fixed )
    3843 (*nfixedvars)++;
    3844
    3845 SCIP_CALL( SCIPdelCons(scip, cons) );
    3846 (*ndelconss)++;
    3847 }
    3848 else if( conshdlrlinear != NULL )
    3849 {
    3850 SCIP_Real coef;
    3851 SCIP_CONS* conslinear;
    3852 char consname[SCIP_MAXSTRLEN];
    3853
    3854 SCIPdebugMsg(scip, " -> variable is multi-aggregated, convert to linear constraint <%s> == 1 \n",
    3855 SCIPvarGetName(consdata->vars[0]));
    3856
    3857 coef = 1.0;
    3858 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "fixmaggr_%s_%s", SCIPconsGetName(cons),SCIPvarGetName(consdata->vars[0]) );
    3859 SCIP_CALL( SCIPcreateConsLinear(scip, &conslinear, consname, 1, consdata->vars, &coef, 1.0, 1.0,
    3863 SCIPconsIsStickingAtNode(cons)) );
    3864
    3865 /* add the downgraded constraint to the problem */
    3866 SCIP_CALL( SCIPaddCons(scip, conslinear) );
    3867 SCIP_CALL( SCIPreleaseCons(scip, &conslinear) );
    3868 SCIP_CALL( SCIPdelCons(scip, cons) );
    3869
    3870 (*ndelconss)++;
    3871 (*naddconss)++;
    3872 }
    3873 }
    3874
    3875 return SCIP_OKAY;
    3876}
    3877
    3878
    3879/*
    3880 * upgrading of linear constraints
    3881 */
    3882
    3883/** creates and captures a normalized (with all coefficients +1) logic or constraint */
    3884static
    3886 SCIP* scip, /**< SCIP data structure */
    3887 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    3888 const char* name, /**< name of constraint */
    3889 int nvars, /**< number of variables in the constraint */
    3890 SCIP_VAR** vars, /**< array with variables of constraint entries */
    3891 SCIP_Real* vals, /**< array with coefficients (+1.0 or -1.0) */
    3892 int mult, /**< multiplier on the coefficients(+1 or -1) */
    3893 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
    3894 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    3895 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
    3896 * Usually set to TRUE. */
    3897 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    3898 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    3899 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    3900 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    3901 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
    3902 * Usually set to TRUE. */
    3903 SCIP_Bool local, /**< is constraint only valid locally?
    3904 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    3905 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
    3906 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
    3907 * adds coefficients to this constraint. */
    3908 SCIP_Bool dynamic, /**< is constraint subject to aging?
    3909 * Usually set to FALSE. Set to TRUE for own cuts which
    3910 * are separated as constraints. */
    3911 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
    3912 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
    3913 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    3914 * if it may be moved to a more global node?
    3915 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
    3916 )
    3917{
    3918 SCIP_VAR** transvars;
    3919 int v;
    3920
    3921 assert(nvars == 0 || vars != NULL);
    3922 assert(nvars == 0 || vals != NULL);
    3923 assert(mult == +1 || mult == -1);
    3924
    3925 /* get temporary memory */
    3926 SCIP_CALL( SCIPallocBufferArray(scip, &transvars, nvars) );
    3927
    3928 /* negate positive or negative variables */
    3929 for( v = 0; v < nvars; ++v )
    3930 {
    3931 if( mult * vals[v] > 0.0 )
    3932 transvars[v] = vars[v];
    3933 else
    3934 {
    3935 SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &transvars[v]) );
    3936 }
    3937 assert(transvars[v] != NULL);
    3938 }
    3939
    3940 /* create the constraint */
    3941 SCIP_CALL( SCIPcreateConsLogicor(scip, cons, name, nvars, transvars,
    3942 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    3943
    3944 /* free temporary memory */
    3945 SCIPfreeBufferArray(scip, &transvars);
    3946
    3947 return SCIP_OKAY;
    3948}
    3949
    3950static
    3951SCIP_DECL_LINCONSUPGD(linconsUpgdLogicor)
    3952{ /*lint --e{715}*/
    3953 assert(upgdcons != NULL);
    3954
    3955 /* check, if linear constraint can be upgraded to logic or constraint
    3956 * - logic or constraints consist only of binary variables with a
    3957 * coefficient of +1.0 or -1.0 (variables with -1.0 coefficients can be negated):
    3958 * lhs <= x1 + ... + xp - y1 - ... - yn <= rhs
    3959 * - negating all variables y = (1-Y) with negative coefficients gives:
    3960 * lhs + n <= x1 + ... + xp + Y1 + ... + Yn <= rhs + n
    3961 * - negating all variables x = (1-X) with positive coefficients and multiplying with -1 gives:
    3962 * p - rhs <= X1 + ... + Xp + y1 + ... + yn <= p - lhs
    3963 * - logic or constraints have left hand side of +1.0, and right hand side of +infinity: x(S) >= 1.0
    3964 * -> without negations: (lhs == 1 - n and rhs == +inf) or (lhs == -inf and rhs = p - 1)
    3965 */
    3966 if( nvars > 2 && nposbin + nnegbin + nposimplbin + nnegimplbin == nvars && ncoeffspone + ncoeffsnone == nvars
    3967 && ((SCIPisEQ(scip, lhs, 1.0 - ncoeffsnone) && SCIPisInfinity(scip, rhs))
    3968 || (SCIPisInfinity(scip, -lhs) && SCIPisEQ(scip, rhs, ncoeffspone - 1.0))) )
    3969 {
    3970 int mult;
    3971
    3972 SCIPdebugMsg(scip, "upgrading constraint <%s> to logic or constraint\n", SCIPconsGetName(cons));
    3973
    3974 /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
    3975 mult = SCIPisInfinity(scip, rhs) ? +1 : -1;
    3976
    3977 /* create the logic or constraint (an automatically upgraded constraint is always unmodifiable) */
    3978 assert(!SCIPconsIsModifiable(cons));
    3979 SCIP_CALL( createNormalizedLogicor(scip, upgdcons, SCIPconsGetName(cons), nvars, vars, vals, mult,
    3984 }
    3985
    3986 return SCIP_OKAY;
    3987}
    3988
    3989/** helper function to enforce constraints */
    3990static
    3992 SCIP* scip, /**< SCIP data structure */
    3993 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    3994 SCIP_CONS** conss, /**< constraints to process */
    3995 int nconss, /**< number of constraints */
    3996 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
    3997 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
    3998 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
    3999 )
    4000{
    4001 SCIP_CONSHDLRDATA* conshdlrdata;
    4002 SCIP_Bool cutoff;
    4003 SCIP_Bool separated;
    4004 SCIP_Bool reduceddom;
    4005 int c;
    4006
    4007 assert(conshdlr != NULL);
    4008 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    4009 assert(nconss == 0 || conss != NULL);
    4010 assert(result != NULL);
    4011
    4012 SCIPdebugMsg(scip, "Enforcing %d logic or constraints for %s solution\n", nconss, sol == NULL ? "LP" : "relaxation");
    4013
    4014 *result = SCIP_FEASIBLE;
    4015
    4016 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4017 assert(conshdlrdata != NULL);
    4018
    4019 cutoff = FALSE;
    4020 separated = FALSE;
    4021 reduceddom = FALSE;
    4022
    4023 /* check all useful logic or constraints for feasibility */
    4024 for( c = 0; c < nusefulconss && !cutoff && !reduceddom; ++c )
    4025 {
    4026 SCIP_CALL( separateCons(scip, conss[c], sol, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
    4027 }
    4028
    4029 /* check all obsolete logic or constraints for feasibility */
    4030 for( c = nusefulconss; c < nconss && !cutoff && !separated && !reduceddom; ++c )
    4031 {
    4032 SCIP_CALL( separateCons(scip, conss[c], sol, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
    4033 }
    4034
    4035 /* return the correct result */
    4036 if( cutoff )
    4037 *result = SCIP_CUTOFF;
    4038 else if( separated )
    4039 *result = SCIP_SEPARATED;
    4040 else if( reduceddom )
    4041 *result = SCIP_REDUCEDDOM;
    4042
    4043 return SCIP_OKAY;
    4044}
    4045
    4046/** adds symmetry information of constraint to a symmetry detection graph */
    4047static
    4049 SCIP* scip, /**< SCIP pointer */
    4050 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
    4051 SCIP_CONS* cons, /**< constraint */
    4052 SYM_GRAPH* graph, /**< symmetry detection graph */
    4053 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
    4054 )
    4055{
    4056 SCIP_CONSDATA* consdata;
    4057 SCIP_VAR** logicorvars;
    4058 SCIP_VAR** vars;
    4059 SCIP_Real* vals;
    4060 SCIP_Real constant = 0.0;
    4061 int nlocvars;
    4062 int nvars;
    4063 int i;
    4064
    4065 assert(scip != NULL);
    4066 assert(cons != NULL);
    4067 assert(graph != NULL);
    4068 assert(success != NULL);
    4069
    4070 consdata = SCIPconsGetData(cons);
    4071 assert(consdata != NULL);
    4072
    4073 /* get active variables of the constraint */
    4074 nvars = SCIPgetNVars(scip);
    4075 nlocvars = SCIPgetNVarsLogicor(scip, cons);
    4076
    4077 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    4078 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
    4079
    4080 logicorvars = SCIPgetVarsLogicor(scip, cons);
    4081 for( i = 0; i < consdata->nvars; ++i )
    4082 {
    4083 vars[i] = logicorvars[i];
    4084 vals[i] = 1.0;
    4085 }
    4086
    4087 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
    4088
    4089 SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars,
    4090 cons, 1.0 - constant, SCIPinfinity(scip), success) );
    4091
    4092 SCIPfreeBufferArray(scip, &vals);
    4093 SCIPfreeBufferArray(scip, &vars);
    4094
    4095 return SCIP_OKAY;
    4096}
    4097
    4098/*
    4099 * Callback methods of constraint handler
    4100 */
    4101
    4102/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    4103static
    4104SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLogicor)
    4105{ /*lint --e{715}*/
    4106 assert(scip != NULL);
    4107 assert(conshdlr != NULL);
    4108 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    4109
    4110 /* call inclusion method of constraint handler */
    4112
    4113 *valid = TRUE;
    4114
    4115 return SCIP_OKAY;
    4116}
    4117
    4118/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
    4119static
    4120SCIP_DECL_CONSFREE(consFreeLogicor)
    4121{ /*lint --e{715}*/
    4122 SCIP_CONSHDLRDATA* conshdlrdata;
    4123
    4124 assert(conshdlr != NULL);
    4125 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    4126 assert(scip != NULL);
    4127
    4128 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4129 assert(conshdlrdata != NULL);
    4130
    4131 /* free constraint handler data */
    4132 conshdlrdataFree(scip, &conshdlrdata);
    4133
    4134 SCIPconshdlrSetData(conshdlr, NULL);
    4135
    4136 return SCIP_OKAY;
    4137}
    4138
    4139
    4140/** presolving initialization method of constraint handler (called when presolving is about to begin) */
    4141static
    4142SCIP_DECL_CONSINITPRE(consInitpreLogicor)
    4143{ /*lint --e{715}*/
    4144 SCIP_CONSHDLRDATA* conshdlrdata;
    4145 SCIP_CONSDATA* consdata;
    4146 int c;
    4147 int v;
    4148
    4149 assert(conshdlr != NULL);
    4150 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4151 assert(conshdlrdata != NULL);
    4152
    4153 conshdlrdata->nlastcliquesneg = 0;
    4154 conshdlrdata->nlastimplsneg = 0;
    4155 conshdlrdata->nlastcliquesshorten = 0;
    4156 conshdlrdata->nlastimplsshorten = 0;
    4157
    4158 /* catch all variable event for deleted variables, which is only used in presolving */
    4159 for( c = nconss - 1; c >= 0; --c )
    4160 {
    4161 consdata = SCIPconsGetData(conss[c]);
    4162 assert(consdata != NULL);
    4163
    4164 for( v = consdata->nvars - 1; v >= 0; --v )
    4165 {
    4166 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
    4167 (SCIP_EVENTDATA*)conss[c], NULL) );
    4168 }
    4169 }
    4170
    4171 return SCIP_OKAY;
    4172}
    4173
    4174/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
    4175static
    4176SCIP_DECL_CONSEXITPRE(consExitpreLogicor)
    4177{ /*lint --e{715}*/
    4178 SCIP_CONSHDLRDATA* conshdlrdata;
    4179 SCIP_CONSDATA* consdata;
    4180 int nchgcoefs = 0;
    4181 int c;
    4182 int v;
    4183
    4184 assert(conshdlr != NULL);
    4185 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4186 assert(conshdlrdata != NULL);
    4187
    4188 /* drop all variable event for deleted variables, which was only used in presolving */
    4189 for( c = 0; c < nconss; ++c )
    4190 {
    4191 consdata = SCIPconsGetData(conss[c]);
    4192 assert(consdata != NULL);
    4193
    4194 for( v = 0; v < consdata->nvars; ++v )
    4195 {
    4196 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
    4197 (SCIP_EVENTDATA*)conss[c], -1) );
    4198 }
    4199
    4200 if( !SCIPconsIsDeleted(conss[c]) && !consdata->presolved )
    4201 {
    4202 SCIP_Bool redundant;
    4203
    4204 /* we are not allowed to detect infeasibility in the exitpre stage */
    4205 SCIP_CALL( applyFixings(scip, conss[c], conshdlrdata->eventhdlr, &redundant, &nchgcoefs, NULL, NULL) );
    4206
    4207 /* it may happen that a constraint still contains variables that are fixed to one; for example, this happens
    4208 * when variable fixings have been detected in the last presolving round by some other plugins (see #2941)
    4209 */
    4210 if( redundant )
    4211 {
    4212 SCIPdebugMsg(scip, "logic or constraint <%s> is redundant (detected during EXITPRE)\n", SCIPconsGetName(conss[c]));
    4213
    4214 if( SCIPconsIsAdded(conss[c]) )
    4215 {
    4216 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
    4217 }
    4218 else
    4219 {
    4220 /* we set the presolved flag to FALSE since not all fixing are removed if redundancy is detected */
    4221 consdata->presolved = FALSE;
    4222 }
    4223 }
    4224 }
    4225 }
    4226
    4227 return SCIP_OKAY;
    4228}
    4229
    4230/** solving process initialization method of constraint handler */
    4231static
    4232SCIP_DECL_CONSINITSOL(consInitsolLogicor)
    4233{ /*lint --e{715}*/
    4234 /* add nlrow representation to NLP, if NLP had been constructed */
    4236 {
    4237 int c;
    4238 for( c = 0; c < nconss; ++c )
    4239 {
    4240 SCIP_CALL( addNlrow(scip, conss[c]) );
    4241 }
    4242 }
    4243
    4244 return SCIP_OKAY;
    4245}
    4246
    4247/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
    4248static
    4249SCIP_DECL_CONSEXITSOL(consExitsolLogicor)
    4250{ /*lint --e{715}*/
    4251 SCIP_CONSDATA* consdata;
    4252 int c;
    4253
    4254 /* release the rows and nlrows of all constraints */
    4255 for( c = 0; c < nconss; ++c )
    4256 {
    4257 consdata = SCIPconsGetData(conss[c]);
    4258 assert(consdata != NULL);
    4259
    4260 if( consdata->row != NULL )
    4261 {
    4262 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
    4263 }
    4264
    4265 if( consdata->nlrow != NULL )
    4266 {
    4267 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
    4268 }
    4269 }
    4270
    4271 return SCIP_OKAY;
    4272}
    4273
    4274
    4275/** frees specific constraint data */
    4276static
    4277SCIP_DECL_CONSDELETE(consDeleteLogicor)
    4278{ /*lint --e{715}*/
    4279 assert(conshdlr != NULL);
    4280 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    4281 assert(consdata != NULL);
    4282 assert(*consdata != NULL);
    4283
    4285 {
    4286 SCIP_CONSHDLRDATA* conshdlrdata;
    4287 int v;
    4288
    4289 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4290 assert(conshdlrdata != NULL);
    4291
    4292 for( v = (*consdata)->nvars - 1; v >= 0; --v )
    4293 {
    4294 SCIP_CALL( SCIPdropVarEvent(scip, (*consdata)->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
    4295 (SCIP_EVENTDATA*)cons, -1) );
    4296 }
    4297 }
    4298
    4299 /* free LP row and logic or constraint */
    4300 SCIP_CALL( consdataFree(scip, consdata) );
    4301
    4302 return SCIP_OKAY;
    4303}
    4304
    4305
    4306/** transforms constraint data into data belonging to the transformed problem */
    4307static
    4308SCIP_DECL_CONSTRANS(consTransLogicor)
    4309{ /*lint --e{715}*/
    4310 SCIP_CONSDATA* sourcedata;
    4311 SCIP_CONSDATA* targetdata;
    4312
    4313 /*debugMsg(scip, "Trans method of logic or constraints\n");*/
    4314
    4315 assert(conshdlr != NULL);
    4316 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    4318 assert(sourcecons != NULL);
    4319 assert(targetcons != NULL);
    4320
    4321 sourcedata = SCIPconsGetData(sourcecons);
    4322 assert(sourcedata != NULL);
    4323 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
    4324
    4325 /* create constraint data for target constraint */
    4326 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars) );
    4327
    4328 /* create target constraint */
    4329 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
    4330 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
    4331 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
    4332 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
    4333 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
    4334
    4335 return SCIP_OKAY;
    4336}
    4337
    4338
    4339/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
    4340static
    4341SCIP_DECL_CONSINITLP(consInitlpLogicor)
    4342{ /*lint --e{715}*/
    4343 int c;
    4344
    4345 *infeasible = FALSE;
    4346
    4347 for( c = 0; c < nconss && !(*infeasible); ++c )
    4348 {
    4349 assert(SCIPconsIsInitial(conss[c]));
    4350 SCIP_CALL( addCut(scip, conss[c], infeasible) );
    4351 }
    4352
    4353 return SCIP_OKAY;
    4354}
    4355
    4356
    4357/** separation method of constraint handler for LP solutions */
    4358static
    4359SCIP_DECL_CONSSEPALP(consSepalpLogicor)
    4360{ /*lint --e{715}*/
    4361 SCIP_CONSHDLRDATA* conshdlrdata;
    4362 SCIP_Bool cutoff;
    4363 SCIP_Bool separated;
    4364 SCIP_Bool reduceddom;
    4365 int c;
    4366
    4367 assert(conshdlr != NULL);
    4368 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    4369 assert(nconss == 0 || conss != NULL);
    4370 assert(result != NULL);
    4371
    4372 SCIPdebugMsg(scip, "separating %d/%d logic or constraints\n", nusefulconss, nconss);
    4373
    4374 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4375 assert(conshdlrdata != NULL);
    4376
    4377 cutoff = FALSE;
    4378 separated = FALSE;
    4379 reduceddom = FALSE;
    4380
    4381 /* check all useful logic or constraints for feasibility */
    4382 for( c = 0; c < nusefulconss && !cutoff; ++c )
    4383 {
    4384 SCIP_CALL( separateCons(scip, conss[c], NULL, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
    4385 }
    4386
    4387 /* combine logic or constraints to get more cuts */
    4388 /**@todo further cuts of logic or constraints */
    4389
    4390 /* return the correct result */
    4391 if( cutoff )
    4392 *result = SCIP_CUTOFF;
    4393 else if( reduceddom )
    4394 *result = SCIP_REDUCEDDOM;
    4395 else if( separated )
    4396 *result = SCIP_SEPARATED;
    4397 else
    4398 *result = SCIP_DIDNOTFIND;
    4399
    4400 return SCIP_OKAY;
    4401}
    4402
    4403
    4404/** separation method of constraint handler for arbitrary primal solutions */
    4405static
    4406SCIP_DECL_CONSSEPASOL(consSepasolLogicor)
    4407{ /*lint --e{715}*/
    4408 SCIP_CONSHDLRDATA* conshdlrdata;
    4409 SCIP_Bool cutoff;
    4410 SCIP_Bool separated;
    4411 SCIP_Bool reduceddom;
    4412 int c;
    4413
    4414 assert(conshdlr != NULL);
    4415 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    4416 assert(nconss == 0 || conss != NULL);
    4417 assert(result != NULL);
    4418
    4419 SCIPdebugMsg(scip, "separating %d/%d logic or constraints\n", nusefulconss, nconss);
    4420
    4421 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4422 assert(conshdlrdata != NULL);
    4423
    4424 cutoff = FALSE;
    4425 separated = FALSE;
    4426 reduceddom = FALSE;
    4427
    4428 /* check all useful logic or constraints for feasibility */
    4429 for( c = 0; c < nusefulconss && !cutoff; ++c )
    4430 {
    4431 SCIP_CALL( separateCons(scip, conss[c], sol, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
    4432 }
    4433
    4434 /* combine logic or constraints to get more cuts */
    4435 /**@todo further cuts of logic or constraints */
    4436
    4437 /* return the correct result */
    4438 if( cutoff )
    4439 *result = SCIP_CUTOFF;
    4440 else if( reduceddom )
    4441 *result = SCIP_REDUCEDDOM;
    4442 else if( separated )
    4443 *result = SCIP_SEPARATED;
    4444 else
    4445 *result = SCIP_DIDNOTFIND;
    4446
    4447 return SCIP_OKAY;
    4448}
    4449
    4450
    4451/** constraint enforcing method of constraint handler for LP solutions */
    4452static
    4453SCIP_DECL_CONSENFOLP(consEnfolpLogicor)
    4454{ /*lint --e{715}*/
    4455 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
    4456
    4457 return SCIP_OKAY;
    4458}
    4459
    4460
    4461/** constraint enforcing method of constraint handler for relaxation solutions */
    4462static
    4463SCIP_DECL_CONSENFORELAX(consEnforelaxLogicor)
    4464{ /*lint --e{715}*/
    4465 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
    4466
    4467 return SCIP_OKAY;
    4468}
    4469
    4470
    4471/** constraint enforcing method of constraint handler for pseudo solutions */
    4472static
    4473SCIP_DECL_CONSENFOPS(consEnfopsLogicor)
    4474{ /*lint --e{715}*/
    4475 SCIP_CONSHDLRDATA* conshdlrdata;
    4476 SCIP_Bool cutoff;
    4477 SCIP_Bool infeasible;
    4478 SCIP_Bool reduceddom;
    4479 SCIP_Bool solvelp;
    4480 int c;
    4481
    4482 assert(conshdlr != NULL);
    4483 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    4484 assert(nconss == 0 || conss != NULL);
    4485 assert(result != NULL);
    4486
    4487 SCIPdebugMsg(scip, "pseudo enforcing %d logic or constraints\n", nconss);
    4488
    4489 *result = SCIP_FEASIBLE;
    4490
    4491 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4492 assert(conshdlrdata != NULL);
    4493
    4494 cutoff = FALSE;
    4495 infeasible = FALSE;
    4496 reduceddom = FALSE;
    4497 solvelp = FALSE;
    4498
    4499 /* check all logic or constraints for feasibility */
    4500 for( c = 0; c < nconss && !cutoff && !reduceddom && !solvelp; ++c )
    4501 {
    4502 SCIP_CALL( enforcePseudo(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &infeasible, &reduceddom, &solvelp) );
    4503 }
    4504
    4505 if( cutoff )
    4506 *result = SCIP_CUTOFF;
    4507 else if( reduceddom )
    4508 *result = SCIP_REDUCEDDOM;
    4509 else if( solvelp )
    4510 *result = SCIP_SOLVELP;
    4511 else if( infeasible )
    4512 *result = SCIP_INFEASIBLE;
    4513
    4514 return SCIP_OKAY;
    4515}
    4516
    4517
    4518/** feasibility check method of constraint handler for integral solutions */
    4519static
    4520SCIP_DECL_CONSCHECK(consCheckLogicor)
    4521{ /*lint --e{715}*/
    4522 SCIP_CONS* cons;
    4523 SCIP_CONSDATA* consdata;
    4524 int c;
    4525
    4526 assert(conshdlr != NULL);
    4527 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    4528 assert(nconss == 0 || conss != NULL);
    4529 assert(result != NULL);
    4530
    4531 *result = SCIP_FEASIBLE;
    4532
    4533 /* check all logic or constraints for feasibility */
    4534 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
    4535 {
    4536 cons = conss[c];
    4537 consdata = SCIPconsGetData(cons);
    4538 assert(consdata != NULL);
    4539 if( checklprows || consdata->row == NULL || !SCIProwIsInLP(consdata->row) )
    4540 {
    4541 if( isConsViolated(scip, cons, sol) )
    4542 {
    4543 /* constraint is violated */
    4544 *result = SCIP_INFEASIBLE;
    4545
    4546 if( printreason )
    4547 {
    4548#ifndef NDEBUG
    4549 int v;
    4550 for( v = 0; v < consdata->nvars; ++v )
    4551 {
    4552 assert( consdata->vars[v] != NULL);
    4553 assert( SCIPvarIsBinary(consdata->vars[v]) );
    4554 assert( SCIPisFeasLT(scip, SCIPgetSolVal(scip, sol, consdata->vars[v]), 1.0) );
    4555 }
    4556#endif
    4557 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
    4558 SCIPinfoMessage(scip, NULL, ";\n");
    4559 SCIPinfoMessage(scip, NULL, "violation: all variables are set to zero\n");
    4560 }
    4561 }
    4562 }
    4563 }
    4564
    4565 return SCIP_OKAY;
    4566}
    4567
    4568
    4569/** domain propagation method of constraint handler */
    4570static
    4571SCIP_DECL_CONSPROP(consPropLogicor)
    4572{ /*lint --e{715}*/
    4573 SCIP_CONSHDLRDATA* conshdlrdata;
    4574 SCIP_Bool cutoff;
    4575 SCIP_Bool reduceddom;
    4576 SCIP_Bool addcut;
    4577 SCIP_Bool mustcheck;
    4578 int c;
    4579#ifndef NDEBUG
    4581#endif
    4582
    4583 assert(conshdlr != NULL);
    4584 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    4585 assert(nconss == 0 || conss != NULL);
    4586 assert(result != NULL);
    4587
    4588 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4589 assert(conshdlrdata != NULL);
    4590
    4591 cutoff = FALSE;
    4592 reduceddom = FALSE;
    4593
    4594 /* propagate all useful logic or constraints */
    4595 for( c = 0; c < nusefulconss && !cutoff; ++c )
    4596 {
    4597 assert(inpresolve || !(SCIPconsGetData(conss[c])->existmultaggr));
    4598
    4599 SCIPdebugMsg(scip, " propagate constraint %s\n", SCIPconsGetName(conss[c]));
    4600 SCIP_CALL( processWatchedVars(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &reduceddom, &addcut, &mustcheck) );
    4601 }
    4602
    4603 /* return the correct result */
    4604 if( cutoff )
    4605 *result = SCIP_CUTOFF;
    4606 else if( reduceddom )
    4607 *result = SCIP_REDUCEDDOM;
    4608 else
    4609 *result = SCIP_DIDNOTFIND;
    4610
    4611 return SCIP_OKAY; /*lint !e438*/
    4612}
    4613
    4614/** presolving method of constraint handler */
    4615static
    4616SCIP_DECL_CONSPRESOL(consPresolLogicor)
    4617{ /*lint --e{715}*/
    4618 SCIP_CONSHDLRDATA* conshdlrdata;
    4619 SCIP_CONS* cons;
    4620 SCIP_CONSDATA* consdata;
    4621 unsigned char* entries;
    4622 SCIP_Bool redundant;
    4623 int c;
    4624 int firstchange;
    4625 int nentries;
    4626 int oldnfixedvars;
    4627 int oldnchgbds;
    4628 int oldndelconss;
    4629 int oldnupgdconss;
    4630 int oldnchgcoefs;
    4631
    4632 assert(conshdlr != NULL);
    4633 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    4634 assert(scip != NULL);
    4635 assert(result != NULL);
    4636
    4637 *result = SCIP_DIDNOTFIND;
    4638
    4639 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4640 assert(conshdlrdata != NULL);
    4641
    4642 nentries = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
    4643
    4644 oldnfixedvars = *nfixedvars;
    4645 oldnchgbds = *nchgbds;
    4646 oldndelconss = *ndelconss;
    4647 oldnupgdconss = *nupgdconss;
    4648 oldnchgcoefs = *nchgcoefs;
    4649
    4650 firstchange = INT_MAX;
    4651
    4652 SCIP_CALL( SCIPallocBufferArray(scip, &entries, nentries) );
    4653
    4654 /* process constraints */
    4655 for( c = 0; c < nconss && *result != SCIP_CUTOFF && !SCIPisStopped(scip); ++c )
    4656 {
    4657 cons = conss[c];
    4658 assert(cons != NULL);
    4659 consdata = SCIPconsGetData(cons);
    4660 assert(consdata != NULL);
    4661
    4662 SCIPdebugMsg(scip, "presolving logic or constraint <%s>\n", SCIPconsGetName(cons));
    4663
    4664 /* force presolving the constraint in the initial round */
    4665 if( nrounds == 0 )
    4666 {
    4668 }
    4669
    4670 redundant = FALSE;
    4671 if( !consdata->presolved )
    4672 {
    4673 /* remove all variables that are fixed to zero, check redundancy due to fixed-to-one variable */
    4674 SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, &redundant, nchgcoefs, naddconss, ndelconss) );
    4675 }
    4676
    4677 if( SCIPconsIsDeleted(cons) )
    4678 continue;
    4679
    4680 /* find pairs of negated variables in constraint: constraint is redundant */
    4681 /* find sets of equal variables in constraint: multiple entries of variable can be replaced by single entry */
    4682 if( !redundant )
    4683 {
    4684 SCIP_CALL( mergeMultiples(scip, cons, conshdlrdata->eventhdlr, &entries, &nentries, &redundant, nchgcoefs) );
    4685 }
    4686
    4687 if( redundant )
    4688 {
    4689 SCIPdebugMsg(scip, "logic or constraint <%s> is redundant\n", SCIPconsGetName(cons));
    4690 SCIP_CALL( SCIPdelCons(scip, cons) );
    4691 (*ndelconss)++;
    4692 *result = SCIP_SUCCESS;
    4693 continue;
    4694 }
    4695 else if( !SCIPconsIsModifiable(cons) )
    4696 {
    4697 if( consdata->nvars <= 2 )
    4698 {
    4699 SCIP_Bool cutoff;
    4700
    4701 /* handle all cases with less than three variables in a logicor constraint */
    4702 SCIP_CALL( fixDeleteOrUpgradeCons(scip, cons, conshdlrdata->eventhdlr, conshdlrdata->conshdlrlinear,
    4703 conshdlrdata->conshdlrsetppc, nfixedvars, nchgbds, nchgcoefs, ndelconss, naddconss, nupgdconss, &cutoff) );
    4704
    4705 if( cutoff )
    4706 {
    4707 *result = SCIP_CUTOFF;
    4708 goto TERMINATE;
    4709 }
    4710 else if( *nfixedvars > oldnfixedvars || *nchgbds > oldnchgbds || *nchgcoefs > oldnchgcoefs
    4711 || *ndelconss > oldndelconss || *nupgdconss > oldnupgdconss )
    4712 *result = SCIP_SUCCESS;
    4713
    4714 if( SCIPconsIsDeleted(cons) )
    4715 continue;
    4716 }
    4717 }
    4718
    4719 /* perform dual reductions */
    4720 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
    4721 {
    4722 SCIP_CALL( dualPresolving(scip, cons, conshdlrdata->eventhdlr, nfixedvars, ndelconss, nchgcoefs, naggrvars, result) );
    4723
    4724 /* if dual reduction deleted the constraint we take the next */
    4725 if( !SCIPconsIsActive(cons) )
    4726 continue;
    4727
    4728 /* in dualpresolving we may have removed variables, so we need to take care of special cases */
    4729 if( consdata->nvars <= 2 )
    4730 {
    4731 SCIP_Bool cutoff;
    4732
    4733 /* handle all cases with less than three variables in a logicor constraint */
    4734 SCIP_CALL( fixDeleteOrUpgradeCons(scip, cons, conshdlrdata->eventhdlr, conshdlrdata->conshdlrlinear,
    4735 conshdlrdata->conshdlrsetppc, nfixedvars, nchgbds, nchgcoefs, ndelconss, naddconss, nupgdconss, &cutoff) );
    4736
    4737 if( cutoff )
    4738 {
    4739 *result = SCIP_CUTOFF;
    4740 goto TERMINATE;
    4741 }
    4742 else if( *nfixedvars > oldnfixedvars || *nchgbds > oldnchgbds || *nchgcoefs > oldnchgcoefs
    4743 || *ndelconss > oldndelconss || *nupgdconss > oldnupgdconss )
    4744 *result = SCIP_SUCCESS;
    4745
    4746 if( SCIPconsIsDeleted(cons) )
    4747 continue;
    4748 }
    4749 }
    4750
    4751 /* remember the first changed constraint to begin the next redundancy round with */
    4752 if( firstchange == INT_MAX && consdata->changed )
    4753 firstchange = c;
    4754
    4755 assert(consdata->nvars >= 2 || SCIPconsIsModifiable(cons));
    4756 }
    4757
    4758 assert(*result != SCIP_CUTOFF);
    4759
    4760 /* fast preprocessing of pairs of logic or constraints, used for equal constraints */
    4761 if( firstchange < nconss && conshdlrdata->presolusehashing )
    4762 {
    4763 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
    4764 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, ndelconss) );
    4765 }
    4766
    4767 /* preprocess pairs of logic or constraints and apply negated clique presolving */
    4769 {
    4770 SCIP_Bool cutoff = FALSE;
    4771
    4772 /* check constraints for redundancy */
    4773 if( conshdlrdata->presolpairwise && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
    4774 {
    4775 SCIP_CALL( removeRedundantConssAndNonzeros(scip, conss, nconss, &entries, &nentries, conshdlrdata->eventhdlr,
    4776 conshdlrdata->usestrengthening, &firstchange, nfixedvars, ndelconss, nchgcoefs, &cutoff) );
    4777
    4778 if( cutoff )
    4779 {
    4780 *result = SCIP_CUTOFF;
    4781 goto TERMINATE;
    4782 }
    4783 }
    4784
    4786 {
    4787 /* try to tighten constraints by reducing the number of variables in the constraints using implications and
    4788 * cliques, also derive fixations through them, @see SCIPshrinkDisjunctiveVarSet()
    4789 */
    4790 if( conshdlrdata->useimplications && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
    4791 {
    4792 SCIP_CALL( shortenConss(scip, conshdlrdata, conshdlrdata->eventhdlr, conss, nconss,
    4793 &entries, &nentries, nfixedvars, ndelconss, nchgcoefs, &cutoff) );
    4794
    4795 if( cutoff )
    4796 {
    4797 *result = SCIP_CUTOFF;
    4798 goto TERMINATE;
    4799 }
    4800 }
    4801
    4802 /* check for redundant constraints due to negated clique information */
    4803 if( conshdlrdata->usenegatedclique && (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0 )
    4804 {
    4805 SCIP_CALL( removeConstraintsDueToNegCliques(scip, conshdlr, conshdlrdata->conshdlrsetppc,
    4806 conshdlrdata->eventhdlr, conss, nconss, &entries, &nentries, nfixedvars, ndelconss,
    4807 nupgdconss, nchgcoefs, &cutoff) );
    4808
    4809 if( cutoff )
    4810 {
    4811 *result = SCIP_CUTOFF;
    4812 goto TERMINATE;
    4813 }
    4814 }
    4815 }
    4816 }
    4817
    4818 TERMINATE:
    4819
    4820 SCIPfreeBufferArray(scip, &entries);
    4821
    4822 return SCIP_OKAY;
    4823}
    4824
    4825
    4826/** propagation conflict resolving method of constraint handler */
    4827static
    4828SCIP_DECL_CONSRESPROP(consRespropLogicor)
    4829{ /*lint --e{715}*/
    4830 SCIP_CONSDATA* consdata;
    4831#ifndef NDEBUG
    4832 SCIP_Bool infervarfound;
    4833#endif
    4834 int v;
    4835
    4836 assert(conshdlr != NULL);
    4837 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    4838 assert(cons != NULL);
    4839 assert(infervar != NULL);
    4840 assert(result != NULL);
    4841
    4842 consdata = SCIPconsGetData(cons);
    4843 assert(consdata != NULL);
    4844
    4845 SCIPdebugMsg(scip, "conflict resolving method of logic or constraint handler\n");
    4846
    4847 /* the only deductions are variables inferred to 1.0 on logic or constraints where all other variables
    4848 * are assigned to zero
    4849 */
    4850 assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5); /* the inference variable must be assigned to one */
    4851
    4852#ifndef NDEBUG
    4853 infervarfound = FALSE;
    4854#endif
    4855 for( v = 0; v < consdata->nvars; ++v )
    4856 {
    4857 if( consdata->vars[v] != infervar )
    4858 {
    4859 /* the reason variable must have been assigned to zero */
    4860 assert(SCIPgetVarUbAtIndex(scip, consdata->vars[v], bdchgidx, FALSE) < 0.5);
    4861 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
    4862 }
    4863#ifndef NDEBUG
    4864 else
    4865 {
    4866 assert(!infervarfound);
    4867 infervarfound = TRUE;
    4868 }
    4869#endif
    4870 }
    4871 assert(infervarfound);
    4872
    4873 *result = SCIP_SUCCESS;
    4874
    4875 return SCIP_OKAY;
    4876}
    4877
    4878
    4879/** variable rounding lock method of constraint handler */
    4880static
    4881SCIP_DECL_CONSLOCK(consLockLogicor)
    4882{ /*lint --e{715}*/
    4883 SCIP_CONSDATA* consdata;
    4884 int i;
    4885
    4886 consdata = SCIPconsGetData(cons);
    4887 assert(consdata != NULL);
    4888
    4889 /* lock every single coefficient */
    4890 for( i = 0; i < consdata->nvars; ++i )
    4891 {
    4892 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
    4893 }
    4894
    4895 return SCIP_OKAY;
    4896}
    4897
    4898
    4899/** constraint activation notification method of constraint handler */
    4900static
    4901SCIP_DECL_CONSACTIVE(consActiveLogicor)
    4902{ /*lint --e{715}*/
    4903 SCIP_CONSHDLRDATA* conshdlrdata;
    4904 SCIP_CONSDATA* consdata;
    4905
    4906 assert(conshdlr != NULL);
    4907 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    4908 assert(cons != NULL);
    4909 assert(SCIPconsIsTransformed(cons));
    4910
    4911 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4912 assert(conshdlrdata != NULL);
    4913 consdata = SCIPconsGetData(cons);
    4914 assert(consdata != NULL);
    4915 assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
    4916
    4917 SCIPdebugMsg(scip, "activating information for logic or constraint <%s>\n", SCIPconsGetName(cons));
    4918 SCIPdebug( SCIP_CALL( consdataPrint(scip, consdata, NULL, TRUE) ) );
    4919
    4920 /* catch events on watched variables */
    4921 if( consdata->watchedvar1 != -1 )
    4922 {
    4923 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[consdata->watchedvar1],
    4924 SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
    4925 &consdata->filterpos1) );
    4926 }
    4927 if( consdata->watchedvar2 != -1 )
    4928 {
    4929 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[consdata->watchedvar2],
    4930 SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
    4931 &consdata->filterpos2) );
    4932 }
    4933
    4935 {
    4936 SCIP_CALL( addNlrow(scip, cons) );
    4937 }
    4938
    4939 return SCIP_OKAY;
    4940}
    4941
    4942
    4943/** constraint deactivation notification method of constraint handler */
    4944static
    4945SCIP_DECL_CONSDEACTIVE(consDeactiveLogicor)
    4946{ /*lint --e{715}*/
    4947 SCIP_CONSHDLRDATA* conshdlrdata;
    4948 SCIP_CONSDATA* consdata;
    4949
    4950 assert(conshdlr != NULL);
    4951 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    4952 assert(cons != NULL);
    4953 assert(SCIPconsIsTransformed(cons));
    4954
    4955 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4956 assert(conshdlrdata != NULL);
    4957 consdata = SCIPconsGetData(cons);
    4958 assert(consdata != NULL);
    4959 assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
    4960
    4961 SCIPdebugMsg(scip, "deactivating information for logic or constraint <%s>\n", SCIPconsGetName(cons));
    4962 SCIPdebug( SCIP_CALL( consdataPrint(scip, consdata, NULL, TRUE) ) );
    4963
    4964 /* drop events on watched variables */
    4965 if( consdata->watchedvar1 != -1 )
    4966 {
    4967 assert(consdata->filterpos1 != -1);
    4968 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar1],
    4969 SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
    4970 consdata->filterpos1) );
    4971 consdata->watchedvar1 = -1;
    4972 consdata->filterpos1 = -1;
    4973 }
    4974 if( consdata->watchedvar2 != -1 )
    4975 {
    4976 assert(consdata->filterpos2 != -1);
    4977 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar2],
    4978 SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
    4979 consdata->filterpos2) );
    4980 consdata->watchedvar2 = -1;
    4981 consdata->filterpos2 = -1;
    4982 }
    4983
    4984 /* remove row from NLP, if still in solving
    4985 * if we are in exitsolve, the whole NLP will be freed anyway
    4986 */
    4987 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
    4988 {
    4989 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
    4990 }
    4991
    4992 return SCIP_OKAY;
    4993}
    4994
    4995
    4996/** constraint display method of constraint handler */
    4997static
    4998SCIP_DECL_CONSPRINT(consPrintLogicor)
    4999{ /*lint --e{715}*/
    5000 assert( scip != NULL );
    5001 assert( conshdlr != NULL );
    5002 assert( cons != NULL );
    5003
    5005
    5006 return SCIP_OKAY;
    5007}
    5008
    5009/** constraint copying method of constraint handler */
    5010static
    5011SCIP_DECL_CONSCOPY(consCopyLogicor)
    5012{ /*lint --e{715}*/
    5013 SCIP_VAR** sourcevars;
    5014 const char* consname;
    5015 int nvars;
    5016
    5017 /* get variables and coefficients of the source constraint */
    5018 sourcevars = SCIPgetVarsLogicor(sourcescip, sourcecons);
    5019 nvars = SCIPgetNVarsLogicor(sourcescip, sourcecons);
    5020
    5021 if( name != NULL )
    5022 consname = name;
    5023 else
    5024 consname = SCIPconsGetName(sourcecons);
    5025
    5026 /* copy the logic using the linear constraint copy method */
    5027 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, NULL,
    5028 1.0, SCIPinfinity(scip), varmap, consmap,
    5029 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
    5030 assert(cons != NULL);
    5031
    5032 return SCIP_OKAY;
    5033}
    5034
    5035/** constraint parsing method of constraint handler */
    5036static
    5037SCIP_DECL_CONSPARSE(consParseLogicor)
    5038{ /*lint --e{715}*/
    5039 SCIP_VAR** vars;
    5040 char* strcopy;
    5041 char* endptr;
    5042 char* startptr;
    5043 int requiredsize;
    5044 int varssize;
    5045 int nvars;
    5046
    5047 SCIPdebugMsg(scip, "parse <%s> as logicor constraint\n", str);
    5048
    5049 *success = FALSE;
    5050
    5051 /* cutoff "logicor" from the constraint string */
    5052 startptr = strchr((char*)str, '(');
    5053
    5054 if( startptr == NULL )
    5055 {
    5056 SCIPerrorMessage("missing starting character '(' parsing logicor\n");
    5057 return SCIP_OKAY;
    5058 }
    5059
    5060 /* skip '(' */
    5061 ++startptr;
    5062
    5063 /* find end character ')' */
    5064 endptr = strrchr(startptr, ')');
    5065
    5066 if( endptr == NULL )
    5067 {
    5068 SCIPerrorMessage("missing ending character ')' parsing logicor\n");
    5069 return SCIP_OKAY;
    5070 }
    5071 assert(endptr >= startptr);
    5072
    5073 if( endptr > startptr )
    5074 {
    5075 /* copy string for parsing; note that SCIPskipSpace() in SCIPparseVarsList() requires that strcopy ends with '\0' */
    5076 SCIP_CALL( SCIPduplicateBufferArray(scip, &strcopy, startptr, (int)(endptr-startptr+1)) );
    5077 strcopy[endptr-startptr] = '\0';
    5078 varssize = 100;
    5079 nvars = 0;
    5080
    5081 /* allocate buffer array for variables */
    5082 SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
    5083
    5084 /* parse string */
    5085 SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
    5086
    5087 if( *success )
    5088 {
    5089 /* check if the size of the variable array was great enough */
    5090 if( varssize < requiredsize )
    5091 {
    5092 /* reallocate memory */
    5093 varssize = requiredsize;
    5094 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
    5095
    5096 /* parse string again with the correct size of the variable array */
    5097 SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
    5098 }
    5099
    5100 assert(*success);
    5101 assert(varssize >= requiredsize);
    5102
    5103 /* create logicor constraint */
    5104 SCIP_CALL( SCIPcreateConsLogicor(scip, cons, name, nvars, vars,
    5105 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    5106 }
    5107
    5108 /* free buffers */
    5109 SCIPfreeBufferArray(scip, &vars);
    5110 SCIPfreeBufferArray(scip, &strcopy);
    5111 }
    5112 else
    5113 {
    5114 if( !modifiable )
    5115 {
    5116 SCIPerrorMessage("cannot create empty logicor constraint\n");
    5117 return SCIP_OKAY;
    5118 }
    5119
    5120 /* create empty logicor constraint */
    5121 SCIP_CALL( SCIPcreateConsLogicor(scip, cons, name, 0, NULL,
    5122 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    5123
    5124 *success = TRUE;
    5125 }
    5126
    5127 return SCIP_OKAY;
    5128}
    5129
    5130/** constraint method of constraint handler which returns the variables (if possible) */
    5131static
    5132SCIP_DECL_CONSGETVARS(consGetVarsLogicor)
    5133{ /*lint --e{715}*/
    5134 SCIP_CONSDATA* consdata;
    5135
    5136 consdata = SCIPconsGetData(cons);
    5137 assert(consdata != NULL);
    5138
    5139 if( varssize < consdata->nvars )
    5140 (*success) = FALSE;
    5141 else
    5142 {
    5143 assert(vars != NULL);
    5144
    5145 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
    5146 (*success) = TRUE;
    5147 }
    5148
    5149 return SCIP_OKAY;
    5150}
    5151
    5152/** constraint method of constraint handler which returns the number of variables (if possible) */
    5153static
    5154SCIP_DECL_CONSGETNVARS(consGetNVarsLogicor)
    5155{ /*lint --e{715}*/
    5156 SCIP_CONSDATA* consdata;
    5157
    5158 consdata = SCIPconsGetData(cons);
    5159 assert(consdata != NULL);
    5160
    5161 (*nvars) = consdata->nvars;
    5162 (*success) = TRUE;
    5163
    5164 return SCIP_OKAY;
    5165}
    5166
    5167/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
    5168static
    5169SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLogicor)
    5170{ /*lint --e{715}*/
    5171 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
    5172
    5173 return SCIP_OKAY;
    5174}
    5175
    5176/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
    5177static
    5178SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLogicor)
    5179{ /*lint --e{715}*/
    5180 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
    5181
    5182 return SCIP_OKAY;
    5183}
    5184
    5185/*
    5186 * Callback methods of event handler
    5187 */
    5188
    5189static
    5190SCIP_DECL_EVENTEXEC(eventExecLogicor)
    5191{ /*lint --e{715}*/
    5192 assert(eventhdlr != NULL);
    5193 assert(eventdata != NULL);
    5194 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
    5195 assert(event != NULL);
    5196
    5197 SCIPdebugMsg(scip, "exec method of event handler for logic or constraints\n");
    5198
    5200 {
    5201 SCIPdebugMsg(scip, "enabling constraint cons <%s> at depth %d\n", SCIPconsGetName((SCIP_CONS*)eventdata), SCIPgetDepth(scip));
    5202
    5203 SCIP_CALL( SCIPenableCons(scip, (SCIP_CONS*)eventdata) );
    5205 }
    5206 else if( SCIPeventGetType(event) == SCIP_EVENTTYPE_UBTIGHTENED )
    5207 {
    5209 }
    5210
    5212 {
    5213 SCIP_VAR* var = SCIPeventGetVar(event);
    5214 SCIP_CONS* cons = (SCIP_CONS*)eventdata;
    5215 SCIP_CONSDATA* consdata;
    5216
    5217 assert(cons != NULL);
    5218 consdata = SCIPconsGetData(cons);
    5219 assert(consdata != NULL);
    5220
    5221 /* we only catch this event in presolving stage */
    5223 assert(var != NULL);
    5224
    5225 consdata->presolved = FALSE;
    5226
    5228 {
    5229 if( SCIPconsIsActive(cons) )
    5230 {
    5231 if( SCIPvarGetLbGlobal(var) < 0.5 && SCIPvarGetUbGlobal(var) > 0.5 )
    5232 consdata->merged = FALSE;
    5233
    5234 if( !consdata->existmultaggr )
    5235 {
    5237 consdata->existmultaggr = TRUE;
    5238 }
    5239 }
    5240 }
    5241 }
    5242
    5243 return SCIP_OKAY;
    5244}
    5245
    5246
    5247/*
    5248 * Callback methods of conflict handler
    5249 */
    5250
    5251/** conflict processing method of conflict handler (called when conflict was found) */
    5252static
    5253SCIP_DECL_CONFLICTEXEC(conflictExecLogicor)
    5254{ /*lint --e{715}*/
    5255 SCIP_VAR** vars;
    5256 int i;
    5257
    5258 assert(conflicthdlr != NULL);
    5259 assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
    5260 assert(bdchginfos != NULL || nbdchginfos == 0);
    5261 assert(result != NULL);
    5262
    5263 *result = SCIP_DIDNOTRUN;
    5264
    5265 /* don't process already resolved conflicts */
    5266 if( resolved )
    5267 return SCIP_OKAY;
    5268
    5269 /* if the conflict consists of only two (binary) variables, it will be handled by the setppc conflict handler */
    5270 if( nbdchginfos == 2 )
    5271 return SCIP_OKAY;
    5272
    5273 *result = SCIP_DIDNOTFIND;
    5274
    5275 /* create array of variables in conflict constraint */
    5276 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
    5277 for( i = 0; i < nbdchginfos; ++i )
    5278 {
    5279 assert(bdchginfos != NULL); /* for flexelint */
    5280 assert(bdchginfos[i] != NULL);
    5281
    5282 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
    5283
    5284 /* we can only treat binary variables */
    5285 if( !SCIPvarIsBinary(vars[i]) )
    5286 break;
    5287
    5288 /* if the variable is fixed to one in the conflict set, we have to use its negation */
    5289 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) > 0.5 )
    5290 {
    5291 SCIP_CALL( SCIPgetNegatedVar(scip, vars[i], &vars[i]) );
    5292 }
    5293 }
    5294
    5295 if( i == nbdchginfos )
    5296 {
    5297 SCIP_CONS* cons;
    5298 char consname[SCIP_MAXSTRLEN];
    5299
    5300 /* create a constraint out of the conflict set */
    5302 SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, consname, nbdchginfos, vars,
    5303 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
    5304
    5305 /* add conflict to SCIP */
    5306 SCIP_CALL( SCIPaddConflict(scip, node, &cons, validnode, conftype, cutoffinvolved) );
    5307
    5308 *result = SCIP_CONSADDED;
    5309 }
    5310
    5311 /* free temporary memory */
    5312 SCIPfreeBufferArray(scip, &vars);
    5313
    5314 return SCIP_OKAY;
    5315}
    5316
    5317
    5318/*
    5319 * constraint specific interface methods
    5320 */
    5321
    5322/** creates the handler for logic or constraints and includes it in SCIP */
    5324 SCIP* scip /**< SCIP data structure */
    5325 )
    5326{
    5327 SCIP_CONSHDLRDATA* conshdlrdata;
    5328 SCIP_CONSHDLR* conshdlr;
    5329 SCIP_CONFLICTHDLR* conflicthdlr;
    5330 SCIP_EVENTHDLR* eventhdlr;
    5331
    5332 /* create event handler for events on watched variables */
    5334 eventExecLogicor, NULL) );
    5335
    5336 /* create conflict handler for logic or constraints */
    5338 conflictExecLogicor, NULL) );
    5339
    5340 /* create constraint handler data */
    5341 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
    5342
    5343 /* include constraint handler */
    5346 consEnfolpLogicor, consEnfopsLogicor, consCheckLogicor, consLockLogicor,
    5347 conshdlrdata) );
    5348 assert(conshdlr != NULL);
    5349
    5350 /* set non-fundamental callbacks via specific setter functions */
    5351 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLogicor) );
    5352 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLogicor, consCopyLogicor) );
    5353 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLogicor) );
    5354 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLogicor) );
    5355 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLogicor) );
    5356 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLogicor) );
    5357 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLogicor) );
    5358 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLogicor) );
    5359 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLogicor) );
    5360 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLogicor) );
    5361 SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreLogicor) );
    5362 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLogicor) );
    5363 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLogicor) );
    5365 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLogicor) );
    5368 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLogicor) );
    5369 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLogicor, consSepasolLogicor, CONSHDLR_SEPAFREQ,
    5371 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLogicor) );
    5372 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLogicor) );
    5373 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLogicor) );
    5374 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLogicor) );
    5375
    5376 conshdlrdata->conshdlrlinear = SCIPfindConshdlr(scip, "linear");
    5377 conshdlrdata->conshdlrsetppc = SCIPfindConshdlr(scip, "setppc");
    5378
    5379 if( conshdlrdata->conshdlrlinear != NULL )
    5380 {
    5381 /* include the linear constraint to logicor constraint upgrade in the linear constraint handler */
    5383 }
    5384
    5385 /* logic or constraint handler parameters */
    5387 "constraints/logicor/presolpairwise",
    5388 "should pairwise constraint comparison be performed in presolving?",
    5389 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
    5391 "constraints/logicor/presolusehashing",
    5392 "should hash table be used for detecting redundant constraints in advance",
    5393 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
    5395 "constraints/logicor/dualpresolving",
    5396 "should dual presolving steps be performed?",
    5397 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
    5399 "constraints/logicor/negatedclique",
    5400 "should negated clique information be used in presolving",
    5401 &conshdlrdata->usenegatedclique, TRUE, DEFAULT_NEGATEDCLIQUE, NULL, NULL) );
    5403 "constraints/logicor/implications",
    5404 "should implications/cliques be used in presolving",
    5405 &conshdlrdata->useimplications, TRUE, DEFAULT_IMPLICATIONS, NULL, NULL) );
    5407 "constraints/logicor/strengthen",
    5408 "should pairwise constraint comparison try to strengthen constraints by removing superflous non-zeros?",
    5409 &conshdlrdata->usestrengthening, TRUE, DEFAULT_STRENGTHEN, NULL, NULL) );
    5410
    5411 return SCIP_OKAY;
    5412}
    5413
    5414
    5415/** creates and captures a logic or constraint
    5416 *
    5417 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    5418 */
    5420 SCIP* scip, /**< SCIP data structure */
    5421 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    5422 const char* name, /**< name of constraint */
    5423 int nvars, /**< number of variables in the constraint */
    5424 SCIP_VAR** vars, /**< array with variables of constraint entries */
    5425 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
    5426 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    5427 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
    5428 * Usually set to TRUE. */
    5429 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    5430 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    5431 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    5432 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    5433 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
    5434 * Usually set to TRUE. */
    5435 SCIP_Bool local, /**< is constraint only valid locally?
    5436 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    5437 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
    5438 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
    5439 * adds coefficients to this constraint. */
    5440 SCIP_Bool dynamic, /**< is constraint subject to aging?
    5441 * Usually set to FALSE. Set to TRUE for own cuts which
    5442 * are separated as constraints. */
    5443 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
    5444 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
    5445 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    5446 * if it may be moved to a more global node?
    5447 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
    5448 )
    5449{
    5450 SCIP_CONSHDLR* conshdlr;
    5451 SCIP_CONSDATA* consdata;
    5452 int i;
    5453
    5454 assert(scip != NULL);
    5455
    5456 /* find the logicor constraint handler */
    5457 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    5458 if( conshdlr == NULL )
    5459 {
    5460 SCIPerrorMessage("logic or constraint handler not found\n");
    5461 return SCIP_INVALIDCALL;
    5462 }
    5463
    5464 /* check whether all variables are binary */
    5465 assert(vars != NULL || nvars == 0);
    5466 for( i = 0; i < nvars; ++i )
    5467 {
    5468 if( !SCIPvarIsBinary(vars[i]) )
    5469 {
    5470 SCIPerrorMessage("operand <%s> is not binary\n", SCIPvarGetName(vars[i]));
    5471 return SCIP_INVALIDDATA;
    5472 }
    5473 }
    5474
    5475 /* create the constraint specific data */
    5476 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars) );
    5477
    5478 /* create constraint */
    5479 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
    5480 local, modifiable, dynamic, removable, stickingatnode) );
    5481
    5483 {
    5484 SCIP_CONSHDLRDATA* conshdlrdata;
    5485 int v;
    5486
    5487 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    5488 assert(conshdlrdata != NULL);
    5489
    5490 for( v = consdata->nvars - 1; v >= 0; --v )
    5491 {
    5492 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
    5493 (SCIP_EVENTDATA*)(*cons), NULL) );
    5494 }
    5495 }
    5496
    5497 return SCIP_OKAY;
    5498}
    5499
    5500/** creates and captures a logicor constraint
    5501 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
    5502 * method SCIPcreateConsLogicor(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
    5503 *
    5504 * @see SCIPcreateConsLogicor() for information about the basic constraint flag configuration
    5505 *
    5506 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    5507 */
    5509 SCIP* scip, /**< SCIP data structure */
    5510 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    5511 const char* name, /**< name of constraint */
    5512 int nvars, /**< number of variables in the constraint */
    5513 SCIP_VAR** vars /**< array with variables of constraint entries */
    5514 )
    5515{
    5516 assert(scip != NULL);
    5517
    5518 SCIP_CALL( SCIPcreateConsLogicor(scip, cons, name, nvars, vars,
    5520
    5521 return SCIP_OKAY;
    5522}
    5523
    5524/** adds coefficient in logic or constraint */
    5526 SCIP* scip, /**< SCIP data structure */
    5527 SCIP_CONS* cons, /**< logicor constraint */
    5528 SCIP_VAR* var /**< variable to add to the constraint */
    5529 )
    5530{
    5531 assert(var != NULL);
    5532
    5533 /*debugMsg(scip, "adding variable <%s> to logicor constraint <%s>\n",
    5534 SCIPvarGetName(var), SCIPconsGetName(cons));*/
    5535
    5536 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    5537 {
    5538 SCIPerrorMessage("constraint is not a logic or constraint\n");
    5539 return SCIP_INVALIDDATA;
    5540 }
    5541
    5542 SCIP_CALL( addCoef(scip, cons, var) );
    5543
    5544 return SCIP_OKAY;
    5545}
    5546
    5547/** gets number of variables in logic or constraint */
    5549 SCIP* scip, /**< SCIP data structure */
    5550 SCIP_CONS* cons /**< constraint data */
    5551 )
    5552{
    5553 SCIP_CONSDATA* consdata;
    5554
    5555 assert(scip != NULL);
    5556
    5557 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    5558 {
    5559 SCIPerrorMessage("constraint is not a logic or constraint\n");
    5560 SCIPABORT();
    5561 return -1; /*lint !e527*/
    5562 }
    5563
    5564 consdata = SCIPconsGetData(cons);
    5565 assert(consdata != NULL);
    5566
    5567 return consdata->nvars;
    5568}
    5569
    5570/** gets array of variables in logic or constraint */
    5572 SCIP* scip, /**< SCIP data structure */
    5573 SCIP_CONS* cons /**< constraint data */
    5574 )
    5575{
    5576 SCIP_CONSDATA* consdata;
    5577
    5578 assert(scip != NULL);
    5579
    5580 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    5581 {
    5582 SCIPerrorMessage("constraint is not a logic or constraint\n");
    5583 SCIPABORT();
    5584 return NULL; /*lint !e527*/
    5585 }
    5586
    5587 consdata = SCIPconsGetData(cons);
    5588 assert(consdata != NULL);
    5589
    5590 return consdata->vars;
    5591}
    5592
    5593/** gets the dual solution of the logic or constraint in the current LP */
    5595 SCIP* scip, /**< SCIP data structure */
    5596 SCIP_CONS* cons /**< constraint data */
    5597 )
    5598{
    5599 SCIP_CONSDATA* consdata;
    5600
    5601 assert(scip != NULL);
    5602
    5603 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    5604 {
    5605 SCIPerrorMessage("constraint is not a logic or constraint\n");
    5606 SCIPABORT();
    5607 return SCIP_INVALID; /*lint !e527*/
    5608 }
    5609
    5610 consdata = SCIPconsGetData(cons);
    5611 assert(consdata != NULL);
    5612
    5613 if( consdata->row != NULL )
    5614 return SCIProwGetDualsol(consdata->row);
    5615 else
    5616 return 0.0;
    5617}
    5618
    5619/** gets the dual Farkas value of the logic or constraint in the current infeasible LP */
    5621 SCIP* scip, /**< SCIP data structure */
    5622 SCIP_CONS* cons /**< constraint data */
    5623 )
    5624{
    5625 SCIP_CONSDATA* consdata;
    5626
    5627 assert(scip != NULL);
    5628
    5629 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    5630 {
    5631 SCIPerrorMessage("constraint is not a logic or constraint\n");
    5632 SCIPABORT();
    5633 return SCIP_INVALID; /*lint !e527*/
    5634 }
    5635
    5636 consdata = SCIPconsGetData(cons);
    5637 assert(consdata != NULL);
    5638
    5639 if( consdata->row != NULL )
    5640 return SCIProwGetDualfarkas(consdata->row);
    5641 else
    5642 return 0.0;
    5643}
    5644
    5645/** returns the linear relaxation of the given logic or constraint; may return NULL if no LP row was yet created;
    5646 * the user must not modify the row!
    5647 */
    5649 SCIP* scip, /**< SCIP data structure */
    5650 SCIP_CONS* cons /**< constraint data */
    5651 )
    5652{
    5653 SCIP_CONSDATA* consdata;
    5654
    5655 assert(scip != NULL);
    5656
    5657 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    5658 {
    5659 SCIPerrorMessage("constraint is not a logic or constraint\n");
    5660 SCIPABORT();
    5661 return NULL; /*lint !e527*/
    5662 }
    5663
    5664 consdata = SCIPconsGetData(cons);
    5665 assert(consdata != NULL);
    5666
    5667 return consdata->row;
    5668}
    5669
    5670/** creates and returns the row of the given logicor constraint */
    5672 SCIP* scip, /**< SCIP data structure */
    5673 SCIP_CONS* cons /**< constraint data */
    5674 )
    5675{
    5676 SCIP_CONSDATA* consdata;
    5677
    5678 assert(scip != NULL);
    5679
    5680 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    5681 {
    5682 SCIPerrorMessage("constraint is not a logic or constraint\n");
    5683 SCIPABORT();
    5684 return SCIP_ERROR; /*lint !e527*/
    5685 }
    5686
    5687 consdata = SCIPconsGetData(cons);
    5688 assert(consdata != NULL);
    5689 assert(consdata->row == NULL);
    5690
    5691 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), 1.0, SCIPinfinity(scip),
    5693
    5694 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->row, consdata->nvars, consdata->vars, 1.0) );
    5695
    5696 return SCIP_OKAY;
    5697}
    5698
    5699/** cleans up (multi-)aggregations and fixings from logicor constraints */
    5701 SCIP* scip, /**< SCIP data structure */
    5702 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
    5703 int* naddconss, /**< pointer to count number of added (linear) constraints */
    5704 int* ndelconss, /**< pointer to count number of deleted (logicor) constraints */
    5705 int* nchgcoefs /**< pointer to count number of changed coefficients */
    5706 )
    5707{
    5708 SCIP_CONSHDLR* conshdlr;
    5709 SCIP_EVENTHDLR* eventhdlr;
    5710 SCIP_CONS** conss;
    5711 unsigned char* entries;
    5712 int nconss;
    5713 int nentries;
    5714 int i;
    5715
    5716 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    5717 if( conshdlr == NULL )
    5718 return SCIP_OKAY;
    5719
    5720 assert(naddconss != NULL);
    5721 assert(ndelconss != NULL);
    5722 assert(nchgcoefs != NULL);
    5723
    5724 eventhdlr = SCIPconshdlrGetData(conshdlr)->eventhdlr;
    5725 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
    5726 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
    5727
    5728 nentries = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
    5729 SCIP_CALL( SCIPallocBufferArray(scip, &entries, nentries) );
    5730
    5731 /* loop backwards since then deleted constraints do not interfere with the loop */
    5732 for( i = nconss - 1; i >= 0; --i )
    5733 {
    5734 SCIP_CONS* cons;
    5735 SCIP_Bool redundant;
    5736
    5737 cons = conss[i];
    5738 redundant = FALSE;
    5739
    5740 SCIP_CALL( applyFixings(scip, cons, eventhdlr, &redundant, nchgcoefs, naddconss, ndelconss) );
    5741
    5742 if( SCIPconsIsDeleted(cons) )
    5743 continue;
    5744
    5745 /* merge constraint */
    5746 if( !redundant )
    5747 {
    5748 SCIP_CALL( mergeMultiples(scip, cons, eventhdlr, &entries, &nentries, &redundant, nchgcoefs) );
    5749 }
    5750
    5751 if( redundant )
    5752 {
    5753 SCIP_CALL( SCIPdelCons(scip, cons) );
    5754 ++(*ndelconss);
    5755 }
    5756 }
    5757
    5758 SCIPfreeBufferArray(scip, &entries);
    5759
    5760 return SCIP_OKAY;
    5761}
    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:255
    #define SCIP_MAXSTRLEN
    Definition: def.h:276
    #define SCIP_Longint
    Definition: def.h:148
    #define SCIP_INVALID
    Definition: def.h:185
    #define SCIP_Bool
    Definition: def.h:98
    #define SCIP_Real
    Definition: def.h:163
    #define TRUE
    Definition: def.h:100
    #define FALSE
    Definition: def.h:101
    #define MAX(x, y)
    Definition: def.h:227
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:155
    #define SCIPABORT()
    Definition: def.h:334
    #define SCIP_LONGINT_MAX
    Definition: def.h:149
    #define SCIP_CALL(x)
    Definition: def.h:362
    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:4802
    SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
    Definition: scip_cons.c:808
    void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: cons.c:4350
    SCIP_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4759
    SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
    Definition: scip_cons.c:540
    SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
    Definition: scip_cons.c:831
    SCIP_RETCODE SCIPsetConshdlrInitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITPRE((*consinitpre)))
    Definition: scip_cons.c:492
    SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
    Definition: scip_cons.c:235
    SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
    Definition: scip_cons.c:281
    SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: scip_cons.c:181
    SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDEACTIVE((*consdeactive)))
    Definition: scip_cons.c:693
    SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)))
    Definition: scip_cons.c:900
    SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
    Definition: scip_cons.c:578
    SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
    Definition: scip_cons.c:372
    SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
    Definition: scip_cons.c:323
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4320
    SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
    Definition: scip_cons.c:516
    SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
    Definition: scip_cons.c:347
    SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
    Definition: scip_cons.c:940
    SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH((*consgetsignedpermsymgraph)))
    Definition: scip_cons.c:924
    SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
    Definition: scip_cons.c:468
    SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
    Definition: scip_cons.c:624
    SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
    Definition: scip_cons.c:444
    SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4340
    SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
    Definition: scip_cons.c:601
    SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
    Definition: scip_cons.c:647
    int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4816
    SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
    Definition: scip_cons.c:854
    SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4739
    SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSACTIVE((*consactive)))
    Definition: scip_cons.c:670
    SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
    Definition: scip_cons.c:785
    SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
    Definition: cons.c:8423
    int SCIPconsGetPos(SCIP_CONS *cons)
    Definition: cons.c:8403
    SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
    Definition: cons.c:8652
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8413
    SCIP_RETCODE SCIPenableCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1837
    SCIP_Bool SCIPconsIsPropagationEnabled(SCIP_CONS *cons)
    Definition: cons.c:8511
    SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
    Definition: cons.c:8562
    SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
    Definition: scip_cons.c:2536
    int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
    Definition: cons.c:8845
    SCIP_RETCODE SCIPenableConsPropagation(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1951
    int SCIPconsGetValidDepth(SCIP_CONS *cons)
    Definition: cons.c:8476
    SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8592
    SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
    Definition: cons.c:8522
    SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
    Definition: cons.c:8702
    SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
    Definition: cons.c:8582
    SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
    Definition: cons.c:8454
    SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    Definition: scip_cons.c:997
    SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
    Definition: cons.c:8612
    SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
    Definition: cons.c:8632
    SCIP_RETCODE SCIPdisableCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1871
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8393
    SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1812
    SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
    Definition: cons.c:8642
    SCIP_Bool SCIPconsIsAdded(SCIP_CONS *cons)
    Definition: cons.c:8822
    SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
    Definition: scip_cons.c:1524
    SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
    Definition: cons.c:8672
    SCIP_RETCODE SCIPdisableConsPropagation(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1981
    SCIP_RETCODE SCIPaddConsAge(SCIP *scip, SCIP_CONS *cons, SCIP_Real deltaage)
    Definition: scip_cons.c:1755
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8572
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8662
    SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
    Definition: scip_cut.c:225
    SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: scip_event.c:111
    const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:396
    SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
    Definition: event.c:1194
    SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
    Definition: scip_event.c:367
    SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
    Definition: scip_event.c:413
    SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
    Definition: event.c:1217
    SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
    Definition: scip_lp.c:87
    #define SCIPfreeCleanBufferArray(scip, ptr)
    Definition: scip_mem.h:146
    #define SCIPallocCleanBufferArray(scip, ptr, num)
    Definition: scip_mem.h:142
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    int SCIPcalcMemGrowSize(SCIP *scip, int num)
    Definition: scip_mem.c:139
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPreallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:128
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPduplicateBufferArray(scip, ptr, source, num)
    Definition: scip_mem.h:132
    #define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
    Definition: scip_mem.h:111
    #define SCIPfreeBufferArrayNull(scip, ptr)
    Definition: scip_mem.h:137
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    #define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:105
    SCIP_RETCODE SCIPdelNlRow(SCIP *scip, SCIP_NLROW *nlrow)
    Definition: scip_nlp.c:424
    SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
    Definition: scip_nlp.c:396
    SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
    Definition: scip_nlp.c:110
    SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
    Definition: scip_nlp.c:1058
    SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
    Definition: nlp.c:1953
    SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
    Definition: scip_nlp.c:954
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    SCIP_RETCODE SCIPaddVarsToRowSameCoef(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real val)
    Definition: scip_lp.c:1718
    SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
    Definition: scip_lp.c:1398
    SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_lp.c:1646
    SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
    Definition: scip_lp.c:1508
    SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
    Definition: lp.c:17719
    SCIP_Real SCIPgetRowLPFeasibility(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1974
    SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
    Definition: lp.c:17917
    SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
    Definition: lp.c:17706
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c: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:23869
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23643
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23479
    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:24569
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23387
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4386
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23499
    SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
    Definition: var.c:23945
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24269
    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:23431
    SCIP_RETCODE SCIPparseVarsList(SCIP *scip, const char *str, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize, char **endptr, char delimiter, SCIP_Bool *success)
    Definition: scip_var.c:805
    SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
    Definition: scip_var.c:10550
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23901
    SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
    Definition: var.c:17551
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23454
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24143
    int SCIPvarGetIndex(SCIP_VAR *var)
    Definition: var.c:23653
    SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
    Definition: scip_var.c:5118
    SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
    Definition: scip_var.c:5296
    SCIP_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:23663
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23268
    SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:24930
    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:24643
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24235
    SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
    Definition: var.c:23444
    SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
    Definition: var.c:23879
    int SCIPgetNCliques(SCIP *scip)
    Definition: scip_var.c:9512
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24121
    SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
    Definition: scip_var.c:10318
    SCIP_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:17275
    SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
    Definition: var.c:17643
    SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
    Definition: var.c:21797
    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:16808
    SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
    Definition: var.c:24920
    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