relax_benders.c
Go to the documentation of this file.
30 * This relaxator is provided to apply Benders' decomposition to a supplied decomposition structure. The relaxator is
31 * invoked if the user supplies a decomposition structure and sets the parameter "decomposition/applybenders" to TRUE.
32 * In addition, it is recommended that the parameter "decomposition/benderslabels" is set to TRUE to ensure that the
33 * block labelling of the variables and constraints is correct for applying Benders' decomposition.
35 * Given a decomposition structure, the relaxator will create a number of SCIP instances: one for the master problem and
36 * one for each subproblems. These SCIP instances are supplied to the default Benders' decomposition plugin to trigger
37 * the execution of the Benders' decomposition algorithm. The original SCIP instance will execute presolving and start
38 * the solving process. When the root node starts solving, this relaxator will be called first. The Benders'
39 * decomposition algorithm attempts to solve the problem to optimality. At the completion of the Benders' decomposition
40 * algorithm, the best found primal and dual bounds are returned to the original SCIP instance. The solution from the
43 * By default, the original SCIP instance will terminate with an optimal solution or infeasible status (if found or
44 * proven by the Benders' decomposition algorithm, resp.), or a status indicating a time, gap, or bound limit, or a
45 * "user interrupt". To prevent the original SCIP instance to continue solving if the Benders' decomposition algorithm
46 * fails to solve the problem, the user interrupt is also triggered if the Benders' decomposition algorithm stopped due
47 * to a node, restart, or solution limit, or when transferring the solution to the original SCIP instance fails.
48 * To continue solving the original SCIP instance after the conclusion of the Benders' decomposition algorithm,
51 * The working limits from the original SCIP instance are copied across to the master problem SCIP instance. However, if
52 * the user desires to have a different node limit for the master problem, for example if they wish to use
53 * Benders' decomposition as a start heuristic, then this can be set with the parameter "relaxing/benders/nodelimit".
55 * If the Benders' decomposition relaxator is used, then statistics for both the original SCIP instance and the master
56 * problem SCIP instance are displayed when the statistics are requested by via the SCIP shell dialog.
59/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
79#define DEFAULT_CONTORIG FALSE /**< continue solving the original SCIP instance if optimal solution is not found */
80#define DEFAULT_NODELIMIT -1LL /**< node limit for the Benders' decomposition solve, -1 indicates original SCIP limit is used. */
93 SCIP_HASHMAP* mastervarmap; /**< variables mapping between the original SCIP and the master problem */
94 SCIP_HASHMAP** subvarmaps; /**< variables mapping between the original SCIP and the subproblems */
100 SCIP_Bool contorig; /**< continue solving the original SCIP instance if optimal solution is not found */
112 SCIP_HASHMAP* varmap, /**< the variable hash map mapping the source variables to the target variables */
127 SCIP_CALL( SCIPcreateVarImpl(targetscip, &var, SCIPvarGetName(sourcevar), SCIPvarGetLbGlobal(sourcevar),
145/* when applying the decomposition, the constraints must be copied across from the original SCIP instance to the
146 * respective Benders' problems in the relaxator. This could be either the master problem or one of the subproblems. The
153 SCIP_HASHMAP* varmap, /**< the variable hash map mapping the source variables to the target variables */
168 SCIPdebugMessage("Adding constraint <%s> to Benders' decomposition subproblem\n", SCIPconsGetName(sourcecons));
184 /* checking all variables to see whether they already exist in the subproblem. If they don't exist, then the variable
196 SCIP_CALL( SCIPgetConsCopy(scip, targetscip, sourcecons, &cons, SCIPconsGetHdlr(sourcecons), varmap, NULL,
198 SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons), SCIPconsIsMarkedPropagate(sourcecons),
205 SCIPerrorMessage("It is not possible to copy constraint <%s>. Benders' decomposition could not be applied.\n",
216/** Applies a Benders' decomposition to the problem based upon the decomposition selected from the storage */
260 SCIP_CALL( SCIPcopyPlugins(scip, relaxdata->masterprob, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
263 /* including the default Benders' decomposition plugin. This is added separately so that any addition of the plugin
280 SCIP_CALL( SCIPcopyPlugins(scip, relaxdata->subproblems[i], TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
303 SCIP_CALL( SCIPhashmapCreate(&relaxdata->mastervarmap, SCIPblkmem(relaxdata->masterprob), nvars) );
310 SCIP_CALL( SCIPhashmapCreate(&relaxdata->subvarmaps[i], SCIPblkmem(relaxdata->subproblems[i]), nvars) );
316 /* the constraints with a block label >= 0 correspond to subproblem constraints. All other constraints are master
322 SCIP_CALL( addConstraintToBendersProblem(scip, relaxdata->subproblems[conslabels[i]], relaxdata->subvarmaps[conslabels[i]],
327 SCIP_CALL( addConstraintToBendersProblem(scip, relaxdata->masterprob, relaxdata->mastervarmap, conss[i]) );
335 * TODO: consider whether the two-phase method should be activated by default in the scenario stages.
345 /* disabling aggregation since it can affect the mapping between the master and subproblem variables */
357/** copies the best solution from the original SCIP instance and adds it to the master problem of the decomposed problem */
418 SCIP_CALL( SCIPtrySolFree(relaxdata->masterprob, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &stored) );
444/** solves the Benders' decomposition subproblems using the best solution from the master problem */
484 SCIP_CALL( SCIPsetupBendersSubproblem(masterprob, benders, bestsol, i, SCIP_BENDERSENFOTYPE_CHECK) );
487 SCIP_CALL( SCIPsolveBendersSubproblem(masterprob, benders, bestsol, i, infeasible, TRUE, NULL) );
513/** using the stored mappings for the variables, the solution values from the master and subproblems are used to set the
540 if( SCIPisNLPConstructed(relaxdata->subproblems[i]) && SCIPgetNNlpis(relaxdata->subproblems[i]) )
547 /* if there are NLP subproblems, then we need to allocate the nlpsols array and collect the NLP subproblems */
557 if( SCIPisNLPConstructed(relaxdata->subproblems[i]) && SCIPgetNNlpis(relaxdata->subproblems[i]) )
575 /* looping over all variables and assigning the value to the current master or subproblem solution */
583 /* if the varlabel is >= 0, then the variable belongs to the subproblem. Otherwise, the variable belongs to the
603 /* the subproblem could be an NLP. As such, we need to get the solution directly from the NLP */
678/** creates a solution for the original SCIP instance using the solution from the decomposed problem */
695 /* if there is no master solution, then no solution is copied across to the original SCIP instance */
718 "The solution found by the Benders' decomposition algorithm is not valid for the original problem.\n");
745 /* if the decomposition has been applied, then the corresponding SCIP instances need to be freed */
804/** solving process initialization method of relaxator (called when branch and bound process is about to begin) */
830 /* if there already exists an active Benders' decomposition, then default decomposition is not applied. */
833 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "A Benders' decomposition already exists. The default Benders' decomposition will not be applied to the stored decomposition.\n");
840 /* if the default Benders' decomposition plugin doesn't exist, then this will result in an error */
843 SCIPerrorMessage("The default Benders' decomposition plugin is required to apply Benders' decomposition using the input decomposition.");
888 SCIP_CALL( SCIPsetLongintParam(relaxdata->masterprob, "limits/totalnodes", relaxdata->nodelimit) );
890 /* presolving the master problem to initialise the Benders' decomposition data structures. This will allow us to
913 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Copying the solution to the original problem variables\n\n");
915 /* a solution for the original SCIP needs to be created. This will transfer the best found solution from the
923 /* if only the Benders' decomposition algorithm should be executed, then there we need to stop the original SCIP
924 * instance. This is achieved by calling SCIPinterruptSolve. However, it is not necessary to interrupt the solve if
937 /* if the user interrupted the Benders' decomposition algorithm, then the main SCIP should be interrupted too */
972 "continue solving the original SCIP instance if the optimal solution is not found by Benders' decomposition",
976 "the node limit applied only to the Benders' decomposition solve (-1 indicates that the original SCIP node limit is used).",
default Benders' decomposition plugin
SCIP_RETCODE SCIPcreateBendersDefault(SCIP *scip, SCIP **subproblems, int nsubproblems)
Definition: benders_default.c:489
SCIP_RETCODE SCIPincludeBendersDefault(SCIP *scip)
Definition: benders_default.c:528
SCIP_RETCODE SCIPcopyPlugins(SCIP *sourcescip, SCIP *targetscip, SCIP_Bool copyreaders, SCIP_Bool copypricers, SCIP_Bool copyconshdlrs, SCIP_Bool copyconflicthdlrs, SCIP_Bool copypresolvers, SCIP_Bool copyrelaxators, SCIP_Bool copyseparators, SCIP_Bool copycutselectors, SCIP_Bool copypropagators, SCIP_Bool copyheuristics, SCIP_Bool copyeventhdlrs, SCIP_Bool copynodeselectors, SCIP_Bool copybranchrules, SCIP_Bool copyiisfinders, SCIP_Bool copydisplays, SCIP_Bool copydialogs, SCIP_Bool copytables, SCIP_Bool copyexprhdlrs, SCIP_Bool copynlpis, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
Definition: scip_copy.c:276
SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
Definition: scip_copy.c:3249
SCIP_RETCODE SCIPgetConsCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_CONS *sourcecons, SCIP_CONS **targetcons, SCIP_CONSHDLR *sourceconshdlr, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *name, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
Definition: scip_copy.c:1580
SCIP_RETCODE SCIPcopyParamSettings(SCIP *sourcescip, SCIP *targetscip)
Definition: scip_copy.c:2547
SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
Definition: scip_copy.c:3292
void SCIPgetDecomps(SCIP *scip, SCIP_DECOMP ***decomps, int *ndecomps, SCIP_Bool original)
Definition: scip_dcmp.c:263
void SCIPdecompGetConsLabels(SCIP_DECOMP *decomp, SCIP_CONS **conss, int *labels, int nconss)
Definition: dcmp.c:198
void SCIPdecompGetVarsLabels(SCIP_DECOMP *decomp, SCIP_VAR **vars, int *labels, int nvars)
Definition: dcmp.c:149
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:2115
SCIP_RETCODE SCIPcreateProbBasic(SCIP *scip, const char *name)
Definition: scip_prob.c:182
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3284
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3143
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3061
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3466
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:225
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip_param.c:250
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:111
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip_param.c:545
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip_param.c:487
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip_param.c:956
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 SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip_param.c:429
SCIP_BENDERS * SCIPfindBenders(SCIP *scip, const char *name)
Definition: scip_benders.c:493
SCIP_RETCODE SCIPfreeBendersSubproblem(SCIP *scip, SCIP_BENDERS *benders, int probnumber)
Definition: scip_benders.c:886
SCIP_RETCODE SCIPsetupBendersSubproblem(SCIP *scip, SCIP_BENDERS *benders, SCIP_SOL *sol, int probnumber, SCIP_BENDERSENFOTYPE type)
Definition: scip_benders.c:805
SCIP_RETCODE SCIPsolveBendersSubproblem(SCIP *scip, SCIP_BENDERS *benders, SCIP_SOL *sol, int probnumber, SCIP_Bool *infeasible, SCIP_Bool solvecip, SCIP_Real *objective)
Definition: scip_benders.c:843
int SCIPbendersGetNSubproblems(SCIP_BENDERS *benders)
Definition: benders.c:6011
SCIP * SCIPbendersSubproblem(SCIP_BENDERS *benders, int probnumber)
Definition: benders.c:6021
SCIP_RETCODE SCIPgetConsNVars(SCIP *scip, SCIP_CONS *cons, int *nvars, SCIP_Bool *success)
Definition: scip_cons.c:2621
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8598
SCIP_RETCODE SCIPgetConsVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int varssize, SCIP_Bool *success)
Definition: scip_cons.c:2577
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1173
#define SCIPallocClearBufferArray(scip, ptr, num)
Definition: scip_mem.h:126
SCIP_RETCODE SCIPincludeRelax(SCIP *scip, const char *name, const char *desc, int priority, int freq, SCIP_DECL_RELAXCOPY((*relaxcopy)), SCIP_DECL_RELAXFREE((*relaxfree)), SCIP_DECL_RELAXINIT((*relaxinit)), SCIP_DECL_RELAXEXIT((*relaxexit)), SCIP_DECL_RELAXINITSOL((*relaxinitsol)), SCIP_DECL_RELAXEXITSOL((*relaxexitsol)), SCIP_DECL_RELAXEXEC((*relaxexec)), SCIP_RELAXDATA *relaxdata)
Definition: scip_relax.c:61
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:516
SCIP_RETCODE SCIPcreateNLPSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:664
SCIP_RETCODE SCIPaddSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *stored)
Definition: scip_sol.c:3842
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 SCIPtrySolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: scip_sol.c:4109
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 SCIPcreateVarImpl(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_IMPLINTTYPE impltype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip_var.c:225
Definition: multiprecision.hpp:66
public methods for Benders' decomposition
public methods for relaxation handlers
static SCIP_RETCODE addVariableToBendersProblem(SCIP *scip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_VAR *sourcevar)
Definition: relax_benders.c:109
static SCIP_RETCODE createOriginalSolution(SCIP *scip, SCIP_RELAX *relax, SCIP_Bool *infeasible)
Definition: relax_benders.c:680
SCIP_RETCODE SCIPincludeRelaxBenders(SCIP *scip)
Definition: relax_benders.c:955
static SCIP_RETCODE freeDecomposition(SCIP *scip, SCIP_RELAX *relax)
Definition: relax_benders.c:731
static SCIP_RETCODE addInitialSolution(SCIP *scip, SCIP_RELAXDATA *relaxdata)
Definition: relax_benders.c:359
static SCIP_RETCODE freeBendersSubproblems(SCIP *scip, SCIP_RELAX *relax)
Definition: relax_benders.c:644
SCIP * SCIPgetMasterProblemRelaxBenders(SCIP *scip)
Definition: relax_benders.c:983
static SCIP_RETCODE solveBendersSubproblems(SCIP *scip, SCIP_RELAX *relax, SCIP_Bool *infeasible)
Definition: relax_benders.c:446
static SCIP_RETCODE getNlpSolution(SCIP *scip, SCIP_SOL **nlpsol)
Definition: relax_benders.c:499
static SCIP_DECL_RELAXINITSOL(relaxInitsolBenders)
Definition: relax_benders.c:806
static SCIP_Bool masterSolutionExists(SCIP *scip, SCIP_RELAX *relax)
Definition: relax_benders.c:425
static SCIP_RETCODE setSolutionValues(SCIP *scip, SCIP_RELAX *relax, SCIP_SOL *sol)
Definition: relax_benders.c:517
static SCIP_RETCODE addConstraintToBendersProblem(SCIP *scip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_CONS *sourcecons)
Definition: relax_benders.c:150
static SCIP_RETCODE applyDecomposition(SCIP *scip, SCIP_RELAX *relax, SCIP_DECOMP *decomp)
Definition: relax_benders.c:218
benders relaxator
SCIP callable library.
Definition: struct_benders.h:58
Definition: struct_cons.h:47
Definition: struct_dcmp.h:45
Definition: struct_misc.h:139
Definition: struct_relax.h:47
Definition: struct_sol.h:74
Definition: struct_var.h:262
Definition: struct_scip.h:72
type definitions for Benders' decomposition methods
type definitions for message output methods
type definitions for relaxators
type definitions for return codes for SCIP methods
type definitions for problem statistics