Scippy

    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-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file cons_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#include <string.h>
    82
    83
    84/* constraint handler properties */
    85#define CONSHDLR_NAME "and"
    86#define CONSHDLR_DESC "constraint handler for AND-constraints: r = and(x1, ..., xn)"
    87#define CONSHDLR_SEPAPRIORITY +850100 /**< priority of the constraint handler for separation */
    88#define CONSHDLR_ENFOPRIORITY -850100 /**< priority of the constraint handler for constraint enforcing */
    89#define CONSHDLR_CHECKPRIORITY -850100 /**< priority of the constraint handler for checking feasibility */
    90#define CONSHDLR_SEPAFREQ 1 /**< frequency for separating cuts; zero means to separate only in the root node */
    91#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
    92#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
    93 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    94#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
    95#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
    96#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
    97#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
    98
    99#define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE)
    100#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
    101
    102#define EVENTHDLR_NAME "and"
    103#define EVENTHDLR_DESC "bound change event handler for AND-constraints"
    104
    105#define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
    106#define DEFAULT_LINEARIZE FALSE /**< should constraint get linearized and removed? */
    107#define DEFAULT_ENFORCECUTS TRUE /**< should cuts be separated during LP enforcing? */
    108#define DEFAULT_AGGRLINEARIZATION FALSE /**< should an aggregated linearization be used? */
    109#define DEFAULT_UPGRRESULTANT FALSE /**< should implied integrality of resultant variables be detected? */
    110#define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving be performed? */
    111
    112#define HASHSIZE_ANDCONS 500 /**< minimal size of hash table in and constraint tables */
    113#define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
    114#define NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
    115#define MINGAINPERNMINCOMPARISONS 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
    116
    117/* @todo maybe use event SCIP_EVENTTYPE_VARUNLOCKED to decide for another dual-presolving run on a constraint */
    118
    119/*
    120 * Data structures
    121 */
    122
    123/** constraint data for AND-constraints */
    124struct SCIP_ConsData
    125{
    126 SCIP_VAR** vars; /**< variables in the AND-constraint */
    127 SCIP_VAR* resvar; /**< resultant variable */
    128 SCIP_ROW** rows; /**< rows for linear relaxation of AND-constraint */
    129 SCIP_ROW* aggrrow; /**< aggregated row for linear relaxation of AND-constraint */
    130 SCIP_NLROW* nlrow; /**< row for representation in nonlinear relaxation */
    131 int nvars; /**< number of variables in AND-constraint */
    132 int varssize; /**< size of vars array */
    133 int nrows; /**< number of rows for linear relaxation of AND-constraint */
    134 int watchedvar1; /**< position of first watched operator variable */
    135 int watchedvar2; /**< position of second watched operator variable */
    136 int filterpos1; /**< event filter position of first watched operator variable */
    137 int filterpos2; /**< event filter position of second watched operator variable */
    138 unsigned int propagated:1; /**< is constraint already preprocessed/propagated? */
    139 unsigned int nofixedzero:1; /**< is none of the operator variables fixed to FALSE? */
    140 unsigned int impladded:1; /**< were the implications of the constraint already added? */
    141 unsigned int opimpladded:1; /**< was the implication for 2 operands with fixed resultant added? */
    142 unsigned int sorted:1; /**< are the constraint's variables sorted? */
    143 unsigned int changed:1; /**< was constraint changed since last pair preprocessing round? */
    144 unsigned int merged:1; /**< are the constraint's equal variables already merged? */
    145};
    146
    147/** constraint handler data */
    148struct SCIP_ConshdlrData
    149{
    150 SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events on watched variables */
    151 SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
    152 SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
    153 SCIP_Bool linearize; /**< should constraint get linearized and removed? */
    154 SCIP_Bool enforcecuts; /**< should cuts be separated during LP enforcing? */
    155 SCIP_Bool aggrlinearization; /**< should an aggregated linearization be used? */
    156 SCIP_Bool upgrresultant; /**< should implied integrality of resultant variables be detected? */
    157 SCIP_Bool dualpresolving; /**< should dual presolving be performed? */
    158};
    159
    160
    161/*
    162 * Propagation rules
    163 */
    164
    166{
    167 PROPRULE_INVALID = 0, /**< propagation was applied without a specific propagation rule */
    168 PROPRULE_1 = 1, /**< v_i = FALSE => r = FALSE */
    169 PROPRULE_2 = 2, /**< r = TRUE => v_i = TRUE for all i */
    170 PROPRULE_3 = 3, /**< v_i = TRUE for all i => r = TRUE */
    171 PROPRULE_4 = 4 /**< r = FALSE, v_i = TRUE for all i except j => v_j = FALSE */
    173typedef enum Proprule PROPRULE;
    174
    175
    176/*
    177 * Local methods
    178 */
    179
    180/** installs rounding locks for the given variable in the given AND-constraint */
    181static
    183 SCIP* scip, /**< SCIP data structure */
    184 SCIP_CONS* cons, /**< constraint data */
    185 SCIP_VAR* var /**< variable of constraint entry */
    186 )
    187{
    188 /* rounding in both directions may violate the constraint */
    189 SCIP_CALL( SCIPlockVarCons(scip, var, cons, TRUE, TRUE) );
    190
    191 return SCIP_OKAY;
    192}
    193
    194/** removes rounding locks for the given variable in the given AND-constraint */
    195static
    197 SCIP* scip, /**< SCIP data structure */
    198 SCIP_CONS* cons, /**< constraint data */
    199 SCIP_VAR* var /**< variable of constraint entry */
    200 )
    201{
    202 /* rounding in both directions may violate the constraint */
    203 SCIP_CALL( SCIPunlockVarCons(scip, var, cons, TRUE, TRUE) );
    204
    205 return SCIP_OKAY;
    206}
    207
    208/** creates constraint handler data */
    209static
    211 SCIP* scip, /**< SCIP data structure */
    212 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
    213 SCIP_EVENTHDLR* eventhdlr /**< event handler */
    214 )
    215{
    216 assert(scip != NULL);
    217 assert(conshdlrdata != NULL);
    218 assert(eventhdlr != NULL);
    219
    220 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
    221
    222 /* set event handler for catching bound change events on variables */
    223 (*conshdlrdata)->eventhdlr = eventhdlr;
    224
    225 return SCIP_OKAY;
    226}
    227
    228/** frees constraint handler data */
    229static
    231 SCIP* scip, /**< SCIP data structure */
    232 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
    233 )
    234{
    235 assert(conshdlrdata != NULL);
    236 assert(*conshdlrdata != NULL);
    237
    238 SCIPfreeBlockMemory(scip, conshdlrdata);
    239}
    240
    241/** catches events for the watched variable at given position */
    242static
    244 SCIP* scip, /**< SCIP data structure */
    245 SCIP_CONSDATA* consdata, /**< AND-constraint data */
    246 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    247 int pos, /**< array position of variable to catch bound change events for */
    248 int* filterpos /**< pointer to store position of event filter entry */
    249 )
    250{
    251 assert(consdata != NULL);
    252 assert(consdata->vars != NULL);
    253 assert(eventhdlr != NULL);
    254 assert(0 <= pos && pos < consdata->nvars);
    255 assert(filterpos != NULL);
    256
    257 /* catch tightening events for lower bound and relaxed events for upper bounds on watched variable */
    259 eventhdlr, (SCIP_EVENTDATA*)consdata, filterpos) );
    260
    261 return SCIP_OKAY;
    262}
    263
    264
    265/** drops events for the watched variable at given position */
    266static
    268 SCIP* scip, /**< SCIP data structure */
    269 SCIP_CONSDATA* consdata, /**< AND-constraint data */
    270 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    271 int pos, /**< array position of watched variable to drop bound change events for */
    272 int filterpos /**< position of event filter entry */
    273 )
    274{
    275 assert(consdata != NULL);
    276 assert(consdata->vars != NULL);
    277 assert(eventhdlr != NULL);
    278 assert(0 <= pos && pos < consdata->nvars);
    279 assert(filterpos >= 0);
    280
    281 /* drop tightening events for lower bound and relaxed events for upper bounds on watched variable */
    283 eventhdlr, (SCIP_EVENTDATA*)consdata, filterpos) );
    284
    285 return SCIP_OKAY;
    286}
    287
    288/** catches needed events on all variables of constraint, except the special ones for watched variables */
    289static
    291 SCIP* scip, /**< SCIP data structure */
    292 SCIP_CONSDATA* consdata, /**< AND-constraint data */
    293 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
    294 )
    295{
    296 int i;
    297
    298 assert(consdata != NULL);
    299
    300 /* catch bound change events for both bounds on resultant variable */
    302 eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
    303
    304 /* catch tightening events for upper bound and relaxed events for lower bounds on operator variables */
    305 for( i = 0; i < consdata->nvars; ++i )
    306 {
    308 eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
    309 }
    310
    311 return SCIP_OKAY;
    312}
    313
    314/** drops events on all variables of constraint, except the special ones for watched variables */
    315static
    317 SCIP* scip, /**< SCIP data structure */
    318 SCIP_CONSDATA* consdata, /**< AND-constraint data */
    319 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
    320 )
    321{
    322 int i;
    323
    324 assert(consdata != NULL);
    325
    326 /* drop bound change events for both bounds on resultant variable */
    328 eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
    329
    330 /* drop tightening events for upper bound and relaxed events for lower bounds on operator variables */
    331 for( i = 0; i < consdata->nvars; ++i )
    332 {
    334 eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
    335 }
    336
    337 return SCIP_OKAY;
    338}
    339
    340/** stores the given variable numbers as watched variables, and updates the event processing */
    341static
    343 SCIP* scip, /**< SCIP data structure */
    344 SCIP_CONSDATA* consdata, /**< AND-constraint data */
    345 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    346 int watchedvar1, /**< new first watched variable */
    347 int watchedvar2 /**< new second watched variable */
    348 )
    349{
    350 assert(consdata != NULL);
    351 assert(watchedvar1 == -1 || watchedvar1 != watchedvar2);
    352 assert(watchedvar1 != -1 || watchedvar2 == -1);
    353 assert(watchedvar1 == -1 || (0 <= watchedvar1 && watchedvar1 < consdata->nvars));
    354 assert(watchedvar2 == -1 || (0 <= watchedvar2 && watchedvar2 < consdata->nvars));
    355
    356 /* if one watched variable is equal to the old other watched variable, just switch positions */
    357 if( watchedvar1 == consdata->watchedvar2 || watchedvar2 == consdata->watchedvar1 )
    358 {
    359 int tmp;
    360
    361 tmp = consdata->watchedvar1;
    362 consdata->watchedvar1 = consdata->watchedvar2;
    363 consdata->watchedvar2 = tmp;
    364 tmp = consdata->filterpos1;
    365 consdata->filterpos1 = consdata->filterpos2;
    366 consdata->filterpos2 = tmp;
    367 }
    368 assert(watchedvar1 == -1 || watchedvar1 != consdata->watchedvar2);
    369 assert(watchedvar2 == -1 || watchedvar2 != consdata->watchedvar1);
    370
    371 /* drop events on old watched variables */
    372 if( consdata->watchedvar1 != -1 && consdata->watchedvar1 != watchedvar1 )
    373 {
    374 assert(consdata->filterpos1 != -1);
    375 SCIP_CALL( consdataDropWatchedEvents(scip, consdata, eventhdlr, consdata->watchedvar1, consdata->filterpos1) );
    376 }
    377 if( consdata->watchedvar2 != -1 && consdata->watchedvar2 != watchedvar2 )
    378 {
    379 assert(consdata->filterpos2 != -1);
    380 SCIP_CALL( consdataDropWatchedEvents(scip, consdata, eventhdlr, consdata->watchedvar2, consdata->filterpos2) );
    381 }
    382
    383 /* catch events on new watched variables */
    384 if( watchedvar1 != -1 && watchedvar1 != consdata->watchedvar1 )
    385 {
    386 SCIP_CALL( consdataCatchWatchedEvents(scip, consdata, eventhdlr, watchedvar1, &consdata->filterpos1) );
    387 }
    388 if( watchedvar2 != -1 && watchedvar2 != consdata->watchedvar2 )
    389 {
    390 SCIP_CALL( consdataCatchWatchedEvents(scip, consdata, eventhdlr, watchedvar2, &consdata->filterpos2) );
    391 }
    392
    393 /* set the new watched variables */
    394 consdata->watchedvar1 = watchedvar1;
    395 consdata->watchedvar2 = watchedvar2;
    396
    397 return SCIP_OKAY;
    398}
    399
    400/** ensures, that the vars array can store at least num entries */
    401static
    403 SCIP* scip, /**< SCIP data structure */
    404 SCIP_CONSDATA* consdata, /**< linear constraint data */
    405 int num /**< minimum number of entries to store */
    406 )
    407{
    408 assert(consdata != NULL);
    409 assert(consdata->nvars <= consdata->varssize);
    410
    411 if( num > consdata->varssize )
    412 {
    413 int newsize;
    414
    415 newsize = SCIPcalcMemGrowSize(scip, num);
    416 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
    417 consdata->varssize = newsize;
    418 }
    419 assert(num <= consdata->varssize);
    420
    421 return SCIP_OKAY;
    422}
    423
    424/** creates constraint data for AND-constraint */
    425static
    427 SCIP* scip, /**< SCIP data structure */
    428 SCIP_CONSDATA** consdata, /**< pointer to store the constraint data */
    429 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    430 int nvars, /**< number of variables in the AND-constraint */
    431 SCIP_VAR** vars, /**< variables in AND-constraint */
    432 SCIP_VAR* resvar /**< resultant variable */
    433 )
    434{
    435 int v;
    436
    437 assert(consdata != NULL);
    438 assert(nvars == 0 || vars != NULL);
    439 assert(resvar != NULL);
    440
    441 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
    442 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
    443 (*consdata)->resvar = resvar;
    444 (*consdata)->rows = NULL;
    445 (*consdata)->aggrrow = NULL;
    446 (*consdata)->nlrow = NULL;
    447 (*consdata)->nvars = nvars;
    448 (*consdata)->varssize = nvars;
    449 (*consdata)->nrows = 0;
    450 (*consdata)->watchedvar1 = -1;
    451 (*consdata)->watchedvar2 = -1;
    452 (*consdata)->filterpos1 = -1;
    453 (*consdata)->filterpos2 = -1;
    454 (*consdata)->propagated = FALSE;
    455 (*consdata)->nofixedzero = FALSE;
    456 (*consdata)->impladded = FALSE;
    457 (*consdata)->opimpladded = FALSE;
    458 (*consdata)->sorted = FALSE;
    459 (*consdata)->changed = TRUE;
    460 (*consdata)->merged = FALSE;
    461
    462 /* get transformed variables, if we are in the transformed problem */
    464 {
    465 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
    466 SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->resvar, &(*consdata)->resvar) );
    467
    468 /* catch needed events on variables */
    469 SCIP_CALL( consdataCatchEvents(scip, *consdata, eventhdlr) );
    470 }
    471
    472 assert(SCIPvarIsBinary((*consdata)->resvar));
    473
    474 /* note: currently, this constraint handler does not handle multiaggregations (e.g. during propagation), hence we forbid
    475 * multiaggregation from the beginning for the involved variables
    476 */
    478 {
    479 for( v = 0; v < (*consdata)->nvars; ++v )
    480 {
    481 assert((*consdata)->vars[v] != NULL);
    482 SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->vars[v]) );
    483 }
    484 SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->resvar) );
    485 }
    486
    487 /* capture vars */
    488 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->resvar) );
    489 for( v = 0; v < (*consdata)->nvars; v++ )
    490 {
    491 assert((*consdata)->vars[v] != NULL);
    492 assert(SCIPvarIsBinary((*consdata)->vars[v]));
    493 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
    494 }
    495
    496 return SCIP_OKAY;
    497}
    498
    499/** releases LP rows of constraint data and frees rows array */
    500static
    502 SCIP* scip, /**< SCIP data structure */
    503 SCIP_CONSDATA* consdata /**< constraint data */
    504 )
    505{
    506 int r;
    507
    508 assert(consdata != NULL);
    509
    510 if( consdata->rows != NULL )
    511 {
    512 for( r = 0; r < consdata->nrows; ++r )
    513 {
    514 SCIP_CALL( SCIPreleaseRow(scip, &consdata->rows[r]) );
    515 }
    516 SCIPfreeBlockMemoryArray(scip, &consdata->rows, consdata->nrows);
    517
    518 consdata->nrows = 0;
    519 }
    520
    521 if( consdata->aggrrow != NULL )
    522 {
    523 SCIP_CALL( SCIPreleaseRow(scip, &consdata->aggrrow) );
    524 consdata->aggrrow = NULL;
    525 }
    526
    527 return SCIP_OKAY;
    528}
    529
    530/** frees constraint data for AND-constraint */
    531static
    533 SCIP* scip, /**< SCIP data structure */
    534 SCIP_CONSDATA** consdata, /**< pointer to the constraint data */
    535 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
    536 )
    537{
    538 int v;
    539
    540 assert(consdata != NULL);
    541 assert(*consdata != NULL);
    542
    544 {
    545 /* drop events for watched variables */
    546 SCIP_CALL( consdataSwitchWatchedvars(scip, *consdata, eventhdlr, -1, -1) );
    547
    548 /* drop all other events on variables */
    549 SCIP_CALL( consdataDropEvents(scip, *consdata, eventhdlr) );
    550 }
    551 else
    552 {
    553 assert((*consdata)->watchedvar1 == -1);
    554 assert((*consdata)->watchedvar2 == -1);
    555 }
    556
    557 /* release and free the rows */
    558 SCIP_CALL( consdataFreeRows(scip, *consdata) );
    559
    560 /* release the nlrow */
    561 if( (*consdata)->nlrow != NULL )
    562 {
    563 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
    564 }
    565
    566 /* release vars */
    567 for( v = 0; v < (*consdata)->nvars; v++ )
    568 {
    569 assert((*consdata)->vars[v] != NULL);
    570 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
    571 }
    572 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->resvar)) );
    573
    574 SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, (*consdata)->varssize);
    575 SCIPfreeBlockMemory(scip, consdata);
    576
    577 return SCIP_OKAY;
    578}
    579
    580/** prints AND-constraint to file stream */
    581static
    583 SCIP* scip, /**< SCIP data structure */
    584 SCIP_CONSDATA* consdata, /**< AND-constraint data */
    585 FILE* file /**< output file (or NULL for standard output) */
    586 )
    587{
    588 assert(consdata != NULL);
    589
    590 /* print resultant */
    591 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->resvar, TRUE) );
    592
    593 /* start the variable list */
    594 SCIPinfoMessage(scip, file, " == and(");
    595
    596 /* print variable list */
    597 SCIP_CALL( SCIPwriteVarsList(scip, file, consdata->vars, consdata->nvars, TRUE, ',') );
    598
    599 /* close the variable list */
    600 SCIPinfoMessage(scip, file, ")");
    601
    602 return SCIP_OKAY;
    603}
    604
    605/** adds coefficient to AND-constraint */
    606static
    608 SCIP* scip, /**< SCIP data structure */
    609 SCIP_CONS* cons, /**< linear constraint */
    610 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    611 SCIP_VAR* var /**< variable to add to the constraint */
    612 )
    613{
    614 SCIP_CONSDATA* consdata;
    615 SCIP_Bool transformed;
    616
    617 assert(var != NULL);
    618
    619 consdata = SCIPconsGetData(cons);
    620 assert(consdata != NULL);
    621 assert(consdata->rows == NULL);
    622
    623 /* are we in the transformed problem? */
    624 transformed = SCIPconsIsTransformed(cons);
    625
    626 /* always use transformed variables in transformed constraints */
    627 if( transformed )
    628 {
    629 SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
    630 }
    631 assert(var != NULL);
    632 assert(transformed == SCIPvarIsTransformed(var));
    633
    634 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
    635 consdata->vars[consdata->nvars] = var;
    636 consdata->nvars++;
    637 consdata->sorted = (consdata->nvars == 1);
    638 consdata->changed = TRUE;
    639 consdata->merged = FALSE;
    640
    641 /* capture variable */
    643
    644 /* if we are in transformed problem, catch the variable's events */
    645 if( transformed )
    646 {
    647 /* catch bound change events of variable */
    649 eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
    650 }
    651
    652 /* install the rounding locks for the new variable */
    653 SCIP_CALL( lockRounding(scip, cons, var) );
    654
    655 /**@todo update LP rows */
    656 if( consdata->rows != NULL )
    657 {
    658 SCIPerrorMessage("cannot add coefficients to AND-constraint after LP relaxation was created\n");
    659 return SCIP_INVALIDCALL;
    660 }
    661
    662 return SCIP_OKAY;
    663}
    664
    665/** deletes coefficient at given position from AND-constraint data */
    666static
    668 SCIP* scip, /**< SCIP data structure */
    669 SCIP_CONS* cons, /**< AND-constraint */
    670 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    671 int pos /**< position of coefficient to delete */
    672 )
    673{
    674 SCIP_CONSDATA* consdata;
    675
    676 assert(eventhdlr != NULL);
    677
    678 consdata = SCIPconsGetData(cons);
    679 assert(consdata != NULL);
    680 assert(0 <= pos && pos < consdata->nvars);
    681 assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(consdata->vars[pos]));
    682
    683 /* remove the rounding locks of the variable */
    684 SCIP_CALL( unlockRounding(scip, cons, consdata->vars[pos]) );
    685
    686 if( SCIPconsIsTransformed(cons) )
    687 {
    688 /* drop bound change events of variable */
    690 eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
    691 }
    692
    693 if( SCIPconsIsTransformed(cons) )
    694 {
    695 /* if the position is watched, stop watching the position */
    696 if( consdata->watchedvar1 == pos )
    697 {
    698 SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar2, -1) );
    699 }
    700 if( consdata->watchedvar2 == pos )
    701 {
    702 SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar1, -1) );
    703 }
    704 }
    705 assert(pos != consdata->watchedvar1);
    706 assert(pos != consdata->watchedvar2);
    707
    708 /* release variable */
    709 SCIP_CALL( SCIPreleaseVar(scip, &(consdata->vars[pos])) );
    710
    711 /* move the last variable to the free slot */
    712 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
    713 consdata->nvars--;
    714
    715 /* if the last variable (that moved) was watched, update the watched position */
    716 if( consdata->watchedvar1 == consdata->nvars )
    717 consdata->watchedvar1 = pos;
    718 if( consdata->watchedvar2 == consdata->nvars )
    719 consdata->watchedvar2 = pos;
    720
    721 consdata->propagated = FALSE;
    722 consdata->sorted = FALSE;
    723 consdata->changed = TRUE;
    724
    725 return SCIP_OKAY;
    726}
    727
    728/** sorts AND-constraint's variables by non-decreasing variable index */
    729static
    731 SCIP_CONSDATA* consdata /**< constraint data */
    732 )
    733{
    734 assert(consdata != NULL);
    735
    736 if( !consdata->sorted )
    737 {
    738 if( consdata->nvars <= 1 )
    739 consdata->sorted = TRUE;
    740 else
    741 {
    742 SCIP_VAR* var1 = NULL;
    743 SCIP_VAR* var2 = NULL;
    744
    745 /* remember watch variables */
    746 if( consdata->watchedvar1 != -1 )
    747 {
    748 var1 = consdata->vars[consdata->watchedvar1];
    749 assert(var1 != NULL);
    750 consdata->watchedvar1 = -1;
    751 if( consdata->watchedvar2 != -1 )
    752 {
    753 var2 = consdata->vars[consdata->watchedvar2];
    754 assert(var2 != NULL);
    755 consdata->watchedvar2 = -1;
    756 }
    757 }
    758 assert(consdata->watchedvar1 == -1);
    759 assert(consdata->watchedvar2 == -1);
    760 assert(var1 != NULL || var2 == NULL);
    761
    762 /* sort variables after index */
    763 SCIPsortPtr((void**)consdata->vars, SCIPvarComp, consdata->nvars);
    764 consdata->sorted = TRUE;
    765
    766 /* correct watched variables */
    767 if( var1 != NULL )
    768 {
    769 int pos;
    770#ifndef NDEBUG
    771 SCIP_Bool found;
    772
    773 found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var1, consdata->nvars, &pos);
    774 assert(found);
    775#else
    776 (void) SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var1, consdata->nvars, &pos);
    777#endif
    778 assert(pos >= 0 && pos < consdata->nvars);
    779 consdata->watchedvar1 = pos;
    780
    781 if( var2 != NULL )
    782 {
    783#ifndef NDEBUG
    784 found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var2, consdata->nvars, &pos);
    785 assert(found);
    786#else
    787 (void) SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var2, consdata->nvars, &pos);
    788#endif
    789 assert(pos >= 0 && pos < consdata->nvars);
    790 consdata->watchedvar2 = pos;
    791 }
    792 }
    793 }
    794 }
    795
    796#ifdef SCIP_DEBUG
    797 /* check sorting */
    798 {
    799 int v;
    800
    801 for( v = 0; v < consdata->nvars; ++v )
    802 {
    803 assert(v == consdata->nvars-1 || SCIPvarCompare(consdata->vars[v], consdata->vars[v+1]) <= 0);
    804 }
    805 }
    806#endif
    807}
    808
    809/** deletes all one-fixed variables */
    810static
    812 SCIP* scip, /**< SCIP data structure */
    813 SCIP_CONS* cons, /**< AND-constraint */
    814 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    815 int* nchgcoefs /**< pointer to add up the number of changed coefficients */
    816 )
    817{
    818 SCIP_CONSDATA* consdata;
    819 SCIP_VAR* var;
    820 int v;
    821
    822 assert(scip != NULL);
    823 assert(cons != NULL);
    824 assert(eventhdlr != NULL);
    825 assert(nchgcoefs != NULL);
    826
    827 consdata = SCIPconsGetData(cons);
    828 assert(consdata != NULL);
    829 assert(consdata->nvars == 0 || consdata->vars != NULL);
    830
    831 v = 0;
    832 while( v < consdata->nvars )
    833 {
    834 var = consdata->vars[v];
    835 assert(SCIPvarIsBinary(var));
    836
    837 if( SCIPvarGetLbGlobal(var) > 0.5 )
    838 {
    839 assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(var), 1.0));
    840 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    841 (*nchgcoefs)++;
    842 }
    843 else
    844 {
    845 SCIP_VAR* repvar;
    846 SCIP_Bool negated;
    847
    848 /* get binary representative of variable */
    849 SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &repvar, &negated) );
    850
    851 /* check, if the variable should be replaced with the representative */
    852 if( repvar != var )
    853 {
    854 /* delete old (aggregated) variable */
    855 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    856
    857 /* add representative instead */
    858 SCIP_CALL( addCoef(scip, cons, eventhdlr, repvar) );
    859 }
    860 else
    861 ++v;
    862 }
    863 }
    864
    865#ifdef SCIP_DISABLED_CODE /* does not work with pseudoboolean constraint handler, need to be fixed */
    866 /* check, if the resultant should be replaced with the active representative */
    867 if( !SCIPvarIsActive(consdata->resvar) )
    868 {
    869 SCIP_VAR* repvar;
    870 SCIP_Bool negated;
    871
    872 /* get binary representative of variable */
    873 SCIP_CALL( SCIPgetBinvarRepresentative(scip, consdata->resvar, &repvar, &negated) );
    874 assert(SCIPvarIsBinary(repvar));
    875
    876 /* check, if the variable should be replaced with the representative */
    877 if( repvar != consdata->resvar )
    878 {
    879 if( SCIPconsIsTransformed(cons) )
    880 {
    881 /* drop bound change events of old resultant */
    883 eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
    884
    885 /* catch bound change events of new resultant */
    887 eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
    888 }
    889
    890 /* release old resultant */
    891 SCIP_CALL( SCIPreleaseVar(scip, &(consdata->resvar)) );
    892
    893 /* capture new resultant */
    894 SCIP_CALL( SCIPcaptureVar(scip, repvar) );
    895
    896 consdata->resvar = repvar;
    897 consdata->changed = TRUE;
    898 }
    899 }
    900#endif
    901
    902 SCIPdebugMsg(scip, "after fixings: ");
    903 SCIPdebug( SCIP_CALL( consdataPrint(scip, consdata, NULL)) );
    904 SCIPdebugMsgPrint(scip, "\n");
    905
    906 return SCIP_OKAY;
    907}
    908
    909/** creates a linearization of the AND-constraint */
    910static
    912 SCIP* scip, /**< SCIP data structure */
    913 SCIP_CONS* cons /**< constraint to check */
    914 )
    915{
    916 SCIP_CONSDATA* consdata;
    917 char rowname[SCIP_MAXSTRLEN];
    918 int nvars;
    919 int i;
    920
    921 consdata = SCIPconsGetData(cons);
    922 assert(consdata != NULL);
    923 assert(consdata->rows == NULL);
    924
    925 nvars = consdata->nvars;
    926
    927 /* get memory for rows */
    928 consdata->nrows = nvars + 1;
    929 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->rows, consdata->nrows) );
    930
    931 /* creates LP rows corresponding to AND-constraint:
    932 * - one additional row: resvar - v1 - ... - vn >= 1-n
    933 * - for each operator variable vi: resvar - vi <= 0
    934 */
    935
    936 /* create additional row */
    937 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_add", SCIPconsGetName(cons));
    938 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[0], cons, rowname, -consdata->nvars + 1.0, SCIPinfinity(scip),
    940 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[0], consdata->resvar, 1.0) );
    941 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->rows[0], nvars, consdata->vars, -1.0) );
    942
    943 /* create operator rows */
    944 for( i = 0; i < nvars; ++i )
    945 {
    946 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), i);
    947 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[i+1], cons, rowname, -SCIPinfinity(scip), 0.0,
    949 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[i+1], consdata->resvar, 1.0) );
    950 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[i+1], consdata->vars[i], -1.0) );
    951 }
    952
    953 return SCIP_OKAY;
    954}
    955
    956/** adds linear relaxation of AND-constraint to the LP */
    957static
    959 SCIP* scip, /**< SCIP data structure */
    960 SCIP_CONS* cons, /**< constraint to check */
    961 SCIP_Bool* infeasible /**< pointer to store whether an infeasibility was detected */
    962 )
    963{
    964 SCIP_CONSDATA* consdata;
    965
    966 /* in the root LP we only add the weaker relaxation which consists of two rows:
    967 * - one additional row: resvar - v1 - ... - vn >= 1-n
    968 * - aggregated row: n*resvar - v1 - ... - vn <= 0.0
    969 *
    970 * during separation we separate the stronger relaxation which consists of n+1 row:
    971 * - one additional row: resvar - v1 - ... - vn >= 1-n
    972 * - for each operator variable vi: resvar - vi <= 0.0
    973 */
    974
    975 consdata = SCIPconsGetData(cons);
    976 assert(consdata != NULL);
    977
    978 /* create the aggregated row */
    979 if( consdata->aggrrow == NULL )
    980 {
    981 char rowname[SCIP_MAXSTRLEN];
    982
    983 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_operators", SCIPconsGetName(cons));
    984 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->aggrrow, cons, rowname, -SCIPinfinity(scip), 0.0,
    986 SCIP_CALL( SCIPaddVarToRow(scip, consdata->aggrrow, consdata->resvar, (SCIP_Real) consdata->nvars) );
    987 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->aggrrow, consdata->nvars, consdata->vars, -1.0) );
    988 }
    989
    990 /* insert aggregated LP row as cut */
    991 if( !SCIProwIsInLP(consdata->aggrrow) )
    992 {
    993 SCIP_CALL( SCIPaddRow(scip, consdata->aggrrow, FALSE, infeasible) );
    994 }
    995
    996 if( !(*infeasible) )
    997 {
    998 if( consdata->rows == NULL )
    999 {
    1000 /* create the n+1 row relaxation */
    1002 }
    1003
    1004 assert(consdata->rows != NULL);
    1005
    1006 /* add additional row */
    1007 if( !SCIProwIsInLP(consdata->rows[0]) )
    1008 {
    1009 SCIP_CALL( SCIPaddRow(scip, consdata->rows[0], FALSE, infeasible) );
    1010 }
    1011 }
    1012
    1013 return SCIP_OKAY;
    1014}
    1015
    1016/** adds constraint as row to the NLP, if not added yet */
    1017static
    1019 SCIP* scip, /**< SCIP data structure */
    1020 SCIP_CONS* cons /**< and constraint */
    1021 )
    1022{
    1023 SCIP_CONSDATA* consdata;
    1024
    1025 assert(SCIPisNLPConstructed(scip));
    1026
    1027 /* skip deactivated, redundant, or local constraints (the NLP does not allow for local rows at the moment) */
    1028 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
    1029 return SCIP_OKAY;
    1030
    1031 consdata = SCIPconsGetData(cons);
    1032 assert(consdata != NULL);
    1033 assert(consdata->resvar != NULL);
    1034
    1035 if( consdata->nlrow == NULL )
    1036 {
    1037 SCIP_EXPR* expr;
    1038 SCIP_EXPR** varexprs;
    1039 SCIP_Real minusone = -1.0;
    1040 int i;
    1041
    1042 SCIP_CALL( SCIPallocBufferArray(scip, &varexprs, consdata->nvars) );
    1043 for( i = 0; i < consdata->nvars; ++i )
    1044 {
    1045 SCIP_CALL( SCIPcreateExprVar(scip, &varexprs[i], consdata->vars[i], NULL, NULL) );
    1046 }
    1047 SCIP_CALL( SCIPcreateExprProduct(scip, &expr, consdata->nvars, varexprs, 1.0, NULL, NULL) );
    1048
    1049 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
    1050 0.0, 1, &consdata->resvar, &minusone, expr, 0.0, 0.0, SCIP_EXPRCURV_UNKNOWN) );
    1051 assert(consdata->nlrow != NULL);
    1052
    1053 SCIP_CALL( SCIPreleaseExpr(scip, &expr) );
    1054 for( i = 0; i < consdata->nvars; ++i )
    1055 {
    1056 SCIP_CALL( SCIPreleaseExpr(scip, &varexprs[i]) );
    1057 }
    1058 SCIPfreeBufferArray(scip, &varexprs);
    1059 }
    1060
    1061 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
    1062 {
    1063 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
    1064 }
    1065
    1066 return SCIP_OKAY;
    1067}
    1068
    1069/** checks AND-constraint for feasibility of given solution: returns TRUE iff constraint is feasible */
    1070static
    1072 SCIP* scip, /**< SCIP data structure */
    1073 SCIP_CONS* cons, /**< constraint to check */
    1074 SCIP_SOL* sol, /**< solution to check, NULL for current solution */
    1075 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
    1076 SCIP_Bool printreason, /**< Should the reason for the violation be printed? */
    1077 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
    1078 )
    1079{
    1080 SCIP_CONSDATA* consdata;
    1081 SCIP_Bool mustcheck;
    1082 int r;
    1083
    1084 assert(violated != NULL);
    1085
    1086 consdata = SCIPconsGetData(cons);
    1087 assert(consdata != NULL);
    1088
    1089 *violated = FALSE;
    1090
    1091 /* check whether we can skip this feasibility check, because all rows are in the LP and do not have to be checked */
    1092 mustcheck = checklprows;
    1093 mustcheck = mustcheck || (consdata->rows == NULL);
    1094 if( !mustcheck )
    1095 {
    1096 assert(consdata->rows != NULL);
    1097
    1098 for( r = 0; r < consdata->nrows; ++r )
    1099 {
    1100 mustcheck = !SCIProwIsInLP(consdata->rows[r]);
    1101 if( mustcheck )
    1102 break;
    1103 }
    1104 }
    1105
    1106 /* check feasibility of constraint if necessary */
    1107 if( mustcheck )
    1108 {
    1109 SCIP_Real minsolval = 1.0;
    1110 SCIP_Real sumsolval = 0.0;
    1111 SCIP_Real solval;
    1112 SCIP_Real viol;
    1113 int minsolind = 0;
    1114 int i;
    1115
    1116 /* increase age of constraint; age is reset to zero, if a violation was found only in case we are in
    1117 * enforcement
    1118 */
    1119 if( sol == NULL )
    1120 {
    1121 SCIP_CALL( SCIPincConsAge(scip, cons) );
    1122 }
    1123
    1124 /* evaluate operator variables */
    1125 for( i = 0; i < consdata->nvars; ++i )
    1126 {
    1127 solval = SCIPgetSolVal(scip, sol, consdata->vars[i]);
    1128
    1129 if( minsolval > solval )
    1130 {
    1131 minsolind = i;
    1132 minsolval = solval;
    1133 }
    1134
    1135 sumsolval += solval;
    1136 }
    1137
    1138 /* the resultant must be at most as large as every operator
    1139 * and at least as large as one minus the sum of negated operators
    1140 */
    1141 solval = SCIPgetSolVal(scip, sol, consdata->resvar);
    1142 viol = MAX3(0.0, solval - minsolval, sumsolval - (consdata->nvars - 1.0 + solval));
    1143
    1144 if( SCIPisFeasPositive(scip, viol) )
    1145 {
    1146 *violated = TRUE;
    1147
    1148 /* only reset constraint age if we are in enforcement */
    1149 if( sol == NULL )
    1150 {
    1152 }
    1153
    1154 if( printreason )
    1155 {
    1156 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
    1157 SCIPinfoMessage(scip, NULL, ";\n");
    1158 SCIPinfoMessage(scip, NULL, "violation:");
    1159
    1160 if( SCIPisFeasPositive(scip, solval - minsolval) )
    1161 {
    1162 SCIPinfoMessage(scip, NULL, " operand <%s> = FALSE and resultant <%s> = TRUE\n",
    1163 SCIPvarGetName(consdata->vars[minsolind]), SCIPvarGetName(consdata->resvar));
    1164 }
    1165 else
    1166 {
    1167 SCIPinfoMessage(scip, NULL, " all operands are TRUE and resultant <%s> = FALSE\n",
    1168 SCIPvarGetName(consdata->resvar));
    1169 }
    1170 }
    1171 }
    1172
    1173 /* update constraint violation in solution */
    1174 if( sol != NULL )
    1175 SCIPupdateSolConsViolation(scip, sol, viol, viol);
    1176 }
    1177
    1178 return SCIP_OKAY;
    1179}
    1180
    1181/** separates given primal solution */
    1182static
    1184 SCIP* scip, /**< SCIP data structure */
    1185 SCIP_CONS* cons, /**< constraint to check */
    1186 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
    1187 SCIP_Bool* separated, /**< pointer to store whether a cut was found */
    1188 SCIP_Bool* cutoff /**< whether a cutoff has been detected */
    1189 )
    1190{
    1191 SCIP_CONSDATA* consdata;
    1192 SCIP_Real feasibility;
    1193 int r;
    1194
    1195 assert(separated != NULL);
    1196 assert(cutoff != NULL);
    1197
    1198 *separated = FALSE;
    1199 *cutoff = FALSE;
    1200
    1201 consdata = SCIPconsGetData(cons);
    1202 assert(consdata != NULL);
    1203
    1204 /* create all necessary rows for the linear relaxation */
    1205 if( consdata->rows == NULL )
    1206 {
    1208 }
    1209 assert(consdata->rows != NULL);
    1210
    1211 /* test all rows for feasibility and add infeasible rows */
    1212 for( r = 0; r < consdata->nrows; ++r )
    1213 {
    1214 if( !SCIProwIsInLP(consdata->rows[r]) )
    1215 {
    1216 feasibility = SCIPgetRowSolFeasibility(scip, consdata->rows[r], sol);
    1217 if( SCIPisFeasNegative(scip, feasibility) )
    1218 {
    1219 SCIP_CALL( SCIPaddRow(scip, consdata->rows[r], FALSE, cutoff) );
    1220 if ( *cutoff )
    1221 return SCIP_OKAY;
    1222 *separated = TRUE;
    1223 }
    1224 }
    1225 }
    1226
    1227 return SCIP_OKAY;
    1228}
    1229
    1230/** analyzes conflicting TRUE assignment to resultant of given constraint, and adds conflict constraint to problem */
    1231static
    1233 SCIP* scip, /**< SCIP data structure */
    1234 SCIP_CONS* cons, /**< AND-constraint that detected the conflict */
    1235 int falsepos /**< position of operand that is fixed to FALSE */
    1236 )
    1237{
    1238 SCIP_CONSDATA* consdata;
    1239
    1240 /* conflict analysis can only be applied in solving stage and if it turned on */
    1242 return SCIP_OKAY;
    1243
    1244 consdata = SCIPconsGetData(cons);
    1245 assert(consdata != NULL);
    1246 assert(SCIPvarGetLbLocal(consdata->resvar) > 0.5);
    1247 assert(0 <= falsepos && falsepos < consdata->nvars);
    1248 assert(SCIPvarGetUbLocal(consdata->vars[falsepos]) < 0.5);
    1249
    1250 /* initialize conflict analysis, and add resultant and single operand variable to conflict candidate queue */
    1252
    1253 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
    1254 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[falsepos]) );
    1255
    1256 /* analyze the conflict */
    1258
    1259 return SCIP_OKAY;
    1260}
    1261
    1262/** analyzes conflicting FALSE assignment to resultant of given constraint, and adds conflict constraint to problem */
    1263static
    1265 SCIP* scip, /**< SCIP data structure */
    1266 SCIP_CONS* cons /**< or constraint that detected the conflict */
    1267 )
    1268{
    1269 SCIP_CONSDATA* consdata;
    1270 int v;
    1271
    1272 assert(!SCIPconsIsModifiable(cons));
    1273
    1274 /* conflict analysis can only be applied in solving stage and if it is applicable */
    1276 return SCIP_OKAY;
    1277
    1278 consdata = SCIPconsGetData(cons);
    1279 assert(consdata != NULL);
    1280 assert(SCIPvarGetUbLocal(consdata->resvar) < 0.5);
    1281
    1282 /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
    1284
    1285 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
    1286 for( v = 0; v < consdata->nvars; ++v )
    1287 {
    1288 assert(SCIPvarGetLbLocal(consdata->vars[v]) > 0.5);
    1289 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
    1290 }
    1291
    1292 /* analyze the conflict */
    1294
    1295 return SCIP_OKAY;
    1296}
    1297
    1298/** tries to fix the given resultant to zero */
    1299static
    1301 SCIP* scip, /**< SCIP data structure */
    1302 SCIP_CONS* cons, /**< AND-constraint to be processed */
    1303 SCIP_VAR* resvar, /**< resultant variable to fix to zero */
    1304 int pos, /**< position of operand that is fixed to FALSE */
    1305 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    1306 int* nfixedvars /**< pointer to add up the number of found domain reductions */
    1307 )
    1308{
    1309 SCIP_Bool infeasible;
    1310 SCIP_Bool tightened;
    1311
    1312 SCIPdebugMsg(scip, "constraint <%s>: operator %d fixed to 0.0 -> fix resultant <%s> to 0.0\n",
    1313 SCIPconsGetName(cons), pos, SCIPvarGetName(resvar));
    1314
    1315 SCIP_CALL( SCIPinferBinvarCons(scip, resvar, FALSE, cons, (int)PROPRULE_1, &infeasible, &tightened) );
    1316
    1317 if( infeasible )
    1318 {
    1319 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
    1320 SCIP_CALL( analyzeConflictOne(scip, cons, pos) );
    1322 (*cutoff) = TRUE;
    1323 }
    1324 else
    1325 {
    1327 if( tightened )
    1328 {
    1330 (*nfixedvars)++;
    1331 }
    1332 }
    1333
    1334 return SCIP_OKAY;
    1335}
    1336
    1337/** fix all operands to one */
    1338static
    1340 SCIP* scip, /**< SCIP data structure */
    1341 SCIP_CONS* cons, /**< AND-constraint to be processed */
    1342 SCIP_VAR** vars, /**< array of operands */
    1343 int nvars, /**< number of operands */
    1344 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    1345 int* nfixedvars /**< pointer to add up the number of found domain reductions */
    1346 )
    1347{
    1348 SCIP_Bool infeasible;
    1349 SCIP_Bool tightened;
    1350 int v;
    1351
    1352 for( v = 0; v < nvars && !(*cutoff); ++v )
    1353 {
    1354 SCIPdebugMsg(scip, "constraint <%s>: resultant fixed to 1.0 -> fix operator var <%s> to 1.0\n",
    1355 SCIPconsGetName(cons), SCIPvarGetName(vars[v]));
    1356
    1357 SCIP_CALL( SCIPinferBinvarCons(scip, vars[v], TRUE, cons, (int)PROPRULE_2, &infeasible, &tightened) );
    1358
    1359 if( infeasible )
    1360 {
    1361 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
    1362 SCIP_CALL( analyzeConflictOne(scip, cons, v) );
    1364 (*cutoff) = TRUE;
    1365 }
    1366 else if( tightened )
    1367 {
    1369 (*nfixedvars)++;
    1370 }
    1371 }
    1372
    1373 if( !(*cutoff) )
    1374 {
    1376 }
    1377
    1378 return SCIP_OKAY;
    1379}
    1380
    1381/** linearize AND-constraint due to a globally to zero fixed resultant; that is, creates, adds, and releases a logicor
    1382 * constraint and remove the AND-constraint globally.
    1383 *
    1384 * Since the resultant is fixed to zero the AND-constraint collapses to linear constraint of the form:
    1385 *
    1386 * - \f$\sum_{i=0}^{n-1} v_i \leq n-1\f$
    1387 *
    1388 * This can be transformed into a logicor constraint of the form
    1389 *
    1390 * - \f$\sum_{i=0}^{n-1} ~v_i \geq 1\f$
    1391 */
    1392static
    1394 SCIP* scip, /**< SCIP data structure */
    1395 SCIP_CONS* cons, /**< AND-constraint to linearize */
    1396 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    1397 int* nfixedvars, /**< pointer to add up the number of found domain reductions */
    1398 int* nupgdconss /**< pointer to add up the number of upgraded constraints */
    1399 )
    1400{
    1401 SCIP_CONSDATA* consdata;
    1402 SCIP_VAR** vars;
    1403 SCIP_CONS* lincons;
    1404 SCIP_Bool conscreated;
    1405 int nvars;
    1406
    1407 consdata = SCIPconsGetData(cons);
    1408 assert(consdata != NULL);
    1409
    1410 assert(!(*cutoff));
    1411 assert(SCIPvarGetUbGlobal(consdata->resvar) < 0.5);
    1412
    1413 nvars = consdata->nvars;
    1414 conscreated = FALSE;
    1415
    1416 /* allocate memory for variables for updated constraint */
    1417 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    1418
    1419 /* if we only have two variables, we prefer a set packing constraint instead of a logicor constraint */
    1420 if( nvars == 2 && !SCIPconsIsModifiable(cons) )
    1421 {
    1422 SCIP_Bool* negated;
    1423 SCIP_Bool infeasible;
    1424 SCIP_Bool tightened;
    1425
    1426 /* get active representation */
    1427 SCIP_CALL( SCIPallocBufferArray(scip, &negated, nvars) );
    1428 SCIP_CALL( SCIPgetBinvarRepresentatives(scip, nvars, consdata->vars, vars, negated) );
    1429 SCIPfreeBufferArray(scip, &negated);
    1430
    1431 /* if one of the two operators is globally fixed to one it follows that the other has to be zero */
    1432 if( SCIPvarGetLbGlobal(vars[0]) > 0.5 )
    1433 {
    1434 SCIP_CALL( SCIPfixVar(scip, vars[1], 0.0, &infeasible, &tightened) );
    1435
    1436 if( infeasible )
    1437 *cutoff = TRUE;
    1438 else if( tightened )
    1439 ++(*nfixedvars);
    1440 }
    1441 else if( SCIPvarGetLbGlobal(vars[1]) > 0.5 )
    1442 {
    1443 SCIP_CALL( SCIPfixVar(scip, vars[0], 0.0, &infeasible, &tightened) );
    1444
    1445 if( infeasible )
    1446 *cutoff = TRUE;
    1447 else if( tightened )
    1448 ++(*nfixedvars);
    1449 }
    1450 else if( SCIPvarGetUbGlobal(vars[0]) > 0.5 && SCIPvarGetUbGlobal(vars[1]) > 0.5 )
    1451 {
    1452 /* create, add, and release the setppc constraint */
    1453 SCIP_CALL( SCIPcreateConsSetpack(scip, &lincons, SCIPconsGetName(cons), nvars, vars,
    1457 SCIPconsIsStickingAtNode(cons)) );
    1458
    1459 conscreated = TRUE;
    1460 }
    1461 }
    1462 else
    1463 {
    1464 int v;
    1465
    1466 /* collect negated variables */
    1467 for( v = 0; v < nvars; ++v )
    1468 {
    1469 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[v], &vars[v]) );
    1470 }
    1471
    1472 /* create, add, and release the logicor constraint */
    1473 SCIP_CALL( SCIPcreateConsLogicor(scip, &lincons, SCIPconsGetName(cons), nvars, vars,
    1477 SCIPconsIsStickingAtNode(cons)) );
    1478
    1479 conscreated = TRUE;
    1480 }
    1481
    1482 if( conscreated )
    1483 {
    1484 /* add and release new constraint */
    1485 SCIPdebugPrintCons(scip, lincons, NULL); /*lint !e644*/
    1486 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &lincons) );
    1487 ++(*nupgdconss);
    1488 }
    1489
    1490 /* remove the AND-constraint globally */
    1491 SCIP_CALL( SCIPdelCons(scip, cons) );
    1492
    1493 /* delete temporary memory */
    1494 SCIPfreeBufferArray(scip, &vars);
    1495
    1496 return SCIP_OKAY;
    1497}
    1498
    1499/** the resultant is fixed to zero; in case all except one operator are fixed to TRUE the last operator has to fixed to FALSE */
    1500/** @note consdata->watchedvars might not be the same to the watchedvar parameters, because the update was not yet done */
    1501static
    1503 SCIP* scip, /**< SCIP data structure */
    1504 SCIP_CONS* cons, /**< AND-constraint to be processed */
    1505 int watchedvar1, /**< maybe last unfixed variable position */
    1506 int watchedvar2, /**< second watched position */
    1507 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    1508 int* nfixedvars /**< pointer to add up the number of found domain reductions */
    1509 )
    1510{
    1511 SCIP_CONSDATA* consdata;
    1512
    1513 consdata = SCIPconsGetData(cons);
    1514 assert(consdata != NULL);
    1515 assert(SCIPvarGetUbLocal(consdata->resvar) < 0.5);
    1516
    1517 if( watchedvar2 == -1 )
    1518 {
    1519 SCIP_Bool infeasible;
    1520 SCIP_Bool tightened;
    1521
    1522 assert(watchedvar1 != -1);
    1523
    1524#ifndef NDEBUG
    1525 /* check that all variables regardless of wathcedvar1 are fixed to 1 */
    1526 {
    1527 int v;
    1528
    1529 for( v = consdata->nvars - 1; v >= 0; --v )
    1530 if( v != watchedvar1 )
    1531 assert(SCIPvarGetLbLocal(consdata->vars[v]) > 0.5);
    1532 }
    1533#endif
    1534
    1535 SCIPdebugMsg(scip, "constraint <%s>: resultant <%s> fixed to 0.0, only one unfixed operand -> fix operand <%s> to 0.0\n",
    1536 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar), SCIPvarGetName(consdata->vars[watchedvar1]));
    1537
    1538 SCIP_CALL( SCIPinferBinvarCons(scip, consdata->vars[watchedvar1], FALSE, cons, (int)PROPRULE_4, &infeasible, &tightened) );
    1539
    1540 if( infeasible )
    1541 {
    1542 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
    1545 *cutoff = TRUE;
    1546 }
    1547 else
    1548 {
    1550 if( tightened )
    1551 {
    1553 (*nfixedvars)++;
    1554 }
    1555 }
    1556 }
    1557
    1558 return SCIP_OKAY;
    1559}
    1560
    1561/** replaces multiple occurrences of variables */
    1562static
    1564 SCIP* scip, /**< SCIP data structure */
    1565 SCIP_CONS* cons, /**< AND-constraint */
    1566 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    1567 unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
    1568 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
    1569 int* nfixedvars, /**< pointer to store number of fixed variables */
    1570 int* nchgcoefs, /**< pointer to store number of changed coefficients */
    1571 int* ndelconss /**< pointer to store number of deleted constraints */
    1572 )
    1573{
    1574 SCIP_CONSDATA* consdata;
    1575 SCIP_VAR** vars;
    1576 SCIP_VAR* var;
    1577 SCIP_VAR* probvar;
    1578 int probidx;
    1579 int nvars;
    1580 int v;
    1581#ifndef NDEBUG
    1582 int nbinvars;
    1583 int nintvars;
    1584 int nimplvars;
    1585#endif
    1586
    1587 assert(scip != NULL);
    1588 assert(cons != NULL);
    1589 assert(eventhdlr != NULL);
    1590 assert(*entries != NULL);
    1591 assert(nentries != NULL);
    1592 assert(nfixedvars != NULL);
    1593 assert(nchgcoefs != NULL);
    1594 assert(ndelconss != NULL);
    1595
    1596 consdata = SCIPconsGetData(cons);
    1597 assert(consdata != NULL);
    1598
    1599 if( consdata->merged )
    1600 return SCIP_OKAY;
    1601
    1602 /* nothing to merge */
    1603 if( consdata->nvars <= 1 )
    1604 {
    1605 consdata->merged = TRUE;
    1606 return SCIP_OKAY;
    1607 }
    1608
    1609 vars = consdata->vars;
    1610 nvars = consdata->nvars;
    1611
    1612 assert(vars != NULL);
    1613 assert(nvars >= 2);
    1614
    1615#ifndef NDEBUG
    1616 nbinvars = SCIPgetNBinVars(scip);
    1617 nintvars = SCIPgetNIntVars(scip);
    1618 nimplvars = SCIPgetNImplVars(scip);
    1619 assert(*nentries >= nbinvars + nintvars + nimplvars);
    1620#endif
    1621
    1622 /* initialize entries array */
    1623 for( v = nvars - 1; v >= 0; --v )
    1624 {
    1625 var = vars[v];
    1626 assert(var != NULL);
    1628
    1629 probvar = (SCIPvarIsActive(var) ? var : SCIPvarGetNegatedVar(var));
    1630 assert(probvar != NULL);
    1631
    1632 probidx = SCIPvarGetProbindex(probvar);
    1633 assert(0 <= probidx);
    1634
    1635 /* check variable type, either pure binary or an integer/implicit integer variable with 0/1 bounds */
    1636 assert((probidx < nbinvars && SCIPvarGetType(probvar) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(probvar))
    1637 || (SCIPvarIsBinary(probvar) &&
    1638 ((probidx >= nbinvars && probidx < nbinvars + nintvars && SCIPvarGetType(probvar) == SCIP_VARTYPE_INTEGER
    1639 && !SCIPvarIsImpliedIntegral(probvar)) ||
    1640 (probidx >= nbinvars + nintvars && probidx < nbinvars + nintvars + nimplvars &&
    1641 SCIPvarIsImpliedIntegral(probvar)))));
    1642
    1643 /* var is not active yet */
    1644 (*entries)[probidx] = 0;
    1645 }
    1646
    1647 /* search for multiple variables; scan from back to front because deletion doesn't affect the order of the front
    1648 * variables
    1649 * @note don't reorder variables because we would loose the watched variables and filter position inforamtion
    1650 */
    1651 for( v = nvars - 1; v >= 0; --v )
    1652 {
    1653 var = vars[v];
    1654 assert(var != NULL);
    1656
    1657 probvar = (SCIPvarIsActive(var) ? var : SCIPvarGetNegatedVar(var));
    1658 assert(probvar != NULL);
    1659
    1660 probidx = SCIPvarGetProbindex(probvar);
    1661 assert(0 <= probidx && probidx < *nentries);
    1662
    1663 /* if var occurs first time in constraint init entries array */
    1664 if( (*entries)[probidx] == 0 )
    1665 {
    1666 (*entries)[probidx] = (SCIPvarIsActive(var) ? 1 : 2);
    1667 }
    1668 /* if var occurs second time in constraint, first time it was not negated */
    1669 else if( ((*entries)[probidx] == 1 && SCIPvarIsActive(var)) || ((*entries)[probidx] == 2 && !SCIPvarIsActive(var)) )
    1670 {
    1671 /* delete the multiple variable */
    1672 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    1673 ++(*nchgcoefs);
    1674 }
    1675 else
    1676 {
    1677 SCIP_Bool infeasible;
    1678 SCIP_Bool fixed;
    1679
    1680 assert(((*entries)[probidx] == 1 && !SCIPvarIsActive(var)) || ((*entries)[probidx] == 2 && SCIPvarIsActive(var)));
    1681
    1682 SCIPdebugMsg(scip, "AND-constraint <%s> is redundant: variable <%s> and its negation are present -> fix resultant <%s> = 0\n",
    1683 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(consdata->resvar));
    1684
    1685 /* negation of the variable is already present in the constraint: fix resultant to zero */
    1686#ifndef NDEBUG
    1687 {
    1688 int i;
    1689 for( i = consdata->nvars - 1; i > v && var != SCIPvarGetNegatedVar(vars[i]); --i )
    1690 {}
    1691 assert(i > v);
    1692 }
    1693#endif
    1694
    1695 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
    1696 assert(!infeasible);
    1697 if( fixed )
    1698 ++(*nfixedvars);
    1699
    1700 SCIP_CALL( SCIPdelCons(scip, cons) );
    1701 break;
    1702 }
    1703 }
    1704
    1705 consdata->merged = TRUE;
    1706
    1707 return SCIP_OKAY;
    1708}
    1709
    1710/** propagates constraint with the following rules:
    1711 * (1) v_i = FALSE => r = FALSE
    1712 * (2) r = TRUE => v_i = TRUE for all i
    1713 * (3) v_i = TRUE for all i => r = TRUE
    1714 * (4) r = FALSE, v_i = TRUE for all i except j => v_j = FALSE
    1715 *
    1716 * additional if the resultant is fixed to zero during presolving or in the root node (globally), then the
    1717 * AND-constraint is collapsed to a linear (logicor) constraint of the form
    1718 * -> sum_{i=0}^{n-1} ~v_i >= 1
    1719 */
    1720static
    1722 SCIP* scip, /**< SCIP data structure */
    1723 SCIP_CONS* cons, /**< AND-constraint to be processed */
    1724 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    1725 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    1726 int* nfixedvars, /**< pointer to add up the number of found domain reductions */
    1727 int* nupgdconss /**< pointer to add up the number of upgraded constraints */
    1728 )
    1729{
    1730 SCIP_CONSDATA* consdata;
    1731 SCIP_VAR* resvar;
    1732 SCIP_VAR** vars;
    1733 int nvars;
    1734 int watchedvar1;
    1735 int watchedvar2;
    1736 int i;
    1737 SCIP_Bool infeasible;
    1738 SCIP_Bool tightened;
    1739
    1740 assert(cutoff != NULL);
    1741 assert(nfixedvars != NULL);
    1742
    1743 consdata = SCIPconsGetData(cons);
    1744 assert(consdata != NULL);
    1745
    1746 resvar = consdata->resvar;
    1747 vars = consdata->vars;
    1748 nvars = consdata->nvars;
    1749
    1750 /* don't process the constraint, if none of the operator variables was fixed to FALSE, and if the watched variables
    1751 * and the resultant weren't fixed to any value since last propagation call
    1752 */
    1753 if( consdata->propagated )
    1754 {
    1755 assert(consdata->nofixedzero);
    1756 assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(resvar), 0.0));
    1757 return SCIP_OKAY;
    1758 }
    1759
    1760 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
    1762 {
    1763 SCIP_CALL( SCIPincConsAge(scip, cons) );
    1764 }
    1765
    1766 /* if one of the operator variables was fixed to FALSE, the resultant can be fixed to FALSE (rule (1)) */
    1767 if( !consdata->nofixedzero )
    1768 {
    1769 for( i = 0; i < nvars && SCIPvarGetUbLocal(vars[i]) > 0.5; ++i ) /* search for operator fixed to zero */
    1770 {}
    1771 if( i < nvars )
    1772 {
    1773 /* fix resultant to zero */
    1774 SCIP_CALL( consdataFixResultantZero(scip, cons, resvar, i, cutoff, nfixedvars) );
    1775 }
    1776 else
    1777 consdata->nofixedzero = TRUE;
    1778 }
    1779
    1780 /* check if resultant variables is globally fixed to zero */
    1781 if( !SCIPinProbing(scip) && SCIPconsGetNUpgradeLocks(cons) == 0 && SCIPvarGetUbGlobal(resvar) < 0.5 )
    1782 {
    1783 SCIP_CALL( consdataLinearize(scip, cons, cutoff, nfixedvars, nupgdconss) );
    1784
    1785 if( *cutoff && SCIPgetDepth(scip) > 0 )
    1786 {
    1787 /* we are done with solving since a global bound change was infeasible */
    1789 }
    1790
    1791 return SCIP_OKAY;
    1792 }
    1793
    1794 /* if the resultant and at least one operand are locally fixed to zero, the constraint is locally redundant */
    1795 if( SCIPvarGetUbLocal(resvar) < 0.5 && !consdata->nofixedzero )
    1796 {
    1798 return SCIP_OKAY;
    1799 }
    1800
    1801 /* if resultant is fixed to TRUE, all operator variables can be fixed to TRUE (rule (2)) */
    1802 if( SCIPvarGetLbLocal(resvar) > 0.5 )
    1803 {
    1804 /* fix operands to one */
    1805 SCIP_CALL( consdataFixOperandsOne(scip, cons, vars, nvars, cutoff, nfixedvars) );
    1806
    1807 return SCIP_OKAY;
    1808 }
    1809
    1810 /* rules (3) and (4) can only be applied, if we know all operator variables */
    1811 if( SCIPconsIsModifiable(cons) )
    1812 return SCIP_OKAY;
    1813
    1814 /* rules (3) and (4) cannot be applied, if we have at least two unfixed variables left;
    1815 * that means, we only have to watch (i.e. capture events) of two variables, and switch to other variables
    1816 * if these ones get fixed
    1817 */
    1818 watchedvar1 = consdata->watchedvar1;
    1819 watchedvar2 = consdata->watchedvar2;
    1820
    1821 /* check, if watched variables are still unfixed */
    1822 if( watchedvar1 != -1 )
    1823 {
    1824 assert(SCIPvarGetUbLocal(vars[watchedvar1]) > 0.5); /* otherwise, rule (1) could be applied */
    1825 if( SCIPvarGetLbLocal(vars[watchedvar1]) > 0.5 )
    1826 watchedvar1 = -1;
    1827 }
    1828 if( watchedvar2 != -1 )
    1829 {
    1830 assert(SCIPvarGetUbLocal(vars[watchedvar2]) > 0.5); /* otherwise, rule (1) could be applied */
    1831 if( SCIPvarGetLbLocal(vars[watchedvar2]) > 0.5 )
    1832 watchedvar2 = -1;
    1833 }
    1834
    1835 /* if only one watched variable is still unfixed, make it the first one */
    1836 if( watchedvar1 == -1 )
    1837 {
    1838 watchedvar1 = watchedvar2;
    1839 watchedvar2 = -1;
    1840 }
    1841 assert(watchedvar1 != -1 || watchedvar2 == -1);
    1842
    1843 /* if the watched variables are invalid (fixed), find new ones if existing */
    1844 if( watchedvar2 == -1 )
    1845 {
    1846 for( i = 0; i < nvars; ++i )
    1847 {
    1848 assert(SCIPvarGetUbLocal(vars[i]) > 0.5); /* otherwise, rule (1) could be applied */
    1849 if( SCIPvarGetLbLocal(vars[i]) < 0.5 )
    1850 {
    1851 if( watchedvar1 == -1 )
    1852 {
    1853 assert(watchedvar2 == -1);
    1854 watchedvar1 = i;
    1855 }
    1856 else if( watchedvar1 != i )
    1857 {
    1858 watchedvar2 = i;
    1859 break;
    1860 }
    1861 }
    1862 }
    1863 }
    1864 assert(watchedvar1 != -1 || watchedvar2 == -1);
    1865
    1866 /* if all variables are fixed to TRUE, the resultant can also be fixed to TRUE (rule (3)) */
    1867 if( watchedvar1 == -1 )
    1868 {
    1869 assert(watchedvar2 == -1);
    1870
    1871 SCIPdebugMsg(scip, "constraint <%s>: all operator vars fixed to 1.0 -> fix resultant <%s> to 1.0\n",
    1872 SCIPconsGetName(cons), SCIPvarGetName(resvar));
    1873 SCIP_CALL( SCIPinferBinvarCons(scip, resvar, TRUE, cons, (int)PROPRULE_3, &infeasible, &tightened) );
    1874
    1875 if( infeasible )
    1876 {
    1877 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
    1880 *cutoff = TRUE;
    1881 }
    1882 else
    1883 {
    1885 if( tightened )
    1886 {
    1888 (*nfixedvars)++;
    1889 }
    1890 }
    1891
    1892 return SCIP_OKAY;
    1893 }
    1894
    1895 /* if resultant is fixed to FALSE, and only one operator variable is not fixed to TRUE, this operator variable
    1896 * can be fixed to FALSE (rule (4))
    1897 */
    1898 if( watchedvar2 == -1 && SCIPvarGetUbLocal(resvar) < 0.5 )
    1899 {
    1900 assert(watchedvar1 != -1);
    1901
    1902 SCIP_CALL( analyzeZeroResultant(scip, cons, watchedvar1, watchedvar2, cutoff, nfixedvars) );
    1903
    1904 return SCIP_OKAY;
    1905 }
    1906
    1907 /* switch to the new watched variables */
    1908 SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, watchedvar1, watchedvar2) );
    1909
    1910 /* mark the constraint propagated if we have an unfixed resultant or are not in probing, it is necessary that a fixed
    1911 * resulting in probing mode does not lead to a propagated constraint, because the constraint upgrade needs to be performed
    1912 */
    1913 consdata->propagated = (!SCIPinProbing(scip) || (SCIPvarGetLbLocal(consdata->resvar) < 0.5 && SCIPvarGetUbLocal(consdata->resvar) > 0.5));
    1914
    1915 return SCIP_OKAY;
    1916}
    1917
    1918/** resolves a conflict on the given variable by supplying the variables needed for applying the corresponding
    1919 * propagation rule (see propagateCons()):
    1920 * (1) v_i = FALSE => r = FALSE
    1921 * (2) r = TRUE => v_i = TRUE for all i
    1922 * (3) v_i = TRUE for all i => r = TRUE
    1923 * (4) r = FALSE, v_i = TRUE for all i except j => v_j = FALSE
    1924 */
    1925static
    1927 SCIP* scip, /**< SCIP data structure */
    1928 SCIP_CONS* cons, /**< constraint that inferred the bound change */
    1929 SCIP_VAR* infervar, /**< variable that was deduced */
    1930 PROPRULE proprule, /**< propagation rule that deduced the value */
    1931 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
    1932 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
    1933 )
    1934{
    1935 SCIP_CONSDATA* consdata;
    1936 SCIP_VAR** vars;
    1937 int nvars;
    1938 int i;
    1939
    1940 assert(result != NULL);
    1941
    1942 consdata = SCIPconsGetData(cons);
    1943 assert(consdata != NULL);
    1944 vars = consdata->vars;
    1945 nvars = consdata->nvars;
    1946
    1947 switch( proprule )
    1948 {
    1949 case PROPRULE_1:
    1950 /* the resultant was inferred to FALSE, because one operand variable was FALSE */
    1951 assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
    1952 assert(infervar == consdata->resvar);
    1953 for( i = 0; i < nvars; ++i )
    1954 {
    1955 if( SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) < 0.5 )
    1956 {
    1958 break;
    1959 }
    1960 }
    1961 assert(i < nvars);
    1962 *result = SCIP_SUCCESS;
    1963 break;
    1964
    1965 case PROPRULE_2:
    1966 /* the operand variable was inferred to TRUE, because the resultant was TRUE */
    1967 assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5);
    1968 assert(SCIPgetVarLbAtIndex(scip, consdata->resvar, bdchgidx, FALSE) > 0.5);
    1969 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
    1970 *result = SCIP_SUCCESS;
    1971 break;
    1972
    1973 case PROPRULE_3:
    1974 /* the resultant was inferred to TRUE, because all operand variables were TRUE */
    1975 assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5);
    1976 assert(infervar == consdata->resvar);
    1977 for( i = 0; i < nvars; ++i )
    1978 {
    1979 assert(SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) > 0.5);
    1981 }
    1982 *result = SCIP_SUCCESS;
    1983 break;
    1984
    1985 case PROPRULE_4:
    1986 /* the operand variable was inferred to FALSE, because the resultant was FALSE and all other operands were TRUE */
    1987 assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
    1988 assert(SCIPgetVarUbAtIndex(scip, consdata->resvar, bdchgidx, FALSE) < 0.5);
    1989 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
    1990 for( i = 0; i < nvars; ++i )
    1991 {
    1992 if( vars[i] != infervar )
    1993 {
    1994 assert(SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) > 0.5);
    1996 }
    1997 }
    1998 *result = SCIP_SUCCESS;
    1999 break;
    2000
    2001 case PROPRULE_INVALID:
    2002 default:
    2003 SCIPerrorMessage("invalid inference information %d in AND-constraint <%s>\n", proprule, SCIPconsGetName(cons));
    2004 return SCIP_INVALIDDATA;
    2005 }
    2006
    2007 return SCIP_OKAY;
    2008}
    2009
    2010/** perform dual presolving on AND-constraints */
    2011static
    2013 SCIP* scip, /**< SCIP data structure */
    2014 SCIP_CONS** conss, /**< AND-constraints to perform dual presolving on */
    2015 int nconss, /**< number of AND-constraints */
    2016 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    2017 unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
    2018 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
    2019 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    2020 int* nfixedvars, /**< pointer to add up the number of found domain reductions */
    2021 int* naggrvars, /**< pointer to add up the number of aggregated variables */
    2022 int* nchgcoefs, /**< pointer to add up the number of changed coefficients */
    2023 int* ndelconss, /**< pointer to add up the number of deleted constraints */
    2024 int* nupgdconss, /**< pointer to add up the number of upgraded constraints */
    2025 int* naddconss /**< pointer to add up the number of added constraints */
    2026 )
    2027{
    2028 SCIP_CONS* cons;
    2029 SCIP_CONSDATA* consdata;
    2030 SCIP_VAR** impoperands;
    2031 SCIP_VAR** vars;
    2032 SCIP_VAR* resvar;
    2033 SCIP_VAR* var;
    2034 int nimpoperands;
    2035 int nvars;
    2036 int size;
    2037 int v;
    2038 int c;
    2039 SCIP_Bool infeasible;
    2040 SCIP_Bool fixed;
    2041
    2042 assert(scip != NULL);
    2043 assert(conss != NULL || nconss == 0);
    2044 assert(eventhdlr != NULL);
    2045 assert(*entries != NULL);
    2046 assert(nentries != NULL);
    2047 assert(cutoff != NULL);
    2048 assert(nfixedvars != NULL);
    2049 assert(naggrvars != NULL);
    2050 assert(nchgcoefs != NULL);
    2051 assert(ndelconss != NULL);
    2052 assert(nupgdconss != NULL);
    2053 assert(naddconss != NULL);
    2054
    2055 if( nconss == 0 )
    2056 return SCIP_OKAY;
    2057
    2058 assert(conss != NULL);
    2059
    2060 size = 2 * (SCIPgetNBinVars(scip) + SCIPgetNImplVars(scip));
    2061
    2062 SCIP_CALL( SCIPallocBufferArray(scip, &impoperands, size) );
    2063
    2064 for( c = nconss - 1; c >= 0 && !(*cutoff); --c )
    2065 {
    2066 cons = conss[c];
    2067 assert(cons != NULL);
    2068
    2069 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsModifiable(cons) )
    2070 continue;
    2071
    2072 /* propagate constraint */
    2073 SCIP_CALL( propagateCons(scip, cons, eventhdlr, cutoff, nfixedvars, nupgdconss) );
    2074
    2075 if( !SCIPconsIsActive(cons) )
    2076 continue;
    2077
    2078 if( *cutoff )
    2079 break;
    2080
    2081 SCIP_CALL( applyFixings(scip, cons, eventhdlr, nchgcoefs) );
    2082
    2083 /* merge multiple occurances of variables or variables with their negated variables */
    2084 SCIP_CALL( mergeMultiples(scip, cons, eventhdlr, entries, nentries, nfixedvars, nchgcoefs, ndelconss) );
    2085
    2086 if( !SCIPconsIsActive(cons) )
    2087 continue;
    2088
    2089 consdata = SCIPconsGetData(cons);
    2090 assert(consdata != NULL);
    2091
    2092 vars = consdata->vars;
    2093 nvars = consdata->nvars;
    2094 assert(vars != NULL || nvars == 0);
    2095
    2096 if( nvars == 0 )
    2097 continue;
    2098
    2099 assert(vars != NULL);
    2100
    2101 resvar = consdata->resvar;
    2102 assert(SCIPvarGetLbGlobal(resvar) < 0.5);
    2103
    2104 /* dual presolving does not apply to a fixed resultant */
    2105 if( SCIPvarGetUbGlobal(resvar) < 0.5 )
    2106 continue;
    2107
    2108 assert(SCIPvarGetNLocksUpType(resvar, SCIP_LOCKTYPE_MODEL) >= 1
    2110
    2113 {
    2114 SCIP_Real resobj;
    2115 SCIP_Real obj;
    2116 SCIP_Real posobjsum = 0;
    2117 SCIP_Real maxobj = -SCIPinfinity(scip);
    2118 int maxpos = -1;
    2119 int oldnfixedvars = *nfixedvars;
    2120 int oldnaggrvars = *naggrvars;
    2121
    2122 nimpoperands = 0;
    2123
    2124 /* collect important operands */
    2125 for( v = nvars - 1; v >= 0; --v )
    2126 {
    2127 var = vars[v];
    2128 assert(var != NULL);
    2131
    2134 {
    2135 impoperands[nimpoperands] = var;
    2136 ++nimpoperands;
    2137
    2138 /* get aggregated objective value of active variable */
    2139 SCIP_CALL( SCIPvarGetAggregatedObj(var, &obj) );
    2140
    2141 /* add up all positive objective values of operands which have exactly one lock in both directions */
    2142 if( obj > 0 )
    2143 posobjsum += obj;
    2144
    2145 /* memorize maximal objective value of operands and its position */
    2146 if( obj > maxobj )
    2147 {
    2148 maxpos = nimpoperands - 1;
    2149 maxobj = obj;
    2150 }
    2151 }
    2152 }
    2153 assert(nimpoperands >= 0 && nimpoperands <= nvars);
    2154
    2155 /* no dual fixable variables found */
    2156 if( nimpoperands == 0 )
    2157 continue;
    2158
    2159 /* get aggregated objective value of active variable */
    2160 SCIP_CALL( SCIPvarGetAggregatedObj(resvar, &resobj) );
    2161
    2162 /* resultant contributes to the objective with a negative value */
    2163 if( SCIPisLE(scip, resobj, 0.0) )
    2164 {
    2165 SCIP_Bool poscontissmall = SCIPisLE(scip, posobjsum, REALABS(resobj));
    2166
    2167 /* if all variables are only locked by this constraint and the resultants contribution more then compensates
    2168 * the positive contribution, we can fix all variables to 1
    2169 */
    2170 if( nimpoperands == nvars && poscontissmall )
    2171 {
    2172 SCIPdebugMsg(scip, "dual-fixing all variables in constraint <%s> to 1\n", SCIPconsGetName(cons));
    2173
    2174 SCIP_CALL( SCIPfixVar(scip, resvar, 1.0, &infeasible, &fixed) );
    2175
    2176 *cutoff = *cutoff || infeasible;
    2177 if( fixed )
    2178 ++(*nfixedvars);
    2179
    2180 for( v = nvars - 1; v >= 0 && !(*cutoff); --v )
    2181 {
    2182 SCIP_CALL( SCIPfixVar(scip, vars[v], 1.0, &infeasible, &fixed) );
    2183
    2184 *cutoff = *cutoff || infeasible;
    2185 if( fixed )
    2186 ++(*nfixedvars);
    2187 }
    2188
    2189 SCIPdebugMsg(scip, "deleting constraint <%s> because all variables are fixed to one\n", SCIPconsGetName(cons));
    2190
    2191 SCIP_CALL( SCIPdelCons(scip, cons) );
    2192 ++(*ndelconss);
    2193 }
    2194 else
    2195 {
    2196 SCIP_Bool aggregationperformed = FALSE;
    2197 SCIP_Bool zerofix = FALSE;
    2198
    2199 assert(nimpoperands > 0);
    2200
    2201 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));
    2202
    2203 for( v = nimpoperands - 1; v >= 0 && !(*cutoff); --v )
    2204 {
    2205 /* get aggregated objective value of active variable */
    2206 SCIP_CALL( SCIPvarGetAggregatedObj(impoperands[v], &obj) );
    2207
    2208 if( SCIPisLE(scip, obj, 0.0) )
    2209 {
    2210 SCIP_CALL( SCIPfixVar(scip, impoperands[v], 1.0, &infeasible, &fixed) );
    2211
    2212 *cutoff = *cutoff || infeasible;
    2213 if( fixed )
    2214 ++(*nfixedvars);
    2215 }
    2216 else if( !poscontissmall )
    2217 {
    2218 SCIP_CALL( SCIPfixVar(scip, impoperands[v], 0.0, &infeasible, &fixed) );
    2219 assert(!infeasible);
    2220 assert(fixed);
    2221
    2222 ++(*nfixedvars);
    2223 zerofix = TRUE;
    2224 }
    2225 else
    2226 {
    2227 SCIP_Bool redundant;
    2228 SCIP_Bool aggregated;
    2229
    2230 /* aggregate resultant to operand */
    2231 SCIP_CALL( SCIPaggregateVars(scip, resvar, impoperands[v], 1.0, -1.0, 0.0,
    2232 &infeasible, &redundant, &aggregated) );
    2233 assert(!infeasible);
    2234
    2235 if( aggregated )
    2236 {
    2237 /* note that we cannot remove the aggregated operand because we do not know the position */
    2238 ++(*naggrvars);
    2239
    2240 aggregationperformed = TRUE;
    2241
    2242 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));
    2243 }
    2244 }
    2245 }
    2246 assert(*nfixedvars - oldnfixedvars + *naggrvars - oldnaggrvars <= nimpoperands);
    2247
    2248 /* did we aggregate the resultant, then we can decide the value to fix it on the (aggregated) objective
    2249 * value since it was a independant variable
    2250 */
    2251 if( aggregationperformed || zerofix )
    2252 {
    2253 SCIP_Real fixval;
    2254
    2255 if( zerofix )
    2256 fixval = 0.0;
    2257 else
    2258 {
    2259 /* get aggregated objective value of active variable, that might be changed */
    2260 SCIP_CALL( SCIPvarGetAggregatedObj(resvar, &obj) );
    2261 assert(!SCIPisPositive(scip, obj));
    2262
    2263 fixval = (SCIPisNegative(scip, obj) ? 1.0 : 0.0);
    2264 }
    2265
    2266 if( fixval < 0.5 || *nfixedvars - oldnfixedvars + *naggrvars - oldnaggrvars == nvars )
    2267 {
    2268 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);
    2269
    2270 SCIP_CALL( SCIPfixVar(scip, resvar, fixval, &infeasible, &fixed) );
    2271 assert(!infeasible);
    2272 assert(fixed);
    2273
    2274 ++(*nfixedvars);
    2275
    2276 SCIPdebugMsg(scip, "deleting constraint <%s> because \n", SCIPconsGetName(cons));
    2277
    2278 SCIP_CALL( SCIPdelCons(scip, cons) );
    2279 ++(*ndelconss);
    2280 }
    2281 }
    2282 }
    2283 }
    2284 /* resultant contributes to the objective with a positive value */
    2285 else
    2286 {
    2287 SCIP_Bool zerofix = FALSE;
    2288#ifndef NDEBUG
    2289 SCIP_Real tmpobj;
    2290
    2291 assert(nimpoperands > 0);
    2292 assert(maxpos >= 0 && maxpos <= consdata->nvars);
    2293 assert(!SCIPisInfinity(scip, -maxobj));
    2294 SCIP_CALL( SCIPvarGetAggregatedObj(impoperands[maxpos], &tmpobj) );
    2295 assert(SCIPisEQ(scip, tmpobj, maxobj));
    2296#endif
    2297
    2298 /* if the smallest possible contribution is negative, but does not compensate the positive contribution of
    2299 * the resultant we need to fix this variable to 0
    2300 */
    2301 if( nimpoperands == nvars && SCIPisLE(scip, maxobj, 0.0) )
    2302 {
    2303 SCIP_Real fixval = (SCIPisLE(scip, REALABS(maxobj), resobj) ? 0.0 : 1.0);
    2304
    2305 SCIPdebugMsg(scip, "dual-fixing variable <%s> in constraint <%s> to %g, because the contribution is%s " \
    2306 "enough to nullify/exceed the contribution of the resultant \n",
    2307 SCIPvarGetName(impoperands[maxpos]), SCIPconsGetName(cons), fixval, (fixval < 0.5) ? " not" : "");
    2308
    2309 SCIP_CALL( SCIPfixVar(scip, impoperands[maxpos], fixval, &infeasible, &fixed) );
    2310 zerofix = (fixval < 0.5);
    2311
    2312 *cutoff = *cutoff || infeasible;
    2313 if( fixed )
    2314 ++(*nfixedvars);
    2315 }
    2316
    2317 SCIPdebugMsg(scip, "dual-fixing all variables, except the variable with the highest contribution to " \
    2318 "the objective, in constraint <%s> with positive contribution to 0 and with negative contribution to 1\n",
    2319 SCIPconsGetName(cons));
    2320
    2321 for( v = nimpoperands - 1; v >= 0 && !(*cutoff); --v )
    2322 {
    2323 /* get aggregated objective value of active variable */
    2324 SCIP_CALL( SCIPvarGetAggregatedObj(impoperands[v], &obj) );
    2325
    2326 if( SCIPisLE(scip, obj, 0.0) )
    2327 {
    2328 if( v == maxpos )
    2329 continue;
    2330
    2331 SCIP_CALL( SCIPfixVar(scip, impoperands[v], 1.0, &infeasible, &fixed) );
    2332 }
    2333 else
    2334 {
    2335 SCIP_CALL( SCIPfixVar(scip, impoperands[v], 0.0, &infeasible, &fixed) );
    2336 zerofix = TRUE;
    2337 }
    2338
    2339 *cutoff = *cutoff || infeasible;
    2340 if( fixed )
    2341 ++(*nfixedvars);
    2342 }
    2343 assert(*nfixedvars - oldnfixedvars <= nimpoperands);
    2344 /* iff we have fixed all variables, all variables needed to be stored in the impoperands array */
    2345 assert((*nfixedvars - oldnfixedvars == nvars) == (nimpoperands == nvars));
    2346
    2347 if( *nfixedvars - oldnfixedvars == nvars )
    2348 {
    2349 SCIPdebugMsg(scip, "all operands are fixed in constraint <%s> => fix resultant <%s> to %g\n", SCIPconsGetName(cons), SCIPvarGetName(resvar), (zerofix ? 0.0 : 1.0));
    2350
    2351 SCIP_CALL( SCIPfixVar(scip, resvar, zerofix ? 0.0 : 1.0, &infeasible, &fixed) );
    2352
    2353 *cutoff = *cutoff || infeasible;
    2354 if( fixed )
    2355 ++(*nfixedvars);
    2356
    2357 SCIPdebugMsg(scip, "deleting constraint <%s> because all variables are fixed\n", SCIPconsGetName(cons));
    2358
    2359 SCIP_CALL( SCIPdelCons(scip, cons) );
    2360 ++(*ndelconss);
    2361 }
    2362 }
    2363 }
    2364 /* resultant is lock by another constraint (handler), check for operands with only one down- and uplock */
    2365 else
    2366 {
    2367 SCIP_Real maxobj = -SCIPinfinity(scip);
    2368 SCIP_Real resobj;
    2369 SCIP_Real obj;
    2370 SCIP_Bool redundant;
    2371 SCIP_Bool aggregated;
    2372 SCIP_Bool resobjispos;
    2373 SCIP_Bool linearize = FALSE;
    2374 SCIP_Bool zerofix = FALSE;
    2375#ifndef NDEBUG
    2376 int oldnchgcoefs = *nchgcoefs;
    2377 int oldnfixedvars = *nfixedvars;
    2378#endif
    2379
    2380 /* get aggregated objective value of active variable */
    2381 SCIP_CALL( SCIPvarGetAggregatedObj(resvar, &resobj) );
    2382
    2383 resobjispos = SCIPisGT(scip, resobj, 0.0);
    2384
    2385 /* we can only aggregate when the objective contribution of the resultant is less or equal to 0 */
    2386 if( !resobjispos )
    2387 {
    2388 SCIP_Bool goodvarsfound = FALSE;
    2389
    2390 for( v = nvars - 1; v >= 0; --v )
    2391 {
    2392 var = vars[v];
    2393 assert(var != NULL);
    2396
    2397 /* get aggregated objective value of active variable */
    2398 SCIP_CALL( SCIPvarGetAggregatedObj(var, &obj) );
    2399
    2400 /* all operands which are only locked by this constraint, the objective contribution is greater or equal
    2401 * to 0 can be aggregated to the resultant
    2402 */
    2405 {
    2406 if( !SCIPisNegative(scip, obj) )
    2407 {
    2408 /* aggregate resultant to operand */
    2409 SCIP_CALL( SCIPaggregateVars(scip, resvar, var, 1.0, -1.0, 0.0, &infeasible, &redundant,
    2410 &aggregated) );
    2411
    2412 if( aggregated && SCIPconsGetNUpgradeLocks(cons) == 0 )
    2413 {
    2414 ++(*naggrvars);
    2415
    2416 linearize = TRUE;
    2417
    2418 /* delete redundant entry from constraint */
    2419 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    2420 ++(*nchgcoefs);
    2421
    2423 "dual aggregating operand <%s> with 1 up- and downlock to the resultant <%s> in constraint <%s>\n",
    2424 SCIPvarGetName(var), SCIPvarGetName(resvar), SCIPconsGetName(cons));
    2425 }
    2426
    2427 *cutoff = *cutoff || infeasible;
    2428 }
    2429 else
    2430 goodvarsfound = TRUE;
    2431 }
    2432 }
    2433 assert(*nchgcoefs - oldnchgcoefs <= nvars);
    2434
    2435 /* if we aggregated an operands with the resultant we can also fix "good" independant operands to 1, since
    2436 * the correctness of "resultant = 0 => at least one operand = 0" in enforced by that aggregation
    2437 * without an aggregation we cannot fix these variables since it might lead to infeasibility, e.g.
    2438 *
    2439 * obj(x3) = -1
    2440 * r = x1 * x2 * x3
    2441 * r = 0
    2442 * x1 = 1
    2443 * x2 = 1
    2444 */
    2445 if( !*cutoff && goodvarsfound && linearize )
    2446 {
    2447 /* fix good variables to 1 */
    2448 for( v = consdata->nvars - 1; v >= 0; --v )
    2449 {
    2450 var = vars[v];
    2451 assert(var != NULL);
    2452
    2455 {
    2456#ifndef NDEBUG
    2457 /* aggregated objective value of active variable need to be negative */
    2458 SCIP_CALL( SCIPvarGetAggregatedObj(var, &obj) );
    2459 assert(SCIPisNegative(scip, obj));
    2460#endif
    2462 "dual-fixing variable <%s> in constraint <%s> to 1, because the contribution is negative\n",
    2463 SCIPvarGetName(var), SCIPconsGetName(cons));
    2464
    2465 SCIP_CALL( SCIPfixVar(scip, var, 1.0, &infeasible, &fixed) );
    2466
    2467 assert(!infeasible);
    2468 if( fixed )
    2469 ++(*nfixedvars);
    2470 }
    2471 }
    2472 assert(*nfixedvars - oldnfixedvars <= consdata->nvars);
    2473 }
    2474 assert(*nchgcoefs - oldnchgcoefs + *nfixedvars - oldnfixedvars <= nvars);
    2475 }
    2476 /* if the downlocks of the resultant are only from this constraint and the objective contribution is positive,
    2477 * we can try to fix operands
    2478 */
    2479 else if( SCIPvarGetNLocksDownType(resvar, SCIP_LOCKTYPE_MODEL) == 1 )
    2480 {
    2481 SCIP_Bool locksareone = TRUE;
    2482 int maxpos = -1;
    2483
    2484 for( v = nvars - 1; v >= 0; --v )
    2485 {
    2486 var = vars[v];
    2487 assert(var != NULL);
    2490
    2491 /* check if all resultants are only locked by this constraint */
    2492 locksareone = locksareone && (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
    2494
    2495 /* get aggregated objective value of active variable */
    2496 SCIP_CALL( SCIPvarGetAggregatedObj(var, &obj) );
    2497
    2498 /* memorize maximal objective value of operands and its position */
    2499 if( obj > maxobj )
    2500 {
    2501 maxpos = v;
    2502 maxobj = obj;
    2503 }
    2504
    2505 /* all operands which are only locked by this constraint, the objective contribution is greater or equal
    2506 * to 0, and the absolute value of the contribution of the resultant exceeds can be eliminated and
    2507 * aggregated to the resultant
    2508 */
    2510 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1 && SCIPisGE(scip, obj, 0.0) )
    2511 {
    2512 SCIPdebugMsg(scip, "dualfix operand <%s> in constraint <%s> to 0\n", SCIPvarGetName(var), SCIPconsGetName(cons));
    2513
    2514 SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) );
    2515
    2516 *cutoff = *cutoff || infeasible;
    2517 if( fixed )
    2518 ++(*nfixedvars);
    2519
    2520 zerofix = TRUE;
    2521 }
    2522 }
    2523 assert(*nchgcoefs - oldnchgcoefs <= nvars);
    2524
    2525 /* if constraint is still active and all operands are only lock by this constraint, we check if we can fix
    2526 * the worst (in objective contribution) operand to zero
    2527 */
    2528 if( !zerofix && locksareone && SCIPisGE(scip, resobj, REALABS(maxobj)) )
    2529 {
    2530 assert(!zerofix);
    2531 /* objective contribution needs to be negative, otherwise, the variable should already be fixed to 0 */
    2532 assert(SCIPisLT(scip, maxobj, 0.0));
    2533
    2534 SCIPdebugMsg(scip, "dualfix operand <%s> with worst contribution in constraint <%s> to 0\n", SCIPvarGetName(vars[maxpos]), SCIPconsGetName(cons));
    2535
    2536 SCIP_CALL( SCIPfixVar(scip, vars[maxpos], 0.0, &infeasible, &fixed) );
    2537
    2538 *cutoff = *cutoff || infeasible;
    2539 if( fixed )
    2540 ++(*nfixedvars);
    2541
    2542 zerofix = TRUE;
    2543 }
    2544
    2545 /* fix the resultant if one operand was fixed to zero and delete the constraint */
    2546 if( zerofix )
    2547 {
    2548 SCIPdebugMsg(scip, "fix resultant <%s> in constraint <%s> to 0\n", SCIPvarGetName(resvar), SCIPconsGetName(cons));
    2549
    2550 SCIP_CALL( SCIPfixVar(scip, resvar, 0.0, &infeasible, &fixed) );
    2551
    2552 *cutoff = *cutoff || infeasible;
    2553 if( fixed )
    2554 ++(*nfixedvars);
    2555
    2556 SCIPdebugMsg(scip, "deleting constraint <%s> because at least one operand and the resultant is fixed to zero\n", SCIPconsGetName(cons));
    2557
    2558 SCIP_CALL( SCIPdelCons(scip, cons) );
    2559 ++(*ndelconss);
    2560 }
    2561 }
    2562
    2563 /* we have to linearize the constraint, otherwise we might get wrong propagations, since due to aggregations a
    2564 * resultant fixed to zero is already fulfilling the constraint, and we must not ensure that some remaining
    2565 * operand needs to be 0
    2566 */
    2567 if( linearize )
    2568 {
    2569 SCIP_CONS* newcons;
    2570 char consname[SCIP_MAXSTRLEN];
    2571 SCIP_VAR* consvars[2];
    2572 SCIP_Real vals[2];
    2573
    2574 assert(SCIPconsIsActive(cons));
    2575 assert(SCIPconsGetNUpgradeLocks(cons) == 0);
    2576
    2577 consvars[0] = consdata->resvar;
    2578 vals[0] = 1.0;
    2579 vals[1] = -1.0;
    2580
    2581 /* create operator linear constraints */
    2582 for( v = consdata->nvars - 1; v >= 0; --v )
    2583 {
    2584 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), v);
    2585 consvars[1] = consdata->vars[v];
    2586
    2587 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, 2, consvars, vals, -SCIPinfinity(scip), 0.0,
    2591 SCIPconsIsStickingAtNode(cons)) );
    2592
    2593 /* add constraint */
    2594 SCIP_CALL( SCIPaddCons(scip, newcons) );
    2595 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
    2596 }
    2597 (*naddconss) += consdata->nvars;
    2598
    2599 SCIPdebugMsg(scip, "deleting constraint <%s> because it was linearized\n", SCIPconsGetName(cons));
    2600
    2601 SCIP_CALL( SCIPdelCons(scip, cons) );
    2602 ++(*ndelconss);
    2603 }
    2604 /* if only one operand is leftover, aggregate it to the resultant */
    2605 else if( consdata->nvars == 1 )
    2606 {
    2607 SCIPdebugMsg(scip, "aggregating last operand <%s> to the resultant <%s> in constraint <%s>\n", SCIPvarGetName(consdata->vars[0]), SCIPvarGetName(resvar), SCIPconsGetName(cons));
    2608
    2609 /* aggregate resultant to operand */
    2610 SCIP_CALL( SCIPaggregateVars(scip, resvar, consdata->vars[0], 1.0, -1.0, 0.0,
    2611 &infeasible, &redundant, &aggregated) );
    2612
    2613 if( aggregated )
    2614 ++(*naggrvars);
    2615
    2616 *cutoff = *cutoff || infeasible;
    2617
    2618 SCIPdebugMsg(scip, "deleting constraint <%s> because all variables are removed\n", SCIPconsGetName(cons));
    2619
    2620 SCIP_CALL( SCIPdelCons(scip, cons) );
    2621 ++(*ndelconss);
    2622 }
    2623
    2624 /* if no operand is leftover delete the constraint */
    2625 if( SCIPconsIsActive(cons) && consdata->nvars == 0 )
    2626 {
    2627 SCIPdebugMsg(scip, "deleting constraint <%s> because all variables are removed\n", SCIPconsGetName(cons));
    2628
    2629 SCIP_CALL( SCIPdelCons(scip, cons) );
    2630 ++(*ndelconss);
    2631 }
    2632 }
    2633 }
    2634
    2635 SCIPfreeBufferArray(scip, &impoperands);
    2636
    2637 return SCIP_OKAY;
    2638}
    2639
    2640/** 1. check if at least two operands or one operand and the resultant are in one clique, if so, we can fix the
    2641 * resultant to zero and in the former case we can also delete this constraint but we need to extract the clique
    2642 * information as constraint
    2643 *
    2644 * x == AND(y, z) and clique(y,z) => x = 0, delete constraint and create y + z <= 1
    2645 * x == AND(y, z) and clique(x,y) => x = 0
    2646 *
    2647 * special handled cases are:
    2648 * - if the resultant is a negation of an operand, in that case we fix the resultant to 0
    2649 * - if the resultant is equal to an operand, we will linearize this constraint by adding all necessary
    2650 * set-packing constraints like resultant + ~operand <= 1 and delete the old constraint
    2651 *
    2652 * x == AND(~x, y) => x = 0
    2653 * x == AND(x, y) => add x + ~y <= 1 and delete the constraint
    2654 *
    2655 * 2. check if one operand is in a clique with the negation of all other operands, this means we can aggregate this
    2656 * operand to the resultant
    2657 *
    2658 * r == AND(x,y,z) and clique(x,~y) and clique(x,~z) => r == x
    2659 *
    2660 * 3. check if the resultant and the negations of all operands are in a clique
    2661 *
    2662 * r == AND(x,y) and clique(r, ~x,~y) => upgrade the constraint to a set-partitioning constraint r + ~x + ~y = 1
    2663 *
    2664 * @note We removed also fixed variables and propagate them, and if only one operand is remaining due to removal, we
    2665 * will aggregate the resultant with this operand
    2666 */
    2667static
    2669 SCIP* scip, /**< SCIP data structure */
    2670 SCIP_CONS* cons, /**< constraint to process */
    2671 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    2672 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
    2673 int* nfixedvars, /**< pointer to add up the number of found domain reductions */
    2674 int* naggrvars, /**< pointer to add up the number of aggregated variables */
    2675 int* nchgcoefs, /**< pointer to add up the number of changed coefficients */
    2676 int* ndelconss, /**< pointer to add up the number of deleted constraints */
    2677 int* naddconss /**< pointer to add up the number of added constraints */
    2678 )
    2679{
    2680 SCIP_CONSDATA* consdata;
    2681 SCIP_VAR** vars;
    2682 SCIP_VAR* var1;
    2683 SCIP_VAR* var2;
    2684 int nvars;
    2685 int vstart;
    2686 int vend;
    2687 int v;
    2688 int v2;
    2689 SCIP_Bool negated;
    2690 SCIP_Bool value1;
    2691 SCIP_Bool value2;
    2692 SCIP_Bool infeasible;
    2693 SCIP_Bool fixed;
    2694 SCIP_Bool allnegoperandsexist;
    2695
    2696 assert(scip != NULL);
    2697 assert(cons != NULL);
    2698 assert(eventhdlr != NULL);
    2699 assert(cutoff != NULL);
    2700 assert(nfixedvars != NULL);
    2701 assert(naggrvars != NULL);
    2702 assert(nchgcoefs != NULL);
    2703 assert(ndelconss != NULL);
    2704 assert(naddconss != NULL);
    2705
    2706 consdata = SCIPconsGetData(cons);
    2707 assert(consdata != NULL);
    2708
    2709 if( !SCIPconsIsActive(cons) || SCIPconsIsModifiable(cons) )
    2710 return SCIP_OKAY;
    2711
    2712 vars = consdata->vars;
    2713 nvars = consdata->nvars;
    2714 assert(vars != NULL || nvars == 0);
    2715
    2716 /* remove fixed variables to be able to ask for cliques
    2717 *
    2718 * if an operand is fixed to 0 fix the resultant to 0 and delete the constraint
    2719 * if an operand is fixed to 1 remove it from the constraint
    2720 */
    2721 for( v = nvars - 1; v >= 0; --v )
    2722 {
    2723 assert(vars != NULL);
    2724
    2725 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
    2726 {
    2727 SCIPdebugMsg(scip, "In constraint <%s> the operand <%s> is fixed to 1 so remove it from the constraint\n",
    2728 SCIPconsGetName(cons), SCIPvarGetName(vars[v]));
    2729
    2730 /* because we loop from back to front we can delete the entry in the consdata structure */
    2731 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
    2732 ++(*nchgcoefs);
    2733
    2734 assert(consdata->vars == vars);
    2735
    2736 continue;
    2737 }
    2738 else if( SCIPvarGetUbGlobal(vars[v]) < 0.5 )
    2739 {
    2740 SCIPdebugMsg(scip, "constraint <%s> redundant: because operand <%s> is fixed to zero so we can fix the resultant <%s> to 0\n",
    2741 SCIPconsGetName(cons), SCIPvarGetName(vars[v]), SCIPvarGetName(consdata->resvar));
    2742
    2743 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
    2744 *cutoff = *cutoff || infeasible;
    2745 if( fixed )
    2746 ++(*nfixedvars);
    2747
    2748 SCIP_CALL( SCIPdelCons(scip, cons) );
    2749 ++(*ndelconss);
    2750
    2751 return SCIP_OKAY;
    2752 }
    2753 }
    2754
    2755 /* if we deleted some operands constraint might be redundant */
    2756 if( consdata->nvars < nvars )
    2757 {
    2758 assert(vars == consdata->vars);
    2759
    2760 /* all operands fixed to one were removed, so if no operand is left this means we can fix the resultant to 1
    2761 * too
    2762 */
    2763 if( consdata->nvars == 0 )
    2764 {
    2765 SCIPdebugMsg(scip, "All operand in constraint <%s> were deleted, so the resultant needs to be fixed to 1\n",
    2766 SCIPconsGetName(cons));
    2767
    2768 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 1.0, &infeasible, &fixed) );
    2769 *cutoff = *cutoff || infeasible;
    2770 if( fixed )
    2771 ++(*nfixedvars);
    2772
    2773 SCIP_CALL( SCIPdelCons(scip, cons) );
    2774 ++(*ndelconss);
    2775
    2776 return SCIP_OKAY;
    2777 }
    2778 /* if only one not fixed operand is left, we can aggregate it to the resultant */
    2779 else if( consdata->nvars == 1 )
    2780 {
    2781 SCIP_Bool redundant;
    2782 SCIP_Bool aggregated;
    2783
    2784 /* aggregate resultant to last operand */
    2785 SCIP_CALL( SCIPaggregateVars(scip, consdata->resvar, consdata->vars[0], 1.0, -1.0, 0.0,
    2786 &infeasible, &redundant, &aggregated) );
    2787
    2788 if( aggregated )
    2789 ++(*naggrvars);
    2790
    2791 SCIP_CALL( SCIPdelCons(scip, cons) );
    2792 ++(*ndelconss);
    2793
    2794 *cutoff = *cutoff || infeasible;
    2795
    2796 return SCIP_OKAY;
    2797 }
    2798
    2799 nvars = consdata->nvars;
    2800 }
    2801
    2802 /* @todo when cliques are improved, we only need to collect all clique-ids for all variables and check for doubled
    2803 * entries
    2804 */
    2805 /* case 1 first part */
    2806 /* check if two operands are in a clique */
    2807 if( SCIPconsGetNUpgradeLocks(cons) == 0 )
    2808 {
    2809 for( v = nvars - 1; v > 0; --v )
    2810 {
    2811 assert(vars != NULL);
    2812
    2813 var1 = vars[v];
    2814 assert(var1 != NULL);
    2815 negated = FALSE;
    2816
    2817 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
    2818 assert(var1 != NULL);
    2819
    2820 if( negated )
    2821 value1 = FALSE;
    2822 else
    2823 value1 = TRUE;
    2824
    2825 assert(SCIPvarGetStatus(var1) != SCIP_VARSTATUS_FIXED);
    2826
    2827 for( v2 = v - 1; v2 >= 0; --v2 )
    2828 {
    2829 var2 = vars[v2];
    2830 assert(var2 != NULL);
    2831
    2832 negated = FALSE;
    2833 SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
    2834 assert(var2 != NULL);
    2835
    2836 if( negated )
    2837 value2 = FALSE;
    2838 else
    2839 value2 = TRUE;
    2840
    2841 assert(SCIPvarGetStatus(var2) != SCIP_VARSTATUS_FIXED);
    2842
    2843 /* if both variables are negated of each other or the same, this will be handled in applyFixings();
    2844 * @note if both variables are the same, then SCIPvarsHaveCommonClique() will return TRUE, so we better
    2845 * continue
    2846 */
    2847 if( var1 == var2 )
    2848 continue;
    2849
    2850 if( SCIPvarsHaveCommonClique(var1, value1, var2, value2, TRUE) )
    2851 {
    2852 SCIP_CONS* cliquecons;
    2853 SCIP_VAR* consvars[2];
    2854 char name[SCIP_MAXSTRLEN];
    2855
    2856 SCIPdebugMsg(scip, "constraint <%s> redundant: because variable <%s> and variable <%s> are in a clique, the resultant <%s> can be fixed to 0\n",
    2857 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2), SCIPvarGetName(consdata->resvar));
    2858
    2859 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
    2860 *cutoff = *cutoff || infeasible;
    2861 if( fixed )
    2862 ++(*nfixedvars);
    2863
    2864 /* create clique constraint which lead to the last fixing */
    2865 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clq_%d", SCIPconsGetName(cons), v2);
    2866
    2867 if( value1 )
    2868 consvars[0] = var1;
    2869 else
    2870 {
    2871 SCIP_CALL( SCIPgetNegatedVar(scip, var1, &(consvars[0])) );
    2872 }
    2873
    2874 if( value2 )
    2875 consvars[1] = var2;
    2876 else
    2877 {
    2878 SCIP_CALL( SCIPgetNegatedVar(scip, var2, &(consvars[1])) );
    2879 }
    2880
    2881 SCIP_CALL( SCIPcreateConsSetpack(scip, &cliquecons, name, 2, consvars,
    2885 SCIPconsIsStickingAtNode(cons)) );
    2886 SCIPdebugMsg(scip, " -> adding clique constraint: ");
    2887 SCIPdebugPrintCons(scip, cliquecons, NULL);
    2888 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &cliquecons) );
    2889 ++(*naddconss);
    2890
    2891 SCIP_CALL( SCIPdelCons(scip, cons) );
    2892 ++(*ndelconss);
    2893
    2894 return SCIP_OKAY;
    2895 }
    2896 }
    2897 }
    2898 }
    2899
    2900 var1 = consdata->resvar;
    2901 assert(var1 != NULL);
    2902
    2903 negated = FALSE;
    2904 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
    2905 assert(var1 != NULL);
    2906
    2907 /* it may appear that we have a fixed resultant */
    2909 {
    2910 /* resultant is fixed to 1, so fix all operands to 1 */
    2911 if( SCIPvarGetLbGlobal(consdata->resvar) > 0.5 )
    2912 {
    2913 SCIPdebugMsg(scip, "In constraint <%s> the resultant <%s> is fixed to 1 so fix all operands to 1\n",
    2914 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
    2915
    2916 /* fix all operands to 1 */
    2917 for( v = nvars - 1; v >= 0 && !(*cutoff); --v )
    2918 {
    2919 assert(vars != NULL);
    2920
    2921 SCIPdebugMsg(scip, "Fixing operand <%s> to 1.\n", SCIPvarGetName(vars[v]));
    2922
    2923 SCIP_CALL( SCIPfixVar(scip, vars[v], 1.0, &infeasible, &fixed) );
    2924 *cutoff = *cutoff || infeasible;
    2925
    2926 if( fixed )
    2927 ++(*nfixedvars);
    2928 }
    2929
    2930 SCIP_CALL( SCIPdelCons(scip, cons) );
    2931 ++(*ndelconss);
    2932 }
    2933 /* the upgrade to a linear constraint because of the to 0 fixed resultant we do in propagateCons() */
    2934 else
    2935 assert(SCIPvarGetUbGlobal(consdata->resvar) < 0.5);
    2936
    2937 return SCIP_OKAY;
    2938 }
    2939
    2940 if( negated )
    2941 value1 = FALSE;
    2942 else
    2943 value1 = TRUE;
    2944
    2945 /* case 1 second part */
    2946 /* check if one operands is in a clique with the resultant */
    2947 for( v = nvars - 1; v >= 0; --v )
    2948 {
    2949 assert(vars != NULL);
    2950
    2951 var2 = vars[v];
    2952 assert(var2 != NULL);
    2953
    2954 negated = FALSE;
    2955 SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
    2956 assert(var2 != NULL);
    2957
    2958 if( negated )
    2959 value2 = FALSE;
    2960 else
    2961 value2 = TRUE;
    2962
    2963 /* if both variables are negated of each other or the same, this will be handled in applyFixings();
    2964 * @note if both variables are the same, then SCIPvarsHaveCommonClique() will return TRUE, so we better continue
    2965 */
    2966 if( var1 == var2 )
    2967 {
    2968 /* x1 == AND(~x1, x2 ...) => x1 = 0 */
    2969 if( value1 != value2 )
    2970 {
    2971 SCIPdebugMsg(scip, "In constraint <%s> the resultant <%s> can be fixed to 0 because the negation of it is an operand.\n",
    2972 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
    2973
    2974 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
    2975 *cutoff = *cutoff || infeasible;
    2976
    2977 if( fixed )
    2978 ++(*nfixedvars);
    2979
    2980 return SCIP_OKAY;
    2981 }
    2982 /* x1 == AND(x1, x2 ...) => delete constraint and create all set-packing constraints x1 + ~x2 <= 1, x1 + ~... <= 1 */
    2983 else if( SCIPconsGetNUpgradeLocks(cons) == 0 )
    2984 {
    2985 SCIP_CONS* cliquecons;
    2986 SCIP_VAR* consvars[2];
    2987 char name[SCIP_MAXSTRLEN];
    2988
    2989 assert(value1 == value2);
    2990
    2991 consvars[0] = consdata->resvar;
    2992
    2993 for( v2 = nvars - 1; v2 >= 0; --v2 )
    2994 {
    2995 var2 = vars[v2];
    2996 negated = FALSE;
    2997 SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
    2998
    2999 /* if the active representations of the resultant and an operand are different then we need to extract
    3000 * this as a clique constraint
    3001 *
    3002 * if the active representations of the resultant and an operand are equal then the clique constraint
    3003 * would look like x1 + ~x1 <= 1, which is redundant
    3004 *
    3005 * if the active representations of the resultant and an operand are negated of each other then the
    3006 * clique constraint would look like x1 + x1 <= 1, which will lead to a fixation of the resultant later
    3007 * on
    3008 */
    3009 if( var1 == var2 )
    3010 {
    3011 if( value1 == negated )
    3012 {
    3013 SCIPdebugMsg(scip, "In constraint <%s> the resultant <%s> can be fixed to 0 because the negation of it is an operand.\n",
    3014 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
    3015
    3016 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
    3017 *cutoff = *cutoff || infeasible;
    3018
    3019 if( fixed )
    3020 ++(*nfixedvars);
    3021
    3022 break;
    3023 }
    3024 }
    3025 else
    3026 {
    3027 SCIP_CALL( SCIPgetNegatedVar(scip, vars[v2], &consvars[1]) );
    3028 assert(consvars[1] != NULL);
    3029
    3030 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clq_%d", SCIPconsGetName(cons), v2);
    3031
    3032 SCIP_CALL( SCIPcreateConsSetpack(scip, &cliquecons, name, 2, consvars,
    3036 SCIPconsIsStickingAtNode(cons)) );
    3037 SCIPdebugMsg(scip, " -> adding clique constraint: ");
    3038 SCIPdebugPrintCons(scip, cliquecons, NULL);
    3039 SCIP_CALL( SCIPaddCons(scip, cliquecons) );
    3040 SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
    3041 ++(*naddconss);
    3042 }
    3043 }
    3044
    3045 /* delete old constraint */
    3046 SCIP_CALL( SCIPdelCons(scip, cons) );
    3047 ++(*ndelconss);
    3048
    3049 return SCIP_OKAY;
    3050 }
    3051 /* due to SCIPvarsHaveCommonClique() returns on two same variables that they are in a clique, we need to
    3052 * handle it explicitly
    3053 */
    3054 else
    3055 continue;
    3056 }
    3057
    3058 /* fix resultant in operand clique */
    3059 if( SCIPvarsHaveCommonClique(var1, value1, var2, value2, TRUE) )
    3060 {
    3061 SCIPdebugMsg(scip, "in constraint <%s> the resultant <%s> can be fixed to 0 because it is in a clique with operand <%s>\n",
    3062 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
    3063
    3064 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
    3065 *cutoff = *cutoff || infeasible;
    3066 if( fixed )
    3067 ++(*nfixedvars);
    3068
    3069 return SCIP_OKAY;
    3070 }
    3071 }
    3072
    3073 if( !SCIPconsIsActive(cons) )
    3074 return SCIP_OKAY;
    3075
    3076 v2 = -1;
    3077 /* check which operands have a negated variable */
    3078 for( v = nvars - 1; v >= 0; --v )
    3079 {
    3080 assert(vars != NULL);
    3081
    3082 var1 = vars[v];
    3083 assert(var1 != NULL);
    3084
    3085 negated = FALSE;
    3086 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
    3087 assert(var1 != NULL);
    3088
    3089 if( SCIPvarGetNegatedVar(var1) == NULL )
    3090 {
    3091 if( v2 >= 0 )
    3092 break;
    3093 v2 = v;
    3094 }
    3095 }
    3096
    3097 allnegoperandsexist = FALSE;
    3098
    3099 /* all operands have a negated variable, so we will check for all possible negated ciques */
    3100 if( v2 == -1 )
    3101 {
    3102 allnegoperandsexist = TRUE;
    3103 vstart = nvars - 1;
    3104 vend = 0;
    3105 }
    3106 /* exactly one operands has no negated variable, so only this variable can be in a clique with all other negations */
    3107 else if( v2 >= 0 && v == -1 )
    3108 {
    3109 vstart = v2;
    3110 vend = v2;
    3111 }
    3112 /* at least two operands have no negated variable, so there is no possible clique with negated variables */
    3113 else
    3114 {
    3115 vstart = -1;
    3116 vend = 0;
    3117 }
    3118
    3119 /* case 2 */
    3120 /* check for negated cliques in the operands */
    3121 for( v = vstart; v >= vend; --v )
    3122 {
    3123 assert(vars != NULL);
    3124
    3125 var1 = vars[v];
    3126 assert(var1 != NULL);
    3127
    3128 negated = FALSE;
    3129 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
    3130 assert(var1 != NULL);
    3131
    3132 if( negated )
    3133 value1 = FALSE;
    3134 else
    3135 value1 = TRUE;
    3136
    3137 for( v2 = nvars - 1; v2 >= 0; --v2 )
    3138 {
    3139 if( v2 == v )
    3140 continue;
    3141
    3142 var2 = vars[v2];
    3143 assert(var2 != NULL);
    3144
    3145 negated = FALSE;
    3146 SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
    3147 assert(var2 != NULL);
    3148
    3149 if( negated )
    3150 value2 = FALSE;
    3151 else
    3152 value2 = TRUE;
    3153
    3154 assert(SCIPvarGetNegatedVar(var2) != NULL);
    3155
    3156 /* invert flag, because we want to check var 1 against all negations of the other variables */
    3157 value2 = !value2;
    3158
    3159 /* due to SCIPvarsHaveCommonClique() returns on two same variables that they are in a clique, we need to handle
    3160 * it explicitly
    3161 */
    3162 if( var1 == var2 && value1 == value2 )
    3163 {
    3164 SCIPdebugMsg(scip, "in constraint <%s> the resultant <%s> can be fixed to 0 because two operands are negated of each other\n",
    3165 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
    3166
    3167 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
    3168 *cutoff = *cutoff || infeasible;
    3169 if( fixed )
    3170 ++(*nfixedvars);
    3171
    3172 return SCIP_OKAY;
    3173 }
    3174
    3175 /* due to SCIPvarsHaveCommonClique() returns on two negated variables that they are not in a clique, we need to
    3176 * handle it explicitly
    3177 */
    3178 if( var1 == var2 && value1 != value2 )
    3179 continue;
    3180
    3181 if( !SCIPvarsHaveCommonClique(var1, value1, var2, value2, TRUE) )
    3182 break;
    3183 }
    3184
    3185 if( v2 == -1 )
    3186 {
    3187 SCIP_Bool redundant;
    3188 SCIP_Bool aggregated;
    3189
    3190 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",
    3191 SCIPconsGetName(cons), SCIPvarGetName(vars[v]), SCIPvarGetName(consdata->resvar));
    3192
    3193 SCIP_CALL( SCIPaggregateVars(scip, consdata->resvar, vars[v], 1.0, -1.0, 0.0,
    3194 &infeasible, &redundant, &aggregated) );
    3195 *cutoff = *cutoff || infeasible;
    3196
    3197 if( aggregated )
    3198 ++(*naggrvars);
    3199
    3200 return SCIP_OKAY;
    3201 }
    3202 }
    3203
    3204 /* case 3 */
    3205 /* check if the resultant and the negations of the operands are in a clique, then we can upgrade this constraint to a
    3206 * set-partitioning constraint
    3207 */
    3208 if( allnegoperandsexist && SCIPconsIsActive(cons) && SCIPconsGetNUpgradeLocks(cons) == 0 )
    3209 {
    3210 SCIP_VAR** newvars;
    3211 SCIP_Bool* negations;
    3212 SCIP_Bool upgrade;
    3213
    3214 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, nvars + 1) );
    3215 SCIP_CALL( SCIPallocBufferArray(scip, &negations, nvars + 1) );
    3216 BMSclearMemoryArray(negations, nvars + 1);
    3217
    3218 var1 = consdata->resvar;
    3219 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negations[nvars]) );
    3220 assert(var1 != NULL);
    3221 assert(SCIPvarGetStatus(var1) != SCIP_VARSTATUS_FIXED);
    3222
    3223 newvars[nvars] = var1;
    3224
    3225 /* get active variables */
    3226 for( v = nvars - 1; v >= 0; --v )
    3227 {
    3228 assert(vars != NULL);
    3229
    3230 var1 = vars[v];
    3231 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negations[v]) );
    3232 assert(var1 != NULL);
    3233 assert(SCIPvarGetStatus(var1) != SCIP_VARSTATUS_FIXED);
    3234
    3235 newvars[v] = var1;
    3236
    3237 /* there should be no variable left that is equal or negated to the resultant */
    3238 assert(newvars[v] != newvars[nvars]);
    3239 }
    3240
    3241 upgrade = TRUE;
    3242
    3243 /* the resultant is in a clique with the negations of all operands, due to this AND-constraint */
    3244 /* only check if the negations of all operands are in a clique */
    3245 for( v = nvars - 1; v >= 0 && upgrade; --v )
    3246 {
    3247 for( v2 = v - 1; v2 >= 0; --v2 )
    3248 {
    3249 /* the resultant need to be in a clique with the negations of all operands */
    3250 if( !SCIPvarsHaveCommonClique(newvars[v], negations[v], newvars[v2], negations[v2], TRUE) )
    3251 {
    3252 upgrade = FALSE;
    3253 break;
    3254 }
    3255 }
    3256 }
    3257
    3258 /* all variables are in a clique, so upgrade thi AND-constraint */
    3259 if( upgrade )
    3260 {
    3261 SCIP_CONS* cliquecons;
    3262 char name[SCIP_MAXSTRLEN];
    3263
    3264 /* get new constraint variables */
    3265 if( negations[nvars] )
    3266 {
    3267 /* negation does not need to be existing, so SCIPvarGetNegatedVar() cannot be called
    3268 * (e.g. resultant = ~x = 1 - x and x = y = newvars[nvars] and negations[nvars] = TRUE,
    3269 * then y does not need to have a negated variable, yet)
    3270 */
    3271 SCIP_CALL( SCIPgetNegatedVar(scip, newvars[nvars], &(newvars[nvars])) );
    3272 }
    3273 assert(newvars[nvars] != NULL);
    3274
    3275 for( v = nvars - 1; v >= 0; --v )
    3276 {
    3277 if( !negations[v] )
    3278 {
    3279 /* negation does not need to be existing, so SCIPvarGetNegatedVar() cannot be called
    3280 * (e.g. vars[v] = ~x = 1 - x and x = y = newvars[v] and negations[v] = TRUE,
    3281 * then y does not need to have a negated variable, yet)
    3282 */
    3283 SCIP_CALL( SCIPgetNegatedVar(scip, newvars[v], &(newvars[v])) );
    3284 }
    3285 assert(newvars[v] != NULL);
    3286 }
    3287
    3288 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clqeq", SCIPconsGetName(cons));
    3289
    3290 SCIP_CALL( SCIPcreateConsSetpart(scip, &cliquecons, name, nvars + 1, newvars,
    3294 SCIPconsIsStickingAtNode(cons)) );
    3295 SCIPdebugMsg(scip, " -> upgrading AND-constraint <%s> with use of clique information to a set-partitioning constraint: \n", SCIPconsGetName(cons));
    3296 SCIPdebugPrintCons(scip, cliquecons, NULL);
    3297 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &cliquecons) );
    3298 ++(*naddconss);
    3299
    3300 /* delete old constraint */
    3301 SCIP_CALL( SCIPdelCons(scip, cons) );
    3302 ++(*ndelconss);
    3303 }
    3304
    3305 SCIPfreeBufferArray(scip, &negations);
    3306 SCIPfreeBufferArray(scip, &newvars);
    3307 }
    3308
    3309 return SCIP_OKAY;
    3310}
    3311
    3312/** gets the key of the given element */
    3313static
    3314SCIP_DECL_HASHGETKEY(hashGetKeyAndcons)
    3315{ /*lint --e{715}*/
    3316 /* the key is the element itself */
    3317 return elem;
    3318}
    3319
    3320/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables */
    3321static
    3322SCIP_DECL_HASHKEYEQ(hashKeyEqAndcons)
    3323{
    3324 SCIP_CONSDATA* consdata1;
    3325 SCIP_CONSDATA* consdata2;
    3326 SCIP_Bool coefsequal;
    3327 int i;
    3328#ifndef NDEBUG
    3329 SCIP* scip;
    3330
    3331 scip = (SCIP*)userptr;
    3332 assert(scip != NULL);
    3333#endif
    3334
    3335 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
    3336 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
    3337
    3338 /* checks trivial case */
    3339 if( consdata1->nvars != consdata2->nvars )
    3340 return FALSE;
    3341
    3342 /* sorts the constraints */
    3343 consdataSort(consdata1);
    3344 consdataSort(consdata2);
    3345 assert(consdata1->sorted);
    3346 assert(consdata2->sorted);
    3347
    3348 coefsequal = TRUE;
    3349
    3350 for( i = 0; i < consdata1->nvars ; ++i )
    3351 {
    3352 /* tests if variables are equal */
    3353 if( consdata1->vars[i] != consdata2->vars[i] )
    3354 {
    3355 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
    3356 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
    3357 coefsequal = FALSE;
    3358 break;
    3359 }
    3360 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
    3361 }
    3362
    3363 return coefsequal;
    3364}
    3365
    3366/** returns the hash value of the key */
    3367static
    3368SCIP_DECL_HASHKEYVAL(hashKeyValAndcons)
    3369{ /*lint --e{715}*/
    3370 SCIP_CONSDATA* consdata;
    3371 int minidx;
    3372 int mididx;
    3373 int maxidx;
    3374
    3375 consdata = SCIPconsGetData((SCIP_CONS*)key);
    3376 assert(consdata != NULL);
    3377 assert(consdata->sorted);
    3378 assert(consdata->nvars > 0);
    3379
    3380 minidx = SCIPvarGetIndex(consdata->vars[0]);
    3381 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
    3382 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
    3383 assert(minidx >= 0 && minidx <= maxidx);
    3384
    3385 return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
    3386}
    3387
    3388/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
    3389 * accordingly; in contrast to removeRedundantConstraints(), it uses a hash table
    3390 */
    3391static
    3393 SCIP* scip, /**< SCIP data structure */
    3394 BMS_BLKMEM* blkmem, /**< block memory */
    3395 SCIP_CONS** conss, /**< constraint set */
    3396 int nconss, /**< number of constraints in constraint set */
    3397 int* firstchange, /**< pointer to store first changed constraint */
    3398 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    3399 int* naggrvars, /**< pointer to count number of aggregated variables */
    3400 int* ndelconss /**< pointer to count number of deleted constraints */
    3401 )
    3402{
    3403 SCIP_HASHTABLE* hashtable;
    3404 int hashtablesize;
    3405 int c;
    3406
    3407 assert(conss != NULL);
    3408 assert(ndelconss != NULL);
    3409
    3410 /* create a hash table for the constraint set */
    3411 hashtablesize = nconss;
    3412 hashtablesize = MAX(hashtablesize, HASHSIZE_ANDCONS);
    3413 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
    3414 hashGetKeyAndcons, hashKeyEqAndcons, hashKeyValAndcons, (void*) scip) );
    3415
    3416 *cutoff = FALSE;
    3417
    3418 /* check all constraints in the given set for redundancy */
    3419 for( c = 0; c < nconss; ++c )
    3420 {
    3421 SCIP_CONS* cons0;
    3422 SCIP_CONS* cons1;
    3423 SCIP_CONSDATA* consdata0;
    3424
    3425 cons0 = conss[c];
    3426
    3427 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
    3428 continue;
    3429
    3430 consdata0 = SCIPconsGetData(cons0);
    3431
    3432 /* sort the constraint */
    3433 consdataSort(consdata0);
    3434 assert(consdata0->sorted);
    3435
    3436 /* get constraint from current hash table with same variables as cons0 */
    3437 cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
    3438
    3439 if( cons1 != NULL )
    3440 {
    3441 SCIP_CONSDATA* consdata1;
    3442 SCIP_Bool redundant;
    3443
    3444 assert(SCIPconsIsActive(cons1));
    3445 assert(!SCIPconsIsModifiable(cons1));
    3446
    3447 consdata1 = SCIPconsGetData(cons1);
    3448
    3449 assert(consdata1 != NULL);
    3450 assert(consdata0->nvars >= 1 && consdata0->nvars == consdata1->nvars);
    3451
    3452 assert(consdata0->sorted && consdata1->sorted);
    3453 assert(consdata0->vars[0] == consdata1->vars[0]);
    3454
    3455 redundant = FALSE;
    3456
    3457 if( consdata0->resvar != consdata1->resvar )
    3458 {
    3459 SCIP_Bool aggregated;
    3460
    3461 assert(SCIPvarCompare(consdata0->resvar, consdata1->resvar) != 0);
    3462
    3463 /* aggregate resultants */
    3464 SCIP_CALL( SCIPaggregateVars(scip, consdata0->resvar, consdata1->resvar, 1.0, -1.0, 0.0,
    3465 cutoff, &redundant, &aggregated) );
    3466 assert(redundant || SCIPdoNotAggr(scip));
    3467
    3468 if( aggregated )
    3469 ++(*naggrvars);
    3470 if( *cutoff )
    3471 goto TERMINATE;
    3472 }
    3473 else
    3474 redundant = TRUE;
    3475
    3476 /* delete consdel */
    3477 if( redundant )
    3478 {
    3479 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
    3480 /* coverity[swapped_arguments] */
    3481 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
    3482
    3483 /* delete constraint */
    3484 SCIP_CALL( SCIPdelCons(scip, cons0) );
    3485 (*ndelconss)++;
    3486 }
    3487
    3488 /* update the first changed constraint to begin the next aggregation round with */
    3489 if( consdata0->changed && SCIPconsGetPos(cons1) < *firstchange )
    3490 *firstchange = SCIPconsGetPos(cons1);
    3491
    3492 assert(SCIPconsIsActive(cons1));
    3493 }
    3494 else
    3495 {
    3496 /* no such constraint in current hash table: insert cons0 into hash table */
    3497 SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
    3498 }
    3499 }
    3500 TERMINATE:
    3501 /* free hash table */
    3502 SCIPhashtableFree(&hashtable);
    3503
    3504 return SCIP_OKAY;
    3505}
    3506
    3507/** helper function to enforce constraints */
    3508static
    3510 SCIP* scip, /**< SCIP data structure */
    3511 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    3512 SCIP_CONS** conss, /**< constraints to process */
    3513 int nconss, /**< number of constraints */
    3514 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
    3515 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
    3516 )
    3517{
    3518 SCIP_CONSHDLRDATA* conshdlrdata;
    3519 SCIP_Bool separated;
    3520 SCIP_Bool violated;
    3521 SCIP_Bool cutoff;
    3522 int i;
    3523
    3524 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3525 assert(conshdlrdata != NULL);
    3526
    3527 *result = SCIP_FEASIBLE;
    3528
    3529 /* method is called only for integral solutions, because the enforcing priority is negative */
    3530 for( i = 0; i < nconss; i++ )
    3531 {
    3532 SCIP_CALL( checkCons(scip, conss[i], sol, FALSE, FALSE, &violated) );
    3533 if( !violated )
    3534 continue;
    3535
    3536 if( !conshdlrdata->enforcecuts )
    3537 {
    3538 *result = SCIP_INFEASIBLE;
    3539 return SCIP_OKAY;
    3540 }
    3541
    3542 SCIP_CALL( separateCons(scip, conss[i], sol, &separated, &cutoff) );
    3543 if( cutoff )
    3544 {
    3545 *result = SCIP_CUTOFF;
    3546 return SCIP_OKAY;
    3547 }
    3548 else if( separated )
    3549 {
    3550 *result = SCIP_SEPARATED;
    3551 }
    3552 else if( *result == SCIP_FEASIBLE ) /* do not change result separated to infeasible */
    3553 {
    3554 *result = SCIP_INFEASIBLE;
    3555 }
    3556 }
    3557
    3558 return SCIP_OKAY;
    3559}
    3560
    3561
    3562/** compares constraint with all prior constraints for possible redundancy or aggregation,
    3563 * and removes or changes constraint accordingly
    3564 */
    3565static
    3567 SCIP* scip, /**< SCIP data structure */
    3568 SCIP_CONS** conss, /**< constraint set */
    3569 int firstchange, /**< first constraint that changed since last pair preprocessing round */
    3570 int chkind, /**< index of constraint to check against all prior indices upto startind */
    3571 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
    3572 int* naggrvars, /**< pointer to count number of aggregated variables */
    3573 int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
    3574 int* ndelconss /**< pointer to count number of deleted constraints */
    3575 )
    3576{
    3577 SCIP_CONS* cons0;
    3578 SCIP_CONSDATA* consdata0;
    3579 SCIP_Bool cons0changed;
    3580 int c;
    3581
    3582 assert(conss != NULL);
    3583 assert(firstchange <= chkind);
    3584 assert(cutoff != NULL);
    3585 assert(naggrvars != NULL);
    3586 assert(nbdchgs != NULL);
    3587 assert(ndelconss != NULL);
    3588
    3589 /* get the constraint to be checked against all prior constraints */
    3590 cons0 = conss[chkind];
    3591 assert(SCIPconsIsActive(cons0));
    3592 assert(!SCIPconsIsModifiable(cons0));
    3593
    3594 consdata0 = SCIPconsGetData(cons0);
    3595
    3596 /* sort the constraint */
    3597 consdataSort(consdata0);
    3598
    3599 assert(consdata0->nvars >= 1);
    3600 assert(consdata0->sorted);
    3601
    3602 /* check constraint against all prior constraints */
    3603 cons0changed = consdata0->changed;
    3604
    3605 if( SCIPconsIsActive(cons0) )
    3606 {
    3607 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff); ++c )
    3608 {
    3609 SCIP_CONS* cons1;
    3610 SCIP_CONSDATA* consdata1;
    3611 SCIP_Bool cons0superset;
    3612 SCIP_Bool cons1superset;
    3613 int v0;
    3614 int v1;
    3615
    3616 if( c % 1000 == 0 && SCIPisStopped(scip) )
    3617 break;
    3618
    3619 cons1 = conss[c];
    3620
    3621 /* ignore inactive and modifiable constraints */
    3622 if( !SCIPconsIsActive(cons1) || SCIPconsIsModifiable(cons1) )
    3623 continue;
    3624
    3625 consdata1 = SCIPconsGetData(cons1);
    3626 assert(consdata1 != NULL);
    3627
    3628#ifdef SCIP_DISABLED_CODE
    3629 SCIPdebugMsg(scip, "preprocess AND-constraint pair <%s>[chg:%d] and <%s>[chg:%d]\n",
    3630 SCIPconsGetName(cons0), cons0changed, SCIPconsGetName(cons1), consdata1->changed);
    3631#endif
    3632
    3633 /* if both constraints were not changed since last round, we can ignore the pair */
    3634 if( !cons0changed && !consdata1->changed )
    3635 continue;
    3636
    3637 assert(consdata1->nvars >= 1);
    3638
    3639 /* sort the constraint */
    3640 consdataSort(consdata1);
    3641 assert(consdata1->sorted);
    3642
    3643 /* check consdata0 against consdata1:
    3644 * - if they consist of the same operands, the resultants can be aggregated
    3645 * - if one operand list is a subset of the other, add implication r0 = 1 -> r1 = 1, or r1 = 1 -> r0 = 1
    3646 */
    3647 v0 = 0;
    3648 v1 = 0;
    3649 cons0superset = TRUE;
    3650 cons1superset = TRUE;
    3651 while( (v0 < consdata0->nvars || v1 < consdata1->nvars) && (cons0superset || cons1superset) )
    3652 {
    3653 int varcmp;
    3654
    3655 /* test, if variable appears in only one or in both constraints */
    3656 if( v0 < consdata0->nvars && v1 < consdata1->nvars )
    3657 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
    3658 else if( v0 < consdata0->nvars )
    3659 varcmp = -1;
    3660 else
    3661 varcmp = +1;
    3662
    3663 switch( varcmp )
    3664 {
    3665 case -1:
    3666 /* variable doesn't appear in consdata1 */
    3667 cons1superset = FALSE;
    3668 v0++;
    3669 break;
    3670
    3671 case +1:
    3672 /* variable doesn't appear in consdata0 */
    3673 cons0superset = FALSE;
    3674 v1++;
    3675 break;
    3676
    3677 case 0:
    3678 /* variable appears in both constraints */
    3679 v0++;
    3680 v1++;
    3681 break;
    3682
    3683 default:
    3684 SCIPerrorMessage("invalid comparison result\n");
    3685 SCIPABORT();
    3686 return SCIP_INVALIDDATA; /*lint !e527*/
    3687 }
    3688 }
    3689
    3690 /* check for equivalence and domination */
    3691 if( cons0superset && cons1superset )
    3692 {
    3693 SCIP_Bool infeasible;
    3694 SCIP_Bool redundant;
    3695 SCIP_Bool aggregated;
    3696
    3697 /* constraints are equivalent */
    3698 SCIPdebugMsg(scip, "equivalent AND-constraints <%s> and <%s>: aggregate resultants <%s> == <%s>\n",
    3699 SCIPconsGetName(cons0), SCIPconsGetName(cons1), SCIPvarGetName(consdata0->resvar),
    3700 SCIPvarGetName(consdata1->resvar));
    3701
    3702 /* aggregate resultants */
    3703 SCIP_CALL( SCIPaggregateVars(scip, consdata0->resvar, consdata1->resvar, 1.0, -1.0, 0.0,
    3704 &infeasible, &redundant, &aggregated) );
    3705 assert(redundant || SCIPdoNotAggr(scip));
    3706
    3707 if( aggregated )
    3708 {
    3709 assert(redundant);
    3710 (*naggrvars)++;
    3711 }
    3712
    3713 if( redundant )
    3714 {
    3715 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
    3716 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
    3717
    3718 /* delete constraint */
    3719 SCIP_CALL( SCIPdelCons(scip, cons1) );
    3720 (*ndelconss)++;
    3721 }
    3722
    3723 *cutoff = *cutoff || infeasible;
    3724 }
    3725 else if( cons0superset )
    3726 {
    3727 SCIP_Bool infeasible;
    3728 int nboundchgs;
    3729
    3730 /* the conjunction of cons0 is a superset of the conjunction of cons1 */
    3731 SCIPdebugMsg(scip, "AND-constraint <%s> is superset of <%s>: add implication <%s> = 1 -> <%s> = 1\n",
    3732 SCIPconsGetName(cons0), SCIPconsGetName(cons1), SCIPvarGetName(consdata0->resvar),
    3733 SCIPvarGetName(consdata1->resvar));
    3734
    3735 /* add implication */
    3736 SCIP_CALL( SCIPaddVarImplication(scip, consdata0->resvar, TRUE, consdata1->resvar, SCIP_BOUNDTYPE_LOWER, 1.0,
    3737 &infeasible, &nboundchgs) );
    3738 *cutoff = *cutoff || infeasible;
    3739 (*nbdchgs) += nboundchgs;
    3740 }
    3741 else if( cons1superset )
    3742 {
    3743 SCIP_Bool infeasible;
    3744 int nboundchgs;
    3745
    3746 /* the conjunction of cons1 is a superset of the conjunction of cons0 */
    3747 SCIPdebugMsg(scip, "AND-constraint <%s> is superset of <%s>: add implication <%s> = 1 -> <%s> = 1\n",
    3748 SCIPconsGetName(cons1), SCIPconsGetName(cons0), SCIPvarGetName(consdata1->resvar),
    3749 SCIPvarGetName(consdata0->resvar));
    3750
    3751 /* add implication */
    3752 SCIP_CALL( SCIPaddVarImplication(scip, consdata1->resvar, TRUE, consdata0->resvar, SCIP_BOUNDTYPE_LOWER, 1.0,
    3753 &infeasible, &nboundchgs) );
    3754 *cutoff = *cutoff || infeasible;
    3755 (*nbdchgs) += nboundchgs;
    3756 }
    3757 }
    3758 }
    3759 consdata0->changed = FALSE;
    3760
    3761 return SCIP_OKAY;
    3762}
    3763
    3764/** adds symmetry information of constraint to a symmetry detection graph */
    3765static
    3767 SCIP* scip, /**< SCIP pointer */
    3768 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
    3769 SCIP_CONS* cons, /**< constraint */
    3770 SYM_GRAPH* graph, /**< symmetry detection graph */
    3771 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
    3772 )
    3773{
    3774 SCIP_CONSDATA* consdata;
    3775 SCIP_VAR** andvars;
    3776 SCIP_VAR** vars;
    3777 SCIP_Real* vals;
    3778 SCIP_Real constant;
    3779 int consnodeidx;
    3780 int andnodeidx;
    3781 int nlocvars;
    3782 int i;
    3783
    3784 assert(scip != NULL);
    3785 assert(cons != NULL);
    3786 assert(graph != NULL);
    3787 assert(success != NULL);
    3788
    3789 consdata = SCIPconsGetData(cons);
    3790 assert(consdata != NULL);
    3791
    3792 /* create arrays to store active representation of variables */
    3793 nlocvars = 1;
    3794 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nlocvars) );
    3795 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nlocvars) );
    3796
    3797 /* add constraint node */
    3798 SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, 0.0, 0.0, &consnodeidx) );
    3799
    3800 /* add resultant to symmetry detection graph */
    3801 assert(consdata->resvar != NULL);
    3802 vars[0] = consdata->resvar;
    3803 vals[0] = 1.0;
    3804 constant = 0.0;
    3805 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
    3806 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, consnodeidx, vars, vals, nlocvars, constant) );
    3807
    3808 /* add node modeling the AND-part and connect it with constraint node */
    3809 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int)SYM_CONSOPTYPE_AND, &andnodeidx) );
    3810 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, andnodeidx, FALSE, 0.0) );
    3811
    3812 /* add variables */
    3813 andvars = consdata->vars;
    3814 for( i = 0; i < consdata->nvars; ++i )
    3815 {
    3816 assert(andvars[i] != NULL);
    3817 vars[0] = andvars[i];
    3818 vals[0] = 1.0;
    3819 constant = 0.0;
    3820 nlocvars = 1;
    3821 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
    3822 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, andnodeidx, vars, vals, nlocvars, constant) );
    3823 }
    3824
    3825 SCIPfreeBufferArray(scip, &vals);
    3826 SCIPfreeBufferArray(scip, &vars);
    3827
    3828 *success = TRUE;
    3829
    3830 return SCIP_OKAY;
    3831}
    3832
    3833/*
    3834 * Callback methods of constraint handler
    3835 */
    3836
    3837/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    3838static
    3840{ /*lint --e{715}*/
    3841 assert(scip != NULL);
    3842 assert(conshdlr != NULL);
    3843 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    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
    5209 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    5210 {
    5211 SCIPerrorMessage("constraint is not an AND-constraint\n");
    5212 SCIPABORT();
    5213 return -1; /*lint !e527*/
    5214 }
    5215
    5216 consdata = SCIPconsGetData(cons);
    5217 assert(consdata != NULL);
    5218
    5219 return consdata->nvars;
    5220}
    5221
    5222/** gets array of variables in AND-constraint */
    5224 SCIP* scip, /**< SCIP data structure */
    5225 SCIP_CONS* cons /**< constraint data */
    5226 )
    5227{ /*lint --e{715}*/
    5228 SCIP_CONSDATA* consdata;
    5229
    5230 assert(scip != NULL);
    5231 assert(cons != NULL);
    5232
    5233 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    5234 {
    5235 SCIPerrorMessage("constraint is not an AND-constraint\n");
    5236 SCIPABORT();
    5237 return NULL; /*lint !e527*/
    5238 }
    5239
    5240 consdata = SCIPconsGetData(cons);
    5241 assert(consdata != NULL);
    5242
    5243 return consdata->vars;
    5244}
    5245
    5246
    5247/** gets the resultant variable in AND-constraint */ /*lint -e715*/
    5249 SCIP* scip, /**< SCIP data structure */
    5250 SCIP_CONS* cons /**< constraint data */
    5251 )
    5252{
    5253 SCIP_CONSDATA* consdata;
    5254
    5255 assert(cons != NULL);
    5256
    5257 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    5258 {
    5259 SCIPerrorMessage("constraint is not an AND-constraint\n");
    5260 SCIPABORT();
    5261 return NULL; /*lint !e527*/
    5262 }
    5263
    5264 consdata = SCIPconsGetData(cons);
    5265 assert(consdata != NULL);
    5266
    5267 return consdata->resvar;
    5268}
    5269
    5270/** return if the variables of the AND-constraint are sorted with respect to their indices */
    5272 SCIP* scip, /**< SCIP data structure */
    5273 SCIP_CONS* cons /**< constraint data */
    5274 )
    5275{
    5276 SCIP_CONSDATA* consdata;
    5277
    5278 assert(scip != NULL);
    5279 assert(cons != NULL);
    5280
    5281 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    5282 {
    5283 SCIPerrorMessage("constraint is not an AND-constraint\n");
    5284 SCIPABORT();
    5285 return FALSE; /*lint !e527*/
    5286 }
    5287
    5288 consdata = SCIPconsGetData(cons);
    5289 assert(consdata != NULL);
    5290
    5291 return consdata->sorted;
    5292}
    5293
    5294/** sort the variables of the AND-constraint with respect to their indices */
    5296 SCIP* scip, /**< SCIP data structure */
    5297 SCIP_CONS* cons /**< constraint data */
    5298 )
    5299{
    5300 SCIP_CONSDATA* consdata;
    5301
    5302 assert(scip != NULL);
    5303 assert(cons != NULL);
    5304
    5305 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    5306 {
    5307 SCIPerrorMessage("constraint is not an AND-constraint\n");
    5308 SCIPABORT();
    5309 return SCIP_INVALIDDATA; /*lint !e527*/
    5310 }
    5311
    5312 consdata = SCIPconsGetData(cons);
    5313 assert(consdata != NULL);
    5314
    5315 consdataSort(consdata);
    5316 assert(consdata->sorted);
    5317
    5318 return SCIP_OKAY;
    5319}
    SCIP_Real * r
    Definition: circlepacking.c:59
    static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
    Definition: cons_and.c:958
    enum Proprule PROPRULE
    Definition: cons_and.c:173
    static SCIP_DECL_CONSACTIVE(consActiveAnd)
    Definition: cons_and.c:4669
    static SCIP_RETCODE consdataFreeRows(SCIP *scip, SCIP_CONSDATA *consdata)
    Definition: cons_and.c:501
    static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
    Definition: cons_and.c:582
    static SCIP_RETCODE consdataCatchWatchedEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos, int *filterpos)
    Definition: cons_and.c:243
    static SCIP_RETCODE consdataDropEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
    Definition: cons_and.c:316
    #define DEFAULT_DUALPRESOLVING
    Definition: cons_and.c:110
    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:2012
    static SCIP_RETCODE consdataSwitchWatchedvars(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int watchedvar1, int watchedvar2)
    Definition: cons_and.c:342
    #define CONSHDLR_NEEDSCONS
    Definition: cons_and.c:97
    #define CONSHDLR_SEPAFREQ
    Definition: cons_and.c:90
    static SCIP_DECL_CONSDELETE(consDeleteAnd)
    Definition: cons_and.c:4198
    static SCIP_DECL_HASHKEYEQ(hashKeyEqAndcons)
    Definition: cons_and.c:3322
    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:667
    #define CONSHDLR_CHECKPRIORITY
    Definition: cons_and.c:89
    static SCIP_DECL_CONSFREE(consFreeAnd)
    Definition: cons_and.c:3855
    #define CONSHDLR_DESC
    Definition: cons_and.c:86
    static SCIP_RETCODE consdataFixOperandsOne(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int nvars, SCIP_Bool *cutoff, int *nfixedvars)
    Definition: cons_and.c:1339
    static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *separated, SCIP_Bool *cutoff)
    Definition: cons_and.c:1183
    static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_VAR *var)
    Definition: cons_and.c:607
    static SCIP_DECL_CONSCOPY(consCopyAnd)
    Definition: cons_and.c:4716
    static SCIP_RETCODE createRelaxation(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:911
    #define CONSHDLR_PROP_TIMING
    Definition: cons_and.c:100
    #define HASHSIZE_ANDCONS
    Definition: cons_and.c:112
    static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
    Definition: cons_and.c:230
    static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_and.c:196
    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:1502
    static SCIP_DECL_CONSINITPRE(consInitpreAnd)
    Definition: cons_and.c:3873
    static SCIP_DECL_HASHGETKEY(hashGetKeyAndcons)
    Definition: cons_and.c:3314
    #define DEFAULT_UPGRRESULTANT
    Definition: cons_and.c:109
    #define CONSHDLR_MAXPREROUNDS
    Definition: cons_and.c:94
    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:1300
    static SCIP_DECL_CONSENFORELAX(consEnforelaxAnd)
    Definition: cons_and.c:4323
    #define DEFAULT_PRESOLPAIRWISE
    Definition: cons_and.c:105
    #define CONSHDLR_SEPAPRIORITY
    Definition: cons_and.c:87
    static SCIP_RETCODE analyzeConflictOne(SCIP *scip, SCIP_CONS *cons, int falsepos)
    Definition: cons_and.c:1232
    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:3392
    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:106
    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:2668
    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:3566
    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:1393
    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:3766
    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:182
    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:402
    Proprule
    Definition: cons_and.c:166
    @ PROPRULE_2
    Definition: cons_and.c:169
    @ PROPRULE_1
    Definition: cons_and.c:168
    @ PROPRULE_3
    Definition: cons_and.c:170
    @ PROPRULE_INVALID
    Definition: cons_and.c:167
    @ PROPRULE_4
    Definition: cons_and.c:171
    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:1071
    #define DEFAULT_PRESOLUSEHASHING
    Definition: cons_and.c:113
    static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_EVENTHDLR *eventhdlr)
    Definition: cons_and.c:532
    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:267
    #define MINGAINPERNMINCOMPARISONS
    Definition: cons_and.c:115
    static SCIP_RETCODE analyzeConflictZero(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:1264
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyAnd)
    Definition: cons_and.c:3839
    static SCIP_DECL_CONSINITSOL(consInitsolAnd)
    Definition: cons_and.c:4156
    #define CONSHDLR_PROPFREQ
    Definition: cons_and.c:91
    static SCIP_DECL_CONSDEACTIVE(consDeactiveAnd)
    Definition: cons_and.c:4681
    #define NMINCOMPARISONS
    Definition: cons_and.c:114
    #define DEFAULT_ENFORCECUTS
    Definition: cons_and.c:107
    #define CONSHDLR_PRESOLTIMING
    Definition: cons_and.c:99
    static SCIP_DECL_CONSGETNVARS(consGetNVarsAnd)
    Definition: cons_and.c:4907
    static void consdataSort(SCIP_CONSDATA *consdata)
    Definition: cons_and.c:730
    static SCIP_DECL_CONSPROP(consPropAnd)
    Definition: cons_and.c:4373
    static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:1018
    static SCIP_DECL_CONSPRINT(consPrintAnd)
    Definition: cons_and.c:4703
    #define CONSHDLR_EAGERFREQ
    Definition: cons_and.c:92
    #define EVENTHDLR_DESC
    Definition: cons_and.c:103
    static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
    Definition: cons_and.c:210
    static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_EVENTHDLR *eventhdlr, int nvars, SCIP_VAR **vars, SCIP_VAR *resvar)
    Definition: cons_and.c:426
    static SCIP_DECL_HASHKEYVAL(hashKeyValAndcons)
    Definition: cons_and.c:3368
    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:88
    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:811
    static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, PROPRULE proprule, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
    Definition: cons_and.c:1926
    #define CONSHDLR_DELAYSEPA
    Definition: cons_and.c:95
    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:1563
    static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, SCIP_SOL *sol, SCIP_RESULT *result)
    Definition: cons_and.c:3509
    #define CONSHDLR_NAME
    Definition: cons_and.c:85
    #define EVENTHDLR_NAME
    Definition: cons_and.c:102
    #define DEFAULT_AGGRLINEARIZATION
    Definition: cons_and.c:108
    static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, int *nfixedvars, int *nupgdconss)
    Definition: cons_and.c:1721
    #define CONSHDLR_DELAYPROP
    Definition: cons_and.c:96
    static SCIP_RETCODE consdataCatchEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
    Definition: cons_and.c:290
    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:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_Bool
    Definition: def.h:91
    #define MAX3(x, y, z)
    Definition: def.h:228
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIPABORT()
    Definition: def.h:327
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_CALL(x)
    Definition: def.h:355
    #define SCIP_CALL_FINALLY(x, y)
    Definition: def.h:397
    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:5248
    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:9460
    SCIP_RETCODE SCIPsortAndCons(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5295
    SCIP_Bool SCIPisAndConsSorted(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5271
    SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_RETCODE SCIPcreateConsSetpart(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    Definition: cons_setppc.c:9402
    SCIP_VAR ** SCIPgetVarsAnd(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_and.c:5223
    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:398
    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:647
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    int SCIPgetNIntVars(SCIP *scip)
    Definition: scip_prob.c:2340
    SCIP_RETCODE SCIPaddConsUpgrade(SCIP *scip, SCIP_CONS *oldcons, SCIP_CONS **newcons)
    Definition: scip_prob.c:3368
    int SCIPgetNImplVars(SCIP *scip)
    Definition: scip_prob.c:2387
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    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:4346
    SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
    Definition: scip_cons.c:540
    SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
    Definition: scip_cons.c:831
    SCIP_RETCODE SCIPsetConshdlrInitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITPRE((*consinitpre)))
    Definition: scip_cons.c:492
    SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
    Definition: scip_cons.c:235
    SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
    Definition: scip_cons.c:281
    SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: scip_cons.c:181
    SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDEACTIVE((*consdeactive)))
    Definition: scip_cons.c:693
    SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)))
    Definition: scip_cons.c:900
    SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
    Definition: scip_cons.c:578
    SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
    Definition: scip_cons.c:372
    SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
    Definition: scip_cons.c:323
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4316
    SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
    Definition: scip_cons.c:516
    SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
    Definition: scip_cons.c:347
    SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
    Definition: scip_cons.c:940
    SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH((*consgetsignedpermsymgraph)))
    Definition: scip_cons.c:924
    SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
    Definition: scip_cons.c:468
    SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
    Definition: scip_cons.c:624
    SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
    Definition: scip_cons.c:444
    SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4336
    SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
    Definition: scip_cons.c:601
    SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
    Definition: scip_cons.c:647
    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:8419
    int SCIPconsGetPos(SCIP_CONS *cons)
    Definition: cons.c:8399
    SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
    Definition: cons.c:8648
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8409
    SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
    Definition: cons.c:8558
    SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
    Definition: scip_cons.c:2536
    int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
    Definition: cons.c:8841
    SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8588
    SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
    Definition: cons.c:8518
    SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
    Definition: cons.c:8698
    SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
    Definition: cons.c:8578
    SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
    Definition: cons.c:8450
    SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    Definition: scip_cons.c:997
    SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
    Definition: cons.c:8608
    SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
    Definition: cons.c:8628
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8389
    SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1812
    SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
    Definition: cons.c:8638
    SCIP_Bool SCIPconsIsAdded(SCIP_CONS *cons)
    Definition: cons.c:8818
    SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
    Definition: scip_cons.c:1524
    SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
    Definition: cons.c:8668
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8568
    SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1784
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8658
    SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
    Definition: scip_cut.c:225
    SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: scip_event.c:111
    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:453
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    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:17530
    SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
    Definition: var.c:23868
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23478
    SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
    Definition: scip_var.c:2119
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4386
    SCIP_Bool SCIPdoNotAggr(SCIP *scip)
    Definition: scip_var.c:10909
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23498
    SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
    Definition: var.c:23944
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_RETCODE SCIPgetBinvarRepresentatives(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **repvars, SCIP_Bool *negated)
    Definition: scip_var.c:2283
    SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
    Definition: var.c:23430
    SCIP_RETCODE SCIPparseVarsList(SCIP *scip, const char *str, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize, char **endptr, char delimiter, SCIP_Bool *success)
    Definition: scip_var.c:805
    SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
    Definition: scip_var.c:10550
    SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
    Definition: var.c:17550
    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:23453
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    int SCIPvarGetIndex(SCIP_VAR *var)
    Definition: var.c:23652
    SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
    Definition: scip_var.c:5118
    SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
    Definition: scip_var.c:5296
    SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2872
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_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:24234
    SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
    Definition: var.c:23443
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    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:17274
    SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
    Definition: var.c:17642
    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:16807
    int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4328
    SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
    Definition: scip_var.c:2078
    SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:1853
    SCIP_Bool 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:1221
    structs for symmetry computations
    methods for dealing with symmetry detection graphs
    @ SCIP_CONFTYPE_PROPAGATION
    Definition: type_conflict.h:62
    struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
    Definition: type_cons.h:64
    #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