SCIP

    Solving Constraint Integer Programs

    cons_and.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_and.c
    26 * @ingroup DEFPLUGINS_CONS
    27 * @ingroup CONSHDLRS
    28 * @brief Constraint handler for AND-constraints, \f$r = x_1 \wedge x_2 \wedge \dots \wedge x_n\f$
    29 * @author Tobias Achterberg
    30 * @author Stefan Heinz
    31 * @author Michael Winkler
    32 *
    33 * This constraint handler deals with AND-constraints. These are constraint of the form:
    34 *
    35 * \f[
    36 * r = x_1 \wedge x_2 \wedge \dots \wedge x_n
    37 * \f]
    38 *
    39 * where \f$x_i\f$ is a binary variable for all \f$i\f$. Hence, \f$r\f$ is also of binary type. The variable \f$r\f$ is
    40 * called resultant and the \f$x\f$'s operators.
    41 */
    42
    43/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    44
    46#include "scip/cons_and.h"
    47#include "scip/cons_linear.h"
    48#include "scip/cons_logicor.h"
    50#include "scip/cons_setppc.h"
    51#include "scip/expr_product.h"
    52#include "scip/expr_var.h"
    53#include "scip/debug.h"
    54#include "scip/pub_cons.h"
    55#include "scip/pub_event.h"
    56#include "scip/pub_lp.h"
    57#include "scip/pub_message.h"
    58#include "scip/pub_misc.h"
    59#include "scip/pub_misc_sort.h"
    60#include "scip/pub_var.h"
    61#include "scip/scip_conflict.h"
    62#include "scip/scip_cons.h"
    63#include "scip/scip_copy.h"
    64#include "scip/scip_cut.h"
    65#include "scip/scip_event.h"
    66#include "scip/scip_expr.h"
    67#include "scip/scip_general.h"
    68#include "scip/scip_lp.h"
    69#include "scip/scip_mem.h"
    70#include "scip/scip_message.h"
    71#include "scip/scip_nlp.h"
    72#include "scip/scip_numerics.h"
    73#include "scip/scip_param.h"
    74#include "scip/scip_prob.h"
    75#include "scip/scip_probing.h"
    76#include "scip/scip_sol.h"
    77#include "scip/scip_tree.h"
    78#include "scip/scip_var.h"
    79#include "scip/symmetry_graph.h"
    81
    82
    83/* constraint handler properties */
    84#define CONSHDLR_NAME "and"
    85#define CONSHDLR_DESC "constraint handler for AND-constraints: r = and(x1, ..., xn)"
    86#define CONSHDLR_SEPAPRIORITY +850100 /**< priority of the constraint handler for separation */
    87#define CONSHDLR_ENFOPRIORITY -850100 /**< priority of the constraint handler for constraint enforcing */
    88#define CONSHDLR_CHECKPRIORITY -850100 /**< priority of the constraint handler for checking feasibility */
    89#define CONSHDLR_SEPAFREQ 1 /**< frequency for separating cuts; zero means to separate only in the root node */
    90#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
    91#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
    92 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    93#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
    94#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
    95#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
    96#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
    97
    98#define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE)
    99#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
    100
    101#define EVENTHDLR_NAME "and"
    102#define EVENTHDLR_DESC "bound change event handler for AND-constraints"
    103
    104#define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
    105#define DEFAULT_LINEARIZE FALSE /**< should constraint get linearized and removed? */
    106#define DEFAULT_ENFORCECUTS TRUE /**< should cuts be separated during LP enforcing? */
    107#define DEFAULT_AGGRLINEARIZATION FALSE /**< should an aggregated linearization be used? */
    108#define DEFAULT_UPGRRESULTANT FALSE /**< should implied integrality of resultant variables be detected? */
    109#define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving be performed? */
    110
    111#define HASHSIZE_ANDCONS 500 /**< minimal size of hash table in and constraint tables */
    112#define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
    113#define NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
    114#define MINGAINPERNMINCOMPARISONS 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
    115
    116/* @todo maybe use event SCIP_EVENTTYPE_VARUNLOCKED to decide for another dual-presolving run on a constraint */
    117
    118/*
    119 * Data structures
    120 */
    121
    122/** constraint data for AND-constraints */
    123struct SCIP_ConsData
    124{
    125 SCIP_VAR** vars; /**< variables in the AND-constraint */
    126 SCIP_VAR* resvar; /**< resultant variable */
    127 SCIP_ROW** rows; /**< rows for linear relaxation of AND-constraint */
    128 SCIP_ROW* aggrrow; /**< aggregated row for linear relaxation of AND-constraint */
    129 SCIP_NLROW* nlrow; /**< row for representation in nonlinear relaxation */
    130 int nvars; /**< number of variables in AND-constraint */
    131 int varssize; /**< size of vars array */
    132 int nrows; /**< number of rows for linear relaxation of AND-constraint */
    133 int watchedvar1; /**< position of first watched operator variable */
    134 int watchedvar2; /**< position of second watched operator variable */
    135 int filterpos1; /**< event filter position of first watched operator variable */
    136 int filterpos2; /**< event filter position of second watched operator variable */
    137 unsigned int propagated:1; /**< is constraint already preprocessed/propagated? */
    138 unsigned int nofixedzero:1; /**< is none of the operator variables fixed to FALSE? */
    139 unsigned int impladded:1; /**< were the implications of the constraint already added? */
    140 unsigned int opimpladded:1; /**< was the implication for 2 operands with fixed resultant added? */
    141 unsigned int sorted:1; /**< are the constraint's variables sorted? */
    142 unsigned int changed:1; /**< was constraint changed since last pair preprocessing round? */
    143 unsigned int merged:1; /**< are the constraint's equal variables already merged? */
    144};
    145
    146/** constraint handler data */
    147struct SCIP_ConshdlrData
    148{
    149 SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events on watched variables */
    150 SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
    151 SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
    152 SCIP_Bool linearize; /**< should constraint get linearized and removed? */
    153 SCIP_Bool enforcecuts; /**< should cuts be separated during LP enforcing? */
    154 SCIP_Bool aggrlinearization; /**< should an aggregated linearization be used? */
    155 SCIP_Bool upgrresultant; /**< should implied integrality of resultant variables be detected? */
    156 SCIP_Bool dualpresolving; /**< should dual presolving be performed? */
    157};
    158
    159
    160/*
    161 * Propagation rules
    162 */
    163
    165{
    166 PROPRULE_INVALID = 0, /**< propagation was applied without a specific propagation rule */
    167 PROPRULE_1 = 1, /**< v_i = FALSE => r = FALSE */
    168 PROPRULE_2 = 2, /**< r = TRUE => v_i = TRUE for all i */
    169 PROPRULE_3 = 3, /**< v_i = TRUE for all i => r = TRUE */
    170 PROPRULE_4 = 4 /**< r = FALSE, v_i = TRUE for all i except j => v_j = FALSE */
    172typedef enum Proprule PROPRULE;
    173
    174
    175/*
    176 * Local methods
    177 */
    178
    179/** installs rounding locks for the given variable in the given AND-constraint */
    180static
    182 SCIP* scip, /**< SCIP data structure */
    183 SCIP_CONS* cons, /**< constraint data */
    184 SCIP_VAR* var /**< variable of constraint entry */
    185 )
    186{
    187 /* rounding in both directions may violate the constraint */
    188 SCIP_CALL( SCIPlockVarCons(scip, var, cons, TRUE, TRUE) );
    189
    190 return SCIP_OKAY;
    191}
    192
    193/** removes rounding locks for the given variable in the given AND-constraint */
    194static
    196 SCIP* scip, /**< SCIP data structure */
    197 SCIP_CONS* cons, /**< constraint data */
    198 SCIP_VAR* var /**< variable of constraint entry */
    199 )
    200{
    201 /* rounding in both directions may violate the constraint */
    202 SCIP_CALL( SCIPunlockVarCons(scip, var, cons, TRUE, TRUE) );
    203
    204 return SCIP_OKAY;
    205}
    206
    207/** creates constraint handler data */
    208static
    210 SCIP* scip, /**< SCIP data structure */
    211 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
    212 SCIP_EVENTHDLR* eventhdlr /**< event handler */
    213 )
    214{
    215 assert(scip != NULL);
    216 assert(conshdlrdata != NULL);
    217 assert(eventhdlr != NULL);
    218
    219 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
    220
    221 /* set event handler for catching bound change events on variables */
    222 (*conshdlrdata)->eventhdlr = eventhdlr;
    223
    224 return SCIP_OKAY;
    225}
    226
    227/** frees constraint handler data */
    228static
    230 SCIP* scip, /**< SCIP data structure */
    231 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
    232 )
    233{
    234 assert(conshdlrdata != NULL);
    235 assert(*conshdlrdata != NULL);
    236
    237 SCIPfreeBlockMemory(scip, conshdlrdata);
    238}
    239
    240/** catches events for the watched variable at given position */
    241static
    243 SCIP* scip, /**< SCIP data structure */
    244 SCIP_CONSDATA* consdata, /**< AND-constraint data */
    245 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    246 int pos, /**< array position of variable to catch bound change events for */
    247 int* filterpos /**< pointer to store position of event filter entry */
    248 )
    249{
    250 assert(consdata != NULL);
    251 assert(consdata->vars != NULL);
    252 assert(eventhdlr != NULL);
    253 assert(0 <= pos && pos < consdata->nvars);
    254 assert(filterpos != NULL);
    255
    256 /* catch tightening events for lower bound and relaxed events for upper bounds on watched variable */
    258 eventhdlr, (SCIP_EVENTDATA*)consdata, filterpos) );
    259
    260 return SCIP_OKAY;
    261}
    262
    263
    264/** drops events for the watched variable at given position */
    265static
    267 SCIP* scip, /**< SCIP data structure */
    268 SCIP_CONSDATA* consdata, /**< AND-constraint data */
    269 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    270 int pos, /**< array position of watched variable to drop bound change events for */
    271 int filterpos /**< position of event filter entry */
    272 )
    273{
    274 assert(consdata != NULL);
    275 assert(consdata->vars != NULL);
    276 assert(eventhdlr != NULL);
    277 assert(0 <= pos && pos < consdata->nvars);
    278 assert(filterpos >= 0);
    279
    280 /* drop tightening events for lower bound and relaxed events for upper bounds on watched variable */
    282 eventhdlr, (SCIP_EVENTDATA*)consdata, filterpos) );
    283
    284 return SCIP_OKAY;
    285}
    286
    287/** catches needed events on all variables of constraint, except the special ones for watched variables */
    288static
    290 SCIP* scip, /**< SCIP data structure */
    291 SCIP_CONSDATA* consdata, /**< AND-constraint data */
    292 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
    293 )
    294{
    295 int i;
    296
    297 assert(consdata != NULL);
    298
    299 /* catch bound change events for both bounds on resultant variable */
    301 eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
    302
    303 /* catch tightening events for upper bound and relaxed events for lower bounds on operator variables */
    304 for( i = 0; i < consdata->nvars; ++i )
    305 {
    307 eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
    308 }
    309
    310 return SCIP_OKAY;
    311}
    312
    313/** drops events on all variables of constraint, except the special ones for watched variables */
    314static
    316 SCIP* scip, /**< SCIP data structure */
    317 SCIP_CONSDATA* consdata, /**< AND-constraint data */
    318 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
    319 )
    320{
    321 int i;
    322
    323 assert(consdata != NULL);
    324
    325 /* drop bound change events for both bounds on resultant variable */
    327 eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
    328
    329 /* drop tightening events for upper bound and relaxed events for lower bounds on operator variables */
    330 for( i = 0; i < consdata->nvars; ++i )
    331 {
    333 eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
    334 }
    335
    336 return SCIP_OKAY;
    337}
    338
    339/** stores the given variable numbers as watched variables, and updates the event processing */
    340static
    342 SCIP* scip, /**< SCIP data structure */
    343 SCIP_CONSDATA* consdata, /**< AND-constraint data */
    344 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    345 int watchedvar1, /**< new first watched variable */
    346 int watchedvar2 /**< new second watched variable */
    347 )
    348{
    349 assert(consdata != NULL);
    350 assert(watchedvar1 == -1 || watchedvar1 != watchedvar2);
    351 assert(watchedvar1 != -1 || watchedvar2 == -1);
    352 assert(watchedvar1 == -1 || (0 <= watchedvar1 && watchedvar1 < consdata->nvars));
    353 assert(watchedvar2 == -1 || (0 <= watchedvar2 && watchedvar2 < consdata->nvars));
    354
    355 /* if one watched variable is equal to the old other watched variable, just switch positions */
    356 if( watchedvar1 == consdata->watchedvar2 || watchedvar2 == consdata->watchedvar1 )
    357 {
    358 int tmp;
    359
    360 tmp = consdata->watchedvar1;
    361 consdata->watchedvar1 = consdata->watchedvar2;
    362 consdata->watchedvar2 = tmp;
    363 tmp = consdata->filterpos1;
    364 consdata->filterpos1 = consdata->filterpos2;
    365 consdata->filterpos2 = tmp;
    366 }
    367 assert(watchedvar1 == -1 || watchedvar1 != consdata->watchedvar2);
    368 assert(watchedvar2 == -1 || watchedvar2 != consdata->watchedvar1);
    369
    370 /* drop events on old watched variables */
    371 if( consdata->watchedvar1 != -1 && consdata->watchedvar1 != watchedvar1 )
    372 {
    373 assert(consdata->filterpos1 != -1);
    374 SCIP_CALL( consdataDropWatchedEvents(scip, consdata, eventhdlr, consdata->watchedvar1, consdata->filterpos1) );
    375 }
    376 if( consdata->watchedvar2 != -1 && consdata->watchedvar2 != watchedvar2 )
    377 {
    378 assert(consdata->filterpos2 != -1);
    379 SCIP_CALL( consdataDropWatchedEvents(scip, consdata, eventhdlr, consdata->watchedvar2, consdata->filterpos2) );
    380 }
    381
    382 /* catch events on new watched variables */
    383 if( watchedvar1 != -1 && watchedvar1 != consdata->watchedvar1 )
    384 {
    385 SCIP_CALL( consdataCatchWatchedEvents(scip, consdata, eventhdlr, watchedvar1, &consdata->filterpos1) );
    386 }
    387 if( watchedvar2 != -1 && watchedvar2 != consdata->watchedvar2 )
    388 {
    389 SCIP_CALL( consdataCatchWatchedEvents(scip, consdata, eventhdlr, watchedvar2, &consdata->filterpos2) );
    390 }
    391
    392 /* set the new watched variables */
    393 consdata->watchedvar1 = watchedvar1;
    394 consdata->watchedvar2 = watchedvar2;
    395
    396 return SCIP_OKAY;
    397}
    398
    399/** ensures, that the vars array can store at least num entries */
    400static
    402 SCIP* scip, /**< SCIP data structure */
    403 SCIP_CONSDATA* consdata, /**< linear constraint data */
    404 int num /**< minimum number of entries to store */
    405 )
    406{
    407 assert(consdata != NULL);
    408 assert(consdata->nvars <= consdata->varssize);
    409
    410 if( num > consdata->varssize )
    411 {
    412 int newsize;
    413
    414 newsize = SCIPcalcMemGrowSize(scip, num);
    415 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
    416 consdata->varssize = newsize;
    417 }
    418 assert(num <= consdata->varssize);
    419
    420 return SCIP_OKAY;
    421}
    422
    423/** creates constraint data for AND-constraint */
    424static
    426 SCIP* scip, /**< SCIP data structure */
    427 SCIP_CONSDATA** consdata, /**< pointer to store the constraint data */
    428 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    429 int nvars, /**< number of variables in the AND-constraint */
    430 SCIP_VAR** vars, /**< variables in AND-constraint */
    431 SCIP_VAR* resvar /**< resultant variable */
    432 )
    433{
    434 int v;
    435
    436 assert(consdata != NULL);
    437 assert(nvars == 0 || vars != NULL);
    438 assert(resvar != NULL);
    439
    440 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
    441 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
    442 (*consdata)->resvar = resvar;
    443 (*consdata)->rows = NULL;
    444 (*consdata)->aggrrow = NULL;
    445 (*consdata)->nlrow = NULL;
    446 (*consdata)->nvars = nvars;
    447 (*consdata)->varssize = nvars;
    448 (*consdata)->nrows = 0;
    449 (*consdata)->watchedvar1 = -1;
    450 (*consdata)->watchedvar2 = -1;
    451 (*consdata)->filterpos1 = -1;
    452 (*consdata)->filterpos2 = -1;
    453 (*consdata)->propagated = FALSE;
    454 (*consdata)->nofixedzero = FALSE;
    455 (*consdata)->impladded = FALSE;
    456 (*consdata)->opimpladded = FALSE;
    457 (*consdata)->sorted = FALSE;
    458 (*consdata)->changed = TRUE;
    459 (*consdata)->merged = FALSE;
    460
    461 /* get transformed variables, if we are in the transformed problem */
    463 {
    464 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
    465 SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->resvar, &(*consdata)->resvar) );
    466
    467 /* catch needed events on variables */
    468 SCIP_CALL( consdataCatchEvents(scip, *consdata, eventhdlr) );
    469 }
    470
    471 assert(SCIPvarIsBinary((*consdata)->resvar));
    472
    473 /* note: currently, this constraint handler does not handle multiaggregations (e.g. during propagation), hence we forbid
    474 * multiaggregation from the beginning for the involved variables
    475 */
    477 {
    478 for( v = 0; v < (*consdata)->nvars; ++v )
    479 {
    480 assert((*consdata)->vars[v] != NULL);
    481 SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->vars[v]) );
    482 }
    483 SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->resvar) );
    484 }
    485
    486 /* capture vars */
    487 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->resvar) );
    488 for( v = 0; v < (*consdata)->nvars; v++ )
    489 {
    490 assert((*consdata)->vars[v] != NULL);
    491 assert(SCIPvarIsBinary((*consdata)->vars[v]));
    492 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
    493 }
    494
    495 return SCIP_OKAY;
    496}
    497
    498/** releases LP rows of constraint data and frees rows array */
    499static
    501 SCIP* scip, /**< SCIP data structure */
    502 SCIP_CONSDATA* consdata /**< constraint data */
    503 )
    504{
    505 int r;
    506
    507 assert(consdata != NULL);
    508
    509 if( consdata->rows != NULL )
    510 {
    511 for( r = 0; r < consdata->nrows; ++r )
    512 {
    513 SCIP_CALL( SCIPreleaseRow(scip, &consdata->rows[r]) );
    514 }
    515 SCIPfreeBlockMemoryArray(scip, &consdata->rows, consdata->nrows);
    516
    517 consdata->nrows = 0;
    518 }
    519
    520 if( consdata->aggrrow != NULL )
    521 {
    522 SCIP_CALL( SCIPreleaseRow(scip, &consdata->aggrrow) );
    523 consdata->aggrrow = NULL;
    524 }
    525
    526 return SCIP_OKAY;
    527}
    528
    529/** frees constraint data for AND-constraint */
    530static
    532 SCIP* scip, /**< SCIP data structure */
    533 SCIP_CONSDATA** consdata, /**< pointer to the constraint data */
    534 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
    535 )
    536{
    537 int v;
    538
    539 assert(consdata != NULL);
    540 assert(*consdata != NULL);
    541
    543 {
    544 /* drop events for watched variables */
    545 SCIP_CALL( consdataSwitchWatchedvars(scip, *consdata, eventhdlr, -1, -1) );
    546
    547 /* drop all other events on variables */
    548 SCIP_CALL( consdataDropEvents(scip, *consdata, eventhdlr) );
    549 }
    550 else
    551 {
    552 assert((*consdata)->watchedvar1 == -1);
    553 assert((*consdata)->watchedvar2 == -1);
    554 }
    555
    556 /* release and free the rows */
    557 SCIP_CALL( consdataFreeRows(scip, *consdata) );
    558
    559 /* release the nlrow */
    560 if( (*consdata)->nlrow != NULL )
    561 {
    562 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
    563 }
    564
    565 /* release vars */
    566 for( v = 0; v < (*consdata)->nvars; v++ )
    567 {
    568 assert((*consdata)->vars[v] != NULL);
    569 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
    570 }
    571 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->resvar)) );
    572
    573 SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, (*consdata)->varssize);
    574 SCIPfreeBlockMemory(scip, consdata);
    575
    576 return SCIP_OKAY;
    577}
    578
    579/** prints AND-constraint to file stream */
    580static
    582 SCIP* scip, /**< SCIP data structure */
    583 SCIP_CONSDATA* consdata, /**< AND-constraint data */
    584 FILE* file /**< output file (or NULL for standard output) */
    585 )
    586{
    587 assert(consdata != NULL);
    588
    589 /* print resultant */
    590 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->resvar, TRUE) );
    591
    592 /* start the variable list */
    593 SCIPinfoMessage(scip, file, " == and(");
    594
    595 /* print variable list */
    596 SCIP_CALL( SCIPwriteVarsList(scip, file, consdata->vars, consdata->nvars, TRUE, ',') );
    597
    598 /* close the variable list */
    599 SCIPinfoMessage(scip, file, ")");
    600
    601 return SCIP_OKAY;
    602}
    603
    604/** adds coefficient to AND-constraint */
    605static
    607 SCIP* scip, /**< SCIP data structure */
    608 SCIP_CONS* cons, /**< linear constraint */
    609 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    610 SCIP_VAR* var /**< variable to add to the constraint */
    611 )
    612{
    613 SCIP_CONSDATA* consdata;
    614 SCIP_Bool transformed;
    615
    616 assert(var != NULL);
    617
    618 consdata = SCIPconsGetData(cons);
    619 assert(consdata != NULL);
    620 assert(consdata->rows == NULL);
    621
    622 /* are we in the transformed problem? */
    623 transformed = SCIPconsIsTransformed(cons);
    624
    625 /* always use transformed variables in transformed constraints */
    626 if( transformed )
    627 {
    628 SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
    629 }
    630 assert(var != NULL);
    631 assert(transformed == SCIPvarIsTransformed(var));
    632
    633 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
    634 consdata->vars[consdata->nvars] = var;
    635 consdata->nvars++;
    636 consdata->sorted = (consdata->nvars == 1);
    637 consdata->changed = TRUE;
    638 consdata->merged = FALSE;
    639
    640 /* capture variable */
    642
    643 /* if we are in transformed problem, catch the variable's events */
    644 if( transformed )
    645 {
    646 /* catch bound change events of variable */
    648 eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
    649 }
    650
    651 /* install the rounding locks for the new variable */
    652 SCIP_CALL( lockRounding(scip, cons, var) );
    653
    654 /**@todo update LP rows */
    655 if( consdata->rows != NULL )
    656 {
    657 SCIPerrorMessage("cannot add coefficients to AND-constraint after LP relaxation was created\n");
    658 return SCIP_INVALIDCALL;
    659 }
    660
    661 return SCIP_OKAY;
    662}
    663
    664/** deletes coefficient at given position from AND-constraint data */
    665static
    667 SCIP* scip, /**< SCIP data structure */
    668 SCIP_CONS* cons, /**< AND-constraint */
    669 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    670 int pos /**< position of coefficient to delete */
    671 )
    672{
    673 SCIP_CONSDATA* consdata;
    674
    675 assert(eventhdlr != NULL);
    676
    677 consdata = SCIPconsGetData(cons);
    678 assert(consdata != NULL);
    679 assert(0 <= pos && pos < consdata->nvars);
    680 assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(consdata->vars[pos]));
    681
    682 /* remove the rounding locks of the variable */
    683 SCIP_CALL( unlockRounding(scip, cons, consdata->vars[pos]) );
    684
    685 if( SCIPconsIsTransformed(cons) )
    686 {
    687 /* drop bound change events of variable */
    689 eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
    690 }
    691
    692 if( SCIPconsIsTransformed(cons) )
    693 {
    694 /* if the position is watched, stop watching the position */
    695 if( consdata->watchedvar1 == pos )
    696 {
    697 SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar2, -1) );
    698 }
    699 if( consdata->watchedvar2 == pos )
    700 {
    701 SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar1, -1) );
    702 }
    703 }
    704 assert(pos != consdata->watchedvar1);
    705 assert(pos != consdata->watchedvar2);
    706
    707 /* release variable */
    708 SCIP_CALL( SCIPreleaseVar(scip, &(consdata->vars[pos])) );
    709
    710 /* move the last variable to the free slot */
    711 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
    712 consdata->nvars--;
    713
    714 /* if the last variable (that moved) was watched, update the watched position */
    715 if( consdata->watchedvar1 == consdata->nvars )
    716 consdata->watchedvar1 = pos;
    717 if( consdata->watchedvar2 == consdata->nvars )
    718 consdata->watchedvar2 = pos;
    719
    720 consdata->propagated = FALSE;
    721 consdata->sorted = FALSE;
    722 consdata->changed = TRUE;
    723
    724 return SCIP_OKAY;
    725}
    726
    727/** sorts AND-constraint's variables by non-decreasing variable index */
    728static
    730 SCIP_CONSDATA* consdata /**< constraint data */
    731 )
    732{
    733 assert(consdata != NULL);
    734
    735 if( !consdata->sorted )
    736 {
    737 if( consdata->nvars <= 1 )
    738 consdata->sorted = TRUE;
    739 else
    740 {
    741 SCIP_VAR* var1 = NULL;
    742 SCIP_VAR* var2 = NULL;
    743
    744 /* remember watch variables */
    745 if( consdata->watchedvar1 != -1 )
    746 {
    747 var1 = consdata->vars[consdata->watchedvar1];
    748 assert(var1 != NULL);
    749 consdata->watchedvar1 = -1;
    750 if( consdata->watchedvar2 != -1 )
    751 {
    752 var2 = consdata->vars[consdata->watchedvar2];
    753 assert(var2 != NULL);
    754 consdata->watchedvar2 = -1;
    755 }
    756 }
    757 assert(consdata->watchedvar1 == -1);
    758 assert(consdata->watchedvar2 == -1);
    759 assert(var1 != NULL || var2 == NULL);
    760
    761 /* sort variables after index */
    762 SCIPsortPtr((void**)consdata->vars, SCIPvarComp, consdata->nvars);
    763 consdata->sorted = TRUE;
    764
    765 /* correct watched variables */
    766 if( var1 != NULL )
    767 {
    768 int pos;
    769#ifndef NDEBUG
    770 SCIP_Bool found;
    771
    772 found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var1, consdata->nvars, &pos);
    773 assert(found);
    774#else
    775 (void) SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var1, consdata->nvars, &pos);
    776#endif
    777 assert(pos >= 0 && pos < consdata->nvars);
    778 consdata->watchedvar1 = pos;
    779
    780 if( var2 != NULL )
    781 {
    782#ifndef NDEBUG
    783 found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var2, consdata->nvars, &pos);
    784 assert(found);
    785#else
    786 (void) SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var2, consdata->nvars, &pos);
    787#endif
    788 assert(pos >= 0 && pos < consdata->nvars);
    789 consdata->watchedvar2 = pos;
    790 }
    791 }
    792 }
    793 }
    794
    795#ifdef SCIP_DEBUG
    796 /* check sorting */
    797 {
    798 int v;
    799
    800 for( v = 0; v < consdata->nvars; ++v )
    801 {
    802 assert(v == consdata->nvars-1 || SCIPvarCompare(consdata->vars[v], consdata->vars[v+1]) <= 0);
    803 }
    804 }
    805#endif
    806}
    807
    808/** deletes all one-fixed variables */
    809static
    811 SCIP* scip, /**< SCIP data structure */
    812 SCIP_CONS* cons, /**< AND-constraint */
    813 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    814 int* nchgcoefs /**< pointer to add up the number of changed coefficients */
    815 )
    816{
    817 SCIP_CONSDATA* consdata;
    818 SCIP_VAR* var;
    819 int v;
    820
    821 assert(scip != NULL);
    822 assert(cons != NULL);
    823 assert(eventhdlr != NULL);
    824 assert(nchgcoefs != NULL);
    825
    826 consdata = SCIPconsGetData(cons);
    827 assert(consdata != NULL);
    828 assert(consdata->nvars == 0 || consdata->vars != NULL);
    829
    830 v = 0;
    831 while( v < consdata->nvars )
    832 {
    833 var = consdata->vars[v];
    834 assert(SCIPvarIsBinary(var));
    835
    836 if( SCIPvarGetLbGlobal(var) > 0.5 )
    837 {
    838 assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(var), 1.0));
    839 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    840 (*nchgcoefs)++;
    841 }
    842 else
    843 {
    844 SCIP_VAR* repvar;
    845 SCIP_Bool negated;
    846
    847 /* get binary representative of variable */
    848 SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &repvar, &negated) );
    849
    850 /* check, if the variable should be replaced with the representative */
    851 if( repvar != var )
    852 {
    853 /* delete old (aggregated) variable */
    854 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    855
    856 /* add representative instead */
    857 SCIP_CALL( addCoef(scip, cons, eventhdlr, repvar) );
    858 }
    859 else
    860 ++v;
    861 }
    862 }
    863
    864#ifdef SCIP_DISABLED_CODE /* does not work with pseudoboolean constraint handler, need to be fixed */
    865 /* check, if the resultant should be replaced with the active representative */
    866 if( !SCIPvarIsActive(consdata->resvar) )
    867 {
    868 SCIP_VAR* repvar;
    869 SCIP_Bool negated;
    870
    871 /* get binary representative of variable */
    872 SCIP_CALL( SCIPgetBinvarRepresentative(scip, consdata->resvar, &repvar, &negated) );
    873 assert(SCIPvarIsBinary(repvar));
    874
    875 /* check, if the variable should be replaced with the representative */
    876 if( repvar != consdata->resvar )
    877 {
    878 if( SCIPconsIsTransformed(cons) )
    879 {
    880 /* drop bound change events of old resultant */
    882 eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
    883
    884 /* catch bound change events of new resultant */
    886 eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
    887 }
    888
    889 /* release old resultant */
    890 SCIP_CALL( SCIPreleaseVar(scip, &(consdata->resvar)) );
    891
    892 /* capture new resultant */
    893 SCIP_CALL( SCIPcaptureVar(scip, repvar) );
    894
    895 consdata->resvar = repvar;
    896 consdata->changed = TRUE;
    897 }
    898 }
    899#endif
    900
    901 SCIPdebugMsg(scip, "after fixings: ");
    902 SCIPdebug( SCIP_CALL( consdataPrint(scip, consdata, NULL)) );
    903 SCIPdebugMsgPrint(scip, "\n");
    904
    905 return SCIP_OKAY;
    906}
    907
    908/** creates a linearization of the AND-constraint */
    909static
    911 SCIP* scip, /**< SCIP data structure */
    912 SCIP_CONS* cons /**< constraint to check */
    913 )
    914{
    915 SCIP_CONSDATA* consdata;
    916 char rowname[SCIP_MAXSTRLEN];
    917 int nvars;
    918 int i;
    919
    920 consdata = SCIPconsGetData(cons);
    921 assert(consdata != NULL);
    922 assert(consdata->rows == NULL);
    923
    924 nvars = consdata->nvars;
    925
    926 /* get memory for rows */
    927 consdata->nrows = nvars + 1;
    928 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->rows, consdata->nrows) );
    929
    930 /* creates LP rows corresponding to AND-constraint:
    931 * - one additional row: resvar - v1 - ... - vn >= 1-n
    932 * - for each operator variable vi: resvar - vi <= 0
    933 */
    934
    935 /* create additional row */
    936 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_add", SCIPconsGetName(cons));
    937 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[0], cons, rowname, -consdata->nvars + 1.0, SCIPinfinity(scip),
    939 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[0], consdata->resvar, 1.0) );
    940 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->rows[0], nvars, consdata->vars, -1.0) );
    941
    942 /* create operator rows */
    943 for( i = 0; i < nvars; ++i )
    944 {
    945 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), i);
    946 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[i+1], cons, rowname, -SCIPinfinity(scip), 0.0,
    948 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[i+1], consdata->resvar, 1.0) );
    949 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[i+1], consdata->vars[i], -1.0) );
    950 }
    951
    952 return SCIP_OKAY;
    953}
    954
    955/** adds linear relaxation of AND-constraint to the LP */
    956static
    958 SCIP* scip, /**< SCIP data structure */
    959 SCIP_CONS* cons, /**< constraint to check */
    960 SCIP_Bool* infeasible /**< pointer to store whether an infeasibility was detected */
    961 )
    962{
    963 SCIP_CONSDATA* consdata;
    964
    965 /* in the root LP we only add the weaker relaxation which consists of two rows:
    966 * - one additional row: resvar - v1 - ... - vn >= 1-n
    967 * - aggregated row: n*resvar - v1 - ... - vn <= 0.0
    968 *
    969 * during separation we separate the stronger relaxation which consists of n+1 row:
    970 * - one additional row: resvar - v1 - ... - vn >= 1-n
    971 * - for each operator variable vi: resvar - vi <= 0.0
    972 */
    973
    974 consdata = SCIPconsGetData(cons);
    975 assert(consdata != NULL);
    976
    977 /* create the aggregated row */
    978 if( consdata->aggrrow == NULL )
    979 {
    980 char rowname[SCIP_MAXSTRLEN];
    981
    982 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_operators", SCIPconsGetName(cons));
    983 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->aggrrow, cons, rowname, -SCIPinfinity(scip), 0.0,
    985 SCIP_CALL( SCIPaddVarToRow(scip, consdata->aggrrow, consdata->resvar, (SCIP_Real) consdata->nvars) );
    986 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->aggrrow, consdata->nvars, consdata->vars, -1.0) );
    987 }
    988
    989 /* insert aggregated LP row as cut */
    990 if( !SCIProwIsInLP(consdata->aggrrow) )
    991 {
    992 SCIP_CALL( SCIPaddRow(scip, consdata->aggrrow, FALSE, infeasible) );
    993 }
    994
    995 if( !(*infeasible) )
    996 {
    997 if( consdata->rows == NULL )
    998 {
    999 /* create the n+1 row relaxation */
    1001 }
    1002
    1003 assert(consdata->rows != NULL);
    1004
    1005 /* add additional row */
    1006 if( !SCIProwIsInLP(consdata->rows[0]) )
    1007 {
    1008 SCIP_CALL( SCIPaddRow(scip, consdata->rows[0], FALSE, infeasible) );
    1009 }
    1010 }
    1011
    1012 return SCIP_OKAY;
    1013}
    1014
    1015/** adds constraint as row to the NLP, if not added yet */
    1016static
    1018 SCIP* scip, /**< SCIP data structure */
    1019 SCIP_CONS* cons /**< and constraint */
    1020 )
    1021{
    1022 SCIP_CONSDATA* consdata;
    1023
    1024 assert(SCIPisNLPConstructed(scip));
    1025
    1026 /* skip deactivated, redundant, or local constraints (the NLP does not allow for local rows at the moment) */
    1027 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
    1028 return SCIP_OKAY;
    1029
    1030 consdata = SCIPconsGetData(cons);
    1031 assert(consdata != NULL);
    1032 assert(consdata->resvar != NULL);
    1033
    1034 if( consdata->nlrow == NULL )
    1035 {
    1036 SCIP_EXPR* expr;
    1037 SCIP_EXPR** varexprs;
    1038 SCIP_Real minusone = -1.0;
    1039 int i;
    1040
    1041 SCIP_CALL( SCIPallocBufferArray(scip, &varexprs, consdata->nvars) );
    1042 for( i = 0; i < consdata->nvars; ++i )
    1043 {
    1044 SCIP_CALL( SCIPcreateExprVar(scip, &varexprs[i], consdata->vars[i], NULL, NULL) );
    1045 }
    1046 SCIP_CALL( SCIPcreateExprProduct(scip, &expr, consdata->nvars, varexprs, 1.0, NULL, NULL) );
    1047
    1048 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
    1049 0.0, 1, &consdata->resvar, &minusone, expr, 0.0, 0.0, SCIP_EXPRCURV_UNKNOWN) );
    1050 assert(consdata->nlrow != NULL);
    1051
    1052 SCIP_CALL( SCIPreleaseExpr(scip, &expr) );
    1053 for( i = 0; i < consdata->nvars; ++i )
    1054 {
    1055 SCIP_CALL( SCIPreleaseExpr(scip, &varexprs[i]) );
    1056 }
    1057 SCIPfreeBufferArray(scip, &varexprs);
    1058 }
    1059
    1060 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
    1061 {
    1062 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
    1063 }
    1064
    1065 return SCIP_OKAY;
    1066}
    1067
    1068/** checks AND-constraint for feasibility of given solution: returns TRUE iff constraint is feasible */
    1069static
    1071 SCIP* scip, /**< SCIP data structure */
    1072 SCIP_CONS* cons, /**< constraint to check */
    1073 SCIP_SOL* sol, /**< solution to check, NULL for current solution */
    1074 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
    1075 SCIP_Bool printreason, /**< Should the reason for the violation be printed? */
    1076 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
    1077 )
    1078{
    1079 SCIP_CONSDATA* consdata;
    1080 SCIP_Bool mustcheck;
    1081 int r;
    1082
    1083 assert(violated != NULL);
    1084
    1085 consdata = SCIPconsGetData(cons);
    1086 assert(consdata != NULL);
    1087
    1088 *violated = FALSE;
    1089
    1090 /* check whether we can skip this feasibility check, because all rows are in the LP and do not have to be checked */
    1091 mustcheck = checklprows;
    1092 mustcheck = mustcheck || (consdata->rows == NULL);
    1093 if( !mustcheck )
    1094 {
    1095 assert(consdata->rows != NULL);
    1096
    1097 for( r = 0; r < consdata->nrows; ++r )
    1098 {
    1099 mustcheck = !SCIProwIsInLP(consdata->rows[r]);
    1100 if( mustcheck )
    1101 break;
    1102 }
    1103 }
    1104
    1105 /* check feasibility of constraint if necessary */
    1106 if( mustcheck )
    1107 {
    1108 SCIP_Real minsolval = 1.0;
    1109 SCIP_Real sumsolval = 0.0;
    1110 SCIP_Real solval;
    1111 SCIP_Real viol;
    1112 int minsolind = 0;
    1113 int i;
    1114
    1115 /* increase age of constraint; age is reset to zero, if a violation was found only in case we are in
    1116 * enforcement
    1117 */
    1118 if( sol == NULL )
    1119 {
    1120 SCIP_CALL( SCIPincConsAge(scip, cons) );
    1121 }
    1122
    1123 /* evaluate operator variables */
    1124 for( i = 0; i < consdata->nvars; ++i )
    1125 {
    1126 solval = SCIPgetSolVal(scip, sol, consdata->vars[i]);
    1127
    1128 if( minsolval > solval )
    1129 {
    1130 minsolind = i;
    1131 minsolval = solval;
    1132 }
    1133
    1134 sumsolval += solval;
    1135 }
    1136
    1137 /* the resultant must be at most as large as every operator
    1138 * and at least as large as one minus the sum of negated operators
    1139 */
    1140 solval = SCIPgetSolVal(scip, sol, consdata->resvar);
    1141 viol = MAX3(0.0, solval - minsolval, sumsolval - (consdata->nvars - 1.0 + solval));
    1142
    1143 if( SCIPisFeasPositive(scip, viol) )
    1144 {
    1145 *violated = TRUE;
    1146
    1147 /* only reset constraint age if we are in enforcement */
    1148 if( sol == NULL )
    1149 {
    1151 }
    1152
    1153 if( printreason )
    1154 {
    1155 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
    1156 SCIPinfoMessage(scip, NULL, ";\n");
    1157 SCIPinfoMessage(scip, NULL, "violation:");
    1158
    1159 if( SCIPisFeasPositive(scip, solval - minsolval) )
    1160 {
    1161 SCIPinfoMessage(scip, NULL, " operand <%s> = FALSE and resultant <%s> = TRUE\n",
    1162 SCIPvarGetName(consdata->vars[minsolind]), SCIPvarGetName(consdata->resvar));
    1163 }
    1164 else
    1165 {
    1166 SCIPinfoMessage(scip, NULL, " all operands are TRUE and resultant <%s> = FALSE\n",
    1167 SCIPvarGetName(consdata->resvar));
    1168 }
    1169 }
    1170 }
    1171
    1172 /* update constraint violation in solution */
    1173 if( sol != NULL )
    1174 SCIPupdateSolConsViolation(scip, sol, viol, viol);
    1175 }
    1176
    1177 return SCIP_OKAY;
    1178}
    1179
    1180/** separates given primal solution */
    1181static
    1183 SCIP* scip, /**< SCIP data structure */
    1184 SCIP_CONS* cons, /**< constraint to check */
    1185 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
    1186 SCIP_Bool* separated, /**< pointer to store whether a cut was found */
    1187 SCIP_Bool* cutoff /**< whether a cutoff has been detected */
    1188 )
    1189{
    1190 SCIP_CONSDATA* consdata;
    1191 SCIP_Real feasibility;
    1192 int r;
    1193
    1194 assert(separated != NULL);
    1195 assert(cutoff != NULL);
    1196
    1197 *separated = FALSE;
    1198 *cutoff = FALSE;
    1199
    1200 consdata = SCIPconsGetData(cons);
    1201 assert(consdata != NULL);
    1202
    1203 /* create all necessary rows for the linear relaxation */
    1204 if( consdata->rows == NULL )
    1205 {
    1207 }
    1208 assert(consdata->rows != NULL);
    1209
    1210 /* test all rows for feasibility and add infeasible rows */
    1211 for( r = 0; r < consdata->nrows; ++r )
    1212 {
    1213 if( !SCIProwIsInLP(consdata->rows[r]) )
    1214 {
    1215 feasibility = SCIPgetRowSolFeasibility(scip, consdata->rows[r], sol);
    1216 if( SCIPisFeasNegative(scip, feasibility) )
    1217 {
    1218 SCIP_CALL( SCIPaddRow(scip, consdata->rows[r], FALSE, cutoff) );
    1219 if ( *cutoff )
    1220 return SCIP_OKAY;
    1221 *separated = TRUE;
    1222 }
    1223 }
    1224 }
    1225
    1226 return SCIP_OKAY;
    1227}
    1228
    1229/** analyzes conflicting TRUE assignment to resultant of given constraint, and adds conflict constraint to problem */
    1230static
    1232 SCIP* scip, /**< SCIP data structure */
    1233 SCIP_CONS* cons, /**< AND-constraint that detected the conflict */
    1234 int falsepos /**< position of operand that is fixed to FALSE */
    1235 )
    1236{
    1237 SCIP_CONSDATA* consdata;
    1238
    1239 /* conflict analysis can only be applied in solving stage and if it turned on */
    1241 return SCIP_OKAY;
    1242
    1243 consdata = SCIPconsGetData(cons);
    1244 assert(consdata != NULL);
    1245 assert(SCIPvarGetLbLocal(consdata->resvar) > 0.5);
    1246 assert(0 <= falsepos && falsepos < consdata->nvars);
    1247 assert(SCIPvarGetUbLocal(consdata->vars[falsepos]) < 0.5);
    1248
    1249 /* initialize conflict analysis, and add resultant and single operand variable to conflict candidate queue */
    1251
    1252 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
    1253 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[falsepos]) );
    1254
    1255 /* analyze the conflict */
    1257
    1258 return SCIP_OKAY;
    1259}
    1260
    1261/** analyzes conflicting FALSE assignment to resultant of given constraint, and adds conflict constraint to problem */
    1262static
    1264 SCIP* scip, /**< SCIP data structure */
    1265 SCIP_CONS* cons /**< or constraint that detected the conflict */
    1266 )
    1267{
    1268 SCIP_CONSDATA* consdata;
    1269 int v;
    1270
    1271 assert(!SCIPconsIsModifiable(cons));
    1272
    1273 /* conflict analysis can only be applied in solving stage and if it is applicable */
    1275 return SCIP_OKAY;
    1276
    1277 consdata = SCIPconsGetData(cons);
    1278 assert(consdata != NULL);
    1279 assert(SCIPvarGetUbLocal(consdata->resvar) < 0.5);
    1280
    1281 /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
    1283
    1284 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
    1285 for( v = 0; v < consdata->nvars; ++v )
    1286 {
    1287 assert(SCIPvarGetLbLocal(consdata->vars[v]) > 0.5);
    1288 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
    1289 }
    1290
    1291 /* analyze the conflict */
    1293
    1294 return SCIP_OKAY;
    1295}
    1296
    1297/** tries to fix the given resultant to zero */
    1298static
    1300 SCIP* scip, /**< SCIP data structure */
    1301 SCIP_CONS* cons, /**< AND-constraint to be processed */
    1302 SCIP_VAR* resvar, /**< resultant variable to fix to zero */
    1303 int pos, /**< position of operand that is fixed to FALSE */
    1304 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    1305 int* nfixedvars /**< pointer to add up the number of found domain reductions */
    1306 )
    1307{
    1308 SCIP_Bool infeasible;
    1309 SCIP_Bool tightened;
    1310
    1311 SCIPdebugMsg(scip, "constraint <%s>: operator %d fixed to 0.0 -> fix resultant <%s> to 0.0\n",
    1312 SCIPconsGetName(cons), pos, SCIPvarGetName(resvar));
    1313
    1314 SCIP_CALL( SCIPinferBinvarCons(scip, resvar, FALSE, cons, (int)PROPRULE_1, &infeasible, &tightened) );
    1315
    1316 if( infeasible )
    1317 {
    1318 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
    1319 SCIP_CALL( analyzeConflictOne(scip, cons, pos) );
    1321 (*cutoff) = TRUE;
    1322 }
    1323 else
    1324 {
    1326 if( tightened )
    1327 {
    1329 (*nfixedvars)++;
    1330 }
    1331 }
    1332
    1333 return SCIP_OKAY;
    1334}
    1335
    1336/** fix all operands to one */
    1337static
    1339 SCIP* scip, /**< SCIP data structure */
    1340 SCIP_CONS* cons, /**< AND-constraint to be processed */
    1341 SCIP_VAR** vars, /**< array of operands */
    1342 int nvars, /**< number of operands */
    1343 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    1344 int* nfixedvars /**< pointer to add up the number of found domain reductions */
    1345 )
    1346{
    1347 SCIP_Bool infeasible;
    1348 SCIP_Bool tightened;
    1349 int v;
    1350
    1351 for( v = 0; v < nvars && !(*cutoff); ++v )
    1352 {
    1353 SCIPdebugMsg(scip, "constraint <%s>: resultant fixed to 1.0 -> fix operator var <%s> to 1.0\n",
    1354 SCIPconsGetName(cons), SCIPvarGetName(vars[v]));
    1355
    1356 SCIP_CALL( SCIPinferBinvarCons(scip, vars[v], TRUE, cons, (int)PROPRULE_2, &infeasible, &tightened) );
    1357
    1358 if( infeasible )
    1359 {
    1360 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
    1361 SCIP_CALL( analyzeConflictOne(scip, cons, v) );
    1363 (*cutoff) = TRUE;
    1364 }
    1365 else if( tightened )
    1366 {
    1368 (*nfixedvars)++;
    1369 }
    1370 }
    1371
    1372 if( !(*cutoff) )
    1373 {
    1375 }
    1376
    1377 return SCIP_OKAY;
    1378}
    1379
    1380/** linearize AND-constraint due to a globally to zero fixed resultant; that is, creates, adds, and releases a logicor
    1381 * constraint and remove the AND-constraint globally.
    1382 *
    1383 * Since the resultant is fixed to zero the AND-constraint collapses to linear constraint of the form:
    1384 *
    1385 * - \f$\sum_{i=0}^{n-1} v_i \leq n-1\f$
    1386 *
    1387 * This can be transformed into a logicor constraint of the form
    1388 *
    1389 * - \f$\sum_{i=0}^{n-1} ~v_i \geq 1\f$
    1390 */
    1391static
    1393 SCIP* scip, /**< SCIP data structure */
    1394 SCIP_CONS* cons, /**< AND-constraint to linearize */
    1395 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    1396 int* nfixedvars, /**< pointer to add up the number of found domain reductions */
    1397 int* nupgdconss /**< pointer to add up the number of upgraded constraints */
    1398 )
    1399{
    1400 SCIP_CONSDATA* consdata;
    1401 SCIP_VAR** vars;
    1402 SCIP_CONS* lincons;
    1403 SCIP_Bool conscreated;
    1404 int nvars;
    1405
    1406 consdata = SCIPconsGetData(cons);
    1407 assert(consdata != NULL);
    1408
    1409 assert(!(*cutoff));
    1410 assert(SCIPvarGetUbGlobal(consdata->resvar) < 0.5);
    1411
    1412 nvars = consdata->nvars;
    1413 conscreated = FALSE;
    1414
    1415 /* allocate memory for variables for updated constraint */
    1416 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    1417
    1418 /* if we only have two variables, we prefer a set packing constraint instead of a logicor constraint */
    1419 if( nvars == 2 && !SCIPconsIsModifiable(cons) )
    1420 {
    1421 SCIP_Bool* negated;
    1422 SCIP_Bool infeasible;
    1423 SCIP_Bool tightened;
    1424
    1425 /* get active representation */
    1426 SCIP_CALL( SCIPallocBufferArray(scip, &negated, nvars) );
    1427 SCIP_CALL( SCIPgetBinvarRepresentatives(scip, nvars, consdata->vars, vars, negated) );
    1428 SCIPfreeBufferArray(scip, &negated);
    1429
    1430 /* if one of the two operators is globally fixed to one it follows that the other has to be zero */
    1431 if( SCIPvarGetLbGlobal(vars[0]) > 0.5 )
    1432 {
    1433 SCIP_CALL( SCIPfixVar(scip, vars[1], 0.0, &infeasible, &tightened) );
    1434
    1435 if( infeasible )
    1436 *cutoff = TRUE;
    1437 else if( tightened )
    1438 ++(*nfixedvars);
    1439 }
    1440 else if( SCIPvarGetLbGlobal(vars[1]) > 0.5 )
    1441 {
    1442 SCIP_CALL( SCIPfixVar(scip, vars[0], 0.0, &infeasible, &tightened) );
    1443
    1444 if( infeasible )
    1445 *cutoff = TRUE;
    1446 else if( tightened )
    1447 ++(*nfixedvars);
    1448 }
    1449 else if( SCIPvarGetUbGlobal(vars[0]) > 0.5 && SCIPvarGetUbGlobal(vars[1]) > 0.5 )
    1450 {
    1451 /* create, add, and release the setppc constraint */
    1452 SCIP_CALL( SCIPcreateConsSetpack(scip, &lincons, SCIPconsGetName(cons), nvars, vars,
    1456 SCIPconsIsStickingAtNode(cons)) );
    1457
    1458 conscreated = TRUE;
    1459 }
    1460 }
    1461 else
    1462 {
    1463 int v;
    1464
    1465 /* collect negated variables */
    1466 for( v = 0; v < nvars; ++v )
    1467 {
    1468 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[v], &vars[v]) );
    1469 }
    1470
    1471 /* create, add, and release the logicor constraint */
    1472 SCIP_CALL( SCIPcreateConsLogicor(scip, &lincons, SCIPconsGetName(cons), nvars, vars,
    1476 SCIPconsIsStickingAtNode(cons)) );
    1477
    1478 conscreated = TRUE;
    1479 }
    1480
    1481 if( conscreated )
    1482 {
    1483 /* add and release new constraint */
    1484 SCIPdebugPrintCons(scip, lincons, NULL); /*lint !e644*/
    1485 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &lincons) );
    1486 ++(*nupgdconss);
    1487 }
    1488
    1489 /* remove the AND-constraint globally */
    1490 SCIP_CALL( SCIPdelCons(scip, cons) );
    1491
    1492 /* delete temporary memory */
    1493 SCIPfreeBufferArray(scip, &vars);
    1494
    1495 return SCIP_OKAY;
    1496}
    1497
    1498/** the resultant is fixed to zero; in case all except one operator are fixed to TRUE the last operator has to fixed to FALSE */
    1499/** @note consdata->watchedvars might not be the same to the watchedvar parameters, because the update was not yet done */
    1500static
    1502 SCIP* scip, /**< SCIP data structure */
    1503 SCIP_CONS* cons, /**< AND-constraint to be processed */
    1504 int watchedvar1, /**< maybe last unfixed variable position */
    1505 int watchedvar2, /**< second watched position */
    1506 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    1507 int* nfixedvars /**< pointer to add up the number of found domain reductions */
    1508 )
    1509{
    1510 SCIP_CONSDATA* consdata;
    1511
    1512 consdata = SCIPconsGetData(cons);
    1513 assert(consdata != NULL);
    1514 assert(SCIPvarGetUbLocal(consdata->resvar) < 0.5);
    1515
    1516 if( watchedvar2 == -1 )
    1517 {
    1518 SCIP_Bool infeasible;
    1519 SCIP_Bool tightened;
    1520
    1521 assert(watchedvar1 != -1);
    1522
    1523#ifndef NDEBUG
    1524 /* check that all variables regardless of wathcedvar1 are fixed to 1 */
    1525 {
    1526 int v;
    1527
    1528 for( v = consdata->nvars - 1; v >= 0; --v )
    1529 if( v != watchedvar1 )
    1530 assert(SCIPvarGetLbLocal(consdata->vars[v]) > 0.5);
    1531 }
    1532#endif
    1533
    1534 SCIPdebugMsg(scip, "constraint <%s>: resultant <%s> fixed to 0.0, only one unfixed operand -> fix operand <%s> to 0.0\n",
    1535 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar), SCIPvarGetName(consdata->vars[watchedvar1]));
    1536
    1537 SCIP_CALL( SCIPinferBinvarCons(scip, consdata->vars[watchedvar1], FALSE, cons, (int)PROPRULE_4, &infeasible, &tightened) );
    1538
    1539 if( infeasible )
    1540 {
    1541 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
    1544 *cutoff = TRUE;
    1545 }
    1546 else
    1547 {
    1549 if( tightened )
    1550 {
    1552 (*nfixedvars)++;
    1553 }
    1554 }
    1555 }
    1556
    1557 return SCIP_OKAY;
    1558}
    1559
    1560/** replaces multiple occurrences of variables */
    1561static
    1563 SCIP* scip, /**< SCIP data structure */
    1564 SCIP_CONS* cons, /**< AND-constraint */
    1565 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    1566 unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
    1567 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
    1568 int* nfixedvars, /**< pointer to store number of fixed variables */
    1569 int* nchgcoefs, /**< pointer to store number of changed coefficients */
    1570 int* ndelconss /**< pointer to store number of deleted constraints */
    1571 )
    1572{
    1573 SCIP_CONSDATA* consdata;
    1574 SCIP_VAR** vars;
    1575 SCIP_VAR* var;
    1576 SCIP_VAR* probvar;
    1577 int probidx;
    1578 int nvars;
    1579 int v;
    1580#ifndef NDEBUG
    1581 int nbinvars;
    1582 int nintvars;
    1583 int nimplvars;
    1584#endif
    1585
    1586 assert(scip != NULL);
    1587 assert(cons != NULL);
    1588 assert(eventhdlr != NULL);
    1589 assert(*entries != NULL);
    1590 assert(nentries != NULL);
    1591 assert(nfixedvars != NULL);
    1592 assert(nchgcoefs != NULL);
    1593 assert(ndelconss != NULL);
    1594
    1595 consdata = SCIPconsGetData(cons);
    1596 assert(consdata != NULL);
    1597
    1598 if( consdata->merged )
    1599 return SCIP_OKAY;
    1600
    1601 /* nothing to merge */
    1602 if( consdata->nvars <= 1 )
    1603 {
    1604 consdata->merged = TRUE;
    1605 return SCIP_OKAY;
    1606 }
    1607
    1608 vars = consdata->vars;
    1609 nvars = consdata->nvars;
    1610
    1611 assert(vars != NULL);
    1612 assert(nvars >= 2);
    1613
    1614#ifndef NDEBUG
    1615 nbinvars = SCIPgetNBinVars(scip);
    1616 nintvars = SCIPgetNIntVars(scip);
    1617 nimplvars = SCIPgetNImplVars(scip);
    1618 assert(*nentries >= nbinvars + nintvars + nimplvars);
    1619#endif
    1620
    1621 /* initialize entries array */
    1622 for( v = nvars - 1; v >= 0; --v )
    1623 {
    1624 var = vars[v];
    1625 assert(var != NULL);
    1627
    1628 probvar = (SCIPvarIsActive(var) ? var : SCIPvarGetNegatedVar(var));
    1629 assert(probvar != NULL);
    1630
    1631 probidx = SCIPvarGetProbindex(probvar);
    1632 assert(0 <= probidx);
    1633
    1634 /* check variable type, either pure binary or an integer/implicit integer variable with 0/1 bounds */
    1635 assert((probidx < nbinvars && SCIPvarGetType(probvar) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(probvar))
    1636 || (SCIPvarIsBinary(probvar) &&
    1637 ((probidx >= nbinvars && probidx < nbinvars + nintvars && SCIPvarGetType(probvar) == SCIP_VARTYPE_INTEGER
    1638 && !SCIPvarIsImpliedIntegral(probvar)) ||
    1639 (probidx >= nbinvars + nintvars && probidx < nbinvars + nintvars + nimplvars &&
    1640 SCIPvarIsImpliedIntegral(probvar)))));
    1641
    1642 /* var is not active yet */
    1643 (*entries)[probidx] = 0;
    1644 }
    1645
    1646 /* search for multiple variables; scan from back to front because deletion doesn't affect the order of the front
    1647 * variables
    1648 * @note don't reorder variables because we would loose the watched variables and filter position inforamtion
    1649 */
    1650 for( v = nvars - 1; v >= 0; --v )
    1651 {
    1652 var = vars[v];
    1653 assert(var != NULL);
    1655
    1656 probvar = (SCIPvarIsActive(var) ? var : SCIPvarGetNegatedVar(var));
    1657 assert(probvar != NULL);
    1658
    1659 probidx = SCIPvarGetProbindex(probvar);
    1660 assert(0 <= probidx && probidx < *nentries);
    1661
    1662 /* if var occurs first time in constraint init entries array */
    1663 if( (*entries)[probidx] == 0 )
    1664 {
    1665 (*entries)[probidx] = (SCIPvarIsActive(var) ? 1 : 2);
    1666 }
    1667 /* if var occurs second time in constraint, first time it was not negated */
    1668 else if( ((*entries)[probidx] == 1 && SCIPvarIsActive(var)) || ((*entries)[probidx] == 2 && !SCIPvarIsActive(var)) )
    1669 {
    1670 /* delete the multiple variable */
    1671 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    1672 ++(*nchgcoefs);
    1673 }
    1674 else
    1675 {
    1676 SCIP_Bool infeasible;
    1677 SCIP_Bool fixed;
    1678
    1679 assert(((*entries)[probidx] == 1 && !SCIPvarIsActive(var)) || ((*entries)[probidx] == 2 && SCIPvarIsActive(var)));
    1680
    1681 SCIPdebugMsg(scip, "AND-constraint <%s> is redundant: variable <%s> and its negation are present -> fix resultant <%s> = 0\n",
    1682 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(consdata->resvar));
    1683
    1684 /* negation of the variable is already present in the constraint: fix resultant to zero */
    1685#ifndef NDEBUG
    1686 {
    1687 int i;
    1688 for( i = consdata->nvars - 1; i > v && var != SCIPvarGetNegatedVar(vars[i]); --i )
    1689 {}
    1690 assert(i > v);
    1691 }
    1692#endif
    1693
    1694 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
    1695 assert(!infeasible);
    1696 if( fixed )
    1697 ++(*nfixedvars);
    1698
    1699 SCIP_CALL( SCIPdelCons(scip, cons) );
    1700 break;
    1701 }
    1702 }
    1703
    1704 consdata->merged = TRUE;
    1705
    1706 return SCIP_OKAY;
    1707}
    1708
    1709/** propagates constraint with the following rules:
    1710 * (1) v_i = FALSE => r = FALSE
    1711 * (2) r = TRUE => v_i = TRUE for all i
    1712 * (3) v_i = TRUE for all i => r = TRUE
    1713 * (4) r = FALSE, v_i = TRUE for all i except j => v_j = FALSE
    1714 *
    1715 * additional if the resultant is fixed to zero during presolving or in the root node (globally), then the
    1716 * AND-constraint is collapsed to a linear (logicor) constraint of the form
    1717 * -> sum_{i=0}^{n-1} ~v_i >= 1
    1718 */
    1719static
    1721 SCIP* scip, /**< SCIP data structure */
    1722 SCIP_CONS* cons, /**< AND-constraint to be processed */
    1723 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    1724 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    1725 int* nfixedvars, /**< pointer to add up the number of found domain reductions */
    1726 int* nupgdconss /**< pointer to add up the number of upgraded constraints */
    1727 )
    1728{
    1729 SCIP_CONSDATA* consdata;
    1730 SCIP_VAR* resvar;
    1731 SCIP_VAR** vars;
    1732 int nvars;
    1733 int watchedvar1;
    1734 int watchedvar2;
    1735 int i;
    1736 SCIP_Bool infeasible;
    1737 SCIP_Bool tightened;
    1738
    1739 assert(cutoff != NULL);
    1740 assert(nfixedvars != NULL);
    1741
    1742 consdata = SCIPconsGetData(cons);
    1743 assert(consdata != NULL);
    1744
    1745 resvar = consdata->resvar;
    1746 vars = consdata->vars;
    1747 nvars = consdata->nvars;
    1748
    1749 /* don't process the constraint, if none of the operator variables was fixed to FALSE, and if the watched variables
    1750 * and the resultant weren't fixed to any value since last propagation call
    1751 */
    1752 if( consdata->propagated )
    1753 {
    1754 assert(consdata->nofixedzero);
    1755 assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(resvar), 0.0));
    1756 return SCIP_OKAY;
    1757 }
    1758
    1759 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
    1761 {
    1762 SCIP_CALL( SCIPincConsAge(scip, cons) );
    1763 }
    1764
    1765 /* if one of the operator variables was fixed to FALSE, the resultant can be fixed to FALSE (rule (1)) */
    1766 if( !consdata->nofixedzero )
    1767 {
    1768 for( i = 0; i < nvars && SCIPvarGetUbLocal(vars[i]) > 0.5; ++i ) /* search for operator fixed to zero */
    1769 {}
    1770 if( i < nvars )
    1771 {
    1772 /* fix resultant to zero */
    1773 SCIP_CALL( consdataFixResultantZero(scip, cons, resvar, i, cutoff, nfixedvars) );
    1774 }
    1775 else
    1776 consdata->nofixedzero = TRUE;
    1777 }
    1778
    1779 /* check if resultant variables is globally fixed to zero */
    1780 if( !SCIPinProbing(scip) && SCIPconsGetNUpgradeLocks(cons) == 0 && SCIPvarGetUbGlobal(resvar) < 0.5 )
    1781 {
    1782 SCIP_CALL( consdataLinearize(scip, cons, cutoff, nfixedvars, nupgdconss) );
    1783
    1784 if( *cutoff && SCIPgetDepth(scip) > 0 )
    1785 {
    1786 /* we are done with solving since a global bound change was infeasible */
    1788 }
    1789
    1790 return SCIP_OKAY;
    1791 }
    1792
    1793 /* if the resultant and at least one operand are locally fixed to zero, the constraint is locally redundant */
    1794 if( SCIPvarGetUbLocal(resvar) < 0.5 && !consdata->nofixedzero )
    1795 {
    1797 return SCIP_OKAY;
    1798 }
    1799
    1800 /* if resultant is fixed to TRUE, all operator variables can be fixed to TRUE (rule (2)) */
    1801 if( SCIPvarGetLbLocal(resvar) > 0.5 )
    1802 {
    1803 /* fix operands to one */
    1804 SCIP_CALL( consdataFixOperandsOne(scip, cons, vars, nvars, cutoff, nfixedvars) );
    1805
    1806 return SCIP_OKAY;
    1807 }
    1808
    1809 /* rules (3) and (4) can only be applied, if we know all operator variables */
    1810 if( SCIPconsIsModifiable(cons) )
    1811 return SCIP_OKAY;
    1812
    1813 /* rules (3) and (4) cannot be applied, if we have at least two unfixed variables left;
    1814 * that means, we only have to watch (i.e. capture events) of two variables, and switch to other variables
    1815 * if these ones get fixed
    1816 */
    1817 watchedvar1 = consdata->watchedvar1;
    1818 watchedvar2 = consdata->watchedvar2;
    1819
    1820 /* check, if watched variables are still unfixed */
    1821 if( watchedvar1 != -1 )
    1822 {
    1823 assert(SCIPvarGetUbLocal(vars[watchedvar1]) > 0.5); /* otherwise, rule (1) could be applied */
    1824 if( SCIPvarGetLbLocal(vars[watchedvar1]) > 0.5 )
    1825 watchedvar1 = -1;
    1826 }
    1827 if( watchedvar2 != -1 )
    1828 {
    1829 assert(SCIPvarGetUbLocal(vars[watchedvar2]) > 0.5); /* otherwise, rule (1) could be applied */
    1830 if( SCIPvarGetLbLocal(vars[watchedvar2]) > 0.5 )
    1831 watchedvar2 = -1;
    1832 }
    1833
    1834 /* if only one watched variable is still unfixed, make it the first one */
    1835 if( watchedvar1 == -1 )
    1836 {
    1837 watchedvar1 = watchedvar2;
    1838 watchedvar2 = -1;
    1839 }
    1840 assert(watchedvar1 != -1 || watchedvar2 == -1);
    1841
    1842 /* if the watched variables are invalid (fixed), find new ones if existing */
    1843 if( watchedvar2 == -1 )
    1844 {
    1845 for( i = 0; i < nvars; ++i )
    1846 {
    1847 assert(SCIPvarGetUbLocal(vars[i]) > 0.5); /* otherwise, rule (1) could be applied */
    1848 if( SCIPvarGetLbLocal(vars[i]) < 0.5 )
    1849 {
    1850 if( watchedvar1 == -1 )
    1851 {
    1852 assert(watchedvar2 == -1);
    1853 watchedvar1 = i;
    1854 }
    1855 else if( watchedvar1 != i )
    1856 {
    1857 watchedvar2 = i;
    1858 break;
    1859 }
    1860 }
    1861 }
    1862 }
    1863 assert(watchedvar1 != -1 || watchedvar2 == -1);
    1864
    1865 /* if all variables are fixed to TRUE, the resultant can also be fixed to TRUE (rule (3)) */
    1866 if( watchedvar1 == -1 )
    1867 {
    1868 assert(watchedvar2 == -1);
    1869
    1870 SCIPdebugMsg(scip, "constraint <%s>: all operator vars fixed to 1.0 -> fix resultant <%s> to 1.0\n",
    1871 SCIPconsGetName(cons), SCIPvarGetName(resvar));
    1872 SCIP_CALL( SCIPinferBinvarCons(scip, resvar, TRUE, cons, (int)PROPRULE_3, &infeasible, &tightened) );
    1873
    1874 if( infeasible )
    1875 {
    1876 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
    1879 *cutoff = TRUE;
    1880 }
    1881 else
    1882 {
    1884 if( tightened )
    1885 {
    1887 (*nfixedvars)++;
    1888 }
    1889 }
    1890
    1891 return SCIP_OKAY;
    1892 }
    1893
    1894 /* if resultant is fixed to FALSE, and only one operator variable is not fixed to TRUE, this operator variable
    1895 * can be fixed to FALSE (rule (4))
    1896 */
    1897 if( watchedvar2 == -1 && SCIPvarGetUbLocal(resvar) < 0.5 )
    1898 {
    1899 assert(watchedvar1 != -1);
    1900
    1901 SCIP_CALL( analyzeZeroResultant(scip, cons, watchedvar1, watchedvar2, cutoff, nfixedvars) );
    1902
    1903 return SCIP_OKAY;
    1904 }
    1905
    1906 /* switch to the new watched variables */
    1907 SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, watchedvar1, watchedvar2) );
    1908
    1909 /* mark the constraint propagated if we have an unfixed resultant or are not in probing, it is necessary that a fixed
    1910 * resulting in probing mode does not lead to a propagated constraint, because the constraint upgrade needs to be performed
    1911 */
    1912 consdata->propagated = (!SCIPinProbing(scip) || (SCIPvarGetLbLocal(consdata->resvar) < 0.5 && SCIPvarGetUbLocal(consdata->resvar) > 0.5));
    1913
    1914 return SCIP_OKAY;
    1915}
    1916
    1917/** resolves a conflict on the given variable by supplying the variables needed for applying the corresponding
    1918 * propagation rule (see propagateCons()):
    1919 * (1) v_i = FALSE => r = FALSE
    1920 * (2) r = TRUE => v_i = TRUE for all i
    1921 * (3) v_i = TRUE for all i => r = TRUE
    1922 * (4) r = FALSE, v_i = TRUE for all i except j => v_j = FALSE
    1923 */
    1924static
    1926 SCIP* scip, /**< SCIP data structure */
    1927 SCIP_CONS* cons, /**< constraint that inferred the bound change */
    1928 SCIP_VAR* infervar, /**< variable that was deduced */
    1929 PROPRULE proprule, /**< propagation rule that deduced the value */
    1930 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
    1931 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
    1932 )
    1933{
    1934 SCIP_CONSDATA* consdata;
    1935 SCIP_VAR** vars;
    1936 int nvars;
    1937 int i;
    1938
    1939 assert(result != NULL);
    1940
    1941 consdata = SCIPconsGetData(cons);
    1942 assert(consdata != NULL);
    1943 vars = consdata->vars;
    1944 nvars = consdata->nvars;
    1945
    1946 switch( proprule )
    1947 {
    1948 case PROPRULE_1:
    1949 /* the resultant was inferred to FALSE, because one operand variable was FALSE */
    1950 assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
    1951 assert(infervar == consdata->resvar);
    1952 for( i = 0; i < nvars; ++i )
    1953 {
    1954 if( SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) < 0.5 )
    1955 {
    1957 break;
    1958 }
    1959 }
    1960 assert(i < nvars);
    1961 *result = SCIP_SUCCESS;
    1962 break;
    1963
    1964 case PROPRULE_2:
    1965 /* the operand variable was inferred to TRUE, because the resultant was TRUE */
    1966 assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5);
    1967 assert(SCIPgetVarLbAtIndex(scip, consdata->resvar, bdchgidx, FALSE) > 0.5);
    1968 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
    1969 *result = SCIP_SUCCESS;
    1970 break;
    1971
    1972 case PROPRULE_3:
    1973 /* the resultant was inferred to TRUE, because all operand variables were TRUE */
    1974 assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5);
    1975 assert(infervar == consdata->resvar);
    1976 for( i = 0; i < nvars; ++i )
    1977 {
    1978 assert(SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) > 0.5);
    1980 }
    1981 *result = SCIP_SUCCESS;
    1982 break;
    1983
    1984 case PROPRULE_4:
    1985 /* the operand variable was inferred to FALSE, because the resultant was FALSE and all other operands were TRUE */
    1986 assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
    1987 assert(SCIPgetVarUbAtIndex(scip, consdata->resvar, bdchgidx, FALSE) < 0.5);
    1988 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
    1989 for( i = 0; i < nvars; ++i )
    1990 {
    1991 if( vars[i] != infervar )
    1992 {
    1993 assert(SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) > 0.5);
    1995 }
    1996 }
    1997 *result = SCIP_SUCCESS;
    1998 break;
    1999
    2000 case PROPRULE_INVALID:
    2001 default:
    2002 SCIPerrorMessage("invalid inference information %d in AND-constraint <%s>\n", proprule, SCIPconsGetName(cons));
    2003 return SCIP_INVALIDDATA;
    2004 }
    2005
    2006 return SCIP_OKAY;
    2007}
    2008
    2009/** perform dual presolving on AND-constraints */
    2010static
    2012 SCIP* scip, /**< SCIP data structure */
    2013 SCIP_CONS** conss, /**< AND-constraints to perform dual presolving on */
    2014 int nconss, /**< number of AND-constraints */
    2015 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    2016 unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
    2017 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
    2018 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    2019 int* nfixedvars, /**< pointer to add up the number of found domain reductions */
    2020 int* naggrvars, /**< pointer to add up the number of aggregated variables */
    2021 int* nchgcoefs, /**< pointer to add up the number of changed coefficients */
    2022 int* ndelconss, /**< pointer to add up the number of deleted constraints */
    2023 int* nupgdconss, /**< pointer to add up the number of upgraded constraints */
    2024 int* naddconss /**< pointer to add up the number of added constraints */
    2025 )
    2026{
    2027 SCIP_CONS* cons;
    2028 SCIP_CONSDATA* consdata;
    2029 SCIP_VAR** impoperands;
    2030 SCIP_VAR** vars;
    2031 SCIP_VAR* resvar;
    2032 SCIP_VAR* var;
    2033 int nimpoperands;
    2034 int nvars;
    2035 int size;
    2036 int v;
    2037 int c;
    2038 SCIP_Bool infeasible;
    2039 SCIP_Bool fixed;
    2040
    2041 assert(scip != NULL);
    2042 assert(conss != NULL || nconss == 0);
    2043 assert(eventhdlr != NULL);
    2044 assert(*entries != NULL);
    2045 assert(nentries != NULL);
    2046 assert(cutoff != NULL);
    2047 assert(nfixedvars != NULL);
    2048 assert(naggrvars != NULL);
    2049 assert(nchgcoefs != NULL);
    2050 assert(ndelconss != NULL);
    2051 assert(nupgdconss != NULL);
    2052 assert(naddconss != NULL);
    2053
    2054 if( nconss == 0 )
    2055 return SCIP_OKAY;
    2056
    2057 assert(conss != NULL);
    2058
    2059 size = 2 * (SCIPgetNBinVars(scip) + SCIPgetNImplVars(scip));
    2060
    2061 SCIP_CALL( SCIPallocBufferArray(scip, &impoperands, size) );
    2062
    2063 for( c = nconss - 1; c >= 0 && !(*cutoff); --c )
    2064 {
    2065 cons = conss[c];
    2066 assert(cons != NULL);
    2067
    2068 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsModifiable(cons) )
    2069 continue;
    2070
    2071 /* propagate constraint */
    2072 SCIP_CALL( propagateCons(scip, cons, eventhdlr, cutoff, nfixedvars, nupgdconss) );
    2073
    2074 if( !SCIPconsIsActive(cons) )
    2075 continue;
    2076
    2077 if( *cutoff )
    2078 break;
    2079
    2080 SCIP_CALL( applyFixings(scip, cons, eventhdlr, nchgcoefs) );
    2081
    2082 /* merge multiple occurances of variables or variables with their negated variables */
    2083 SCIP_CALL( mergeMultiples(scip, cons, eventhdlr, entries, nentries, nfixedvars, nchgcoefs, ndelconss) );
    2084
    2085 if( !SCIPconsIsActive(cons) )
    2086 continue;
    2087
    2088 consdata = SCIPconsGetData(cons);
    2089 assert(consdata != NULL);
    2090
    2091 vars = consdata->vars;
    2092 nvars = consdata->nvars;
    2093 assert(vars != NULL || nvars == 0);
    2094
    2095 if( nvars == 0 )
    2096 continue;
    2097
    2098 assert(vars != NULL);
    2099
    2100 resvar = consdata->resvar;
    2101 assert(SCIPvarGetLbGlobal(resvar) < 0.5);
    2102
    2103 /* dual presolving does not apply to a fixed resultant */
    2104 if( SCIPvarGetUbGlobal(resvar) < 0.5 )
    2105 continue;
    2106
    2107 assert(SCIPvarGetNLocksUpType(resvar, SCIP_LOCKTYPE_MODEL) >= 1
    2109
    2112 {
    2113 SCIP_Real resobj;
    2114 SCIP_Real obj;
    2115 SCIP_Real posobjsum = 0;
    2116 SCIP_Real maxobj = -SCIPinfinity(scip);
    2117 int maxpos = -1;
    2118 int oldnfixedvars = *nfixedvars;
    2119 int oldnaggrvars = *naggrvars;
    2120
    2121 nimpoperands = 0;
    2122
    2123 /* collect important operands */
    2124 for( v = nvars - 1; v >= 0; --v )
    2125 {
    2126 var = vars[v];
    2127 assert(var != NULL);
    2130
    2133 {
    2134 impoperands[nimpoperands] = var;
    2135 ++nimpoperands;
    2136
    2137 /* get aggregated objective value of active variable */
    2138 SCIP_CALL( SCIPvarGetAggregatedObj(var, &obj) );
    2139
    2140 /* add up all positive objective values of operands which have exactly one lock in both directions */
    2141 if( obj > 0 )
    2142 posobjsum += obj;
    2143
    2144 /* memorize maximal objective value of operands and its position */
    2145 if( obj > maxobj )
    2146 {
    2147 maxpos = nimpoperands - 1;
    2148 maxobj = obj;
    2149 }
    2150 }
    2151 }
    2152 assert(nimpoperands >= 0 && nimpoperands <= nvars);
    2153
    2154 /* no dual fixable variables found */
    2155 if( nimpoperands == 0 )
    2156 continue;
    2157
    2158 /* get aggregated objective value of active variable */
    2159 SCIP_CALL( SCIPvarGetAggregatedObj(resvar, &resobj) );
    2160
    2161 /* resultant contributes to the objective with a negative value */
    2162 if( SCIPisLE(scip, resobj, 0.0) )
    2163 {
    2164 SCIP_Bool poscontissmall = SCIPisLE(scip, posobjsum, REALABS(resobj));
    2165
    2166 /* if all variables are only locked by this constraint and the resultants contribution more then compensates
    2167 * the positive contribution, we can fix all variables to 1
    2168 */
    2169 if( nimpoperands == nvars && poscontissmall )
    2170 {
    2171 SCIPdebugMsg(scip, "dual-fixing all variables in constraint <%s> to 1\n", SCIPconsGetName(cons));
    2172
    2173 SCIP_CALL( SCIPfixVar(scip, resvar, 1.0, &infeasible, &fixed) );
    2174
    2175 *cutoff = *cutoff || infeasible;
    2176 if( fixed )
    2177 ++(*nfixedvars);
    2178
    2179 for( v = nvars - 1; v >= 0 && !(*cutoff); --v )
    2180 {
    2181 SCIP_CALL( SCIPfixVar(scip, vars[v], 1.0, &infeasible, &fixed) );
    2182
    2183 *cutoff = *cutoff || infeasible;
    2184 if( fixed )
    2185 ++(*nfixedvars);
    2186 }
    2187
    2188 SCIPdebugMsg(scip, "deleting constraint <%s> because all variables are fixed to one\n", SCIPconsGetName(cons));
    2189
    2190 SCIP_CALL( SCIPdelCons(scip, cons) );
    2191 ++(*ndelconss);
    2192 }
    2193 else
    2194 {
    2195 SCIP_Bool aggregationperformed = FALSE;
    2196 SCIP_Bool zerofix = FALSE;
    2197
    2198 assert(nimpoperands > 0);
    2199
    2200 SCIPdebugMsg(scip, "dual-fixing all variables in constraint <%s> with positive contribution (when together exceeding the negative contribution of the resultant) to 0 and with negative contribution to 1\n", SCIPconsGetName(cons));
    2201
    2202 for( v = nimpoperands - 1; v >= 0 && !(*cutoff); --v )
    2203 {
    2204 /* get aggregated objective value of active variable */
    2205 SCIP_CALL( SCIPvarGetAggregatedObj(impoperands[v], &obj) );
    2206
    2207 if( SCIPisLE(scip, obj, 0.0) )
    2208 {
    2209 SCIP_CALL( SCIPfixVar(scip, impoperands[v], 1.0, &infeasible, &fixed) );
    2210
    2211 *cutoff = *cutoff || infeasible;
    2212 if( fixed )
    2213 ++(*nfixedvars);
    2214 }
    2215 else if( !poscontissmall )
    2216 {
    2217 SCIP_CALL( SCIPfixVar(scip, impoperands[v], 0.0, &infeasible, &fixed) );
    2218 assert(!infeasible);
    2219 assert(fixed);
    2220
    2221 ++(*nfixedvars);
    2222 zerofix = TRUE;
    2223 }
    2224 else
    2225 {
    2226 SCIP_Bool redundant;
    2227 SCIP_Bool aggregated;
    2228
    2229 /* aggregate resultant to operand */
    2230 SCIP_CALL( SCIPaggregateVars(scip, resvar, impoperands[v], 1.0, -1.0, 0.0,
    2231 &infeasible, &redundant, &aggregated) );
    2232 assert(!infeasible);
    2233
    2234 if( aggregated )
    2235 {
    2236 /* note that we cannot remove the aggregated operand because we do not know the position */
    2237 ++(*naggrvars);
    2238
    2239 aggregationperformed = TRUE;
    2240
    2241 SCIPdebugMsg(scip, "dual aggregating operand <%s> with 1 up- and downlock to the resultant <%s> in constraint <%s>\n", SCIPvarGetName(impoperands[v]), SCIPvarGetName(resvar), SCIPconsGetName(cons));
    2242 }
    2243 }
    2244 }
    2245 assert(*nfixedvars - oldnfixedvars + *naggrvars - oldnaggrvars <= nimpoperands);
    2246
    2247 /* did we aggregate the resultant, then we can decide the value to fix it on the (aggregated) objective
    2248 * value since it was a independant variable
    2249 */
    2250 if( aggregationperformed || zerofix )
    2251 {
    2252 SCIP_Real fixval;
    2253
    2254 if( zerofix )
    2255 fixval = 0.0;
    2256 else
    2257 {
    2258 /* get aggregated objective value of active variable, that might be changed */
    2259 SCIP_CALL( SCIPvarGetAggregatedObj(resvar, &obj) );
    2260 assert(!SCIPisPositive(scip, obj));
    2261
    2262 fixval = (SCIPisNegative(scip, obj) ? 1.0 : 0.0);
    2263 }
    2264
    2265 if( fixval < 0.5 || *nfixedvars - oldnfixedvars + *naggrvars - oldnaggrvars == nvars )
    2266 {
    2267 SCIPdebugMsg(scip, "constraint <%s> we can fix the resultant <%s> to %g, because the AND-constraint will alwys be fulfilled\n", SCIPconsGetName(cons), SCIPvarGetName(resvar), fixval);
    2268
    2269 SCIP_CALL( SCIPfixVar(scip, resvar, fixval, &infeasible, &fixed) );
    2270 assert(!infeasible);
    2271 assert(fixed);
    2272
    2273 ++(*nfixedvars);
    2274
    2275 SCIPdebugMsg(scip, "deleting constraint <%s> because \n", SCIPconsGetName(cons));
    2276
    2277 SCIP_CALL( SCIPdelCons(scip, cons) );
    2278 ++(*ndelconss);
    2279 }
    2280 }
    2281 }
    2282 }
    2283 /* resultant contributes to the objective with a positive value */
    2284 else
    2285 {
    2286 SCIP_Bool zerofix = FALSE;
    2287#ifndef NDEBUG
    2288 SCIP_Real tmpobj;
    2289
    2290 assert(nimpoperands > 0);
    2291 assert(maxpos >= 0 && maxpos <= consdata->nvars);
    2292 assert(!SCIPisInfinity(scip, -maxobj));
    2293 SCIP_CALL( SCIPvarGetAggregatedObj(impoperands[maxpos], &tmpobj) );
    2294 assert(SCIPisEQ(scip, tmpobj, maxobj));
    2295#endif
    2296
    2297 /* if the smallest possible contribution is negative, but does not compensate the positive contribution of
    2298 * the resultant we need to fix this variable to 0
    2299 */
    2300 if( nimpoperands == nvars && SCIPisLE(scip, maxobj, 0.0) )
    2301 {
    2302 SCIP_Real fixval = (SCIPisLE(scip, REALABS(maxobj), resobj) ? 0.0 : 1.0);
    2303
    2304 SCIPdebugMsg(scip, "dual-fixing variable <%s> in constraint <%s> to %g, because the contribution is%s " \
    2305 "enough to nullify/exceed the contribution of the resultant \n",
    2306 SCIPvarGetName(impoperands[maxpos]), SCIPconsGetName(cons), fixval, (fixval < 0.5) ? " not" : "");
    2307
    2308 SCIP_CALL( SCIPfixVar(scip, impoperands[maxpos], fixval, &infeasible, &fixed) );
    2309 zerofix = (fixval < 0.5);
    2310
    2311 *cutoff = *cutoff || infeasible;
    2312 if( fixed )
    2313 ++(*nfixedvars);
    2314 }
    2315
    2316 SCIPdebugMsg(scip, "dual-fixing all variables, except the variable with the highest contribution to " \
    2317 "the objective, in constraint <%s> with positive contribution to 0 and with negative contribution to 1\n",
    2318 SCIPconsGetName(cons));
    2319
    2320 for( v = nimpoperands - 1; v >= 0 && !(*cutoff); --v )
    2321 {
    2322 /* get aggregated objective value of active variable */
    2323 SCIP_CALL( SCIPvarGetAggregatedObj(impoperands[v], &obj) );
    2324
    2325 if( SCIPisLE(scip, obj, 0.0) )
    2326 {
    2327 if( v == maxpos )
    2328 continue;
    2329
    2330 SCIP_CALL( SCIPfixVar(scip, impoperands[v], 1.0, &infeasible, &fixed) );
    2331 }
    2332 else
    2333 {
    2334 SCIP_CALL( SCIPfixVar(scip, impoperands[v], 0.0, &infeasible, &fixed) );
    2335 zerofix = TRUE;
    2336 }
    2337
    2338 *cutoff = *cutoff || infeasible;
    2339 if( fixed )
    2340 ++(*nfixedvars);
    2341 }
    2342 assert(*nfixedvars - oldnfixedvars <= nimpoperands);
    2343 /* iff we have fixed all variables, all variables needed to be stored in the impoperands array */
    2344 assert((*nfixedvars - oldnfixedvars == nvars) == (nimpoperands == nvars));
    2345
    2346 if( *nfixedvars - oldnfixedvars == nvars )
    2347 {
    2348 SCIPdebugMsg(scip, "all operands are fixed in constraint <%s> => fix resultant <%s> to %g\n", SCIPconsGetName(cons), SCIPvarGetName(resvar), (zerofix ? 0.0 : 1.0));
    2349
    2350 SCIP_CALL( SCIPfixVar(scip, resvar, zerofix ? 0.0 : 1.0, &infeasible, &fixed) );
    2351
    2352 *cutoff = *cutoff || infeasible;
    2353 if( fixed )
    2354 ++(*nfixedvars);
    2355
    2356 SCIPdebugMsg(scip, "deleting constraint <%s> because all variables are fixed\n", SCIPconsGetName(cons));
    2357
    2358 SCIP_CALL( SCIPdelCons(scip, cons) );
    2359 ++(*ndelconss);
    2360 }
    2361 }
    2362 }
    2363 /* resultant is lock by another constraint (handler), check for operands with only one down- and uplock */
    2364 else
    2365 {
    2366 SCIP_Real maxobj = -SCIPinfinity(scip);
    2367 SCIP_Real resobj;
    2368 SCIP_Real obj;
    2369 SCIP_Bool redundant;
    2370 SCIP_Bool aggregated;
    2371 SCIP_Bool resobjispos;
    2372 SCIP_Bool linearize = FALSE;
    2373 SCIP_Bool zerofix = FALSE;
    2374#ifndef NDEBUG
    2375 int oldnchgcoefs = *nchgcoefs;
    2376 int oldnfixedvars = *nfixedvars;
    2377#endif
    2378
    2379 /* get aggregated objective value of active variable */
    2380 SCIP_CALL( SCIPvarGetAggregatedObj(resvar, &resobj) );
    2381
    2382 resobjispos = SCIPisGT(scip, resobj, 0.0);
    2383
    2384 /* we can only aggregate when the objective contribution of the resultant is less or equal to 0 */
    2385 if( !resobjispos )
    2386 {
    2387 SCIP_Bool goodvarsfound = FALSE;
    2388
    2389 for( v = nvars - 1; v >= 0; --v )
    2390 {
    2391 var = vars[v];
    2392 assert(var != NULL);
    2395
    2396 /* get aggregated objective value of active variable */
    2397 SCIP_CALL( SCIPvarGetAggregatedObj(var, &obj) );
    2398
    2399 /* all operands which are only locked by this constraint, the objective contribution is greater or equal
    2400 * to 0 can be aggregated to the resultant
    2401 */
    2404 {
    2405 if( !SCIPisNegative(scip, obj) )
    2406 {
    2407 /* aggregate resultant to operand */
    2408 SCIP_CALL( SCIPaggregateVars(scip, resvar, var, 1.0, -1.0, 0.0, &infeasible, &redundant,
    2409 &aggregated) );
    2410
    2411 if( aggregated && SCIPconsGetNUpgradeLocks(cons) == 0 )
    2412 {
    2413 ++(*naggrvars);
    2414
    2415 linearize = TRUE;
    2416
    2417 /* delete redundant entry from constraint */
    2418 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    2419 ++(*nchgcoefs);
    2420
    2422 "dual aggregating operand <%s> with 1 up- and downlock to the resultant <%s> in constraint <%s>\n",
    2423 SCIPvarGetName(var), SCIPvarGetName(resvar), SCIPconsGetName(cons));
    2424 }
    2425
    2426 *cutoff = *cutoff || infeasible;
    2427 }
    2428 else
    2429 goodvarsfound = TRUE;
    2430 }
    2431 }
    2432 assert(*nchgcoefs - oldnchgcoefs <= nvars);
    2433
    2434 /* if we aggregated an operands with the resultant we can also fix "good" independant operands to 1, since
    2435 * the correctness of "resultant = 0 => at least one operand = 0" in enforced by that aggregation
    2436 * without an aggregation we cannot fix these variables since it might lead to infeasibility, e.g.
    2437 *
    2438 * obj(x3) = -1
    2439 * r = x1 * x2 * x3
    2440 * r = 0
    2441 * x1 = 1
    2442 * x2 = 1
    2443 */
    2444 if( !*cutoff && goodvarsfound && linearize )
    2445 {
    2446 /* fix good variables to 1 */
    2447 for( v = consdata->nvars - 1; v >= 0; --v )
    2448 {
    2449 var = vars[v];
    2450 assert(var != NULL);
    2451
    2454 {
    2455#ifndef NDEBUG
    2456 /* aggregated objective value of active variable need to be negative */
    2457 SCIP_CALL( SCIPvarGetAggregatedObj(var, &obj) );
    2458 assert(SCIPisNegative(scip, obj));
    2459#endif
    2461 "dual-fixing variable <%s> in constraint <%s> to 1, because the contribution is negative\n",
    2462 SCIPvarGetName(var), SCIPconsGetName(cons));
    2463
    2464 SCIP_CALL( SCIPfixVar(scip, var, 1.0, &infeasible, &fixed) );
    2465
    2466 assert(!infeasible);
    2467 if( fixed )
    2468 ++(*nfixedvars);
    2469 }
    2470 }
    2471 assert(*nfixedvars - oldnfixedvars <= consdata->nvars);
    2472 }
    2473 assert(*nchgcoefs - oldnchgcoefs + *nfixedvars - oldnfixedvars <= nvars);
    2474 }
    2475 /* if the downlocks of the resultant are only from this constraint and the objective contribution is positive,
    2476 * we can try to fix operands
    2477 */
    2478 else if( SCIPvarGetNLocksDownType(resvar, SCIP_LOCKTYPE_MODEL) == 1 )
    2479 {
    2480 SCIP_Bool locksareone = TRUE;
    2481 int maxpos = -1;
    2482
    2483 for( v = nvars - 1; v >= 0; --v )
    2484 {
    2485 var = vars[v];
    2486 assert(var != NULL);
    2489
    2490 /* check if all resultants are only locked by this constraint */
    2491 locksareone = locksareone && (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
    2493
    2494 /* get aggregated objective value of active variable */
    2495 SCIP_CALL( SCIPvarGetAggregatedObj(var, &obj) );
    2496
    2497 /* memorize maximal objective value of operands and its position */
    2498 if( obj > maxobj )
    2499 {
    2500 maxpos = v;
    2501 maxobj = obj;
    2502 }
    2503
    2504 /* all operands which are only locked by this constraint, the objective contribution is greater or equal
    2505 * to 0, and the absolute value of the contribution of the resultant exceeds can be eliminated and
    2506 * aggregated to the resultant
    2507 */
    2509 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1 && SCIPisGE(scip, obj, 0.0) )
    2510 {
    2511 SCIPdebugMsg(scip, "dualfix operand <%s> in constraint <%s> to 0\n", SCIPvarGetName(var), SCIPconsGetName(cons));
    2512
    2513 SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) );
    2514
    2515 *cutoff = *cutoff || infeasible;
    2516 if( fixed )
    2517 ++(*nfixedvars);
    2518
    2519 zerofix = TRUE;
    2520 }
    2521 }
    2522 assert(*nchgcoefs - oldnchgcoefs <= nvars);
    2523
    2524 /* if constraint is still active and all operands are only lock by this constraint, we check if we can fix
    2525 * the worst (in objective contribution) operand to zero
    2526 */
    2527 if( !zerofix && locksareone && SCIPisGE(scip, resobj, REALABS(maxobj)) )
    2528 {
    2529 assert(!zerofix);
    2530 /* objective contribution needs to be negative, otherwise, the variable should already be fixed to 0 */
    2531 assert(SCIPisLT(scip, maxobj, 0.0));
    2532
    2533 SCIPdebugMsg(scip, "dualfix operand <%s> with worst contribution in constraint <%s> to 0\n", SCIPvarGetName(vars[maxpos]), SCIPconsGetName(cons));
    2534
    2535 SCIP_CALL( SCIPfixVar(scip, vars[maxpos], 0.0, &infeasible, &fixed) );
    2536
    2537 *cutoff = *cutoff || infeasible;
    2538 if( fixed )
    2539 ++(*nfixedvars);
    2540
    2541 zerofix = TRUE;
    2542 }
    2543
    2544 /* fix the resultant if one operand was fixed to zero and delete the constraint */
    2545 if( zerofix )
    2546 {
    2547 SCIPdebugMsg(scip, "fix resultant <%s> in constraint <%s> to 0\n", SCIPvarGetName(resvar), SCIPconsGetName(cons));
    2548
    2549 SCIP_CALL( SCIPfixVar(scip, resvar, 0.0, &infeasible, &fixed) );
    2550
    2551 *cutoff = *cutoff || infeasible;
    2552 if( fixed )
    2553 ++(*nfixedvars);
    2554
    2555 SCIPdebugMsg(scip, "deleting constraint <%s> because at least one operand and the resultant is fixed to zero\n", SCIPconsGetName(cons));
    2556
    2557 SCIP_CALL( SCIPdelCons(scip, cons) );
    2558 ++(*ndelconss);
    2559 }
    2560 }
    2561
    2562 /* we have to linearize the constraint, otherwise we might get wrong propagations, since due to aggregations a
    2563 * resultant fixed to zero is already fulfilling the constraint, and we must not ensure that some remaining
    2564 * operand needs to be 0
    2565 */
    2566 if( linearize )
    2567 {
    2568 SCIP_CONS* newcons;
    2569 char consname[SCIP_MAXSTRLEN];
    2570 SCIP_VAR* consvars[2];
    2571 SCIP_Real vals[2];
    2572
    2573 assert(SCIPconsIsActive(cons));
    2574 assert(SCIPconsGetNUpgradeLocks(cons) == 0);
    2575
    2576 consvars[0] = consdata->resvar;
    2577 vals[0] = 1.0;
    2578 vals[1] = -1.0;
    2579
    2580 /* create operator linear constraints */
    2581 for( v = consdata->nvars - 1; v >= 0; --v )
    2582 {
    2583 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), v);
    2584 consvars[1] = consdata->vars[v];
    2585
    2586 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, 2, consvars, vals, -SCIPinfinity(scip), 0.0,
    2590 SCIPconsIsStickingAtNode(cons)) );
    2591
    2592 /* add constraint */
    2593 SCIP_CALL( SCIPaddCons(scip, newcons) );
    2594 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    2595 }
    2596 (*naddconss) += consdata->nvars;
    2597
    2598 SCIPdebugMsg(scip, "deleting constraint <%s> because it was linearized\n", SCIPconsGetName(cons));
    2599
    2600 SCIP_CALL( SCIPdelCons(scip, cons) );
    2601 ++(*ndelconss);
    2602 }
    2603 /* if only one operand is leftover, aggregate it to the resultant */
    2604 else if( consdata->nvars == 1 )
    2605 {
    2606 SCIPdebugMsg(scip, "aggregating last operand <%s> to the resultant <%s> in constraint <%s>\n", SCIPvarGetName(consdata->vars[0]), SCIPvarGetName(resvar), SCIPconsGetName(cons));
    2607
    2608 /* aggregate resultant to operand */
    2609 SCIP_CALL( SCIPaggregateVars(scip, resvar, consdata->vars[0], 1.0, -1.0, 0.0,
    2610 &infeasible, &redundant, &aggregated) );
    2611
    2612 if( aggregated )
    2613 ++(*naggrvars);
    2614
    2615 *cutoff = *cutoff || infeasible;
    2616
    2617 SCIPdebugMsg(scip, "deleting constraint <%s> because all variables are removed\n", SCIPconsGetName(cons));
    2618
    2619 SCIP_CALL( SCIPdelCons(scip, cons) );
    2620 ++(*ndelconss);
    2621 }
    2622
    2623 /* if no operand is leftover delete the constraint */
    2624 if( SCIPconsIsActive(cons) && consdata->nvars == 0 )
    2625 {
    2626 SCIPdebugMsg(scip, "deleting constraint <%s> because all variables are removed\n", SCIPconsGetName(cons));
    2627
    2628 SCIP_CALL( SCIPdelCons(scip, cons) );
    2629 ++(*ndelconss);
    2630 }
    2631 }
    2632 }
    2633
    2634 SCIPfreeBufferArray(scip, &impoperands);
    2635
    2636 return SCIP_OKAY;
    2637}
    2638
    2639/** 1. check if at least two operands or one operand and the resultant are in one clique, if so, we can fix the
    2640 * resultant to zero and in the former case we can also delete this constraint but we need to extract the clique
    2641 * information as constraint
    2642 *
    2643 * x == AND(y, z) and clique(y,z) => x = 0, delete constraint and create y + z <= 1
    2644 * x == AND(y, z) and clique(x,y) => x = 0
    2645 *
    2646 * special handled cases are:
    2647 * - if the resultant is a negation of an operand, in that case we fix the resultant to 0
    2648 * - if the resultant is equal to an operand, we will linearize this constraint by adding all necessary
    2649 * set-packing constraints like resultant + ~operand <= 1 and delete the old constraint
    2650 *
    2651 * x == AND(~x, y) => x = 0
    2652 * x == AND(x, y) => add x + ~y <= 1 and delete the constraint
    2653 *
    2654 * 2. check if one operand is in a clique with the negation of all other operands, this means we can aggregate this
    2655 * operand to the resultant
    2656 *
    2657 * r == AND(x,y,z) and clique(x,~y) and clique(x,~z) => r == x
    2658 *
    2659 * 3. check if the resultant and the negations of all operands are in a clique
    2660 *
    2661 * r == AND(x,y) and clique(r, ~x,~y) => upgrade the constraint to a set-partitioning constraint r + ~x + ~y = 1
    2662 *
    2663 * @note We removed also fixed variables and propagate them, and if only one operand is remaining due to removal, we
    2664 * will aggregate the resultant with this operand
    2665 */
    2666static
    2668 SCIP* scip, /**< SCIP data structure */
    2669 SCIP_CONS* cons, /**< constraint to process */
    2670 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    2671 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    2672 int* nfixedvars, /**< pointer to add up the number of found domain reductions */
    2673 int* naggrvars, /**< pointer to add up the number of aggregated variables */
    2674 int* nchgcoefs, /**< pointer to add up the number of changed coefficients */
    2675 int* ndelconss, /**< pointer to add up the number of deleted constraints */
    2676 int* naddconss /**< pointer to add up the number of added constraints */
    2677 )
    2678{
    2679 SCIP_CONSDATA* consdata;
    2680 SCIP_VAR** vars;
    2681 SCIP_VAR* var1;
    2682 SCIP_VAR* var2;
    2683 int nvars;
    2684 int vstart;
    2685 int vend;
    2686 int v;
    2687 int v2;
    2688 SCIP_Bool negated;
    2689 SCIP_Bool value1;
    2690 SCIP_Bool value2;
    2691 SCIP_Bool infeasible;
    2692 SCIP_Bool fixed;
    2693 SCIP_Bool allnegoperandsexist;
    2694
    2695 assert(scip != NULL);
    2696 assert(cons != NULL);
    2697 assert(eventhdlr != NULL);
    2698 assert(cutoff != NULL);
    2699 assert(nfixedvars != NULL);
    2700 assert(naggrvars != NULL);
    2701 assert(nchgcoefs != NULL);
    2702 assert(ndelconss != NULL);
    2703 assert(naddconss != NULL);
    2704
    2705 consdata = SCIPconsGetData(cons);
    2706 assert(consdata != NULL);
    2707
    2708 if( !SCIPconsIsActive(cons) || SCIPconsIsModifiable(cons) )
    2709 return SCIP_OKAY;
    2710
    2711 vars = consdata->vars;
    2712 nvars = consdata->nvars;
    2713 assert(vars != NULL || nvars == 0);
    2714
    2715 /* remove fixed variables to be able to ask for cliques
    2716 *
    2717 * if an operand is fixed to 0 fix the resultant to 0 and delete the constraint
    2718 * if an operand is fixed to 1 remove it from the constraint
    2719 */
    2720 for( v = nvars - 1; v >= 0; --v )
    2721 {
    2722 assert(vars != NULL);
    2723
    2724 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
    2725 {
    2726 SCIPdebugMsg(scip, "In constraint <%s> the operand <%s> is fixed to 1 so remove it from the constraint\n",
    2727 SCIPconsGetName(cons), SCIPvarGetName(vars[v]));
    2728
    2729 /* because we loop from back to front we can delete the entry in the consdata structure */
    2730 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    2731 ++(*nchgcoefs);
    2732
    2733 assert(consdata->vars == vars);
    2734
    2735 continue;
    2736 }
    2737 else if( SCIPvarGetUbGlobal(vars[v]) < 0.5 )
    2738 {
    2739 SCIPdebugMsg(scip, "constraint <%s> redundant: because operand <%s> is fixed to zero so we can fix the resultant <%s> to 0\n",
    2740 SCIPconsGetName(cons), SCIPvarGetName(vars[v]), SCIPvarGetName(consdata->resvar));
    2741
    2742 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
    2743 *cutoff = *cutoff || infeasible;
    2744 if( fixed )
    2745 ++(*nfixedvars);
    2746
    2747 SCIP_CALL( SCIPdelCons(scip, cons) );
    2748 ++(*ndelconss);
    2749
    2750 return SCIP_OKAY;
    2751 }
    2752 }
    2753
    2754 /* if we deleted some operands constraint might be redundant */
    2755 if( consdata->nvars < nvars )
    2756 {
    2757 assert(vars == consdata->vars);
    2758
    2759 /* all operands fixed to one were removed, so if no operand is left this means we can fix the resultant to 1
    2760 * too
    2761 */
    2762 if( consdata->nvars == 0 )
    2763 {
    2764 SCIPdebugMsg(scip, "All operand in constraint <%s> were deleted, so the resultant needs to be fixed to 1\n",
    2765 SCIPconsGetName(cons));
    2766
    2767 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 1.0, &infeasible, &fixed) );
    2768 *cutoff = *cutoff || infeasible;
    2769 if( fixed )
    2770 ++(*nfixedvars);
    2771
    2772 SCIP_CALL( SCIPdelCons(scip, cons) );
    2773 ++(*ndelconss);
    2774
    2775 return SCIP_OKAY;
    2776 }
    2777 /* if only one not fixed operand is left, we can aggregate it to the resultant */
    2778 else if( consdata->nvars == 1 )
    2779 {
    2780 SCIP_Bool redundant;
    2781 SCIP_Bool aggregated;
    2782
    2783 /* aggregate resultant to last operand */
    2784 SCIP_CALL( SCIPaggregateVars(scip, consdata->resvar, consdata->vars[0], 1.0, -1.0, 0.0,
    2785 &infeasible, &redundant, &aggregated) );
    2786
    2787 if( aggregated )
    2788 ++(*naggrvars);
    2789
    2790 SCIP_CALL( SCIPdelCons(scip, cons) );
    2791 ++(*ndelconss);
    2792
    2793 *cutoff = *cutoff || infeasible;
    2794
    2795 return SCIP_OKAY;
    2796 }
    2797
    2798 nvars = consdata->nvars;
    2799 }
    2800
    2801 /* @todo when cliques are improved, we only need to collect all clique-ids for all variables and check for doubled
    2802 * entries
    2803 */
    2804 /* case 1 first part */
    2805 /* check if two operands are in a clique */
    2806 if( SCIPconsGetNUpgradeLocks(cons) == 0 )
    2807 {
    2808 for( v = nvars - 1; v > 0; --v )
    2809 {
    2810 assert(vars != NULL);
    2811
    2812 var1 = vars[v];
    2813 assert(var1 != NULL);
    2814 negated = FALSE;
    2815
    2816 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
    2817 assert(var1 != NULL);
    2818
    2819 if( negated )
    2820 value1 = FALSE;
    2821 else
    2822 value1 = TRUE;
    2823
    2824 assert(SCIPvarGetStatus(var1) != SCIP_VARSTATUS_FIXED);
    2825
    2826 for( v2 = v - 1; v2 >= 0; --v2 )
    2827 {
    2828 var2 = vars[v2];
    2829 assert(var2 != NULL);
    2830
    2831 negated = FALSE;
    2832 SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
    2833 assert(var2 != NULL);
    2834
    2835 if( negated )
    2836 value2 = FALSE;
    2837 else
    2838 value2 = TRUE;
    2839
    2840 assert(SCIPvarGetStatus(var2) != SCIP_VARSTATUS_FIXED);
    2841
    2842 /* if both variables are negated of each other or the same, this will be handled in applyFixings();
    2843 * @note if both variables are the same, then SCIPvarsHaveCommonClique() will return TRUE, so we better
    2844 * continue
    2845 */
    2846 if( var1 == var2 )
    2847 continue;
    2848
    2849 if( SCIPvarsHaveCommonClique(var1, value1, var2, value2, TRUE) )
    2850 {
    2851 SCIP_CONS* cliquecons;
    2852 SCIP_VAR* consvars[2];
    2853 char name[SCIP_MAXSTRLEN];
    2854
    2855 SCIPdebugMsg(scip, "constraint <%s> redundant: because variable <%s> and variable <%s> are in a clique, the resultant <%s> can be fixed to 0\n",
    2856 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2), SCIPvarGetName(consdata->resvar));
    2857
    2858 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
    2859 *cutoff = *cutoff || infeasible;
    2860 if( fixed )
    2861 ++(*nfixedvars);
    2862
    2863 /* create clique constraint which lead to the last fixing */
    2864 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clq_%d", SCIPconsGetName(cons), v2);
    2865
    2866 if( value1 )
    2867 consvars[0] = var1;
    2868 else
    2869 {
    2870 SCIP_CALL( SCIPgetNegatedVar(scip, var1, &(consvars[0])) );
    2871 }
    2872
    2873 if( value2 )
    2874 consvars[1] = var2;
    2875 else
    2876 {
    2877 SCIP_CALL( SCIPgetNegatedVar(scip, var2, &(consvars[1])) );
    2878 }
    2879
    2880 SCIP_CALL( SCIPcreateConsSetpack(scip, &cliquecons, name, 2, consvars,
    2884 SCIPconsIsStickingAtNode(cons)) );
    2885 SCIPdebugMsg(scip, " -> adding clique constraint: ");
    2886 SCIPdebugPrintCons(scip, cliquecons, NULL);
    2887 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &cliquecons) );
    2888 ++(*naddconss);
    2889
    2890 SCIP_CALL( SCIPdelCons(scip, cons) );
    2891 ++(*ndelconss);
    2892
    2893 return SCIP_OKAY;
    2894 }
    2895 }
    2896 }
    2897 }
    2898
    2899 var1 = consdata->resvar;
    2900 assert(var1 != NULL);
    2901
    2902 negated = FALSE;
    2903 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
    2904 assert(var1 != NULL);
    2905
    2906 /* it may appear that we have a fixed resultant */
    2908 {
    2909 /* resultant is fixed to 1, so fix all operands to 1 */
    2910 if( SCIPvarGetLbGlobal(consdata->resvar) > 0.5 )
    2911 {
    2912 SCIPdebugMsg(scip, "In constraint <%s> the resultant <%s> is fixed to 1 so fix all operands to 1\n",
    2913 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
    2914
    2915 /* fix all operands to 1 */
    2916 for( v = nvars - 1; v >= 0 && !(*cutoff); --v )
    2917 {
    2918 assert(vars != NULL);
    2919
    2920 SCIPdebugMsg(scip, "Fixing operand <%s> to 1.\n", SCIPvarGetName(vars[v]));
    2921
    2922 SCIP_CALL( SCIPfixVar(scip, vars[v], 1.0, &infeasible, &fixed) );
    2923 *cutoff = *cutoff || infeasible;
    2924
    2925 if( fixed )
    2926 ++(*nfixedvars);
    2927 }
    2928
    2929 SCIP_CALL( SCIPdelCons(scip, cons) );
    2930 ++(*ndelconss);
    2931 }
    2932 /* the upgrade to a linear constraint because of the to 0 fixed resultant we do in propagateCons() */
    2933 else
    2934 assert(SCIPvarGetUbGlobal(consdata->resvar) < 0.5);
    2935
    2936 return SCIP_OKAY;
    2937 }
    2938
    2939 if( negated )
    2940 value1 = FALSE;
    2941 else
    2942 value1 = TRUE;
    2943
    2944 /* case 1 second part */
    2945 /* check if one operands is in a clique with the resultant */
    2946 for( v = nvars - 1; v >= 0; --v )
    2947 {
    2948 assert(vars != NULL);
    2949
    2950 var2 = vars[v];
    2951 assert(var2 != NULL);
    2952
    2953 negated = FALSE;
    2954 SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
    2955 assert(var2 != NULL);
    2956
    2957 if( negated )
    2958 value2 = FALSE;
    2959 else
    2960 value2 = TRUE;
    2961
    2962 /* if both variables are negated of each other or the same, this will be handled in applyFixings();
    2963 * @note if both variables are the same, then SCIPvarsHaveCommonClique() will return TRUE, so we better continue
    2964 */
    2965 if( var1 == var2 )
    2966 {
    2967 /* x1 == AND(~x1, x2 ...) => x1 = 0 */
    2968 if( value1 != value2 )
    2969 {
    2970 SCIPdebugMsg(scip, "In constraint <%s> the resultant <%s> can be fixed to 0 because the negation of it is an operand.\n",
    2971 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
    2972
    2973 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
    2974 *cutoff = *cutoff || infeasible;
    2975
    2976 if( fixed )
    2977 ++(*nfixedvars);
    2978
    2979 return SCIP_OKAY;
    2980 }
    2981 /* x1 == AND(x1, x2 ...) => delete constraint and create all set-packing constraints x1 + ~x2 <= 1, x1 + ~... <= 1 */
    2982 else if( SCIPconsGetNUpgradeLocks(cons) == 0 )
    2983 {
    2984 SCIP_CONS* cliquecons;
    2985 SCIP_VAR* consvars[2];
    2986 char name[SCIP_MAXSTRLEN];
    2987
    2988 assert(value1 == value2);
    2989
    2990 consvars[0] = consdata->resvar;
    2991
    2992 for( v2 = nvars - 1; v2 >= 0; --v2 )
    2993 {
    2994 var2 = vars[v2];
    2995 negated = FALSE;
    2996 SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
    2997
    2998 /* if the active representations of the resultant and an operand are different then we need to extract
    2999 * this as a clique constraint
    3000 *
    3001 * if the active representations of the resultant and an operand are equal then the clique constraint
    3002 * would look like x1 + ~x1 <= 1, which is redundant
    3003 *
    3004 * if the active representations of the resultant and an operand are negated of each other then the
    3005 * clique constraint would look like x1 + x1 <= 1, which will lead to a fixation of the resultant later
    3006 * on
    3007 */
    3008 if( var1 == var2 )
    3009 {
    3010 if( value1 == negated )
    3011 {
    3012 SCIPdebugMsg(scip, "In constraint <%s> the resultant <%s> can be fixed to 0 because the negation of it is an operand.\n",
    3013 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
    3014
    3015 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
    3016 *cutoff = *cutoff || infeasible;
    3017
    3018 if( fixed )
    3019 ++(*nfixedvars);
    3020
    3021 break;
    3022 }
    3023 }
    3024 else
    3025 {
    3026 SCIP_CALL( SCIPgetNegatedVar(scip, vars[v2], &consvars[1]) );
    3027 assert(consvars[1] != NULL);
    3028
    3029 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clq_%d", SCIPconsGetName(cons), v2);
    3030
    3031 SCIP_CALL( SCIPcreateConsSetpack(scip, &cliquecons, name, 2, consvars,
    3035 SCIPconsIsStickingAtNode(cons)) );
    3036 SCIPdebugMsg(scip, " -> adding clique constraint: ");
    3037 SCIPdebugPrintCons(scip, cliquecons, NULL);
    3038 SCIP_CALL( SCIPaddCons(scip, cliquecons) );
    3039 SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
    3040 ++(*naddconss);
    3041 }
    3042 }
    3043
    3044 /* delete old constraint */
    3045 SCIP_CALL( SCIPdelCons(scip, cons) );
    3046 ++(*ndelconss);
    3047
    3048 return SCIP_OKAY;
    3049 }
    3050 /* due to SCIPvarsHaveCommonClique() returns on two same variables that they are in a clique, we need to
    3051 * handle it explicitly
    3052 */
    3053 else
    3054 continue;
    3055 }
    3056
    3057 /* fix resultant in operand clique */
    3058 if( SCIPvarsHaveCommonClique(var1, value1, var2, value2, TRUE) )
    3059 {
    3060 SCIPdebugMsg(scip, "in constraint <%s> the resultant <%s> can be fixed to 0 because it is in a clique with operand <%s>\n",
    3061 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
    3062
    3063 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
    3064 *cutoff = *cutoff || infeasible;
    3065 if( fixed )
    3066 ++(*nfixedvars);
    3067
    3068 return SCIP_OKAY;
    3069 }
    3070 }
    3071
    3072 if( !SCIPconsIsActive(cons) )
    3073 return SCIP_OKAY;
    3074
    3075 v2 = -1;
    3076 /* check which operands have a negated variable */
    3077 for( v = nvars - 1; v >= 0; --v )
    3078 {
    3079 assert(vars != NULL);
    3080
    3081 var1 = vars[v];
    3082 assert(var1 != NULL);
    3083
    3084 negated = FALSE;
    3085 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
    3086 assert(var1 != NULL);
    3087
    3088 if( SCIPvarGetNegatedVar(var1) == NULL )
    3089 {
    3090 if( v2 >= 0 )
    3091 break;
    3092 v2 = v;
    3093 }
    3094 }
    3095
    3096 allnegoperandsexist = FALSE;
    3097
    3098 /* all operands have a negated variable, so we will check for all possible negated ciques */
    3099 if( v2 == -1 )
    3100 {
    3101 allnegoperandsexist = TRUE;
    3102 vstart = nvars - 1;
    3103 vend = 0;
    3104 }
    3105 /* exactly one operands has no negated variable, so only this variable can be in a clique with all other negations */
    3106 else if( v2 >= 0 && v == -1 )
    3107 {
    3108 vstart = v2;
    3109 vend = v2;
    3110 }
    3111 /* at least two operands have no negated variable, so there is no possible clique with negated variables */
    3112 else
    3113 {
    3114 vstart = -1;
    3115 vend = 0;
    3116 }
    3117
    3118 /* case 2 */
    3119 /* check for negated cliques in the operands */
    3120 for( v = vstart; v >= vend; --v )
    3121 {
    3122 assert(vars != NULL);
    3123
    3124 var1 = vars[v];
    3125 assert(var1 != NULL);
    3126
    3127 negated = FALSE;
    3128 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
    3129 assert(var1 != NULL);
    3130
    3131 if( negated )
    3132 value1 = FALSE;
    3133 else
    3134 value1 = TRUE;
    3135
    3136 for( v2 = nvars - 1; v2 >= 0; --v2 )
    3137 {
    3138 if( v2 == v )
    3139 continue;
    3140
    3141 var2 = vars[v2];
    3142 assert(var2 != NULL);
    3143
    3144 negated = FALSE;
    3145 SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
    3146 assert(var2 != NULL);
    3147
    3148 if( negated )
    3149 value2 = FALSE;
    3150 else
    3151 value2 = TRUE;
    3152
    3153 assert(SCIPvarGetNegatedVar(var2) != NULL);
    3154
    3155 /* invert flag, because we want to check var 1 against all negations of the other variables */
    3156 value2 = !value2;
    3157
    3158 /* due to SCIPvarsHaveCommonClique() returns on two same variables that they are in a clique, we need to handle
    3159 * it explicitly
    3160 */
    3161 if( var1 == var2 && value1 == value2 )
    3162 {
    3163 SCIPdebugMsg(scip, "in constraint <%s> the resultant <%s> can be fixed to 0 because two operands are negated of each other\n",
    3164 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
    3165
    3166 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
    3167 *cutoff = *cutoff || infeasible;
    3168 if( fixed )
    3169 ++(*nfixedvars);
    3170
    3171 return SCIP_OKAY;
    3172 }
    3173
    3174 /* due to SCIPvarsHaveCommonClique() returns on two negated variables that they are not in a clique, we need to
    3175 * handle it explicitly
    3176 */
    3177 if( var1 == var2 && value1 != value2 )
    3178 continue;
    3179
    3180 if( !SCIPvarsHaveCommonClique(var1, value1, var2, value2, TRUE) )
    3181 break;
    3182 }
    3183
    3184 if( v2 == -1 )
    3185 {
    3186 SCIP_Bool redundant;
    3187 SCIP_Bool aggregated;
    3188
    3189 SCIPdebugMsg(scip, "In constraint <%s> the operand <%s> is in a negated clique with all other operands, so we can aggregated this operand to the resultant <%s>.\n",
    3190 SCIPconsGetName(cons), SCIPvarGetName(vars[v]), SCIPvarGetName(consdata->resvar));
    3191
    3192 SCIP_CALL( SCIPaggregateVars(scip, consdata->resvar, vars[v], 1.0, -1.0, 0.0,
    3193 &infeasible, &redundant, &aggregated) );
    3194 *cutoff = *cutoff || infeasible;
    3195
    3196 if( aggregated )
    3197 ++(*naggrvars);
    3198
    3199 return SCIP_OKAY;
    3200 }
    3201 }
    3202
    3203 /* case 3 */
    3204 /* check if the resultant and the negations of the operands are in a clique, then we can upgrade this constraint to a
    3205 * set-partitioning constraint
    3206 */
    3207 if( allnegoperandsexist && SCIPconsIsActive(cons) && SCIPconsGetNUpgradeLocks(cons) == 0 )
    3208 {
    3209 SCIP_VAR** newvars;
    3210 SCIP_Bool* negations;
    3211 SCIP_Bool upgrade;
    3212
    3213 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, nvars + 1) );
    3214 SCIP_CALL( SCIPallocBufferArray(scip, &negations, nvars + 1) );
    3215 BMSclearMemoryArray(negations, nvars + 1);
    3216
    3217 var1 = consdata->resvar;
    3218 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negations[nvars]) );
    3219 assert(var1 != NULL);
    3220 assert(SCIPvarGetStatus(var1) != SCIP_VARSTATUS_FIXED);
    3221
    3222 newvars[nvars] = var1;
    3223
    3224 /* get active variables */
    3225 for( v = nvars - 1; v >= 0; --v )
    3226 {
    3227 assert(vars != NULL);
    3228
    3229 var1 = vars[v];
    3230 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negations[v]) );
    3231 assert(var1 != NULL);
    3232 assert(SCIPvarGetStatus(var1) != SCIP_VARSTATUS_FIXED);
    3233
    3234 newvars[v] = var1;
    3235
    3236 /* there should be no variable left that is equal or negated to the resultant */
    3237 assert(newvars[v] != newvars[nvars]);
    3238 }
    3239
    3240 upgrade = TRUE;
    3241
    3242 /* the resultant is in a clique with the negations of all operands, due to this AND-constraint */
    3243 /* only check if the negations of all operands are in a clique */
    3244 for( v = nvars - 1; v >= 0 && upgrade; --v )
    3245 {
    3246 for( v2 = v - 1; v2 >= 0; --v2 )
    3247 {
    3248 /* the resultant need to be in a clique with the negations of all operands */
    3249 if( !SCIPvarsHaveCommonClique(newvars[v], negations[v], newvars[v2], negations[v2], TRUE) )
    3250 {
    3251 upgrade = FALSE;
    3252 break;
    3253 }
    3254 }
    3255 }
    3256
    3257 /* all variables are in a clique, so upgrade thi AND-constraint */
    3258 if( upgrade )
    3259 {
    3260 SCIP_CONS* cliquecons;
    3261 char name[SCIP_MAXSTRLEN];
    3262
    3263 /* get new constraint variables */
    3264 if( negations[nvars] )
    3265 {
    3266 /* negation does not need to be existing, so SCIPvarGetNegatedVar() cannot be called
    3267 * (e.g. resultant = ~x = 1 - x and x = y = newvars[nvars] and negations[nvars] = TRUE,
    3268 * then y does not need to have a negated variable, yet)
    3269 */
    3270 SCIP_CALL( SCIPgetNegatedVar(scip, newvars[nvars], &(newvars[nvars])) );
    3271 }
    3272 assert(newvars[nvars] != NULL);
    3273
    3274 for( v = nvars - 1; v >= 0; --v )
    3275 {
    3276 if( !negations[v] )
    3277 {
    3278 /* negation does not need to be existing, so SCIPvarGetNegatedVar() cannot be called
    3279 * (e.g. vars[v] = ~x = 1 - x and x = y = newvars[v] and negations[v] = TRUE,
    3280 * then y does not need to have a negated variable, yet)
    3281 */
    3282 SCIP_CALL( SCIPgetNegatedVar(scip, newvars[v], &(newvars[v])) );
    3283 }
    3284 assert(newvars[v] != NULL);
    3285 }
    3286
    3287 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clqeq", SCIPconsGetName(cons));
    3288
    3289 SCIP_CALL( SCIPcreateConsSetpart(scip, &cliquecons, name, nvars + 1, newvars,
    3293 SCIPconsIsStickingAtNode(cons)) );
    3294 SCIPdebugMsg(scip, " -> upgrading AND-constraint <%s> with use of clique information to a set-partitioning constraint: \n", SCIPconsGetName(cons));
    3295 SCIPdebugPrintCons(scip, cliquecons, NULL);
    3296 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &cliquecons) );
    3297 ++(*naddconss);
    3298
    3299 /* delete old constraint */
    3300 SCIP_CALL( SCIPdelCons(scip, cons) );
    3301 ++(*ndelconss);
    3302 }
    3303
    3304 SCIPfreeBufferArray(scip, &negations);
    3305 SCIPfreeBufferArray(scip, &newvars);
    3306 }
    3307
    3308 return SCIP_OKAY;
    3309}
    3310
    3311/** gets the key of the given element */
    3312static
    3313SCIP_DECL_HASHGETKEY(hashGetKeyAndcons)
    3314{ /*lint --e{715}*/
    3315 /* the key is the element itself */
    3316 return elem;
    3317}
    3318
    3319/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables */
    3320static
    3321SCIP_DECL_HASHKEYEQ(hashKeyEqAndcons)
    3322{
    3323 SCIP_CONSDATA* consdata1;
    3324 SCIP_CONSDATA* consdata2;
    3325 SCIP_Bool coefsequal;
    3326 int i;
    3327#ifndef NDEBUG
    3328 SCIP* scip;
    3329
    3330 scip = (SCIP*)userptr;
    3331 assert(scip != NULL);
    3332#endif
    3333
    3334 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
    3335 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
    3336
    3337 /* checks trivial case */
    3338 if( consdata1->nvars != consdata2->nvars )
    3339 return FALSE;
    3340
    3341 /* sorts the constraints */
    3342 consdataSort(consdata1);
    3343 consdataSort(consdata2);
    3344 assert(consdata1->sorted);
    3345 assert(consdata2->sorted);
    3346
    3347 coefsequal = TRUE;
    3348
    3349 for( i = 0; i < consdata1->nvars ; ++i )
    3350 {
    3351 /* tests if variables are equal */
    3352 if( consdata1->vars[i] != consdata2->vars[i] )
    3353 {
    3354 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
    3355 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
    3356 coefsequal = FALSE;
    3357 break;
    3358 }
    3359 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
    3360 }
    3361
    3362 return coefsequal;
    3363}
    3364
    3365/** returns the hash value of the key */
    3366static
    3367SCIP_DECL_HASHKEYVAL(hashKeyValAndcons)
    3368{ /*lint --e{715}*/
    3369 SCIP_CONSDATA* consdata;
    3370 int minidx;
    3371 int mididx;
    3372 int maxidx;
    3373
    3374 consdata = SCIPconsGetData((SCIP_CONS*)key);
    3375 assert(consdata != NULL);
    3376 assert(consdata->sorted);
    3377 assert(consdata->nvars > 0);
    3378
    3379 minidx = SCIPvarGetIndex(consdata->vars[0]);
    3380 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
    3381 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
    3382 assert(minidx >= 0 && minidx <= maxidx);
    3383
    3384 return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
    3385}
    3386
    3387/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
    3388 * accordingly; in contrast to removeRedundantConstraints(), it uses a hash table
    3389 */
    3390static
    3392 SCIP* scip, /**< SCIP data structure */
    3393 BMS_BLKMEM* blkmem, /**< block memory */
    3394 SCIP_CONS** conss, /**< constraint set */
    3395 int nconss, /**< number of constraints in constraint set */
    3396 int* firstchange, /**< pointer to store first changed constraint */
    3397 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    3398 int* naggrvars, /**< pointer to count number of aggregated variables */
    3399 int* ndelconss /**< pointer to count number of deleted constraints */
    3400 )
    3401{
    3402 SCIP_HASHTABLE* hashtable;
    3403 int hashtablesize;
    3404 int c;
    3405
    3406 assert(conss != NULL);
    3407 assert(ndelconss != NULL);
    3408
    3409 /* create a hash table for the constraint set */
    3410 hashtablesize = nconss;
    3411 hashtablesize = MAX(hashtablesize, HASHSIZE_ANDCONS);
    3412 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
    3413 hashGetKeyAndcons, hashKeyEqAndcons, hashKeyValAndcons, (void*) scip) );
    3414
    3415 *cutoff = FALSE;
    3416
    3417 /* check all constraints in the given set for redundancy */
    3418 for( c = 0; c < nconss; ++c )
    3419 {
    3420 SCIP_CONS* cons0;
    3421 SCIP_CONS* cons1;
    3422 SCIP_CONSDATA* consdata0;
    3423
    3424 cons0 = conss[c];
    3425
    3426 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
    3427 continue;
    3428
    3429 consdata0 = SCIPconsGetData(cons0);
    3430
    3431 /* sort the constraint */
    3432 consdataSort(consdata0);
    3433 assert(consdata0->sorted);
    3434
    3435 /* get constraint from current hash table with same variables as cons0 */
    3436 cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
    3437
    3438 if( cons1 != NULL )
    3439 {
    3440 SCIP_CONSDATA* consdata1;
    3441 SCIP_Bool redundant;
    3442
    3443 assert(SCIPconsIsActive(cons1));
    3444 assert(!SCIPconsIsModifiable(cons1));
    3445
    3446 consdata1 = SCIPconsGetData(cons1);
    3447
    3448 assert(consdata1 != NULL);
    3449 assert(consdata0->nvars >= 1 && consdata0->nvars == consdata1->nvars);
    3450
    3451 assert(consdata0->sorted && consdata1->sorted);
    3452 assert(consdata0->vars[0] == consdata1->vars[0]);
    3453
    3454 redundant = FALSE;
    3455
    3456 if( consdata0->resvar != consdata1->resvar )
    3457 {
    3458 SCIP_Bool aggregated;
    3459
    3460 assert(SCIPvarCompare(consdata0->resvar, consdata1->resvar) != 0);
    3461
    3462 /* aggregate resultants */
    3463 SCIP_CALL( SCIPaggregateVars(scip, consdata0->resvar, consdata1->resvar, 1.0, -1.0, 0.0,
    3464 cutoff, &redundant, &aggregated) );
    3465 assert(redundant || SCIPdoNotAggr(scip));
    3466
    3467 if( aggregated )
    3468 ++(*naggrvars);
    3469 if( *cutoff )
    3470 goto TERMINATE;
    3471 }
    3472 else
    3473 redundant = TRUE;
    3474
    3475 /* delete consdel */
    3476 if( redundant )
    3477 {
    3478 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
    3479 /* coverity[swapped_arguments] */
    3480 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
    3481
    3482 /* delete constraint */
    3483 SCIP_CALL( SCIPdelCons(scip, cons0) );
    3484 (*ndelconss)++;
    3485 }
    3486
    3487 /* update the first changed constraint to begin the next aggregation round with */
    3488 if( consdata0->changed && SCIPconsGetPos(cons1) < *firstchange )
    3489 *firstchange = SCIPconsGetPos(cons1);
    3490
    3491 assert(SCIPconsIsActive(cons1));
    3492 }
    3493 else
    3494 {
    3495 /* no such constraint in current hash table: insert cons0 into hash table */
    3496 SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
    3497 }
    3498 }
    3499 TERMINATE:
    3500 /* free hash table */
    3501 SCIPhashtableFree(&hashtable);
    3502
    3503 return SCIP_OKAY;
    3504}
    3505
    3506/** helper function to enforce constraints */
    3507static
    3509 SCIP* scip, /**< SCIP data structure */
    3510 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    3511 SCIP_CONS** conss, /**< constraints to process */
    3512 int nconss, /**< number of constraints */
    3513 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
    3514 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
    3515 )
    3516{
    3517 SCIP_CONSHDLRDATA* conshdlrdata;
    3518 SCIP_Bool separated;
    3519 SCIP_Bool violated;
    3520 SCIP_Bool cutoff;
    3521 int i;
    3522
    3523 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3524 assert(conshdlrdata != NULL);
    3525
    3526 *result = SCIP_FEASIBLE;
    3527
    3528 /* method is called only for integral solutions, because the enforcing priority is negative */
    3529 for( i = 0; i < nconss; i++ )
    3530 {
    3531 SCIP_CALL( checkCons(scip, conss[i], sol, FALSE, FALSE, &violated) );
    3532 if( !violated )
    3533 continue;
    3534
    3535 if( !conshdlrdata->enforcecuts )
    3536 {
    3537 *result = SCIP_INFEASIBLE;
    3538 return SCIP_OKAY;
    3539 }
    3540
    3541 SCIP_CALL( separateCons(scip, conss[i], sol, &separated, &cutoff) );
    3542 if( cutoff )
    3543 {
    3544 *result = SCIP_CUTOFF;
    3545 return SCIP_OKAY;
    3546 }
    3547 else if( separated )
    3548 {
    3549 *result = SCIP_SEPARATED;
    3550 }
    3551 else if( *result == SCIP_FEASIBLE ) /* do not change result separated to infeasible */
    3552 {
    3553 *result = SCIP_INFEASIBLE;
    3554 }
    3555 }
    3556
    3557 return SCIP_OKAY;
    3558}
    3559
    3560
    3561/** compares constraint with all prior constraints for possible redundancy or aggregation,
    3562 * and removes or changes constraint accordingly
    3563 */
    3564static
    3566 SCIP* scip, /**< SCIP data structure */
    3567 SCIP_CONS** conss, /**< constraint set */
    3568 int firstchange, /**< first constraint that changed since last pair preprocessing round */
    3569 int chkind, /**< index of constraint to check against all prior indices upto startind */
    3570 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    3571 int* naggrvars, /**< pointer to count number of aggregated variables */
    3572 int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
    3573 int* ndelconss /**< pointer to count number of deleted constraints */
    3574 )
    3575{
    3576 SCIP_CONS* cons0;
    3577 SCIP_CONSDATA* consdata0;
    3578 SCIP_Bool cons0changed;
    3579 int c;
    3580
    3581 assert(conss != NULL);
    3582 assert(firstchange <= chkind);
    3583 assert(cutoff != NULL);
    3584 assert(naggrvars != NULL);
    3585 assert(nbdchgs != NULL);
    3586 assert(ndelconss != NULL);
    3587
    3588 /* get the constraint to be checked against all prior constraints */
    3589 cons0 = conss[chkind];
    3590 assert(SCIPconsIsActive(cons0));
    3591 assert(!SCIPconsIsModifiable(cons0));
    3592
    3593 consdata0 = SCIPconsGetData(cons0);
    3594
    3595 /* sort the constraint */
    3596 consdataSort(consdata0);
    3597
    3598 assert(consdata0->nvars >= 1);
    3599 assert(consdata0->sorted);
    3600
    3601 /* check constraint against all prior constraints */
    3602 cons0changed = consdata0->changed;
    3603
    3604 if( SCIPconsIsActive(cons0) )
    3605 {
    3606 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff); ++c )
    3607 {
    3608 SCIP_CONS* cons1;
    3609 SCIP_CONSDATA* consdata1;
    3610 SCIP_Bool cons0superset;
    3611 SCIP_Bool cons1superset;
    3612 int v0;
    3613 int v1;
    3614
    3615 if( c % 1000 == 0 && SCIPisStopped(scip) )
    3616 break;
    3617
    3618 cons1 = conss[c];
    3619
    3620 /* ignore inactive and modifiable constraints */
    3621 if( !SCIPconsIsActive(cons1) || SCIPconsIsModifiable(cons1) )
    3622 continue;
    3623
    3624 consdata1 = SCIPconsGetData(cons1);
    3625 assert(consdata1 != NULL);
    3626
    3627#ifdef SCIP_DISABLED_CODE
    3628 SCIPdebugMsg(scip, "preprocess AND-constraint pair <%s>[chg:%d] and <%s>[chg:%d]\n",
    3629 SCIPconsGetName(cons0), cons0changed, SCIPconsGetName(cons1), consdata1->changed);
    3630#endif
    3631
    3632 /* if both constraints were not changed since last round, we can ignore the pair */
    3633 if( !cons0changed && !consdata1->changed )
    3634 continue;
    3635
    3636 assert(consdata1->nvars >= 1);
    3637
    3638 /* sort the constraint */
    3639 consdataSort(consdata1);
    3640 assert(consdata1->sorted);
    3641
    3642 /* check consdata0 against consdata1:
    3643 * - if they consist of the same operands, the resultants can be aggregated
    3644 * - if one operand list is a subset of the other, add implication r0 = 1 -> r1 = 1, or r1 = 1 -> r0 = 1
    3645 */
    3646 v0 = 0;
    3647 v1 = 0;
    3648 cons0superset = TRUE;
    3649 cons1superset = TRUE;
    3650 while( (v0 < consdata0->nvars || v1 < consdata1->nvars) && (cons0superset || cons1superset) )
    3651 {
    3652 int varcmp;
    3653
    3654 /* test, if variable appears in only one or in both constraints */
    3655 if( v0 < consdata0->nvars && v1 < consdata1->nvars )
    3656 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
    3657 else if( v0 < consdata0->nvars )
    3658 varcmp = -1;
    3659 else
    3660 varcmp = +1;
    3661
    3662 switch( varcmp )
    3663 {
    3664 case -1:
    3665 /* variable doesn't appear in consdata1 */
    3666 cons1superset = FALSE;
    3667 v0++;
    3668 break;
    3669
    3670 case +1:
    3671 /* variable doesn't appear in consdata0 */
    3672 cons0superset = FALSE;
    3673 v1++;
    3674 break;
    3675
    3676 case 0:
    3677 /* variable appears in both constraints */
    3678 v0++;
    3679 v1++;
    3680 break;
    3681
    3682 default:
    3683 SCIPerrorMessage("invalid comparison result\n");
    3684 SCIPABORT();
    3685 return SCIP_INVALIDDATA; /*lint !e527*/
    3686 }
    3687 }
    3688
    3689 /* check for equivalence and domination */
    3690 if( cons0superset && cons1superset )
    3691 {
    3692 SCIP_Bool infeasible;
    3693 SCIP_Bool redundant;
    3694 SCIP_Bool aggregated;
    3695
    3696 /* constraints are equivalent */
    3697 SCIPdebugMsg(scip, "equivalent AND-constraints <%s> and <%s>: aggregate resultants <%s> == <%s>\n",
    3698 SCIPconsGetName(cons0), SCIPconsGetName(cons1), SCIPvarGetName(consdata0->resvar),
    3699 SCIPvarGetName(consdata1->resvar));
    3700
    3701 /* aggregate resultants */
    3702 SCIP_CALL( SCIPaggregateVars(scip, consdata0->resvar, consdata1->resvar, 1.0, -1.0, 0.0,
    3703 &infeasible, &redundant, &aggregated) );
    3704 assert(redundant || SCIPdoNotAggr(scip));
    3705
    3706 if( aggregated )
    3707 {
    3708 assert(redundant);
    3709 (*naggrvars)++;
    3710 }
    3711
    3712 if( redundant )
    3713 {
    3714 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
    3715 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
    3716
    3717 /* delete constraint */
    3718 SCIP_CALL( SCIPdelCons(scip, cons1) );
    3719 (*ndelconss)++;
    3720 }
    3721
    3722 *cutoff = *cutoff || infeasible;
    3723 }
    3724 else if( cons0superset )
    3725 {
    3726 SCIP_Bool infeasible;
    3727 int nboundchgs;
    3728
    3729 /* the conjunction of cons0 is a superset of the conjunction of cons1 */
    3730 SCIPdebugMsg(scip, "AND-constraint <%s> is superset of <%s>: add implication <%s> = 1 -> <%s> = 1\n",
    3731 SCIPconsGetName(cons0), SCIPconsGetName(cons1), SCIPvarGetName(consdata0->resvar),
    3732 SCIPvarGetName(consdata1->resvar));
    3733
    3734 /* add implication */
    3735 SCIP_CALL( SCIPaddVarImplication(scip, consdata0->resvar, TRUE, consdata1->resvar, SCIP_BOUNDTYPE_LOWER, 1.0,
    3736 &infeasible, &nboundchgs) );
    3737 *cutoff = *cutoff || infeasible;
    3738 (*nbdchgs) += nboundchgs;
    3739 }
    3740 else if( cons1superset )
    3741 {
    3742 SCIP_Bool infeasible;
    3743 int nboundchgs;
    3744
    3745 /* the conjunction of cons1 is a superset of the conjunction of cons0 */
    3746 SCIPdebugMsg(scip, "AND-constraint <%s> is superset of <%s>: add implication <%s> = 1 -> <%s> = 1\n",
    3747 SCIPconsGetName(cons1), SCIPconsGetName(cons0), SCIPvarGetName(consdata1->resvar),
    3748 SCIPvarGetName(consdata0->resvar));
    3749
    3750 /* add implication */
    3751 SCIP_CALL( SCIPaddVarImplication(scip, consdata1->resvar, TRUE, consdata0->resvar, SCIP_BOUNDTYPE_LOWER, 1.0,
    3752 &infeasible, &nboundchgs) );
    3753 *cutoff = *cutoff || infeasible;
    3754 (*nbdchgs) += nboundchgs;
    3755 }
    3756 }
    3757 }
    3758 consdata0->changed = FALSE;
    3759
    3760 return SCIP_OKAY;
    3761}
    3762
    3763/** adds symmetry information of constraint to a symmetry detection graph */
    3764static
    3766 SCIP* scip, /**< SCIP pointer */
    3767 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
    3768 SCIP_CONS* cons, /**< constraint */
    3769 SYM_GRAPH* graph, /**< symmetry detection graph */
    3770 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
    3771 )
    3772{
    3773 SCIP_CONSDATA* consdata;
    3774 SCIP_VAR** andvars;
    3775 SCIP_VAR** vars;
    3776 SCIP_Real* vals;
    3777 SCIP_Real constant;
    3778 int consnodeidx;
    3779 int andnodeidx;
    3780 int nlocvars;
    3781 int i;
    3782
    3783 assert(scip != NULL);
    3784 assert(cons != NULL);
    3785 assert(graph != NULL);
    3786 assert(success != NULL);
    3787
    3788 consdata = SCIPconsGetData(cons);
    3789 assert(consdata != NULL);
    3790
    3791 /* create arrays to store active representation of variables */
    3792 nlocvars = 1;
    3793 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nlocvars) );
    3794 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nlocvars) );
    3795
    3796 /* add constraint node */
    3797 SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, 0.0, 0.0, &consnodeidx) );
    3798
    3799 /* add resultant to symmetry detection graph */
    3800 assert(consdata->resvar != NULL);
    3801 vars[0] = consdata->resvar;
    3802 vals[0] = 1.0;
    3803 constant = 0.0;
    3804 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
    3805 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, consnodeidx, vars, vals, nlocvars, constant) );
    3806
    3807 /* add node modeling the AND-part and connect it with constraint node */
    3808 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int)SYM_CONSOPTYPE_AND, &andnodeidx) );
    3809 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, andnodeidx, FALSE, 0.0) );
    3810
    3811 /* add variables */
    3812 andvars = consdata->vars;
    3813 for( i = 0; i < consdata->nvars; ++i )
    3814 {
    3815 assert(andvars[i] != NULL);
    3816 vars[0] = andvars[i];
    3817 vals[0] = 1.0;
    3818 constant = 0.0;
    3819 nlocvars = 1;
    3820 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
    3821 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, andnodeidx, vars, vals, nlocvars, constant) );
    3822 }
    3823
    3824 SCIPfreeBufferArray(scip, &vals);
    3825 SCIPfreeBufferArray(scip, &vars);
    3826
    3827 *success = TRUE;
    3828
    3829 return SCIP_OKAY;
    3830}
    3831
    3832/*
    3833 * Callback methods of constraint handler
    3834 */
    3835
    3836/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    3837static
    3839{ /*lint --e{715}*/
    3840 assert(scip != NULL);
    3841 assert(conshdlr != NULL);
    3842
    3844
    3845 /* call inclusion method of constraint handler */
    3847
    3848 *valid = TRUE;
    3849
    3850 return SCIP_OKAY;
    3851}
    3852
    3853/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
    3854static
    3856{ /*lint --e{715}*/
    3857 SCIP_CONSHDLRDATA* conshdlrdata;
    3858
    3859 /* free constraint handler data */
    3860 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3861 assert(conshdlrdata != NULL);
    3862
    3863 conshdlrdataFree(scip, &conshdlrdata);
    3864
    3865 SCIPconshdlrSetData(conshdlr, NULL);
    3866
    3867 return SCIP_OKAY;
    3868}
    3869
    3870
    3871/** presolving initialization method of constraint handler (called when presolving is about to begin) */
    3872static
    3874{ /*lint --e{715}*/
    3875 SCIP_CONSHDLRDATA* conshdlrdata;
    3876
    3877 assert( scip != NULL );
    3878 assert( conshdlr != NULL );
    3879 assert( nconss == 0 || conss != NULL );
    3880
    3881 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3882 assert(conshdlrdata != NULL);
    3883
    3884 if( conshdlrdata->linearize )
    3885 {
    3886 /* linearize all AND-constraints and remove the AND-constraints */
    3887 SCIP_CONS* newcons;
    3888 SCIP_CONS* cons;
    3889 SCIP_CONSDATA* consdata;
    3890 char consname[SCIP_MAXSTRLEN];
    3891
    3892 SCIP_VAR** vars;
    3893 SCIP_Real* vals;
    3894
    3895 int nvars;
    3896 int c, v;
    3897
    3898 /* allocate buffer array */
    3899 SCIP_CALL( SCIPallocBufferArray(scip, &vars, 2) );
    3900 SCIP_CALL( SCIPallocBufferArray(scip, &vals, 2) );
    3901
    3902 for( c = 0; c < nconss; ++c )
    3903 {
    3904 cons = conss[c];
    3905 assert( cons != NULL );
    3906
    3907 /* only added constraints can be upgraded */
    3908 if( !SCIPconsIsAdded(cons) || SCIPconsGetNUpgradeLocks(cons) >= 1 )
    3909 continue;
    3910
    3911 consdata = SCIPconsGetData(cons);
    3912 assert( consdata != NULL );
    3913 assert( consdata->resvar != NULL );
    3914
    3915 nvars = consdata->nvars;
    3916
    3917 if( !conshdlrdata->aggrlinearization )
    3918 {
    3919 vars[0] = consdata->resvar;
    3920 vals[0] = 1.0;
    3921 vals[1] = -1.0;
    3922
    3923 /* create operator linear constraints */
    3924 for( v = 0; v < nvars; ++v )
    3925 {
    3926 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), v);
    3927 vars[1] = consdata->vars[v];
    3928
    3929 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, 2, vars, vals, -SCIPinfinity(scip), 0.0,
    3933 SCIPconsIsStickingAtNode(cons)) );
    3934
    3935 /* add constraint */
    3936 SCIP_CALL( SCIPaddCons(scip, newcons) );
    3937 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    3938 }
    3939 }
    3940
    3941 /* reallocate buffer array */
    3942 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, nvars + 1) );
    3943 SCIP_CALL( SCIPreallocBufferArray(scip, &vals, nvars + 1) );
    3944
    3945 for( v = 0; v < nvars; ++v )
    3946 {
    3947 vars[v] = consdata->vars[v];
    3948 vals[v] = -1.0;
    3949 }
    3950
    3951 vars[nvars] = consdata->resvar;
    3952
    3953 if( conshdlrdata->aggrlinearization )
    3954 {
    3955 /* create additional linear constraint */
    3956 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_operators", SCIPconsGetName(cons));
    3957
    3958 vals[nvars] = (SCIP_Real) nvars;
    3959
    3960 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, nvars + 1, vars, vals, -SCIPinfinity(scip), 0.0,
    3964 SCIPconsIsStickingAtNode(cons)) );
    3965
    3966 /* add constraint */
    3967 SCIP_CALL( SCIPaddCons(scip, newcons) );
    3968 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    3969 }
    3970
    3971 /* create additional linear constraint */
    3972 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_add", SCIPconsGetName(cons));
    3973
    3974 vals[nvars] = 1.0;
    3975
    3976 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, nvars + 1, vars, vals, -nvars + 1.0, SCIPinfinity(scip),
    3980 SCIPconsIsStickingAtNode(cons)) );
    3981
    3982 /* add constraint */
    3983 SCIP_CALL( SCIPaddCons(scip, newcons) );
    3984 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    3985
    3986 /* delete constraint */
    3987 SCIP_CALL( SCIPdelCons(scip, cons) );
    3988 }
    3989
    3990 /* free buffer array */
    3991 SCIPfreeBufferArray(scip, &vars);
    3992 SCIPfreeBufferArray(scip, &vals);
    3993 }
    3994
    3995 return SCIP_OKAY;
    3996}
    3997
    3998
    3999#ifdef GMLGATEPRINTING
    4000
    4001/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
    4002static
    4003SCIP_DECL_CONSEXITPRE(consExitpreAnd)
    4004{ /*lint --e{715}*/
    4005 SCIP_HASHMAP* hashmap;
    4006 FILE* gmlfile;
    4007 char fname[SCIP_MAXSTRLEN];
    4008 SCIP_CONS* cons;
    4009 SCIP_CONSDATA* consdata;
    4010 SCIP_VAR** activeconsvars;
    4011 SCIP_VAR* activevar;
    4012 int* varnodeids;
    4013 SCIP_VAR** vars;
    4014 int nvars;
    4015 int nbinvars;
    4016 int nintvars;
    4017 int nimplvars;
    4018 int ncontvars;
    4019 int v;
    4020 int c;
    4021 int resid;
    4022 int varid;
    4023 int id = 1;
    4024
    4025 /* no AND-constraints available */
    4026 if( nconss == 0 )
    4027 return SCIP_OKAY;
    4028
    4029 nvars = SCIPgetNVars(scip);
    4030
    4031 /* no variables left anymore */
    4032 if( nvars == 0 )
    4033 return SCIP_OKAY;
    4034
    4035 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    4036 SCIP_CALL( SCIPallocBufferArray(scip, &varnodeids, nvars) );
    4037 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, &nimplvars, &ncontvars) );
    4038
    4039 /* open gml file */
    4040 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "and-gates%p.gml", scip);
    4041 gmlfile = fopen(fname, "w");
    4042
    4043 if( gmlfile == NULL )
    4044 {
    4045 SCIPerrorMessage("cannot open graph file <%s>\n", fname);
    4046 SCIPABORT();
    4047 return SCIP_WRITEERROR; /*lint !e527*/
    4048 }
    4049
    4050 /* create the variable mapping hash map */
    4051 SCIP_CALL_FINALLY( SCIPhashmapCreate(&hashmap, SCIPblkmem(scip), nvars), fclose(gmlfile) );
    4052
    4053 /* write starting of gml file */
    4054 SCIPgmlWriteOpening(gmlfile, TRUE);
    4055
    4056 /* walk over all AND-constraints */
    4057 for( c = nconss - 1; c >= 0; --c )
    4058 {
    4059 cons = conss[c];
    4060
    4061 /* only handle active constraints */
    4062 if( !SCIPconsIsActive(cons) )
    4063 continue;
    4064
    4065 consdata = SCIPconsGetData(cons);
    4066 assert(consdata != NULL);
    4067
    4068 /* only handle constraints which have operands */
    4069 if( consdata->nvars == 0 )
    4070 continue;
    4071
    4072 assert(consdata->vars != NULL);
    4073 assert(consdata->resvar != NULL);
    4074
    4075 /* get active variable of resultant */
    4076 activevar = SCIPvarGetProbvar(consdata->resvar);
    4077
    4078 /* check if we already found this variables */
    4079 resid = SCIPhashmapGetImageInt(hashmap, activevar);
    4080 assert(resid >= 0);
    4081
    4082 if( resid == 0 )
    4083 {
    4084 resid = id;
    4085 ++id;
    4086 SCIP_CALL( SCIPhashmapInsertInt(hashmap, (void*)activevar, resid) );
    4087
    4088 /* write new gml node for new resultant */
    4089 SCIPgmlWriteNode(gmlfile, resid, SCIPvarGetName(activevar), NULL, NULL, NULL);
    4090 }
    4091
    4092 /* copy operands to get problem variables for */
    4093 SCIP_CALL( SCIPduplicateBufferArray(scip, &activeconsvars, consdata->vars, consdata->nvars) );
    4094
    4095 /* get problem variables of operands */
    4096 SCIPvarsGetProbvar(activeconsvars, consdata->nvars);
    4097
    4098 for( v = consdata->nvars - 1; v >= 0; --v )
    4099 {
    4100 /* check if we already found this variables */
    4101 varid = SCIPhashmapGetImageInt(hashmap, activeconsvars[v]);
    4102 if( varid == 0 )
    4103 {
    4104 varid = id;
    4105 ++id;
    4106 SCIP_CALL( SCIPhashmapInsertInt(hashmap, (void*)activeconsvars[v], varid) );
    4107
    4108 /* write new gml node for new operand */
    4109 SCIPgmlWriteNode(gmlfile, varid, SCIPvarGetName(activeconsvars[v]), NULL, NULL, NULL);
    4110 }
    4111 /* write gml arc between resultant and operand */
    4112 SCIPgmlWriteArc(gmlfile, resid, varid, NULL, NULL);
    4113 }
    4114
    4115 /* free temporary memory for active constraint variables */
    4116 SCIPfreeBufferArray(scip, &activeconsvars);
    4117 }
    4118
    4119 /* write all remaining variables as nodes */
    4120#ifdef SCIP_DISABLED_CODE
    4121 for( v = nvars - 1; v >= 0; --v )
    4122 {
    4123 activevar = SCIPvarGetProbvar(vars[v]);
    4124
    4125 varid = SCIPhashmapGetImageInt(hashmap, activevar);
    4126 assert(varid >= 0);
    4127
    4128 if( varid == 0 )
    4129 {
    4130 varid = id;
    4131 ++id;
    4132 SCIP_CALL( SCIPhashmapInsertInt(hashmap, (void*)activeconsvars[v], varid) );
    4133
    4134 /* write new gml node for new operand */
    4135 SCIPgmlWriteNode(gmlfile, varid, SCIPvarGetName(activevar), NULL, NULL, NULL);
    4136 }
    4137 }
    4138#endif
    4139
    4140 /* free the variable mapping hash map */
    4141 SCIPhashmapFree(&hashmap);
    4142
    4143 SCIPgmlWriteClosing(gmlfile);
    4144
    4145 fclose(gmlfile);
    4146
    4147 SCIPfreeBufferArray(scip, &varnodeids);
    4148 SCIPfreeBufferArray(scip, &vars);
    4149
    4150 return SCIP_OKAY;
    4151}
    4152#endif
    4153
    4154/** solving process initialization method of constraint handler */
    4155static
    4157{ /*lint --e{715}*/
    4158 /* add nlrow representation to NLP, if NLP had been constructed */
    4160 {
    4161 int c;
    4162 for( c = 0; c < nconss; ++c )
    4163 {
    4164 SCIP_CALL( addNlrow(scip, conss[c]) );
    4165 }
    4166 }
    4167
    4168 return SCIP_OKAY;
    4169}
    4170
    4171/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
    4172static
    4174{ /*lint --e{715}*/
    4175 SCIP_CONSDATA* consdata;
    4176 int c;
    4177
    4178 /* release and free the rows and nlrow of all constraints */
    4179 for( c = 0; c < nconss; ++c )
    4180 {
    4181 consdata = SCIPconsGetData(conss[c]);
    4182 assert(consdata != NULL);
    4183
    4184 SCIP_CALL( consdataFreeRows(scip, consdata) );
    4185
    4186 if( consdata->nlrow != NULL )
    4187 {
    4188 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
    4189 }
    4190 }
    4191
    4192 return SCIP_OKAY;
    4193}
    4194
    4195
    4196/** frees specific constraint data */
    4197static
    4199{ /*lint --e{715}*/
    4200 SCIP_CONSHDLRDATA* conshdlrdata;
    4201
    4202 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4203 assert(conshdlrdata != NULL);
    4204
    4205 SCIP_CALL( consdataFree(scip, consdata, conshdlrdata->eventhdlr) );
    4206
    4207 return SCIP_OKAY;
    4208}
    4209
    4210
    4211/** transforms constraint data into data belonging to the transformed problem */
    4212static
    4214{ /*lint --e{715}*/
    4215 SCIP_CONSHDLRDATA* conshdlrdata;
    4216 SCIP_CONSDATA* sourcedata;
    4217 SCIP_CONSDATA* targetdata;
    4218
    4219 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4220 assert(conshdlrdata != NULL);
    4221
    4222 sourcedata = SCIPconsGetData(sourcecons);
    4223 assert(sourcedata != NULL);
    4224
    4225 /* create target constraint data */
    4226 SCIP_CALL( consdataCreate(scip, &targetdata, conshdlrdata->eventhdlr,
    4227 sourcedata->nvars, sourcedata->vars, sourcedata->resvar) );
    4228
    4229 /* create target constraint */
    4230 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
    4231 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
    4232 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
    4233 SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons),
    4234 SCIPconsIsStickingAtNode(sourcecons)) );
    4235
    4236 return SCIP_OKAY;
    4237}
    4238
    4239
    4240/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
    4241static
    4243{ /*lint --e{715}*/
    4244 int i;
    4245
    4246 *infeasible = FALSE;
    4247
    4248 for( i = 0; i < nconss && !(*infeasible); i++ )
    4249 {
    4250 assert(SCIPconsIsInitial(conss[i]));
    4251 SCIP_CALL( addRelaxation(scip, conss[i], infeasible) );
    4252 }
    4253
    4254 return SCIP_OKAY;
    4255}
    4256
    4257
    4258/** separation method of constraint handler for LP solutions */
    4259static
    4261{ /*lint --e{715}*/
    4262 SCIP_Bool separated;
    4263 SCIP_Bool cutoff;
    4264 int c;
    4265
    4266 *result = SCIP_DIDNOTFIND;
    4267
    4268 /* separate all useful constraints */
    4269 for( c = 0; c < nusefulconss; ++c )
    4270 {
    4271 SCIP_CALL( separateCons(scip, conss[c], NULL, &separated, &cutoff) );
    4272 if ( cutoff )
    4273 *result = SCIP_CUTOFF;
    4274 else if ( separated )
    4275 *result = SCIP_SEPARATED;
    4276 }
    4277
    4278 /* combine constraints to get more cuts */
    4279 /**@todo combine constraints to get further cuts */
    4280
    4281 return SCIP_OKAY;
    4282}
    4283
    4284
    4285/** separation method of constraint handler for arbitrary primal solutions */
    4286static
    4288{ /*lint --e{715}*/
    4289 SCIP_Bool separated;
    4290 SCIP_Bool cutoff;
    4291 int c;
    4292
    4293 *result = SCIP_DIDNOTFIND;
    4294
    4295 /* separate all useful constraints */
    4296 for( c = 0; c < nusefulconss; ++c )
    4297 {
    4298 SCIP_CALL( separateCons(scip, conss[c], sol, &separated, &cutoff) );
    4299 if ( cutoff )
    4300 *result = SCIP_CUTOFF;
    4301 else if ( separated )
    4302 *result = SCIP_SEPARATED;
    4303 }
    4304
    4305 /* combine constraints to get more cuts */
    4306 /**@todo combine constraints to get further cuts */
    4307
    4308 return SCIP_OKAY;
    4309}
    4310
    4311
    4312/** constraint enforcing method of constraint handler for LP solutions */
    4313static
    4315{ /*lint --e{715}*/
    4316 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, NULL, result) );
    4317
    4318 return SCIP_OKAY;
    4319}
    4320
    4321/** constraint enforcing method of constraint handler for relaxation solutions */
    4322static
    4324{ /*lint --e{715}*/
    4325 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, sol, result) );
    4326
    4327 return SCIP_OKAY;
    4328}
    4329
    4330/** constraint enforcing method of constraint handler for pseudo solutions */
    4331static
    4333{ /*lint --e{715}*/
    4334 SCIP_Bool violated;
    4335 int i;
    4336
    4337 /* method is called only for integral solutions, because the enforcing priority is negative */
    4338 for( i = 0; i < nconss; i++ )
    4339 {
    4340 SCIP_CALL( checkCons(scip, conss[i], NULL, TRUE, FALSE, &violated) );
    4341 if( violated )
    4342 {
    4343 *result = SCIP_INFEASIBLE;
    4344 return SCIP_OKAY;
    4345 }
    4346 }
    4347 *result = SCIP_FEASIBLE;
    4348
    4349 return SCIP_OKAY;
    4350}
    4351
    4352/** feasibility check method of constraint handler and */
    4353static
    4355{ /*lint --e{715}*/
    4356 SCIP_Bool violated;
    4357 int i;
    4358
    4359 *result = SCIP_FEASIBLE;
    4360
    4361 for( i = 0; i < nconss && ( *result == SCIP_FEASIBLE || completely ); ++i )
    4362 {
    4363 SCIP_CALL( checkCons(scip, conss[i], sol, checklprows, printreason, &violated) );
    4364 if( violated )
    4365 *result = SCIP_INFEASIBLE;
    4366 }
    4367
    4368 return SCIP_OKAY;
    4369}
    4370
    4371/** domain propagation method of constraint handler */
    4372static
    4374{ /*lint --e{715}*/
    4375 SCIP_CONSHDLRDATA* conshdlrdata;
    4376 SCIP_Bool cutoff;
    4377 int nfixedvars;
    4378 int nupgdconss;
    4379 int c;
    4380
    4381 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4382 assert(conshdlrdata != NULL);
    4383
    4384 cutoff = FALSE;
    4385 nfixedvars = 0;
    4386 nupgdconss = 0;
    4387
    4388 /* propagate all useful constraints */
    4389 for( c = 0; c < nusefulconss && !cutoff; ++c )
    4390 {
    4391 SCIP_CALL( propagateCons(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &nfixedvars, &nupgdconss) );
    4392 }
    4393
    4394 /* return the correct result */
    4395 if( cutoff )
    4396 *result = SCIP_CUTOFF;
    4397 else if( nfixedvars > 0 || nupgdconss > 0 )
    4398 *result = SCIP_REDUCEDDOM;
    4399 else
    4400 *result = SCIP_DIDNOTFIND;
    4401
    4402 return SCIP_OKAY;
    4403}
    4404
    4405
    4406/** presolving method of constraint handler */
    4407static
    4409{ /*lint --e{715}*/
    4410 SCIP_CONSHDLRDATA* conshdlrdata;
    4411 SCIP_CONS* cons;
    4412 SCIP_CONSDATA* consdata;
    4413 unsigned char* entries;
    4414 SCIP_Bool cutoff;
    4415 int oldnfixedvars;
    4416 int oldnaggrvars;
    4417 int oldnchgbds;
    4418 int oldndelconss;
    4419 int oldnupgdconss;
    4420 int firstchange;
    4421 int nentries;
    4422 int c;
    4423
    4424 assert(result != NULL);
    4425
    4426 oldnfixedvars = *nfixedvars;
    4427 oldnaggrvars = *naggrvars;
    4428 oldnchgbds = *nchgbds;
    4429 oldndelconss = *ndelconss;
    4430 oldnupgdconss = *nupgdconss;
    4431
    4432 nentries = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
    4433 SCIP_CALL( SCIPallocBufferArray(scip, &entries, nentries) );
    4434
    4435 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4436 assert(conshdlrdata != NULL);
    4437
    4438 /* process constraints */
    4439 cutoff = FALSE;
    4440 firstchange = INT_MAX;
    4441 for( c = 0; c < nconss && !cutoff && (c % 1000 != 0 || !SCIPisStopped(scip)); ++c )
    4442 {
    4443 cons = conss[c];
    4444 assert(cons != NULL);
    4445 consdata = SCIPconsGetData(cons);
    4446 assert(consdata != NULL);
    4447
    4448 /* force presolving the constraint in the initial round */
    4449 if( nrounds == 0 )
    4450 consdata->propagated = FALSE;
    4451
    4452 /* remember the first changed constraint to begin the next aggregation round with */
    4453 if( firstchange == INT_MAX && consdata->changed )
    4454 firstchange = c;
    4455
    4456 /* propagate constraint */
    4457 SCIP_CALL( propagateCons(scip, cons, conshdlrdata->eventhdlr, &cutoff, nfixedvars, nupgdconss) );
    4458
    4459 /* remove all variables that are fixed to one; merge multiple entries of the same variable;
    4460 * fix resultant to zero if a pair of negated variables is contained in the operand variables
    4461 */
    4462 if( !cutoff && !SCIPconsIsDeleted(cons) )
    4463 {
    4464 SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, nchgcoefs) );
    4465
    4466 /* merge multiple occurances of variables or variables with their negated variables */
    4467 SCIP_CALL( mergeMultiples(scip, cons, conshdlrdata->eventhdlr, &entries, &nentries, nfixedvars, nchgcoefs, ndelconss) );
    4468 }
    4469
    4470 if( !cutoff && !SCIPconsIsDeleted(cons) && !SCIPconsIsModifiable(cons) )
    4471 {
    4472 assert(consdata->nvars >= 1); /* otherwise, propagateCons() has deleted the constraint */
    4473
    4474 /* if only one variable is left, the resultant has to be equal to this single variable */
    4475 if( consdata->nvars == 1 )
    4476 {
    4477 SCIP_Bool redundant;
    4478 SCIP_Bool aggregated;
    4479
    4480 SCIPdebugMsg(scip, "AND-constraint <%s> has only one variable not fixed to 1.0\n", SCIPconsGetName(cons));
    4481
    4482 assert(consdata->vars != NULL);
    4483 assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(consdata->vars[0]), 0.0));
    4484 assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(consdata->vars[0]), 1.0));
    4485
    4486 /* aggregate variables: resultant - operand == 0 */
    4487 SCIP_CALL( SCIPaggregateVars(scip, consdata->resvar, consdata->vars[0], 1.0, -1.0, 0.0,
    4488 &cutoff, &redundant, &aggregated) );
    4489 assert(redundant || SCIPdoNotAggr(scip));
    4490
    4491 if( aggregated )
    4492 {
    4493 assert(redundant);
    4494 (*naggrvars)++;
    4495 }
    4496
    4497 if( redundant )
    4498 {
    4499 /* delete constraint */
    4500 SCIP_CALL( SCIPdelCons(scip, cons) );
    4501 (*ndelconss)++;
    4502 }
    4503 }
    4504 else if( !consdata->impladded )
    4505 {
    4506 int i;
    4507
    4508 /* add implications: resultant == 1 -> all operands == 1 */
    4509 for( i = 0; i < consdata->nvars && !cutoff; ++i )
    4510 {
    4511 int nimplbdchgs;
    4512
    4513 SCIP_CALL( SCIPaddVarImplication(scip, consdata->resvar, TRUE, consdata->vars[i],
    4514 SCIP_BOUNDTYPE_LOWER, 1.0, &cutoff, &nimplbdchgs) );
    4515 (*nchgbds) += nimplbdchgs;
    4516 }
    4517 consdata->impladded = TRUE;
    4518 }
    4519
    4520 /* if in r = x and y, the resultant is fixed to zero, add implication x = 1 -> y = 0 */
    4521 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 2 && !consdata->opimpladded
    4522 && SCIPvarGetUbGlobal(consdata->resvar) < 0.5 )
    4523 {
    4524 int nimplbdchgs;
    4525
    4526 SCIP_CALL( SCIPaddVarImplication(scip, consdata->vars[0], TRUE, consdata->vars[1],
    4527 SCIP_BOUNDTYPE_UPPER, 0.0, &cutoff, &nimplbdchgs) );
    4528 (*nchgbds) += nimplbdchgs;
    4529 consdata->opimpladded = TRUE;
    4530 }
    4531 }
    4532 }
    4533
    4534 /* perform dual presolving on AND-constraints */
    4535 if( conshdlrdata->dualpresolving && !cutoff && !SCIPisStopped(scip) && SCIPallowStrongDualReds(scip))
    4536 {
    4537 SCIP_CALL( dualPresolve(scip, conss, nconss, conshdlrdata->eventhdlr, &entries, &nentries, &cutoff, nfixedvars, naggrvars, nchgcoefs, ndelconss, nupgdconss, naddconss) );
    4538 }
    4539
    4540 /* check for cliques inside the AND constraint */
    4541 if( (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
    4542 {
    4543 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
    4544 {
    4545 cons = conss[c];
    4546 assert(cons != NULL);
    4547
    4548 if( !SCIPconsIsActive(cons) )
    4549 continue;
    4550
    4551 /* cliquePresolve() may aggregate variables which need to be removed from other constraints, we also need
    4552 * to make sure that we remove fixed variables by calling propagateCons() to make sure that applyFixing()
    4553 * and mergeMultiples() work
    4554 */
    4555 SCIP_CALL( propagateCons(scip, cons, conshdlrdata->eventhdlr, &cutoff, nfixedvars, nupgdconss) );
    4556
    4557 if( !cutoff && !SCIPconsIsDeleted(cons) )
    4558 {
    4559 /* remove all variables that are fixed to one; merge multiple entries of the same variable;
    4560 * fix resultant to zero if a pair of negated variables is contained in the operand variables
    4561 */
    4562 SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, nchgcoefs) );
    4563 SCIP_CALL( mergeMultiples(scip, cons, conshdlrdata->eventhdlr, &entries, &nentries, nfixedvars, nchgcoefs, ndelconss) );
    4564
    4565 /* check if at least two operands are in one clique */
    4566 SCIP_CALL( cliquePresolve(scip, cons, conshdlrdata->eventhdlr, &cutoff, nfixedvars, naggrvars, nchgcoefs, ndelconss, naddconss) );
    4567 }
    4568 }
    4569 }
    4570
    4571 /* process pairs of constraints: check them for equal operands in order to aggregate resultants;
    4572 * only apply this expensive procedure, if the single constraint preprocessing did not find any reductions
    4573 * (otherwise, we delay the presolving to be called again next time)
    4574 */
    4575 if( !cutoff && conshdlrdata->presolusehashing && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
    4576 {
    4577 if( *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars )
    4578 {
    4579 if( firstchange < nconss )
    4580 {
    4581 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
    4582 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff, naggrvars, ndelconss) );
    4583 oldnaggrvars = *naggrvars;
    4584 }
    4585 }
    4586 }
    4587
    4588 if( !cutoff && conshdlrdata->presolpairwise && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
    4589 {
    4590 if( *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars )
    4591 {
    4592 SCIP_Longint npaircomparisons;
    4593 npaircomparisons = 0;
    4594 oldndelconss = *ndelconss;
    4595
    4596 for( c = firstchange; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
    4597 {
    4598 if( SCIPconsIsActive(conss[c]) && !SCIPconsIsModifiable(conss[c]) )
    4599 {
    4600 npaircomparisons += ((SCIPconsGetData(conss[c])->changed) ? (SCIP_Longint) c : ((SCIP_Longint) c - (SCIP_Longint) firstchange));
    4601
    4602 SCIP_CALL( preprocessConstraintPairs(scip, conss, firstchange, c, &cutoff, naggrvars, nchgbds,
    4603 ndelconss) );
    4604
    4605 if( npaircomparisons > NMINCOMPARISONS )
    4606 {
    4607 if( ((*ndelconss - oldndelconss) + (*naggrvars - oldnaggrvars) + (*nchgbds - oldnchgbds)/2.0) / ((SCIP_Real) npaircomparisons) < MINGAINPERNMINCOMPARISONS )
    4608 break;
    4609 oldndelconss = *ndelconss;
    4610 oldnaggrvars = *naggrvars;
    4611 oldnchgbds = *nchgbds;
    4612
    4613 npaircomparisons = 0;
    4614 }
    4615 }
    4616 }
    4617 }
    4618 }
    4619
    4620 SCIPfreeBufferArray(scip, &entries);
    4621
    4622 /* return the correct result code */
    4623 if( cutoff )
    4624 *result = SCIP_CUTOFF;
    4625 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds
    4626 || *ndelconss > oldndelconss || *nupgdconss > oldnupgdconss )
    4627 *result = SCIP_SUCCESS;
    4628 else
    4629 *result = SCIP_DIDNOTFIND;
    4630
    4631 return SCIP_OKAY;
    4632}
    4633
    4634
    4635/** propagation conflict resolving method of constraint handler */
    4636static
    4638{ /*lint --e{715}*/
    4639 SCIP_CALL( resolvePropagation(scip, cons, infervar, (PROPRULE)inferinfo, bdchgidx, result) );
    4640
    4641 return SCIP_OKAY;
    4642}
    4643
    4644
    4645/** variable rounding lock method of constraint handler */
    4646static
    4648{ /*lint --e{715}*/
    4649 SCIP_CONSDATA* consdata;
    4650 int i;
    4651
    4652 consdata = SCIPconsGetData(cons);
    4653 assert(consdata != NULL);
    4654
    4655 /* resultant variable */
    4656 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->resvar, locktype, nlockspos + nlocksneg, nlockspos + nlocksneg) );
    4657
    4658 /* operand variables */
    4659 for( i = 0; i < consdata->nvars; ++i )
    4660 {
    4661 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos + nlocksneg, nlockspos + nlocksneg) );
    4662 }
    4663
    4664 return SCIP_OKAY;
    4665}
    4666
    4667/** constraint activation notification method of constraint handler */
    4668static
    4670{ /*lint --e{715}*/
    4672 {
    4673 SCIP_CALL( addNlrow(scip, cons) );
    4674 }
    4675
    4676 return SCIP_OKAY;
    4677}
    4678
    4679/** constraint deactivation notification method of constraint handler */
    4680static
    4682{ /*lint --e{715}*/
    4683 SCIP_CONSDATA* consdata;
    4684
    4685 assert(cons != NULL);
    4686
    4687 consdata = SCIPconsGetData(cons);
    4688 assert(consdata != NULL);
    4689
    4690 /* remove row from NLP, if still in solving
    4691 * if we are in exitsolve, the whole NLP will be freed anyway
    4692 */
    4693 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
    4694 {
    4695 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
    4696 }
    4697
    4698 return SCIP_OKAY;
    4699}
    4700
    4701/** constraint display method of constraint handler */
    4702static
    4704{ /*lint --e{715}*/
    4705 assert( scip != NULL );
    4706 assert( conshdlr != NULL );
    4707 assert( cons != NULL );
    4708
    4710
    4711 return SCIP_OKAY;
    4712}
    4713
    4714/** constraint copying method of constraint handler */
    4715static
    4717{ /*lint --e{715}*/
    4718 SCIP_VAR** sourcevars;
    4719 SCIP_VAR** vars;
    4720 SCIP_VAR* sourceresvar;
    4721 SCIP_VAR* resvar;
    4722 const char* consname;
    4723 int nvars;
    4724 int v;
    4725
    4726 assert(valid != NULL);
    4727 (*valid) = TRUE;
    4728
    4729 sourceresvar = SCIPgetResultantAnd(sourcescip, sourcecons);
    4730
    4731 /* map resultant to active variable of the target SCIP */
    4732 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourceresvar, &resvar, varmap, consmap, global, valid) );
    4733 assert(!(*valid) || resvar != NULL);
    4734
    4735 /* we do not copy, if a variable is missing */
    4736 if( !(*valid) )
    4737 return SCIP_OKAY;
    4738
    4739 /* map operand variables to active variables of the target SCIP */
    4740 sourcevars = SCIPgetVarsAnd(sourcescip, sourcecons);
    4741 nvars = SCIPgetNVarsAnd(sourcescip, sourcecons);
    4742
    4743 if( nvars == -1 )
    4744 return SCIP_INVALIDCALL;
    4745
    4746 /* allocate buffer array */
    4747 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    4748
    4749 for( v = 0; v < nvars; ++v )
    4750 {
    4751 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &vars[v], varmap, consmap, global, valid) );
    4752 assert(!(*valid) || vars[v] != NULL);
    4753
    4754 /* we do not copy, if a variable is missing */
    4755 if( !(*valid) )
    4756 goto TERMINATE;
    4757 }
    4758
    4759 if( name != NULL )
    4760 consname = name;
    4761 else
    4762 consname = SCIPconsGetName(sourcecons);
    4763
    4764 /* creates and captures a AND-constraint */
    4765 SCIP_CALL( SCIPcreateConsAnd(scip, cons, consname, resvar, nvars, vars,
    4766 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    4767
    4768 TERMINATE:
    4769 /* free buffer array */
    4770 SCIPfreeBufferArray(scip, &vars);
    4771
    4772 return SCIP_OKAY;
    4773}
    4774
    4775/** constraint parsing method of constraint handler */
    4776static
    4778{ /*lint --e{715}*/
    4779 SCIP_VAR** vars;
    4780 SCIP_VAR* resvar;
    4781 char* endptr;
    4782 int requiredsize;
    4783 int varssize;
    4784 int nvars;
    4785
    4786 SCIPdebugMsg(scip, "parse <%s> as AND-constraint\n", str);
    4787
    4788 *success = FALSE;
    4789
    4790 /* parse variable name of resultant */
    4791 SCIP_CALL( SCIPparseVarName(scip, str, &resvar, &endptr) );
    4792
    4793 if( resvar == NULL )
    4794 {
    4795 SCIPerrorMessage("resultant variable does not exist\n");
    4796 }
    4797 else
    4798 {
    4799 char* strcopy = NULL;
    4800 char* startptr;
    4801
    4802 str = endptr;
    4803
    4804 /* cutoff "== and(" form the constraint string */
    4805 startptr = strchr((char*)str, '(');
    4806
    4807 if( startptr == NULL )
    4808 {
    4809 SCIPerrorMessage("missing starting character '(' parsing AND-constraint\n");
    4810 return SCIP_OKAY;
    4811 }
    4812
    4813 /* skip '(' */
    4814 ++startptr;
    4815
    4816 /* find end character ')' */
    4817 endptr = strrchr(startptr, ')');
    4818
    4819 if( endptr == NULL )
    4820 {
    4821 SCIPerrorMessage("missing ending character ')' parsing AND-constraint\n");
    4822 return SCIP_OKAY;
    4823 }
    4824 assert(endptr >= startptr);
    4825
    4826 if( endptr > startptr )
    4827 {
    4828 /* copy string for parsing; note that SCIPskipSpace() in SCIPparseVarsList() requires that strcopy ends with '\0' */
    4829 SCIP_CALL( SCIPduplicateBufferArray(scip, &strcopy, startptr, (int)(endptr-startptr+1)) );
    4830 strcopy[endptr-startptr] = '\0';
    4831 varssize = 100;
    4832 nvars = 0;
    4833
    4834 /* allocate buffer array for variables */
    4835 SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
    4836
    4837 /* parse string */
    4838 SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
    4839
    4840 if( *success )
    4841 {
    4842 /* check if the size of the variable array was great enough */
    4843 if( varssize < requiredsize )
    4844 {
    4845 /* reallocate memory */
    4846 varssize = requiredsize;
    4847 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
    4848
    4849 /* parse string again with the correct size of the variable array */
    4850 SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
    4851 }
    4852
    4853 assert(*success);
    4854 assert(varssize >= requiredsize);
    4855
    4856 /* create AND-constraint */
    4857 SCIP_CALL( SCIPcreateConsAnd(scip, cons, name, resvar, nvars, vars,
    4858 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    4859 }
    4860
    4861 /* free variable buffer */
    4862 SCIPfreeBufferArray(scip, &vars);
    4863 SCIPfreeBufferArray(scip, &strcopy);
    4864 }
    4865 else
    4866 {
    4867 if( !modifiable )
    4868 {
    4869 SCIPerrorMessage("cannot create empty AND-constraint\n");
    4870 return SCIP_OKAY;
    4871 }
    4872
    4873 /* create empty AND-constraint */
    4874 SCIP_CALL( SCIPcreateConsAnd(scip, cons, name, resvar, 0, NULL,
    4875 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    4876
    4877 *success = TRUE;
    4878 }
    4879 }
    4880
    4881 return SCIP_OKAY;
    4882}
    4883
    4884/** constraint method of constraint handler which returns the variables (if possible) */
    4885static
    4887{ /*lint --e{715}*/
    4888 SCIP_CONSDATA* consdata;
    4889
    4890 consdata = SCIPconsGetData(cons);
    4891 assert(consdata != NULL);
    4892
    4893 if( varssize < consdata->nvars + 1 )
    4894 (*success) = FALSE;
    4895 else
    4896 {
    4897 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
    4898 vars[consdata->nvars] = consdata->resvar;
    4899 (*success) = TRUE;
    4900 }
    4901
    4902 return SCIP_OKAY;
    4903}
    4904
    4905/** constraint method of constraint handler which returns the number of variable (if possible) */
    4906static
    4908{ /*lint --e{715}*/
    4909 SCIP_CONSDATA* consdata;
    4910
    4911 assert(cons != NULL);
    4912
    4913 consdata = SCIPconsGetData(cons);
    4914 assert(consdata != NULL);
    4915
    4916 (*nvars) = consdata->nvars + 1;
    4917 (*success) = TRUE;
    4918
    4919 return SCIP_OKAY;
    4920}
    4921
    4922/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
    4923static
    4924SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphAnd)
    4925{ /*lint --e{715}*/
    4926 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
    4927
    4928 return SCIP_OKAY;
    4929}
    4930
    4931/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
    4932static
    4933SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphAnd)
    4934{ /*lint --e{715}*/
    4935 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
    4936
    4937 return SCIP_OKAY;
    4938}
    4939
    4940/*
    4941 * Callback methods of event handler
    4942 */
    4943
    4944static
    4946{ /*lint --e{715}*/
    4947 SCIP_CONSDATA* consdata;
    4948
    4949 assert(eventhdlr != NULL);
    4950 assert(eventdata != NULL);
    4951 assert(event != NULL);
    4952
    4953 consdata = (SCIP_CONSDATA*)eventdata;
    4954 assert(consdata != NULL);
    4955
    4956 /* check, if the variable was fixed to zero */
    4958 consdata->nofixedzero = FALSE;
    4959
    4960 consdata->propagated = FALSE;
    4961
    4962 return SCIP_OKAY;
    4963}
    4964
    4965
    4966/*
    4967 * constraint specific interface methods
    4968 */
    4969
    4970/** creates the handler for AND-constraints and includes it in SCIP */
    4972 SCIP* scip /**< SCIP data structure */
    4973 )
    4974{
    4975 SCIP_CONSHDLRDATA* conshdlrdata;
    4976 SCIP_CONSHDLR* conshdlr;
    4977 SCIP_EVENTHDLR* eventhdlr;
    4978
    4979 /* create event handler for events on variables */
    4981 eventExecAnd, NULL) );
    4982
    4983 /* create constraint handler data */
    4984 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
    4985
    4986 /* include constraint handler */
    4989 consEnfolpAnd, consEnfopsAnd, consCheckAnd, consLockAnd,
    4990 conshdlrdata) );
    4991
    4992 assert(conshdlr != NULL);
    4993
    4994 /* set non-fundamental callbacks via specific setter functions */
    4995 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyAnd, consCopyAnd) );
    4996 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveAnd) );
    4997 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveAnd) );
    4998 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteAnd) );
    4999#ifdef GMLGATEPRINTING
    5000 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreAnd) );
    5001#endif
    5002 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolAnd) );
    5003 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolAnd) );
    5004 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeAnd) );
    5005 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsAnd) );
    5006 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsAnd) );
    5007 SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreAnd) );
    5008 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpAnd) );
    5009 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseAnd) );
    5011 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintAnd) );
    5014 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropAnd) );
    5015 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpAnd, consSepasolAnd, CONSHDLR_SEPAFREQ,
    5017 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransAnd) );
    5018 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxAnd) );
    5019 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphAnd) );
    5020 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphAnd) );
    5021
    5022 /* add AND-constraint handler parameters */
    5024 "constraints/" CONSHDLR_NAME "/presolpairwise",
    5025 "should pairwise constraint comparison be performed in presolving?",
    5026 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
    5028 "constraints/and/presolusehashing",
    5029 "should hash table be used for detecting redundant constraints in advance",
    5030 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
    5032 "constraints/" CONSHDLR_NAME "/linearize",
    5033 "should the AND-constraint get linearized and removed (in presolving)?",
    5034 &conshdlrdata->linearize, TRUE, DEFAULT_LINEARIZE, NULL, NULL) );
    5036 "constraints/" CONSHDLR_NAME "/enforcecuts",
    5037 "should cuts be separated during LP enforcing?",
    5038 &conshdlrdata->enforcecuts, TRUE, DEFAULT_ENFORCECUTS, NULL, NULL) );
    5040 "constraints/" CONSHDLR_NAME "/aggrlinearization",
    5041 "should an aggregated linearization be used?",
    5042 &conshdlrdata->aggrlinearization, TRUE, DEFAULT_AGGRLINEARIZATION, NULL, NULL) );
    5044 "constraints/" CONSHDLR_NAME "/upgraderesultant",
    5045 "should implied integrality of resultant variables be detected?",
    5046 &conshdlrdata->upgrresultant, TRUE, DEFAULT_UPGRRESULTANT, NULL, NULL) );
    5048 "constraints/" CONSHDLR_NAME "/dualpresolving",
    5049 "should dual presolving be performed?",
    5050 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
    5051
    5052 return SCIP_OKAY;
    5053}
    5054
    5055/** creates and captures a AND-constraint
    5056 *
    5057 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    5058 */
    5060 SCIP* scip, /**< SCIP data structure */
    5061 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    5062 const char* name, /**< name of constraint */
    5063 SCIP_VAR* resvar, /**< resultant variable of the operation */
    5064 int nvars, /**< number of operator variables in the constraint */
    5065 SCIP_VAR** vars, /**< array with operator variables of constraint */
    5066 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
    5067 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    5068 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
    5069 * Usually set to TRUE. */
    5070 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    5071 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    5072 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    5073 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    5074 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
    5075 * Usually set to TRUE. */
    5076 SCIP_Bool local, /**< is constraint only valid locally?
    5077 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    5078 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
    5079 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
    5080 * adds coefficients to this constraint. */
    5081 SCIP_Bool dynamic, /**< is constraint subject to aging?
    5082 * Usually set to FALSE. Set to TRUE for own cuts which
    5083 * are separated as constraints. */
    5084 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
    5085 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
    5086 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    5087 * if it may be moved to a more global node?
    5088 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
    5089 )
    5090{
    5091 SCIP_CONSHDLR* conshdlr;
    5092 SCIP_CONSHDLRDATA* conshdlrdata;
    5093 SCIP_CONSDATA* consdata;
    5094 SCIP_Bool infeasible;
    5095 int i;
    5096
    5097 /* find the AND-constraint handler */
    5098 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    5099 if( conshdlr == NULL )
    5100 {
    5101 SCIPerrorMessage("AND-constraint handler not found\n");
    5102 return SCIP_PLUGINNOTFOUND;
    5103 }
    5104
    5105 /* check whether resultant variable is binary */
    5106 if( !SCIPvarIsBinary(resvar) )
    5107 {
    5108 SCIPerrorMessage("resultant <%s> is not binary\n", SCIPvarGetName(resvar));
    5109 return SCIP_INVALIDDATA;
    5110 }
    5111
    5112 /* check whether all variables are binary */
    5113 assert(vars != NULL || nvars == 0);
    5114 for( i = 0; i < nvars; ++i )
    5115 {
    5116 if( !SCIPvarIsBinary(vars[i]) )
    5117 {
    5118 SCIPerrorMessage("operand <%s> is not binary\n", SCIPvarGetName(vars[i]));
    5119 return SCIP_INVALIDDATA;
    5120 }
    5121 }
    5122
    5123 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    5124 assert(conshdlrdata != NULL);
    5125
    5126 /* upgrade binary resultant variable to an implicit binary variable */
    5127 /* @todo add implicit upgrade in presolving, improve decision making for upgrade by creating an implication graph */
    5128 if( conshdlrdata->upgrresultant && !SCIPvarIsImpliedIntegral(resvar) )
    5129 {
    5130 SCIP_VAR* activeresvar;
    5131 SCIP_VAR* activevar;
    5132 int v;
    5133
    5134 if( SCIPisTransformed(scip) )
    5135 activeresvar = SCIPvarGetProbvar(resvar);
    5136 else
    5137 activeresvar = resvar;
    5138
    5139 if( SCIPvarGetType(activeresvar) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(activeresvar) )
    5140 {
    5141 /* check if we can upgrade the variable type of the resultant */
    5142 for( v = nvars - 1; v >= 0; --v )
    5143 {
    5144 if( SCIPisTransformed(scip) )
    5145 activevar = SCIPvarGetProbvar(vars[v]);
    5146 else
    5147 activevar = vars[v];
    5148
    5149 if( activevar == activeresvar || SCIPvarIsImpliedIntegral(activevar) )
    5150 break;
    5151 }
    5152
    5153 /* upgrade the type of the resultant */
    5154 if( v < 0 )
    5155 {
    5156 SCIP_CALL( SCIPchgVarImplType(scip, resvar, SCIP_IMPLINTTYPE_STRONG, &infeasible) );
    5157 assert(!infeasible);
    5158 }
    5159 }
    5160 }
    5161
    5162 /* create constraint data */
    5163 SCIP_CALL( consdataCreate(scip, &consdata, conshdlrdata->eventhdlr, nvars, vars, resvar) );
    5164
    5165 /* create constraint */
    5166 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
    5167 local, modifiable, dynamic, removable, stickingatnode) );
    5168
    5169 return SCIP_OKAY;
    5170}
    5171
    5172/** creates and captures an AND-constraint
    5173 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
    5174 * method SCIPcreateConsAnd(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
    5175 *
    5176 * @see SCIPcreateConsAnd() for information about the basic constraint flag configuration
    5177 *
    5178 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    5179 */
    5181 SCIP* scip, /**< SCIP data structure */
    5182 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    5183 const char* name, /**< name of constraint */
    5184 SCIP_VAR* resvar, /**< resultant variable of the operation */
    5185 int nvars, /**< number of operator variables in the constraint */
    5186 SCIP_VAR** vars /**< array with operator variables of constraint */
    5187 )
    5188{
    5189 assert(scip != NULL);
    5190
    5191 SCIP_CALL( SCIPcreateConsAnd(scip, cons, name, resvar, nvars, vars,
    5193
    5194 return SCIP_OKAY;
    5195}
    5196
    5197
    5198/** gets number of variables in AND-constraint */
    5200 SCIP* scip, /**< SCIP data structure */
    5201 SCIP_CONS* cons /**< constraint data */
    5202 )
    5203{
    5204 SCIP_CONSDATA* consdata;
    5205
    5206 assert(scip != NULL);
    5207 assert(cons != NULL);
    5208
    5210
    5211 consdata = SCIPconsGetData(cons);
    5212 assert(consdata != NULL);
    5213
    5214 return consdata->nvars;
    5215}
    5216
    5217/** gets array of variables in AND-constraint */
    5219 SCIP* scip, /**< SCIP data structure */
    5220 SCIP_CONS* cons /**< constraint data */
    5221 )
    5222{ /*lint --e{715}*/
    5223 SCIP_CONSDATA* consdata;
    5224
    5225 assert(scip != NULL);
    5226 assert(cons != NULL);
    5227
    5229
    5230 consdata = SCIPconsGetData(cons);
    5231 assert(consdata != NULL);
    5232
    5233 return consdata->vars;
    5234}
    5235
    5236
    5237/** gets the resultant variable in AND-constraint */ /*lint -e715*/
    5239 SCIP* scip, /**< SCIP data structure */
    5240 SCIP_CONS* cons /**< constraint data */
    5241 )
    5242{
    5243 SCIP_CONSDATA* consdata;
    5244
    5245 assert(cons != NULL);
    5246
    5248
    5249 consdata = SCIPconsGetData(cons);
    5250 assert(consdata != NULL);
    5251
    5252 return consdata->resvar;
    5253}
    5254
    5255/** return if the variables of the AND-constraint are sorted with respect to their indices */
    5257 SCIP* scip, /**< SCIP data structure */
    5258 SCIP_CONS* cons /**< constraint data */
    5259 )
    5260{
    5261 SCIP_CONSDATA* consdata;
    5262
    5263 assert(scip != NULL);
    5264 assert(cons != NULL);
    5265
    5267
    5268 consdata = SCIPconsGetData(cons);
    5269 assert(consdata != NULL);
    5270
    5271 return consdata->sorted;
    5272}
    5273
    5274/** sort the variables of the AND-constraint with respect to their indices */
    5276 SCIP* scip, /**< SCIP data structure */
    5277 SCIP_CONS* cons /**< constraint data */
    5278 )
    5279{
    5280 SCIP_CONSDATA* consdata;
    5281
    5282 assert(scip != NULL);
    5283 assert(cons != NULL);
    5284
    5286
    5287 consdata = SCIPconsGetData(cons);
    5288 assert(consdata != NULL);
    5289
    5290 consdataSort(consdata);
    5291 assert(consdata->sorted);
    5292
    5293 return SCIP_OKAY;
    5294}
    SCIP_Real * r
    Definition: circlepacking.c:59
    static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
    Definition: cons_and.c:957
    enum Proprule PROPRULE
    Definition: cons_and.c:172
    static SCIP_DECL_CONSACTIVE(consActiveAnd)
    Definition: cons_and.c:4669
    static SCIP_RETCODE consdataFreeRows(SCIP *scip, SCIP_CONSDATA *consdata)
    Definition: cons_and.c:500
    static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
    Definition: cons_and.c:581
    static SCIP_RETCODE consdataCatchWatchedEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos, int *filterpos)
    Definition: cons_and.c:242
    static SCIP_RETCODE consdataDropEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
    Definition: cons_and.c:315
    #define DEFAULT_DUALPRESOLVING
    Definition: cons_and.c:109
    static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_EVENTHDLR *eventhdlr, unsigned char **entries, int *nentries, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *nchgcoefs, int *ndelconss, int *nupgdconss, int *naddconss)
    Definition: cons_and.c:2011
    static SCIP_RETCODE consdataSwitchWatchedvars(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int watchedvar1, int watchedvar2)
    Definition: cons_and.c:341
    #define CONSHDLR_NEEDSCONS
    Definition: cons_and.c:96
    #define CONSHDLR_SEPAFREQ
    Definition: cons_and.c:89
    static SCIP_DECL_CONSDELETE(consDeleteAnd)
    Definition: cons_and.c:4198
    static SCIP_DECL_HASHKEYEQ(hashKeyEqAndcons)
    Definition: cons_and.c:3321
    static SCIP_DECL_EVENTEXEC(eventExecAnd)
    Definition: cons_and.c:4945
    static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
    Definition: cons_and.c:666
    #define CONSHDLR_CHECKPRIORITY
    Definition: cons_and.c:88
    static SCIP_DECL_CONSFREE(consFreeAnd)
    Definition: cons_and.c:3855
    #define CONSHDLR_DESC
    Definition: cons_and.c:85
    static SCIP_RETCODE consdataFixOperandsOne(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int nvars, SCIP_Bool *cutoff, int *nfixedvars)
    Definition: cons_and.c:1338
    static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *separated, SCIP_Bool *cutoff)
    Definition: cons_and.c:1182
    static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_VAR *var)
    Definition: cons_and.c:606
    static SCIP_DECL_CONSCOPY(consCopyAnd)
    Definition: cons_and.c:4716
    static SCIP_RETCODE createRelaxation(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:910
    #define CONSHDLR_PROP_TIMING
    Definition: cons_and.c:99
    #define HASHSIZE_ANDCONS
    Definition: cons_and.c:111
    static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
    Definition: cons_and.c:229
    static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_and.c:195
    static SCIP_DECL_CONSENFOPS(consEnfopsAnd)
    Definition: cons_and.c:4332
    static SCIP_RETCODE analyzeZeroResultant(SCIP *scip, SCIP_CONS *cons, int watchedvar1, int watchedvar2, SCIP_Bool *cutoff, int *nfixedvars)
    Definition: cons_and.c:1501
    static SCIP_DECL_CONSINITPRE(consInitpreAnd)
    Definition: cons_and.c:3873
    static SCIP_DECL_HASHGETKEY(hashGetKeyAndcons)
    Definition: cons_and.c:3313
    #define DEFAULT_UPGRRESULTANT
    Definition: cons_and.c:108
    #define CONSHDLR_MAXPREROUNDS
    Definition: cons_and.c:93
    static SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphAnd)
    Definition: cons_and.c:4933
    static SCIP_RETCODE consdataFixResultantZero(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *resvar, int pos, SCIP_Bool *cutoff, int *nfixedvars)
    Definition: cons_and.c:1299
    static SCIP_DECL_CONSENFORELAX(consEnforelaxAnd)
    Definition: cons_and.c:4323
    #define DEFAULT_PRESOLPAIRWISE
    Definition: cons_and.c:104
    #define CONSHDLR_SEPAPRIORITY
    Definition: cons_and.c:86
    static SCIP_RETCODE analyzeConflictOne(SCIP *scip, SCIP_CONS *cons, int falsepos)
    Definition: cons_and.c:1231
    static SCIP_RETCODE detectRedundantConstraints(SCIP *scip, BMS_BLKMEM *blkmem, SCIP_CONS **conss, int nconss, int *firstchange, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
    Definition: cons_and.c:3391
    static SCIP_DECL_CONSRESPROP(consRespropAnd)
    Definition: cons_and.c:4637
    static SCIP_DECL_CONSSEPASOL(consSepasolAnd)
    Definition: cons_and.c:4287
    #define DEFAULT_LINEARIZE
    Definition: cons_and.c:105
    static SCIP_RETCODE cliquePresolve(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *nchgcoefs, int *ndelconss, int *naddconss)
    Definition: cons_and.c:2667
    static SCIP_RETCODE preprocessConstraintPairs(SCIP *scip, SCIP_CONS **conss, int firstchange, int chkind, SCIP_Bool *cutoff, int *naggrvars, int *nbdchgs, int *ndelconss)
    Definition: cons_and.c:3565
    static SCIP_DECL_CONSTRANS(consTransAnd)
    Definition: cons_and.c:4213
    static SCIP_RETCODE consdataLinearize(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nupgdconss)
    Definition: cons_and.c:1392
    static SCIP_DECL_CONSLOCK(consLockAnd)
    Definition: cons_and.c:4647
    static SCIP_DECL_CONSINITLP(consInitlpAnd)
    Definition: cons_and.c:4242
    static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
    Definition: cons_and.c:3765
    static SCIP_DECL_CONSSEPALP(consSepalpAnd)
    Definition: cons_and.c:4260
    static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_and.c:181
    static SCIP_DECL_CONSEXITSOL(consExitsolAnd)
    Definition: cons_and.c:4173
    static SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphAnd)
    Definition: cons_and.c:4924
    static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
    Definition: cons_and.c:401
    Proprule
    Definition: cons_and.c:165
    @ PROPRULE_2
    Definition: cons_and.c:168
    @ PROPRULE_1
    Definition: cons_and.c:167
    @ PROPRULE_3
    Definition: cons_and.c:169
    @ PROPRULE_INVALID
    Definition: cons_and.c:166
    @ PROPRULE_4
    Definition: cons_and.c:170
    static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool *violated)
    Definition: cons_and.c:1070
    #define DEFAULT_PRESOLUSEHASHING
    Definition: cons_and.c:112
    static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_EVENTHDLR *eventhdlr)
    Definition: cons_and.c:531
    static SCIP_DECL_CONSPARSE(consParseAnd)
    Definition: cons_and.c:4777
    static SCIP_RETCODE consdataDropWatchedEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos, int filterpos)
    Definition: cons_and.c:266
    #define MINGAINPERNMINCOMPARISONS
    Definition: cons_and.c:114
    static SCIP_RETCODE analyzeConflictZero(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:1263
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyAnd)
    Definition: cons_and.c:3838
    static SCIP_DECL_CONSINITSOL(consInitsolAnd)
    Definition: cons_and.c:4156
    #define CONSHDLR_PROPFREQ
    Definition: cons_and.c:90
    static SCIP_DECL_CONSDEACTIVE(consDeactiveAnd)
    Definition: cons_and.c:4681
    #define NMINCOMPARISONS
    Definition: cons_and.c:113
    #define DEFAULT_ENFORCECUTS
    Definition: cons_and.c:106
    #define CONSHDLR_PRESOLTIMING
    Definition: cons_and.c:98
    static SCIP_DECL_CONSGETNVARS(consGetNVarsAnd)
    Definition: cons_and.c:4907
    static void consdataSort(SCIP_CONSDATA *consdata)
    Definition: cons_and.c:729
    static SCIP_DECL_CONSPROP(consPropAnd)
    Definition: cons_and.c:4373
    static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:1017
    static SCIP_DECL_CONSPRINT(consPrintAnd)
    Definition: cons_and.c:4703
    #define CONSHDLR_EAGERFREQ
    Definition: cons_and.c:91
    #define EVENTHDLR_DESC
    Definition: cons_and.c:102
    static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
    Definition: cons_and.c:209
    static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_EVENTHDLR *eventhdlr, int nvars, SCIP_VAR **vars, SCIP_VAR *resvar)
    Definition: cons_and.c:425
    static SCIP_DECL_HASHKEYVAL(hashKeyValAndcons)
    Definition: cons_and.c:3367
    static SCIP_DECL_CONSENFOLP(consEnfolpAnd)
    Definition: cons_and.c:4314
    static SCIP_DECL_CONSPRESOL(consPresolAnd)
    Definition: cons_and.c:4408
    #define CONSHDLR_ENFOPRIORITY
    Definition: cons_and.c:87
    static SCIP_DECL_CONSCHECK(consCheckAnd)
    Definition: cons_and.c:4354
    static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int *nchgcoefs)
    Definition: cons_and.c:810
    static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, PROPRULE proprule, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
    Definition: cons_and.c:1925
    #define CONSHDLR_DELAYSEPA
    Definition: cons_and.c:94
    static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, unsigned char **entries, int *nentries, int *nfixedvars, int *nchgcoefs, int *ndelconss)
    Definition: cons_and.c:1562
    static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, SCIP_SOL *sol, SCIP_RESULT *result)
    Definition: cons_and.c:3508
    #define CONSHDLR_NAME
    Definition: cons_and.c:84
    #define EVENTHDLR_NAME
    Definition: cons_and.c:101
    #define DEFAULT_AGGRLINEARIZATION
    Definition: cons_and.c:107
    static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, int *nfixedvars, int *nupgdconss)
    Definition: cons_and.c:1720
    #define CONSHDLR_DELAYPROP
    Definition: cons_and.c:95
    static SCIP_RETCODE consdataCatchEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
    Definition: cons_and.c:289
    static SCIP_DECL_CONSGETVARS(consGetVarsAnd)
    Definition: cons_and.c:4886
    Constraint handler for AND constraints, .
    Constraint handler for linear constraints in their most general form, .
    Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
    constraint handler for pseudoboolean constraints
    Constraint handler for the set partitioning / packing / covering constraints .
    methods for debugging
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_Bool
    Definition: def.h:100
    #define MAX3(x, y, z)
    Definition: def.h:237
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIPABORT()
    Definition: def.h:336
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_CALL(x)
    Definition: def.h:364
    #define SCIP_CALL_FINALLY(x, y)
    Definition: def.h:406
    product expression handler
    variable expression handler
    SCIP_RETCODE SCIPcreateConsAnd(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    Definition: cons_and.c:5059
    SCIP_VAR * SCIPgetResultantAnd(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5238
    int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5199
    SCIP_RETCODE SCIPcreateConsSetpack(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    Definition: cons_setppc.c:9551
    SCIP_RETCODE SCIPsortAndCons(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5275
    SCIP_Bool SCIPisAndConsSorted(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5256
    SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_RETCODE SCIPcreateConsSetpart(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    Definition: cons_setppc.c:9493
    SCIP_VAR ** SCIPgetVarsAnd(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5218
    SCIP_RETCODE SCIPcreateConsLogicor(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_RETCODE SCIPcreateConsBasicAnd(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, int nvars, SCIP_VAR **vars)
    Definition: cons_and.c:5180
    SCIP_RETCODE SCIPincludeConshdlrAnd(SCIP *scip)
    Definition: cons_and.c:4971
    SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
    Definition: scip_copy.c:713
    SCIP_RETCODE SCIPcreateExprVar(SCIP *scip, SCIP_EXPR **expr, SCIP_VAR *var, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_var.c:397
    SCIP_RETCODE SCIPcreateExprProduct(SCIP *scip, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real coefficient, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    void SCIPgmlWriteNode(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
    Definition: misc.c:501
    void SCIPgmlWriteClosing(FILE *file)
    Definition: misc.c:703
    void SCIPgmlWriteOpening(FILE *file, SCIP_Bool directed)
    Definition: misc.c:687
    void SCIPgmlWriteArc(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
    Definition: misc.c:643
    SCIP_Bool SCIPisTransformed(SCIP *scip)
    Definition: scip_general.c:655
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    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
    SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
    Definition: scip_prob.c:2115
    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_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 SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:4067
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #define SCIPdebugMsgPrint
    Definition: scip_message.h:79
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    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)
    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 SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
    Definition: scip_cons.c:808
    void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: cons.c:4350
    SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
    Definition: scip_cons.c:540
    SCIP_RETCODE 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
    SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
    Definition: scip_cons.c:854
    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_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_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
    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 SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8572
    SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1784
    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
    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_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
    Definition: scip_expr.c:1443
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    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 SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #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_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
    Definition: scip_lp.c:2131
    SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
    Definition: scip_lp.c:1508
    SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
    Definition: lp.c:17917
    void SCIPupdateSolConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
    Definition: scip_sol.c:451
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisGT(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 SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPinRepropagation(SCIP *scip)
    Definition: scip_tree.c:146
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_RETCODE SCIPcutoffNode(SCIP *scip, SCIP_NODE *node)
    Definition: scip_tree.c:436
    SCIP_NODE * SCIPgetRootNode(SCIP *scip)
    Definition: scip_tree.c:110
    SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
    Definition: scip_var.c:5210
    void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
    Definition: var.c:17575
    SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23674
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23510
    SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
    Definition: scip_var.c:2119
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23418
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4380
    SCIP_Bool SCIPdoNotAggr(SCIP *scip)
    Definition: scip_var.c:10909
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23530
    SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
    Definition: var.c:23976
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_RETCODE SCIPgetBinvarRepresentatives(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **repvars, SCIP_Bool *negated)
    Definition: scip_var.c:2283
    SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
    Definition: var.c:23462
    SCIP_RETCODE SCIPparseVarsList(SCIP *scip, const char *str, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize, char **endptr, char delimiter, SCIP_Bool *success)
    Definition: scip_var.c:805
    SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
    Definition: scip_var.c:10550
    SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
    Definition: var.c:17595
    SCIP_RETCODE SCIPchgVarImplType(SCIP *scip, SCIP_VAR *var, SCIP_IMPLINTTYPE impltype, SCIP_Bool *infeasible)
    Definition: scip_var.c:10218
    SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
    Definition: scip_var.c:728
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23485
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24174
    int SCIPvarGetIndex(SCIP_VAR *var)
    Definition: var.c:23684
    SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
    Definition: scip_var.c:5118
    SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
    Definition: scip_var.c:5296
    SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2872
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23694
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
    Definition: scip_var.c:2166
    SCIP_RETCODE SCIPaddVarImplication(SCIP *scip, SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
    Definition: scip_var.c:8740
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
    Definition: var.c:23475
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:11057
    SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
    Definition: scip_var.c:10318
    SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2736
    int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
    Definition: var.c:17319
    SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
    Definition: var.c:17687
    SCIP_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 SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
    Definition: scip_var.c:361
    SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
    Definition: scip_var.c:2236
    SCIP_RETCODE SCIPwriteVarsList(SCIP *scip, FILE *file, SCIP_VAR **vars, int nvars, SCIP_Bool type, char delimiter)
    Definition: scip_var.c:423
    SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
    Definition: var.c:16852
    int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4322
    SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
    Definition: scip_var.c:2078
    SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:1853
    SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
    Definition: scip_var.c:10984
    SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
    void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    SCIP_RETCODE SCIPaddSymgraphEdge(SCIP *scip, SYM_GRAPH *graph, int first, int second, SCIP_Bool hasval, SCIP_Real val)
    SCIP_RETCODE SCIPaddSymgraphOpnode(SCIP *scip, SYM_GRAPH *graph, int op, int *nodeidx)
    SCIP_RETCODE SCIPgetSymActiveVariables(SCIP *scip, SYM_SYMTYPE symtype, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
    SCIP_RETCODE SCIPaddSymgraphConsnode(SCIP *scip, SYM_GRAPH *graph, SCIP_CONS *cons, SCIP_Real lhs, SCIP_Real rhs, int *nodeidx)
    SCIP_RETCODE SCIPaddSymgraphVarAggregation(SCIP *scip, SYM_GRAPH *graph, int rootidx, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Real constant)
    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
    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 problem copies
    public methods for cuts and aggregation rows
    public methods for event handler plugins and event handlers
    public functions to work with algebraic expressions
    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 the branch-and-bound tree
    public methods for SCIP variables
    static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
    Main separation function.
    Definition: sepa_flower.c:1219
    structs for symmetry computations
    methods for dealing with symmetry detection graphs
    @ SCIP_CONFTYPE_PROPAGATION
    Definition: type_conflict.h:62
    struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
    Definition: type_cons.h:64
    #define SCIP_DECL_CONSEXITPRE(x)
    Definition: type_cons.h:180
    struct SCIP_ConsData SCIP_CONSDATA
    Definition: type_cons.h:65
    #define SCIP_EVENTTYPE_BOUNDCHANGED
    Definition: type_event.h:127
    struct SCIP_EventData SCIP_EVENTDATA
    Definition: type_event.h:179
    #define SCIP_EVENTTYPE_UBTIGHTENED
    Definition: type_event.h:79
    #define SCIP_EVENTTYPE_LBRELAXED
    Definition: type_event.h:78
    #define SCIP_EVENTTYPE_LBTIGHTENED
    Definition: type_event.h:77
    #define SCIP_EVENTTYPE_UBRELAXED
    Definition: type_event.h:80
    @ SCIP_EXPRCURV_UNKNOWN
    Definition: type_expr.h:62
    @ SCIP_BOUNDTYPE_UPPER
    Definition: type_lp.h:58
    @ SCIP_BOUNDTYPE_LOWER
    Definition: type_lp.h:57
    @ 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_SEPARATED
    Definition: type_result.h:49
    @ 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_PLUGINNOTFOUND
    Definition: type_retcode.h:54
    @ SCIP_WRITEERROR
    Definition: type_retcode.h:46
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_EXITPRESOLVE
    Definition: type_set.h:50
    @ SCIP_STAGE_SOLVING
    Definition: type_set.h:53
    enum SYM_Symtype SYM_SYMTYPE
    Definition: type_symmetry.h:64
    @ SYM_CONSOPTYPE_AND
    Definition: type_symmetry.h:92
    @ SYM_SYMTYPE_SIGNPERM
    Definition: type_symmetry.h:62
    @ SYM_SYMTYPE_PERM
    Definition: type_symmetry.h:61
    #define SCIP_PRESOLTIMING_EXHAUSTIVE
    Definition: type_timing.h:54
    @ SCIP_IMPLINTTYPE_STRONG
    Definition: type_var.h:106
    @ 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_LOCKTYPE_MODEL
    Definition: type_var.h:141