Scippy

SCIP

Solving Constraint Integer Programs

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-2024 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 <string.h>
54
55#define BENDERSCUT_NAME "integer"
56#define BENDERSCUT_DESC "Laporte and Louveaux Benders' decomposition integer cut"
57#define BENDERSCUT_PRIORITY 0
58#define BENDERSCUT_LPCUT FALSE
59
60#define SCIP_DEFAULT_ADDCUTS FALSE /** Should cuts be generated, instead of constraints */
61#define SCIP_DEFAULT_CUTCONSTANT -10000.0
62
63/*
64 * Data structures
65 */
66
67/** Benders' decomposition cuts data */
68struct SCIP_BenderscutData
69{
70 SCIP_BENDERS* benders; /**< the Benders' decomposition data structure */
71 SCIP_Real cutconstant; /**< the constant for computing the integer cuts */
72 SCIP_Real* subprobconstant; /**< the constant for each subproblem used for computing the integer cuts */
73 SCIP_Bool addcuts; /**< should cuts be generated instead of constraints */
74 SCIP_Bool* firstcut; /**< flag to indicate that the first cut needs to be generated. */
75 int nsubproblems; /**< the number of subproblems for the Benders' decomposition */
76};
77
78/** method to call, when the priority of a Benders' decomposition was changed */
79static
80SCIP_DECL_PARAMCHGD(paramChgdBenderscutintConstant)
81{ /*lint --e{715}*/
82 SCIP_BENDERSCUTDATA* benderscutdata;
83 int i;
84
85 benderscutdata = (SCIP_BENDERSCUTDATA*)SCIPparamGetData(param);
86 assert(benderscutdata != NULL);
87
88 for( i = 0; i < benderscutdata->nsubproblems; i++ )
89 benderscutdata->subprobconstant[i] = benderscutdata->cutconstant;
90
91 return SCIP_OKAY;
92}
93
94
95/** creates the Benders' decomposition cut data */
96static
98 SCIP* scip, /**< the SCIP data structure */
99 SCIP_BENDERSCUTDATA* benderscutdata /**< the Benders' cut data */
100 )
101{
102 int i;
103
104 assert(scip != NULL);
105 assert(benderscutdata != NULL);
106
107 /* allocating the memory for the subproblem constants */
108 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &benderscutdata->subprobconstant, benderscutdata->nsubproblems) );
109 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &benderscutdata->firstcut, benderscutdata->nsubproblems) );
110
111 for( i = 0; i < benderscutdata->nsubproblems; i++ )
112 {
113 benderscutdata->subprobconstant[i] = benderscutdata->cutconstant;
114 benderscutdata->firstcut[i] = TRUE;
115 }
116
117 return SCIP_OKAY;
118}
119
120/*
121 * Local methods
122 */
123
124/** updates the cut constant for the given subproblem based upon the global bounds of the associated auxiliary variable */
125static
127 SCIP* masterprob, /**< the SCIP instance of the master problem */
128 SCIP_BENDERS* benders, /**< the benders' decomposition structure */
129 SCIP_BENDERSCUTDATA* benderscutdata, /**< the Benders' decomposition cut data */
130 int probnumber /**< the index for the subproblem */
131 )
132{
133 SCIP_VAR* auxiliaryvar;
134
135 assert(masterprob != NULL);
136 assert(benders != NULL);
137 assert(benderscutdata != NULL);
138
139 auxiliaryvar = SCIPbendersGetAuxiliaryVar(benders, probnumber);
140
141 /* checking if the subproblem lower bound has been updated. If it is has changed, then firstcut is set to TRUE.
142 * Otherwise, the constant remains the same.
143 */
144 if( SCIPisGT(masterprob, SCIPbendersGetSubproblemLowerbound(benders, probnumber),
145 benderscutdata->subprobconstant[probnumber]) )
146 {
147 benderscutdata->subprobconstant[probnumber] = SCIPbendersGetSubproblemLowerbound(benders, probnumber);
148 benderscutdata->firstcut[probnumber] = TRUE;
149 }
150
151 /* updating the cut constant if the auxiliary variable global lower bound is greater than the current constant */
152 if( SCIPisGT(masterprob, SCIPvarGetLbGlobal(auxiliaryvar), benderscutdata->subprobconstant[probnumber]) )
153 benderscutdata->subprobconstant[probnumber] = SCIPvarGetLbGlobal(auxiliaryvar);
154}
155
156/** computes a standard Benders' optimality cut from the dual solutions of the LP */
157static
159 SCIP* masterprob, /**< the SCIP instance of the master problem */
160 SCIP_BENDERS* benders, /**< the benders' decomposition structure */
161 SCIP_SOL* sol, /**< primal CIP solution */
162 SCIP_CONS* cons, /**< the constraint for the generated cut, can be NULL */
163 SCIP_ROW* row, /**< the row for the generated cut, can be NULL */
164 SCIP_Real cutconstant, /**< the constant value in the integer optimality cut */
165 int probnumber, /**< the number of the pricing problem */
166 SCIP_Bool addcut, /**< indicates whether a cut is created instead of a constraint */
167 SCIP_Bool* success /**< was the cut generation successful? */
168 )
169{
170 SCIP_VAR** vars;
171 int nvars;
172 SCIP_Real subprobobj; /* the objective function value of the subproblem */
173 SCIP_Real lhs; /* the left hand side of the cut */
174 int i;
175 SCIPdebug( SCIP* subproblem; )
176
177#ifndef NDEBUG
178 SCIP_Real verifyobj = 0;
179#endif
180
181 assert(masterprob != NULL);
182 assert(benders != NULL);
183 assert(cons != NULL || addcut);
184 assert(row != NULL || !addcut);
185
186 (*success) = FALSE;
187
188 /* getting the best solution from the subproblem */
189
190 subprobobj = SCIPbendersGetSubproblemObjval(benders, probnumber);
191
192 SCIPdebug( subproblem = SCIPbendersSubproblem(benders, probnumber); )
193 SCIPdebug( SCIPdebugMsg(masterprob, "Subproblem %d - Objective Value: Stored - %g Orig Obj - %g Cut constant - %g\n",
194 probnumber, SCIPbendersGetSubproblemObjval(benders, probnumber), SCIPgetSolOrigObj(subproblem, SCIPgetBestSol(subproblem))*(int)SCIPgetObjsense(subproblem),
195 cutconstant); )
196
197 nvars = SCIPgetNVars(masterprob);
198 vars = SCIPgetVars(masterprob);
199
200 /* adding the subproblem objective function value to the lhs */
201 if( addcut )
202 lhs = SCIProwGetLhs(row);
203 else
204 lhs = SCIPgetLhsLinear(masterprob, cons);
205
206 /* looping over all master problem variables to update the coefficients in the computed cut. */
207 for( i = 0; i < nvars; i++ )
208 {
209 SCIP_VAR* subprobvar;
210 SCIP_Real coef;
211
212 SCIP_CALL( SCIPgetBendersSubproblemVar(masterprob, benders, vars[i], &subprobvar, probnumber) );
213
214 /* if there is a corresponding subproblem variable, then the variable will not be NULL. */
215 if( subprobvar != NULL )
216 {
217 /* if the variable is on its upper bound, then the subproblem objective value is added to the cut */
218 if( SCIPisFeasEQ(masterprob, SCIPgetSolVal(masterprob, sol, vars[i]), 1.0) )
219 {
220 coef = -(subprobobj - cutconstant);
221 lhs -= (subprobobj - cutconstant);
222 }
223 else
224 coef = (subprobobj - cutconstant);
225
226 /* adding the variable to the cut. The coefficient is the subproblem objective value */
227 if( addcut )
228 {
229 SCIP_CALL( SCIPaddVarToRow(masterprob, row, vars[i], coef) );
230 }
231 else
232 {
233 SCIP_CALL( SCIPaddCoefLinear(masterprob, cons, vars[i], coef) );
234 }
235 }
236 }
237
238 lhs += subprobobj;
239
240 /* if the bound becomes infinite, then the cut generation terminates. */
241 if( SCIPisInfinity(masterprob, lhs) || SCIPisInfinity(masterprob, -lhs) )
242 {
243 (*success) = FALSE;
244 SCIPdebugMsg(masterprob, "Infinite bound when generating integer optimality cut.\n");
245 return SCIP_OKAY;
246 }
247
248 /* Update the lhs of the cut */
249 if( addcut )
250 {
251 SCIP_CALL( SCIPchgRowLhs(masterprob, row, lhs) );
252 }
253 else
254 {
255 SCIP_CALL( SCIPchgLhsLinear(masterprob, cons, lhs) );
256 }
257
258#ifndef NDEBUG
259 if( addcut )
260 lhs = SCIProwGetLhs(row);
261 else
262 lhs = SCIPgetLhsLinear(masterprob, cons);
263 verifyobj += lhs;
264
265 if( addcut )
266 verifyobj -= SCIPgetRowSolActivity(masterprob, row, sol);
267 else
268 verifyobj -= SCIPgetActivityLinear(masterprob, cons, sol);
269#endif
270
271 assert(SCIPisFeasEQ(masterprob, verifyobj, subprobobj));
272
273 (*success) = TRUE;
274
275 return SCIP_OKAY;
276}
277
278
279/** adds the auxiliary variable to the generated cut. If this is the first optimality cut for the subproblem, then the
280 * auxiliary variable is first created and added to the master problem.
281 */
282static
284 SCIP* masterprob, /**< the SCIP instance of the master problem */
285 SCIP_BENDERS* benders, /**< the benders' decomposition structure */
286 SCIP_CONS* cons, /**< the constraint for the generated cut, can be NULL */
287 SCIP_ROW* row, /**< the row for the generated cut, can be NULL */
288 int probnumber, /**< the number of the pricing problem */
289 SCIP_Bool addcut /**< indicates whether a cut is created instead of a constraint */
290 )
291{
292 SCIP_VAR* auxiliaryvar;
293
294 assert(masterprob != NULL);
295 assert(benders != NULL);
296 assert(cons != NULL || addcut);
297 assert(row != NULL || !addcut);
298
299 auxiliaryvar = SCIPbendersGetAuxiliaryVar(benders, probnumber);
300
301 /* adding the auxiliary variable to the generated cut */
302 if( addcut )
303 {
304 SCIP_CALL( SCIPaddVarToRow(masterprob, row, auxiliaryvar, 1.0) );
305 }
306 else
307 {
308 SCIP_CALL( SCIPaddCoefLinear(masterprob, cons, auxiliaryvar, 1.0) );
309 }
310
311 return SCIP_OKAY;
312}
313
314
315/** generates and applies Benders' cuts */
316static
318 SCIP* masterprob, /**< the SCIP instance of the master problem */
319 SCIP_BENDERS* benders, /**< the benders' decomposition */
320 SCIP_BENDERSCUT* benderscut, /**< the benders' decomposition cut method */
321 SCIP_SOL* sol, /**< primal CIP solution */
322 int probnumber, /**< the number of the pricing problem */
323 SCIP_BENDERSENFOTYPE type, /**< the enforcement type calling this function */
324 SCIP_RESULT* result, /**< the result from solving the subproblems */
325 SCIP_Bool initcons /**< is this function called to generate the initial constraint */
326 )
327{
328 SCIP_BENDERSCUTDATA* benderscutdata;
329 SCIP_CONSHDLR* consbenders;
330 SCIP_CONS* cons;
331 SCIP_ROW* row;
332 char cutname[SCIP_MAXSTRLEN];
333 SCIP_Bool optimal;
334 SCIP_Bool addcut;
335 SCIP_Bool success;
336
337 assert(masterprob != NULL);
338 assert(benders != NULL);
339 assert(benderscut != NULL);
340 assert(result != NULL);
341
342 row = NULL;
343 cons = NULL;
344
345 success = FALSE;
346
347 /* retrieving the Benders' cut data */
348 benderscutdata = SCIPbenderscutGetData(benderscut);
349
350 /* if the cuts are generated prior to the solving stage, then rows can not be generated. So constraints must be added
351 * to the master problem.
352 */
353 if( SCIPgetStage(masterprob) < SCIP_STAGE_INITSOLVE )
354 addcut = FALSE;
355 else
356 addcut = benderscutdata->addcuts;
357
358 /* retrieving the Benders' decomposition constraint handler */
359 consbenders = SCIPfindConshdlr(masterprob, "benders");
360
361 /* checking the optimality of the original problem with a comparison between the auxiliary variable and the
362 * objective value of the subproblem
363 */
364 optimal = FALSE;
365 SCIP_CALL( SCIPcheckBendersSubproblemOptimality(masterprob, benders, sol, probnumber, &optimal) );
366
367 if( optimal )
368 {
369 (*result) = SCIP_FEASIBLE;
370 SCIPdebugMsg(masterprob, "No <%s> cut added. Current Master Problem Obj: %g\n", BENDERSCUT_NAME,
371 SCIPgetSolOrigObj(masterprob, NULL)*(int)SCIPgetObjsense(masterprob));
372 return SCIP_OKAY;
373 }
374
375 /* checking whether the subproblem constant is less than the auxiliary variable global lower bound */
376 updateSubproblemCutConstant(masterprob, benders, benderscutdata, probnumber);
377
378 /* if no integer cuts have been previously generated and the bound on the auxiliary variable is -infinity,
379 * then an initial lower bounding cut is added
380 */
381 if( benderscutdata->firstcut[probnumber]
382 && SCIPisInfinity(masterprob, -SCIPvarGetLbGlobal(SCIPbendersGetAuxiliaryVar(benders, probnumber))) )
383 {
384 benderscutdata->firstcut[probnumber] = FALSE;
385 SCIP_CALL( generateAndApplyBendersIntegerCuts(masterprob, benders, benderscut, sol, probnumber, type, result,
386 TRUE) );
387 }
388
389 /* setting the name of the generated cut */
390 (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "integeroptcut_%d_%" SCIP_LONGINT_FORMAT, probnumber,
391 SCIPbenderscutGetNFound(benderscut) );
392
393 /* creating an empty row or constraint for the Benders' cut */
394 if( addcut )
395 {
396 SCIP_CALL( SCIPcreateEmptyRowConshdlr(masterprob, &row, consbenders, cutname, 0.0, SCIPinfinity(masterprob), FALSE,
397 FALSE, TRUE) );
398 }
399 else
400 {
401 SCIP_CALL( SCIPcreateConsBasicLinear(masterprob, &cons, cutname, 0, NULL, NULL, 0.0, SCIPinfinity(masterprob)) );
402 SCIP_CALL( SCIPsetConsDynamic(masterprob, cons, TRUE) );
403 SCIP_CALL( SCIPsetConsRemovable(masterprob, cons, TRUE) );
404 }
405
406 if( initcons )
407 {
408 SCIP_Real lhs;
409
410 /* adding the subproblem objective function value to the lhs */
411 if( addcut )
412 lhs = SCIProwGetLhs(row);
413 else
414 lhs = SCIPgetLhsLinear(masterprob, cons);
415
416 lhs += benderscutdata->subprobconstant[probnumber];
417
418 /* if the bound becomes infinite, then the cut generation terminates. */
419 if( SCIPisInfinity(masterprob, lhs) || SCIPisInfinity(masterprob, -lhs) )
420 {
421 success = FALSE;
422 SCIPdebugMsg(masterprob, "Infinite bound when generating integer optimality cut.\n");
423 }
424
425 /* Update the lhs of the cut */
426 if( addcut )
427 {
428 SCIP_CALL( SCIPchgRowLhs(masterprob, row, lhs) );
429 }
430 else
431 {
432 SCIP_CALL( SCIPchgLhsLinear(masterprob, cons, lhs) );
433 }
434 }
435 else
436 {
437 /* computing the coefficients of the optimality cut */
438 SCIP_CALL( computeStandardIntegerOptCut(masterprob, benders, sol, cons, row,
439 benderscutdata->subprobconstant[probnumber], probnumber, addcut, &success) );
440 }
441
442 /* if success is FALSE, then there was an error in generating the integer optimality cut. No cut will be added to
443 * the master problem. Otherwise, the constraint is added to the master problem.
444 */
445 if( !success )
446 {
447 (*result) = SCIP_DIDNOTFIND;
448 SCIPdebugMsg(masterprob, "Error in generating Benders' integer optimality cut for problem %d.\n", probnumber);
449 }
450 else
451 {
452 /* adding the auxiliary variable to the optimality cut */
453 SCIP_CALL( addAuxiliaryVariableToCut(masterprob, benders, cons, row, probnumber, addcut) );
454
455 /* adding the constraint to the master problem */
456 if( addcut )
457 {
458 SCIP_Bool infeasible;
459
461 {
462 SCIP_CALL( SCIPaddRow(masterprob, row, FALSE, &infeasible) );
463 assert(!infeasible);
464 }
465 else
466 {
468 SCIP_CALL( SCIPaddPoolCut(masterprob, row) );
469 }
470
471#ifdef SCIP_DEBUG
472 SCIP_CALL( SCIPprintRow(masterprob, row, NULL) );
473 SCIPinfoMessage(masterprob, NULL, ";\n");
474#endif
475
476 (*result) = SCIP_SEPARATED;
477 }
478 else
479 {
480 SCIP_CALL( SCIPaddCons(masterprob, cons) );
481
482 SCIPdebugPrintCons(masterprob, cons, NULL);
483
484 (*result) = SCIP_CONSADDED;
485 }
486 }
487
488 if( addcut )
489 {
490 /* release the row */
491 SCIP_CALL( SCIPreleaseRow(masterprob, &row) );
492 }
493 else
494 {
495 /* release the constraint */
496 SCIP_CALL( SCIPreleaseCons(masterprob, &cons) );
497 }
498
499 return SCIP_OKAY;
500}
501
502/*
503 * Callback methods of Benders' decomposition cuts
504 */
505
506/** destructor of Benders' decomposition cuts to free user data (called when SCIP is exiting) */
507static
508SCIP_DECL_BENDERSCUTFREE(benderscutFreeInt)
509{ /*lint --e{715}*/
510 SCIP_BENDERSCUTDATA* benderscutdata;
511
512 assert( benderscut != NULL );
513 assert( strcmp(SCIPbenderscutGetName(benderscut), BENDERSCUT_NAME) == 0 );
514
515 /* free Benders' cut data */
516 benderscutdata = SCIPbenderscutGetData(benderscut);
517 assert( benderscutdata != NULL );
518
519 SCIPfreeBlockMemory(scip, &benderscutdata);
520
521 SCIPbenderscutSetData(benderscut, NULL);
522
523 return SCIP_OKAY;
524}
525
526
527/** initialization method of Benders' decomposition cuts (called after problem was transformed) */
528static
529SCIP_DECL_BENDERSCUTINIT(benderscutInitInt)
530{ /*lint --e{715}*/
531 SCIP_BENDERSCUTDATA* benderscutdata;
532
533 assert( benderscut != NULL );
534 assert( strcmp(SCIPbenderscutGetName(benderscut), BENDERSCUT_NAME) == 0 );
535
536 /* free Benders' cut data */
537 benderscutdata = SCIPbenderscutGetData(benderscut);
538 assert( benderscutdata != NULL );
539
540 benderscutdata->nsubproblems = SCIPbendersGetNSubproblems(benderscutdata->benders);
541 SCIP_CALL( createBenderscutData(scip, benderscutdata) );
542
543 return SCIP_OKAY;
544}
545
546/** deinitialization method of Benders' decomposition cuts (called before transformed problem is freed) */
547static
548SCIP_DECL_BENDERSCUTEXIT(benderscutExitInt)
549{ /*lint --e{715}*/
550 SCIP_BENDERSCUTDATA* benderscutdata;
551
552 assert( benderscut != NULL );
553 assert( strcmp(SCIPbenderscutGetName(benderscut), BENDERSCUT_NAME) == 0 );
554
555 /* free Benders' cut data */
556 benderscutdata = SCIPbenderscutGetData(benderscut);
557 assert( benderscutdata != NULL );
558
559 SCIPfreeBlockMemoryArray(scip, &benderscutdata->firstcut, benderscutdata->nsubproblems);
560 SCIPfreeBlockMemoryArray(scip, &benderscutdata->subprobconstant, benderscutdata->nsubproblems);
561
562 return SCIP_OKAY;
563}
564
565/** execution method of Benders' decomposition cuts */
566static
567SCIP_DECL_BENDERSCUTEXEC(benderscutExecInt)
568{ /*lint --e{715}*/
569 SCIP* subproblem;
570
571 assert(scip != NULL);
572 assert(benders != NULL);
573 assert(benderscut != NULL);
574 assert(result != NULL);
575
576 subproblem = SCIPbendersSubproblem(benders, probnumber);
577
578 if( subproblem == NULL )
579 {
580 SCIPdebugMsg(scip, "The subproblem %d is set to NULL. The <%s> Benders' decomposition cut can not be executed.\n",
581 probnumber, BENDERSCUT_NAME);
582
583 (*result) = SCIP_DIDNOTRUN;
584 return SCIP_OKAY;
585 }
586
587 /* it is only possible to generate the Laporte and Louveaux cuts for pure binary master problems */
589 && (!SCIPbendersMasterIsNonlinear(benders)
591 {
592 SCIPinfoMessage(scip, NULL, "The integer optimality cuts can only be applied to problems with a "
593 "pure binary master problem. The integer optimality cuts will be disabled.\n");
594
595 SCIPbenderscutSetEnabled(benderscut, FALSE);
596
597 return SCIP_OKAY;
598 }
599
600 /* the integer subproblem could terminate early if the auxiliary variable value is much greater than the optimal
601 * solution. As such, it is only necessary to generate a cut if the subproblem is OPTIMAL */
602 if( SCIPgetStatus(subproblem) == SCIP_STATUS_OPTIMAL )
603 {
604 /* generating a cut for a given subproblem */
605 SCIP_CALL( generateAndApplyBendersIntegerCuts(scip, benders, benderscut, sol, probnumber, type, result, FALSE) );
606 }
607
608 return SCIP_OKAY;
609}
610
611
612/*
613 * Benders' decomposition cuts specific interface methods
614 */
615
616/** creates the int Benders' decomposition cuts and includes it in SCIP */
618 SCIP* scip, /**< SCIP data structure */
619 SCIP_BENDERS* benders /**< Benders' decomposition */
620 )
621{
622 SCIP_BENDERSCUTDATA* benderscutdata;
623 SCIP_BENDERSCUT* benderscut;
625
626 assert(benders != NULL);
627
628 /* create int Benders' decomposition cuts data */
629 SCIP_CALL( SCIPallocBlockMemory(scip, &benderscutdata) );
630 benderscutdata->benders = benders;
631
632 benderscut = NULL;
633
634 /* include Benders' decomposition cuts */
636 BENDERSCUT_PRIORITY, BENDERSCUT_LPCUT, benderscutExecInt, benderscutdata) );
637
638 assert(benderscut != NULL);
639
640 /* set non fundamental callbacks via setter functions */
641 SCIP_CALL( SCIPsetBenderscutFree(scip, benderscut, benderscutFreeInt) );
642 SCIP_CALL( SCIPsetBenderscutInit(scip, benderscut, benderscutInitInt) );
643 SCIP_CALL( SCIPsetBenderscutExit(scip, benderscut, benderscutExitInt) );
644
645 /* add int Benders' decomposition cuts parameters */
646 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/benderscut/%s/cutsconstant",
649 "the constant term of the integer Benders' cuts.",
650 &benderscutdata->cutconstant, FALSE, SCIP_DEFAULT_CUTCONSTANT, -SCIPinfinity(scip), SCIPinfinity(scip),
651 paramChgdBenderscutintConstant, (SCIP_PARAMDATA*)benderscutdata) );
652
653 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/benderscut/%s/addcuts",
656 "should cuts be generated and added to the cutpool instead of global constraints directly added to the problem.",
657 &benderscutdata->addcuts, FALSE, SCIP_DEFAULT_ADDCUTS, NULL, NULL) );
658
659 return SCIP_OKAY;
660}
#define SCIP_DEFAULT_ADDCUTS
#define BENDERSCUT_LPCUT
static SCIP_DECL_BENDERSCUTINIT(benderscutInitInt)
static SCIP_DECL_BENDERSCUTFREE(benderscutFreeInt)
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)
static SCIP_DECL_BENDERSCUTEXEC(benderscutExecInt)
#define BENDERSCUT_PRIORITY
#define BENDERSCUT_DESC
#define BENDERSCUT_NAME
static SCIP_DECL_BENDERSCUTEXIT(benderscutExitInt)
#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_DECL_PARAMCHGD(paramChgdBenderscutintConstant)
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:266
#define SCIP_MAXSTRLEN
Definition: def.h:287
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:172
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIP_LONGINT_FORMAT
Definition: def.h:164
#define SCIP_CALL(x)
Definition: def.h:373
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)
Definition: scip_general.c:508
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:390
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2770
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1947
SCIP_OBJSENSE SCIPgetObjsense(SCIP *scip)
Definition: scip_prob.c:1225
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2037
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
#define SCIPdebugMsg
Definition: scip_message.h:78
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:6182
SCIP_RETCODE SCIPgetBendersSubproblemVar(SCIP *scip, SCIP_BENDERS *benders, SCIP_VAR *var, SCIP_VAR **mappedvar, int probnumber)
Definition: scip_benders.c:696
const char * SCIPbendersGetName(SCIP_BENDERS *benders)
Definition: benders.c:5946
int SCIPbendersGetNSubproblems(SCIP_BENDERS *benders)
Definition: benders.c:5990
SCIP * SCIPbendersSubproblem(SCIP_BENDERS *benders, int probnumber)
Definition: benders.c:6000
SCIP_Bool SCIPbendersMasterIsNonlinear(SCIP_BENDERS *benders)
Definition: benders.c:6459
SCIP_RETCODE SCIPcheckBendersSubproblemOptimality(SCIP *scip, SCIP_BENDERS *benders, SCIP_SOL *sol, int probnumber, SCIP_Bool *optimal)
Definition: scip_benders.c:892
SCIP_Real SCIPbendersGetSubproblemObjval(SCIP_BENDERS *benders, int probnumber)
Definition: benders.c:6221
SCIP_Real SCIPbendersGetSubproblemLowerbound(SCIP_BENDERS *benders, int probnumber)
Definition: benders.c:6788
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 SCIPsetBenderscutExit(SCIP *scip, SCIP_BENDERSCUT *benderscut, SCIP_DECL_BENDERSCUTEXIT((*benderscutexit)))
SCIP_RETCODE SCIPsetBenderscutInit(SCIP *scip, SCIP_BENDERSCUT *benderscut, SCIP_DECL_BENDERSCUTINIT((*benderscutinit)))
SCIP_RETCODE SCIPsetBenderscutFree(SCIP *scip, SCIP_BENDERSCUT *benderscut, SCIP_DECL_BENDERSCUTFREE((*benderscutfree)))
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:941
SCIP_RETCODE SCIPsetConsDynamic(SCIP *scip, SCIP_CONS *cons, SCIP_Bool dynamic)
Definition: scip_cons.c:1450
SCIP_RETCODE SCIPsetConsRemovable(SCIP *scip, SCIP_CONS *cons, SCIP_Bool removable)
Definition: scip_cons.c:1475
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1174
SCIP_RETCODE SCIPaddPoolCut(SCIP *scip, SCIP_ROW *row)
Definition: scip_cut.c:361
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:250
#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:17292
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip_lp.c:1583
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:1391
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1701
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2212
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1562
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2144
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip_sol.c:2165
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1296
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1213
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:18077
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10880
static const char * paramname[]
Definition: lpi_msk.c:5096
SCIP_PARAMDATA * SCIPparamGetData(SCIP_PARAM *param)
Definition: paramset.c:679
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)
Definition: pub_message.h:102
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
@ SCIP_BENDERSENFOTYPE_RELAX
Definition: type_benders.h:47
@ SCIP_BENDERSENFOTYPE_LP
Definition: type_benders.h:46
@ SCIP_BENDERSENFOTYPE_CHECK
Definition: type_benders.h:49
@ SCIP_BENDERSENFOTYPE_PSEUDO
Definition: type_benders.h:48
enum SCIP_BendersEnfoType SCIP_BENDERSENFOTYPE
Definition: type_benders.h:51
struct SCIP_BenderscutData SCIP_BENDERSCUTDATA
struct SCIP_ParamData SCIP_PARAMDATA
Definition: type_paramset.h:87
@ 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
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_INITSOLVE
Definition: type_set.h:52
@ SCIP_STATUS_OPTIMAL
Definition: type_stat.h:61