1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2022 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License. */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15
16 /**@file objbenders.h
17 * @brief C++ wrapper for Benders' decomposition
18 * @author Stephen J. Maher
19 */
20
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22
23 #ifndef __SCIP_OBJBENDERS_H__
24 #define __SCIP_OBJBENDERS_H__
25
26
27 #include <cassert>
28 #include <cstring>
29
30 #include "scip/scip.h"
31 #include "objscip/objcloneable.h"
32
33 namespace scip
34 {
35
36 /**
37 * @brief C++ wrapper for Benders' decomposition plugins
38 *
39 * This class defines the interface for the Benders' decomposition framework implemented in C++. Note that there
40 * are pure virtual functions (these have to be implemented). These functions are: benders_exec(), benders_createsub(),
41 * benders_getvar().
42 *
43 * - \ref BENDER "Instructions for implementing a Benders' decomposition plugin"
44 * - \ref BENDERS "List of available Benders' decomposition plugins"
45 * - \ref type_benders.h "Corresponding C interface"
46 */
(1) Event missing_copy_ctor: |
Class "scip::ObjBenders" owns resources that are freed in its destructor but has no user-written copy constructor. |
(2) Event free_resource: |
The destructor frees member "scip_desc_". [details] |
(3) Event free_resource: |
The destructor frees member "scip_name_". [details] |
47 class ObjBenders : public ObjCloneable
48 {
49 public:
50 /*lint --e{1540}*/
51
52 /** SCIP data structure */
53 SCIP* scip_;
54
55 /** name of the Benders' decomposition */
56 char* scip_name_;
57
58 /** description of the Benders' decomposition */
59 char* scip_desc_;
60
61 /** the priority of the Benders' decomposition */
62 const int scip_priority_;
63
64 /** should cuts be generated from the LP solution */
65 const SCIP_Bool scip_cutlp_;
66
67 /** should cuts be generated from the pseudo solution */
68 const SCIP_Bool scip_cutpseudo_;
69
70 /** should cuts be generated from the relaxation solution */
71 const SCIP_Bool scip_cutrelax_;
72
73 /** should this Benders' decomposition share the auxiliary variables from the highest priority Benders? */
74 const SCIP_Bool scip_shareauxvars_;
75
76 /** default constructor */
77 ObjBenders(
78 SCIP* scip, /**< SCIP data structure */
79 const char* name, /**< name of Benders' decomposition */
80 const char* desc, /**< description of Benders' decomposition */
81 int priority, /**< priority of the Benders' decomposition */
82 SCIP_Bool cutlp, /**< should Benders' cuts be generated for LP solutions */
83 SCIP_Bool cutpseudo, /**< should Benders' cuts be generated for pseudo solutions */
84 SCIP_Bool cutrelax, /**< should Benders' cuts be generated for relaxation solutions */
85 SCIP_Bool shareauxvars /**< should this Benders' use the highest priority Benders' aux vars */
86 )
87 : scip_(scip),
88 scip_name_(0),
89 scip_desc_(0),
90 scip_priority_(priority),
91 scip_cutlp_(cutlp),
92 scip_cutpseudo_(cutpseudo),
93 scip_cutrelax_(cutrelax),
94 scip_shareauxvars_(shareauxvars)
95 {
96 /* the macro SCIPduplicateMemoryArray does not need the first argument: */
97 SCIP_CALL_ABORT( SCIPduplicateMemoryArray(scip_, &scip_name_, name, std::strlen(name)+1) );
98 SCIP_CALL_ABORT( SCIPduplicateMemoryArray(scip_, &scip_desc_, desc, std::strlen(desc)+1) );
99 }
100
101 /** destructor */
102 virtual ~ObjBenders()
103 {
104 /* the macro SCIPfreeMemoryArray does not need the first argument: */
105 /*lint --e{64}*/
(1) Event freed_arg: |
"BMSfreeMemory_call" frees parameter "this->scip_name_". [details] |
106 SCIPfreeMemoryArray(scip_, &scip_name_);
(1) Event freed_arg: |
"BMSfreeMemory_call" frees parameter "this->scip_desc_". [details] |
107 SCIPfreeMemoryArray(scip_, &scip_desc_);
108 }
109
110 /** copy method for benders plugins (called when SCIP copies plugins)
111 *
112 * @see SCIP_DECL_BENDERSCOPY(x) in @ref type_benders.h
113 */
114 virtual SCIP_DECL_BENDERSCOPY(scip_copy)
115 { /*lint --e{715}*/
116 return SCIP_OKAY;
117 }
118
119 /** destructor of variable benders to free user data (called when SCIP is exiting)
120 *
121 * @see SCIP_DECL_BENDERSFREE(x) in @ref type_benders.h
122 */
123 virtual SCIP_DECL_BENDERSFREE(scip_free)
124 { /*lint --e{715}*/
125 return SCIP_OKAY;
126 }
127
128 /** initialization method of variable benders (called after problem was transformed and benders is active)
129 *
130 * @see SCIP_DECL_BENDERSINIT(x) in @ref type_benders.h
131 */
132 virtual SCIP_DECL_BENDERSINIT(scip_init)
133 { /*lint --e{715}*/
134 return SCIP_OKAY;
135 }
136
137 /** deinitialization method of variable benders (called before transformed problem is freed and benders is active)
138 *
139 * @see SCIP_DECL_BENDERSEXIT(x) in @ref type_benders.h
140 */
141 virtual SCIP_DECL_BENDERSEXIT(scip_exit)
142 { /*lint --e{715}*/
143 return SCIP_OKAY;
144 }
145
146 /** presolving initialization method of constraint handler (called when presolving is about to begin)
147 *
148 * @see SCIP_DECL_BENDERSINITPRE(x) in @ref type_benders.h
149 */
150 virtual SCIP_DECL_BENDERSINITPRE(scip_initpre)
151 { /*lint --e{715}*/
152 return SCIP_OKAY;
153 }
154
155 /** presolving deinitialization method of constraint handler (called after presolving has been finished)
156 *
157 * @see SCIP_DECL_BENDERSEXITPRE(x) in @ref type_benders.h
158 */
159 virtual SCIP_DECL_BENDERSEXITPRE(scip_exitpre)
160 { /*lint --e{715}*/
161 return SCIP_OKAY;
162 }
163
164 /** solving process initialization method of variable benders (called when branch and bound process is about to begin)
165 *
166 * @see SCIP_DECL_BENDERSINITSOL(x) in @ref type_benders.h
167 */
168 virtual SCIP_DECL_BENDERSINITSOL(scip_initsol)
169 { /*lint --e{715}*/
170 return SCIP_OKAY;
171 }
172
173 /** solving process deinitialization method of variable benders (called before branch and bound process data is freed)
174 *
175 * @see SCIP_DECL_BENDERSEXITSOL(x) in @ref type_benders.h
176 */
177 virtual SCIP_DECL_BENDERSEXITSOL(scip_exitsol)
178 { /*lint --e{715}*/
179 return SCIP_OKAY;
180 }
181
182 /** the method for creating the Benders' decomposition subproblem. This method is called during the initialisation stage
183 * (after the master problem was transformed)
184 *
185 * @see SCIP_DECL_BENDERSCREATESUB(x) in @ref type_benders.h
186 */
187 virtual SCIP_DECL_BENDERSCREATESUB(scip_createsub) = 0;
188
189 /** called before the subproblem solving loop for Benders' decomposition. The pre subproblem solve function gives the
190 * user an oppportunity to perform any global set up for the Benders' decomposition.
191 *
192 * @see SCIP_DECL_BENDERSPRESUBSOLVE(x) in @ref type_benders.h
193 */
194 virtual SCIP_DECL_BENDERSPRESUBSOLVE(scip_presubsolve)
195 { /*lint --e{715}*/
196 return SCIP_OKAY;
197 }
198
199 /** the solving method for a single convex Benders' decomposition subproblem. The solving methods are separated so
200 * that they can be called in parallel.
201 *
202 * @see SCIP_DECL_BENDERSSOLVESUBCONVEX(x) in @ref type_benders.h
203 */
204 virtual SCIP_DECL_BENDERSSOLVESUBCONVEX(scip_solvesubconvex)
205 { /*lint --e{715}*/
206 return SCIP_OKAY;
207 }
208
209 /** the solving method for a single Benders' decomposition subproblem. The solving methods are separated so that they
210 * can be called in parallel.
211 *
212 * @see SCIP_DECL_BENDERSSOLVESUB(x) in @ref type_benders.h
213 */
214 virtual SCIP_DECL_BENDERSSOLVESUB(scip_solvesub)
215 { /*lint --e{715}*/
216 return SCIP_OKAY;
217 }
218
219 /** the post-solve method for Benders' decomposition. The post-solve method is called after the subproblems have
220 * been solved but before they are freed.
221 * @see SCIP_DECL_BENDERSPOSTSOLVE(x) in @ref type_benders.h
222 */
223 virtual SCIP_DECL_BENDERSPOSTSOLVE(scip_postsolve)
224 { /*lint --e{715}*/
225 return SCIP_OKAY;
226 }
227
228 /** frees the subproblem so that it can be resolved in the next iteration. In the SCIP case, this involves freeing the
229 * transformed problem using SCIPfreeTransform()
230 *
231 * @see SCIP_DECL_BENDERSFREESUB(x) in @ref type_benders.h
232 */
233 virtual SCIP_DECL_BENDERSFREESUB(scip_freesub)
234 { /*lint --e{715}*/
235 return SCIP_OKAY;
236 }
237
238 /** the variable mapping from the subproblem to the master problem.
239 *
240 * @see SCIP_DECL_BENDERSGETVAR(x) in @ref type_benders.h
241 */
242 virtual SCIP_DECL_BENDERSGETVAR(scip_getvar) = 0;
243
244 };
245
246 } /* namespace scip */
247
248
249
250 /** creates the Benders' decomposition for the given Benders' decomposition object and includes it in SCIP
251 *
252 * The method should be called in one of the following ways:
253 *
254 * 1. The user is resposible of deleting the object:
255 * SCIP_CALL( SCIPcreate(&scip) );
256 * ...
257 * MyBenders* mybenders = new MyBenders(...);
258 * SCIP_CALL( SCIPincludeObjBenders(scip, &mybenders, FALSE) );
259 * ...
260 * SCIP_CALL( SCIPfree(&scip) );
261 * delete mybenders; // delete benders AFTER SCIPfree() !
262 *
263 * 2. The object pointer is passed to SCIP and deleted by SCIP in the SCIPfree() call:
264 * SCIP_CALL( SCIPcreate(&scip) );
265 * ...
266 * SCIP_CALL( SCIPincludeObjBenders(scip, new MyBenders(...), TRUE) );
267 * ...
268 * SCIP_CALL( SCIPfree(&scip) ); // destructor of MyBenders is called here
269 */
270 SCIP_EXPORT
271 SCIP_RETCODE SCIPincludeObjBenders(
272 SCIP* scip, /**< SCIP data structure */
273 scip::ObjBenders* objbenders, /**< Benders' decomposition object */
274 SCIP_Bool deleteobject /**< should the Benders' decomposition object be deleted when benders is freed? */
275 );
276
277 /** returns the benders object of the given name, or 0 if not existing */
278 SCIP_EXPORT
279 scip::ObjBenders* SCIPfindObjBenders(
280 SCIP* scip, /**< SCIP data structure */
281 const char* name /**< name of Benders' decomposition */
282 );
283
284 /** returns the benders object for the given constraint handler */
285 SCIP_EXPORT
286 scip::ObjBenders* SCIPgetObjBenders(
287 SCIP* scip, /**< SCIP data structure */
288 SCIP_BENDERS* benders /**< Benders' decomposition */
289 );
290
291 #endif
292