SCIP

    Solving Constraint Integer Programs

    cons_conjunction.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_conjunction.c
    26 * @ingroup DEFPLUGINS_CONS
    27 * @brief constraint handler for conjunction constraints
    28 * @author Tobias Achterberg
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    35#include "scip/pub_cons.h"
    36#include "scip/pub_message.h"
    37#include "scip/scip_cons.h"
    38#include "scip/scip_copy.h"
    39#include "scip/scip_general.h"
    40#include "scip/scip_mem.h"
    41#include "scip/scip_message.h"
    42#include "scip/scip_prob.h"
    43#include "scip/scip_sol.h"
    44
    45
    46/* constraint handler properties */
    47#define CONSHDLR_NAME "conjunction"
    48#define CONSHDLR_DESC "conjunction of constraints"
    49#define CONSHDLR_ENFOPRIORITY +900000 /**< priority of the constraint handler for constraint enforcing */
    50#define CONSHDLR_CHECKPRIORITY -900000 /**< priority of the constraint handler for checking feasibility */
    51#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
    52 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    53#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
    54#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
    55
    56#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_FAST
    57
    58/*
    59 * Data structures
    60 */
    61
    62/** constraint data for conjunction constraints */
    63struct SCIP_ConsData
    64{
    65 SCIP_CONS** conss; /**< constraints in conjunction */
    66 int consssize; /**< size of conss array */
    67 int nconss; /**< number of constraints in conjunction */
    68};
    69
    70
    71/*
    72 * Local methods
    73 */
    74
    75/** creates conjunction constraint data, captures initial constraints of conjunction */
    76static
    78 SCIP* scip, /**< SCIP data structure */
    79 SCIP_CONSDATA** consdata, /**< pointer to constraint data */
    80 SCIP_CONS** conss, /**< initial constraint in conjunction */
    81 int nconss /**< number of initial constraints in conjunction */
    82 )
    83{
    84 assert(consdata != NULL);
    85
    87 if( nconss > 0 )
    88 {
    89 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->conss, conss, nconss) );
    90 (*consdata)->consssize = nconss;
    91 (*consdata)->nconss = nconss;
    92
    94 {
    95 SCIP_CALL( SCIPtransformConss(scip, nconss, (*consdata)->conss, (*consdata)->conss) );
    96 }
    97 else
    98 {
    99 int c;
    100
    101 for( c = 0; c < nconss; ++c )
    102 {
    103 SCIP_CALL( SCIPcaptureCons(scip, conss[c]) );
    104 }
    105 }
    106 }
    107 else
    108 {
    109 (*consdata)->conss = NULL;
    110 (*consdata)->consssize = 0;
    111 (*consdata)->nconss = 0;
    112 }
    113
    114 return SCIP_OKAY;
    115}
    116
    117/** frees constraint data and releases all constraints in conjunction */
    118static
    120 SCIP* scip, /**< SCIP data structure */
    121 SCIP_CONSDATA** consdata /**< pointer to constraint data */
    122 )
    123{
    124 int c;
    125
    126 assert(consdata != NULL);
    127 assert(*consdata != NULL);
    128
    129 /* release constraints */
    130 for( c = 0; c < (*consdata)->nconss; ++c )
    131 {
    132 SCIP_CALL( SCIPreleaseCons(scip, &(*consdata)->conss[c]) );
    133 }
    134
    135 /* free memory */
    136 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->conss, (*consdata)->consssize);
    137 SCIPfreeBlockMemory(scip, consdata);
    138
    139 return SCIP_OKAY;
    140}
    141
    142/** adds constraint to conjunction */
    143static
    145 SCIP* scip, /**< SCIP data structure */
    146 SCIP_CONSDATA* consdata, /**< constraint data */
    147 SCIP_CONS* cons /**< constraint to add to the conjunction */
    148 )
    149{
    150 assert(consdata != NULL);
    151
    152 /* get memory for additional constraint */
    153 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &consdata->conss, &consdata->consssize, consdata->nconss+1) );
    154 assert(consdata->conss != NULL);
    155 assert(consdata->nconss < consdata->consssize);
    156
    157 /* insert constraint in array */
    158 consdata->conss[consdata->nconss] = cons;
    159 consdata->nconss++;
    160
    162 {
    163 SCIP_CALL( SCIPtransformCons(scip, consdata->conss[consdata->nconss - 1], &(consdata->conss[consdata->nconss - 1])) );
    164 }
    165 else
    166 {
    167 /* capture constraint */
    169 }
    170
    171 return SCIP_OKAY;
    172}
    173
    174/** adds all constraints in conjunction constraints to the problem; disables unmodifiable conjunction constraints */
    175static
    177 SCIP* scip, /**< SCIP data structure */
    178 SCIP_CONS** conss, /**< active conjunction constraints */
    179 int nconss, /**< number of active conjunction constraints */
    180 SCIP_RESULT* result /**< pointer to store the result */
    181 )
    182{
    183 SCIP_CONSDATA* consdata;
    184 int c;
    185 int i;
    186
    187 assert(result != NULL);
    188
    189 for( c = 0; c < nconss; ++c )
    190 {
    191 consdata = SCIPconsGetData(conss[c]);
    192 assert(consdata != NULL);
    193
    194 /* add all inactive constraints to local subproblem */
    195 for( i = 0; i < consdata->nconss; ++i )
    196 {
    197 /* update check flag for sub constraints when upgrade takes place */
    198 if( SCIPconsIsChecked(conss[c]) )
    199 {
    200 /* make sure, the constraint is checked for feasibility */
    201 SCIP_CALL( SCIPsetConsChecked(scip, consdata->conss[i], TRUE) );
    202 }
    203
    204 if( !SCIPconsIsActive(consdata->conss[i]) )
    205 {
    206 SCIPdebugMsg(scip, "adding constraint <%s> from add conjunction <%s>\n",
    207 SCIPconsGetName(consdata->conss[i]), SCIPconsGetName(conss[c]));
    208 SCIP_CALL( SCIPaddConsLocal(scip, consdata->conss[i], NULL) );
    209 *result = SCIP_CONSADDED;
    210 }
    211 }
    212
    213 /* disable conjunction constraint, if it is unmodifiable */
    214 if( !SCIPconsIsModifiable(conss[c]) )
    215 {
    216 SCIP_CALL( SCIPdelConsLocal(scip, conss[c]) );
    217 }
    218 }
    219
    220 return SCIP_OKAY;
    221}
    222
    223/** checks all constraints in conjunction constraints for feasibility */
    224static
    226 SCIP* scip, /**< SCIP data structure */
    227 SCIP_CONS** conss, /**< active conjunction constraints */
    228 int nconss, /**< number of active conjunction constraints */
    229 SCIP_SOL* sol, /**< solution to check */
    230 SCIP_Bool checkintegrality, /**< Has integrality to be checked? */
    231 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
    232 SCIP_Bool printreason, /**< Should the reason for the violation be printed? */
    233 SCIP_Bool completely, /**< Should all violations be checked? */
    234 SCIP_RESULT* result /**< pointer to store the result */
    235 )
    236{
    237 SCIP_CONSDATA* consdata;
    238 int c;
    239 int i;
    240
    241 assert(result != NULL);
    242
    243 *result = SCIP_FEASIBLE;
    244
    245 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
    246 {
    247 SCIP_RESULT subresult = SCIP_FEASIBLE;
    248
    249 consdata = SCIPconsGetData(conss[c]);
    250 assert(consdata != NULL);
    251
    252 /* check all constraints */
    253 for( i = 0; i < consdata->nconss && subresult == SCIP_FEASIBLE; ++i )
    254 {
    255 SCIP_CALL( SCIPcheckCons(scip, consdata->conss[i], sol, checkintegrality, checklprows, printreason, &subresult) );
    256 assert(subresult == SCIP_FEASIBLE || subresult == SCIP_INFEASIBLE);
    257 }
    258
    259 if( subresult == SCIP_INFEASIBLE )
    260 {
    261 /* mark solution as violated */
    262 *result = SCIP_INFEASIBLE;
    263 /* update constraint violation in solution */
    264 if ( sol != NULL )
    265 SCIPupdateSolConsViolation(scip, sol, 1.0, 1.0);
    266 if( printreason )
    267 {
    268 assert( 0 < i && i <= consdata->nconss );
    269 SCIPinfoMessage(scip, NULL, "Conjunction constraint %s is violated, at least the sub-constraint %s is violated by this given solution.\n",
    270 SCIPconsGetName(conss[c]), SCIPconsGetName(consdata->conss[i-1]));
    271 SCIPdebug( SCIP_CALL( SCIPprintCons(scip, conss[c], NULL) ) );
    272 }
    273 }
    274 }
    275
    276 return SCIP_OKAY;
    277}
    278
    279
    280/*
    281 * Callback methods of constraint handler
    282 */
    283
    284
    285 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
    286static
    287SCIP_DECL_CONSHDLRCOPY(conshdlrCopyConjunction)
    288{ /*lint --e{715}*/
    289 assert(scip != NULL);
    290 assert(conshdlr != NULL);
    291
    293
    294 /* call inclusion method of constraint handler */
    296
    297 *valid = TRUE;
    298
    299 return SCIP_OKAY;
    300}
    301
    302
    303/** frees specific constraint data */
    304static
    305SCIP_DECL_CONSDELETE(consDeleteConjunction)
    306{ /*lint --e{715}*/
    307 SCIP_CALL( consdataFree(scip, consdata) );
    308
    309 return SCIP_OKAY;
    310}
    311
    312/** transforms constraint data into data belonging to the transformed problem */
    313static
    314SCIP_DECL_CONSTRANS(consTransConjunction)
    315{ /*lint --e{715}*/
    316 SCIP_CONSDATA* sourcedata;
    317 SCIP_CONSDATA* targetdata;
    318 int c;
    319
    320 /* create constraint data for target constraint */
    321 SCIP_CALL( SCIPallocBlockMemory(scip, &targetdata) );
    322
    323 /* get constraint data of source constraint */
    324 sourcedata = SCIPconsGetData(sourcecons);
    325
    326 if( sourcedata->nconss > 0 )
    327 {
    328 targetdata->consssize = sourcedata->nconss;
    329 targetdata->nconss = sourcedata->nconss;
    330 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &targetdata->conss, targetdata->consssize) );
    331 for( c = 0; c < sourcedata->nconss; ++c )
    332 {
    333 SCIP_CALL( SCIPtransformCons(scip, sourcedata->conss[c], &targetdata->conss[c]) );
    334 }
    335 }
    336 else
    337 {
    338 targetdata->conss = NULL;
    339 targetdata->consssize = 0;
    340 targetdata->nconss = 0;
    341 }
    342
    343 /* create target constraint */
    344 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
    345 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
    346 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
    347 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
    348 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
    349
    350 return SCIP_OKAY;
    351}
    352
    353
    354/** constraint enforcing method of constraint handler for LP solutions */
    355static
    356SCIP_DECL_CONSENFOLP(consEnfolpConjunction)
    357{ /*lint --e{715}*/
    358 *result = SCIP_FEASIBLE;
    359
    360 /* add all constraints to the current node */
    361 SCIP_CALL( addAllConss(scip, conss, nconss, result) );
    362
    363 return SCIP_OKAY;
    364}
    365
    366
    367/** constraint enforcing method of constraint handler for relaxation solutions */
    368static
    369SCIP_DECL_CONSENFORELAX(consEnforelaxConjunction)
    370{ /*lint --e{715}*/
    371 *result = SCIP_FEASIBLE;
    372
    373 /* add all constraints to the current node */
    374 SCIP_CALL( addAllConss(scip, conss, nconss, result) );
    375
    376 return SCIP_OKAY;
    377}
    378
    379
    380/** constraint enforcing method of constraint handler for pseudo solutions */
    381static
    382SCIP_DECL_CONSENFOPS(consEnfopsConjunction)
    383{ /*lint --e{715}*/
    384 *result = SCIP_FEASIBLE;
    385
    386 /* add all constraints to the current node */
    387 SCIP_CALL( addAllConss(scip, conss, nconss, result) );
    388
    389 return SCIP_OKAY;
    390}
    391
    392
    393/** feasibility check method of constraint handler for integral solutions */
    394static
    395SCIP_DECL_CONSCHECK(consCheckConjunction)
    396{ /*lint --e{715}*/
    397 *result = SCIP_FEASIBLE;
    398
    399 /* check all constraints of the conjunction */
    400 SCIP_CALL( checkAllConss(scip, conss, nconss, sol, checkintegrality, checklprows, printreason, completely, result) );
    401
    402 return SCIP_OKAY;
    403}
    404
    405
    406/** presolving method of constraint handler */
    407static
    408SCIP_DECL_CONSPRESOL(consPresolConjunction)
    409{ /*lint --e{715}*/
    410 SCIP_CONSDATA* consdata;
    411 int c;
    412 int i;
    413
    414 assert(result != NULL);
    415
    416 *result = SCIP_DIDNOTFIND;
    417
    418 /* all constraints in a conjunction constraint of the global problem can be added directly to the problem and
    419 * removed from the conjunction constraint;
    420 * an unmodifiable conjunction constraint can be deleted
    421 */
    422 for( c = 0; c < nconss; ++c )
    423 {
    424 consdata = SCIPconsGetData(conss[c]);
    425 assert(consdata != NULL);
    426
    427 /* add all inactive constraints to the global problem */
    428 for( i = 0; i < consdata->nconss; ++i )
    429 {
    430 /* update check flag for sub constraints when upgrade takes place */
    431 if( SCIPconsIsChecked(conss[c]) )
    432 {
    433 /* make sure, the constraint is checked for feasibility */
    434 SCIP_CALL( SCIPsetConsChecked(scip, consdata->conss[i], TRUE) );
    435 }
    436
    437 /* add constraint, if it is not active yet */
    438 if( !SCIPconsIsActive(consdata->conss[i]) )
    439 {
    440 SCIPdebugMsg(scip, "adding constraint <%s> from add conjunction <%s>\n",
    441 SCIPconsGetName(consdata->conss[i]), SCIPconsGetName(conss[c]));
    442 SCIP_CALL( SCIPaddCons(scip, consdata->conss[i]) );
    443 *result = SCIP_SUCCESS;
    444 }
    445 /* release constraint because it will be removed from the conjunction constraint */
    446 SCIP_CALL( SCIPreleaseCons(scip, &(consdata->conss[i])) );
    447 }
    448 /* all constraints where removed, so we need to clear the array */
    449 consdata->nconss = 0;
    450
    451 /* delete conjunction constraint, if it is unmodifiable */
    452 if( !SCIPconsIsModifiable(conss[c]) )
    453 {
    454 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
    455 }
    456 }
    457
    458 return SCIP_OKAY;
    459}
    460
    461
    462/** variable rounding lock method of constraint handler */
    463static
    464SCIP_DECL_CONSLOCK(consLockConjunction)
    465{ /*lint --e{715}*/
    466 SCIP_CONSDATA* consdata;
    467 int c;
    468
    469 assert(locktype == SCIP_LOCKTYPE_MODEL);
    470
    471 consdata = SCIPconsGetData(cons);
    472 assert(consdata != NULL);
    473
    474 /* lock sub constraints */
    475 for( c = 0; c < consdata->nconss; ++c )
    476 {
    477 SCIP_CALL( SCIPaddConsLocksType(scip, consdata->conss[c], locktype, nlockspos, nlocksneg) );
    478 }
    479
    480 return SCIP_OKAY;
    481}
    482
    483
    484/** constraint display method of constraint handler */
    485static
    486SCIP_DECL_CONSPRINT(consPrintConjunction)
    487{ /*lint --e{715}*/
    488 SCIP_CONSDATA* consdata;
    489 int i;
    490
    491 assert( scip != NULL );
    492 assert( conshdlr != NULL );
    493 assert( cons != NULL );
    494
    495 consdata = SCIPconsGetData(cons);
    496 assert(consdata != NULL);
    497
    498 SCIPinfoMessage(scip, file, "conjunction(");
    499
    500 for( i = 0; i < consdata->nconss; ++i )
    501 {
    502 if( i > 0 )
    503 SCIPinfoMessage(scip, file, ", ");
    504 SCIP_CALL( SCIPprintCons(scip, consdata->conss[i], file) );
    505 }
    506 SCIPinfoMessage(scip, file, ")");
    507
    508 return SCIP_OKAY;
    509}
    510
    511/** constraint parsing method of constraint handler */
    512static
    513SCIP_DECL_CONSPARSE(consParseConjunction)
    514{ /*lint --e{715}*/
    515 SCIP_CONS** conss;
    516 int nconss;
    517 int sconss;
    518 char* token;
    519 char* saveptr;
    520 char* nexttokenstart;
    521 char* copystr;
    522
    523 assert(scip != NULL);
    524 assert(conshdlr != NULL);
    525 assert(cons != NULL);
    526 assert(success != NULL);
    527 assert(str != NULL);
    528 assert(name != NULL);
    529
    530 SCIPdebugMsg(scip, "parsing conjunction <%s>\n", name);
    531
    532 *success = TRUE;
    533
    534 /* allocate memory for constraint in conjunction, initial size is set to 10 */
    535 nconss = 0;
    536 sconss = 10;
    537 SCIP_CALL( SCIPallocBufferArray(scip, &conss, sconss) );
    538 SCIP_CALL( SCIPduplicateBufferArray(scip, &copystr, str, (int)strlen(str)+1) );
    539
    540 /* find '(' at the beginning, string should start with 'conjunction(' */
    541 saveptr = strpbrk(copystr, "("); /*lint !e158*/
    542
    543 if( saveptr == NULL )
    544 {
    545 SCIPdebugMsg(scip, "error parsing conjunctive constraint: \"%s\"\n", str);
    546 *success = FALSE;
    547 goto TERMINATE;
    548 }
    549 assert(saveptr != NULL); /* for lint */
    550
    551 /* skip '(' */
    552 ++saveptr;
    553 /* remember token start position */
    554 nexttokenstart = saveptr;
    555
    556 /* brackets '(' and ')' can exist co we check for them and the constraint delimeter */
    557 saveptr = strpbrk(saveptr, "(,");
    558
    559 /* brackets '(' and ')' can exist in the rest of the string so we need to skip them to find the end of the first
    560 * sub-constraint marked by a ','
    561 */
    562 if( saveptr != NULL )
    563 {
    564 do
    565 {
    566 int bracketcounter = 0;
    567
    568 if( *saveptr == '(' )
    569 {
    570 do
    571 {
    572 ++bracketcounter;
    573 ++saveptr;
    574
    575 /* find last ending bracket */
    576 while( bracketcounter > 0 )
    577 {
    578 saveptr = strpbrk(saveptr, "()");
    579
    580 if( saveptr != NULL )
    581 {
    582 if( *saveptr == '(' )
    583 ++bracketcounter;
    584 else
    585 --bracketcounter;
    586
    587 ++saveptr;
    588 }
    589 else
    590 {
    591 SCIPdebugMsg(scip, "error parsing conjunctive constraint: \"%s\"\n", str);
    592 *success = FALSE;
    593 goto TERMINATE;
    594 }
    595 }
    596
    597 saveptr = strpbrk(saveptr, "(,");
    598 }
    599 while( saveptr != NULL && *saveptr == '(' );
    600 }
    601
    602 /* we found a ',' so the end of the first sub-constraint is determined */
    603 if( saveptr != NULL )
    604 {
    605 assert(*saveptr == ',');
    606
    607 /* resize constraint array if necessary */
    608 if( nconss == sconss )
    609 {
    610 sconss = SCIPcalcMemGrowSize(scip, nconss+1);
    611 assert(nconss < sconss);
    612
    613 SCIP_CALL( SCIPreallocBufferArray(scip, &conss, sconss) );
    614 }
    615 assert(nexttokenstart != NULL); /* for lint */
    616 assert(saveptr > nexttokenstart);
    617
    618 /* extract token for parsing */
    619 SCIP_CALL( SCIPduplicateBufferArray(scip, &token, nexttokenstart, saveptr - nexttokenstart + 1) );
    620 token[saveptr - nexttokenstart] = '\0';
    621
    622 SCIPdebugMsg(scip, "conjunctive parsing token(constraint): %s\n", token);
    623
    624 /* parsing a constraint, part of the conjunction */
    625 SCIP_CALL( SCIPparseCons(scip, &(conss[nconss]), token, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, success) );
    626
    627 SCIPfreeBufferArray(scip, &token);
    628
    629 if( *success )
    630 ++nconss;
    631 else
    632 {
    633 SCIPdebugMsg(scip, "error parsing conjunctive constraint: \"%s\"\n", str);
    634 goto TERMINATE;
    635 }
    636 /* skip ',' delimeter */
    637 ++saveptr;
    638 /* remember token start position */
    639 nexttokenstart = saveptr;
    640
    641 saveptr = strpbrk(saveptr, "(,");
    642 }
    643 }
    644 while( saveptr != NULL );
    645 }
    646
    647 /* find end of conjunction constraint */
    648 saveptr = strrchr(nexttokenstart, ')');
    649
    650 if( saveptr == NULL )
    651 {
    652 SCIPdebugMsg(scip, "error parsing conjunctive constraint: \"%s\"\n", str);
    653 *success = FALSE;
    654 goto TERMINATE;
    655 }
    656 /* parse last sub-constraint */
    657 else
    658 {
    659 /* resize constraint array if necessary */
    660 if( nconss == sconss )
    661 {
    662 ++sconss;
    663 SCIP_CALL( SCIPreallocBufferArray(scip, &conss, sconss) );
    664 }
    665
    666 assert(saveptr > nexttokenstart);
    667
    668 /* extract token for parsing */
    669 SCIP_CALL( SCIPduplicateBufferArray(scip, &token, nexttokenstart, saveptr - nexttokenstart + 1) );
    670 token[saveptr - nexttokenstart] = '\0';
    671
    672 SCIPdebugMsg(scip, "conjunctive parsing token(constraint): %s\n", token);
    673
    674 /* parsing a constraint, part of the conjunction */
    675 SCIP_CALL( SCIPparseCons(scip, &(conss[nconss]), token, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, success) );
    676
    677 if( *success )
    678 ++nconss;
    679
    680 SCIPfreeBufferArray(scip, &token);
    681 }
    682 assert(nconss > 0 || !(*success));
    683
    684 /* if parsing sub-constraints was fine, create the conjunctive constraint */
    685 if( *success )
    686 {
    687 /* create conjunctive constraint */
    688 SCIP_CALL( SCIPcreateConsConjunction(scip, cons, name, nconss, conss,
    689 enforce, check, local, modifiable, dynamic) );
    690 }
    691
    692 /* free parsed constraints */
    693 for( --nconss; nconss >= 0; --nconss )
    694 {
    695 SCIP_CALL( SCIPreleaseCons(scip, &conss[nconss]) );
    696 }
    697
    698 TERMINATE:
    699 /* free temporary memory */
    700 SCIPfreeBufferArray(scip, &copystr);
    701 SCIPfreeBufferArray(scip, &conss);
    702
    703 return SCIP_OKAY;
    704}
    705
    706/** constraint copying method of constraint handler */
    707static
    708SCIP_DECL_CONSCOPY(consCopyConjunction)
    709{ /*lint --e{715}*/
    710 SCIP_CONSDATA* sourcedata;
    711 SCIP_CONS** sourceconss;
    712 SCIP_CONS** conss;
    713 int nconss;
    714 int c;
    715
    716 *valid = TRUE;
    717
    718 sourcedata = SCIPconsGetData(sourcecons);
    719 assert(sourcedata != NULL);
    720
    721 sourceconss = sourcedata->conss;
    722 nconss = sourcedata->nconss;
    723
    724 if( nconss > 0 )
    725 {
    726 assert(sourceconss != NULL);
    727
    728 SCIP_CALL( SCIPallocBufferArray(scip, &conss, nconss) );
    729
    730 /* copy each constraint one by one */
    731 for( c = 0; c < nconss && (*valid); ++c )
    732 {
    733 SCIP_CALL( SCIPgetConsCopy(sourcescip, scip, sourceconss[c], &conss[c], SCIPconsGetHdlr(sourceconss[c]),
    734 varmap, consmap, SCIPconsGetName(sourceconss[c]),
    735 SCIPconsIsInitial(sourceconss[c]), SCIPconsIsSeparated(sourceconss[c]), SCIPconsIsEnforced(sourceconss[c]),
    736 SCIPconsIsChecked(sourceconss[c]), SCIPconsIsPropagated(sourceconss[c]),
    737 SCIPconsIsLocal(sourceconss[c]), SCIPconsIsModifiable(sourceconss[c]),
    738 SCIPconsIsDynamic(sourceconss[c]), SCIPconsIsRemovable(sourceconss[c]), SCIPconsIsStickingAtNode(sourceconss[c]),
    739 global, valid) );
    740 assert(!(*valid) || conss[c] != NULL);
    741 }
    742
    743 if( *valid )
    744 {
    745 if( name == NULL )
    746 {
    747 SCIP_CALL( SCIPcreateConsConjunction(scip, cons, SCIPconsGetName(sourcecons), nconss, conss,
    748 enforce, check, local, modifiable, dynamic) );
    749 }
    750 else
    751 {
    752 SCIP_CALL( SCIPcreateConsConjunction(scip, cons, name, nconss, conss,
    753 enforce, check, local, modifiable, dynamic) );
    754 }
    755 }
    756
    757 /* release the copied constraints */
    758 for( c = (*valid ? c - 1 : c - 2); c >= 0; --c )
    759 {
    760 assert(conss[c] != NULL);
    761 SCIP_CALL( SCIPreleaseCons(scip, &conss[c]) );
    762 }
    763
    764 SCIPfreeBufferArray(scip, &conss);
    765 }
    766
    767 return SCIP_OKAY;
    768}
    769
    770
    771/*
    772 * constraint specific interface methods
    773 */
    774
    775/** creates the handler for conjunction constraints and includes it in SCIP */
    777 SCIP* scip /**< SCIP data structure */
    778 )
    779{
    780 SCIP_CONSHDLR* conshdlr;
    781
    782 /* include constraint handler */
    785 consEnfolpConjunction, consEnfopsConjunction, consCheckConjunction, consLockConjunction,
    786 NULL) );
    787
    788 assert(conshdlr != NULL);
    789
    790 /* set non-fundamental callbacks via specific setter functions */
    791 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyConjunction, consCopyConjunction) );
    792 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteConjunction) );
    793 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseConjunction) );
    794 SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolConjunction, CONSHDLR_MAXPREROUNDS,
    796 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintConjunction) );
    797 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransConjunction) );
    798 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxConjunction) );
    799
    800 return SCIP_OKAY;
    801}
    802
    803/** creates and captures a conjunction constraint
    804 *
    805 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    806 */
    808 SCIP* scip, /**< SCIP data structure */
    809 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    810 const char* name, /**< name of constraint */
    811 int nconss, /**< number of initial constraints in conjunction */
    812 SCIP_CONS** conss, /**< initial constraint in conjunction */
    813 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    814 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    815 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    816 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    817 SCIP_Bool local, /**< is constraint only valid locally?
    818 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    819 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
    820 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
    821 * adds coefficients to this constraint. */
    822 SCIP_Bool dynamic /**< is constraint subject to aging?
    823 * Usually set to FALSE. Set to TRUE for own cuts which
    824 * are separated as constraints. */
    825 )
    826{
    827 SCIP_CONSHDLR* conshdlr;
    828 SCIP_CONSDATA* consdata;
    829
    830 /* find the conjunction constraint handler */
    832 if( conshdlr == NULL )
    833 {
    834 SCIPerrorMessage("conjunction constraint handler not found\n");
    835 return SCIP_PLUGINNOTFOUND;
    836 }
    837
    838 /* create constraint data */
    839 SCIP_CALL( consdataCreate(scip, &consdata, conss, nconss) );
    840
    841 /* create constraint */
    842 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, FALSE, FALSE, enforce, check, FALSE,
    843 local, modifiable, dynamic, FALSE, FALSE) );
    844
    845 return SCIP_OKAY;
    846}
    847
    848/** creates and captures an and constraint
    849 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
    850 * method SCIPcreateConsConjunction(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
    851 *
    852 * @see SCIPcreateConsConjunction() for information about the basic constraint flag configuration
    853 *
    854 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    855 */
    857 SCIP* scip, /**< SCIP data structure */
    858 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    859 const char* name, /**< name of constraint */
    860 int nconss, /**< number of initial constraints in conjunction */
    861 SCIP_CONS** conss /**< initial constraint in conjunction */
    862 )
    863{
    864 assert(scip != NULL);
    865
    866 SCIP_CALL( SCIPcreateConsConjunction(scip, cons, name, nconss, conss,
    867 TRUE, TRUE, FALSE, FALSE, FALSE) );
    868
    869 return SCIP_OKAY;
    870}
    871
    872/** adds constraint to the conjunction of constraints */
    874 SCIP* scip, /**< SCIP data structure */
    875 SCIP_CONS* cons, /**< conjunction constraint */
    876 SCIP_CONS* addcons /**< additional constraint in conjunction */
    877 )
    878{
    879 SCIP_CONSDATA* consdata;
    880
    881 assert(cons != NULL);
    882 assert(addcons != NULL);
    883
    885
    886 consdata = SCIPconsGetData(cons);
    887 assert(consdata != NULL);
    888
    889 SCIP_CALL( consdataAddCons(scip, consdata, addcons) );
    890
    891 return SCIP_OKAY;
    892}
    #define CONSHDLR_NEEDSCONS
    #define CONSHDLR_CHECKPRIORITY
    #define CONSHDLR_DESC
    static SCIP_RETCODE checkAllConss(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_SOL *sol, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool completely, SCIP_RESULT *result)
    static SCIP_DECL_CONSDELETE(consDeleteConjunction)
    static SCIP_RETCODE consdataAddCons(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_CONS *cons)
    #define CONSHDLR_MAXPREROUNDS
    static SCIP_DECL_CONSPRINT(consPrintConjunction)
    static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_CONS **conss, int nconss)
    static SCIP_DECL_CONSENFORELAX(consEnforelaxConjunction)
    static SCIP_DECL_CONSCOPY(consCopyConjunction)
    static SCIP_DECL_CONSLOCK(consLockConjunction)
    static SCIP_DECL_CONSENFOPS(consEnfopsConjunction)
    static SCIP_DECL_CONSTRANS(consTransConjunction)
    #define CONSHDLR_PRESOLTIMING
    static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
    static SCIP_DECL_CONSPARSE(consParseConjunction)
    #define CONSHDLR_EAGERFREQ
    static SCIP_DECL_CONSCHECK(consCheckConjunction)
    #define CONSHDLR_ENFOPRIORITY
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyConjunction)
    static SCIP_DECL_CONSPRESOL(consPresolConjunction)
    #define CONSHDLR_NAME
    static SCIP_RETCODE addAllConss(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_RESULT *result)
    static SCIP_DECL_CONSENFOLP(consEnfolpConjunction)
    constraint handler for conjunction 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 TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_RETCODE SCIPcreateConsConjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nconss, SCIP_CONS **conss, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic)
    SCIP_RETCODE SCIPaddConsElemConjunction(SCIP *scip, SCIP_CONS *cons, SCIP_CONS *addcons)
    SCIP_RETCODE SCIPcreateConsBasicConjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nconss, SCIP_CONS **conss)
    SCIP_RETCODE SCIPincludeConshdlrConjunction(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_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_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:4067
    SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
    Definition: scip_prob.c:3986
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
    Definition: scip_cons.c:808
    SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
    Definition: scip_cons.c:540
    SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: scip_cons.c:181
    SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
    Definition: scip_cons.c:578
    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 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_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_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8592
    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_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 SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #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
    void SCIPupdateSolConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
    Definition: scip_sol.c:451
    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 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 global and local (sub)problems
    public methods for solutions
    static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
    Main separation function.
    Definition: sepa_flower.c:1219
    struct SCIP_ConsData SCIP_CONSDATA
    Definition: type_cons.h:65
    @ SCIP_FEASIBLE
    Definition: type_result.h:45
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_CONSADDED
    Definition: type_result.h:52
    @ 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_LOCKTYPE_MODEL
    Definition: type_var.h:141