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