Scippy

    SCIP

    Solving Constraint Integer Programs

    cons_disjunction.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_disjunction.c
    26 * @ingroup DEFPLUGINS_CONS
    27 * @brief constraint handler for disjunction constraints
    28 * @author Stefan Heinz
    29 * @author Michael Winkler
    30 */
    31
    32/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    33
    36#include "scip/pub_cons.h"
    37#include "scip/pub_message.h"
    38#include "scip/pub_tree.h"
    39#include "scip/scip_branch.h"
    40#include "scip/scip_cons.h"
    41#include "scip/scip_copy.h"
    42#include "scip/scip_general.h"
    43#include "scip/scip_mem.h"
    44#include "scip/scip_message.h"
    45#include "scip/scip_param.h"
    46#include "scip/scip_prob.h"
    47#include "scip/scip_probing.h"
    48#include "scip/scip_sol.h"
    50#include "scip/scip_tree.h"
    51#include "scip/symmetry_graph.h"
    52#include <string.h>
    53
    54
    55/* constraint handler properties */
    56#define CONSHDLR_NAME "disjunction"
    57#define CONSHDLR_DESC "disjunction of constraints (or(cons1, cons2, ..., consn))"
    58#define CONSHDLR_ENFOPRIORITY -950000 /**< priority of the constraint handler for constraint enforcing */
    59#define CONSHDLR_CHECKPRIORITY -900000 /**< priority of the constraint handler for checking feasibility */
    60#define CONSHDLR_PROPFREQ -1 /**< frequency for propagating domains; zero means only preprocessing propagation */
    61#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
    62 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    63#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in
    64 * (-1: no limit) */
    65#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
    66#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
    67
    68#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_FAST
    69#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
    70
    71
    72#define DEFAULT_ALWAYSBRANCH TRUE /**< alawys perform branching if one of the constraints is violated, otherwise only if all integers are fixed */
    73
    74/*
    75 * Data structures
    76 */
    77
    78/** constraint data for disjunction constraints */
    79struct SCIP_ConsData
    80{
    81 SCIP_CONS** conss; /**< constraints in disjunction */
    82 SCIP_CONS* relaxcons; /**< a conjunction constraint containing the linear relaxation of the
    83 * disjunction constraint, or NULL
    84 */
    85 int consssize; /**< size of conss array */
    86 int nconss; /**< number of constraints in disjunction */
    87};
    88
    89/** constraint handler data */
    90struct SCIP_ConshdlrData
    91{
    92 SCIP_Bool alwaysbranch; /**< alawys perform branching if one of the constraints is violated, otherwise only if all integers are fixed */
    93};
    94
    95/*
    96 * Local methods
    97 */
    98
    99/** creates disjunction constraint data, captures initial constraints of disjunction */
    100static
    102 SCIP* scip, /**< SCIP data structure */
    103 SCIP_CONSDATA** consdata, /**< pointer to constraint data */
    104 SCIP_CONS** conss, /**< initial constraint in disjunction */
    105 int nconss, /**< number of initial constraints in disjunction */
    106 SCIP_CONS* relaxcons /**< a conjunction constraint containing the liner relaxation of the disjunction constraint, or NULL */
    107 )
    108{
    109 assert(scip != NULL);
    110 assert(consdata != NULL);
    111
    112 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
    113 if( nconss > 0 )
    114 {
    115 assert(conss != NULL);
    116
    117 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->conss, conss, nconss) );
    118
    119 (*consdata)->consssize = nconss;
    120 (*consdata)->nconss = nconss;
    121 (*consdata)->relaxcons = relaxcons;
    122
    123 /* we need to capture the constraints to avoid that SCIP deletes them since they are not (yet) added to the
    124 * problem
    125 */
    127 {
    128 SCIP_CALL( SCIPtransformConss(scip, nconss, (*consdata)->conss, (*consdata)->conss) );
    129
    130 if( (*consdata)->relaxcons != NULL )
    131 {
    132 SCIP_CALL( SCIPtransformCons(scip, (*consdata)->relaxcons, &(*consdata)->relaxcons) );
    133 }
    134 }
    135 else
    136 {
    137 int c;
    138
    139 for( c = 0; c < nconss; ++c )
    140 {
    141 assert(conss[c] != NULL);
    142 SCIP_CALL( SCIPcaptureCons(scip, conss[c]) );
    143 }
    144
    145 if( (*consdata)->relaxcons != NULL )
    146 {
    147 SCIP_CALL( SCIPcaptureCons(scip, (*consdata)->relaxcons) );
    148 }
    149 }
    150 }
    151 else
    152 {
    153 (*consdata)->conss = NULL;
    154 (*consdata)->consssize = 0;
    155 (*consdata)->nconss = 0;
    156 (*consdata)->relaxcons = NULL;
    157 }
    158
    159 return SCIP_OKAY;
    160}
    161
    162/** frees constraint data and releases all constraints in disjunction */
    163static
    165 SCIP* scip, /**< SCIP data structure */
    166 SCIP_CONSDATA** consdata /**< pointer to constraint data */
    167 )
    168{
    169 int c;
    170
    171 assert(scip != NULL);
    172 assert(consdata != NULL);
    173 assert(*consdata != NULL);
    174
    175 /* release constraints */
    176 for( c = 0; c < (*consdata)->nconss; ++c )
    177 {
    178 SCIP_CALL( SCIPreleaseCons(scip, &(*consdata)->conss[c]) );
    179 }
    180
    181 /* release relaxation constraint */
    182 if( (*consdata)->relaxcons != NULL )
    183 {
    184 SCIP_CALL( SCIPreleaseCons(scip, &(*consdata)->relaxcons) );
    185 }
    186
    187 /* free memory */
    188 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->conss, (*consdata)->consssize);
    189 SCIPfreeBlockMemory(scip, consdata);
    190
    191 return SCIP_OKAY;
    192}
    193
    194/** adds constraint to disjunction */
    195static
    197 SCIP* scip, /**< SCIP data structure */
    198 SCIP_CONSDATA* consdata, /**< constraint data */
    199 SCIP_CONS* cons /**< constraint to add to the disjunction */
    200 )
    201{
    202 assert(scip != NULL);
    203 assert(consdata != NULL);
    204 assert(cons != NULL);
    205
    206 /* get memory for additional constraint */
    207 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &consdata->conss, &consdata->consssize, consdata->nconss+1) );
    208 assert(consdata->conss != NULL);
    209 assert(consdata->nconss < consdata->consssize);
    210
    211 /* insert constraint in array */
    212 consdata->conss[consdata->nconss] = cons;
    213 consdata->nconss++;
    214
    216 {
    217 SCIP_CALL( SCIPtransformCons(scip, consdata->conss[consdata->nconss - 1], &(consdata->conss[consdata->nconss - 1])) );
    218 }
    219 else
    220 {
    221 /* capture constraint */
    223 }
    224
    225 return SCIP_OKAY;
    226}
    227
    228/** branches on disjunctive constraint */
    229static
    231 SCIP* scip, /**< SCIP data structure */
    232 SCIP_CONS* cons, /**< active disjunction constraint */
    233 SCIP_RESULT* result /**< pointer to store the result */
    234 )
    235{
    236 SCIP_CONSDATA* consdata;
    237 SCIP_CONS** conss;
    238 SCIP_NODE* child;
    239 SCIP_Real estimate;
    240 int nconss;
    241 int i;
    242
    243 assert(result != NULL);
    244
    245 /* cannot branch on modifiable constraint */
    246 if( SCIPconsIsModifiable(cons) )
    247 return SCIP_OKAY;
    248
    249 consdata = SCIPconsGetData(cons);
    250 assert(consdata != NULL);
    251
    252 conss = consdata->conss;
    253 assert(conss != NULL);
    254
    255 nconss = consdata->nconss;
    256 assert(nconss > 0);
    257
    259
    260 /* add all inactive constraints to local subproblem */
    261 for( i = 0; i < nconss; ++i )
    262 {
    263 /* create the branch-and-bound tree child nodes of the current node */
    264 SCIP_CALL( SCIPcreateChild(scip, &child, 0.0, estimate) );
    265
    266 /* if disjunctive constraint needs to be checked, the upgraded constraint also needs to be checked */
    267 if( SCIPconsIsChecked(cons) )
    268 {
    269 SCIP_CALL( SCIPsetConsChecked(scip, conss[i], TRUE) );
    270 }
    271
    272 /* mark constraint to be local; otherwise during INITLP the (global) row of all constraints of the disjunction
    273 * constrtaint will enter the LP
    274 */
    275 SCIP_CALL( SCIPsetConsLocal(scip, conss[i], TRUE) );
    276
    277 /* add constraints to nodes */
    278 SCIP_CALL( SCIPaddConsNode(scip, child, conss[i], NULL) );
    279 SCIPdebugMsg(scip, "add cons %s to node %lld from %lld\n", SCIPconsGetName(conss[i]), SCIPnodeGetNumber(child),
    281
    282 /* remove disjunction constraint, from child node */
    283 SCIP_CALL( SCIPdelConsNode(scip, child, cons) );
    284 }
    285
    286 SCIPdebugMsg(scip, "disjunction constraint <%s> branched %d childs\n", SCIPconsGetName(cons), nconss);
    287
    288 /* reset constraint age */
    290
    291 *result = SCIP_BRANCHED;
    292
    293 return SCIP_OKAY;
    294}
    295
    296/** checks disjunction constraints if at least one is feasible */
    297static
    299 SCIP* scip, /**< SCIP data structure */
    300 SCIP_CONS* cons, /**< active disjunction constraint */
    301 SCIP_SOL* sol, /**< solution to check */
    302 SCIP_Bool checkintegrality, /**< Has integrality to be checked? */
    303 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
    304 SCIP_Bool printreason, /**< Should the reason for the violation be printed? */
    305 SCIP_RESULT* result /**< pointer to store the result */
    306 )
    307{
    308 SCIP_CONSDATA* consdata;
    309 SCIP_CONS** conss;
    310 int nconss;
    311 int i;
    312
    313 assert(result != NULL);
    314
    315 consdata = SCIPconsGetData(cons);
    316 assert(consdata != NULL);
    317
    318 conss = consdata->conss;
    319 assert(conss != NULL);
    320
    321 nconss = consdata->nconss;
    322 assert(nconss > 0);
    323
    324 *result = SCIP_INFEASIBLE;
    325
    327
    328 /* check all constraints */
    329 for( i = 0; i < nconss && *result != SCIP_FEASIBLE; ++i )
    330 {
    331 SCIP_CALL( SCIPcheckCons(scip, conss[i], sol, checkintegrality, checklprows, FALSE, result) );
    332 assert(*result == SCIP_FEASIBLE || *result == SCIP_INFEASIBLE);
    333 }
    334
    336
    337 if( *result == SCIP_INFEASIBLE )
    338 {
    339 if( sol != NULL )
    340 SCIPupdateSolConsViolation(scip, sol, 1.0, 1.0);
    341
    342 if( printreason )
    343 {
    344 SCIPinfoMessage(scip, NULL, "constraint %s is violated, all sub-constraints in this disjunction are violated by this given solution\n", SCIPconsGetName(cons));
    346 }
    347 }
    348
    349 return SCIP_OKAY;
    350}
    351
    352/** propagation method for disjunction constraint */
    353static
    355 SCIP* scip, /**< SCIP data structure */
    356 SCIP_CONS* cons, /**< disjunctive constraint */
    357 int* ndelconss /**< pointer to count number of deleted constraints */
    358 )
    359{
    360 SCIP_CONSDATA* consdata;
    361 SCIP_CONS** conss;
    362 int nconss;
    363 int c;
    364
    365 assert(scip != NULL);
    366 assert(cons != NULL);
    367 assert(ndelconss != NULL);
    368
    369 consdata = SCIPconsGetData(cons);
    370 assert(consdata != NULL);
    371
    372 conss = consdata->conss;
    373 assert(conss != NULL);
    374
    375 nconss = consdata->nconss;
    376 assert(nconss >= 1);
    377
    378 for( c = 0; c < nconss; ++c )
    379 {
    380 /* if a constraint of the disjunction is already active, the disjunction is enforce by this constraint and
    381 * therefore redundant and can be locally deleted
    382 */
    383 if( SCIPconsIsActive(conss[c]) )
    384 {
    385 /* if we can globally delete the whole disjunctive constraint, because one constraint is already active, we
    386 * might need to update the check stage
    387 */
    389 {
    390 /* if disjunctive constraint needs to be checked, the upgraded constraint also needs to be checked */
    391 if( SCIPconsIsChecked(cons) )
    392 {
    393 SCIP_CALL( SCIPsetConsChecked(scip, conss[c], TRUE) );
    394 }
    395 }
    396
    397 (*ndelconss)++;
    399 break;
    400 }
    401 /* if a sub-constraint is globally deleted, it means that this constraint is redundant and always fulfilled and
    402 * this makes also this disjunction redundant
    403 */
    404 else if( SCIPconsIsDeleted(conss[c]) )
    405 {
    406 (*ndelconss)++;
    407 SCIP_CALL( SCIPdelCons(scip, cons) );
    408 break;
    409 }
    410 }
    411
    412 return SCIP_OKAY;
    413}
    414
    415/** helper function to enforce constraints */
    416static
    418 SCIP* scip, /**< SCIP data structure */
    419 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    420 SCIP_CONS** conss, /**< constraints to process */
    421 int nconss, /**< number of constraints */
    422 SCIP_SOL* sol, /**< solution to enforce (NULL for LP solution) */
    423 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
    424 )
    425{
    426 SCIP_CONSHDLRDATA* conshdlrdata;
    428 int c;
    429
    430 *result = SCIP_FEASIBLE;
    431
    432 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    433 assert(conshdlrdata != NULL);
    434
    435 branch = SCIPgetNPseudoBranchCands(scip) == 0 || conshdlrdata->alwaysbranch;
    436
    437 for( c = 0; c < nconss && *result != SCIP_BRANCHED; ++c )
    438 {
    439 /* check the disjunction */
    440 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, FALSE, FALSE, result) );
    441
    442 if( *result == SCIP_INFEASIBLE && branch )
    443 {
    444 SCIP_CALL( branchCons(scip, conss[c], result) );
    445 }
    446 }
    447
    448 return SCIP_OKAY;
    449}
    450
    451/** adds symmetry information of constraint to a symmetry detection graph */
    452static
    454 SCIP* scip, /**< SCIP pointer */
    455 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
    456 SCIP_CONS* cons, /**< constraint */
    457 SYM_GRAPH* graph, /**< symmetry detection graph */
    458 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
    459 )
    460{
    461 SYM_GRAPH* symgraph;
    462 SCIP_CONSHDLR* conshdlr;
    463 SCIP_CONSDATA* consdata;
    464 int rootnode;
    465 int subroot = -1;
    466 int c;
    467
    468 assert(scip != NULL);
    469 assert(cons != NULL);
    470 assert(graph != NULL);
    471 assert(success != NULL);
    472
    473 *success = TRUE;
    474
    475 consdata = SCIPconsGetData(cons);
    476 assert(consdata != NULL);
    477
    478 /* check whether all constraints in the disjunction can build symmetry detection graphs */
    479 for( c = 0; c < consdata->nconss && *success; ++c )
    480 {
    481 conshdlr = SCIPconsGetHdlr(consdata->conss[c]);
    482 assert(conshdlr != NULL);
    483
    484 if( symtype == SYM_SYMTYPE_PERM )
    485 {
    487 *success = FALSE;
    488 }
    489 else
    490 {
    491 assert(symtype == SYM_SYMTYPE_SIGNPERM);
    493 *success = FALSE;
    494 }
    495 }
    496
    497 /* terminate if not all constraints can build symmetry detection graphs */
    498 if( !(*success) )
    499 return SCIP_OKAY;
    500
    501 /* start building the symmetry detection graph for the disjunctive constraint */
    502 SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, 0.0, 0.0, &rootnode) );
    503
    504 /* copy of graph: most constraints are linear, use modest estimation of number of nodes */
    506 5, 5, 1, SCIPgetNVars(scip)) );
    507
    508 /* for each constraint, build the symmetry detection graph and copy it to the global graph */
    509 for( c = 0; c < consdata->nconss && *success; ++c )
    510 {
    512
    513 if( symtype == SYM_SYMTYPE_PERM )
    514 {
    515 SCIP_CALL( SCIPgetConsPermsymGraph(scip, consdata->conss[c], symgraph, success) );
    516 }
    517 else
    518 {
    519 assert(symtype == SYM_SYMTYPE_SIGNPERM);
    520
    521 SCIP_CALL( SCIPgetConsSignedPermsymGraph(scip, consdata->conss[c], symgraph, success) );
    522 }
    523
    524 if( *success )
    525 {
    526 /* copy the symmetry detection graph and find its root node with index in target graph */
    527 SCIP_CALL( SCIPcopySymgraphAsSubgraph(scip, symgraph, graph, consdata->conss[c], &subroot) );
    528
    529 if( subroot < 0 )
    530 *success = FALSE;
    531
    532 /* connect root of disjunction constraint with root of copied graph */
    533 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, rootnode, subroot, FALSE, 0.0) );
    534 }
    535 }
    536 SCIP_CALL( SCIPfreeSymgraph(scip, &symgraph) );
    537
    538 return SCIP_OKAY;
    539}
    540
    541/*
    542 * Callback methods of constraint handler
    543 */
    544
    545/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    546static
    547SCIP_DECL_CONSHDLRCOPY(conshdlrCopyDisjunction)
    548{ /*lint --e{715}*/
    549 assert(scip != NULL);
    550 assert(conshdlr != NULL);
    551 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    552
    553 /* call inclusion method of constraint handler */
    555
    556 *valid = TRUE;
    557
    558 return SCIP_OKAY;
    559}
    560
    561/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
    562static
    563SCIP_DECL_CONSFREE(consFreeDisjunction)
    564{
    565 SCIP_CONSHDLRDATA* conshdlrdata;
    566
    567 assert(scip != NULL);
    568 assert(conshdlr != NULL);
    569 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    570
    571 /* free constraint handler data */
    572 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    573 assert(conshdlrdata != NULL);
    574
    575 SCIPfreeBlockMemory(scip, &conshdlrdata);
    576
    577 SCIPconshdlrSetData(conshdlr, NULL);
    578
    579 return SCIP_OKAY;
    580}
    581
    582/** frees specific constraint data */
    583static
    584SCIP_DECL_CONSDELETE(consDeleteDisjunction)
    585{ /*lint --e{715}*/
    586 SCIP_CALL( consdataFree(scip, consdata) );
    587
    588 return SCIP_OKAY;
    589}
    590
    591
    592/** transforms constraint data into data belonging to the transformed problem */
    593static
    594SCIP_DECL_CONSTRANS(consTransDisjunction)
    595{ /*lint --e{715}*/
    596 SCIP_CONSDATA* sourcedata;
    597 SCIP_CONSDATA* targetdata;
    598
    599 /* get constraint data of source constraint */
    600 sourcedata = SCIPconsGetData(sourcecons);
    601 assert(sourcedata != NULL);
    602
    603 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->conss, sourcedata->nconss, sourcedata->relaxcons) );
    604
    605 /* create target constraint */
    606 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
    607 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
    608 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
    609 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
    610 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
    611
    612 return SCIP_OKAY;
    613}
    614
    615/** LP initialization method of constraint handler */
    616static
    617SCIP_DECL_CONSINITLP(consInitlpDisjunction)
    618{ /*lint --e{715}*/
    619 SCIP_CONSDATA* consdata;
    620 int c;
    621
    622 *infeasible = FALSE;
    623
    624 for( c = 0; c < nconss; ++c )
    625 {
    626 consdata = SCIPconsGetData(conss[c]);
    627 assert(consdata != NULL);
    628
    629 /* if we have a relaxation constraint and it is not active, then we add it locally */
    630 if( consdata->relaxcons != NULL && !SCIPconsIsActive(consdata->relaxcons) )
    631 {
    632 SCIP_CALL( SCIPaddConsLocal(scip, consdata->relaxcons, NULL) );
    633 }
    634 }
    635
    636 return SCIP_OKAY;
    637}
    638
    639
    640/** constraint enforcing method of constraint handler for LP solutions */
    641static
    642SCIP_DECL_CONSENFOLP(consEnfolpDisjunction)
    643{ /*lint --e{715}*/
    644 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, NULL, result) );
    645
    646 return SCIP_OKAY;
    647}
    648
    649
    650/** constraint enforcing method of constraint handler for relaxation solutions */
    651static
    652SCIP_DECL_CONSENFORELAX(consEnforelaxDisjunction)
    653{ /*lint --e{715}*/
    654 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, sol, result) );
    655
    656 return SCIP_OKAY;
    657}
    658
    659
    660/** constraint enforcing method of constraint handler for pseudo solutions */
    661static
    662SCIP_DECL_CONSENFOPS(consEnfopsDisjunction)
    663{ /*lint --e{715}*/
    664 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, NULL, result) );
    665
    666 return SCIP_OKAY;
    667}
    668
    669
    670/** feasibility check method of constraint handler for integral solutions */
    671static
    672SCIP_DECL_CONSCHECK(consCheckDisjunction)
    673{ /*lint --e{715}*/
    674 int c;
    675
    676 *result = SCIP_FEASIBLE;
    677
    678 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
    679 {
    680 SCIP_RESULT tmpres;
    681
    682 /* check the disjunction */
    683 SCIP_CALL( checkCons(scip, conss[c], sol, checkintegrality, checklprows, printreason, &tmpres) );
    684 assert(tmpres == SCIP_FEASIBLE || tmpres == SCIP_INFEASIBLE);
    685
    686 if( tmpres == SCIP_INFEASIBLE )
    687 *result = SCIP_INFEASIBLE;
    688 }
    689
    690 return SCIP_OKAY;
    691}
    692
    693
    694/** domain propagation method of constraint handler */
    695static
    696SCIP_DECL_CONSPROP(consPropDisjunction)
    697{ /*lint --e{715}*/
    698 int ndelconss;
    699 int c;
    700
    701 ndelconss = 0;
    702
    703 /* in probing mode we do not for deletable constraints */
    704 if( !SCIPinProbing(scip) )
    705 {
    706 for( c = 0; c < nconss; ++c )
    707 {
    708 /* propagate constraint */
    709 SCIP_CALL( propagateCons(scip, conss[c], &ndelconss) );
    710 }
    711 }
    712
    713 /* adjust result code */
    714 if( ndelconss > 0 )
    715 *result = SCIP_REDUCEDDOM;
    716 else
    717 *result = SCIP_DIDNOTFIND;
    718
    719 return SCIP_OKAY;
    720}
    721
    722
    723/** presolving method of constraint handler */
    724static
    725SCIP_DECL_CONSPRESOL(consPresolDisjunction)
    726{ /*lint --e{715}*/
    727 SCIP_CONSDATA* consdata;
    728 int oldndelconss;
    729 int c;
    730
    731 assert(result != NULL);
    732
    733 *result = SCIP_DIDNOTFIND;
    734 oldndelconss = *ndelconss;
    735
    736 /* all disjunction constraints with one constraint can be replaced with that corresponding constraint */
    737 for( c = 0; c < nconss; ++c )
    738 {
    739 consdata = SCIPconsGetData(conss[c]);
    740 assert(consdata != NULL);
    741
    742 if( !SCIPconsIsModifiable(conss[c]) && consdata->nconss == 1 )
    743 {
    744 /* add constraint to the problem */
    745 if( !SCIPconsIsActive(consdata->conss[0]) )
    746 {
    747 SCIP_CONS* subcons = consdata->conss[0];
    748
    749 /* if disjunctive constraint needs to be checked, the upgraded constraint also needs to be checked */
    750 if( SCIPconsIsChecked(conss[c]) )
    751 {
    753 }
    754
    755 SCIP_CALL( SCIPaddCons(scip, subcons) );
    756 }
    757
    758 /* remove disjunction constraint */
    759 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
    760
    761 *result = SCIP_SUCCESS;
    762
    763 continue;
    764 }
    765
    766 /* propagate constraint */
    767 SCIP_CALL( propagateCons(scip, conss[c], ndelconss) );
    768 }
    769
    770 if( *ndelconss > oldndelconss )
    771 *result = SCIP_SUCCESS;
    772
    773 return SCIP_OKAY;
    774}
    775
    776
    777/** variable rounding lock method of constraint handler */
    778static
    779SCIP_DECL_CONSLOCK(consLockDisjunction)
    780{ /*lint --e{715}*/
    781 SCIP_CONSDATA* consdata;
    782 int c;
    783
    784 assert(locktype == SCIP_LOCKTYPE_MODEL);
    785
    786 consdata = SCIPconsGetData(cons);
    787 assert(consdata != NULL);
    788
    789 /* lock sub constraints */
    790 for( c = 0; c < consdata->nconss; ++c )
    791 {
    792 SCIP_CALL( SCIPaddConsLocksType(scip, consdata->conss[c], locktype, nlockspos, nlocksneg) );
    793 }
    794
    795 return SCIP_OKAY;
    796}
    797
    798
    799/** constraint display method of constraint handler */
    800static
    801SCIP_DECL_CONSPRINT(consPrintDisjunction)
    802{ /*lint --e{715}*/
    803 SCIP_CONSDATA* consdata;
    804 int i;
    805
    806 assert(scip != NULL);
    807 assert(conshdlr != NULL);
    808 assert(cons != NULL);
    809
    810 consdata = SCIPconsGetData(cons);
    811 assert(consdata != NULL);
    812
    813 SCIPinfoMessage(scip, file, "disjunction(");
    814
    815 for( i = 0; i < consdata->nconss; ++i )
    816 {
    817 if( i > 0 )
    818 SCIPinfoMessage(scip, file, ", ");
    819 SCIP_CALL( SCIPprintCons(scip, consdata->conss[i], file) );
    820 }
    821
    822 /* print relaxation */
    823 if( consdata->relaxcons != NULL )
    824 {
    825 SCIPinfoMessage(scip, file, ",, ");
    826 SCIP_CALL( SCIPprintCons(scip, consdata->relaxcons, file) );
    827 }
    828
    829 SCIPinfoMessage(scip, file, ")");
    830
    831 return SCIP_OKAY;
    832}
    833
    834/** constraint parsing method of constraint handler */
    835static
    836SCIP_DECL_CONSPARSE(consParseDisjunction)
    837{ /*lint --e{715}*/
    838 SCIP_CONS** conss;
    839 SCIP_Bool relaxed = FALSE;
    840 int nconss;
    841 int sconss;
    842 char* token;
    843 char* saveptr;
    844 char* nexttokenstart;
    845 char* copystr;
    846
    847 assert(scip != NULL);
    848 assert(conshdlr != NULL);
    849 assert(cons != NULL);
    850 assert(success != NULL);
    851 assert(str != NULL);
    852 assert(name != NULL);
    853
    854 SCIPdebugMsg(scip, "parsing disjunction <%s>\n", name);
    855
    856 *success = TRUE;
    857
    858 /* allocate memory for constraint in disjunction, initial size is set to 10 */
    859 nconss = 0;
    860 sconss = 10;
    861 SCIP_CALL( SCIPallocBufferArray(scip, &conss, sconss) );
    862 SCIP_CALL( SCIPduplicateBufferArray(scip, &copystr, str, (int)strlen(str)+1) );
    863
    864 /* find '(' at the beginning, string should start with 'disjunction(' */
    865 saveptr = strpbrk(copystr, "("); /*lint !e158*/
    866
    867 if( saveptr == NULL )
    868 {
    869 SCIPdebugMsg(scip, "error parsing disjunctive constraint: \"%s\"\n", str);
    870 *success = FALSE;
    871 goto TERMINATE;
    872 }
    873 assert(saveptr != NULL); /* for lint */
    874
    875 /* skip '(' */
    876 ++saveptr;
    877 /* remember token start position */
    878 nexttokenstart = saveptr;
    879
    880 /* brackets '(' and ')' can exist co we check for them and the constraint delimeter */
    881 saveptr = strpbrk(saveptr, "(,");
    882
    883 /* brackets '(' and ')' can exist in the rest of the string so we need to skip them to find the end of the first
    884 * sub-constraint marked by a ','
    885 */
    886 if( saveptr != NULL )
    887 {
    888 do
    889 {
    890 int bracketcounter = 0;
    891
    892 if( *saveptr == '(' )
    893 {
    894 do
    895 {
    896 ++bracketcounter;
    897 ++saveptr;
    898
    899 /* find last ending bracket */
    900 while( bracketcounter > 0 )
    901 {
    902 saveptr = strpbrk(saveptr, "()");
    903
    904 if( saveptr != NULL )
    905 {
    906 if( *saveptr == '(' )
    907 ++bracketcounter;
    908 else
    909 --bracketcounter;
    910
    911 ++saveptr;
    912 }
    913 else
    914 {
    915 SCIPdebugMsg(scip, "error parsing disjunctive constraint: \"%s\"\n", str);
    916 *success = FALSE;
    917 goto TERMINATE;
    918 }
    919 }
    920
    921 saveptr = strpbrk(saveptr, "(,");
    922 }
    923 while( saveptr != NULL && *saveptr == '(' );
    924 }
    925
    926 /* we found a ',' so the end of the first sub-constraint is determined */
    927 if( saveptr != NULL )
    928 {
    929 assert(*saveptr == ',');
    930
    931 /* resize constraint array if necessary */
    932 if( nconss == sconss )
    933 {
    934 sconss = SCIPcalcMemGrowSize(scip, nconss+1);
    935 assert(nconss < sconss);
    936
    937 SCIP_CALL( SCIPreallocBufferArray(scip, &conss, sconss) );
    938 }
    939
    940 assert(saveptr > nexttokenstart);
    941
    942 /* extract token for parsing */
    943 SCIP_CALL( SCIPduplicateBufferArray(scip, &token, nexttokenstart, saveptr - nexttokenstart + 1) );
    944 token[saveptr - nexttokenstart] = '\0';
    945
    946 SCIPdebugMsg(scip, "disjunctive parsing token(constraint): %s\n", token);
    947
    948 /* parsing a constraint, part of the disjunction */
    949 SCIP_CALL( SCIPparseCons(scip, &(conss[nconss]), token, initial, separate, enforce, FALSE, propagate, TRUE, modifiable, dynamic, removable, stickingatnode, success) );
    950
    951 SCIPfreeBufferArray(scip, &token);
    952
    953 if( *success )
    954 ++nconss;
    955 else
    956 {
    957 SCIPdebugMsg(scip, "error parsing disjunctive constraint: \"%s\"\n", str);
    958 goto TERMINATE;
    959 }
    960 /* skip ',' delimeter */
    961 ++saveptr;
    962 /* remember token start position */
    963 nexttokenstart = saveptr;
    964
    965 /* check if we found the last constraint, which is a conjunctive relaxation of the disjunction, and in the
    966 * CIP format marked by two consecutive ','
    967 */
    968 if( *nexttokenstart == ',' )
    969 {
    970 /* remember token start position */
    971 nexttokenstart = saveptr+1;
    972
    973 relaxed = TRUE;
    974 break;
    975 }
    976
    977 saveptr = strpbrk(saveptr, "(,");
    978 }
    979 }
    980 while( saveptr != NULL );
    981 }
    982
    983 /* find end of disjunction constraint */
    984 saveptr = strrchr(nexttokenstart, ')');
    985
    986 if( saveptr == NULL )
    987 {
    988 SCIPdebugMsg(scip, "error parsing disjunctive constraint: \"%s\"\n", str);
    989 *success = FALSE;
    990 goto TERMINATE;
    991 }
    992 /* parse last sub-constraint */
    993 else
    994 {
    995 /* resize constraint array if necessary */
    996 if( nconss == sconss )
    997 {
    998 ++sconss;
    999 SCIP_CALL( SCIPreallocBufferArray(scip, &conss, sconss) );
    1000 }
    1001
    1002 assert(saveptr > nexttokenstart);
    1003
    1004 /* extract token for parsing */
    1005 SCIP_CALL( SCIPduplicateBufferArray(scip, &token, nexttokenstart, saveptr - nexttokenstart + 1) );
    1006 token[saveptr - nexttokenstart] = '\0';
    1007
    1008 SCIPdebugMsg(scip, "disjunctive parsing token(constraint): %s\n", token);
    1009
    1010 /* parsing a constraint, part of the disjunction */
    1011 SCIP_CALL( SCIPparseCons(scip, &(conss[nconss]), token, initial, separate, enforce, FALSE, propagate, TRUE, modifiable, dynamic, removable, stickingatnode, success) );
    1012
    1013 if( *success )
    1014 ++nconss;
    1015
    1016 SCIPfreeBufferArray(scip, &token);
    1017 }
    1018 assert(nconss > 0 || !(*success));
    1019
    1020 /* if parsing sub-constraints was fine, create the disjunctive constraint */
    1021 if( *success )
    1022 {
    1023 /* create disjunctive constraint */
    1024 SCIP_CALL( SCIPcreateConsDisjunction(scip, cons, name, relaxed ? nconss - 1: nconss, conss, relaxed ? conss[nconss - 1] : NULL,
    1025 initial, enforce, check, local, modifiable, dynamic) );
    1026 }
    1027
    1028 /* free parsed constraints */
    1029 for( --nconss; nconss >= 0; --nconss )
    1030 {
    1031 SCIP_CALL( SCIPreleaseCons(scip, &conss[nconss]) );
    1032 }
    1033
    1034 TERMINATE:
    1035 /* free temporary memory */
    1036 SCIPfreeBufferArray(scip, &copystr);
    1037 SCIPfreeBufferArray(scip, &conss);
    1038
    1039 return SCIP_OKAY;
    1040}
    1041
    1042
    1043/** constraint copying method of constraint handler */
    1044static
    1045SCIP_DECL_CONSCOPY(consCopyDisjunction)
    1046{ /*lint --e{715}*/
    1047 SCIP_CONSDATA* sourcedata;
    1048 SCIP_CONS** sourceconss;
    1049 SCIP_CONS** conss;
    1050 int nconss;
    1051 int c;
    1052
    1053 *valid = TRUE;
    1054
    1055 sourcedata = SCIPconsGetData(sourcecons);
    1056 assert(sourcedata != NULL);
    1057
    1058 nconss = sourcedata->nconss;
    1059
    1060 SCIP_CALL( SCIPallocBufferArray(scip, &conss, nconss) );
    1061 sourceconss = sourcedata->conss;
    1062
    1063 /* copy each constraint one by one */
    1064 for( c = 0; c < nconss && (*valid); ++c )
    1065 {
    1066 SCIP_CALL( SCIPgetConsCopy(sourcescip, scip, sourceconss[c], &conss[c], SCIPconsGetHdlr(sourceconss[c]),
    1067 varmap, consmap, SCIPconsGetName(sourceconss[c]),
    1068 SCIPconsIsInitial(sourceconss[c]), SCIPconsIsSeparated(sourceconss[c]), SCIPconsIsEnforced(sourceconss[c]),
    1069 SCIPconsIsChecked(sourceconss[c]), SCIPconsIsPropagated(sourceconss[c]),
    1070 SCIPconsIsLocal(sourceconss[c]), SCIPconsIsModifiable(sourceconss[c]),
    1071 SCIPconsIsDynamic(sourceconss[c]), SCIPconsIsRemovable(sourceconss[c]), SCIPconsIsStickingAtNode(sourceconss[c]),
    1072 global, valid) );
    1073 assert(!(*valid) || conss[c] != NULL);
    1074 }
    1075
    1076 if( *valid )
    1077 {
    1078 SCIP_CONS* sourcerelaxcons;
    1079 SCIP_CONS* targetrelaxcons;
    1080
    1081 sourcerelaxcons = sourcedata->relaxcons;
    1082 targetrelaxcons = NULL;
    1083
    1084 if( sourcerelaxcons != NULL )
    1085 {
    1086 SCIP_CALL( SCIPgetConsCopy(sourcescip, scip, sourcerelaxcons, &targetrelaxcons, SCIPconsGetHdlr(sourcerelaxcons),
    1087 varmap, consmap, SCIPconsGetName(sourcerelaxcons),
    1088 SCIPconsIsInitial(sourcerelaxcons), SCIPconsIsSeparated(sourcerelaxcons), SCIPconsIsEnforced(sourcerelaxcons),
    1089 SCIPconsIsChecked(sourcerelaxcons), SCIPconsIsPropagated(sourcerelaxcons),
    1090 SCIPconsIsLocal(sourcerelaxcons), SCIPconsIsModifiable(sourcerelaxcons),
    1091 SCIPconsIsDynamic(sourcerelaxcons), SCIPconsIsRemovable(sourcerelaxcons),
    1092 SCIPconsIsStickingAtNode(sourcerelaxcons),
    1093 global, valid) );
    1094 }
    1095
    1096 if( *valid )
    1097 {
    1098 if( name == NULL )
    1099 {
    1100 SCIP_CALL( SCIPcreateConsDisjunction(scip, cons, SCIPconsGetName(sourcecons), nconss, conss, targetrelaxcons,
    1101 initial, enforce, check, local, modifiable, dynamic) );
    1102 }
    1103 else
    1104 {
    1105 SCIP_CALL( SCIPcreateConsDisjunction(scip, cons, name, nconss, conss, targetrelaxcons,
    1106 initial, enforce, check, local, modifiable, dynamic) );
    1107 }
    1108
    1109 if( targetrelaxcons != NULL )
    1110 {
    1111 SCIP_CALL( SCIPreleaseCons(scip, &targetrelaxcons) );
    1112 }
    1113 }
    1114 }
    1115
    1116 /* release the copied constraints */
    1117 for( c = (*valid ? c - 1 : c - 2); c >= 0; --c )
    1118 {
    1119 assert(conss[c] != NULL);
    1120 SCIP_CALL( SCIPreleaseCons(scip, &conss[c]) );
    1121 }
    1122
    1123 SCIPfreeBufferArray(scip, &conss);
    1124
    1125 return SCIP_OKAY;
    1126}
    1127
    1128
    1129/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
    1130static
    1131SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphDisjunction)
    1132{ /*lint --e{715}*/
    1133 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
    1134
    1135 return SCIP_OKAY;
    1136}
    1137
    1138
    1139/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
    1140static
    1141SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphDisjunction)
    1142{ /*lint --e{715}*/
    1143 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
    1144
    1145 return SCIP_OKAY;
    1146}
    1147
    1148
    1149/*
    1150 * constraint specific interface methods
    1151 */
    1152
    1153/** creates the handler for disjunction constraints and includes it in SCIP */
    1155 SCIP* scip /**< SCIP data structure */
    1156 )
    1157{
    1158 SCIP_CONSHDLRDATA* conshdlrdata;
    1159 SCIP_CONSHDLR* conshdlr;
    1160
    1161 /* create disjunction constraint handler data */
    1162 SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
    1163
    1164 /* include constraint handler */
    1167 consEnfolpDisjunction, consEnfopsDisjunction, consCheckDisjunction, consLockDisjunction,
    1168 conshdlrdata) );
    1169
    1170 assert(conshdlr != NULL);
    1171
    1172 /* set non-fundamental callbacks via specific setter functions */
    1173 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyDisjunction, consCopyDisjunction) );
    1174 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeDisjunction) );
    1175 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteDisjunction) );
    1176 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpDisjunction) );
    1177 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseDisjunction) );
    1178 SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolDisjunction, CONSHDLR_MAXPREROUNDS,
    1180 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintDisjunction) );
    1181 SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropDisjunction, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
    1183 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransDisjunction) );
    1184 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxDisjunction) );
    1185 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphDisjunction) );
    1186 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphDisjunction) );
    1187
    1189 "constraints/" CONSHDLR_NAME "/alwaysbranch",
    1190 "alawys perform branching if one of the constraints is violated, otherwise only if all integers are fixed",
    1191 &conshdlrdata->alwaysbranch, FALSE, DEFAULT_ALWAYSBRANCH, NULL, NULL) );
    1192
    1193 return SCIP_OKAY;
    1194}
    1195
    1196/** creates and captures a disjunction constraint
    1197 *
    1198 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    1199 */
    1201 SCIP* scip, /**< SCIP data structure */
    1202 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    1203 const char* name, /**< name of constraint */
    1204 int nconss, /**< number of initial constraints in disjunction */
    1205 SCIP_CONS** conss, /**< initial constraint in disjunction */
    1206 SCIP_CONS* relaxcons, /**< a conjunction constraint containing the linear relaxation of the disjunction constraint, or NULL */
    1207 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
    1208 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    1209 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    1210 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    1211 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    1212 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    1213 SCIP_Bool local, /**< is constraint only valid locally?
    1214 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    1215 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
    1216 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
    1217 * adds coefficients to this constraint. */
    1218 SCIP_Bool dynamic /**< is constraint subject to aging?
    1219 * Usually set to FALSE. Set to TRUE for own cuts which
    1220 * are separated as constraints. */
    1221 )
    1222{
    1223 SCIP_CONSHDLR* conshdlr;
    1224 SCIP_CONSDATA* consdata;
    1225
    1226 /* find the disjunction constraint handler */
    1227 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    1228 if( conshdlr == NULL )
    1229 {
    1230 SCIPerrorMessage("disjunction constraint handler not found\n");
    1231 return SCIP_PLUGINNOTFOUND;
    1232 }
    1233
    1234 /* create constraint data */
    1235 SCIP_CALL( consdataCreate(scip, &consdata, conss, nconss, relaxcons) );
    1236
    1237 /* create constraint */
    1238 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, FALSE, enforce, check, FALSE,
    1239 local, modifiable, dynamic, FALSE, FALSE) );
    1240
    1241 return SCIP_OKAY;
    1242}
    1243
    1244/** creates and captures a cumulative constraint
    1245 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
    1246 * method SCIPcreateConsDisjunction(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
    1247 *
    1248 * @see SCIPcreateConsDisjunction() for information about the basic constraint flag configuration
    1249 *
    1250 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    1251 */
    1253 SCIP* scip, /**< SCIP data structure */
    1254 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    1255 const char* name, /**< name of constraint */
    1256 int nconss, /**< number of initial constraints in disjunction */
    1257 SCIP_CONS** conss, /**< initial constraint in disjunction */
    1258 SCIP_CONS* relaxcons /**< a conjunction constraint containing the linear relaxation of the disjunction constraint, or NULL */
    1259 )
    1260{
    1261 assert(scip != NULL);
    1262
    1263 SCIP_CALL( SCIPcreateConsDisjunction(scip, cons, name, nconss, conss, relaxcons,
    1264 TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
    1265
    1266 return SCIP_OKAY;
    1267}
    1268
    1269
    1270/** adds constraint to the disjunction of constraints */
    1272 SCIP* scip, /**< SCIP data structure */
    1273 SCIP_CONS* cons, /**< disjunction constraint */
    1274 SCIP_CONS* addcons /**< additional constraint in disjunction */
    1275 )
    1276{
    1277 SCIP_CONSDATA* consdata;
    1278
    1279 assert(cons != NULL);
    1280 assert(addcons != NULL);
    1281
    1282 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
    1283 {
    1284 SCIPerrorMessage("constraint is not a disjunction constraint\n");
    1285 return SCIP_INVALIDDATA;
    1286 }
    1287
    1288 consdata = SCIPconsGetData(cons);
    1289 assert(consdata != NULL);
    1290
    1291 SCIP_CALL( consdataAddCons(scip, consdata, addcons) );
    1292
    1293 return SCIP_OKAY;
    1294}
    1295
    static SCIP_RETCODE branch(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_RESULT *result)
    static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, int *ndelconss)
    #define CONSHDLR_NEEDSCONS
    static SCIP_DECL_CONSPRESOL(consPresolDisjunction)
    #define CONSHDLR_CHECKPRIORITY
    #define CONSHDLR_DESC
    static SCIP_DECL_CONSCHECK(consCheckDisjunction)
    static SCIP_DECL_CONSTRANS(consTransDisjunction)
    static SCIP_DECL_CONSLOCK(consLockDisjunction)
    static SCIP_DECL_CONSFREE(consFreeDisjunction)
    static SCIP_DECL_CONSDELETE(consDeleteDisjunction)
    #define CONSHDLR_PROP_TIMING
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyDisjunction)
    static SCIP_DECL_CONSPROP(consPropDisjunction)
    static SCIP_RETCODE consdataAddCons(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_CONS *cons)
    #define CONSHDLR_MAXPREROUNDS
    static SCIP_RETCODE branchCons(SCIP *scip, SCIP_CONS *cons, SCIP_RESULT *result)
    static SCIP_DECL_CONSPRINT(consPrintDisjunction)
    static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
    static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_RESULT *result)
    static SCIP_DECL_CONSCOPY(consCopyDisjunction)
    static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_CONS **conss, int nconss, SCIP_CONS *relaxcons)
    static SCIP_DECL_CONSENFOLP(consEnfolpDisjunction)
    #define CONSHDLR_PROPFREQ
    static SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphDisjunction)
    #define CONSHDLR_PRESOLTIMING
    static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
    static SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphDisjunction)
    static SCIP_DECL_CONSENFOPS(consEnfopsDisjunction)
    #define CONSHDLR_EAGERFREQ
    #define CONSHDLR_ENFOPRIORITY
    #define DEFAULT_ALWAYSBRANCH
    static SCIP_DECL_CONSINITLP(consInitlpDisjunction)
    static SCIP_DECL_CONSPARSE(consParseDisjunction)
    static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, SCIP_SOL *sol, SCIP_RESULT *result)
    #define CONSHDLR_NAME
    static SCIP_DECL_CONSENFORELAX(consEnforelaxDisjunction)
    #define CONSHDLR_DELAYPROP
    constraint handler for disjunction constraints
    #define NULL
    Definition: def.h:248
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPcreateConsBasicDisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nconss, SCIP_CONS **conss, SCIP_CONS *relaxcons)
    SCIP_RETCODE SCIPaddConsElemDisjunction(SCIP *scip, SCIP_CONS *cons, SCIP_CONS *addcons)
    SCIP_RETCODE SCIPcreateConsDisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nconss, SCIP_CONS **conss, SCIP_CONS *relaxcons, SCIP_Bool initial, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic)
    SCIP_RETCODE SCIPincludeConshdlrDisjunction(SCIP *scip)
    SCIP_RETCODE SCIPgetConsCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_CONS *sourcecons, SCIP_CONS **targetcons, SCIP_CONSHDLR *sourceconshdlr, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *name, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
    Definition: scip_copy.c:1580
    SCIP_Bool SCIPisTransformed(SCIP *scip)
    Definition: scip_general.c:647
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    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
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    SCIP_RETCODE SCIPdelConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons)
    Definition: scip_prob.c:4017
    SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:4067
    SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
    Definition: scip_prob.c:3901
    SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
    Definition: scip_prob.c:3986
    SCIP_Real SCIPgetLocalTransEstimate(SCIP *scip)
    Definition: scip_prob.c:4139
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #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 SCIPcreateChild(SCIP *scip, SCIP_NODE **node, SCIP_Real nodeselprio, SCIP_Real estimate)
    Definition: scip_branch.c:1025
    int SCIPgetNPseudoBranchCands(SCIP *scip)
    Definition: scip_branch.c:766
    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 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_Bool SCIPconshdlrSupportsSignedPermsymDetection(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:5456
    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 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_Bool SCIPconshdlrSupportsPermsymDetection(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:5446
    SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
    Definition: scip_cons.c:624
    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 SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
    Definition: scip_cons.c:785
    SCIP_RETCODE SCIPgetConsSignedPermsymGraph(SCIP *scip, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
    Definition: scip_cons.c:2687
    SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
    Definition: cons.c:8419
    SCIP_RETCODE SCIPcheckCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_RESULT *result)
    Definition: scip_cons.c:2135
    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
    SCIP_RETCODE SCIPtransformConss(SCIP *scip, int nconss, SCIP_CONS **conss, SCIP_CONS **transconss)
    Definition: scip_cons.c:1625
    SCIP_RETCODE SCIPgetConsPermsymGraph(SCIP *scip, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
    Definition: scip_cons.c:2654
    SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8588
    SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
    Definition: cons.c:8518
    SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
    Definition: cons.c:8578
    SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
    Definition: cons.c:8450
    SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    Definition: scip_cons.c:997
    SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
    Definition: cons.c:8608
    SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
    Definition: cons.c:8628
    SCIP_RETCODE SCIPaddConsLocksType(SCIP *scip, SCIP_CONS *cons, SCIP_LOCKTYPE locktype, int nlockspos, int nlocksneg)
    Definition: scip_cons.c:2072
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8389
    SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1812
    SCIP_RETCODE SCIPsetConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_Bool local)
    Definition: scip_cons.c:1398
    SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
    Definition: cons.c:8638
    SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
    Definition: cons.c:8668
    SCIP_RETCODE SCIPparseCons(SCIP *scip, SCIP_CONS **cons, const char *str, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool *success)
    Definition: scip_cons.c:1081
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_RETCODE SCIPtransformCons(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **transcons)
    Definition: scip_cons.c:1584
    SCIP_RETCODE SCIPsetConsChecked(SCIP *scip, SCIP_CONS *cons, SCIP_Bool check)
    Definition: scip_cons.c:1346
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8568
    SCIP_RETCODE SCIPcaptureCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1138
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8658
    #define SCIPensureBlockMemoryArray(scip, ptr, arraysizeptr, minsize)
    Definition: scip_mem.h:107
    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 SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
    Definition: scip_mem.h:111
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    #define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:105
    SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
    Definition: tree.c:8483
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    void SCIPupdateSolConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
    Definition: scip_sol.c:453
    void SCIPdeactivateSolViolationUpdates(SCIP *scip)
    Definition: scip_sol.c:493
    void SCIPactivateSolViolationUpdates(SCIP *scip)
    Definition: scip_sol.c:485
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    SCIP_RETCODE SCIPaddSymgraphEdge(SCIP *scip, SYM_GRAPH *graph, int first, int second, SCIP_Bool hasval, SCIP_Real val)
    SCIP_RETCODE SCIPfreeSymgraph(SCIP *scip, SYM_GRAPH **graph)
    SCIP_RETCODE SCIPcreateSymgraph(SCIP *scip, SYM_SYMTYPE symtype, SYM_GRAPH **graph, SCIP_VAR **symvars, int nsymvars, int nopnodes, int nvalnodes, int nconsnodes, int nedges)
    SCIP_RETCODE SCIPcopySymgraphAsSubgraph(SCIP *scip, SYM_GRAPH *sourcegraph, SYM_GRAPH *targetgraph, SCIP_CONS *sourcecons, int *rootidx)
    SCIP_RETCODE SCIPaddSymgraphConsnode(SCIP *scip, SYM_GRAPH *graph, SCIP_CONS *cons, SCIP_Real lhs, SCIP_Real rhs, int *nodeidx)
    SCIP_RETCODE SCIPclearSymgraph(SCIP *scip, SYM_GRAPH *graph, SCIP_VAR **symvars, int nsymvars, SYM_SYMTYPE symtype)
    memory allocation routines
    public methods for managing constraints
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    public methods for branch and bound tree
    public methods for branching rule plugins and branching
    public methods for constraint handler plugins and constraints
    public methods for problem copies
    general public methods
    public methods for memory management
    public methods for message handling
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for the probing mode
    public methods for solutions
    public methods for querying solving statistics
    public methods for the branch-and-bound tree
    static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
    Main separation function.
    Definition: sepa_flower.c:1221
    SCIP_CONS ** conss
    methods for dealing with symmetry detection graphs
    struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
    Definition: type_cons.h:64
    struct SCIP_ConsData SCIP_CONSDATA
    Definition: type_cons.h:65
    @ SCIP_FEASIBLE
    Definition: type_result.h:45
    @ SCIP_REDUCEDDOM
    Definition: type_result.h:51
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_BRANCHED
    Definition: type_result.h:54
    @ 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_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_PRESOLVING
    Definition: type_set.h:49
    enum SYM_Symtype SYM_SYMTYPE
    Definition: type_symmetry.h:64
    @ SYM_SYMTYPE_SIGNPERM
    Definition: type_symmetry.h:62
    @ SYM_SYMTYPE_PERM
    Definition: type_symmetry.h:61
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141