SCIP Doxygen Documentation
Loading...
Searching...
No Matches
benderscut_int.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file benderscut_int.c
26 * @ingroup OTHER_CFILES
27 * @brief Generates a Laporte and Louveaux Benders' decomposition integer cut
28 * @author Stephen J. Maher
29 */
30
31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32
33#include "scip/benderscut_int.h"
34#include "scip/cons_linear.h"
35#include "scip/pub_benderscut.h"
36#include "scip/pub_benders.h"
37#include "scip/pub_lp.h"
38#include "scip/pub_message.h"
39#include "scip/pub_misc.h"
40#include "scip/pub_paramset.h"
41#include "scip/pub_var.h"
42#include "scip/scip_benders.h"
43#include "scip/scip_cons.h"
44#include "scip/scip_cut.h"
45#include "scip/scip_general.h"
46#include "scip/scip_lp.h"
47#include "scip/scip_mem.h"
48#include "scip/scip_message.h"
49#include "scip/scip_numerics.h"
50#include "scip/scip_param.h"
51#include "scip/scip_prob.h"
52#include "scip/scip_sol.h"
53#include "scip/type_message.h"
54#include <string.h>
55
56#define BENDERSCUT_NAME "integer"
57#define BENDERSCUT_DESC "Laporte and Louveaux Benders' decomposition integer cut"
58#define BENDERSCUT_PRIORITY 0
59#define BENDERSCUT_LPCUT FALSE
60
61#define SCIP_DEFAULT_ADDCUTS FALSE /** Should cuts be generated, instead of constraints */
62#define SCIP_DEFAULT_CUTCONSTANT -10000.0
63
64/*
65 * Data structures
66 */
67
68/** Benders' decomposition cuts data */
69struct SCIP_BenderscutData
70{
71 SCIP_BENDERS* benders; /**< the Benders' decomposition data structure */
72 SCIP_Real cutconstant; /**< the constant for computing the integer cuts */
73 SCIP_Real* subprobconstant; /**< the constant for each subproblem used for computing the integer cuts */
74 SCIP_Bool addcuts; /**< should cuts be generated instead of constraints */
75 SCIP_Bool* firstcut; /**< flag to indicate that the first cut needs to be generated. */
76 int nsubproblems; /**< the number of subproblems for the Benders' decomposition */
77 SCIP_Bool subprobsvalid; /**< is it valid to apply integer cuts for this problem */
78 SCIP_Bool created; /**< has the Benders cut data been created */
79};
80
81/** method to call, when the priority of a Benders' decomposition was changed */
82static
83SCIP_DECL_PARAMCHGD(paramChgdBenderscutintConstant)
84{ /*lint --e{715}*/
85 SCIP_BENDERSCUTDATA* benderscutdata;
86 int i;
87
88 benderscutdata = (SCIP_BENDERSCUTDATA*)SCIPparamGetData(param);
89 assert(benderscutdata != NULL);
90
91 for( i = 0; i < benderscutdata->nsubproblems; i++ )
92 benderscutdata->subprobconstant[i] = benderscutdata->cutconstant;
93
94 return SCIP_OKAY;
95}
96
97
98/** creates the Benders' decomposition cut data */
99static
101 SCIP* scip, /**< the SCIP data structure */
102 SCIP_BENDERSCUTDATA* benderscutdata /**< the Benders' cut data */
103 )
104{
105 int nmastervars;
106 int nmasterbinvars;
107 int i;
108
109 assert(scip != NULL);
110 assert(benderscutdata != NULL);
111
112 benderscutdata->nsubproblems = SCIPbendersGetNSubproblems(benderscutdata->benders);
113 benderscutdata->subprobsvalid = TRUE;
114
115 /* allocating the memory for the subproblem constants */
116 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &benderscutdata->subprobconstant, benderscutdata->nsubproblems) );
117 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &benderscutdata->firstcut, benderscutdata->nsubproblems) );
118
119 for( i = 0; i < benderscutdata->nsubproblems; i++ )
120 {
121 benderscutdata->subprobconstant[i] = benderscutdata->cutconstant;
122 benderscutdata->firstcut[i] = TRUE;
123
124 /* it is only possible to generate the no-good cut for subproblems that only include binary master variables */
125 SCIPbendersGetSubproblemMasterVarsData(benderscutdata->benders, i, NULL, &nmastervars, &nmasterbinvars, NULL);
126
127 if( nmastervars != nmasterbinvars )
128 {
129 benderscutdata->subprobsvalid = FALSE;
130 }
131 }
132
133 benderscutdata->created = TRUE;
134
135 return SCIP_OKAY;
136}
137
138/*
139 * Local methods
140 */
141
142/** updates the cut constant for the given subproblem based upon the global bounds of the associated auxiliary variable */
143static
145 SCIP* masterprob, /**< the SCIP instance of the master problem */
146 SCIP_BENDERS* benders, /**< the benders' decomposition structure */
147 SCIP_BENDERSCUTDATA* benderscutdata, /**< the Benders' decomposition cut data */
148 int probnumber /**< the index for the subproblem */
149 )
150{
151 SCIP_VAR* auxiliaryvar;
152
153 assert(masterprob != NULL);
154 assert(benders != NULL);
155 assert(benderscutdata != NULL);
156
157 auxiliaryvar = SCIPbendersGetAuxiliaryVar(benders, probnumber);
158
159 /* checking if the subproblem lower bound has been updated. If it is has changed, then firstcut is set to TRUE.
160 * Otherwise, the constant remains the same.
161 */
162 if( SCIPisGT(masterprob, SCIPbendersGetSubproblemLowerbound(benders, probnumber),
163 benderscutdata->subprobconstant[probnumber]) )
164 {
165 benderscutdata->subprobconstant[probnumber] = SCIPbendersGetSubproblemLowerbound(benders, probnumber);
166 benderscutdata->firstcut[probnumber] = TRUE;
167 }
168
169 /* updating the cut constant if the auxiliary variable global lower bound is greater than the current constant */
170 if( SCIPisGT(masterprob, SCIPvarGetLbGlobal(auxiliaryvar), benderscutdata->subprobconstant[probnumber]) )
171 benderscutdata->subprobconstant[probnumber] = SCIPvarGetLbGlobal(auxiliaryvar);
172}
173
174/** computes a standard Benders' optimality cut from the dual solutions of the LP */
175static
177 SCIP* masterprob, /**< the SCIP instance of the master problem */
178 SCIP_BENDERS* benders, /**< the benders' decomposition structure */
179 SCIP_SOL* sol, /**< primal CIP solution */
180 SCIP_CONS* cons, /**< the constraint for the generated cut, can be NULL */
181 SCIP_ROW* row, /**< the row for the generated cut, can be NULL */
182 SCIP_Real cutconstant, /**< the constant value in the integer optimality cut */
183 int probnumber, /**< the number of the pricing problem */
184 SCIP_Bool addcut, /**< indicates whether a cut is created instead of a constraint */
185 SCIP_Bool* success /**< was the cut generation successful? */
186 )
187{
188 SCIP_VAR** vars;
189 int nvars;
190 SCIP_Real subprobobj; /* the objective function value of the subproblem */
191 SCIP_Real lhs; /* the left hand side of the cut */
192 int i;
193 SCIPdebug( SCIP* subproblem; )
194
195#ifndef NDEBUG
196 SCIP_Real verifyobj = 0;
197#endif
198
199 assert(masterprob != NULL);
200 assert(benders != NULL);
201 assert(cons != NULL || addcut);
202 assert(row != NULL || !addcut);
203
204 (*success) = FALSE;
205
206 /* getting the best solution from the subproblem */
207
208 subprobobj = SCIPbendersGetSubproblemObjval(benders, probnumber);
209
210 SCIPdebug( subproblem = SCIPbendersSubproblem(benders, probnumber); )
211 SCIPdebug( SCIPdebugMsg(masterprob, "Subproblem %d - Objective Value: Stored - %g Orig Obj - %g Cut constant - %g\n",
212 probnumber, SCIPbendersGetSubproblemObjval(benders, probnumber), SCIPgetSolOrigObj(subproblem, SCIPgetBestSol(subproblem))*(int)SCIPgetObjsense(subproblem),
213 cutconstant); )
214
215 nvars = SCIPgetNVars(masterprob);
216 vars = SCIPgetVars(masterprob);
217
218 /* adding the subproblem objective function value to the lhs */
219 if( addcut )
220 lhs = SCIProwGetLhs(row);
221 else
222 lhs = SCIPgetLhsLinear(masterprob, cons);
223
224 /* looping over all master problem variables to update the coefficients in the computed cut. */
225 for( i = 0; i < nvars; i++ )
226 {
227 SCIP_VAR* subprobvar;
228 SCIP_Real coef;
229
230 SCIP_CALL( SCIPgetBendersSubproblemVar(masterprob, benders, vars[i], &subprobvar, probnumber) );
231
232 /* if there is a corresponding subproblem variable, then the variable will not be NULL. */
233 if( subprobvar != NULL )
234 {
235 /* if the variable is on its upper bound, then the subproblem objective value is added to the cut */
236 if( SCIPisFeasEQ(masterprob, SCIPgetSolVal(masterprob, sol, vars[i]), 1.0) )
237 {
238 coef = -(subprobobj - cutconstant);
239 lhs -= (subprobobj - cutconstant);
240 }
241 else
242 coef = (subprobobj - cutconstant);
243
244 /* adding the variable to the cut. The coefficient is the subproblem objective value */
245 if( addcut )
246 {
247 SCIP_CALL( SCIPaddVarToRow(masterprob, row, vars[i], coef) );
248 }
249 else
250 {
251 SCIP_CALL( SCIPaddCoefLinear(masterprob, cons, vars[i], coef) );
252 }
253 }
254 }
255
256 lhs += subprobobj;
257
258 /* if the bound becomes infinite, then the cut generation terminates. */
259 if( SCIPisInfinity(masterprob, lhs) || SCIPisInfinity(masterprob, -lhs) )
260 {
261 (*success) = FALSE;
262 SCIPdebugMsg(masterprob, "Infinite bound when generating integer optimality cut.\n");
263 return SCIP_OKAY;
264 }
265
266 /* Update the lhs of the cut */
267 if( addcut )
268 {
269 SCIP_CALL( SCIPchgRowLhs(masterprob, row, lhs) );
270 }
271 else
272 {
273 SCIP_CALL( SCIPchgLhsLinear(masterprob, cons, lhs) );
274 }
275
276#ifndef NDEBUG
277 if( addcut )
278 lhs = SCIProwGetLhs(row);
279 else
280 lhs = SCIPgetLhsLinear(masterprob, cons);
281 verifyobj += lhs;
282
283 if( addcut )
284 verifyobj -= SCIPgetRowSolActivity(masterprob, row, sol);
285 else
286 verifyobj -= SCIPgetActivityLinear(masterprob, cons, sol);
287#endif
288
289 assert(SCIPisFeasEQ(masterprob, verifyobj, subprobobj));
290
291 (*success) = TRUE;
292
293 return SCIP_OKAY;
294}
295
296
297/** adds the auxiliary variable to the generated cut. If this is the first optimality cut for the subproblem, then the
298 * auxiliary variable is first created and added to the master problem.
299 */
300static
302 SCIP* masterprob, /**< the SCIP instance of the master problem */
303 SCIP_BENDERS* benders, /**< the benders' decomposition structure */
304 SCIP_CONS* cons, /**< the constraint for the generated cut, can be NULL */
305 SCIP_ROW* row, /**< the row for the generated cut, can be NULL */
306 int probnumber, /**< the number of the pricing problem */
307 SCIP_Bool addcut /**< indicates whether a cut is created instead of a constraint */
308 )
309{
310 SCIP_VAR* auxiliaryvar;
311
312 assert(masterprob != NULL);
313 assert(benders != NULL);
314 assert(cons != NULL || addcut);
315 assert(row != NULL || !addcut);
316
317 auxiliaryvar = SCIPbendersGetAuxiliaryVar(benders, probnumber);
318
319 /* adding the auxiliary variable to the generated cut */
320 if( addcut )
321 {
322 SCIP_CALL( SCIPaddVarToRow(masterprob, row, auxiliaryvar, 1.0) );
323 }
324 else
325 {
326 SCIP_CALL( SCIPaddCoefLinear(masterprob, cons, auxiliaryvar, 1.0) );
327 }
328
329 return SCIP_OKAY;
330}
331
332
333/** generates and applies Benders' cuts */
334static
336 SCIP* masterprob, /**< the SCIP instance of the master problem */
337 SCIP_BENDERS* benders, /**< the benders' decomposition */
338 SCIP_BENDERSCUT* benderscut, /**< the benders' decomposition cut method */
339 SCIP_SOL* sol, /**< primal CIP solution */
340 int probnumber, /**< the number of the pricing problem */
341 SCIP_BENDERSENFOTYPE type, /**< the enforcement type calling this function */
342 SCIP_RESULT* result, /**< the result from solving the subproblems */
343 SCIP_Bool initcons /**< is this function called to generate the initial constraint */
344 )
345{
346 SCIP_BENDERSCUTDATA* benderscutdata;
347 SCIP_CONSHDLR* consbenders;
348 SCIP_CONS* cons;
349 SCIP_ROW* row;
350 char cutname[SCIP_MAXSTRLEN];
351 SCIP_Bool optimal;
352 SCIP_Bool addcut;
353 SCIP_Bool success;
354
355 assert(masterprob != NULL);
356 assert(benders != NULL);
357 assert(benderscut != NULL);
358 assert(result != NULL);
359
360 row = NULL;
361 cons = NULL;
362
363 success = FALSE;
364
365 /* retrieving the Benders' cut data */
366 benderscutdata = SCIPbenderscutGetData(benderscut);
367
368 /* if the cuts are generated prior to the solving stage, then rows can not be generated. So constraints must be added
369 * to the master problem.
370 */
371 if( SCIPgetStage(masterprob) < SCIP_STAGE_INITSOLVE )
372 addcut = FALSE;
373 else
374 addcut = benderscutdata->addcuts;
375
376 /* retrieving the Benders' decomposition constraint handler */
377 consbenders = SCIPfindConshdlr(masterprob, "benders");
378
379 /* checking the optimality of the original problem with a comparison between the auxiliary variable and the
380 * objective value of the subproblem
381 */
382 optimal = FALSE;
383 SCIP_CALL( SCIPcheckBendersSubproblemOptimality(masterprob, benders, sol, probnumber, &optimal) );
384
385 if( optimal )
386 {
387 (*result) = SCIP_FEASIBLE;
388 SCIPdebugMsg(masterprob, "No <%s> cut added. Current Master Problem Obj: %g\n", BENDERSCUT_NAME,
389 SCIPgetSolOrigObj(masterprob, NULL)*(int)SCIPgetObjsense(masterprob));
390 return SCIP_OKAY;
391 }
392
393 /* checking whether the subproblem constant is less than the auxiliary variable global lower bound */
394 updateSubproblemCutConstant(masterprob, benders, benderscutdata, probnumber);
395
396 /* if no integer cuts have been previously generated and the bound on the auxiliary variable is -infinity,
397 * then an initial lower bounding cut is added
398 */
399 if( benderscutdata->firstcut[probnumber]
400 && SCIPisInfinity(masterprob, -SCIPvarGetLbGlobal(SCIPbendersGetAuxiliaryVar(benders, probnumber))) )
401 {
402 benderscutdata->firstcut[probnumber] = FALSE;
403 SCIP_CALL( generateAndApplyBendersIntegerCuts(masterprob, benders, benderscut, sol, probnumber, type, result,
404 TRUE) );
405 }
406
407 /* setting the name of the generated cut */
408 (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "integeroptcut_%d_%" SCIP_LONGINT_FORMAT, probnumber,
409 SCIPbenderscutGetNFound(benderscut) );
410
411 /* creating an empty row or constraint for the Benders' cut */
412 if( addcut )
413 {
414 SCIP_CALL( SCIPcreateEmptyRowConshdlr(masterprob, &row, consbenders, cutname, 0.0, SCIPinfinity(masterprob), FALSE,
415 FALSE, TRUE) );
416 }
417 else
418 {
419 SCIP_CALL( SCIPcreateConsBasicLinear(masterprob, &cons, cutname, 0, NULL, NULL, 0.0, SCIPinfinity(masterprob)) );
420 SCIP_CALL( SCIPsetConsDynamic(masterprob, cons, TRUE) );
421 SCIP_CALL( SCIPsetConsRemovable(masterprob, cons, TRUE) );
422 }
423
424 if( initcons )
425 {
426 SCIP_Real lhs;
427
428 /* adding the subproblem objective function value to the lhs */
429 if( addcut )
430 lhs = SCIProwGetLhs(row);
431 else
432 lhs = SCIPgetLhsLinear(masterprob, cons);
433
434 lhs += benderscutdata->subprobconstant[probnumber];
435
436 /* if the bound becomes infinite, then the cut generation terminates. */
437 if( SCIPisInfinity(masterprob, lhs) || SCIPisInfinity(masterprob, -lhs) )
438 {
439 success = FALSE;
440 SCIPdebugMsg(masterprob, "Infinite bound when generating integer optimality cut.\n");
441 }
442
443 /* Update the lhs of the cut */
444 if( addcut )
445 {
446 SCIP_CALL( SCIPchgRowLhs(masterprob, row, lhs) );
447 }
448 else
449 {
450 SCIP_CALL( SCIPchgLhsLinear(masterprob, cons, lhs) );
451 }
452 }
453 else
454 {
455 /* computing the coefficients of the optimality cut */
456 SCIP_CALL( computeStandardIntegerOptCut(masterprob, benders, sol, cons, row,
457 benderscutdata->subprobconstant[probnumber], probnumber, addcut, &success) );
458 }
459
460 /* if success is FALSE, then there was an error in generating the integer optimality cut. No cut will be added to
461 * the master problem. Otherwise, the constraint is added to the master problem.
462 */
463 if( !success )
464 {
465 (*result) = SCIP_DIDNOTFIND;
466 SCIPdebugMsg(masterprob, "Error in generating Benders' integer optimality cut for problem %d.\n", probnumber);
467 }
468 else
469 {
470 /* adding the auxiliary variable to the optimality cut */
471 SCIP_CALL( addAuxiliaryVariableToCut(masterprob, benders, cons, row, probnumber, addcut) );
472
473 /* adding the constraint to the master problem */
474 if( addcut )
475 {
476 SCIP_Bool infeasible;
477
479 {
480 SCIP_CALL( SCIPaddRow(masterprob, row, FALSE, &infeasible) );
481 assert(!infeasible);
482 }
483 else
484 {
486 SCIP_CALL( SCIPaddPoolCut(masterprob, row) );
487 }
488
489#ifdef SCIP_DEBUG
490 SCIP_CALL( SCIPprintRow(masterprob, row, NULL) );
491 SCIPinfoMessage(masterprob, NULL, ";\n");
492#endif
493
494 (*result) = SCIP_SEPARATED;
495 }
496 else
497 {
498 SCIP_CALL( SCIPaddCons(masterprob, cons) );
499
500 SCIPdebugPrintCons(masterprob, cons, NULL);
501
502 (*result) = SCIP_CONSADDED;
503 }
504 }
505
506 if( addcut )
507 {
508 /* release the row */
509 SCIP_CALL( SCIPreleaseRow(masterprob, &row) );
510 }
511 else
512 {
513 /* release the constraint */
514 SCIP_CALL( SCIPreleaseCons(masterprob, &cons) );
515 }
516
517 return SCIP_OKAY;
518}
519
520/*
521 * Callback methods of Benders' decomposition cuts
522 */
523
524/** destructor of Benders' decomposition cuts to free user data (called when SCIP is exiting) */
525static
526SCIP_DECL_BENDERSCUTFREE(benderscutFreeInt)
527{ /*lint --e{715}*/
528 SCIP_BENDERSCUTDATA* benderscutdata;
529
530 assert( benderscut != NULL );
531 assert( strcmp(SCIPbenderscutGetName(benderscut), BENDERSCUT_NAME) == 0 );
532
533 /* free Benders' cut data */
534 benderscutdata = SCIPbenderscutGetData(benderscut);
535 assert( benderscutdata != NULL );
536
537 SCIPfreeBlockMemory(scip, &benderscutdata);
538
539 SCIPbenderscutSetData(benderscut, NULL);
540
541 return SCIP_OKAY;
542}
543
544
545/** deinitialization method of Benders' decomposition cuts (called before transformed problem is freed) */
546static
547SCIP_DECL_BENDERSCUTEXIT(benderscutExitInt)
548{ /*lint --e{715}*/
549 SCIP_BENDERSCUTDATA* benderscutdata;
550
551 assert( benderscut != NULL );
552 assert( strcmp(SCIPbenderscutGetName(benderscut), BENDERSCUT_NAME) == 0 );
553
554 /* free Benders' cut data */
555 benderscutdata = SCIPbenderscutGetData(benderscut);
556 assert( benderscutdata != NULL );
557
558 if( benderscutdata->firstcut != NULL )
559 SCIPfreeBlockMemoryArray(scip, &benderscutdata->firstcut, benderscutdata->nsubproblems);
560
561 if( benderscutdata->subprobconstant != NULL)
562 SCIPfreeBlockMemoryArray(scip, &benderscutdata->subprobconstant, benderscutdata->nsubproblems);
563
564 return SCIP_OKAY;
565}
566
567/** execution method of Benders' decomposition cuts */
568static
569SCIP_DECL_BENDERSCUTEXEC(benderscutExecInt)
570{ /*lint --e{715}*/
571 SCIP* subproblem;
572 SCIP_BENDERSCUTDATA* benderscutdata;
573
574 assert(scip != NULL);
575 assert(benders != NULL);
576 assert(benderscut != NULL);
577 assert(result != NULL);
578
579 subproblem = SCIPbendersSubproblem(benders, probnumber);
580
581 if( subproblem == NULL )
582 {
583 SCIPdebugMsg(scip, "The subproblem %d is set to NULL. The <%s> Benders' decomposition cut can not be executed.\n",
584 probnumber, BENDERSCUT_NAME);
585
586 (*result) = SCIP_DIDNOTRUN;
587 return SCIP_OKAY;
588 }
589
590 /* retrieving the Benders' cut data */
591 benderscutdata = SCIPbenderscutGetData(benderscut);
592 assert(benderscutdata != NULL);
593
594 /* if the Benders' cut data has not been created, then it is created now */
595 if( !benderscutdata->created )
596 {
597 SCIP_CALL( createBenderscutData(scip, benderscutdata) );
598 }
599
600 /* it is only possible to generate the Laporte and Louveaux cuts when the linking variables are all binary */
601 if( !benderscutdata->subprobsvalid )
602 {
603 SCIPwarningMessage(scip, "The integer optimality cuts have been disabled because some linking variables are not binary.\n"
604 "Since there is at least one non-convex subproblem, i.e. not LP or convex NLP, the problem will be solved heuristically.\n");
605
606 SCIPbenderscutSetEnabled(benderscut, FALSE);
607
608 return SCIP_OKAY;
609 }
610
611 /* the integer subproblem could terminate early if the auxiliary variable value is much greater than the optimal
612 * solution. As such, it is only necessary to generate a cut if the subproblem is OPTIMAL */
613 if( SCIPgetStatus(subproblem) == SCIP_STATUS_OPTIMAL )
614 {
615 /* generating a cut for a given subproblem */
616 SCIP_CALL( generateAndApplyBendersIntegerCuts(scip, benders, benderscut, sol, probnumber, type, result, FALSE) );
617 }
618
619 return SCIP_OKAY;
620}
621
622
623/*
624 * Benders' decomposition cuts specific interface methods
625 */
626
627/** creates the int Benders' decomposition cuts and includes it in SCIP */
629 SCIP* scip, /**< SCIP data structure */
630 SCIP_BENDERS* benders /**< Benders' decomposition */
631 )
632{
633 SCIP_BENDERSCUTDATA* benderscutdata;
634 SCIP_BENDERSCUT* benderscut;
636
637 assert(benders != NULL);
638
639 /* create int Benders' decomposition cuts data */
640 SCIP_CALL( SCIPallocBlockMemory(scip, &benderscutdata) );
641 BMSclearMemory(benderscutdata);
642 benderscutdata->benders = benders;
643
644 benderscut = NULL;
645
646 /* include Benders' decomposition cuts */
648 BENDERSCUT_PRIORITY, BENDERSCUT_LPCUT, benderscutExecInt, benderscutdata) );
649
650 assert(benderscut != NULL);
651
652 /* set non fundamental callbacks via setter functions */
653 SCIP_CALL( SCIPsetBenderscutFree(scip, benderscut, benderscutFreeInt) );
654 SCIP_CALL( SCIPsetBenderscutExit(scip, benderscut, benderscutExitInt) );
655
656 /* add int Benders' decomposition cuts parameters */
657 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/benderscut/%s/cutsconstant",
660 "the constant term of the integer Benders' cuts.",
661 &benderscutdata->cutconstant, FALSE, SCIP_DEFAULT_CUTCONSTANT, -SCIPinfinity(scip), SCIPinfinity(scip),
662 paramChgdBenderscutintConstant, (SCIP_PARAMDATA*)benderscutdata) );
663
664 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/benderscut/%s/addcuts",
667 "should cuts be generated and added to the cutpool instead of global constraints directly added to the problem.",
668 &benderscutdata->addcuts, FALSE, SCIP_DEFAULT_ADDCUTS, NULL, NULL) );
669
670 return SCIP_OKAY;
671}
#define BENDERSCUT_LPCUT
#define BENDERSCUT_PRIORITY
#define BENDERSCUT_DESC
#define BENDERSCUT_NAME
#define SCIP_DEFAULT_ADDCUTS
static SCIP_RETCODE computeStandardIntegerOptCut(SCIP *masterprob, SCIP_BENDERS *benders, SCIP_SOL *sol, SCIP_CONS *cons, SCIP_ROW *row, SCIP_Real cutconstant, int probnumber, SCIP_Bool addcut, SCIP_Bool *success)
#define SCIP_DEFAULT_CUTCONSTANT
static SCIP_RETCODE createBenderscutData(SCIP *scip, SCIP_BENDERSCUTDATA *benderscutdata)
static SCIP_RETCODE generateAndApplyBendersIntegerCuts(SCIP *masterprob, SCIP_BENDERS *benders, SCIP_BENDERSCUT *benderscut, SCIP_SOL *sol, int probnumber, SCIP_BENDERSENFOTYPE type, SCIP_RESULT *result, SCIP_Bool initcons)
static void updateSubproblemCutConstant(SCIP *masterprob, SCIP_BENDERS *benders, SCIP_BENDERSCUTDATA *benderscutdata, int probnumber)
static SCIP_RETCODE addAuxiliaryVariableToCut(SCIP *masterprob, SCIP_BENDERS *benders, SCIP_CONS *cons, SCIP_ROW *row, int probnumber, SCIP_Bool addcut)
Generates a Laporte and Louveaux Benders' decomposition integer cut.
Constraint handler for linear constraints in their most general form, .
#define NULL
Definition def.h:255
#define SCIP_MAXSTRLEN
Definition def.h:276
#define SCIP_Bool
Definition def.h:98
#define SCIP_Real
Definition def.h:163
#define TRUE
Definition def.h:100
#define FALSE
Definition def.h:101
#define SCIP_LONGINT_FORMAT
Definition def.h:155
#define SCIP_CALL(x)
Definition def.h:362
SCIP_RETCODE SCIPincludeBenderscutInt(SCIP *scip, SCIP_BENDERS *benders)
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
SCIP_Real SCIPgetActivityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
SCIP_STATUS SCIPgetStatus(SCIP *scip)
SCIP_STAGE SCIPgetStage(SCIP *scip)
int SCIPgetNVars(SCIP *scip)
Definition scip_prob.c:2246
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3274
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition scip_prob.c:2201
SCIP_OBJSENSE SCIPgetObjsense(SCIP *scip)
Definition scip_prob.c:1400
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
#define SCIPdebugMsg
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:139
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_VAR * SCIPbendersGetAuxiliaryVar(SCIP_BENDERS *benders, int probnumber)
Definition benders.c:6212
SCIP_RETCODE SCIPgetBendersSubproblemVar(SCIP *scip, SCIP_BENDERS *benders, SCIP_VAR *var, SCIP_VAR **mappedvar, int probnumber)
const char * SCIPbendersGetName(SCIP_BENDERS *benders)
Definition benders.c:5966
int SCIPbendersGetNSubproblems(SCIP_BENDERS *benders)
Definition benders.c:6010
SCIP * SCIPbendersSubproblem(SCIP_BENDERS *benders, int probnumber)
Definition benders.c:6020
void SCIPbendersGetSubproblemMasterVarsData(SCIP_BENDERS *benders, int probnumber, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars)
Definition benders.c:6258
SCIP_RETCODE SCIPcheckBendersSubproblemOptimality(SCIP *scip, SCIP_BENDERS *benders, SCIP_SOL *sol, int probnumber, SCIP_Bool *optimal)
SCIP_Real SCIPbendersGetSubproblemObjval(SCIP_BENDERS *benders, int probnumber)
Definition benders.c:6301
SCIP_Real SCIPbendersGetSubproblemLowerbound(SCIP_BENDERS *benders, int probnumber)
Definition benders.c:6892
SCIP_RETCODE SCIPsetBenderscutExit(SCIP *scip, SCIP_BENDERSCUT *benderscut,)
SCIP_RETCODE SCIPincludeBenderscutBasic(SCIP *scip, SCIP_BENDERS *benders, SCIP_BENDERSCUT **benderscutptr, const char *name, const char *desc, int priority, SCIP_Bool islpcut, SCIP_DECL_BENDERSCUTEXEC((*benderscutexec)), SCIP_BENDERSCUTDATA *benderscutdata)
SCIP_RETCODE SCIPsetBenderscutFree(SCIP *scip, SCIP_BENDERSCUT *benderscut,)
void SCIPbenderscutSetData(SCIP_BENDERSCUT *benderscut, SCIP_BENDERSCUTDATA *benderscutdata)
Definition benderscut.c:413
const char * SCIPbenderscutGetName(SCIP_BENDERSCUT *benderscut)
Definition benderscut.c:492
SCIP_BENDERSCUTDATA * SCIPbenderscutGetData(SCIP_BENDERSCUT *benderscut)
Definition benderscut.c:403
SCIP_Longint SCIPbenderscutGetNFound(SCIP_BENDERSCUT *benderscut)
Definition benderscut.c:543
void SCIPbenderscutSetEnabled(SCIP_BENDERSCUT *benderscut, SCIP_Bool enabled)
Definition benderscut.c:593
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition scip_cons.c:940
SCIP_RETCODE SCIPsetConsDynamic(SCIP *scip, SCIP_CONS *cons, SCIP_Bool dynamic)
Definition scip_cons.c:1449
SCIP_RETCODE SCIPsetConsRemovable(SCIP *scip, SCIP_CONS *cons, SCIP_Bool removable)
Definition scip_cons.c:1474
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition scip_cons.c:1173
SCIP_RETCODE SCIPaddPoolCut(SCIP *scip, SCIP_ROW *row)
Definition scip_cut.c:336
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition scip_cut.c:225
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:110
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:93
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition lp.c:17686
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition scip_lp.c:1529
SCIP_RETCODE SCIPcreateEmptyRowConshdlr(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition scip_lp.c:1367
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition scip_lp.c:1646
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition scip_lp.c:2176
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition scip_lp.c:1508
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition scip_lp.c:2108
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition scip_sol.c:2988
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition scip_sol.c:1892
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1765
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24120
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
return SCIP_OKAY
static SCIP_SOL * sol
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
static SCIP_VAR ** vars
static const char * paramname[]
Definition lpi_msk.c:5172
#define BMSclearMemory(ptr)
Definition memory.h:129
SCIP_PARAMDATA * SCIPparamGetData(SCIP_PARAM *param)
Definition paramset.c:678
public methods for Benders' decomposition
public methods for Benders' decomposition cuts
public methods for LP management
public methods for message output
#define SCIPdebug(x)
Definition pub_message.h:93
#define SCIPdebugPrintCons(x, y, z)
public data structures and miscellaneous methods
public methods for handling parameter settings
public methods for problem variables
public methods for Benders decomposition
public methods for constraint handler plugins and constraints
public methods for cuts and aggregation rows
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for solutions
struct SCIP_Benders SCIP_BENDERS
@ SCIP_BENDERSENFOTYPE_RELAX
@ SCIP_BENDERSENFOTYPE_LP
@ SCIP_BENDERSENFOTYPE_CHECK
@ SCIP_BENDERSENFOTYPE_PSEUDO
enum SCIP_BendersEnfoType SCIP_BENDERSENFOTYPE
struct SCIP_Benderscut SCIP_BENDERSCUT
#define SCIP_DECL_BENDERSCUTEXEC(x)
struct SCIP_BenderscutData SCIP_BENDERSCUTDATA
#define SCIP_DECL_BENDERSCUTFREE(x)
#define SCIP_DECL_BENDERSCUTEXIT(x)
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
type definitions for message output methods
struct SCIP_ParamData SCIP_PARAMDATA
#define SCIP_DECL_PARAMCHGD(x)
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_FEASIBLE
Definition type_result.h:45
@ SCIP_DIDNOTFIND
Definition type_result.h:44
@ SCIP_CONSADDED
Definition type_result.h:52
@ SCIP_SEPARATED
Definition type_result.h:49
enum SCIP_Result SCIP_RESULT
Definition type_result.h:61
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
@ SCIP_STAGE_INITSOLVE
Definition type_set.h:52
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
@ SCIP_STATUS_OPTIMAL
Definition type_stat.h:43
struct SCIP_Var SCIP_VAR
Definition type_var.h:166