Scippy

    SCIP

    Solving Constraint Integer Programs

    cons_benders.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file cons_benders.c
    26 * @ingroup DEFPLUGINS_CONS
    27 * @brief constraint handler for Benders' decomposition
    28 * @author Stephen J. Maher
    29 *
    30 * Two constraint handlers are implemented for the generation of Benders' decomposition cuts. When included in a
    31 * problem, the Benders' decomposition constraint handlers generate cuts during the enforcement of LP and relaxation
    32 * solutions. Additionally, Benders' decomposition cuts can be generated when checking the feasibility of solutions with
    33 * respect to the subproblem constraints.
    34 *
    35 * This constraint handler has an enforcement priority that is less than the integer constraint handler. This means that
    36 * only integer feasible solutions from the LP solver are enforced by this constraint handler. This is the traditional
    37 * behaviour of the branch-and-check approach to Benders' decomposition. Additionally, the check priority is set low,
    38 * such that this expensive constraint handler is only called as a final check on primal feasible solutions.
    39 *
    40 * This constraint handler in the standard constraint handler that should be added when using Benders' decomposition.
    41 * Additionally, there is a flag in SCIPincludeConshdlrBenders that permits the addition of the LP constraint handler,
    42 * cons_benderslp. The use of both cons_benders and cons_benderslp allows the user to perform a multiphase Benders'
    43 * decomposition algorithm.
    44 */
    45
    46/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    47
    48#include <assert.h>
    49#include <string.h>
    50
    51#include "scip/scip.h"
    52#include "scip/cons_benders.h"
    53#include "scip/heur_trysol.h"
    54#include "scip/heuristics.h"
    55
    56
    57/* fundamental constraint handler properties */
    58#define CONSHDLR_NAME "benders"
    59#define CONSHDLR_DESC "constraint handler to execute Benders' Decomposition"
    60#define CONSHDLR_ENFOPRIORITY -100 /**< priority of the constraint handler for constraint enforcing */
    61#define CONSHDLR_CHECKPRIORITY -5000000 /**< priority of the constraint handler for checking feasibility */
    62#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
    63 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    64#define CONSHDLR_MAXPREROUNDS 0 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
    65#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_FAST /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
    66#define CONSHDLR_NEEDSCONS FALSE /**< should the constraint handler be skipped, if no constraints are available? */
    67
    68
    69#define DEFAULT_CHECKEDSOLSSIZE 20 /**< initial size of the checked sols array */
    70#define DEFAULT_ACTIVE FALSE /**< is the constraint handler active? */
    71
    72/*
    73 * Data structures
    74 */
    75
    76/** constraint handler data */
    77struct SCIP_ConshdlrData
    78{
    79 int* checkedsols; /**< an array of solutions that this constraint has already checked */
    80 int ncheckedsols; /**< the number of checked solutions */
    81 int checkedsolssize; /**< the size of the checked solutions array */
    82 SCIP_Bool active; /**< is the constraint handler active? */
    83};
    84
    85/*
    86 * Local methods
    87 */
    88
    89/** constructs a new solution based upon the solutions to the Benders' decomposition subproblems */
    90static
    92 SCIP* scip, /**< the SCIP instance */
    93 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    94 SCIP_SOL* sol, /**< primal CIP solution */
    95 SCIP_BENDERSENFOTYPE type /**< the type of solution being enforced */
    96 )
    97{
    98 SCIP_CONSHDLRDATA* conshdlrdata;
    99 SCIP_SOL* newsol;
    100 SCIP_HEUR* heurtrysol;
    101 SCIP_BENDERS** benders;
    102 SCIP_VAR** auxiliaryvars;
    103 int nactivebenders;
    104 int nsubproblems;
    105 int i;
    106 int j;
    107 SCIP_Bool success = TRUE;
    108
    109 /* don't propose new solutions if not in presolve or solving */
    111 return SCIP_OKAY;
    112
    113 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    114 assert(conshdlrdata != NULL);
    115
    116 benders = SCIPgetBenders(scip);
    117 nactivebenders = SCIPgetNActiveBenders(scip);
    118
    119 /* if the solution is NULL, then we create the solution from the LP sol */
    120 if( sol != NULL )
    121 {
    122 assert(type == SCIP_BENDERSENFOTYPE_CHECK);
    123 SCIP_CALL( SCIPcreateSolCopy(scip, &newsol, sol) );
    124 }
    125 else
    126 {
    127 switch( type )
    128 {
    130 SCIP_CALL( SCIPcreateLPSol(scip, &newsol, NULL) );
    131 break;
    134 break;
    137 break;
    138 default:
    139 SCIP_CALL( SCIPcreateLPSol(scip, &newsol, NULL) );
    140 break;
    141 } /*lint !e788*/
    142 }
    143 SCIP_CALL( SCIPunlinkSol(scip, newsol) );
    144
    145 /* looping through all Benders' decompositions to construct the new solution */
    146 for( i = 0; i < nactivebenders; i++ )
    147 {
    148 SCIP_VAR* masterauxvar;
    149 SCIP_BENDERSOBJTYPE objtype;
    150 SCIP_Real masterauxvarval = 0.0;
    151
    152 /* getting the objective type for the subproblems */
    153 objtype = SCIPbendersGetObjectiveType(benders[i]);
    154
    155 /* getting the auxiliary variables and the number of subproblems from the Benders' decomposition structure */
    156 masterauxvar = SCIPbenderGetMasterAuxiliaryVar(benders[i]);
    157 auxiliaryvars = SCIPbendersGetAuxiliaryVars(benders[i]);
    158 nsubproblems = SCIPbendersGetNSubproblems(benders[i]);
    159
    160 /* setting the auxiliary variable in the new solution */
    161 for( j = 0; j < nsubproblems; j++ )
    162 {
    163 SCIP_Real objval;
    164
    165 objval = SCIPbendersGetSubproblemObjval(benders[i], j);
    166
    167 if( SCIPvarGetStatus(auxiliaryvars[j]) == SCIP_VARSTATUS_FIXED
    168 && !SCIPisEQ(scip, SCIPgetSolVal(scip, newsol, auxiliaryvars[j]), objval) )
    169 {
    170 success = FALSE;
    171 break;
    172 }
    173 else if( SCIPisLT(scip, SCIPgetSolVal(scip, newsol, auxiliaryvars[j]), objval) )
    174 {
    175 SCIP_CALL( SCIPsetSolVal(scip, newsol, auxiliaryvars[j], objval) );
    176 }
    177
    178 if( objtype == SCIP_BENDERSOBJTYPE_SUM )
    179 {
    180 masterauxvarval += objval;
    181 }
    182 else
    183 {
    184 assert(objtype == SCIP_BENDERSOBJTYPE_MAX);
    185 masterauxvarval = MAX(masterauxvarval, objval);
    186 }
    187 }
    188
    189 /* setting the value of the master auxiliary variable. It is possible that the master auxiliary variable is
    190 * removed during presolve. As such, it could be NULL in sub-SCIPs or inactive in the original SCIP.
    191 */
    192 if( masterauxvar != NULL && SCIPvarIsActive(masterauxvar) )
    193 {
    194 SCIP_CALL( SCIPsetSolVal(scip, newsol, SCIPbenderGetMasterAuxiliaryVar(benders[i]), masterauxvarval) );
    195 }
    196
    197 if( !success )
    198 break;
    199 }
    200
    201 /* if setting the variable values was successful, then we try to add the solution */
    202 if( success ) /*lint !e774*/
    203 {
    204 /* checking the size of the checkedsols array and extending it is there is not enough memory */
    205 assert(conshdlrdata->ncheckedsols <= conshdlrdata->checkedsolssize);
    206 if( conshdlrdata->ncheckedsols + 1 > conshdlrdata->checkedsolssize )
    207 {
    208 int newsize;
    209
    210 newsize = SCIPcalcMemGrowSize(scip, conshdlrdata->ncheckedsols + 1);
    211 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->checkedsols, conshdlrdata->checkedsolssize, newsize) );
    212 conshdlrdata->checkedsolssize = newsize;
    213 }
    214 assert(conshdlrdata->ncheckedsols + 1 <= conshdlrdata->checkedsolssize);
    215
    216 /* recording the solution number to avoid checking the solution again */
    217 conshdlrdata->checkedsols[conshdlrdata->ncheckedsols] = SCIPsolGetIndex(newsol);
    218 conshdlrdata->ncheckedsols++;
    219
    220 /* getting the try solution heuristic */
    221 heurtrysol = SCIPfindHeur(scip, "trysol");
    222
    223 /* passing the new solution to the trysol heuristic */
    224 SCIP_CALL( SCIPcheckSol(scip, newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
    225 if ( success )
    226 {
    227 SCIP_CALL( SCIPheurPassSolAddSol(scip, heurtrysol, newsol) );
    228 SCIPdebugMsg(scip, "Creating solution was successful.\n");
    229 }
    230 else
    231 {
    232 /* the solution might not be feasible, because of additional constraints */
    233 SCIPdebugMsg(scip, "Creating solution was not successful.\n");
    234 }
    235 }
    236
    237 SCIP_CALL( SCIPfreeSol(scip, &newsol) );
    238
    239 return SCIP_OKAY;
    240}
    241
    242/** checks the Benders' decomposition auxiliary variables for unboundedness. */
    243static
    245 SCIP* scip, /**< the SCIP data structure */
    246 SCIP_BENDERS* benders, /**< the Benders' decomposition data structure */
    247 SCIP_SOL* sol /**< the primal solution to enforce, or NULL for the current LP/pseudo sol */
    248 )
    249{
    250 int nsubproblems;
    251 SCIP_Bool unbounded = FALSE;
    252 int i;
    253
    254 assert(scip != NULL);
    255 assert(benders != NULL);
    256
    257 nsubproblems = SCIPbendersGetNSubproblems(benders);
    258
    259 /* checking the auxiliary variable values for unboundedness */
    260 for( i = 0; i < nsubproblems; i++ )
    261 {
    263 || SCIPisInfinity(scip, -SCIPgetBendersAuxiliaryVarVal(scip, benders, sol, i)) )
    264 {
    265 unbounded = TRUE;
    266 break;
    267 }
    268 }
    269
    270 return unbounded;
    271}
    272
    273/** enforces Benders' constraints for given solution
    274 *
    275 * This method is called from cons_benderslp and cons_benders. If the method is called from cons_benderslp, then the
    276 * solutions are not guaranteed to be integer feasible. This is because the default priority is set greater than the
    277 * integer constraint handler. If this method is called from cons_benders, then, because the default enforcement
    278 * priority is set less than that of the integer constraint handler, then it can be assumed that the solutions are
    279 * integer feasible.
    280 *
    281 * The checkint flag indicates whether integer feasibility can be assumed. If it is not assumed, i.e. checkint ==
    282 * FALSE, then only the convex relaxations of the subproblems are solved. If integer feasibility is assumed, i.e.
    283 * checkint == TRUE, then the convex relaxations and the full CIP are solved to generate Benders' cuts and check
    284 * solution feasibility.
    285 */
    287 SCIP* scip, /**< the SCIP instance */
    288 SCIP_SOL* sol, /**< the primal solution to enforce, or NULL for the current LP/pseudo sol */
    289 SCIP_CONSHDLR* conshdlr, /**< the constraint handler */
    290 SCIP_RESULT* result, /**< the result of the enforcement */
    291 SCIP_BENDERSENFOTYPE type, /**< the type of solution being enforced */
    292 SCIP_Bool checkint /**< should integrality be considered when checking the subproblems */
    293 )
    294{
    295 SCIP_BENDERS** benders;
    296 SCIP_Bool infeasible;
    297 SCIP_Bool auxviol;
    298 int nactivebenders;
    299 int i;
    300
    301 assert(scip != NULL);
    302 assert(conshdlr != NULL);
    303 assert(result != NULL);
    304
    305 (*result) = SCIP_FEASIBLE;
    306 infeasible = FALSE;
    307 auxviol = FALSE;
    308
    309 benders = SCIPgetBenders(scip);
    310 nactivebenders = SCIPgetNActiveBenders(scip);
    311
    312 for( i = 0; i < nactivebenders; i++ )
    313 {
    314 /* if any subproblems are declared as infeasible, then the result must be returned as infeasible. It is not
    315 * possible to generate cuts, since the LP is infeasible without performing any master variable fixing
    316 */
    318 {
    319 (*result) = SCIP_INFEASIBLE;
    320
    321 /* the Benders' decomposition subproblems do not need to be checked, since there is a subproblem that is
    322 * infeasible.
    323 */
    324 break;
    325 }
    326
    327 switch( type )
    328 {
    330 if( SCIPbendersCutLP(benders[i]) )
    331 {
    332 SCIP_Bool unbounded = FALSE;
    333
    334 /* if the solution is unbounded, then it may not be possible to generate any Benders' decomposition
    335 * cuts. If the unboundedness is from the auxiliary variables, then cuts are required. Otherwise, if
    336 * the unboundedness comes from original variables, then the unboundedness needs to be handled by other
    337 * constraint handlers or the problem is reported as unbounded
    338 * */
    340 {
    341 if( !unboundedAuxiliaryVariables(scip, benders[i], NULL) )
    342 {
    343 (*result) = SCIP_FEASIBLE;
    344 auxviol = FALSE;
    345 unbounded = TRUE;
    346 }
    347 }
    348
    349 if( !unbounded )
    350 {
    351 SCIP_CALL( SCIPsolveBendersSubproblems(scip, benders[i], NULL, result, &infeasible, &auxviol, type, checkint) );
    352 }
    353 }
    354 break;
    356 if( SCIPbendersCutRelaxation(benders[i]) )
    357 {
    358 SCIP_CALL( SCIPsolveBendersSubproblems(scip, benders[i], sol, result, &infeasible, &auxviol, type, checkint) );
    359 }
    360 break;
    362 if( SCIPbendersCutPseudo(benders[i]) )
    363 {
    364 SCIP_CALL( SCIPsolveBendersSubproblems(scip, benders[i], NULL, result, &infeasible, &auxviol, type, checkint) );
    365 }
    366 break;
    368 SCIPwarningMessage(scip, "The conscheck callback is not supported\n");
    369 break;
    370 default:
    371 break;
    372 } /*lint !e788*/
    373
    374 /* The decompositions are checked until one is found that is not feasible. Not being feasible could mean that
    375 * infeasibility of the original problem has been proven or a constraint has been added. If the result
    376 * SCIP_DIDNOTRUN is returned, then the next decomposition is checked */
    377 if( (*result) != SCIP_FEASIBLE && (*result) != SCIP_DIDNOTRUN )
    378 break;
    379 }
    380
    381 /* if the constraint handler was called with an integer feasible solution, then a feasible solution can be proposed */
    382 if( checkint )
    383 {
    384 /* in the case that the problem is feasible, this means that all subproblems are feasible. The auxiliary variables
    385 * still need to be updated. This is done by constructing a valid solution. */
    386 if( (*result) == SCIP_FEASIBLE && auxviol )
    387 {
    388 SCIP_CALL( constructValidSolution(scip, conshdlr, sol, type) );
    389
    390 (*result) = SCIP_INFEASIBLE;
    391 }
    392 }
    393
    394 /* if no Benders' decomposition were run, then the result is returned as SCIP_FEASIBLE. The SCIP_DIDNOTRUN result
    395 * indicates that no subproblems were checked or that cuts were disabled, so that it is not guaranteed that this
    396 * solution is feasible.
    397 */
    398 if( (*result) == SCIP_DIDNOTRUN )
    399 (*result) = SCIP_FEASIBLE;
    400
    401 return SCIP_OKAY;
    402}
    403
    404/*
    405 * Callback methods of constraint handler
    406 */
    407
    408/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    409static
    410SCIP_DECL_CONSHDLRCOPY(conshdlrCopyBenders)
    411{ /*lint --e{715}*/
    412 assert(scip != NULL);
    413
    415
    416 *valid = TRUE;
    417
    418 return SCIP_OKAY;
    419}
    420
    421/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
    422static
    423SCIP_DECL_CONSFREE(consFreeBenders)
    424{ /*lint --e{715}*/
    425 SCIP_CONSHDLRDATA* conshdlrdata;
    426
    427 assert(scip != NULL);
    428 assert(conshdlr != NULL);
    429
    430 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    431 assert(conshdlrdata != NULL);
    432
    433 /* freeing the constraint handler data */
    434 SCIPfreeMemory(scip, &conshdlrdata);
    435
    436 return SCIP_OKAY;
    437}
    438
    439
    440/** initialization method of constraint handler (called after problem was transformed) */
    441static
    442SCIP_DECL_CONSINIT(consInitBenders)
    443{ /*lint --e{715}*/
    444 SCIP_CONSHDLRDATA* conshdlrdata;
    445
    446 assert(scip != NULL);
    447 assert(conshdlr != NULL);
    448
    449 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    450 assert(conshdlrdata != NULL);
    451
    452 /* disable benders handler */
    453 if( !conshdlrdata->active )
    454 {
    456 return SCIP_OKAY;
    457 }
    458
    459 conshdlrdata->checkedsolssize = DEFAULT_CHECKEDSOLSSIZE;
    460 conshdlrdata->ncheckedsols = 0;
    461
    462 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &conshdlrdata->checkedsols, conshdlrdata->checkedsolssize) );
    463
    464 return SCIP_OKAY;
    465}
    466
    467
    468/** deinitialization method of constraint handler (called before transformed problem is freed) */
    469static
    470SCIP_DECL_CONSEXIT(consExitBenders)
    471{ /*lint --e{715}*/
    472 SCIP_CONSHDLRDATA* conshdlrdata;
    473
    474 assert(scip != NULL);
    475 assert(conshdlr != NULL);
    476
    477 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    478 assert(conshdlrdata != NULL);
    479
    480 /* reenable benders handler */
    481 if( SCIPconshdlrNeedsCons(conshdlr) )
    482 {
    483 assert(!conshdlrdata->active);
    485 return SCIP_OKAY;
    486 }
    487
    488 /* freeing the checked sols array */
    489 SCIPfreeBlockMemoryArray(scip, &conshdlrdata->checkedsols, conshdlrdata->checkedsolssize);
    490
    491 return SCIP_OKAY;
    492}
    493
    494
    495/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
    496static
    497SCIP_DECL_CONSINITLP(consInitlpBenders)
    498{ /*lint --e{715}*/
    499 SCIP_BENDERS** benders;
    500 int nactivebenders;
    501 int i;
    502
    503 assert(scip != NULL);
    504 assert(conshdlr != NULL);
    505
    506 benders = SCIPgetBenders(scip);
    507 nactivebenders = SCIPgetNActiveBenders(scip);
    508
    509 (*infeasible) = FALSE;
    510
    511 /* checking all Benders' decomposition implementations to see if any subproblems have been declared as infeasible */
    512 for( i = 0; i < nactivebenders && !(*infeasible); i++ )
    513 (*infeasible) = SCIPbendersSubproblemsAreInfeasible(benders[i]);
    514
    515 return SCIP_OKAY;
    516}
    517
    518/** constraint enforcing method of constraint handler for LP solutions */
    519static
    520SCIP_DECL_CONSENFOLP(consEnfolpBenders)
    521{ /*lint --e{715}*/
    522 assert(scip != NULL);
    523 assert(conshdlr != NULL);
    524
    526
    527 return SCIP_OKAY;
    528}
    529
    530
    531/** constraint enforcing method of constraint handler for relaxation solutions */
    532static
    533SCIP_DECL_CONSENFORELAX(consEnforelaxBenders)
    534{ /*lint --e{715}*/
    535 assert(scip != NULL);
    536 assert(conshdlr != NULL);
    537
    539
    540 return SCIP_OKAY;
    541}
    542
    543
    544/** constraint enforcing method of constraint handler for pseudo solutions */
    545static
    546SCIP_DECL_CONSENFOPS(consEnfopsBenders)
    547{ /*lint --e{715}*/
    548 assert(scip != NULL);
    549 assert(conshdlr != NULL);
    550
    552
    553 return SCIP_OKAY;
    554}
    555
    556
    557/** feasibility check method of constraint handler for integral solutions
    558 *
    559 * This function checks the feasibility of the Benders' decomposition master problem. In the case that the problem is
    560 * feasible, then the auxiliary variables must be updated with the subproblem objective function values. It is not
    561 * possible to simply update the auxiliary variable values, so a new solution is created.
    562 */
    563static
    564SCIP_DECL_CONSCHECK(consCheckBenders)
    565{ /*lint --e{715}*/
    566 SCIP_CONSHDLRDATA* conshdlrdata;
    567 SCIP_BENDERS** benders;
    568 int nactivebenders;
    569 int solindex;
    570 int i;
    571 SCIP_Bool performcheck;
    572 SCIP_Bool auxviol;
    573
    574 assert(scip != NULL);
    575 assert(conshdlr != NULL);
    576 assert(result != NULL);
    577
    578 *result = SCIP_FEASIBLE;
    579
    580 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    581 assert(conshdlrdata != NULL);
    582
    583 if( !conshdlrdata->active )
    584 return SCIP_OKAY;
    585
    586 performcheck = TRUE;
    587 auxviol = FALSE;
    588
    589 /* if the constraint handler is active, then the check must be performed. */
    590 benders = SCIPgetBenders(scip);
    591 nactivebenders = SCIPgetNActiveBenders(scip);
    592
    593 /* checking if the solution was constructed by this constraint handler */
    594 solindex = SCIPsolGetIndex(sol);
    595 for( i = 0; i < conshdlrdata->ncheckedsols; i++ )
    596 {
    597 if( conshdlrdata->checkedsols[i] == solindex )
    598 {
    599 conshdlrdata->checkedsols[0] = conshdlrdata->checkedsols[conshdlrdata->ncheckedsols - 1];
    600 conshdlrdata->ncheckedsols--;
    601
    602 performcheck = FALSE;
    603 break;
    604 }
    605 }
    606
    607 /* if the solution has not been checked before, then we must perform the check */
    608 if( performcheck && nactivebenders > 0 )
    609 {
    610 for( i = 0; i < nactivebenders; i++ )
    611 {
    612 /* if any subproblems are declared as infeasible, then the result must be returned as infeasible. It is not
    613 * possible to generate cuts, since the LP is infeasible without performing any master variable fixing
    614 */
    616 {
    617 (*result) = SCIP_INFEASIBLE;
    618 }
    619 else
    620 {
    621 SCIP_Bool infeasible;
    622 infeasible = FALSE;
    623
    624 SCIP_CALL( SCIPsolveBendersSubproblems(scip, benders[i], sol, result, &infeasible, &auxviol,
    626 }
    627
    628 /* in the case of multiple Benders' decompositions, the subproblems are solved until a constriant is added or
    629 * infeasibility is proven. So if the result is not SCIP_FEASIBLE, then the loop is exited */
    630 if( (*result) != SCIP_FEASIBLE )
    631 break;
    632 }
    633
    634 /* in the case that the problem is feasible, this means that all subproblems are feasible. The auxiliary variables
    635 * still need to be updated. This is done by constructing a valid solution. */
    636 if( (*result) == SCIP_FEASIBLE )
    637 {
    638 if( auxviol )
    639 {
    640 if( !SCIPsolIsOriginal(sol) )
    641 {
    643 }
    644
    645 if( printreason )
    646 SCIPmessagePrintInfo(SCIPgetMessagehdlr(scip), "all subproblems are feasible but there is a violation in the auxiliary variables\n");
    647
    648 (*result) = SCIP_INFEASIBLE;
    649 }
    650 }
    651
    652 /* if no Benders' decomposition were run, then the result is returned as SCIP_FEASIBLE. The SCIP_DIDNOTRUN result
    653 * indicates that no subproblems were checked or that cuts were disabled, so that it is not guaranteed that this
    654 * solution is feasible.
    655 */
    656 if( (*result) == SCIP_DIDNOTRUN )
    657 (*result) = SCIP_FEASIBLE;
    658 }
    659
    660 return SCIP_OKAY;
    661}
    662
    663
    664/** the presolving method for the Benders' decomposition constraint handler
    665 *
    666 * This method is used to update the lower bounds of the auxiliary problem and to identify infeasibility before the
    667 * subproblems are solved. When SCIP is copied, the Benders' decomposition subproblems from the source SCIP are
    668 * transferred to the target SCIP. So there is no need to perform this presolving step in the copied SCIP, since the
    669 * computed bounds would be identical.
    670 */
    671static
    672SCIP_DECL_CONSPRESOL(consPresolBenders)
    673{ /*lint --e{715}*/
    674 SCIP_BENDERS** benders;
    675 int nactivebenders;
    676 int nsubproblems;
    677 int i;
    678 int j;
    679
    680 assert(scip != NULL);
    681 assert(conshdlr != NULL);
    682
    683 (*result) = SCIP_DIDNOTFIND;
    684
    685 /* this presolving step is only valid for the main SCIP instance. If the SCIP instance is copied, then the presolving
    686 * step is not performed.
    687 */
    688 if( SCIPgetSubscipDepth(scip) > 0 )
    689 {
    690 (*result) = SCIP_DIDNOTRUN;
    691 return SCIP_OKAY;
    692 }
    693
    694 /* it is only possible to compute the lower bound of the subproblems if the constraint handler is active */
    695 benders = SCIPgetBenders(scip);
    696 nactivebenders = SCIPgetNActiveBenders(scip);
    697
    698 /* need to compute the lower bound for all active Benders' decompositions */
    699 for( i = 0; i < nactivebenders; i++ )
    700 {
    701 nsubproblems = SCIPbendersGetNSubproblems(benders[i]);
    702
    703 for( j = 0; j < nsubproblems; j++ )
    704 {
    705 SCIP_VAR* auxiliaryvar;
    706 SCIP_Real lowerbound;
    707 SCIP_Bool infeasible;
    708
    709 infeasible = FALSE;
    710
    711 /* computing the lower bound of the subproblem by solving it without any variable fixings */
    712 SCIP_CALL( SCIPcomputeBendersSubproblemLowerbound(scip, benders[i], j, &lowerbound, &infeasible) );
    713
    714 if( infeasible )
    715 {
    716 (*result) = SCIP_CUTOFF;
    717 break;
    718 }
    719
    720 /* retrieving the auxiliary variable */
    721 auxiliaryvar = SCIPbendersGetAuxiliaryVar(benders[i], j);
    722
    723 /* only update the lower bound if it is greater than the current lower bound */
    724 if( SCIPisGT(scip, lowerbound, SCIPvarGetLbLocal(auxiliaryvar)) )
    725 {
    726 SCIPdebugMsg(scip, "Tightened lower bound of <%s> to %g\n", SCIPvarGetName(auxiliaryvar), lowerbound);
    727 /* updating the lower bound of the auxiliary variable */
    728 SCIP_CALL( SCIPchgVarLb(scip, auxiliaryvar, lowerbound) );
    729
    730 (*nchgbds)++;
    731 (*result) = SCIP_SUCCESS;
    732 }
    733
    734 /* stores the lower bound for the subproblem */
    735 SCIPbendersUpdateSubproblemLowerbound(benders[i], j, lowerbound);
    736 }
    737
    738 if( (*result) == SCIP_CUTOFF )
    739 break;
    740 }
    741
    742 return SCIP_OKAY;
    743}
    744
    745/** variable rounding lock method of constraint handler
    746 * The auxiliary variables and the master problem variables need to lock added by the Benders' decomposition
    747 * constraint. The auxiliary variables require a down lock. The master problem variable need both up and down lock.
    748 * The master problem variables require locks in both directions because the coefficients in all potential Benders'
    749 * cuts are not known in general.
    750 */
    751static
    752SCIP_DECL_CONSLOCK(consLockBenders)
    753{ /*lint --e{715}*/
    754 SCIP_CONSHDLRDATA* conshdlrdata;
    755 SCIP_BENDERS** benders;
    756 SCIP_VAR** vars;
    757 int nactivebenders;
    758 int nsubproblems;
    759 int nvars;
    760 int i;
    761 int j;
    762
    763 assert(scip != NULL);
    764 assert(conshdlr != NULL);
    765 assert(locktype == SCIP_LOCKTYPE_MODEL);
    766
    767 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    768 assert(conshdlrdata != NULL);
    769
    770 if( !conshdlrdata->active )
    771 return SCIP_OKAY;
    772
    773 /* the locks should only be added if the Benders' decomposition constraint handler has been activated */
    774 benders = SCIPgetBenders(scip);
    775 nactivebenders = SCIPgetNActiveBenders(scip);
    776
    777 /* retrieving the master problem variables */
    778 SCIP_CALL( SCIPgetOrigVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    779
    780 /* need to compute the lower bound for all active Benders' decompositions */
    781 for( i = 0; i < nactivebenders; i++ )
    782 {
    783 nsubproblems = SCIPbendersGetNSubproblems(benders[i]);
    784
    785 /* if the auxiliary variable exists, then we need to add a down lock. Initially, a down lock is added to all
    786 * auxiliary variables during creating. This is because the creation of auxiliary variable occurs after
    787 * CONS_LOCK is called. The inclusion of the auxiliary variables in this function is to cover the case if locks
    788 * are added or removed after presolving.
    789 */
    790 for( j = 0; j < nsubproblems; j++ )
    791 {
    792 SCIP_VAR* auxvar;
    793
    794 auxvar = SCIPbendersGetAuxiliaryVar(benders[i], j);
    795
    796 if( auxvar != NULL )
    797 {
    798 SCIP_CALL( SCIPaddVarLocksType(scip, auxvar, locktype, nlockspos, nlocksneg) );
    799 }
    800 }
    801
    802 /* adding up and down locks for all master problem variables. Since the locks for all constraint handlers
    803 * without constraints, no auxiliary variables have been added. As such, all variables are master variables.
    804 */
    805 for( j = 0; j < nvars; j++ )
    806 {
    807 SCIP_CALL( SCIPaddVarLocksType(scip, vars[j], locktype, (nlockspos + nlocksneg)*nsubproblems,
    808 (nlockspos + nlocksneg)*nsubproblems) );
    809 }
    810 }
    811
    812 return SCIP_OKAY;
    813}
    814
    815
    816/*
    817 * constraint specific interface methods
    818 */
    819
    820/** creates the handler for Benders' decomposition and includes it in SCIP */
    822 SCIP* scip /**< SCIP data structure */
    823 )
    824{
    825 SCIP_CONSHDLRDATA* conshdlrdata;
    826 SCIP_CONSHDLR* conshdlr;
    827
    828 /* create benders constraint handler data */
    829 conshdlrdata = NULL;
    830
    831 SCIP_CALL( SCIPallocMemory(scip, &conshdlrdata) );
    832
    833 conshdlr = NULL;
    834
    835 /* include constraint handler */
    838 consEnfolpBenders, consEnfopsBenders, consCheckBenders, consLockBenders,
    839 conshdlrdata) );
    840 assert(conshdlr != NULL);
    841
    842 /* set non-fundamental callbacks via specific setter functions */
    843 SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitBenders) );
    844 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitBenders) );
    845 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyBenders, NULL) );
    846 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeBenders) );
    847 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpBenders) );
    848 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxBenders) );
    850
    851 /* add Benders' decomposition constraint handler parameters */
    853 "constraints/" CONSHDLR_NAME "/active", "is the Benders' decomposition constraint handler active?",
    854 &conshdlrdata->active, FALSE, DEFAULT_ACTIVE, NULL, NULL));
    855
    856 return SCIP_OKAY;
    857}
    static GRAPHNODE ** active
    static SCIP_RETCODE constructValidSolution(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_SOL *sol, SCIP_BENDERSENFOTYPE type)
    Definition: cons_benders.c:91
    #define CONSHDLR_NEEDSCONS
    Definition: cons_benders.c:66
    static SCIP_DECL_CONSINIT(consInitBenders)
    Definition: cons_benders.c:442
    #define CONSHDLR_CHECKPRIORITY
    Definition: cons_benders.c:61
    #define CONSHDLR_DESC
    Definition: cons_benders.c:59
    static SCIP_DECL_CONSEXIT(consExitBenders)
    Definition: cons_benders.c:470
    static SCIP_DECL_CONSLOCK(consLockBenders)
    Definition: cons_benders.c:752
    #define CONSHDLR_MAXPREROUNDS
    Definition: cons_benders.c:64
    static SCIP_DECL_CONSCHECK(consCheckBenders)
    Definition: cons_benders.c:564
    static SCIP_DECL_CONSFREE(consFreeBenders)
    Definition: cons_benders.c:423
    static SCIP_DECL_CONSENFOLP(consEnfolpBenders)
    Definition: cons_benders.c:520
    static SCIP_DECL_CONSPRESOL(consPresolBenders)
    Definition: cons_benders.c:672
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyBenders)
    Definition: cons_benders.c:410
    #define DEFAULT_CHECKEDSOLSSIZE
    Definition: cons_benders.c:69
    static SCIP_DECL_CONSENFORELAX(consEnforelaxBenders)
    Definition: cons_benders.c:533
    #define CONSHDLR_PRESOLTIMING
    Definition: cons_benders.c:65
    static SCIP_DECL_CONSENFOPS(consEnfopsBenders)
    Definition: cons_benders.c:546
    #define CONSHDLR_EAGERFREQ
    Definition: cons_benders.c:62
    #define CONSHDLR_ENFOPRIORITY
    Definition: cons_benders.c:60
    static SCIP_Bool unboundedAuxiliaryVariables(SCIP *scip, SCIP_BENDERS *benders, SCIP_SOL *sol)
    Definition: cons_benders.c:244
    #define CONSHDLR_NAME
    Definition: cons_benders.c:58
    static SCIP_DECL_CONSINITLP(consInitlpBenders)
    Definition: cons_benders.c:497
    #define DEFAULT_ACTIVE
    Definition: cons_benders.c:70
    constraint handler for Benders' decomposition
    #define NULL
    Definition: def.h:248
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPconsBendersEnforceSolution(SCIP *scip, SCIP_SOL *sol, SCIP_CONSHDLR *conshdlr, SCIP_RESULT *result, SCIP_BENDERSENFOTYPE type, SCIP_Bool checkint)
    Definition: cons_benders.c:286
    SCIP_RETCODE SCIPincludeConshdlrBenders(SCIP *scip)
    Definition: cons_benders.c:821
    int SCIPgetSubscipDepth(SCIP *scip)
    Definition: scip_copy.c:2588
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    SCIP_RETCODE SCIPgetOrigVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
    Definition: scip_prob.c:2753
    SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
    Definition: scip_message.c:88
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    SCIP_RETCODE SCIPheurPassSolAddSol(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *sol)
    Definition: heur_trysol.c:296
    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
    int SCIPgetNActiveBenders(SCIP *scip)
    Definition: scip_benders.c:532
    SCIP_BENDERSOBJTYPE SCIPbendersGetObjectiveType(SCIP_BENDERS *benders)
    Definition: benders.c:6852
    SCIP_Bool SCIPbendersCutRelaxation(SCIP_BENDERS *benders)
    Definition: benders.c:6145
    SCIP_BENDERS ** SCIPgetBenders(SCIP *scip)
    Definition: scip_benders.c:508
    SCIP_RETCODE SCIPcomputeBendersSubproblemLowerbound(SCIP *scip, SCIP_BENDERS *benders, int probnumber, SCIP_Real *lowerbound, SCIP_Bool *infeasible)
    Definition: scip_benders.c:984
    SCIP_VAR * SCIPbendersGetAuxiliaryVar(SCIP_BENDERS *benders, int probnumber)
    Definition: benders.c:6213
    SCIP_Real SCIPgetBendersAuxiliaryVarVal(SCIP *scip, SCIP_BENDERS *benders, SCIP_SOL *sol, int probnumber)
    Definition: scip_benders.c:956
    SCIP_Bool SCIPbendersSubproblemsAreInfeasible(SCIP_BENDERS *benders)
    Definition: benders.c:6577
    SCIP_Bool SCIPbendersCutPseudo(SCIP_BENDERS *benders)
    Definition: benders.c:6135
    SCIP_VAR ** SCIPbendersGetAuxiliaryVars(SCIP_BENDERS *benders)
    Definition: benders.c:6225
    int SCIPbendersGetNSubproblems(SCIP_BENDERS *benders)
    Definition: benders.c:6011
    void SCIPbendersUpdateSubproblemLowerbound(SCIP_BENDERS *benders, int probnumber, SCIP_Real lowerbound)
    Definition: benders.c:6874
    SCIP_Bool SCIPbendersCutLP(SCIP_BENDERS *benders)
    Definition: benders.c:6125
    SCIP_RETCODE SCIPsolveBendersSubproblems(SCIP *scip, SCIP_BENDERS *benders, SCIP_SOL *sol, SCIP_RESULT *result, SCIP_Bool *infeasible, SCIP_Bool *auxviol, SCIP_BENDERSENFOTYPE type, SCIP_Bool checkint)
    Definition: scip_benders.c:647
    SCIP_VAR * SCIPbenderGetMasterAuxiliaryVar(SCIP_BENDERS *benders)
    Definition: benders.c:6203
    SCIP_Real SCIPbendersGetSubproblemObjval(SCIP_BENDERS *benders, int probnumber)
    Definition: benders.c:6302
    SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
    Definition: scip_cons.c:540
    SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
    Definition: scip_cons.c:396
    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 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
    SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
    Definition: scip_cons.c:420
    SCIP_Bool SCIPconshdlrNeedsCons(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:5302
    SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
    Definition: scip_cons.c:347
    void SCIPconshdlrSetNeedsCons(SCIP_CONSHDLR *conshdlr, SCIP_Bool needscons)
    Definition: cons.c:5312
    SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
    Definition: scip_cons.c:624
    SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4336
    SCIP_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
    Definition: scip_heur.c:263
    SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
    Definition: scip_lp.c:174
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    int SCIPcalcMemGrowSize(SCIP *scip, int num)
    Definition: scip_mem.c:139
    #define SCIPallocMemory(scip, ptr)
    Definition: scip_mem.h:60
    #define SCIPfreeMemory(scip, ptr)
    Definition: scip_mem.h:78
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
    Definition: scip_sol.c:884
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    SCIP_RETCODE SCIPcreateLPSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:608
    SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1506
    SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
    Definition: sol.c:4140
    SCIP_RETCODE SCIPcreateRelaxSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:699
    int SCIPsolGetIndex(SCIP_SOL *sol)
    Definition: sol.c:4290
    SCIP_RETCODE SCIPcheckSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *feasible)
    Definition: scip_sol.c:4312
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1571
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    SCIP_RETCODE SCIPcreatePseudoSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:726
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:5697
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
    Definition: scip_var.c:5118
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    primal heuristic that tries a given solution
    methods commonly used by primal heuristics
    void SCIPmessagePrintInfo(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
    Definition: message.c:594
    SCIP callable library.
    @ SCIP_BENDERSENFOTYPE_RELAX
    Definition: type_benders.h:52
    @ SCIP_BENDERSENFOTYPE_LP
    Definition: type_benders.h:51
    @ SCIP_BENDERSENFOTYPE_CHECK
    Definition: type_benders.h:54
    @ SCIP_BENDERSENFOTYPE_PSEUDO
    Definition: type_benders.h:53
    enum SCIP_BendersObjectiveType SCIP_BENDERSOBJTYPE
    Definition: type_benders.h:91
    @ SCIP_BENDERSOBJTYPE_SUM
    Definition: type_benders.h:88
    @ SCIP_BENDERSOBJTYPE_MAX
    Definition: type_benders.h:89
    enum SCIP_BendersEnfoType SCIP_BENDERSENFOTYPE
    Definition: type_benders.h:56
    struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
    Definition: type_cons.h:64
    @ SCIP_LPSOLSTAT_UNBOUNDEDRAY
    Definition: type_lp.h:46
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_FEASIBLE
    Definition: type_result.h:45
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ 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_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_INITPRESOLVE
    Definition: type_set.h:48
    @ SCIP_STAGE_SOLVED
    Definition: type_set.h:54
    @ SCIP_VARSTATUS_FIXED
    Definition: type_var.h:54
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141