Scippy

SCIP

Solving Constraint Integer Programs

relax_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 relax_benders.c
26 * @ingroup DEFPLUGINS_RELAX
27 * @brief benders relaxator
28 * @author Stephen J. Maher
29 *
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.
34 *
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
41 * decomposed problem is mapped back to the original instance variables.
42 *
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,
49 * parameter "relaxing/benders/continueorig" can be set to TRUE.
50 *
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".
54 *
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.
57 */
58
59/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
60
61#include <assert.h>
62
63#include "scip/scip.h"
65#include "scip/pub_benders.h"
66#include "scip/pub_relax.h"
67#include "scip/relax_benders.h"
68#include "scip/type_benders.h"
69#include "scip/type_message.h"
70#include "scip/type_relax.h"
71#include "scip/type_retcode.h"
72#include "scip/type_stat.h"
73
74#define RELAX_NAME "benders"
75#define RELAX_DESC "applies default Benders' decomposition and solves the problem"
76#define RELAX_PRIORITY 1
77#define RELAX_FREQ 0
78
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. */
81
82
83/*
84 * Data structures
85 */
86
87/** relaxator data */
88struct SCIP_RelaxData
89{
90 SCIP* masterprob; /**< the SCIP instance of the master problem */
91 SCIP** subproblems; /**< an array of SCIP instances for the subproblems */
92 SCIP_DECOMP* decomp; /**< the structure used for the decomposition */
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 */
95 int nsubproblems; /**< the number of subproblems */
96 SCIP_Bool decompapplied; /**< indicates whether the decomposition was applied */
97
98 /* parameters */
99 SCIP_Longint nodelimit; /**< the node limit for the Benders' decomposition solve */
100 SCIP_Bool contorig; /**< continue solving the original SCIP instance if optimal solution is not found */
101};
102
103/*
104 * Local methods
105 */
106
107/** adding variables from the original problem to the respective decomposed problem */
108static
110 SCIP* scip, /**< the SCIP data structure */
111 SCIP* targetscip, /**< the SCIP instance that the constraint will be copied into */
112 SCIP_HASHMAP* varmap, /**< the variable hash map mapping the source variables to the target variables */
113 SCIP_VAR* sourcevar /**< the variable to add to the problem */
114 )
115{
116 assert(scip != NULL);
117 assert(targetscip != NULL);
118 assert(varmap != NULL);
119 assert(sourcevar != NULL);
120
121 /* if the variable is not in the hashmap, then it doesn't exist in the subproblem */
122 if( !SCIPhashmapExists(varmap, sourcevar) )
123 {
124 SCIP_VAR* var;
125
126 /* creating a variable as a copy of the original variable. */
127 SCIP_CALL( SCIPcreateVarImpl(targetscip, &var, SCIPvarGetName(sourcevar), SCIPvarGetLbGlobal(sourcevar),
128 SCIPvarGetUbGlobal(sourcevar), SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
129 SCIPvarGetImplType(sourcevar), SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
130 NULL, NULL, NULL, NULL, NULL) );
131
132 /* adding the variable to the subproblem */
133 SCIP_CALL( SCIPaddVar(targetscip, var) );
134
135 /* adding the variable to the hash map so that it is copied correctly in the constraint */
136 SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, var) );
137
138 /* releasing the variable */
139 SCIP_CALL( SCIPreleaseVar(targetscip, &var) );
140 }
141
142 return SCIP_OKAY;
143}
144
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
147 * process for performing this is the same for either problem type.
148 */
149static
151 SCIP* scip, /**< the original SCIP instance */
152 SCIP* targetscip, /**< the SCIP instance that the constraint will be copied into */
153 SCIP_HASHMAP* varmap, /**< the variable hash map mapping the source variables to the target variables */
154 SCIP_CONS* sourcecons /**< the constraint that being added to the subproblem */
155 )
156{
157 SCIP_CONS* cons;
158 SCIP_VAR** consvars;
159 int nconsvars;
160 int i;
161 SCIP_Bool success;
162
163 assert(scip != NULL);
164 assert(targetscip != NULL);
165 assert(varmap != NULL);
166 assert(sourcecons != NULL);
167
168 SCIPdebugMessage("Adding constraint <%s> to Benders' decomposition subproblem\n", SCIPconsGetName(sourcecons));
169
170 /* getting the variables that are in the constraint */
171 SCIP_CALL( SCIPgetConsNVars(scip, sourcecons, &nconsvars, &success) );
172 if( !success )
173 return SCIP_ERROR;
174
175 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
176
177 SCIP_CALL( SCIPgetConsVars(scip, sourcecons, consvars, nconsvars, &success) );
178 if( !success )
179 {
180 SCIPfreeBufferArray(scip, &consvars);
181 return SCIP_ERROR;
182 }
183
184 /* checking all variables to see whether they already exist in the subproblem. If they don't exist, then the variable
185 * is created
186 */
187 for( i = 0; i < nconsvars; i++ )
188 {
189 SCIP_CALL( addVariableToBendersProblem(scip, targetscip, varmap, consvars[i]) );
190 }
191
192 /* freeing the buffer memory for the consvars */
193 SCIPfreeBufferArray(scip, &consvars);
194
195 /* copying the constraint from the master scip to the subproblem */
196 SCIP_CALL( SCIPgetConsCopy(scip, targetscip, sourcecons, &cons, SCIPconsGetHdlr(sourcecons), varmap, NULL,
197 SCIPconsGetName(sourcecons), SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
198 SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons), SCIPconsIsMarkedPropagate(sourcecons),
199 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
200 SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons), TRUE, &success) );
201
202 /* if the copy failed, then the subproblem for the decomposition could not be performed. */
203 if( !success )
204 {
205 SCIPerrorMessage("It is not possible to copy constraint <%s>. Benders' decomposition could not be applied.\n",
206 SCIPconsGetName(sourcecons));
207 return SCIP_ERROR;
208 }
209
210 SCIP_CALL( SCIPaddCons(targetscip, cons) );
211 SCIP_CALL( SCIPreleaseCons(targetscip, &cons) );
212
213 return SCIP_OKAY;
214}
215
216/** Applies a Benders' decomposition to the problem based upon the decomposition selected from the storage */
217static
219 SCIP* scip, /**< the original SCIP instance */
220 SCIP_RELAX* relax, /**< the relaxator */
221 SCIP_DECOMP* decomp /**< the decomposition to apply to the problem */
222 )
223{
224 SCIP_RELAXDATA* relaxdata;
225 SCIP_VAR** vars;
226 SCIP_CONS** conss;
227 int* varslabels;
228 int* conslabels;
229 int nvars;
230 int nconss;
231 int nblocks;
232 int i;
233 char probname[SCIP_MAXSTRLEN];
234 SCIP_Bool valid;
235
236 assert(scip != NULL);
237 assert(decomp != NULL);
238 assert(relax != NULL);
239
240 relaxdata = SCIPrelaxGetData(relax);
241 assert(relaxdata != NULL);
242
243 SCIPdebugMessage("Applying a Benders' decomposition to <%s>\n", SCIPgetProbName(scip));
244
245 /* storing the decomposition */
246 relaxdata->decomp = decomp;
247
248 /* retrieving the number of blocks for this decomposition */
249 nblocks = SCIPdecompGetNBlocks(decomp);
250 assert(nblocks > 0);
251
252 /* initialising the subproblems for the Benders' decomposition */
253 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->subproblems, nblocks) );
254 relaxdata->nsubproblems = nblocks;
255
256 /* creating the master problem */
257 SCIP_CALL( SCIPcreate(&relaxdata->masterprob) );
258
259 /* copying the plugins from the original SCIP instance to the master SCIP */
260 SCIP_CALL( SCIPcopyPlugins(scip, relaxdata->masterprob, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
261 TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, &valid) );
262
263 /* including the default Benders' decomposition plugin. This is added separately so that any addition of the plugin
264 * in the master problem is ignored
265 */
266 SCIP_CALL( SCIPincludeBendersDefault(relaxdata->masterprob) );
267
268 /* copying the parameter settings from the original SCIP to the master problem */
269 SCIP_CALL( SCIPcopyParamSettings(scip, relaxdata->masterprob) );
270
271 (void) SCIPsnprintf(probname, SCIP_MAXSTRLEN, "master_%s", SCIPgetProbName(scip));
272 SCIP_CALL( SCIPcreateProbBasic(relaxdata->masterprob, probname) );
273
274 /* creating the subproblems before adding the constraints */
275 for( i = 0; i < nblocks; i++ )
276 {
277 SCIP_CALL( SCIPcreate(&relaxdata->subproblems[i]) );
278
279 /* copying the plugins from the original SCIP instance to the subproblem SCIP */
280 SCIP_CALL( SCIPcopyPlugins(scip, relaxdata->subproblems[i], TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
281 TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, &valid) );
282
283 (void) SCIPsnprintf(probname, SCIP_MAXSTRLEN, "sub_%s_%d", SCIPgetProbName(scip), i);
284 SCIP_CALL( SCIPcreateProbBasic(relaxdata->subproblems[i], probname) );
285 }
286
287 /* TODO: Need to work out whether a check for original and transformed problem is necessary */
288
289 /* getting the variables and constraints from the problem */
290 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
291 conss = SCIPgetConss(scip);
292 nconss = SCIPgetNConss(scip);
293
294 /* allocating buffer memory for the labels arrays */
295 SCIP_CALL( SCIPallocBufferArray(scip, &varslabels, nvars) );
296 SCIP_CALL( SCIPallocBufferArray(scip, &conslabels, nconss) );
297
298 /* getting the labels for the variables and constraints from the decomposition */
299 SCIPdecompGetVarsLabels(decomp, vars, varslabels, nvars);
300 SCIPdecompGetConsLabels(decomp, conss, conslabels, nconss);
301
302 /* creating the variable map for the master problem */
303 SCIP_CALL( SCIPhashmapCreate(&relaxdata->mastervarmap, SCIPblkmem(relaxdata->masterprob), nvars) );
304
305 /* creating the variable maps for adding the constraints to the subproblems */
306 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &relaxdata->subvarmaps, nblocks) );
307
308 for( i = 0; i < nblocks; i++ )
309 {
310 SCIP_CALL( SCIPhashmapCreate(&relaxdata->subvarmaps[i], SCIPblkmem(relaxdata->subproblems[i]), nvars) );
311 }
312
313 /* copying the constraints to the appropriate subproblems */
314 for( i = 0; i < nconss; i++ )
315 {
316 /* the constraints with a block label >= 0 correspond to subproblem constraints. All other constraints are master
317 * constraints.
318 */
319 if( conslabels[i] >= 0 )
320 {
321 assert(conslabels[i] < relaxdata->nsubproblems);
322 SCIP_CALL( addConstraintToBendersProblem(scip, relaxdata->subproblems[conslabels[i]], relaxdata->subvarmaps[conslabels[i]],
323 conss[i]) );
324 }
325 else
326 {
327 SCIP_CALL( addConstraintToBendersProblem(scip, relaxdata->masterprob, relaxdata->mastervarmap, conss[i]) );
328 }
329 }
330
331 /* creating the Benders' decomposition by calling the default plugin */
332 SCIP_CALL( SCIPcreateBendersDefault(relaxdata->masterprob, relaxdata->subproblems, nblocks) );
333
334 /* activating the Benders' constraint handler for the scenario stages.
335 * TODO: consider whether the two-phase method should be activated by default in the scenario stages.
336 */
337 SCIP_CALL( SCIPsetBoolParam(relaxdata->masterprob, "constraints/benders/active", TRUE) );
338 SCIP_CALL( SCIPsetBoolParam(relaxdata->masterprob, "constraints/benderslp/active", TRUE) );
339
340 /* changing settings that are required for Benders' decomposition */
341 SCIP_CALL( SCIPsetPresolving(relaxdata->masterprob, SCIP_PARAMSETTING_OFF, TRUE) );
342 SCIP_CALL( SCIPsetIntParam(relaxdata->masterprob, "propagating/maxrounds", 0) );
343 SCIP_CALL( SCIPsetIntParam(relaxdata->masterprob, "propagating/maxroundsroot", 0) );
344
345 /* disabling aggregation since it can affect the mapping between the master and subproblem variables */
346 SCIP_CALL( SCIPsetBoolParam(relaxdata->masterprob, "presolving/donotaggr", TRUE) );
347 SCIP_CALL( SCIPsetBoolParam(relaxdata->masterprob, "presolving/donotmultaggr", TRUE) );
348
349 SCIPfreeBufferArray(scip, &conslabels);
350 SCIPfreeBufferArray(scip, &varslabels);
351
352 relaxdata->decompapplied = TRUE;
353
354 return SCIP_OKAY;
355}
356
357/** copies the best solution from the original SCIP instance and adds it to the master problem of the decomposed problem */
358static
360 SCIP* scip, /**< the SCIP instance */
361 SCIP_RELAXDATA* relaxdata /**< the relaxator data */
362 )
363{
364 SCIP* masterprob;
365 SCIP_SOL* sol;
366 SCIP_SOL* bestsol;
367 SCIP_DECOMP* decomp;
368 SCIP_VAR** vars;
369 int* varslabels;
370 int nvars;
371 int i;
372 SCIP_Bool stored;
373
374 assert(scip != NULL);
375 assert(relaxdata != NULL);
376 assert(relaxdata->masterprob != NULL);
377
378 masterprob = relaxdata->masterprob;
379
380 bestsol = SCIPgetBestSol(scip);
381
382 /* if the best solution doesn't exist, then there is no solution to copy */
383 if( bestsol == NULL )
384 return SCIP_OKAY;
385
386 vars = SCIPgetVars(scip);
387 nvars = SCIPgetNVars(scip);
388
389 SCIP_CALL( SCIPcreateSol(masterprob, &sol, NULL) );
390
391 decomp = relaxdata->decomp;
392
393 /* allocating buffer memory for the labels arrays */
394 SCIP_CALL( SCIPallocBufferArray(scip, &varslabels, nvars) );
395
396 /* getting the labels for the variables and constraints from the decomposition */
397 SCIPdecompGetVarsLabels(decomp, vars, varslabels, nvars);
398
399 /* setting the value of the variables that are in the master problem */
400 for( i = 0; i < nvars; i++ )
401 {
402 SCIP_VAR* mappedvar;
403
404 /* we are only interested in the master problem variables */
405 if( varslabels[i] < 0 )
406 {
407 mappedvar = (SCIP_VAR*)SCIPhashmapGetImage(relaxdata->mastervarmap, vars[i]);
408 if( mappedvar != NULL )
409 {
410 SCIP_CALL( SCIPsetSolVal(masterprob, sol, mappedvar,
411 SCIPgetSolVal(scip, bestsol, vars[i])) );
412 }
413 }
414 }
415
416 SCIPfreeBufferArray(scip, &varslabels);
417
418 SCIP_CALL( SCIPtrySolFree(relaxdata->masterprob, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &stored) );
419
420 return SCIP_OKAY;
421}
422
423/** returns whether a solution exists for the master problem */
424static
426 SCIP* scip, /**< the SCIP data structure */
427 SCIP_RELAX* relax /**< the relaxator */
428 )
429{
430 SCIP_RELAXDATA* relaxdata;
431
432 assert(scip != NULL);
433 assert(relax != NULL);
434
435 relaxdata = SCIPrelaxGetData(relax);
436 assert(relaxdata != NULL);
437
438 assert(relaxdata->masterprob != NULL);
439
440 return (SCIPgetBestSol(relaxdata->masterprob) != NULL);
441}
442
443
444/** solves the Benders' decomposition subproblems using the best solution from the master problem */
445static
447 SCIP* scip, /**< the SCIP data structure */
448 SCIP_RELAX* relax, /**< the relaxator */
449 SCIP_Bool* infeasible /**< indicates whether the best solution is infeasible */
450 )
451{
452 SCIP_RELAXDATA* relaxdata;
453 SCIP* masterprob;
454 SCIP_BENDERS* benders;
455 SCIP_SOL* bestsol;
456 int i;
457
458 assert(scip != NULL);
459 assert(relax != NULL);
460 assert(infeasible != NULL);
461
462 relaxdata = SCIPrelaxGetData(relax);
463 assert(relaxdata != NULL);
464
465 masterprob = relaxdata->masterprob;
466
467 assert(SCIPgetNActiveBenders(masterprob) == 1);
468
469 /* getting the Default Benders' plugin to solve the subproblems */
470 benders = SCIPfindBenders(masterprob, "default");
471 assert(benders != NULL);
472 assert(relaxdata->nsubproblems == SCIPbendersGetNSubproblems(benders));
473
474 /* getting the best solution for the master problem */
475 bestsol = SCIPgetBestSol(masterprob);
476
477 /* solving the Benders' decomposition subproblems */
478 for( i = 0; i < relaxdata->nsubproblems; i++)
479 {
480 assert(SCIPbendersSubproblem(benders, i) != NULL
482
483 /* setting up the subproblem with the best solution from the master problem */
484 SCIP_CALL( SCIPsetupBendersSubproblem(masterprob, benders, bestsol, i, SCIP_BENDERSENFOTYPE_CHECK) );
485
486 /* solving the subproblem */
487 SCIP_CALL( SCIPsolveBendersSubproblem(masterprob, benders, bestsol, i, infeasible, TRUE, NULL) );
488
489 /* if a subproblem is infeasible, then the solution is reported as infeasible */
490 if( (*infeasible) )
491 break;
492 }
493
494 return SCIP_OKAY;
495}
496
497/** constructs the NLP solution and returns it */
498static
500 SCIP* scip, /**< the SCIP instance for which an NLP must be constructed */
501 SCIP_SOL** nlpsol /**< the NLP solution that will be created */
502 )
503{
504 assert(scip != NULL);
505 assert(SCIPisNLPConstructed(scip));
506 assert(SCIPgetNNlpis(scip));
507
508 SCIP_CALL( SCIPcreateNLPSol(scip, nlpsol, NULL) );
509
510 return SCIP_OKAY;
511}
512
513/** using the stored mappings for the variables, the solution values from the master and subproblems are used to set the
514 * solution values in the original SCIP solution
515 */
516static
518 SCIP* scip, /**< the original SCIP instance */
519 SCIP_RELAX* relax, /**< the relaxator */
520 SCIP_SOL* sol /**< the solution for the original SCIP instance */
521 )
522{
523 SCIP_RELAXDATA* relaxdata;
524 SCIP_DECOMP* decomp;
525 SCIP_VAR** vars;
526 SCIP_SOL** nlpsols;
527 int* varslabels;
528 int nvars;
529 int i;
530 SCIP_Bool nlpsubprob;
531
532 relaxdata = SCIPrelaxGetData(relax);
533 assert(relaxdata != NULL);
534
535 nlpsols = NULL;
536 nlpsubprob = FALSE;
537 /* checking whether the NLP solutions should be collected. */
538 for( i = 0; i < relaxdata->nsubproblems; i++ )
539 {
540 if( SCIPisNLPConstructed(relaxdata->subproblems[i]) && SCIPgetNNlpis(relaxdata->subproblems[i]) )
541 {
542 nlpsubprob = TRUE;
543 break;
544 }
545 }
546
547 /* if there are NLP subproblems, then we need to allocate the nlpsols array and collect the NLP subproblems */
548 if( nlpsubprob )
549 {
550 SCIP* subproblem;
551
552 SCIP_CALL( SCIPallocClearBufferArray(scip, &nlpsols, relaxdata->nsubproblems) );
553
554 for( i = 0; i < relaxdata->nsubproblems; i++ )
555 {
556 subproblem = relaxdata->subproblems[i];
557 if( SCIPisNLPConstructed(relaxdata->subproblems[i]) && SCIPgetNNlpis(relaxdata->subproblems[i]) )
558 {
559 SCIP_CALL( getNlpSolution(subproblem, &(nlpsols[i])) );
560 }
561 }
562 }
563
564 decomp = relaxdata->decomp;
565
566 /* getting the variables and constraints from the problem */
567 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
568
569 /* allocating buffer memory for the labels arrays */
570 SCIP_CALL( SCIPallocBufferArray(scip, &varslabels, nvars) );
571
572 /* getting the labels for the variables and constraints from the decomposition */
573 SCIPdecompGetVarsLabels(decomp, vars, varslabels, nvars);
574
575 /* looping over all variables and assigning the value to the current master or subproblem solution */
576 for( i = 0; i < nvars; i++ )
577 {
578 SCIP* solscip;
579 SCIP_HASHMAP* varmap;
580 SCIP_SOL* bestsol;
581 SCIP_Bool subproblem;
582
583 /* if the varlabel is >= 0, then the variable belongs to the subproblem. Otherwise, the variable belongs to the
584 * master problem.
585 */
586 subproblem = varslabels[i] >= 0;
587 if( subproblem )
588 {
589 solscip = relaxdata->subproblems[varslabels[i]];
590 varmap = relaxdata->subvarmaps[varslabels[i]];
591 }
592 else
593 {
594 solscip = relaxdata->masterprob;
595 varmap = relaxdata->mastervarmap;
596 }
597
598 if( SCIPhashmapExists(varmap, vars[i]) )
599 {
600 SCIP_VAR* mappedvar;
601 SCIP_Bool nlprelaxation;
602
603 /* the subproblem could be an NLP. As such, we need to get the solution directly from the NLP */
604 nlprelaxation = subproblem && SCIPisNLPConstructed(solscip) && SCIPgetNNlpis(solscip);
605 assert(!nlprelaxation || nlpsols != NULL);
606 if( nlprelaxation && nlpsols != NULL )
607 {
608 assert(nlpsols[varslabels[i]] != NULL);
609 bestsol = nlpsols[varslabels[i]];
610 }
611 else
612 bestsol = SCIPgetBestSol(solscip);
613
614 mappedvar = (SCIP_VAR*)SCIPhashmapGetImage(varmap, vars[i]);
615 if( mappedvar != NULL )
616 {
617 SCIP_CALL( SCIPsetSolVal(scip, sol, vars[i],
618 SCIPgetSolVal(solscip, bestsol, mappedvar)) );
619 }
620 }
621 }
622
623 SCIPfreeBufferArray(scip, &varslabels);
624
625 /* if there were NLP subproblems, then the solutions and storage array must be freed */
626 if( nlpsubprob )
627 {
628 for( i = relaxdata->nsubproblems - 1; i >= 0; i-- )
629 {
630 if( nlpsols[i] != NULL )
631 {
632 SCIP_CALL( SCIPfreeSol(relaxdata->subproblems[i], &(nlpsols[i])) );
633 }
634 }
635
636 SCIPfreeBufferArray(scip, &nlpsols);
637 }
638
639 return SCIP_OKAY;
640}
641
642/** frees the subproblems after the solve */
643static
645 SCIP* scip, /**< the SCIP data structure */
646 SCIP_RELAX* relax /**< the relaxator */
647 )
648{
649 SCIP_RELAXDATA* relaxdata;
650 SCIP* masterprob;
651 SCIP_BENDERS* benders;
652 int i;
653
654 assert(scip != NULL);
655 assert(relax != NULL);
656
657 relaxdata = SCIPrelaxGetData(relax);
658 assert(relaxdata != NULL);
659
660 masterprob = relaxdata->masterprob;
661 assert(SCIPgetNActiveBenders(masterprob) == 1);
662
663 /* getting the Default Benders' plugin to solve the subproblems */
664 benders = SCIPfindBenders(masterprob, "default");
665 assert(benders != NULL);
666 assert(relaxdata->nsubproblems == SCIPbendersGetNSubproblems(benders));
667
668 /* freeing the Benders' decomposition subproblems */
669 for( i = 0; i < relaxdata->nsubproblems; i++)
670 {
672 }
673
674 return SCIP_OKAY;
675}
676
677
678/** creates a solution for the original SCIP instance using the solution from the decomposed problem */
679static
681 SCIP* scip, /**< the SCIP data structure */
682 SCIP_RELAX* relax, /**< the relaxator */
683 SCIP_Bool* infeasible /**< indicates whether the best solution is infeasible */
684 )
685{
686 SCIP_SOL* sol;
687 SCIP_Bool success;
688
689 assert(scip != NULL);
690 assert(relax != NULL);
691 assert(infeasible != NULL);
692
693 (*infeasible) = FALSE;
694
695 /* if there is no master solution, then no solution is copied across to the original SCIP instance */
696 if( !masterSolutionExists(scip, relax) )
697 return SCIP_OKAY;
698
699 /* creating the solution for the original SCIP */
700 SCIP_CALL( SCIPcreateSol(scip, &sol, NULL) );
701
702 /* solving the Benders' decomposition subproblems with the best master problem solution */
703 SCIP_CALL( solveBendersSubproblems(scip, relax, infeasible) );
704
705 /* setting the solution values of the solution based on the decomposed problem solution */
706 SCIP_CALL( setSolutionValues(scip, relax, sol) );
707
708 /* checking if the solution is feasible for the original problem */
709 SCIP_CALL( SCIPcheckSol(scip, sol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
710 if( success )
711 {
712 SCIP_Bool stored;
713 SCIP_CALL( SCIPaddSol(scip, sol, &stored) );
714 }
715 else
716 {
718 "The solution found by the Benders' decomposition algorithm is not valid for the original problem.\n");
719 }
720
721 SCIP_CALL( SCIPfreeSol(scip, &sol) );
722
723 /* freeing the subproblems after the solve */
725
726 return SCIP_OKAY;
727}
728
729/* frees all of the data structures used to apply the decomposition */
730static
732 SCIP* scip, /**< the SCIP data structure */
733 SCIP_RELAX* relax /**< the relaxator */
734 )
735{
736 SCIP_RELAXDATA* relaxdata;
737 int i;
738
739 assert(scip != NULL);
740 assert(relax != NULL);
741
742 relaxdata = SCIPrelaxGetData(relax);
743 assert(relaxdata != NULL);
744
745 /* if the decomposition has been applied, then the corresponding SCIP instances need to be freed */
746 if( relaxdata->decompapplied )
747 {
748 /* freeing the variable hash maps */
749 for( i = relaxdata->nsubproblems - 1; i >= 0; i-- )
750 {
751 SCIPhashmapFree(&relaxdata->subvarmaps[i]);
752 }
753 SCIPhashmapFree(&relaxdata->mastervarmap);
754
755 SCIP_CALL( SCIPfree(&relaxdata->masterprob) );
756
757 for( i = relaxdata->nsubproblems - 1; i >= 0; i-- )
758 {
759 SCIP_CALL( SCIPfree(&relaxdata->subproblems[i]) );
760 }
761
762 /* freeing the allocated arrays */
763 SCIPfreeBlockMemoryArray(scip, &relaxdata->subvarmaps, relaxdata->nsubproblems);
764 SCIPfreeBlockMemoryArray(scip, &relaxdata->subproblems, relaxdata->nsubproblems);
765
766 relaxdata->decompapplied = FALSE;
767 }
768
769 return SCIP_OKAY;
770}
771
772/*
773 * Callback methods of relaxator
774 */
775
776#define relaxCopyBenders NULL
777#define relaxInitBenders NULL
778#define relaxExitBenders NULL
779#define relaxExitsolBenders NULL
780
781/** destructor of relaxator to free user data (called when SCIP is exiting) */
782static
783SCIP_DECL_RELAXFREE(relaxFreeBenders)
784{ /*lint --e{715}*/
785SCIP_RELAXDATA* relaxdata;
786
787 assert(scip != NULL);
788 assert(relax != NULL);
789
790 relaxdata = SCIPrelaxGetData(relax);
791 assert(relaxdata != NULL);
792
793 /* freeing the decomposition information */
795
796 SCIPfreeBlockMemory(scip, &relaxdata);
797
798 return SCIP_OKAY;
799}
800
801
802
803
804/** solving process initialization method of relaxator (called when branch and bound process is about to begin) */
805static
806SCIP_DECL_RELAXINITSOL(relaxInitsolBenders)
807{ /*lint --e{715}*/
808 SCIP_BENDERS* benders;
809 SCIP_DECOMP** decomps;
810 int ndecomps;
811 SCIP_Bool applybenders;
812
813 assert(scip != NULL);
814
815 /* if a decomposition has been previously applied, then it must be freed first */
817
818 SCIP_CALL( SCIPgetBoolParam(scip, "decomposition/applybenders", &applybenders) );
819 if( !applybenders )
820 return SCIP_OKAY;
821
822 SCIPgetDecomps(scip, &decomps, &ndecomps, FALSE);
823
824 /* if there are no decompositions, then Benders' decomposition can't be applied */
825 if( ndecomps == 0 )
826 return SCIP_OKAY;
827
828 assert(decomps[0] != NULL);
829
830 /* if there already exists an active Benders' decomposition, then default decomposition is not applied. */
831 if( SCIPgetNActiveBenders(scip) > 0 )
832 {
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");
834 return SCIP_OKAY;
835 }
836
837 /* retrieving the default Benders' decomposition plugin */
838 benders = SCIPfindBenders(scip, "default");
839
840 /* if the default Benders' decomposition plugin doesn't exist, then this will result in an error */
841 if( benders == NULL )
842 {
843 SCIPerrorMessage("The default Benders' decomposition plugin is required to apply Benders' decomposition using the input decomposition.");
844 return SCIP_ERROR;
845 }
846
847 /* applying the Benders' decomposition */
848 SCIP_CALL( applyDecomposition(scip, relax, decomps[0]) );
849
850 return SCIP_OKAY;
851}
852
853/** execution method of relaxator */
854static
855SCIP_DECL_RELAXEXEC(relaxExecBenders)
856{ /*lint --e{715}*/
857 SCIP_RELAXDATA* relaxdata;
858 SCIP_Bool success;
859 SCIP_Bool infeasible;
860 SCIP_STATUS masterstatus;
861
862 assert(scip != NULL);
863 assert(relax != NULL);
864
865 (*result) = SCIP_DIDNOTRUN;
866 infeasible = FALSE;
867
868 relaxdata = SCIPrelaxGetData(relax);
869 assert(relaxdata != NULL);
870
871 /* the relaxator is only executed if the Benders decomposition is applied */
872 if( !relaxdata->decompapplied )
873 return SCIP_OKAY;
874
875 /* checking whether there is enough time and memory to perform the decomposition solve */
876 SCIP_CALL( SCIPcheckCopyLimits(scip, &success) );
877 if( !success )
878 return SCIP_OKAY;
879
881 "\nApplying Benders' decomposition and solving the decomposed problem.\n\n");
882
883 /* copying the time and memory limits from the original SCIP to the master problem */
884 SCIP_CALL( SCIPcopyLimits(scip, relaxdata->masterprob) );
885
886 /* is a Benders' decomposition node limit is set, then it is applied to the master problem */
887 if( relaxdata->nodelimit >= 0 )
888 SCIP_CALL( SCIPsetLongintParam(relaxdata->masterprob, "limits/totalnodes", relaxdata->nodelimit) );
889
890 /* presolving the master problem to initialise the Benders' decomposition data structures. This will allow us to
891 * supply an initial solution coming from the original SCIP instance.
892 */
893 SCIP_CALL( SCIPpresolve(relaxdata->masterprob) );
894
895 /* adding an initial solution from the original SCIP instance */
896 SCIP_CALL( addInitialSolution(scip, relaxdata) );
897
898 SCIP_CALL( SCIPsolve(relaxdata->masterprob) );
899
900 masterstatus = SCIPgetStatus(relaxdata->masterprob);
901
903 "\nBenders' decomposition solve has completed with status %s.", SCIPstatusName(masterstatus));
904
905 /* if the problem is solved to be infeasible, then the result needs to be set to CUTOFF. */
906 if( masterstatus == SCIP_STATUS_INFEASIBLE )
907 {
909 (*result) = SCIP_CUTOFF;
910 return SCIP_OKAY;
911 }
912
913 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Copying the solution to the original problem variables\n\n");
914
915 /* a solution for the original SCIP needs to be created. This will transfer the best found solution from the
916 * Benders decomposition solve back to the original SCIP instance.
917 */
918 SCIP_CALL( createOriginalSolution(scip, relax, &infeasible) );
919
920 (*lowerbound) = SCIPgetDualbound(relaxdata->masterprob);
921 (*result) = SCIP_SUCCESS;
922
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
925 * the time, gap, primal or dual limits are reached in the Benders' decomposition algorithm.
926 */
927 if( !relaxdata->contorig &&
928 masterstatus != SCIP_STATUS_TIMELIMIT &&
929 masterstatus != SCIP_STATUS_GAPLIMIT &&
930 masterstatus != SCIP_STATUS_PRIMALLIMIT &&
931 masterstatus != SCIP_STATUS_DUALLIMIT
932 )
933 {
935 }
936
937 /* if the user interrupted the Benders' decomposition algorithm, then the main SCIP should be interrupted too */
938 if( masterstatus == SCIP_STATUS_USERINTERRUPT )
939 {
941 }
942
943 return SCIP_OKAY;
944}
945
946
947
948
949
950/*
951 * relaxator specific interface methods
952 */
953
954/** creates the benders relaxator and includes it in SCIP */
956 SCIP* scip /**< SCIP data structure */
957 )
958{
959 SCIP_RELAXDATA* relaxdata;
960
961 /* create benders relaxator data */
962 relaxdata = NULL;
964
965 /* include relaxator */
967 relaxCopyBenders, relaxFreeBenders, relaxInitBenders, relaxExitBenders, relaxInitsolBenders,
968 relaxExitsolBenders, relaxExecBenders, relaxdata) );
969
970 /* adding parameters for the Benders' relaxator */
971 SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/" RELAX_NAME "/continueorig",
972 "continue solving the original SCIP instance if the optimal solution is not found by Benders' decomposition",
973 &relaxdata->contorig, FALSE, DEFAULT_CONTORIG, NULL, NULL) );
974
975 SCIP_CALL( SCIPaddLongintParam(scip, "relaxing/" RELAX_NAME "/nodelimit",
976 "the node limit applied only to the Benders' decomposition solve (-1 indicates that the original SCIP node limit is used).",
977 &relaxdata->nodelimit, FALSE, DEFAULT_NODELIMIT, -1LL, SCIP_LONGINT_MAX, NULL, NULL) );
978
979 return SCIP_OKAY;
980}
981
982/** returns the master problem SCIP instance */
984 SCIP* scip /**< SCIP data structure */
985 )
986{
987 SCIP_RELAX* relax;
988 SCIP_RELAXDATA* relaxdata;
989
990 assert(scip != NULL);
991
992 relax = SCIPfindRelax(scip, RELAX_NAME);
993 if( relax == NULL )
994 return NULL;
995
996 relaxdata = SCIPrelaxGetData(relax);
997 assert(relaxdata != NULL);
998
999 /* if the decomposition has not been applied, then there are no statistics to display */
1000 if( !relaxdata->decompapplied )
1001 return NULL;
1002
1003 return relaxdata->masterprob;
1004}
default Benders' decomposition plugin
#define NULL
Definition: def.h:248
#define SCIP_MAXSTRLEN
Definition: def.h:269
#define SCIP_Longint
Definition: def.h:141
#define SCIP_Bool
Definition: def.h:91
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIP_LONGINT_MAX
Definition: def.h:142
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_RETCODE SCIPcreateBendersDefault(SCIP *scip, SCIP **subproblems, int nsubproblems)
SCIP_RETCODE SCIPincludeBendersDefault(SCIP *scip)
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
int SCIPdecompGetNBlocks(SCIP_DECOMP *decomp)
Definition: dcmp.c:279
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
const char * SCIPstatusName(SCIP_STATUS status)
Definition: scip_general.c:576
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip_general.c:402
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip_general.c:370
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip_general.c:562
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:444
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1907
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1242
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:2115
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition: scip_prob.c:3666
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:2246
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3274
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3620
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:2201
SCIP_RETCODE SCIPcreateProbBasic(SCIP *scip, const char *name)
Definition: scip_prob.c:182
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3095
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
int SCIPgetNActiveBenders(SCIP *scip)
Definition: scip_benders.c:532
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 SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8648
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8409
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8558
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8598
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8588
SCIP_RETCODE SCIPgetConsVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int varssize, SCIP_Bool *success)
Definition: scip_cons.c:2577
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8578
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8628
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8389
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8638
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8668
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1173
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8568
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8658
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
#define SCIPallocClearBlockMemory(scip, ptr)
Definition: scip_mem.h:91
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
#define SCIPallocClearBufferArray(scip, ptr, num)
Definition: scip_mem.h:126
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
int SCIPgetNNlpis(SCIP *scip)
Definition: scip_nlpi.c:205
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:110
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_RELAX * SCIPfindRelax(SCIP *scip, const char *name)
Definition: scip_relax.c:237
SCIP_RELAXDATA * SCIPrelaxGetData(SCIP_RELAX *relax)
Definition: relax.c:460
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip_sol.c:2981
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:516
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:1252
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 SCIPpresolve(SCIP *scip)
Definition: scip_solve.c:2449
SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
Definition: scip_solve.c:3548
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip_solve.c:2635
SCIP_Real SCIPgetDualbound(SCIP *scip)
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:23514
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:23900
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:23453
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
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
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1887
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:23524
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:24120
SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
Definition: var.c:23463
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10827
public methods for Benders' decomposition
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebugMessage
Definition: pub_message.h:96
public methods for relaxation handlers
static SCIP_RETCODE addVariableToBendersProblem(SCIP *scip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_VAR *sourcevar)
#define RELAX_DESC
Definition: relax_benders.c:75
static SCIP_RETCODE createOriginalSolution(SCIP *scip, SCIP_RELAX *relax, SCIP_Bool *infeasible)
#define RELAX_PRIORITY
Definition: relax_benders.c:76
SCIP_RETCODE SCIPincludeRelaxBenders(SCIP *scip)
static SCIP_RETCODE freeDecomposition(SCIP *scip, SCIP_RELAX *relax)
static SCIP_RETCODE addInitialSolution(SCIP *scip, SCIP_RELAXDATA *relaxdata)
#define RELAX_NAME
Definition: relax_benders.c:74
#define RELAX_FREQ
Definition: relax_benders.c:77
#define relaxExitBenders
static SCIP_RETCODE freeBendersSubproblems(SCIP *scip, SCIP_RELAX *relax)
SCIP * SCIPgetMasterProblemRelaxBenders(SCIP *scip)
static SCIP_RETCODE solveBendersSubproblems(SCIP *scip, SCIP_RELAX *relax, SCIP_Bool *infeasible)
#define relaxExitsolBenders
static SCIP_DECL_RELAXEXEC(relaxExecBenders)
static SCIP_RETCODE getNlpSolution(SCIP *scip, SCIP_SOL **nlpsol)
#define DEFAULT_NODELIMIT
Definition: relax_benders.c:80
static SCIP_DECL_RELAXINITSOL(relaxInitsolBenders)
static SCIP_Bool masterSolutionExists(SCIP *scip, SCIP_RELAX *relax)
static SCIP_RETCODE setSolutionValues(SCIP *scip, SCIP_RELAX *relax, SCIP_SOL *sol)
static SCIP_DECL_RELAXFREE(relaxFreeBenders)
#define relaxInitBenders
#define DEFAULT_CONTORIG
Definition: relax_benders.c:79
#define relaxCopyBenders
static SCIP_RETCODE addConstraintToBendersProblem(SCIP *scip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_CONS *sourcecons)
static SCIP_RETCODE applyDecomposition(SCIP *scip, SCIP_RELAX *relax, SCIP_DECOMP *decomp)
benders relaxator
SCIP callable library.
type definitions for Benders' decomposition methods
@ SCIP_BENDERSENFOTYPE_CHECK
Definition: type_benders.h:54
type definitions for message output methods
@ SCIP_VERBLEVEL_NORMAL
Definition: type_message.h:60
@ SCIP_PARAMSETTING_OFF
Definition: type_paramset.h:63
type definitions for relaxators
struct SCIP_RelaxData SCIP_RELAXDATA
Definition: type_relax.h:52
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_CUTOFF
Definition: type_result.h:48
@ SCIP_SUCCESS
Definition: type_result.h:58
type definitions for return codes for SCIP methods
@ SCIP_OKAY
Definition: type_retcode.h:42
@ SCIP_ERROR
Definition: type_retcode.h:43
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_PROBLEM
Definition: type_set.h:45
type definitions for problem statistics
@ SCIP_STATUS_PRIMALLIMIT
Definition: type_stat.h:57
@ SCIP_STATUS_GAPLIMIT
Definition: type_stat.h:56
@ SCIP_STATUS_USERINTERRUPT
Definition: type_stat.h:47
@ SCIP_STATUS_TIMELIMIT
Definition: type_stat.h:54
@ SCIP_STATUS_INFEASIBLE
Definition: type_stat.h:44
@ SCIP_STATUS_DUALLIMIT
Definition: type_stat.h:58
enum SCIP_Status SCIP_STATUS
Definition: type_stat.h:64