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