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   benders.c
26   	 * @ingroup OTHER_CFILES
27   	 * @brief  methods for Benders' decomposition
28   	 * @author Stephen J. Maher
29   	 */
30   	
31   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32   	
33   	#include <assert.h>
34   	#include <string.h>
35   	
36   	#include "scip/def.h"
37   	#include "scip/set.h"
38   	#include "scip/clock.h"
39   	#include "scip/dcmp.h"
40   	#include "scip/paramset.h"
41   	#include "scip/lp.h"
42   	#include "scip/prob.h"
43   	#include "scip/pricestore.h"
44   	#include "scip/scip.h"
45   	#include "scip/scipdefplugins.h"
46   	#include "scip/benders.h"
47   	#include "scip/pub_message.h"
48   	#include "scip/pub_misc.h"
49   	#include "scip/cons_linear.h"
50   	#include "scip/cons_nonlinear.h"
51   	
52   	#include "scip/struct_benders.h"
53   	#include "scip/struct_benderscut.h"
54   	
55   	#include "scip/benderscut.h"
56   	
57   	/* Defaults for parameters */
58   	#define SCIP_DEFAULT_TRANSFERCUTS         FALSE  /** should Benders' cuts generated in LNS heuristics be transferred to the main SCIP instance? */
59   	#define SCIP_DEFAULT_CUTSASCONSS           TRUE  /** should the transferred cuts be added as constraints? */
60   	#define SCIP_DEFAULT_LNSCHECK              TRUE  /** should the Benders' decomposition be used in LNS heuristics */
61   	#define SCIP_DEFAULT_LNSMAXDEPTH             -1  /** maximum depth at which the LNS check is performed */
62   	#define SCIP_DEFAULT_LNSMAXCALLS             10  /** the maximum number of Benders' decomposition calls in LNS heuristics */
63   	#define SCIP_DEFAULT_LNSMAXCALLSROOT          0  /** the maximum number of root node Benders' decomposition calls in LNS heuristics */
64   	#define SCIP_DEFAULT_SUBPROBFRAC            1.0  /** fraction of subproblems that are solved in each iteration */
65   	#define SCIP_DEFAULT_UPDATEAUXVARBOUND    FALSE  /** should the auxiliary variable lower bound be updated by solving the subproblem */
66   	#define SCIP_DEFAULT_AUXVARSIMPLINT       FALSE  /** set the auxiliary variables as implint if the subproblem objective is integer */
67   	#define SCIP_DEFAULT_CUTCHECK              TRUE  /** should cuts be generated during the checking of solutions? */
68   	#define SCIP_DEFAULT_STRENGTHENMULT         0.5  /** the convex combination multiplier for the cut strengthening */
69   	#define SCIP_DEFAULT_NOIMPROVELIMIT           5  /** the maximum number of cut strengthening without improvement */
70   	#define SCIP_DEFAULT_STRENGTHENPERTURB    1e-06  /** the amount by which the cut strengthening solution is perturbed */
71   	#define SCIP_DEFAULT_STRENGTHENENABLED    FALSE  /** enable the core point cut strengthening approach */
72   	#define SCIP_DEFAULT_STRENGTHENINTPOINT     'r'  /** where should the strengthening interior point be sourced from ('l'p relaxation, 'f'irst solution, 'i'ncumbent solution, 'r'elative interior point, vector of 'o'nes, vector of 'z'eros) */
73   	#define SCIP_DEFAULT_NUMTHREADS               1  /** the number of parallel threads to use when solving the subproblems */
74   	#define SCIP_DEFAULT_EXECFEASPHASE        FALSE  /** should a feasibility phase be executed during the root node processing */
75   	#define SCIP_DEFAULT_SLACKVARCOEF          1e+6  /** the initial objective coefficient of the slack variables in the subproblem */
76   	#define SCIP_DEFAULT_MAXSLACKVARCOEF       1e+9  /** the maximal objective coefficient of the slack variables in the subproblem */
77   	#define SCIP_DEFAULT_CHECKCONSCONVEXITY    TRUE  /** should the constraints of the subproblem be checked for convexity? */
78   	#define SCIP_DEFAULT_NLPITERLIMIT         10000  /** iteration limit for NLP solver */
79   	
80   	#define BENDERS_MAXPSEUDOSOLS                 5  /** the maximum number of pseudo solutions checked before suggesting
81   	                                                  *  merge candidates */
82   	
83   	#define BENDERS_ARRAYSIZE        1000    /**< the initial size of the added constraints/cuts arrays */
84   	
85   	#define AUXILIARYVAR_NAME     "##bendersauxiliaryvar" /** the name for the Benders' auxiliary variables in the master problem */
86   	#define SLACKVAR_NAME         "##bendersslackvar"     /** the name for the Benders' slack variables added to each
87   	                                                       *  constraints in the subproblems */
88   	#define NLINEARCONSHDLRS 5
89   	
90   	/* event handler properties */
91   	#define NODEFOCUS_EVENTHDLR_NAME         "bendersnodefocus"
92   	#define NODEFOCUS_EVENTHDLR_DESC         "node focus event handler for Benders' decomposition"
93   	
94   	#define MIPNODEFOCUS_EVENTHDLR_NAME      "bendersmipsolvenodefocus"
95   	#define MIPNODEFOCUS_EVENTHDLR_DESC      "node focus event handler for the MIP solve method for Benders' decomposition"
96   	
97   	#define UPPERBOUND_EVENTHDLR_NAME        "bendersupperbound"
98   	#define UPPERBOUND_EVENTHDLR_DESC        "found solution event handler to terminate subproblem solve for a given upper bound"
99   	
100  	#define NODESOLVED_EVENTHDLR_NAME        "bendersnodesolved"
101  	#define NODESOLVED_EVENTHDLR_DESC        "node solved event handler for the Benders' integer cuts"
102  	
103  	
104  	/** event handler data */
105  	struct SCIP_EventhdlrData
106  	{
107  	   int                   filterpos;          /**< the event filter entry */
108  	   int                   numruns;            /**< the number of times that the problem has been solved */
109  	   SCIP_Real             upperbound;         /**< an upper bound for the problem */
110  	   SCIP_Bool             solvecip;           /**< is the event called from a MIP subproblem solve*/
111  	};
112  	
113  	
114  	/* ---------------- Local methods for event handlers ---------------- */
115  	
116  	/** initialises the members of the eventhandler data */
117  	static
118  	SCIP_RETCODE initEventhandlerData(
119  	   SCIP*                 scip,               /**< the SCIP data structure */
120  	   SCIP_EVENTHDLRDATA*   eventhdlrdata       /**< the event handler data */
121  	   )
122  	{
123  	   assert(scip != NULL);
124  	   assert(eventhdlrdata != NULL);
125  	
126  	   eventhdlrdata->filterpos = -1;
127  	   eventhdlrdata->numruns = 0;
128  	   eventhdlrdata->upperbound = -SCIPinfinity(scip);
129  	   eventhdlrdata->solvecip = FALSE;
130  	
131  	   return SCIP_OKAY;
132  	}
133  	
134  	/** initsol method for the event handlers */
135  	static
136  	SCIP_RETCODE initsolEventhandler(
137  	   SCIP*                 scip,               /**< the SCIP data structure */
138  	   SCIP_EVENTHDLR*       eventhdlr,          /**< the event handlers data structure */
139  	   SCIP_EVENTTYPE        eventtype           /**< event type mask to select events to catch */
140  	   )
141  	{
142  	   SCIP_EVENTHDLRDATA* eventhdlrdata;
143  	
144  	   assert(scip != NULL);
145  	   assert(eventhdlr != NULL);
146  	
147  	   eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
148  	
149  	   SCIP_CALL(SCIPcatchEvent(scip, eventtype, eventhdlr, NULL, &eventhdlrdata->filterpos));
150  	
151  	   return SCIP_OKAY;
152  	}
153  	
154  	/** the exit sol method for the event handlers */
155  	static
156  	SCIP_RETCODE exitsolEventhandler(
157  	   SCIP*                 scip,               /**< the SCIP data structure */
158  	   SCIP_EVENTHDLR*       eventhdlr,          /**< the event handlers data structure */
159  	   SCIP_EVENTTYPE        eventtype           /**< event type mask to select events to catch */
160  	   )
161  	{
162  	   SCIP_EVENTHDLRDATA* eventhdlrdata;
163  	
164  	   assert(scip != NULL);
165  	   assert(eventhdlr != NULL);
166  	
167  	   eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
168  	
169  	   if( eventhdlrdata->filterpos >= 0 )
170  	   {
171  	      SCIP_CALL(SCIPdropEvent(scip, eventtype, eventhdlr, NULL, eventhdlrdata->filterpos));
172  	      eventhdlrdata->filterpos = -1;
173  	   }
174  	
175  	   return SCIP_OKAY;
176  	}
177  	
178  	/** the exit method for the event handlers */
179  	static
180  	SCIP_RETCODE exitEventhandler(
181  	   SCIP*                 scip,               /**< the SCIP data structure */
182  	   SCIP_EVENTHDLR*       eventhdlr           /**< the event handlers data structure */
183  	   )
184  	{
185  	   SCIP_EVENTHDLRDATA* eventhdlrdata;
186  	
187  	   assert(scip != NULL);
188  	   assert(eventhdlr != NULL);
189  	
190  	   eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
191  	
192  	   /* reinitialise the event handler data */
193  	   SCIP_CALL( initEventhandlerData(scip, eventhdlrdata) );
194  	
195  	   return SCIP_OKAY;
196  	}
197  	
198  	/** free method for the event handler */
199  	static
200  	SCIP_RETCODE freeEventhandler(
201  	   SCIP*                 scip,               /**< the SCIP data structure */
202  	   SCIP_EVENTHDLR*       eventhdlr           /**< the event handlers data structure */
203  	   )
204  	{
205  	   SCIP_EVENTHDLRDATA* eventhdlrdata;
206  	
207  	   assert(scip != NULL);
208  	   assert(eventhdlr != NULL);
209  	
210  	   eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
211  	   assert(eventhdlrdata != NULL);
212  	
213  	   SCIPfreeBlockMemory(scip, &eventhdlrdata);
214  	
215  	   SCIPeventhdlrSetData(eventhdlr, NULL);
216  	
217  	   return SCIP_OKAY;
218  	}
219  	
220  	
221  	
222  	/* ---------------- Callback methods of node focus event handler ---------------- */
223  	
224  	/** exec the event handler */
225  	static
226  	SCIP_DECL_EVENTEXEC(eventExecBendersNodefocus)
227  	{  /*lint --e{715}*/
228  	   SCIP_EVENTHDLRDATA* eventhdlrdata;
229  	
230  	   assert(scip != NULL);
231  	   assert(eventhdlr != NULL);
232  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), NODEFOCUS_EVENTHDLR_NAME) == 0);
233  	
234  	   eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
235  	
236  	   /* sending an interrupt solve signal to return the control back to the Benders' decomposition plugin.
237  	    * This will ensure the SCIP stage is SCIP_STAGE_SOLVING, allowing the use of probing mode. */
238  	   SCIP_CALL( SCIPinterruptSolve(scip) );
239  	
240  	   SCIP_CALL(SCIPdropEvent(scip, SCIP_EVENTTYPE_NODEFOCUSED, eventhdlr, NULL, eventhdlrdata->filterpos));
241  	   eventhdlrdata->filterpos = -1;
242  	
243  	   return SCIP_OKAY;
244  	}
245  	
246  	/** solving process initialization method of event handler (called when branch and bound process is about to begin) */
247  	static
248  	SCIP_DECL_EVENTINITSOL(eventInitsolBendersNodefocus)
249  	{
250  	   assert(scip != NULL);
251  	   assert(eventhdlr != NULL);
252  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), NODEFOCUS_EVENTHDLR_NAME) == 0);
253  	
254  	   SCIP_CALL( initsolEventhandler(scip, eventhdlr, SCIP_EVENTTYPE_NODEFOCUSED) );
255  	
256  	   return SCIP_OKAY;
257  	}
258  	
259  	/** solving process deinitialization method of event handler (called before branch and bound process data is freed) */
260  	static
261  	SCIP_DECL_EVENTEXITSOL(eventExitsolBendersNodefocus)
262  	{
263  	   assert(scip != NULL);
264  	   assert(eventhdlr != NULL);
265  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), NODEFOCUS_EVENTHDLR_NAME) == 0);
266  	
267  	   SCIP_CALL( exitsolEventhandler(scip, eventhdlr, SCIP_EVENTTYPE_NODEFOCUSED) );
268  	
269  	   return SCIP_OKAY;
270  	}
271  	
272  	/** deinitialization method of event handler (called before transformed problem is freed) */
273  	static
274  	SCIP_DECL_EVENTEXIT(eventExitBendersNodefocus)
275  	{
276  	   assert(scip != NULL);
277  	   assert(eventhdlr != NULL);
278  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), NODEFOCUS_EVENTHDLR_NAME) == 0);
279  	
280  	   SCIP_CALL( exitEventhandler(scip, eventhdlr) );
281  	
282  	   return SCIP_OKAY;
283  	}
284  	
285  	/** deinitialization method of event handler (called before transformed problem is freed) */
286  	static
287  	SCIP_DECL_EVENTFREE(eventFreeBendersNodefocus)
288  	{
289  	   assert(scip != NULL);
290  	   assert(eventhdlr != NULL);
291  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), NODEFOCUS_EVENTHDLR_NAME) == 0);
292  	
293  	   SCIP_CALL( freeEventhandler(scip, eventhdlr) );
294  	
295  	   return SCIP_OKAY;
296  	}
297  	
298  	
299  	/* ---------------- Callback methods of MIP solve node focus event handler ---------------- */
300  	
301  	/** exec the event handler */
302  	static
303  	SCIP_DECL_EVENTEXEC(eventExecBendersMipnodefocus)
304  	{  /*lint --e{715}*/
305  	   SCIP_EVENTHDLRDATA* eventhdlrdata;
306  	
307  	   assert(scip != NULL);
308  	   assert(eventhdlr != NULL);
309  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), MIPNODEFOCUS_EVENTHDLR_NAME) == 0);
310  	
311  	   eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
312  	
313  	   /* interrupting the solve so that the control is returned back to the Benders' core. */
314  	   if( eventhdlrdata->numruns == 0 && !eventhdlrdata->solvecip )
315  	   {
316  	      SCIP_CALL( SCIPinterruptSolve(scip) );
317  	   }
318  	
319  	   SCIP_CALL(SCIPdropEvent(scip, SCIP_EVENTTYPE_NODEFOCUSED, eventhdlr, NULL, eventhdlrdata->filterpos));
320  	   eventhdlrdata->filterpos = -1;
321  	
322  	   eventhdlrdata->numruns++;
323  	
324  	   return SCIP_OKAY;
325  	}
326  	
327  	/** solving process initialization method of event handler (called when branch and bound process is about to begin) */
328  	static
329  	SCIP_DECL_EVENTINITSOL(eventInitsolBendersMipnodefocus)
330  	{
331  	   assert(scip != NULL);
332  	   assert(eventhdlr != NULL);
333  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), MIPNODEFOCUS_EVENTHDLR_NAME) == 0);
334  	
335  	   SCIP_CALL( initsolEventhandler(scip, eventhdlr, SCIP_EVENTTYPE_NODEFOCUSED) );
336  	
337  	   return SCIP_OKAY;
338  	}
339  	
340  	/** solving process deinitialization method of event handler (called before branch and bound process data is freed) */
341  	static
342  	SCIP_DECL_EVENTEXITSOL(eventExitsolBendersMipnodefocus)
343  	{
344  	   assert(scip != NULL);
345  	   assert(eventhdlr != NULL);
346  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), MIPNODEFOCUS_EVENTHDLR_NAME) == 0);
347  	
348  	   SCIP_CALL( exitsolEventhandler(scip, eventhdlr, SCIP_EVENTTYPE_NODEFOCUSED) );
349  	
350  	   return SCIP_OKAY;
351  	}
352  	
353  	/** deinitialization method of event handler (called before transformed problem is freed) */
354  	static
355  	SCIP_DECL_EVENTEXIT(eventExitBendersMipnodefocus)
356  	{
357  	   assert(scip != NULL);
358  	   assert(eventhdlr != NULL);
359  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), MIPNODEFOCUS_EVENTHDLR_NAME) == 0);
360  	
361  	   SCIP_CALL( exitEventhandler(scip, eventhdlr) );
362  	
363  	   return SCIP_OKAY;
364  	}
365  	
366  	/** deinitialization method of event handler (called before transformed problem is freed) */
367  	static
368  	SCIP_DECL_EVENTFREE(eventFreeBendersMipnodefocus)
369  	{
370  	   assert(scip != NULL);
371  	   assert(eventhdlr != NULL);
372  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), MIPNODEFOCUS_EVENTHDLR_NAME) == 0);
373  	
374  	   SCIP_CALL( freeEventhandler(scip, eventhdlr) );
375  	
376  	   return SCIP_OKAY;
377  	}
378  	
379  	/* ---------------- Callback methods of solution found event handler ---------------- */
380  	
381  	/** exec the event handler */
382  	static
383  	SCIP_DECL_EVENTEXEC(eventExecBendersUpperbound)
384  	{  /*lint --e{715}*/
385  	   SCIP_EVENTHDLRDATA* eventhdlrdata;
386  	   SCIP_SOL* bestsol;
387  	
388  	   assert(scip != NULL);
389  	   assert(eventhdlr != NULL);
390  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), UPPERBOUND_EVENTHDLR_NAME) == 0);
391  	
392  	   eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
393  	   assert(eventhdlrdata != NULL);
394  	
395  	   bestsol = SCIPgetBestSol(scip);
396  	
397  	   if( SCIPisLT(scip, SCIPgetSolOrigObj(scip, bestsol)*(int)SCIPgetObjsense(scip), eventhdlrdata->upperbound) )
398  	   {
399  	      SCIP_CALL( SCIPinterruptSolve(scip) );
400  	   }
401  	
402  	   return SCIP_OKAY;
403  	}
404  	
405  	/** solving process initialization method of event handler (called when branch and bound process is about to begin) */
406  	static
407  	SCIP_DECL_EVENTINITSOL(eventInitsolBendersUpperbound)
408  	{
409  	   assert(scip != NULL);
410  	   assert(eventhdlr != NULL);
411  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), UPPERBOUND_EVENTHDLR_NAME) == 0);
412  	
413  	   SCIP_CALL( initsolEventhandler(scip, eventhdlr, SCIP_EVENTTYPE_BESTSOLFOUND) );
414  	
415  	   return SCIP_OKAY;
416  	}
417  	
418  	/** solving process deinitialization method of event handler (called before branch and bound process data is freed) */
419  	static
420  	SCIP_DECL_EVENTEXITSOL(eventExitsolBendersUpperbound)
421  	{
422  	   assert(scip != NULL);
423  	   assert(eventhdlr != NULL);
424  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), UPPERBOUND_EVENTHDLR_NAME) == 0);
425  	
426  	   SCIP_CALL( exitsolEventhandler(scip, eventhdlr, SCIP_EVENTTYPE_BESTSOLFOUND) );
427  	
428  	   return SCIP_OKAY;
429  	}
430  	
431  	/** deinitialization method of event handler (called before transformed problem is freed) */
432  	static
433  	SCIP_DECL_EVENTEXIT(eventExitBendersUpperbound)
434  	{
435  	   assert(scip != NULL);
436  	   assert(eventhdlr != NULL);
437  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), UPPERBOUND_EVENTHDLR_NAME) == 0);
438  	
439  	   SCIP_CALL( exitEventhandler(scip, eventhdlr) );
440  	
441  	   return SCIP_OKAY;
442  	}
443  	
444  	/** deinitialization method of event handler (called before transformed problem is freed) */
445  	static
446  	SCIP_DECL_EVENTFREE(eventFreeBendersUpperbound)
447  	{
448  	   assert(scip != NULL);
449  	   assert(eventhdlr != NULL);
450  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), UPPERBOUND_EVENTHDLR_NAME) == 0);
451  	
452  	   SCIP_CALL( freeEventhandler(scip, eventhdlr) );
453  	
454  	   return SCIP_OKAY;
455  	}
456  	
457  	/** updates the upper bound in the event handler data */
458  	static
459  	SCIP_RETCODE updateEventhdlrUpperbound(
460  	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
461  	   int                   probnumber,         /**< the subproblem number */
462  	   SCIP_Real             upperbound          /**< the upper bound value */
463  	   )
464  	{
465  	   SCIP_EVENTHDLR* eventhdlr;
466  	   SCIP_EVENTHDLRDATA* eventhdlrdata;
467  	
468  	   assert(benders != NULL);
469  	   assert(probnumber >= 0 && probnumber < benders->nsubproblems);
470  	
471  	   eventhdlr = SCIPfindEventhdlr(SCIPbendersSubproblem(benders, probnumber), UPPERBOUND_EVENTHDLR_NAME);
472  	   assert(eventhdlr != NULL);
473  	
474  	   eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
475  	   assert(eventhdlrdata != NULL);
476  	
477  	   eventhdlrdata->upperbound = upperbound;
478  	
479  	   return SCIP_OKAY;
480  	}
481  	
482  	/* ---------------- Callback methods of the node solved event handler ---------------- */
483  	
484  	/** Updates the cut constant of the Benders' cuts data.
485  	 *  This function solves the master problem with only the auxiliary variables in the objective function.
486  	 */
487  	static
488  	SCIP_RETCODE updateSubproblemLowerbound(
489  	   SCIP*                 masterprob,         /**< the SCIP instance of the master problem */
490  	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
491  	   )
492  	{
493  	   SCIP_VAR** vars;
494  	   int nvars;
495  	   int nsubproblems;
496  	   int i;
497  	   SCIP_Bool lperror;
498  	   SCIP_Bool cutoff;
499  	
500  	   assert(masterprob != NULL);
501  	   assert(benders != NULL);
502  	
503  	   /* don't run in probing or in repropagation */
504  	   if( SCIPinProbing(masterprob) || SCIPinRepropagation(masterprob) || SCIPinDive(masterprob) )
505  	      return SCIP_OKAY;
506  	
507  	   nsubproblems = SCIPbendersGetNSubproblems(benders);
508  	
509  	   SCIP_CALL( SCIPstartProbing(masterprob) );
510  	
511  	   /* change the master problem variables to 0 */
512  	   nvars = SCIPgetNVars(masterprob);
513  	   vars = SCIPgetVars(masterprob);
514  	
515  	   /* setting the objective function coefficient to 0 for all variables */
516  	   for( i = 0; i < nvars; i++ )
517  	   {
518  	      if( SCIPvarGetStatus(vars[i]) == SCIP_VARSTATUS_COLUMN )
519  	      {
520  	         SCIP_CALL( SCIPchgVarObjProbing(masterprob, vars[i], 0.0) );
521  	      }
522  	   }
523  	
524  	   /* solving an LP for all subproblems to find the lower bound */
525  	   for( i = 0; i < nsubproblems; i++)
526  	   {
527  	      SCIP_VAR* auxiliaryvar;
528  	
529  	      auxiliaryvar = SCIPbendersGetAuxiliaryVar(benders, i);
530  	
531  	      if( SCIPvarGetStatus(auxiliaryvar) != SCIP_VARSTATUS_COLUMN )
532  	         continue;
533  	
534  	      SCIP_CALL( SCIPchgVarObjProbing(masterprob, auxiliaryvar, 1.0) );
535  	
536  	      /* solving the probing LP to get a lower bound on the auxiliary variables */
537  	      SCIP_CALL( SCIPsolveProbingLP(masterprob, -1, &lperror, &cutoff) );
538  	
539  	      if( !SCIPisInfinity(masterprob, -SCIPgetSolTransObj(masterprob, NULL)) )
540  	         SCIPbendersUpdateSubproblemLowerbound(benders, i, SCIPgetSolTransObj(masterprob, NULL));
541  	
542  	      SCIPdebugMsg(masterprob, "Cut constant for subproblem %d: %g\n", i,
543  	         SCIPbendersGetSubproblemLowerbound(benders, i));
544  	
545  	      SCIP_CALL( SCIPchgVarObjProbing(masterprob, auxiliaryvar, 0.0) );
546  	   }
547  	
548  	   SCIP_CALL( SCIPendProbing(masterprob) );
549  	
550  	   return SCIP_OKAY;
551  	}
552  	
553  	/** exec the event handler */
554  	static
555  	SCIP_DECL_EVENTEXEC(eventExecBendersNodesolved)
556  	{  /*lint --e{715}*/
557  	   SCIP_BENDERS* benders;
558  	
559  	   assert(scip != NULL);
560  	   assert(eventhdlr != NULL);
561  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), NODESOLVED_EVENTHDLR_NAME) == 0);
562  	
563  	   benders = (SCIP_BENDERS*)SCIPeventhdlrGetData(eventhdlr);   /*lint !e826*/
564  	
565  	   if( SCIPbendersGetNSubproblems(benders) > 0
566  	      && SCIPbendersGetNSubproblems(benders) > SCIPbendersGetNConvexSubproblems(benders) )
567  	   {
568  	      SCIP_CALL( updateSubproblemLowerbound(scip, benders) );
569  	   }
570  	
571  	   SCIP_CALL( SCIPdropEvent(scip, SCIP_EVENTTYPE_NODESOLVED, eventhdlr, NULL, -1) );
572  	
573  	   return SCIP_OKAY;
574  	}
575  	
576  	/** solving process initialization method of event handler (called when branch and bound process is about to begin) */
577  	static
578  	SCIP_DECL_EVENTINITSOL(eventInitsolBendersNodesolved)
579  	{
580  	   SCIP_BENDERS* benders;
581  	
582  	   assert(scip != NULL);
583  	   assert(eventhdlr != NULL);
584  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), NODESOLVED_EVENTHDLR_NAME) == 0);
585  	
586  	   /* getting the Benders' decomposition data structure */
587  	   benders = (SCIP_BENDERS*)SCIPeventhdlrGetData(eventhdlr);   /*lint !e826*/
588  	
589  	   /* The event is only caught if there is an active Benders' decomposition, the integer subproblem are solved and
590  	    * the Benders' decomposition has not been copied in thread safe mode
591  	    */
592  	   if( SCIPbendersIsActive(benders) && !SCIPbendersOnlyCheckConvexRelax(benders, SCIPgetSubscipsOff(scip))
593  	      && !benders->threadsafe )
594  	   {
595  	      SCIP_CALL( SCIPcatchEvent(scip, SCIP_EVENTTYPE_NODESOLVED, eventhdlr, NULL, NULL) );
596  	   }
597  	
598  	   return SCIP_OKAY;
599  	}
600  	
601  	
602  	/* ---------------- Methods for the parallelisation of Benders' decomposition ---------------- */
603  	
604  	/** comparison method for sorting the subproblems.
605  	 *  The subproblem that has been called the least is prioritised
606  	 */
607  	static
608  	SCIP_DECL_SORTPTRCOMP(benderssubcompdefault)
609  	{
610  	   SCIP_SUBPROBLEMSOLVESTAT* solvestat1;
611  	   SCIP_SUBPROBLEMSOLVESTAT* solvestat2;
612  	
613  	   assert(elem1 != NULL);
614  	   assert(elem2 != NULL);
615  	
616  	   solvestat1 = (SCIP_SUBPROBLEMSOLVESTAT*)elem1;
617  	   solvestat2 = (SCIP_SUBPROBLEMSOLVESTAT*)elem2;
618  	
619  	   /* prefer subproblems with fewer calls, using the index as tie breaker */
620  	   if( MAX(solvestat1->ncalls, solvestat2->ncalls) == 0 )
621  	      return solvestat1->idx - solvestat2->idx;
622  	   else if( solvestat1->ncalls != solvestat2->ncalls )
623  	      return solvestat1->ncalls - solvestat2->ncalls;
624  	   else
625  	   {
626  	      /* prefer the harder problem (with more average iterations) */
627  	      int avgiterdiff = (int)solvestat2->avgiter - (int)solvestat1->avgiter;
628  	
629  	      if( avgiterdiff != 0 )
630  	         return avgiterdiff;
631  	
632  	      return solvestat1->idx - solvestat2->idx;
633  	   }
634  	
635  	/* the code below does not give a total order of the elements */
636  	#ifdef SCIP_DISABLED_CODE
637  	   if( solvestat1->ncalls == 0 )
638  	      if( solvestat2->ncalls == 0 )
639  	         if( solvestat1->idx < solvestat2->idx )
640  	            return -1;
641  	         else
642  	            return 1;
643  	      else
644  	         return -1;
645  	   else if( solvestat2->ncalls == 0 )
646  	      return 1;
647  	   else
648  	   {
649  	      if( solvestat1->ncalls < solvestat2->ncalls )
650  	         return -1;
651  	      else if( solvestat2->ncalls < solvestat1->ncalls )
652  	         return 1;
653  	      else
654  	      {
655  	         /* we want to execute the hard subproblems first */
656  	         if( solvestat1->avgiter > solvestat2->avgiter )
657  	            return 1;
658  	         else
659  	            return -1;
660  	      }
661  	   }
662  	#endif
663  	}
664  	
665  	/* Local methods */
666  	
667  	/** A workaround for GCG. This is a temp vardata that is set for the auxiliary variables */
668  	struct SCIP_VarData
669  	{
670  	   int                   vartype;             /**< the variable type. In GCG this indicates whether the variable is a
671  	                                               *   master problem or subproblem variable. */
672  	};
673  	
674  	/** adds the auxiliary variables to the Benders' decomposition master problem */
675  	static
676  	SCIP_RETCODE addAuxiliaryVariablesToMaster(
677  	   SCIP*                 scip,               /**< SCIP data structure */
678  	   SCIP_BENDERS*         benders             /**< Benders' decomposition structure */
679  	   )
680  	{
681  	   SCIP_BENDERS* topbenders;        /* the highest priority Benders' decomposition */
682  	   SCIP_VAR* auxiliaryvar;
683  	   SCIP_VARDATA* vardata;
684  	   char varname[SCIP_MAXSTRLEN];    /* the name of the auxiliary variable */
685  	   SCIP_Bool shareauxvars;
686  	   int i;
687  	
688  	   /* this is a workaround for GCG. GCG expects that the variable has vardata when added. So a dummy vardata is created */
689  	   SCIP_CALL( SCIPallocBlockMemory(scip, &vardata) );
690  	   vardata->vartype = -1;
691  	
692  	   /* getting the highest priority Benders' decomposition */
693  	   topbenders = SCIPgetBenders(scip)[0];
694  	
695  	   /* if the current Benders is the highest priority Benders, then we need to create the auxiliary variables.
696  	    * Otherwise, if the shareauxvars flag is set, then the auxiliary variables from the highest priority Benders' are
697  	    * stored with this Benders. */
698  	   shareauxvars = FALSE;
699  	   if( topbenders != benders && SCIPbendersShareAuxVars(benders) )
700  	      shareauxvars = TRUE;
701  	
702  	   for( i = 0; i < SCIPbendersGetNSubproblems(benders); i++ )
703  	   {
704  	      /* if the auxiliary variables are shared, then a pointer to the variable is retrieved from topbenders,
705  	       * otherwise the auxiliaryvariable is created. */
706  	      if( shareauxvars )
707  	      {
708  	         auxiliaryvar = SCIPbendersGetAuxiliaryVar(topbenders, i);
709  	
710  	         SCIP_CALL( SCIPcaptureVar(scip, auxiliaryvar) );
711  	      }
712  	      else
713  	      {
714  	         SCIP_VARTYPE vartype;
715  	
716  	         /* set the variable type of the auxiliary variables to implicit integer if the objective function of the
717  	          * subproblem is guaranteed to be integer. This behaviour is controlled through a user parameter.
718  	          * NOTE: It is only possible to determine if the objective function is integral if the subproblem is defined as
719  	          * a SCIP instance, i.e. not NULL.
720  	          */
721  	         if( benders->auxvarsimplint && SCIPbendersSubproblem(benders, i) != NULL
722  	            && SCIPisObjIntegral(SCIPbendersSubproblem(benders, i)) )
723  	            vartype = SCIP_VARTYPE_IMPLINT;
724  	         else
725  	            vartype = SCIP_VARTYPE_CONTINUOUS;
726  	
727  	         (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s_%d_%s", AUXILIARYVAR_NAME, i, SCIPbendersGetName(benders) );
728  	         SCIP_CALL( SCIPcreateVarBasic(scip, &auxiliaryvar, varname, benders->subproblowerbound[i], SCIPinfinity(scip),
729  	               1.0, vartype) );
730  	
731  	         SCIPvarSetData(auxiliaryvar, vardata);
732  	
733  	         SCIP_CALL( SCIPaddVar(scip, auxiliaryvar) );
734  	
735  	         /* adding the down lock for the Benders' decomposition constraint handler */
736  	         SCIP_CALL( SCIPaddVarLocksType(scip, auxiliaryvar, SCIP_LOCKTYPE_MODEL, 1, 0) );
737  	      }
738  	
739  	      benders->auxiliaryvars[i] = auxiliaryvar;
740  	   }
741  	
742  	   SCIPfreeBlockMemory(scip, &vardata);
743  	
744  	   return SCIP_OKAY;
745  	}
746  	
747  	/** assigns the copied auxiliary variables in the target SCIP to the target Benders' decomposition data */
748  	static
749  	SCIP_RETCODE assignAuxiliaryVariables(
750  	   SCIP*                 scip,               /**< SCIP data structure, the target scip */
751  	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
752  	   )
753  	{
754  	   SCIP_BENDERS* topbenders;        /* the highest priority Benders' decomposition */
755  	   SCIP_VAR* targetvar;
756  	   SCIP_VARDATA* vardata;
757  	   char varname[SCIP_MAXSTRLEN];    /* the name of the auxiliary variable */
758  	   SCIP_Bool shareauxvars;
759  	   int subscipdepth;
760  	   int i;
761  	   int j;
762  	
763  	   assert(scip != NULL);
764  	   assert(benders != NULL);
765  	
766  	   /* this is a workaround for GCG. GCG expects that the variable has vardata when added. So a dummy vardata is created */
767  	   SCIP_CALL( SCIPallocBlockMemory(scip, &vardata) );
768  	   vardata->vartype = -1;
769  	
770  	   /* getting the highest priority Benders' decomposition */
771  	   topbenders = SCIPgetBenders(scip)[0];
772  	
773  	   /* if the auxiliary variable are shared, then the variable name will have a suffix of the highest priority Benders'
774  	    * name. So the shareauxvars flag indicates how to search for the auxiliary variables */
775  	   shareauxvars = FALSE;
776  	   if( topbenders != benders && SCIPbendersShareAuxVars(benders) )
777  	      shareauxvars = TRUE;
778  	
779  	   subscipdepth = SCIPgetSubscipDepth(scip);
780  	
781  	   for( i = 0; i < SCIPbendersGetNSubproblems(benders); i++ )
782  	   {
783  	      char prefix[SCIP_MAXSTRLEN];
784  	      char tmpprefix[SCIP_MAXSTRLEN];
785  	      int len = 1;
786  	
787  	      j = 0;
788  	      targetvar = NULL;
789  	
790  	      /* the prefix for the variable names is required for UG, since we don't know how many copies have been made. To
791  	       * find the target variable, we start with an empty prefix. Then t_ is prepended until the target variable is
792  	       * found
793  	       */
794  	      prefix[0] = '\0';
795  	      while( targetvar == NULL && j <= subscipdepth )
796  	      {
797  	         if( shareauxvars )
798  	            (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s%s_%d_%s", prefix, AUXILIARYVAR_NAME, i, SCIPbendersGetName(topbenders));
799  	         else
800  	            (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s%s_%d_%s", prefix, AUXILIARYVAR_NAME, i, SCIPbendersGetName(benders));
801  	
802  	         /* finding the variable in the copied problem that has the same name as the auxiliary variable */
803  	         targetvar = SCIPfindVar(scip, varname);
804  	
805  	         (void) SCIPsnprintf(tmpprefix, len, "t_%s", prefix);
806  	         len += 2;
807  	         (void) strncpy(prefix, tmpprefix, len); /*lint !e732*/
808  	
809  	         j++;
810  	      }
811  	
812  	      if( targetvar != NULL )
813  	      {
814  	         SCIPvarSetData(targetvar, vardata);
815  	
816  	         benders->auxiliaryvars[i] = SCIPvarGetTransVar(targetvar);
817  	
818  	         SCIP_CALL( SCIPcaptureVar(scip, benders->auxiliaryvars[i]) );
819  	      }
820  	      else
821  	      {
822  	         SCIPABORT();
823  	      }
824  	   }
825  	
826  	   SCIPfreeBlockMemory(scip, &vardata);
827  	
828  	   return SCIP_OKAY;
829  	}
830  	
831  	/** sets the subproblem objective value array to -infinity */
832  	static
833  	void resetSubproblemObjectiveValue(
834  	   SCIP_BENDERS*         benders,            /**< the Benders' decomposition structure */
835  	   SCIP_SET*             set                 /**< global SCIP settings */
836  	   )
837  	{
838  	   SCIP* subproblem;
839  	   SCIP_Real inf;
840  	   int nsubproblems;
841  	   int i;
842  	
843  	   assert(benders != NULL);
844  	
845  	   nsubproblems = SCIPbendersGetNSubproblems(benders);
846  	
847  	   for( i = 0; i < nsubproblems; i++ )
848  	   {
849  	      subproblem = SCIPbendersSubproblem(benders, i);
850  	      if( subproblem != NULL )
851  	         inf = SCIPinfinity(subproblem);
852  	      else
853  	         inf = SCIPsetInfinity(set);
854  	
855  	      SCIPbendersSetSubproblemObjval(benders, i, inf);
856  	   }
857  	}
858  	
859  	/** compares two Benders' decompositions w. r. to their priority */
860  	SCIP_DECL_SORTPTRCOMP(SCIPbendersComp)
861  	{  /*lint --e{715}*/
862  	   return ((SCIP_BENDERS*)elem2)->priority - ((SCIP_BENDERS*)elem1)->priority;
863  	}
864  	
865  	/** comparison method for sorting Benders' decompositions w.r.t. to their name */
866  	SCIP_DECL_SORTPTRCOMP(SCIPbendersCompName)
867  	{
868  	   return strcmp(SCIPbendersGetName((SCIP_BENDERS*)elem1), SCIPbendersGetName((SCIP_BENDERS*)elem2));
869  	}
870  	
871  	/** method to call, when the priority of a Benders' decomposition was changed */
872  	static
873  	SCIP_DECL_PARAMCHGD(paramChgdBendersPriority)
874  	{  /*lint --e{715}*/
875  	   SCIP_PARAMDATA* paramdata;
876  	
877  	   paramdata = SCIPparamGetData(param);
878  	   assert(paramdata != NULL);
879  	
880  	   /* use SCIPsetBendersPriority() to mark the Benders' decompositions as unsorted */
881  	   SCIPsetBendersPriority(scip, (SCIP_BENDERS*)paramdata, SCIPparamGetInt(param)); /*lint !e740*/
882  	
883  	   return SCIP_OKAY;
884  	}
885  	
886  	/** creates a variable mapping between the master problem variables of the source scip and the sub scip */
887  	static
888  	SCIP_RETCODE createMasterVarMapping(
889  	   SCIP_BENDERS*         benders,            /**< Benders' decomposition of the target SCIP instance */
890  	   SCIP_SET*             sourceset,          /**< global SCIP settings from the source SCIP */
891  	   SCIP_HASHMAP*         varmap              /**< a hashmap to store the mapping of source variables corresponding
892  	                                              *   target variables; must not be NULL */
893  	   )
894  	{
895  	   SCIP_VAR** vars;
896  	   SCIP_VAR* targetvar;
897  	   int nvars;
898  	   int i;
899  	
900  	   assert(benders != NULL);
901  	   assert(sourceset != NULL);
902  	   assert(benders->iscopy);
903  	   assert(benders->mastervarsmap == NULL);
904  	
905  	   /* getting the master problem variable data */
906  	   vars = SCIPgetVars(sourceset->scip);
907  	   nvars = SCIPgetNVars(sourceset->scip);
908  	
909  	   /* creating the hashmap for the mapping between the master variable of the target and source scip */
910  	   SCIP_CALL( SCIPhashmapCreate(&benders->mastervarsmap, SCIPblkmem(sourceset->scip), nvars) );
911  	
912  	   for( i = 0; i < nvars; i++ )
913  	   {
914  	      /* getting the variable pointer for the target SCIP variables. The variable mapping returns the target SCIP
915  	       * varibale for a given source SCIP variable. */
916  	      targetvar = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[i]);
917  	      if( targetvar != NULL )
918  	      {
919  	         SCIP_CALL( SCIPhashmapInsert(benders->mastervarsmap, targetvar, vars[i]) );
920  	         SCIP_CALL( SCIPcaptureVar(sourceset->scip, vars[i]) );
921  	      }
922  	   }
923  	
924  	   return SCIP_OKAY;
925  	}
926  	
927  	/** copies the given Benders' decomposition to a new SCIP */
928  	SCIP_RETCODE SCIPbendersCopyInclude(
929  	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
930  	   SCIP_SET*             sourceset,          /**< SCIP_SET of SCIP to copy from */
931  	   SCIP_SET*             targetset,          /**< SCIP_SET of SCIP to copy to */
932  	   SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of source variables corresponding
933  	                                              *   target variables; if NULL, then the transfer of cuts is not possible */
934  	   SCIP_Bool             threadsafe,         /**< must the Benders' decomposition copy be thread safe */
935  	   SCIP_Bool*            valid               /**< was the copying process valid? */
936  	   )
937  	{
938  	   SCIP_BENDERS* targetbenders;  /* the copy of the Benders' decomposition struct in the target set */
939  	   int i;
940  	
941  	   assert(benders != NULL);
942  	   assert(targetset != NULL);
943  	   assert(valid != NULL);
944  	   assert(targetset->scip != NULL);
945  	
946  	   (*valid) = FALSE;
947  	
948  	   if( benders->benderscopy != NULL && targetset->benders_copybenders && SCIPbendersIsActive(benders) )
949  	   {
950  	      SCIPsetDebugMsg(targetset, "including Benders' decomposition %s in subscip %p\n", SCIPbendersGetName(benders), (void*)targetset->scip);
951  	      SCIP_CALL( benders->benderscopy(targetset->scip, benders, threadsafe) );
952  	
953  	      /* copying the Benders' cuts */
954  	      targetbenders = SCIPsetFindBenders(targetset, SCIPbendersGetName(benders));
955  	
956  	      /* storing the pointer to the source scip instance */
957  	      targetbenders->sourcescip = sourceset->scip;
958  	
959  	      /* the flag is set to indicate that the Benders' decomposition is a copy */
960  	      targetbenders->iscopy = TRUE;
961  	
962  	      /* storing whether the lnscheck should be performed */
963  	      targetbenders->lnscheck = benders->lnscheck;
964  	      targetbenders->lnsmaxdepth = benders->lnsmaxdepth;
965  	      targetbenders->lnsmaxcalls = benders->lnsmaxcalls;
966  	      targetbenders->lnsmaxcallsroot = benders->lnsmaxcallsroot;
967  	
968  	      /* storing whether the Benders' copy required thread safety */
969  	      targetbenders->threadsafe = threadsafe;
970  	
971  	      /* calling the copy method for the Benders' cuts */
972  	      SCIPbendersSortBenderscuts(benders);
973  	      for( i = 0; i < benders->nbenderscuts; i++ )
974  	      {
975  	         SCIP_CALL( SCIPbenderscutCopyInclude(targetbenders, benders->benderscuts[i], targetset) );
976  	      }
977  	
978  	      /* When the Benders' decomposition is copied then a variable mapping between the master problem variables is
979  	       * required. This variable mapping is used to transfer the cuts generated in the target SCIP to the source SCIP.
980  	       * The variable map is stored in the target Benders' decomposition. This will be freed when the sub-SCIP is freed.
981  	       */
982  	      if( varmap != NULL )
983  	      {
984  	         SCIP_CALL( createMasterVarMapping(targetbenders, sourceset, varmap) );
985  	      }
986  	
987  	      assert((varmap != NULL && targetbenders->mastervarsmap != NULL)
988  	         || (varmap == NULL && targetbenders->mastervarsmap == NULL));
989  	   }
990  	
991  	   /* if the Benders' decomposition is active, then copy is not valid. */
992  	   (*valid) = !SCIPbendersIsActive(benders);
993  	
994  	   return SCIP_OKAY;
995  	}
996  	
997  	/** internal method for creating a Benders' decomposition structure */
998  	static
999  	SCIP_RETCODE doBendersCreate(
1000 	   SCIP_BENDERS**        benders,            /**< pointer to Benders' decomposition data structure */
1001 	   SCIP_SET*             set,                /**< global SCIP settings */
1002 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
1003 	   BMS_BLKMEM*           blkmem,             /**< block memory for parameter settings */
1004 	   const char*           name,               /**< name of Benders' decomposition */
1005 	   const char*           desc,               /**< description of Benders' decomposition */
1006 	   int                   priority,           /**< priority of the Benders' decomposition */
1007 	   SCIP_Bool             cutlp,              /**< should Benders' cuts be generated for LP solutions */
1008 	   SCIP_Bool             cutpseudo,          /**< should Benders' cuts be generated for pseudo solutions */
1009 	   SCIP_Bool             cutrelax,           /**< should Benders' cuts be generated for relaxation solutions */
1010 	   SCIP_Bool             shareauxvars,       /**< should this Benders' use the highest priority Benders aux vars */
1011 	   SCIP_DECL_BENDERSCOPY ((*benderscopy)),   /**< copy method of Benders' decomposition or NULL if you don't want to copy your plugin into sub-SCIPs */
1012 	   SCIP_DECL_BENDERSFREE ((*bendersfree)),   /**< destructor of Benders' decomposition */
1013 	   SCIP_DECL_BENDERSINIT ((*bendersinit)),   /**< initialize Benders' decomposition */
1014 	   SCIP_DECL_BENDERSEXIT ((*bendersexit)),   /**< deinitialize Benders' decomposition */
1015 	   SCIP_DECL_BENDERSINITPRE((*bendersinitpre)),/**< presolving initialization method for Benders' decomposition */
1016 	   SCIP_DECL_BENDERSEXITPRE((*bendersexitpre)),/**< presolving deinitialization method for Benders' decomposition */
1017 	   SCIP_DECL_BENDERSINITSOL((*bendersinitsol)),/**< solving process initialization method of Benders' decomposition */
1018 	   SCIP_DECL_BENDERSEXITSOL((*bendersexitsol)),/**< solving process deinitialization method of Benders' decomposition */
1019 	   SCIP_DECL_BENDERSGETVAR((*bendersgetvar)),/**< returns the master variable for a given subproblem variable */
1020 	   SCIP_DECL_BENDERSCREATESUB((*benderscreatesub)),/**< creates a Benders' decomposition subproblem */
1021 	   SCIP_DECL_BENDERSPRESUBSOLVE((*benderspresubsolve)),/**< called prior to the subproblem solving loop */
1022 	   SCIP_DECL_BENDERSSOLVESUBCONVEX((*benderssolvesubconvex)),/**< the solving method for convex Benders' decomposition subproblems */
1023 	   SCIP_DECL_BENDERSSOLVESUB((*benderssolvesub)),/**< the solving method for the Benders' decomposition subproblems */
1024 	   SCIP_DECL_BENDERSPOSTSOLVE((*benderspostsolve)),/**< called after the subproblems are solved. */
1025 	   SCIP_DECL_BENDERSFREESUB((*bendersfreesub)),/**< the freeing method for the Benders' decomposition subproblems */
1026 	   SCIP_BENDERSDATA*     bendersdata         /**< Benders' decomposition data */
1027 	   )
1028 	{
1029 	   char paramname[SCIP_MAXSTRLEN];
1030 	   char paramdesc[SCIP_MAXSTRLEN];
1031 	
1032 	   assert(benders != NULL);
1033 	   assert(name != NULL);
1034 	   assert(desc != NULL);
1035 	
1036 	   /* Checking whether the benderssolvesub and the bendersfreesub are both implemented or both are not implemented */
1037 	   if( (benderssolvesubconvex == NULL && benderssolvesub == NULL && bendersfreesub != NULL)
1038 	      || ((benderssolvesubconvex != NULL || benderssolvesub != NULL) && bendersfreesub == NULL) )
1039 	   {
1040 	      SCIPerrorMessage("Benders' decomposition <%s> requires that if bendersFreesub%s is implemented, then at least "
1041 	         "one of bendersSolvesubconvex%s or bendersSolvesub%s are implemented.\n", name, name, name, name);
1042 	      return SCIP_INVALIDCALL;
1043 	   }
1044 	
1045 	   SCIP_ALLOC( BMSallocMemory(benders) );
1046 	   BMSclearMemory(*benders);
1047 	   SCIP_ALLOC( BMSduplicateMemoryArray(&(*benders)->name, name, strlen(name)+1) );
1048 	   SCIP_ALLOC( BMSduplicateMemoryArray(&(*benders)->desc, desc, strlen(desc)+1) );
1049 	   (*benders)->priority = priority;
1050 	   (*benders)->cutlp = cutlp;
1051 	   (*benders)->cutpseudo = cutpseudo;
1052 	   (*benders)->cutrelax = cutrelax;
1053 	   (*benders)->shareauxvars = shareauxvars;
1054 	   (*benders)->benderscopy = benderscopy;
1055 	   (*benders)->bendersfree = bendersfree;
1056 	   (*benders)->bendersinit = bendersinit;
1057 	   (*benders)->bendersexit = bendersexit;
1058 	   (*benders)->bendersinitpre = bendersinitpre;
1059 	   (*benders)->bendersexitpre = bendersexitpre;
1060 	   (*benders)->bendersinitsol = bendersinitsol;
1061 	   (*benders)->bendersexitsol = bendersexitsol;
1062 	   (*benders)->bendersgetvar = bendersgetvar;
1063 	   (*benders)->benderscreatesub = benderscreatesub;
1064 	   (*benders)->benderspresubsolve = benderspresubsolve;
1065 	   (*benders)->benderssolvesubconvex = benderssolvesubconvex;
1066 	   (*benders)->benderssolvesub = benderssolvesub;
1067 	   (*benders)->benderspostsolve = benderspostsolve;
1068 	   (*benders)->bendersfreesub = bendersfreesub;
1069 	   (*benders)->bendersdata = bendersdata;
1070 	   SCIP_CALL( SCIPclockCreate(&(*benders)->setuptime, SCIP_CLOCKTYPE_DEFAULT) );
1071 	   SCIP_CALL( SCIPclockCreate(&(*benders)->bendersclock, SCIP_CLOCKTYPE_DEFAULT) );
1072 	   (*benders)->nlpparam = SCIP_NLPPARAM_DEFAULT(set->scip);  /*lint !e446*/
1073 	
1074 	   /* add parameters */
1075 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/priority", name);
1076 	   (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "priority of Benders' decomposition <%s>", name);
1077 	   SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
1078 	         &(*benders)->priority, FALSE, priority, INT_MIN/4, INT_MAX/4,
1079 	         paramChgdBendersPriority, (SCIP_PARAMDATA*)(*benders)) ); /*lint !e740*/
1080 	
1081 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/cutlp", name);
1082 	   SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
1083 	         "should Benders' cuts be generated for LP solutions?", &(*benders)->cutlp, FALSE, cutlp, NULL, NULL) ); /*lint !e740*/
1084 	
1085 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/cutpseudo", name);
1086 	   SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
1087 	         "should Benders' cuts be generated for pseudo solutions?", &(*benders)->cutpseudo, FALSE, cutpseudo, NULL, NULL) ); /*lint !e740*/
1088 	
1089 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/cutrelax", name);
1090 	   SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
1091 	         "should Benders' cuts be generated for relaxation solutions?", &(*benders)->cutrelax, FALSE, cutrelax, NULL, NULL) ); /*lint !e740*/
1092 	
1093 	   /* These parameters are left for the user to decide in a settings file. This departs from the usual SCIP convention
1094 	    * where the settings available at the creation of the plugin can be set in the function call.
1095 	    */
1096 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/transfercuts", name);
1097 	   SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
1098 	         "should Benders' cuts from LNS heuristics be transferred to the main SCIP instance?", &(*benders)->transfercuts,
1099 	         FALSE, SCIP_DEFAULT_TRANSFERCUTS, NULL, NULL) ); /*lint !e740*/
1100 	
1101 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/lnscheck", name);
1102 	   SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
1103 	         "should Benders' decomposition be used in LNS heurisics?", &(*benders)->lnscheck, FALSE, SCIP_DEFAULT_LNSCHECK,
1104 	         NULL, NULL) ); /*lint !e740*/
1105 	
1106 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/lnsmaxdepth", name);
1107 	   SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
1108 	         "maximum depth at which the LNS check is performed (-1: no limit)", &(*benders)->lnsmaxdepth, TRUE,
1109 	         SCIP_DEFAULT_LNSMAXDEPTH, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
1110 	
1111 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/lnsmaxcalls", name);
1112 	   SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
1113 	         "the maximum number of Benders' decomposition calls in LNS heuristics (-1: no limit)", &(*benders)->lnsmaxcalls,
1114 	         TRUE, SCIP_DEFAULT_LNSMAXCALLS, -1, INT_MAX, NULL, NULL) );
1115 	
1116 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/lnsmaxcallsroot", name);
1117 	   SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
1118 	         "the maximum number of root node Benders' decomposition calls in LNS heuristics (-1: no limit)",
1119 	         &(*benders)->lnsmaxcallsroot, TRUE, SCIP_DEFAULT_LNSMAXCALLSROOT, -1, INT_MAX, NULL, NULL) );
1120 	
1121 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/cutsasconss", name);
1122 	   SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
1123 	         "should the transferred cuts be added as constraints?", &(*benders)->cutsasconss, FALSE,
1124 	         SCIP_DEFAULT_CUTSASCONSS, NULL, NULL) ); /*lint !e740*/
1125 	
1126 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/subprobfrac", name);
1127 	   SCIP_CALL( SCIPsetAddRealParam(set, messagehdlr, blkmem, paramname,
1128 	         "fraction of subproblems that are solved in each iteration", &(*benders)->subprobfrac, FALSE,
1129 	         SCIP_DEFAULT_SUBPROBFRAC, 0.0, 1.0, NULL, NULL) ); /*lint !e740*/
1130 	
1131 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/updateauxvarbound", name);
1132 	   SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
1133 	         "should the auxiliary variable bound be updated by solving the subproblem?", &(*benders)->updateauxvarbound,
1134 	         FALSE, SCIP_DEFAULT_UPDATEAUXVARBOUND, NULL, NULL) ); /*lint !e740*/
1135 	
1136 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/auxvarsimplint", name);
1137 	   SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
1138 	         "if the subproblem objective is integer, then define the auxiliary variables as implicit integers?",
1139 	         &(*benders)->auxvarsimplint, FALSE, SCIP_DEFAULT_AUXVARSIMPLINT, NULL, NULL) ); /*lint !e740*/
1140 	
1141 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/cutcheck", name);
1142 	   SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
1143 	         "should Benders' cuts be generated while checking solutions?",
1144 	         &(*benders)->cutcheck, FALSE, SCIP_DEFAULT_CUTCHECK, NULL, NULL) ); /*lint !e740*/
1145 	
1146 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/cutstrengthenmult", name);
1147 	   SCIP_CALL( SCIPsetAddRealParam(set, messagehdlr, blkmem, paramname,
1148 	         "the convex combination multiplier for the cut strengthening", &(*benders)->convexmult, FALSE,
1149 	         SCIP_DEFAULT_STRENGTHENMULT, 0.0, 1.0, NULL, NULL) ); /*lint !e740*/
1150 	
1151 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/noimprovelimit", name);
1152 	   SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
1153 	         "the maximum number of cut strengthening without improvement", &(*benders)->noimprovelimit, TRUE,
1154 	         SCIP_DEFAULT_NOIMPROVELIMIT, 0, INT_MAX, NULL, NULL) );
1155 	
1156 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/corepointperturb", name);
1157 	   SCIP_CALL( SCIPsetAddRealParam(set, messagehdlr, blkmem, paramname,
1158 	         "the constant use to perturb the cut strengthening core point", &(*benders)->perturbeps, FALSE,
1159 	         SCIP_DEFAULT_STRENGTHENPERTURB, 0.0, 1.0, NULL, NULL) ); /*lint !e740*/
1160 	
1161 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/cutstrengthenenabled", name);
1162 	   SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
1163 	         "should the core point cut strengthening be employed (only applied to fractional solutions or continuous subproblems)?",
1164 	         &(*benders)->strengthenenabled, FALSE, SCIP_DEFAULT_STRENGTHENENABLED, NULL, NULL) ); /*lint !e740*/
1165 	
1166 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/cutstrengthenintpoint", name);
1167 	   SCIP_CALL( SCIPsetAddCharParam(set, messagehdlr, blkmem, paramname,
1168 	         "where should the strengthening interior point be sourced from ('l'p relaxation, 'f'irst solution, 'i'ncumbent solution, 'r'elative interior point, vector of 'o'nes, vector of 'z'eros)",
1169 	         &(*benders)->strengthenintpoint, FALSE, SCIP_DEFAULT_STRENGTHENINTPOINT, "lfiroz", NULL, NULL) ); /*lint !e740*/
1170 	
1171 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/numthreads", name);
1172 	   SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
1173 	         "the number of threads to use when solving the subproblems", &(*benders)->numthreads, TRUE,
1174 	         SCIP_DEFAULT_NUMTHREADS, 1, INT_MAX, NULL, NULL) );
1175 	
1176 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/execfeasphase", name);
1177 	   SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
1178 	         "should a feasibility phase be executed during the root node, i.e. adding slack variables to constraints to ensure feasibility",
1179 	         &(*benders)->execfeasphase, FALSE, SCIP_DEFAULT_EXECFEASPHASE, NULL, NULL) ); /*lint !e740*/
1180 	
1181 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/slackvarcoef", name);
1182 	   SCIP_CALL( SCIPsetAddRealParam(set, messagehdlr, blkmem, paramname,
1183 	         "the initial objective coefficient of the slack variables in the subproblem", &(*benders)->slackvarcoef, FALSE,
1184 	         SCIP_DEFAULT_SLACKVARCOEF, 0.0, SCIPsetInfinity(set), NULL, NULL) ); /*lint !e740*/
1185 	
1186 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/maxslackvarcoef", name);
1187 	   SCIP_CALL( SCIPsetAddRealParam(set, messagehdlr, blkmem, paramname,
1188 	         "the maximal objective coefficient of the slack variables in the subproblem", &(*benders)->maxslackvarcoef, FALSE,
1189 	         SCIP_DEFAULT_MAXSLACKVARCOEF, 0.0, SCIPsetInfinity(set), NULL, NULL) ); /*lint !e740*/
1190 	
1191 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/checkconsconvexity", name);
1192 	   SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
1193 	         "should the constraints of the subproblems be checked for convexity?", &(*benders)->checkconsconvexity, FALSE,
1194 	         SCIP_DEFAULT_CHECKCONSCONVEXITY, NULL, NULL) ); /*lint !e740*/
1195 	
1196 	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/nlpiterlimit", name);
1197 	   SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
1198 	         "iteration limit for NLP solver", &(*benders)->nlpparam.iterlimit, FALSE,
1199 	         SCIP_DEFAULT_NLPITERLIMIT, 0, INT_MAX, NULL, NULL) ); /*lint !e740*/
1200 	
1201 	   return SCIP_OKAY;
1202 	}
1203 	
1204 	/** creates a Benders' decomposition structure
1205 	 *
1206 	 *  To use the Benders' decomposition for solving a problem, it first has to be activated with a call to SCIPactivateBenders().
1207 	 */
1208 	SCIP_RETCODE SCIPbendersCreate(
1209 	   SCIP_BENDERS**        benders,            /**< pointer to Benders' decomposition data structure */
1210 	   SCIP_SET*             set,                /**< global SCIP settings */
1211 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
1212 	   BMS_BLKMEM*           blkmem,             /**< block memory for parameter settings */
1213 	   const char*           name,               /**< name of Benders' decomposition */
1214 	   const char*           desc,               /**< description of Benders' decomposition */
1215 	   int                   priority,           /**< priority of the Benders' decomposition */
1216 	   SCIP_Bool             cutlp,              /**< should Benders' cuts be generated for LP solutions */
1217 	   SCIP_Bool             cutpseudo,          /**< should Benders' cuts be generated for pseudo solutions */
1218 	   SCIP_Bool             cutrelax,           /**< should Benders' cuts be generated for relaxation solutions */
1219 	   SCIP_Bool             shareauxvars,       /**< should this Benders' use the highest priority Benders aux vars */
1220 	   SCIP_DECL_BENDERSCOPY ((*benderscopy)),   /**< copy method of Benders' decomposition or NULL if you don't want to copy your plugin into sub-SCIPs */
1221 	   SCIP_DECL_BENDERSFREE ((*bendersfree)),   /**< destructor of Benders' decomposition */
1222 	   SCIP_DECL_BENDERSINIT ((*bendersinit)),   /**< initialize Benders' decomposition */
1223 	   SCIP_DECL_BENDERSEXIT ((*bendersexit)),   /**< deinitialize Benders' decomposition */
1224 	   SCIP_DECL_BENDERSINITPRE((*bendersinitpre)),/**< presolving initialization method for Benders' decomposition */
1225 	   SCIP_DECL_BENDERSEXITPRE((*bendersexitpre)),/**< presolving deinitialization method for Benders' decomposition */
1226 	   SCIP_DECL_BENDERSINITSOL((*bendersinitsol)),/**< solving process initialization method of Benders' decomposition */
1227 	   SCIP_DECL_BENDERSEXITSOL((*bendersexitsol)),/**< solving process deinitialization method of Benders' decomposition */
1228 	   SCIP_DECL_BENDERSGETVAR((*bendersgetvar)),/**< returns the master variable for a given subproblem variable */
1229 	   SCIP_DECL_BENDERSCREATESUB((*benderscreatesub)),/**< creates a Benders' decomposition subproblem */
1230 	   SCIP_DECL_BENDERSPRESUBSOLVE((*benderspresubsolve)),/**< called prior to the subproblem solving loop */
1231 	   SCIP_DECL_BENDERSSOLVESUBCONVEX((*benderssolvesubconvex)),/**< the solving method for convex Benders' decomposition subproblems */
1232 	   SCIP_DECL_BENDERSSOLVESUB((*benderssolvesub)),/**< the solving method for the Benders' decomposition subproblems */
1233 	   SCIP_DECL_BENDERSPOSTSOLVE((*benderspostsolve)),/**< called after the subproblems are solved. */
1234 	   SCIP_DECL_BENDERSFREESUB((*bendersfreesub)),/**< the freeing method for the Benders' decomposition subproblems */
1235 	   SCIP_BENDERSDATA*     bendersdata         /**< Benders' decomposition data */
1236 	   )
1237 	{
1238 	   assert(benders != NULL);
1239 	   assert(name != NULL);
1240 	   assert(desc != NULL);
1241 	
1242 	   SCIP_CALL_FINALLY( doBendersCreate(benders, set, messagehdlr, blkmem, name, desc, priority, cutlp, cutpseudo,
1243 	         cutrelax, shareauxvars, benderscopy, bendersfree, bendersinit, bendersexit, bendersinitpre, bendersexitpre,
1244 	         bendersinitsol, bendersexitsol, bendersgetvar, benderscreatesub, benderspresubsolve, benderssolvesubconvex,
1245 	         benderssolvesub, benderspostsolve, bendersfreesub, bendersdata), (void) SCIPbendersFree(benders, set) );
1246 	
1247 	   return SCIP_OKAY;
1248 	}
1249 	
1250 	
1251 	/** releases the variables that have been captured in the hashmap */
1252 	static
1253 	SCIP_RETCODE releaseVarMappingHashmapVars(
1254 	   SCIP*                 scip,               /**< the SCIP data structure */
1255 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
1256 	   )
1257 	{
1258 	   int nentries;
1259 	   int i;
1260 	
1261 	   assert(scip != NULL);
1262 	   assert(benders != NULL);
1263 	
1264 	   assert(benders->mastervarsmap != NULL);
1265 	
1266 	   nentries = SCIPhashmapGetNEntries(benders->mastervarsmap);
1267 	
1268 	   for( i = 0; i < nentries; ++i )
1269 	   {
1270 	      SCIP_HASHMAPENTRY* entry;
1271 	      entry = SCIPhashmapGetEntry(benders->mastervarsmap, i);
1272 	
1273 	      if( entry != NULL )
1274 	      {
1275 	         SCIP_VAR* var;
1276 	         var = (SCIP_VAR*) SCIPhashmapEntryGetImage(entry);
1277 	
1278 	         SCIP_CALL( SCIPreleaseVar(scip, &var) );
1279 	      }
1280 	   }
1281 	
1282 	   return SCIP_OKAY;
1283 	}
1284 	
1285 	
1286 	/** calls destructor and frees memory of Benders' decomposition */
1287 	SCIP_RETCODE SCIPbendersFree(
1288 	   SCIP_BENDERS**        benders,            /**< pointer to Benders' decomposition data structure */
1289 	   SCIP_SET*             set                 /**< global SCIP settings */
1290 	   )
1291 	{
1292 	   int i;
1293 	
1294 	   assert(benders != NULL);
1295 	   assert(*benders != NULL);
1296 	   assert(!(*benders)->initialized);
1297 	   assert(set != NULL);
1298 	
1299 	   /* call destructor of Benders' decomposition */
1300 	   if( (*benders)->bendersfree != NULL )
1301 	   {
1302 	      SCIP_CALL( (*benders)->bendersfree(set->scip, *benders) );
1303 	   }
1304 	
1305 	   /* if the Benders' decomposition is a copy and a varmap has been passed to SCIP_BENDERS, then the variable map
1306 	    * between the source and the target SCIP needs to be freed.
1307 	    */
1308 	   if( (*benders)->iscopy && (*benders)->mastervarsmap != NULL )
1309 	   {
1310 	      SCIP_CALL( releaseVarMappingHashmapVars((*benders)->sourcescip, (*benders)) );
1311 	      SCIPhashmapFree(&(*benders)->mastervarsmap);
1312 	   }
1313 	
1314 	   /* freeing the Benders' cuts */
1315 	   for( i = 0; i < (*benders)->nbenderscuts; i++ )
1316 	   {
1317 	      SCIP_CALL( SCIPbenderscutFree(&((*benders)->benderscuts[i]), set) );
1318 	   }
1319 	   BMSfreeMemoryArrayNull(&(*benders)->benderscuts);
1320 	
1321 	   SCIPclockFree(&(*benders)->bendersclock);
1322 	   SCIPclockFree(&(*benders)->setuptime);
1323 	   BMSfreeMemoryArray(&(*benders)->name);
1324 	   BMSfreeMemoryArray(&(*benders)->desc);
1325 	   BMSfreeMemory(benders);
1326 	
1327 	   return SCIP_OKAY;
1328 	}
1329 	
1330 	/* adds a slack variable to the given constraint */
1331 	static
1332 	SCIP_RETCODE addSlackVars(
1333 	   SCIP*                 scip,               /**< the SCIP data structure */
1334 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
1335 	   SCIP_CONS*            cons,               /**< constraint to which the slack variable(s) is added to */
1336 	   SCIP_CONSHDLR**       linearconshdlrs,    /**< an array storing the linear constraint handlers */
1337 	   SCIP_CONSHDLR*        nlconshdlr,         /**< pointer to the nonlinear constraint handler */
1338 	   int                   nlinearconshdlrs    /**< the number of linear constraint handlers */
1339 	   )
1340 	{
1341 	   SCIP_CONSHDLR* conshdlr;
1342 	   SCIP_VAR* var;
1343 	   SCIP_Real rhs;
1344 	   SCIP_Real lhs;
1345 	   SCIP_Real objcoef;
1346 	   int i;
1347 	   SCIP_Bool linearcons;
1348 	   SCIP_Bool success;
1349 	   char name[SCIP_MAXSTRLEN];
1350 	
1351 	   conshdlr = SCIPconsGetHdlr(cons);
1352 	
1353 	   /* assume that the constraint is not linear, then we check whether it is linear */
1354 	   linearcons = FALSE;
1355 	
1356 	   /* checking whether the constraint is a linear constraint. If so, we add a coefficient to the constraint */
1357 	   for( i = 0; i < nlinearconshdlrs; ++i )
1358 	   {
1359 	      if( conshdlr == linearconshdlrs[i] )
1360 	      {
1361 	         linearcons = TRUE;
1362 	         break;
1363 	      }
1364 	   }
1365 	
1366 	   if( !linearcons && conshdlr != nlconshdlr )
1367 	   {
1368 	      SCIPwarningMessage(scip, "The subproblem includes constraint <%s>. "
1369 	         "This is not supported and the slack variable will not be added to the constraint. Feasibility cuts may be invalid.\n",
1370 	         SCIPconshdlrGetName(conshdlr));
1371 	   }
1372 	
1373 	   if( linearcons )
1374 	   {
1375 	      rhs = SCIPconsGetRhs(scip, cons, &success);
1376 	      assert(success);
1377 	      lhs = SCIPconsGetLhs(scip, cons, &success);
1378 	      assert(success);
1379 	   }
1380 	   else
1381 	   {
1382 	      rhs = SCIPgetRhsNonlinear(cons);
1383 	      lhs = SCIPgetLhsNonlinear(cons);
1384 	   }
1385 	
1386 	   /* getting the objective coefficient for the slack variables */
1387 	   objcoef = benders->slackvarcoef;
1388 	
1389 	   /* if the right hand side is finite, then we need to add a slack variable with a negative coefficient */
1390 	   if( !SCIPisInfinity(scip, rhs) )
1391 	   {
1392 	      (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%s_neg", SLACKVAR_NAME, SCIPconsGetName(cons) );
1393 	
1394 	      SCIP_CALL( SCIPcreateVarBasic(scip, &var, name, 0.0, SCIPinfinity(scip), objcoef, SCIP_VARTYPE_CONTINUOUS) );
1395 	
1396 	      /* adding the slack variable to the subproblem */
1397 	      SCIP_CALL( SCIPaddVar(scip, var) );
1398 	
1399 	      /* adds the slack variable to the constraint */
1400 	      if( linearcons )
1401 	      {
1402 	         SCIP_CALL( SCIPconsAddCoef(scip, cons, var, -1.0) );
1403 	      }
1404 	      else
1405 	      {
1406 	         SCIP_CALL( SCIPaddLinearVarNonlinear(scip, cons, var, -1.0) );
1407 	      }
1408 	
1409 	      /* releasing the variable */
1410 	      SCIP_CALL( SCIPreleaseVar(scip, &var) );
1411 	   }
1412 	
1413 	   /* if the left hand side if finite, then we need to add a slack variable with a positive coefficient */
1414 	   if( !SCIPisInfinity(scip, -lhs) )
1415 	   {
1416 	      (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%s_pos", SLACKVAR_NAME, SCIPconsGetName(cons) );
1417 	
1418 	      SCIP_CALL( SCIPcreateVarBasic(scip, &var, name, 0.0, SCIPinfinity(scip), objcoef, SCIP_VARTYPE_CONTINUOUS) );
1419 	
1420 	      /* adding the slack variable to the subproblem */
1421 	      SCIP_CALL( SCIPaddVar(scip, var) );
1422 	
1423 	      /* adds the slack variable to the constraint */
1424 	      if( linearcons )
1425 	      {
1426 	         SCIP_CALL( SCIPconsAddCoef(scip, cons, var, 1.0) );
1427 	      }
1428 	      else
1429 	      {
1430 	         SCIP_CALL( SCIPaddLinearVarNonlinear(scip, cons, var, 1.0) );
1431 	      }
1432 	
1433 	      /* releasing the variable */
1434 	      SCIP_CALL( SCIPreleaseVar(scip, &var) );
1435 	   }
1436 	
1437 	   return SCIP_OKAY;
1438 	}
1439 	
1440 	/** adds the slack variables to each of the constraints for the generation of feasibility cuts for the given non-linear
1441 	 * subproblem
1442 	 */
1443 	static
1444 	SCIP_RETCODE addSlackVarsToConstraints(
1445 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
1446 	   SCIP_SET*             set,                /**< global SCIP settings */
1447 	   int                   probnumber          /**< the subproblem number */
1448 	   )
1449 	{
1450 	   SCIP* subproblem;
1451 	   SCIP_CONSHDLR* linearconshdlrs[NLINEARCONSHDLRS];
1452 	   SCIP_CONSHDLR* nlconshdlr;
1453 	   SCIP_CONS* cons;
1454 	   int i;
1455 	
1456 	   assert(benders != NULL);
1457 	   assert(set != NULL);
1458 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
1459 	
1460 	   subproblem = SCIPbendersSubproblem(benders, probnumber);
1461 	
1462 	   /* get pointers to linear constraints handlers, so can avoid string comparisons */
1463 	   linearconshdlrs[0] = SCIPfindConshdlr(subproblem, "knapsack");
1464 	   linearconshdlrs[1] = SCIPfindConshdlr(subproblem, "linear");
1465 	   linearconshdlrs[2] = SCIPfindConshdlr(subproblem, "logicor");
1466 	   linearconshdlrs[3] = SCIPfindConshdlr(subproblem, "setppc");
1467 	   linearconshdlrs[4] = SCIPfindConshdlr(subproblem, "varbound");
1468 	
1469 	   nlconshdlr = SCIPfindConshdlr(subproblem, "nonlinear");
1470 	
1471 	   for( i = 0; i < SCIPgetNOrigConss(subproblem); ++i )
1472 	   {
1473 	      cons = SCIPgetOrigConss(subproblem)[i];
1474 	
1475 	      /* adding the slack variables to the constraint */
1476 	      SCIP_CALL( addSlackVars(subproblem, benders, cons, linearconshdlrs, nlconshdlr, NLINEARCONSHDLRS) );
1477 	   }
1478 	
1479 	   return SCIP_OKAY;
1480 	}
1481 	
1482 	/** initialises a MIP subproblem by putting the problem into SCIP_STAGE_SOLVING. This is achieved by calling SCIPsolve
1483 	 *  and then interrupting the solve in a node focus event handler.
1484 	 *  The LP subproblem is also initialised using this method; however, a different event handler is added. This event
1485 	 *  handler will put the LP subproblem into probing mode.
1486 	 *  The MIP solving function is called to initialise the subproblem because this function calls SCIPsolve with the
1487 	 *  appropriate parameter settings for Benders' decomposition.
1488 	 */
1489 	static
1490 	SCIP_RETCODE initialiseSubproblem(
1491 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
1492 	   SCIP_SET*             set,                /**< global SCIP settings */
1493 	   int                   probnumber,         /**< the subproblem number */
1494 	   SCIP_Bool*            success             /**< was the initialisation process successful */
1495 	   )
1496 	{
1497 	   SCIP* subproblem;
1498 	   SCIP_STATUS solvestatus;
1499 	   SCIP_Bool cutoff;
1500 	
1501 	   assert(benders != NULL);
1502 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
1503 	   assert(success != NULL);
1504 	
1505 	   (*success) = FALSE;
1506 	
1507 	   subproblem = SCIPbendersSubproblem(benders, probnumber);
1508 	   assert(subproblem != NULL);
1509 	
1510 	   /* Getting the problem into the right SCIP stage for solving */
1511 	   SCIP_CALL( SCIPbendersSolveSubproblemCIP(set->scip, benders, probnumber, &solvestatus, FALSE) );
1512 	
1513 	   /* Constructing the LP that can be solved in later iterations */
1514 	   if( solvestatus != SCIP_STATUS_BESTSOLLIMIT && solvestatus != SCIP_STATUS_TIMELIMIT
1515 	      && solvestatus != SCIP_STATUS_MEMLIMIT )
1516 	   {
1517 	      assert(SCIPgetStage(subproblem) == SCIP_STAGE_SOLVING);
1518 	
1519 	      SCIP_CALL( SCIPconstructLP(subproblem, &cutoff) );
1520 	      (*success) = TRUE;
1521 	   }
1522 	
1523 	   return SCIP_OKAY;
1524 	}
1525 	
1526 	
1527 	/** initialises an LP subproblem by putting the problem into probing mode. The probing mode is invoked in a node focus
1528 	 *  event handler. This event handler is added just prior to calling the initialise subproblem function.
1529 	 */
1530 	static
1531 	SCIP_RETCODE initialiseLPSubproblem(
1532 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
1533 	   SCIP_SET*             set,                /**< global SCIP settings */
1534 	   int                   probnumber          /**< the subproblem number */
1535 	   )
1536 	{
1537 	   SCIP* subproblem;
1538 	   SCIP_EVENTHDLR* eventhdlr;
1539 	   SCIP_EVENTHDLRDATA* eventhdlrdata;
1540 	   SCIP_Bool success;
1541 	
1542 	   assert(benders != NULL);
1543 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
1544 	
1545 	   subproblem = SCIPbendersSubproblem(benders, probnumber);
1546 	   assert(subproblem != NULL);
1547 	
1548 	   /* include event handler into SCIP */
1549 	   SCIP_CALL( SCIPallocBlockMemory(subproblem, &eventhdlrdata) );
1550 	
1551 	   SCIP_CALL( initEventhandlerData(subproblem, eventhdlrdata) );
1552 	
1553 	   SCIP_CALL( SCIPincludeEventhdlrBasic(subproblem, &eventhdlr, NODEFOCUS_EVENTHDLR_NAME, NODEFOCUS_EVENTHDLR_DESC,
1554 	         eventExecBendersNodefocus, eventhdlrdata) );
1555 	   SCIP_CALL( SCIPsetEventhdlrInitsol(subproblem, eventhdlr, eventInitsolBendersNodefocus) );
1556 	   SCIP_CALL( SCIPsetEventhdlrExitsol(subproblem, eventhdlr, eventExitsolBendersNodefocus) );
1557 	   SCIP_CALL( SCIPsetEventhdlrExit(subproblem, eventhdlr, eventExitBendersNodefocus) );
1558 	   SCIP_CALL( SCIPsetEventhdlrFree(subproblem, eventhdlr, eventFreeBendersNodefocus) );
1559 	   assert(eventhdlr != NULL);
1560 	
1561 	   /* calling an initial solve to put the problem into probing mode */
1562 	   SCIP_CALL( initialiseSubproblem(benders, set, probnumber, &success) );
1563 	
1564 	   return SCIP_OKAY; /*lint !e438*/
1565 	}
1566 	
1567 	/** checks whether the convex relaxation of the subproblem is sufficient to solve the original problem to optimality
1568 	 *
1569 	 * We check whether we can conclude that the CIP is actually an LP or a convex NLP.
1570 	 * To do this, we check that all variables are of continuous type and that every constraint is either handled by known
1571 	 * linear constraint handler (knapsack, linear, logicor, setppc, varbound) or the nonlinear constraint handler.
1572 	 * In the latter case, we also check whether the nonlinear constraint is convex.
1573 	 * Further, nonlinear constraints are only considered if an NLP solver interface is available, i.e., and NLP could
1574 	 * be solved.
1575 	 * If constraints are present that cannot be identified as linear or convex nonlinear, then we assume that the
1576 	 * problem is not convex, thus solving its LP or NLP relaxation will not be sufficient.
1577 	 */
1578 	static
1579 	SCIP_RETCODE checkSubproblemConvexity(
1580 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
1581 	   SCIP_SET*             set,                /**< global SCIP settings */
1582 	   int                   probnumber          /**< the subproblem number, or -1 for the master problem */
1583 	   )
1584 	{
1585 	   SCIP* subproblem;
1586 	   SCIP_CONSHDLR* conshdlr;
1587 	   SCIP_CONS* cons;
1588 	   SCIP_HASHMAP* assumevarfixed;
1589 	   SCIP_VAR** vars;
1590 	   int nvars;
1591 	   int nbinvars;
1592 	   int nintvars;
1593 	   int nimplintvars;
1594 	   int i;
1595 	   int j;
1596 	   SCIP_Bool convexcons;
1597 	   SCIP_Bool discretevar;
1598 	   SCIP_Bool isnonlinear;
1599 	   SCIP_CONSHDLR* linearconshdlrs[NLINEARCONSHDLRS];
1600 	   SCIP_CONSHDLR* nlconshdlr = NULL;
1601 	
1602 	   assert(benders != NULL);
1603 	   assert(set != NULL);
1604 	   assert(probnumber >= -1 && probnumber < SCIPbendersGetNSubproblems(benders));
1605 	
1606 	   assumevarfixed = NULL;
1607 	   if( probnumber >= 0 )
1608 	      subproblem = SCIPbendersSubproblem(benders, probnumber);
1609 	   else
1610 	      subproblem = set->scip;
1611 	
1612 	   assert(subproblem != NULL);
1613 	
1614 	   convexcons = FALSE;
1615 	   discretevar = FALSE;
1616 	   isnonlinear = FALSE;
1617 	
1618 	   /* getting the number of integer and binary variables to determine the problem type */
1619 	   SCIP_CALL( SCIPgetVarsData(subproblem, &vars, &nvars, &nbinvars, &nintvars, &nimplintvars, NULL) );
1620 	
1621 	   /* if there are any binary, integer or implicit integer variables, then the subproblems is marked as non-convex */
1622 	   if( nbinvars != 0 || nintvars != 0 || nimplintvars != 0 )
1623 	   {
1624 	      discretevar = TRUE;
1625 	   }
1626 	
1627 	   /* get pointers to linear constraints handlers, so can avoid string comparisons */
1628 	   linearconshdlrs[0] = SCIPfindConshdlr(subproblem, "knapsack");
1629 	   linearconshdlrs[1] = SCIPfindConshdlr(subproblem, "linear");
1630 	   linearconshdlrs[2] = SCIPfindConshdlr(subproblem, "logicor");
1631 	   linearconshdlrs[3] = SCIPfindConshdlr(subproblem, "setppc");
1632 	   linearconshdlrs[4] = SCIPfindConshdlr(subproblem, "varbound");
1633 	
1634 	   /* Get pointer to the nonlinear constraint handler if we also have an NLP solver to solve NLPs.
1635 	    * If there is no NLP solver, but there are (convex) nonlinear constraints, then the LP relaxation of subproblems
1636 	    * will (currently) not be sufficient to solve subproblems to optimality. Thus, we also take the presence of convex
1637 	    * nonlinear constraints as signal for having to solve the CIP eventually, thus, by abuse of notation,
1638 	    * return not-convex here. In summary, we do not need to have a special look onto non-linear constraints
1639 	    * if no NLP solver is present, and can treat them as any other constraint that is not of linear type.
1640 	    */
1641 	   if( SCIPgetNNlpis(subproblem) > 0 )
1642 	   {
1643 	      nlconshdlr = SCIPfindConshdlr(subproblem, "nonlinear");
1644 	   }
1645 	
1646 	   /* if the nonlinear constraint handler exists, then we create a hashmap of variables that can be assumed to be fixed.
1647 	    * These variables correspond to the copies of the master variables in the subproblem
1648 	    */
1649 	   if( probnumber >= 0 && nlconshdlr != NULL )
1650 	   {
1651 	      SCIP_VAR* mappedvar;
1652 	
1653 	      SCIP_CALL( SCIPhashmapCreate(&assumevarfixed, SCIPblkmem(set->scip), SCIPgetNVars(subproblem)) );
1654 	
1655 	      /* finding the subproblem variables that correspond to master variables */
1656 	      for( i = 0; i < nvars; i++ )
1657 	      {
1658 	         /* getting the corresponding master problem variable for the given variable */
1659 	         SCIP_CALL( SCIPbendersGetVar(benders, set, vars[i], &mappedvar, -1) );
1660 	
1661 	         /* if the mapped variable is not NULL, then it must be stored as a possible fixed variable */
1662 	         if( mappedvar != NULL )
1663 	         {
1664 	            SCIP_CALL( SCIPhashmapInsert(assumevarfixed, vars[i], vars[i]) );
1665 	         }
1666 	      }
1667 	   }
1668 	
1669 	   for( i = 0; i < SCIPgetNOrigConss(subproblem); ++i )
1670 	   {
1671 	      cons = SCIPgetOrigConss(subproblem)[i];
1672 	      conshdlr = SCIPconsGetHdlr(cons);
1673 	
1674 	      for( j = 0; j < NLINEARCONSHDLRS; ++j )
1675 	         if( conshdlr == linearconshdlrs[j] )
1676 	            break;
1677 	
1678 	      /* if linear constraint, then we are good */
1679 	      if( j < NLINEARCONSHDLRS )
1680 	      {
1681 	#ifdef SCIP_MOREDEBUG
1682 	         SCIPdebugMsg(subproblem, "subproblem <%s>: constraint <%s> is linear\n", SCIPgetProbName(subproblem), SCIPconsGetName(cons));
1683 	#endif
1684 	         continue;
1685 	      }
1686 	
1687 	      /* if cons_nonlinear (and nlconshdlr != NULL), then check whether convex */
1688 	      if( conshdlr == nlconshdlr )
1689 	      {
1690 	         SCIP_Bool isconvex;
1691 	         SCIP_EXPRCURV curv;
1692 	         SCIP_Bool havelhs;
1693 	         SCIP_Bool haverhs;
1694 	
1695 	         isnonlinear = TRUE;
1696 	
1697 	         havelhs = !SCIPisInfinity(subproblem, -SCIPgetLhsNonlinear(cons));
1698 	         haverhs = !SCIPisInfinity(subproblem,  SCIPgetRhsNonlinear(cons));
1699 	         if( havelhs && haverhs )
1700 	         {
1701 	            isconvex = FALSE;
1702 	         }
1703 	         else
1704 	         {
1705 	            /* look at curvature stored in cons, though at this stage this will be unknown a.a. */
1706 	            curv = SCIPgetCurvatureNonlinear(cons);
1707 	            isconvex = ((!havelhs || (curv & SCIP_EXPRCURV_CONCAVE) == SCIP_EXPRCURV_CONCAVE)) &&
1708 	                ((!haverhs || (curv & SCIP_EXPRCURV_CONVEX) == SCIP_EXPRCURV_CONVEX));
1709 	
1710 	            if( !isconvex )
1711 	            {
1712 	               /* if not found convex, compute curvature via nlhdlr_convex and decide again */
1713 	
1714 	               /* make sure activities are up to date. SCIPhasExprCurvature currently assumes that this is already the case */
1715 	               SCIP_CALL( SCIPevalExprActivity(subproblem, SCIPgetExprNonlinear(cons)) );
1716 	
1717 	               SCIP_CALL( SCIPhasExprCurvature(subproblem, SCIPgetExprNonlinear(cons), havelhs ? SCIP_EXPRCURV_CONCAVE : SCIP_EXPRCURV_CONVEX, &isconvex, assumevarfixed) );
1718 	            }
1719 	         }
1720 	
1721 	         if( isconvex )
1722 	         {
1723 	#ifdef SCIP_MOREDEBUG
1724 	            SCIPdebugMsg(subproblem, "subproblem <%s>: nonlinear constraint <%s> is convex\n", SCIPgetProbName(subproblem), SCIPconsGetName(cons));
1725 	#endif
1726 	            continue;
1727 	         }
1728 	         else
1729 	         {
1730 	#ifdef SCIP_MOREDEBUG
1731 	            SCIPdebugMsg(subproblem, "subproblem <%s>: nonlinear constraint <%s> not convex\n", SCIPgetProbName(subproblem), SCIPconsGetName(cons));
1732 	#endif
1733 	            goto TERMINATE;
1734 	         }
1735 	      }
1736 	
1737 	#ifdef SCIP_MOREDEBUG
1738 	      SCIPdebugMsg(subproblem, "subproblem <%s>: potentially nonconvex constraint <%s>\n", SCIPgetProbName(subproblem), SCIPconsGetName(cons));
1739 	#endif
1740 	      goto TERMINATE;
1741 	   }
1742 	
1743 	   /* if we made it until here, then all constraints are known and convex */
1744 	   convexcons = TRUE;
1745 	
1746 	TERMINATE:
1747 	   /* setting the flag for the convexity of the subproblem. If convexity doesn't need to be checked, then it is assumed
1748 	    * that the subproblems are convex. However, if there are discrete variables, then the problem must be set as
1749 	    * non-convex. The discrete master variables will be changed to continuous, but this will happen at the first call to
1750 	    * SCIPbendersSetupSubproblem
1751 	    */
1752 	   if( probnumber >= 0 )
1753 	   {
1754 	      convexcons = convexcons || !benders->checkconsconvexity;
1755 	
1756 	      if( convexcons && !discretevar )
1757 	         SCIPbendersSetSubproblemType(benders, probnumber, SCIP_BENDERSSUBTYPE_CONVEXCONT);
1758 	      else if( convexcons && discretevar )
1759 	         SCIPbendersSetSubproblemType(benders, probnumber, SCIP_BENDERSSUBTYPE_CONVEXDIS);
1760 	      else if( !convexcons && !discretevar )
1761 	         SCIPbendersSetSubproblemType(benders, probnumber, SCIP_BENDERSSUBTYPE_NONCONVEXCONT);
1762 	      else if( !convexcons && discretevar )
1763 	         SCIPbendersSetSubproblemType(benders, probnumber, SCIP_BENDERSSUBTYPE_NONCONVEXDIS);
1764 	      else
1765 	         SCIPABORT();
1766 	   }
1767 	
1768 	   /* setting the non-linear subproblem flag */
1769 	   if( probnumber >= 0 )
1770 	      SCIPbendersSetSubproblemIsNonlinear(benders, probnumber, isnonlinear);
1771 	   else
1772 	      SCIPbendersSetMasterIsNonlinear(benders, isnonlinear);
1773 	
1774 	   if( probnumber >= 0 )
1775 	   {
1776 	      SCIPsetDebugMsg(set, "subproblem <%s> has been found to be of type %d\n", SCIPgetProbName(subproblem),
1777 	         SCIPbendersGetSubproblemType(benders, probnumber));
1778 	   }
1779 	
1780 	   /* releasing the fixed variable hashmap */
1781 	   if( assumevarfixed != NULL )
1782 	      SCIPhashmapFree(&assumevarfixed);
1783 	
1784 	   return SCIP_OKAY;
1785 	}
1786 	
1787 	/** creates the subproblems and registers it with the Benders' decomposition struct */
1788 	static
1789 	SCIP_RETCODE createSubproblems(
1790 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
1791 	   SCIP_SET*             set                 /**< global SCIP settings */
1792 	   )
1793 	{
1794 	   SCIP* subproblem;
1795 	   SCIP_EVENTHDLR* eventhdlr;
1796 	   SCIP_VAR* mastervar;
1797 	   SCIP_VAR** vars;
1798 	   int nvars;
1799 	   int nsubproblems;
1800 	   int i;
1801 	   int j;
1802 	
1803 	   assert(benders != NULL);
1804 	   assert(set != NULL);
1805 	
1806 	   /* if the subproblems have already been created, then they will not be created again. This is the case if the
1807 	    * transformed problem has been freed and then retransformed. The subproblems should only be created when the problem
1808 	    * is first transformed. */
1809 	   if( benders->subprobscreated )
1810 	      return SCIP_OKAY;
1811 	
1812 	   nsubproblems = SCIPbendersGetNSubproblems(benders);
1813 	
1814 	   /* creating all subproblems */
1815 	   for( i = 0; i < nsubproblems; i++ )
1816 	   {
1817 	      /* calling the create subproblem call back method */
1818 	      SCIP_CALL( benders->benderscreatesub(set->scip, benders, i) );
1819 	
1820 	      subproblem = SCIPbendersSubproblem(benders, i);
1821 	
1822 	      /* the subproblem SCIP instance could be set to NULL. This is because user defined subproblem solving methods
1823 	       * could be used that don't solve a SCIP instance. Thus, the following setup of the subproblem SCIP instance is
1824 	       * not required.
1825 	       *
1826 	       * NOTE: since the subproblems are supplied as NULL pointers, the internal convexity check can not be performed.
1827 	       * The user needs to explicitly specify the subproblem type.
1828 	       */
1829 	      if( subproblem != NULL )
1830 	      {
1831 	         /* setting global limits for the subproblems. This overwrites the limits set by the user */
1832 	         SCIP_CALL( SCIPsetIntParam(subproblem, "limits/maxorigsol", 0) );
1833 	
1834 	         /* getting the number of integer and binary variables to determine the problem type */
1835 	         SCIP_CALL( SCIPgetVarsData(subproblem, &vars, &nvars, NULL, NULL, NULL, NULL) );
1836 	
1837 	         /* The objective function coefficients of the master problem are set to zero. This is necessary for the Benders'
1838 	          * decomposition algorithm, since the cut methods and the objective function check assumes that the objective
1839 	          * coefficients of the master problem variables are zero.
1840 	          *
1841 	          * This only occurs if the Benders' decomposition is not a copy. It is assumed that the correct objective
1842 	          * coefficients are given during the first subproblem creation.
1843 	          *
1844 	          * If the subproblems were copied, then the master variables will be checked to ensure that they have a zero
1845 	          * objective value.
1846 	          */
1847 	         if( !benders->iscopy || benders->threadsafe )
1848 	         {
1849 	            SCIP_Bool objchanged = FALSE;
1850 	
1851 	            assert(SCIPgetStage(subproblem) == SCIP_STAGE_PROBLEM);
1852 	            for( j = 0; j < nvars; j++ )
1853 	            {
1854 	               /* retrieving the master problem variable */
1855 	               SCIP_CALL( SCIPbendersGetVar(benders, set, vars[j], &mastervar, -1) );
1856 	
1857 	               /* if mastervar is not NULL, then the subproblem variable has a corresponding master problem variable */
1858 	               if( mastervar != NULL && SCIPvarGetObj(vars[j]) != 0.0 )
1859 	               {
1860 	                  SCIPverbMessage(subproblem, SCIP_VERBLEVEL_FULL, NULL, "Benders' decomposition: Changing the objective "
1861 	                     "coefficient of copy of master problem variable <%s> in subproblem %d to zero.\n",
1862 	                     SCIPvarGetName(mastervar), i);
1863 	                  /* changing the subproblem variable objective coefficient to zero */
1864 	                  SCIP_CALL( SCIPchgVarObj(subproblem, vars[j], 0.0) );
1865 	
1866 	                  objchanged = TRUE;
1867 	               }
1868 	            }
1869 	
1870 	            if( objchanged )
1871 	            {
1872 	               SCIPverbMessage(subproblem, SCIP_VERBLEVEL_HIGH, NULL, "Benders' decomposition: Objective coefficients of "
1873 	                  "copied of master problem variables has been changed to zero.\n");
1874 	            }
1875 	         }
1876 	
1877 	         /* changing all of the master problem variable to continuous. */
1878 	         SCIP_CALL( SCIPbendersChgMastervarsToCont(benders, set, i) );
1879 	
1880 	         /* checking the convexity of the subproblem. The convexity of the subproblem indicates whether the convex
1881 	          * relaxation is a valid relaxation for the problem
1882 	          */
1883 	         SCIP_CALL( checkSubproblemConvexity(benders, set, i) );
1884 	
1885 	         /* if the problem is convex and has nonlinear constraints, then slack variables must be added to each of the
1886 	          * constraints
1887 	             */
1888 	         if( benders->execfeasphase ||
1889 	            (SCIPbendersGetSubproblemType(benders, i) <= SCIP_BENDERSSUBTYPE_CONVEXDIS
1890 	             && SCIPbendersSubproblemIsNonlinear(benders, i)) )
1891 	         {
1892 	            /* the slack variables are only added to the subproblem once. If the initialisation methods are called from a
1893 	             * copy, then the slack variables are not re-added. Alternatively, if the copy must be threadsafe, then the
1894 	             * subproblems are created from scratch again, so the slack variables need to be added.
1895 	             */
1896 	            if( !benders->iscopy || benders->threadsafe )
1897 	            {
1898 	               SCIP_CALL( addSlackVarsToConstraints(benders, set, i) );
1899 	            }
1900 	
1901 	            /* setting the flag to indicate that slack variables have been added to the subproblem constraints. This is only
1902 	             * set if the slack variables have been added at the request of the user.
1903 	             */
1904 	            if( benders->execfeasphase )
1905 	               benders->feasibilityphase = TRUE;
1906 	         }
1907 	
1908 	         /* after checking the subproblem for convexity, if the subproblem has convex constraints and continuous variables,
1909 	          * then the problem is entered into probing mode. Otherwise, it is initialised as a CIP
1910 	          */
1911 	         if( SCIPbendersGetSubproblemType(benders, i) == SCIP_BENDERSSUBTYPE_CONVEXCONT )
1912 	         {
1913 	            /* if the user has not implemented a solve subproblem callback, then the subproblem solves are performed
1914 	             * internally. To be more efficient the subproblem is put into probing mode. */
1915 	            if( benders->benderssolvesubconvex == NULL && benders->benderssolvesub == NULL
1916 	               && SCIPgetStage(subproblem) <= SCIP_STAGE_PROBLEM )
1917 	            {
1918 	               SCIP_CALL( initialiseLPSubproblem(benders, set, i) );
1919 	            }
1920 	         }
1921 	         else
1922 	         {
1923 	            SCIP_EVENTHDLRDATA* eventhdlrdata_mipnodefocus;
1924 	            SCIP_EVENTHDLRDATA* eventhdlrdata_upperbound;
1925 	
1926 	            /* because the subproblems could be reused in the copy, the event handler is not created again. If the
1927 	             * threadsafe is TRUE, then it is assumed that the subproblems are not reused.
1928 	             * NOTE: This currently works with the benders_default implementation. It may not be very general. */
1929 	            if( benders->benderssolvesubconvex == NULL && benders->benderssolvesub == NULL
1930 	               && (!benders->iscopy || benders->threadsafe) )
1931 	            {
1932 	               SCIP_CALL( SCIPallocBlockMemory(subproblem, &eventhdlrdata_mipnodefocus) );
1933 	               SCIP_CALL( SCIPallocBlockMemory(subproblem, &eventhdlrdata_upperbound) );
1934 	
1935 	               SCIP_CALL( initEventhandlerData(subproblem, eventhdlrdata_mipnodefocus) );
1936 	               SCIP_CALL( initEventhandlerData(subproblem, eventhdlrdata_upperbound) );
1937 	
1938 	               /* include the first LP solved event handler into the subproblem */
1939 	               SCIP_CALL( SCIPincludeEventhdlrBasic(subproblem, &eventhdlr, MIPNODEFOCUS_EVENTHDLR_NAME,
1940 	                     MIPNODEFOCUS_EVENTHDLR_DESC, eventExecBendersMipnodefocus, eventhdlrdata_mipnodefocus) );
1941 	               SCIP_CALL( SCIPsetEventhdlrInitsol(subproblem, eventhdlr, eventInitsolBendersMipnodefocus) );
1942 	               SCIP_CALL( SCIPsetEventhdlrExitsol(subproblem, eventhdlr, eventExitsolBendersMipnodefocus) );
1943 	               SCIP_CALL( SCIPsetEventhdlrExit(subproblem, eventhdlr, eventExitBendersMipnodefocus) );
1944 	               SCIP_CALL( SCIPsetEventhdlrFree(subproblem, eventhdlr, eventFreeBendersMipnodefocus) );
1945 	               assert(eventhdlr != NULL);
1946 	
1947 	               /* include the upper bound interrupt event handler into the subproblem */
1948 	               SCIP_CALL( SCIPincludeEventhdlrBasic(subproblem, &eventhdlr, UPPERBOUND_EVENTHDLR_NAME,
1949 	                     UPPERBOUND_EVENTHDLR_DESC, eventExecBendersUpperbound, eventhdlrdata_upperbound) );
1950 	               SCIP_CALL( SCIPsetEventhdlrInitsol(subproblem, eventhdlr, eventInitsolBendersUpperbound) );
1951 	               SCIP_CALL( SCIPsetEventhdlrExitsol(subproblem, eventhdlr, eventExitsolBendersUpperbound) );
1952 	               SCIP_CALL( SCIPsetEventhdlrExit(subproblem, eventhdlr, eventExitBendersUpperbound) );
1953 	               SCIP_CALL( SCIPsetEventhdlrFree(subproblem, eventhdlr, eventFreeBendersUpperbound) );
1954 	               assert(eventhdlr != NULL);
1955 	            }
1956 	         }
1957 	      }
1958 	      else
1959 	      {
1960 	         /* a user must specify the subproblem type if they are not supplying a SCIP instance. */
1961 	         if( SCIPbendersGetSubproblemType(benders, i) == SCIP_BENDERSSUBTYPE_UNKNOWN )
1962 	         {
1963 	            SCIPerrorMessage("If the subproblem is set to NULL, then the subproblem type must be specified.\n");
1964 	            SCIPerrorMessage("In the subproblem creation callback, call SCIPbendersSetSubproblemType with the appropriate problem type.\n");
1965 	
1966 	            return SCIP_ERROR;
1967 	         }
1968 	      }
1969 	   }
1970 	
1971 	   /* checking the convexity of the master problem. This information is useful for the cut generation methods, such as
1972 	    * non-good and integer cuts
1973 	    */
1974 	   SCIP_CALL( checkSubproblemConvexity(benders, set, -1) );
1975 	
1976 	   benders->subprobscreated = TRUE;
1977 	
1978 	   return SCIP_OKAY;
1979 	}
1980 	
1981 	
1982 	/** initializes Benders' decomposition */
1983 	SCIP_RETCODE SCIPbendersInit(
1984 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
1985 	   SCIP_SET*             set                 /**< global SCIP settings */
1986 	   )
1987 	{
1988 	   int i;
1989 	
1990 	   assert(benders != NULL);
1991 	   assert(set != NULL);
1992 	
1993 	   if( benders->initialized )
1994 	   {
1995 	      SCIPerrorMessage("Benders' decomposition <%s> already initialized\n", benders->name);
1996 	      return SCIP_INVALIDCALL;
1997 	   }
1998 	
1999 	   if( set->misc_resetstat )
2000 	   {
2001 	      SCIPclockReset(benders->setuptime);
2002 	      SCIPclockReset(benders->bendersclock);
2003 	
2004 	      benders->ncalls = 0;
2005 	      benders->ncutsfound = 0;
2006 	      benders->ntransferred = 0;
2007 	   }
2008 	
2009 	   /* start timing */
2010 	   SCIPclockStart(benders->setuptime, set);
2011 	
2012 	   if( benders->bendersinit != NULL )
2013 	   {
2014 	      SCIP_CALL( benders->bendersinit(set->scip, benders) );
2015 	   }
2016 	
2017 	   benders->initialized = TRUE;
2018 	
2019 	   /* if the Benders' decomposition is a copy, then the auxiliary variables already exist. So they are registered with
2020 	    * the Benders' decomposition struct during the init stage. If the Benders' decomposition is not a copy, then the
2021 	    * auxiliary variables need to be created, which occurs in the initpre stage
2022 	    */
2023 	   if( benders->iscopy )
2024 	   {
2025 	      /* the copied auxiliary variables must be assigned to the target Benders' decomposition */
2026 	      SCIP_CALL( assignAuxiliaryVariables(set->scip, benders) );
2027 	   }
2028 	
2029 	   /* creates the subproblems and sets up the probing mode for LP subproblems. This function calls the benderscreatesub
2030 	    * callback. */
2031 	   SCIP_CALL( createSubproblems(benders, set) );
2032 	
2033 	   /* storing the solution tolerance set by the SCIP parameters */
2034 	   SCIP_CALL( SCIPsetGetRealParam(set, "benders/solutiontol", &benders->solutiontol) );
2035 	
2036 	   /* allocating memory for the stored constraints array */
2037 	   if( benders->storedcutssize == 0 )
2038 	   {
2039 	      SCIP_ALLOC( BMSallocBlockMemoryArray(SCIPblkmem(set->scip), &benders->storedcuts, BENDERS_ARRAYSIZE) );
2040 	      benders->storedcutssize = BENDERS_ARRAYSIZE;
2041 	      benders->nstoredcuts = 0;
2042 	   }
2043 	
2044 	   /* initialising the Benders' cuts */
2045 	   SCIPbendersSortBenderscuts(benders);
2046 	   for( i = 0; i < benders->nbenderscuts; i++ )
2047 	   {
2048 	      SCIP_CALL( SCIPbenderscutInit(benders->benderscuts[i], set) );
2049 	   }
2050 	
2051 	   /* stop timing */
2052 	   SCIPclockStop(benders->setuptime, set);
2053 	
2054 	   return SCIP_OKAY;
2055 	}
2056 	
2057 	
2058 	/** Transfers Benders' cuts that were generated while solving a sub-SCIP to the original SCIP instance. This involves
2059 	 *  creating a constraint/cut that is equivalent to the generated cut in the sub-SCIP. This new constraint/cut is then
2060 	 *  added to the original SCIP instance.
2061 	 */
2062 	static
2063 	SCIP_RETCODE createAndAddTransferredCut(
2064 	   SCIP*                 sourcescip,         /**< the source SCIP from when the Benders' decomposition was copied */
2065 	   SCIP_BENDERS*         benders,            /**< the Benders' decomposition structure of the sub SCIP */
2066 	   SCIP_VAR**            vars,               /**< the variables from the source constraint */
2067 	   SCIP_Real*            vals,               /**< the coefficients of the variables in the source constriant */
2068 	   SCIP_Real             lhs,                /**< the LHS of the source constraint */
2069 	   SCIP_Real             rhs,                /**< the RHS of the source constraint */
2070 	   int                   nvars               /**< the number of variables in the source constraint */
2071 	   )
2072 	{
2073 	   SCIP_BENDERS* sourcebenders;     /* the Benders' decomposition of the source SCIP */
2074 	   SCIP_CONSHDLR* consbenders;      /* a helper variable for the Benders' decomposition constraint handler */
2075 	   SCIP_CONS* transfercons = NULL;  /* the constraint that is generated to transfer the constraints/cuts */
2076 	   SCIP_ROW* transfercut = NULL;    /* the cut that is generated to transfer the constraints/cuts */
2077 	   SCIP_VAR* sourcevar;             /* the source variable that will be added to the transferred cut */
2078 	   SCIP_VAR* origvar;
2079 	   SCIP_Real scalar;
2080 	   SCIP_Real constant;
2081 	   char cutname[SCIP_MAXSTRLEN];    /* the name of the transferred cut */
2082 	   int i;
2083 	   SCIP_Bool fail;
2084 	
2085 	   assert(sourcescip != NULL);
2086 	   assert(benders != NULL);
2087 	   assert(vars != NULL);
2088 	   assert(vals != NULL);
2089 	
2090 	   /* retrieving the source Benders' decomposition structure */
2091 	   sourcebenders = SCIPfindBenders(sourcescip, SCIPbendersGetName(benders));
2092 	
2093 	   /* retrieving the Benders' decomposition constraint handler */
2094 	   consbenders = SCIPfindConshdlr(sourcescip, "benders");
2095 	
2096 	   /* setting the name of the transferred cut */
2097 	   (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "transferredcut_%d",
2098 	      SCIPbendersGetNTransferredCuts(sourcebenders) );
2099 	
2100 	   /* TODO: It could be more efficient to pass an updated vars array with the vals array to the
2101 	    * SCIPcreateConsBasicLinear/SCIPcreateEmptyRowConshdlr. This should be implemented to improve the performance of the
2102 	    * Large Neighbourhood Benders Search.
2103 	    */
2104 	
2105 	   /* creating an empty row/constraint for the transferred cut */
2106 	   if( sourcebenders->cutsasconss )
2107 	   {
2108 	      SCIP_CALL( SCIPcreateConsBasicLinear(sourcescip, &transfercons, cutname, 0, NULL, NULL, lhs, rhs) );
2109 	      SCIP_CALL( SCIPsetConsRemovable(sourcescip, transfercons, TRUE) );
2110 	   }
2111 	   else
2112 	   {
2113 	      SCIP_CALL( SCIPcreateEmptyRowConshdlr(sourcescip, &transfercut, consbenders, cutname, lhs, rhs, FALSE,
2114 	            FALSE, TRUE) );
2115 	   }
2116 	
2117 	   fail = FALSE;
2118 	   for( i = 0; i < nvars; i++ )
2119 	   {
2120 	      /* getting the original variable for the transformed variable */
2121 	      origvar = vars[i];
2122 	      scalar = 1.0;
2123 	      constant = 0.0;
2124 	      SCIP_CALL( SCIPvarGetOrigvarSum(&origvar, &scalar, &constant) );
2125 	
2126 	      /* getting the source var from the hash map */
2127 	      sourcevar = (SCIP_VAR*) SCIPhashmapGetImage(benders->mastervarsmap, origvar);
2128 	
2129 	      /* if the source variable is not found, then the mapping in incomplete. So the constraint can not be
2130 	       * transferred. */
2131 	      if( sourcevar == NULL )
2132 	      {
2133 	         fail = TRUE;
2134 	         break;
2135 	      }
2136 	
2137 	      if( sourcebenders->cutsasconss )
2138 	      {
2139 	         assert( transfercons != NULL );
2140 	         SCIP_CALL( SCIPaddCoefLinear(sourcescip, transfercons, sourcevar, vals[i]) );    /*lint !e644*/
2141 	      }
2142 	      else
2143 	      {
2144 	         assert( transfercut != NULL );
2145 	         SCIP_CALL( SCIPaddVarToRow(sourcescip, transfercut, sourcevar, vals[i]) );       /*lint !e644*/
2146 	      }
2147 	   }
2148 	
2149 	   /* if all of the source variables were found to generate the cut */
2150 	   if( !fail )
2151 	   {
2152 	      if( sourcebenders->cutsasconss )
2153 	      {
2154 	         SCIP_CALL( SCIPaddCons(sourcescip, transfercons) );
2155 	      }
2156 	      else
2157 	      {
2158 	         SCIP_CALL( SCIPaddPoolCut(sourcescip, transfercut) );
2159 	      }
2160 	
2161 	      sourcebenders->ntransferred++;
2162 	   }
2163 	
2164 	   /* release the row/constraint */
2165 	   if( sourcebenders->cutsasconss )
2166 	   {
2167 	      /* only release if the creation of the constraint failed. */
2168 	      SCIP_CALL( SCIPreleaseCons(sourcescip, &transfercons) );
2169 	   }
2170 	   else
2171 	   {
2172 	      SCIP_CALL( SCIPreleaseRow(sourcescip, &transfercut) );
2173 	   }
2174 	
2175 	   return SCIP_OKAY;
2176 	}
2177 	
2178 	
2179 	/** transfers the cuts generated in a subscip to the source scip */
2180 	static
2181 	SCIP_RETCODE transferBendersCuts(
2182 	   SCIP*                 sourcescip,         /**< the source SCIP from when the Benders' decomposition was copied */
2183 	   SCIP*                 subscip,            /**< the sub SCIP where the Benders' cuts were generated */
2184 	   SCIP_BENDERS*         benders             /**< the Benders' decomposition structure of the sub SCIP */
2185 	   )
2186 	{
2187 	   SCIP_BENDERS* sourcebenders;     /* the Benders' decomposition of the source SCIP */
2188 	   SCIP_VAR** vars;                 /* the variables of the added constraint/row */
2189 	   SCIP_Real* vals;                 /* the values of the added constraint/row */
2190 	   SCIP_Real lhs;                   /* the LHS of the added constraint/row */
2191 	   SCIP_Real rhs;                   /* the RHS of the added constraint/row */
2192 	   int naddedcuts;
2193 	   int nvars;
2194 	   int i;
2195 	
2196 	   assert(subscip != NULL);
2197 	   assert(benders != NULL);
2198 	
2199 	   /* retrieving the source Benders' decomposition structure */
2200 	   sourcebenders = SCIPfindBenders(sourcescip, SCIPbendersGetName(benders));
2201 	
2202 	   /* exit if the cuts should not be transferred from the sub SCIP to the source SCIP. */
2203 	   if( !sourcebenders->transfercuts || benders->mastervarsmap == NULL )
2204 	      return SCIP_OKAY;
2205 	
2206 	   /* retrieving the number of stored Benders' cuts */
2207 	   naddedcuts =  SCIPbendersGetNStoredCuts(benders);
2208 	
2209 	   /* looping over all added cuts to construct the cut for the source scip */
2210 	   for( i = 0; i < naddedcuts; i++ )
2211 	   {
2212 	      /* collecting the variable information from the constraint */
2213 	      SCIP_CALL( SCIPbendersGetStoredCutData(benders, i, &vars, &vals, &lhs, &rhs, &nvars) );
2214 	
2215 	      if( nvars > 0 )
2216 	      {
2217 	         /* create and add the cut to be transferred from the sub SCIP to the source SCIP */
2218 	         SCIP_CALL( createAndAddTransferredCut(sourcescip, benders, vars, vals, lhs, rhs, nvars) );
2219 	      }
2220 	   }
2221 	
2222 	   return SCIP_OKAY;
2223 	}
2224 	
2225 	
2226 	/** calls exit method of Benders' decomposition */
2227 	SCIP_RETCODE SCIPbendersExit(
2228 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
2229 	   SCIP_SET*             set                 /**< global SCIP settings */
2230 	   )
2231 	{
2232 	   int nsubproblems;
2233 	   int i;
2234 	
2235 	   assert(benders != NULL);
2236 	   assert(set != NULL);
2237 	
2238 	   if( !benders->initialized )
2239 	   {
2240 	      SCIPerrorMessage("Benders' decomposition <%s> not initialized\n", benders->name);
2241 	      return SCIP_INVALIDCALL;
2242 	   }
2243 	
2244 	   /* start timing */
2245 	   SCIPclockStart(benders->setuptime, set);
2246 	
2247 	   if( benders->bendersexit != NULL )
2248 	   {
2249 	      SCIP_CALL( benders->bendersexit(set->scip, benders) );
2250 	   }
2251 	
2252 	   /* if the Benders' decomposition is a copy, then is a variable mapping was provided, then the generated cuts will
2253 	    * be transferred to the source scip
2254 	    */
2255 	   if( benders->iscopy && benders->mastervarsmap != NULL )
2256 	   {
2257 	      SCIP_CALL( transferBendersCuts(benders->sourcescip, set->scip, benders) );
2258 	   }
2259 	
2260 	   /* releasing the stored constraints */
2261 	   for( i = benders->nstoredcuts - 1; i >= 0; i-- )
2262 	   {
2263 	      SCIPfreeBlockMemoryArray(set->scip, &benders->storedcuts[i]->vals, benders->storedcuts[i]->nvars);
2264 	      SCIPfreeBlockMemoryArray(set->scip, &benders->storedcuts[i]->vars, benders->storedcuts[i]->nvars);
2265 	      SCIPfreeBlockMemory(set->scip, &benders->storedcuts[i]); /*lint !e866*/
2266 	   }
2267 	
2268 	   BMSfreeBlockMemoryArray(SCIPblkmem(set->scip), &benders->storedcuts, benders->storedcutssize);
2269 	   benders->storedcutssize = 0;
2270 	   benders->nstoredcuts = 0;
2271 	
2272 	   /* releasing all of the auxiliary variables */
2273 	   nsubproblems = SCIPbendersGetNSubproblems(benders);
2274 	   for( i = 0; i < nsubproblems; i++ )
2275 	   {
2276 	      /* it is possible that the master problem is not solved. As such, the auxiliary variables will not be created. So
2277 	       * we don't need to release the variables
2278 	       */
2279 	      if( benders->auxiliaryvars[i] != NULL )
2280 	      {
2281 	         /* we need to remove the locks from the auxiliary variables. This will be called always for the highest priority
2282 	          * Benders' plugin and others if the auxiliary variables are not shared
2283 	          */
2284 	         if( !benders->iscopy && SCIPvarGetNLocksDown(benders->auxiliaryvars[i]) > 0 )
2285 	            SCIP_CALL( SCIPaddVarLocksType(set->scip, benders->auxiliaryvars[i], SCIP_LOCKTYPE_MODEL, -1, 0) );
2286 	
2287 	         SCIP_CALL( SCIPreleaseVar(set->scip, &benders->auxiliaryvars[i]) );
2288 	      }
2289 	   }
2290 	
2291 	   /* if a corepoint has been used for cut strengthening, then this needs to be freed */
2292 	   if( benders->corepoint != NULL )
2293 	   {
2294 	      SCIP_CALL( SCIPfreeSol(set->scip, &benders->corepoint) );
2295 	   }
2296 	
2297 	   /* calling the exit method for the Benders' cuts */
2298 	   SCIPbendersSortBenderscuts(benders);
2299 	   for( i = 0; i < benders->nbenderscuts; i++ )
2300 	   {
2301 	      SCIP_CALL( SCIPbenderscutExit(benders->benderscuts[i], set) );
2302 	   }
2303 	
2304 	   benders->initialized = FALSE;
2305 	
2306 	   /* stop timing */
2307 	   SCIPclockStop(benders->setuptime, set);
2308 	
2309 	   return SCIP_OKAY;
2310 	}
2311 	
2312 	/** Checks whether a subproblem is independent. */
2313 	static
2314 	SCIP_RETCODE checkSubproblemIndependence(
2315 	   SCIP*                 scip,               /**< the SCIP data structure */
2316 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
2317 	   )
2318 	{
2319 	   SCIP_VAR** vars;
2320 	   int nvars;
2321 	   int nsubproblems;
2322 	   int i;
2323 	   int j;
2324 	
2325 	   assert(scip != NULL);
2326 	   assert(benders != NULL);
2327 	
2328 	   /* retrieving the master problem variables */
2329 	   SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
2330 	
2331 	   nsubproblems = SCIPbendersGetNSubproblems(benders);
2332 	
2333 	   /* looping over all subproblems to check whether there exists at least one master problem variable */
2334 	   for( i = 0; i < nsubproblems; i++ )
2335 	   {
2336 	      SCIP_Bool independent = FALSE;
2337 	
2338 	      /* if there are user defined solving or freeing functions, then it is not possible to declare the independence of
2339 	       * the subproblems.
2340 	       */
2341 	      if( benders->benderssolvesubconvex == NULL && benders->benderssolvesub == NULL
2342 	         && benders->bendersfreesub == NULL )
2343 	      {
2344 	         independent = TRUE;
2345 	
2346 	         for( j = 0; j < nvars; j++ )
2347 	         {
2348 	            SCIP_VAR* subprobvar;
2349 	
2350 	            /* getting the subproblem problem variable corresponding to the master problem variable */
2351 	            SCIP_CALL( SCIPgetBendersSubproblemVar(scip, benders, vars[j], &subprobvar, i) );
2352 	
2353 	            /* if the subporblem variable is not NULL, then the subproblem depends on the master problem */
2354 	            if( subprobvar != NULL )
2355 	            {
2356 	               independent = FALSE;
2357 	               break;
2358 	            }
2359 	         }
2360 	
2361 	         /* setting the independent flag */
2362 	         SCIPbendersSetSubproblemIsIndependent(benders, i, independent);
2363 	      }
2364 	   }
2365 	
2366 	   return SCIP_OKAY;
2367 	}
2368 	
2369 	/** informs the Benders' decomposition that the presolving process is being started */
2370 	SCIP_RETCODE SCIPbendersInitpre(
2371 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
2372 	   SCIP_SET*             set,                /**< global SCIP settings */
2373 	   SCIP_STAT*            stat                /**< dynamic problem statistics */
2374 	   )
2375 	{
2376 	   assert(benders != NULL);
2377 	   assert(set != NULL);
2378 	   assert(stat != NULL);
2379 	
2380 	   /* if the Benders' decomposition is the original, then the auxiliary variables need to be created. If the Benders'
2381 	    * decomposition is a copy, then the auxiliary variables already exist. The assignment of the auxiliary variables
2382 	    * occurs in bendersInit
2383 	    */
2384 	   if( !benders->iscopy )
2385 	   {
2386 	      /* check the subproblem independence. This check is only performed if the user has not implemented a solve
2387 	       * subproblem function.
2388 	       */
2389 	      if( benders->benderssolvesubconvex == NULL && benders->benderssolvesub == NULL )
2390 	        SCIP_CALL( checkSubproblemIndependence(set->scip, benders) );
2391 	
2392 	      /* adding the auxiliary variables to the master problem */
2393 	      SCIP_CALL( addAuxiliaryVariablesToMaster(set->scip, benders) );
2394 	   }
2395 	
2396 	   /* call presolving initialization method of Benders' decomposition */
2397 	   if( benders->bendersinitpre != NULL )
2398 	   {
2399 	      /* start timing */
2400 	      SCIPclockStart(benders->setuptime, set);
2401 	
2402 	      SCIP_CALL( benders->bendersinitpre(set->scip, benders) );
2403 	
2404 	      /* stop timing */
2405 	      SCIPclockStop(benders->setuptime, set);
2406 	   }
2407 	
2408 	   return SCIP_OKAY;
2409 	}
2410 	
2411 	
2412 	/** informs the Benders' decomposition that the presolving process has completed */
2413 	SCIP_RETCODE SCIPbendersExitpre(
2414 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
2415 	   SCIP_SET*             set,                /**< global SCIP settings */
2416 	   SCIP_STAT*            stat                /**< dynamic problem statistics */
2417 	   )
2418 	{
2419 	   assert(benders != NULL);
2420 	   assert(set != NULL);
2421 	   assert(stat != NULL);
2422 	
2423 	   /* call presolving  deinitialization method of Benders' decomposition */
2424 	   if( benders->bendersexitpre != NULL )
2425 	   {
2426 	      /* start timing */
2427 	      SCIPclockStart(benders->setuptime, set);
2428 	
2429 	      SCIP_CALL( benders->bendersexitpre(set->scip, benders) );
2430 	
2431 	      /* stop timing */
2432 	      SCIPclockStop(benders->setuptime, set);
2433 	   }
2434 	
2435 	   return SCIP_OKAY;
2436 	}
2437 	
2438 	/** informs Benders' decomposition that the branch and bound process is being started */
2439 	SCIP_RETCODE SCIPbendersInitsol(
2440 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
2441 	   SCIP_SET*             set                 /**< global SCIP settings */
2442 	   )
2443 	{
2444 	   int i;
2445 	
2446 	   assert(benders != NULL);
2447 	   assert(set != NULL);
2448 	
2449 	   /* call solving process initialization method of Benders' decomposition */
2450 	   if( benders->bendersinitsol != NULL )
2451 	   {
2452 	      /* start timing */
2453 	      SCIPclockStart(benders->setuptime, set);
2454 	
2455 	      SCIP_CALL( benders->bendersinitsol(set->scip, benders) );
2456 	
2457 	      /* stop timing */
2458 	      SCIPclockStop(benders->setuptime, set);
2459 	   }
2460 	
2461 	   /* calling the initsol method for the Benders' cuts */
2462 	   SCIPbendersSortBenderscuts(benders);
2463 	   for( i = 0; i < benders->nbenderscuts; i++ )
2464 	   {
2465 	      SCIP_CALL( SCIPbenderscutInitsol(benders->benderscuts[i], set) );
2466 	   }
2467 	
2468 	   return SCIP_OKAY;
2469 	}
2470 	
2471 	/** informs Benders' decomposition that the branch and bound process data is being freed */
2472 	SCIP_RETCODE SCIPbendersExitsol(
2473 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
2474 	   SCIP_SET*             set                 /**< global SCIP settings */
2475 	   )
2476 	{
2477 	   int nsubproblems;
2478 	   int i;
2479 	
2480 	   assert(benders != NULL);
2481 	   assert(set != NULL);
2482 	
2483 	   nsubproblems = SCIPbendersGetNSubproblems(benders);
2484 	   /* freeing all subproblems that are independent, this is because they have not bee freed during the subproblem
2485 	    * solving loop.
2486 	    */
2487 	   for( i = 0; i < nsubproblems; i++ )
2488 	   {
2489 	      if( SCIPbendersSubproblemIsIndependent(benders, i) )
2490 	      {
2491 	         /* disabling the independence of the subproblem so that it can be freed */
2492 	         SCIPbendersSetSubproblemIsIndependent(benders, i, FALSE);
2493 	
2494 	         /* freeing the independent subproblem */
2495 	         SCIP_CALL( SCIPbendersFreeSubproblem(benders, set, i) );
2496 	      }
2497 	   }
2498 	
2499 	   /* call solving process deinitialization method of Benders' decomposition */
2500 	   if( benders->bendersexitsol != NULL )
2501 	   {
2502 	      /* start timing */
2503 	      SCIPclockStart(benders->setuptime, set);
2504 	
2505 	      SCIP_CALL( benders->bendersexitsol(set->scip, benders) );
2506 	
2507 	      /* stop timing */
2508 	      SCIPclockStop(benders->setuptime, set);
2509 	   }
2510 	
2511 	   /* sorting the Benders' decomposition cuts in order of priority. Only a single cut is generated for each subproblem
2512 	    * per solving iteration. This is particularly important in the case of the optimality and feasibility cuts. Since
2513 	    * these work on two different solutions to the subproblem, it is not necessary to generate both cuts. So, once the
2514 	    * feasibility cut is generated, then no other cuts will be generated.
2515 	    */
2516 	   SCIPbendersSortBenderscuts(benders);
2517 	
2518 	   /* calling the exitsol method for the Benders' cuts */
2519 	   for( i = 0; i < benders->nbenderscuts; i++ )
2520 	   {
2521 	      SCIP_CALL( SCIPbenderscutExitsol(benders->benderscuts[i], set) );
2522 	   }
2523 	
2524 	   return SCIP_OKAY;
2525 	}
2526 	
2527 	/** activates Benders' decomposition such that it is called in LP solving loop */
2528 	SCIP_RETCODE SCIPbendersActivate(
2529 	   SCIP_BENDERS*         benders,            /**< the Benders' decomposition structure */
2530 	   SCIP_SET*             set,                /**< global SCIP settings */
2531 	   int                   nsubproblems        /**< the number subproblems used in this decomposition */
2532 	   )
2533 	{
2534 	   SCIP_EVENTHDLR* eventhdlr;
2535 	   SCIP_EVENTHDLRDATA* eventhdlrdata;
2536 	   int i;
2537 	
2538 	   assert(benders != NULL);
2539 	   assert(set != NULL);
2540 	   assert(set->stage == SCIP_STAGE_INIT || set->stage == SCIP_STAGE_PROBLEM);
2541 	
2542 	   if( !benders->active )
2543 	   {
2544 	      benders->active = TRUE;
2545 	      set->nactivebenders++;
2546 	      set->benderssorted = FALSE;
2547 	
2548 	      benders->nsubproblems = nsubproblems;
2549 	      benders->nactivesubprobs = nsubproblems;
2550 	      benders->prevlowerbound = -SCIPsetInfinity(set);
2551 	      benders->strengthenround = FALSE;
2552 	
2553 	      /* allocating memory for the subproblems arrays */
2554 	      SCIP_ALLOC( BMSallocMemoryArray(&benders->subproblems, benders->nsubproblems) );
2555 	      SCIP_ALLOC( BMSallocMemoryArray(&benders->auxiliaryvars, benders->nsubproblems) );
2556 	      SCIP_ALLOC( BMSallocMemoryArray(&benders->solvestat, benders->nsubproblems) );
2557 	      SCIP_ALLOC( BMSallocMemoryArray(&benders->subprobobjval, benders->nsubproblems) );
2558 	      SCIP_ALLOC( BMSallocMemoryArray(&benders->bestsubprobobjval, benders->nsubproblems) );
2559 	      SCIP_ALLOC( BMSallocMemoryArray(&benders->subproblowerbound, benders->nsubproblems) );
2560 	      SCIP_ALLOC( BMSallocMemoryArray(&benders->subprobtype, benders->nsubproblems) );
2561 	      SCIP_ALLOC( BMSallocMemoryArray(&benders->subprobisconvex, benders->nsubproblems) );
2562 	      SCIP_ALLOC( BMSallocMemoryArray(&benders->subprobisnonlinear, benders->nsubproblems) );
2563 	      SCIP_ALLOC( BMSallocMemoryArray(&benders->subprobsetup, benders->nsubproblems) );
2564 	      SCIP_ALLOC( BMSallocMemoryArray(&benders->indepsubprob, benders->nsubproblems) );
2565 	      SCIP_ALLOC( BMSallocMemoryArray(&benders->subprobenabled, benders->nsubproblems) );
2566 	      SCIP_ALLOC( BMSallocMemoryArray(&benders->mastervarscont, benders->nsubproblems) );
2567 	
2568 	      /* creating the priority queue for the subproblem solving status */
2569 	      SCIP_CALL( SCIPpqueueCreate(&benders->subprobqueue, benders->nsubproblems, 1.1,
2570 	            benders->benderssubcomp == NULL ? benderssubcompdefault : benders->benderssubcomp, NULL) );
2571 	
2572 	      for( i = 0; i < benders->nsubproblems; i++ )
2573 	      {
2574 	         SCIP_SUBPROBLEMSOLVESTAT* solvestat;
2575 	
2576 	         benders->subproblems[i] = NULL;
2577 	         benders->auxiliaryvars[i] = NULL;
2578 	         benders->subprobobjval[i] = SCIPsetInfinity(set);
2579 	         benders->bestsubprobobjval[i] = SCIPsetInfinity(set);
2580 	         benders->subproblowerbound[i] = -SCIPsetInfinity(set);
2581 	         benders->subprobtype[i] = SCIP_BENDERSSUBTYPE_UNKNOWN;
2582 	         benders->subprobisconvex[i] = FALSE;
2583 	         benders->subprobisnonlinear[i] = FALSE;
2584 	         benders->subprobsetup[i] = FALSE;
2585 	         benders->indepsubprob[i] = FALSE;
2586 	         benders->subprobenabled[i] = TRUE;
2587 	         benders->mastervarscont[i] = FALSE;
2588 	
2589 	         /* initialising the subproblem solving status */
2590 	         SCIP_ALLOC( BMSallocMemory(&solvestat) );
2591 	         solvestat->idx = i;
2592 	         solvestat->ncalls = 0;
2593 	         solvestat->avgiter = 0;
2594 	         benders->solvestat[i] = solvestat;
2595 	
2596 	         /* inserting the initial elements into the priority queue */
2597 	         SCIP_CALL( SCIPpqueueInsert(benders->subprobqueue, benders->solvestat[i]) );
2598 	      }
2599 	
2600 	      /* adding an eventhandler for updating the lower bound when the root node is solved. */
2601 	      eventhdlrdata = (SCIP_EVENTHDLRDATA*)benders;
2602 	
2603 	      /* include event handler into SCIP */
2604 	      SCIP_CALL( SCIPincludeEventhdlrBasic(set->scip, &eventhdlr, NODESOLVED_EVENTHDLR_NAME, NODESOLVED_EVENTHDLR_DESC,
2605 	            eventExecBendersNodesolved, eventhdlrdata) );
2606 	      SCIP_CALL( SCIPsetEventhdlrInitsol(set->scip, eventhdlr, eventInitsolBendersNodesolved) );
2607 	      assert(eventhdlr != NULL);
2608 	   }
2609 	
2610 	   return SCIP_OKAY;
2611 	}
2612 	
2613 	/** deactivates Benders' decomposition such that it is no longer called in LP solving loop */
2614 	SCIP_RETCODE SCIPbendersDeactivate(
2615 	   SCIP_BENDERS*         benders,            /**< the Benders' decomposition structure */
2616 	   SCIP_SET*             set                 /**< global SCIP settings */
2617 	   )
2618 	{
2619 	   int i;
2620 	
2621 	   assert(benders != NULL);
2622 	   assert(set != NULL);
2623 	   assert(set->stage == SCIP_STAGE_INIT || set->stage == SCIP_STAGE_PROBLEM);
2624 	
2625 	   if( benders->active )
2626 	   {
2627 	      int nsubproblems;
2628 	
2629 	      nsubproblems = SCIPbendersGetNSubproblems(benders);
2630 	
2631 	#ifndef NDEBUG
2632 	      /* checking whether the auxiliary variables and subproblems are all NULL */
2633 	      for( i = 0; i < nsubproblems; i++ )
2634 	         assert(benders->auxiliaryvars[i] == NULL);
2635 	#endif
2636 	
2637 	      /* if the subproblems were created by the Benders' decomposition core, then they need to be freed */
2638 	      if( benders->freesubprobs )
2639 	      {
2640 	         for( i = SCIPbendersGetNSubproblems(benders) - 1; i >= 0; i-- )
2641 	         {
2642 	            SCIP* subproblem = SCIPbendersSubproblem(benders, i);
2643 	            SCIP_CALL( SCIPfree(&subproblem) );
2644 	         }
2645 	      }
2646 	
2647 	      benders->active = FALSE;
2648 	      set->nactivebenders--;
2649 	      set->benderssorted = FALSE;
2650 	
2651 	      /* freeing the priority queue memory */
2652 	      SCIPpqueueFree(&benders->subprobqueue);
2653 	
2654 	      for( i = nsubproblems - 1; i >= 0; i-- )
2655 	         BMSfreeMemory(&benders->solvestat[i]);
2656 	
2657 	      /* freeing the memory allocated during the activation of the Benders' decomposition */
2658 	      BMSfreeMemoryArray(&benders->mastervarscont);
2659 	      BMSfreeMemoryArray(&benders->subprobenabled);
2660 	      BMSfreeMemoryArray(&benders->indepsubprob);
2661 	      BMSfreeMemoryArray(&benders->subprobsetup);
2662 	      BMSfreeMemoryArray(&benders->subprobisnonlinear);
2663 	      BMSfreeMemoryArray(&benders->subprobisconvex);
2664 	      BMSfreeMemoryArray(&benders->subprobtype);
2665 	      BMSfreeMemoryArray(&benders->subproblowerbound);
2666 	      BMSfreeMemoryArray(&benders->bestsubprobobjval);
2667 	      BMSfreeMemoryArray(&benders->subprobobjval);
2668 	      BMSfreeMemoryArray(&benders->auxiliaryvars);
2669 	      BMSfreeMemoryArray(&benders->solvestat);
2670 	      BMSfreeMemoryArray(&benders->subproblems);
2671 	   }
2672 	
2673 	   return SCIP_OKAY;
2674 	}
2675 	
2676 	/** returns whether the given Benders' decomposition is in use in the current problem */
2677 	SCIP_Bool SCIPbendersIsActive(
2678 	   SCIP_BENDERS*         benders             /**< the Benders' decomposition structure */
2679 	   )
2680 	{
2681 	   assert(benders != NULL);
2682 	
2683 	   return benders->active;
2684 	}
2685 	
2686 	/** updates the lower bound for all auxiliary variables. This is called if the first LP enforced is unbounded. */
2687 	static
2688 	SCIP_RETCODE updateAuxiliaryVarLowerbound(
2689 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
2690 	   SCIP_SET*             set,                /**< global SCIP settings */
2691 	   SCIP_RESULT*          result              /**< the result from updating the auxiliary variable lower bound */
2692 	   )
2693 	{
2694 	   int nsubproblems;
2695 	   int i;
2696 	
2697 	   assert(benders != NULL);
2698 	   assert(set != NULL);
2699 	
2700 	   (*result) = SCIP_DIDNOTRUN;
2701 	
2702 	   nsubproblems = SCIPbendersGetNSubproblems(benders);
2703 	
2704 	   for( i = 0; i < nsubproblems; i++ )
2705 	   {
2706 	      SCIP_VAR* auxiliaryvar;
2707 	      SCIP_Real lowerbound;
2708 	      SCIP_Bool infeasible;
2709 	
2710 	      infeasible = FALSE;
2711 	
2712 	      /* computing the lower bound of the subproblem by solving it without any variable fixings */
2713 	      SCIP_CALL( SCIPbendersComputeSubproblemLowerbound(benders, set, i, &lowerbound, &infeasible) );
2714 	
2715 	      /* if the subproblem is infeasible, then the original problem is infeasible */
2716 	      if( infeasible )
2717 	      {
2718 	         (*result) = SCIP_INFEASIBLE;
2719 	         break;
2720 	      }
2721 	
2722 	      /* retrieving the auxiliary variable */
2723 	      auxiliaryvar = SCIPbendersGetAuxiliaryVar(benders, i);
2724 	
2725 	      /* only update the lower bound if it is greater than the current lower bound */
2726 	      if( SCIPsetIsGT(set, lowerbound, SCIPvarGetLbGlobal(auxiliaryvar)) )
2727 	      {
2728 	         SCIPsetDebugMsg(set, "Tightened lower bound of <%s> to %g\n", SCIPvarGetName(auxiliaryvar), lowerbound);
2729 	         /* updating the lower bound of the auxiliary variable */
2730 	         SCIP_CALL( SCIPchgVarLb(set->scip, auxiliaryvar, lowerbound) );
2731 	         (*result) = SCIP_REDUCEDDOM;
2732 	      }
2733 	
2734 	      /* stores the lower bound for the subproblem */
2735 	      SCIPbendersUpdateSubproblemLowerbound(benders, i, lowerbound);
2736 	   }
2737 	
2738 	   return SCIP_OKAY;
2739 	}
2740 	
2741 	/** sets the core point used for cut strengthening. If the strenghtenintpoint is set to 'i', then the core point is
2742 	 *  reinitialised each time the incumbent is updated
2743 	 */
2744 	static
2745 	SCIP_RETCODE setAndUpdateCorePoint(
2746 	   SCIP*                 scip,               /**< the SCIP data structure */
2747 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
2748 	   )
2749 	{
2750 	   SCIP_SOL* bestsol;
2751 	
2752 	   assert(scip != NULL);
2753 	   assert(benders != NULL);
2754 	
2755 	   /* if the core point is not NULL and the interior point is not reinitialised, then nothing is done  */
2756 	   if( benders->corepoint != NULL && benders->strengthenintpoint != 'i' )
2757 	      return SCIP_OKAY;
2758 	
2759 	   bestsol = SCIPgetBestSol(scip);
2760 	
2761 	   /* if the core point should be updated, then this only happens if the incumbent solution has been updated */
2762 	   if( benders->strengthenintpoint == 'i' && benders->initcorepoint == bestsol )
2763 	      return SCIP_OKAY;
2764 	
2765 	   /* if a corepoint has been used for cut strengthening, then this needs to be freed */
2766 	   if( benders->corepoint != NULL )
2767 	   {
2768 	      SCIP_CALL( SCIPfreeSol(scip, &benders->corepoint) );
2769 	   }
2770 	
2771 	   switch( benders->strengthenintpoint )
2772 	   {
2773 	      SCIP_VAR** vars;
2774 	      SCIP_Real timelimit;
2775 	      int nvars;
2776 	      int i;
2777 	
2778 	      case 'l':
2779 	         SCIP_CALL( SCIPcreateLPSol(scip, &benders->corepoint, NULL) );
2780 	         SCIP_CALL( SCIPunlinkSol(scip, benders->corepoint) );
2781 	         break;
2782 	      case 'f':
2783 	      case 'i':
2784 	         SCIP_CALL( SCIPcreateSolCopy(scip, &benders->corepoint, bestsol) );
2785 	         SCIP_CALL( SCIPunlinkSol(scip, benders->corepoint) );
2786 	         benders->initcorepoint = bestsol;
2787 	         break;
2788 	      case 'r':
2789 	         /* prepare time limit */
2790 	         SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
2791 	         if ( ! SCIPisInfinity(scip, timelimit) )
2792 	            timelimit -= SCIPgetSolvingTime(scip);
2793 	
2794 	         /* if there is time remaining, then compute the relative interior point. Otherwise, return the LP solution */
2795 	         if ( timelimit > 0.0 )
2796 	         {
2797 	            SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, 0, "Computing relative interior point (time limit: %g, iter limit: %d) ...\n", timelimit, INT_MAX);
2798 	            SCIP_CALL( SCIPcomputeLPRelIntPoint(scip, TRUE, FALSE, timelimit, INT_MAX, &benders->corepoint) );
2799 	         }
2800 	         else
2801 	         {
2802 	            SCIP_CALL( SCIPcreateLPSol(scip, &benders->corepoint, NULL) );
2803 	            SCIP_CALL( SCIPunlinkSol(scip, benders->corepoint) );
2804 	         }
2805 	         break;
2806 	      case 'z':
2807 	         SCIP_CALL( SCIPcreateSol(scip, &benders->corepoint, NULL) );
2808 	         break;
2809 	      case 'o':
2810 	         SCIP_CALL( SCIPcreateSol(scip, &benders->corepoint, NULL) );
2811 	
2812 	         /* getting the variable data so that the  */
2813 	         SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
2814 	
2815 	         /* setting all variable values to 1.0 */
2816 	         for( i = 0; i < nvars; i++ )
2817 	         {
2818 	            SCIP_CALL( SCIPsetSolVal(scip, benders->corepoint, vars[i], 1.0) );
2819 	         }
2820 	         break;
2821 	      default:
2822 	         SCIP_CALL( SCIPcreateLPSol(scip, &benders->corepoint, NULL) );
2823 	         SCIP_CALL( SCIPunlinkSol(scip, benders->corepoint) );
2824 	   }
2825 	
2826 	   return SCIP_OKAY;
2827 	}
2828 	
2829 	/** performs cut strengthening by using an interior solution to generate cuts */
2830 	static
2831 	SCIP_RETCODE performInteriorSolCutStrengthening(
2832 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
2833 	   SCIP_SET*             set,                /**< global SCIP settings */
2834 	   SCIP_SOL*             sol,                /**< primal CIP solution */
2835 	   SCIP_BENDERSENFOTYPE  type,               /**< the type of solution being enforced */
2836 	   SCIP_Bool             checkint,           /**< are the subproblems called during a check/enforce of integer sols? */
2837 	   SCIP_Bool             perturbsol,         /**< should the solution be perturbed to escape infeasibility? */
2838 	   SCIP_Bool*            auxviol,            /**< set to TRUE only if the solution is feasible but the aux vars are violated */
2839 	   SCIP_Bool*            infeasible,         /**< is the master problem infeasible with respect to the Benders' cuts? */
2840 	   SCIP_Bool*            skipsolve,          /**< should the main solve be skipped as a result of this strengthening? */
2841 	   SCIP_RESULT*          result              /**< result of the pricing process */
2842 	   )
2843 	{
2844 	   SCIP_SOL* sepapoint;
2845 	   SCIP_VAR** vars;
2846 	   int prevcutsfound;
2847 	   int nvars;
2848 	   int i;
2849 	
2850 	   assert(benders != NULL);
2851 	   assert(set != NULL);
2852 	
2853 	   (*result) = SCIP_DIDNOTRUN;
2854 	   (*skipsolve) = FALSE;
2855 	
2856 	   /* the cut stabilisation is only performed when enforcing LP solutions. The solution is not NULL if the stabilisation
2857 	    * is currently being performed. It is important to avoid recursion
2858 	    */
2859 	   if( type != SCIP_BENDERSENFOTYPE_LP || sol != NULL )
2860 	      return SCIP_OKAY;
2861 	
2862 	   /* checking if a change to the lower bound has occurred */
2863 	   if( SCIPsetIsGT(set, SCIPgetLowerbound(set->scip), benders->prevlowerbound)
2864 	      || SCIPgetCurrentNode(set->scip) != benders->prevnode )
2865 	   {
2866 	      benders->prevnode = SCIPgetCurrentNode(set->scip);
2867 	      benders->prevlowerbound = SCIPgetLowerbound(set->scip);
2868 	      benders->noimprovecount = 0;
2869 	   }
2870 	   else
2871 	      benders->noimprovecount++;
2872 	
2873 	   /* if the number of iterations without improvement exceeds 3*noimprovelimit, then the no stabilisation is performed
2874 	    */
2875 	   if( benders->noimprovecount > 3*benders->noimprovelimit )
2876 	      return SCIP_OKAY;
2877 	
2878 	   /* if there is no incumbent solution, then it is not possible to create the core point and hence the strengthening
2879 	    * can not be performed
2880 	    */
2881 	   if( SCIPgetBestSol(set->scip) == NULL )
2882 	      return SCIP_OKAY;
2883 	
2884 	   /* if no LP iterations have been performed since the last call of the cut strenghtening, then the strengthening is
2885 	    * aborted
2886 	    */
2887 	   if( benders->prevnlpiter == SCIPgetNLPIterations(set->scip) )
2888 	      return SCIP_OKAY;
2889 	
2890 	   benders->prevnlpiter = SCIPgetNLPIterations(set->scip);
2891 	
2892 	   /* if the separation point solution is NULL, then we create the solution using the current LP relaxation. */
2893 	   SCIP_CALL( setAndUpdateCorePoint(set->scip, benders) );
2894 	
2895 	   /* creating the separation point
2896 	    * TODO: This could be a little to memory heavy, it may be better just to create the separation point once and then
2897 	    * update it each time.
2898 	    */
2899 	   SCIP_CALL( SCIPcreateLPSol(set->scip, &sepapoint, NULL) );
2900 	   SCIP_CALL( SCIPunlinkSol(set->scip, sepapoint) );
2901 	
2902 	   SCIP_CALL( SCIPgetVarsData(set->scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
2903 	   assert(vars != NULL);
2904 	
2905 	   /* creating a solution that is a convex combination of the LP solution and the separation point */
2906 	   for( i = 0; i < nvars; i++ )
2907 	   {
2908 	      SCIP_VAR* subvar;
2909 	      SCIP_Real corepointval;
2910 	      SCIP_Real lpsolval;
2911 	      SCIP_Real newsolval;
2912 	      int j;
2913 	
2914 	      corepointval = SCIPgetSolVal(set->scip, benders->corepoint, vars[i]);
2915 	      lpsolval = SCIPgetSolVal(set->scip, sol, vars[i]);
2916 	      newsolval = lpsolval;
2917 	
2918 	      /* checking whether the master variable is mapped to any subproblem variables */
2919 	      subvar = NULL;
2920 	      j = 0;
2921 	      while( subvar == NULL && j < SCIPgetBendersNSubproblems(set->scip, benders)  )
2922 	      {
2923 	         SCIP_CALL( SCIPgetBendersSubproblemVar(set->scip, benders, vars[i], &subvar, j) );
2924 	         j++;
2925 	      }
2926 	
2927 	      /* if the variable is a linking variable and it is not fixed, then a convex combination with the corepoint is
2928 	       * computed.
2929 	       */
2930 	      if( subvar != NULL && SCIPvarGetStatus(vars[i]) != SCIP_VARSTATUS_FIXED )
2931 	      {
2932 	         /* if the number of iterations without improvement exceeds noimprovelimit, then no convex combination is
2933 	          * created
2934 	          */
2935 	         if( !perturbsol && benders->noimprovecount <= benders->noimprovelimit )
2936 	         {
2937 	            newsolval = lpsolval*benders->convexmult + corepointval*(1 - benders->convexmult);
2938 	
2939 	            /* updating the core point */
2940 	            SCIP_CALL( SCIPsetSolVal(set->scip, benders->corepoint, vars[i], newsolval) );
2941 	         }
2942 	
2943 	         /* if the number of iterations without improvement is less than 2*noimprovelimit, then perturbation is
2944 	          * performed
2945 	          * TODO: This should be a random vector!!!!
2946 	          */
2947 	         if( perturbsol || benders->noimprovecount <= 2*benders->noimprovelimit )
2948 	            newsolval += benders->perturbeps;
2949 	      }
2950 	
2951 	      /* updating the separation point */
2952 	      SCIP_CALL( SCIPsetSolVal(set->scip, sepapoint, vars[i], newsolval) );
2953 	   }
2954 	
2955 	   /* storing the number of cuts found */
2956 	   prevcutsfound = SCIPbendersGetNCutsFound(benders);
2957 	
2958 	   SCIPsetDebugMsg(set, "solving Benders' decomposition subproblems with stabilised point.\n");
2959 	
2960 	   /* calling the subproblem solving method to generate cuts from the separation solution */
2961 	   SCIP_CALL( SCIPsolveBendersSubproblems(set->scip, benders, sepapoint, result, infeasible, auxviol, type, checkint) );
2962 	
2963 	   SCIPsetDebugMsg(set, "solved Benders' decomposition subproblems with stabilised point. noimprovecount %d result %d\n",
2964 	      benders->noimprovecount, (*result));
2965 	
2966 	   /* if constraints were added, then the main Benders' solving loop is skipped. */
2967 	   if( !(*infeasible) && ((*result) == SCIP_CONSADDED || (*result) == SCIP_SEPARATED) )
2968 	      (*skipsolve) = TRUE;
2969 	
2970 	   /* capturing cut strengthening statistics */
2971 	   benders->nstrengthencalls++;
2972 	   benders->nstrengthencuts += (SCIPbendersGetNCutsFound(benders) - prevcutsfound);
2973 	
2974 	   /* if no cuts were added, then the strengthening round is marked as failed */
2975 	   if( SCIPbendersGetNCutsFound(benders) == prevcutsfound )
2976 	      benders->nstrengthenfails++;
2977 	
2978 	   /* freeing the sepapoint solution */
2979 	   SCIP_CALL( SCIPfreeSol(set->scip, &sepapoint) );
2980 	
2981 	   return SCIP_OKAY;
2982 	}
2983 	
2984 	
2985 	/** Returns whether only the convex relaxations will be checked in this solve loop
2986 	 *  when Benders' is used in the LNS heuristics, only the convex relaxations of the master/subproblems are checked,
2987 	 *  i.e. no integer cuts are generated. In this case, then Benders' decomposition is performed under the assumption
2988 	 *  that all subproblems are convex relaxations.
2989 	 */
2990 	SCIP_Bool SCIPbendersOnlyCheckConvexRelax(
2991 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
2992 	   SCIP_Bool             subscipsoff         /**< flag indicating whether plugins using sub-SCIPs are deactivated */
2993 	   )
2994 	{
2995 	   return benders->iscopy && benders->lnscheck && subscipsoff;
2996 	}
2997 	
2998 	/** returns the number of subproblems that will be checked in this iteration */
2999 	static
3000 	int numSubproblemsToCheck(
3001 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
3002 	   SCIP_SET*             set,                /**< global SCIP settings */
3003 	   SCIP_BENDERSENFOTYPE  type                /**< the type of solution being enforced */
3004 	   )
3005 	{
3006 	   if( benders->ncalls == 0 || type == SCIP_BENDERSENFOTYPE_CHECK
3007 	      || SCIPbendersOnlyCheckConvexRelax(benders, SCIPsetGetSubscipsOff(set)) )
3008 	      return SCIPbendersGetNSubproblems(benders);
3009 	   else
3010 	      return (int) SCIPsetCeil(set, (SCIP_Real) SCIPbendersGetNSubproblems(benders)*benders->subprobfrac);
3011 	}
3012 	
3013 	/** returns whether the solving of the given subproblem needs to be executed */
3014 	static
3015 	SCIP_Bool subproblemIsActive(
3016 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
3017 	   int                   probnumber          /**< the subproblem index */
3018 	   )
3019 	{
3020 	   return (!SCIPbendersSubproblemIsIndependent(benders, probnumber)
3021 	      && SCIPbendersSubproblemIsEnabled(benders, probnumber));
3022 	}
3023 	
3024 	/** creates an ordered list of subproblem indices to be solved */
3025 	static
3026 	void createSolveSubproblemIndexList(
3027 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
3028 	   SCIP_SET*             set,                /**< global SCIP settings */
3029 	   SCIP_BENDERSENFOTYPE  type,               /**< the type of solution being enforced */
3030 	   int**                 solveidx,           /**< a list of subproblem indices to the solved in the current iteration */
3031 	   int*                  nsolveidx           /**< the number of subproblem indices in the list */
3032 	   )
3033 	{
3034 	   int nsubproblems;
3035 	   int numtocheck;
3036 	   int subproblemcount;
3037 	
3038 	   assert(benders != NULL);
3039 	   assert(set != NULL);
3040 	   assert((*solveidx) != NULL);
3041 	   assert(nsolveidx != NULL);
3042 	   assert(SCIPpqueueNElems(benders->subprobqueue) <= SCIPbendersGetNSubproblems(benders));
3043 	
3044 	   nsubproblems = SCIPbendersGetNSubproblems(benders);
3045 	
3046 	   /* it is possible to only solve a subset of subproblems. This is given by a parameter. */
3047 	   numtocheck = numSubproblemsToCheck(benders, set, type);
3048 	
3049 	   (*nsolveidx) = 0;
3050 	
3051 	   subproblemcount = 0;
3052 	   while( subproblemcount < nsubproblems && subproblemcount < numtocheck )
3053 	   {
3054 	      SCIP_SUBPROBLEMSOLVESTAT* solvestat;
3055 	
3056 	      solvestat = (SCIP_SUBPROBLEMSOLVESTAT*)SCIPpqueueRemove(benders->subprobqueue);
3057 	      (*solveidx)[(*nsolveidx)] = solvestat->idx;
3058 	      (*nsolveidx)++;
3059 	
3060 	      subproblemcount++;
3061 	   }
3062 	}
3063 	
3064 	/** updates the subproblem solving statistics and inserts the indices into the queue */
3065 	static
3066 	SCIP_RETCODE updateSubproblemStatQueue(
3067 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
3068 	   int*                  solveidx,           /**< the list of indices of subproblems that were solved */
3069 	   int                   nsolveidx,          /**< the number of subproblem indices */
3070 	   SCIP_Bool             updatestat          /**< should the statistics be updated */
3071 	   )
3072 	{
3073 	   int i;
3074 	
3075 	   assert(benders != NULL);
3076 	   assert(solveidx != NULL);
3077 	
3078 	   for( i = 0; i < nsolveidx; i++ )
3079 	   {
3080 	      SCIP* subproblem;
3081 	      SCIP_SUBPROBLEMSOLVESTAT* solvestat;
3082 	
3083 	      subproblem = SCIPbendersSubproblem(benders, solveidx[i]);
3084 	      solvestat = benders->solvestat[solveidx[i]];
3085 	      assert(solvestat->idx == solveidx[i]);
3086 	
3087 	      /* updating the solving statistics */
3088 	      if( updatestat )
3089 	      {
3090 	         if( subproblem == NULL )
3091 	            solvestat->avgiter = 1;
3092 	         else
3093 	            solvestat->avgiter = (SCIP_Real)(solvestat->avgiter*solvestat->ncalls + SCIPgetNLPIterations(subproblem))
3094 	               /(SCIP_Real)(solvestat->ncalls + 1);
3095 	         solvestat->ncalls++;
3096 	      }
3097 	
3098 	      /* inserting the solving statistics into the priority queue */
3099 	      SCIP_CALL( SCIPpqueueInsert(benders->subprobqueue, solvestat) );
3100 	   }
3101 	
3102 	   assert(SCIPpqueueNElems(benders->subprobqueue) == SCIPbendersGetNSubproblems(benders));
3103 	
3104 	   return SCIP_OKAY;
3105 	}
3106 	
3107 	/** Solves each of the Benders' decomposition subproblems for the given solution. All, or a fraction, of subproblems are
3108 	 *  solved before the Benders' decomposition cuts are generated.
3109 	 *  Since a convex relaxation of the subproblem could be solved to generate cuts, a parameter nverified is used to
3110 	 *  identified the number of subproblems that have been solved in their "original" form. For example, if the subproblem
3111 	 *  is a MIP, then if the LP is solved to generate cuts, this does not constitute a verification. The verification is
3112 	 *  only performed when the MIP is solved.
3113 	 */
3114 	static
3115 	SCIP_RETCODE solveBendersSubproblems(
3116 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
3117 	   SCIP_SET*             set,                /**< global SCIP settings */
3118 	   SCIP_SOL*             sol,                /**< primal CIP solution */
3119 	   SCIP_BENDERSENFOTYPE  type,               /**< the type of solution being enforced */
3120 	   SCIP_BENDERSSOLVELOOP solveloop,          /**< the current solve loop */
3121 	   SCIP_Bool             checkint,           /**< are the subproblems called during a check/enforce of integer sols? */
3122 	   int*                  nverified,          /**< the number of subproblems verified in the current loop */
3123 	   int*                  solveidx,           /**< the indices of subproblems to be solved in this loop */
3124 	   int                   nsolveidx,          /**< the number of subproblems to be solved in this loop */
3125 	   SCIP_Bool**           subprobsolved,      /**< an array indicating the subproblems that were solved in this loop. */
3126 	   SCIP_BENDERSSUBSTATUS** substatus,        /**< array to store the status of the subsystem */
3127 	   SCIP_Bool*            infeasible,         /**< is the master problem infeasible with respect to the Benders' cuts? */
3128 	   SCIP_Bool*            optimal,            /**< is the current solution optimal? */
3129 	   SCIP_Bool*            stopped             /**< was the solving process stopped? */
3130 	   )
3131 	{
3132 	   SCIP_Bool onlyconvexcheck;
3133 	#ifdef _OPENMP
3134 	   int numthreads;
3135 	   int maxnthreads;
3136 	#endif
3137 	   int i;
3138 	   int j;
3139 	
3140 	   /* local variables for parallelisation of the solving loop */
3141 	   int locnverified = *nverified;
3142 	   SCIP_Bool locinfeasible = *infeasible;
3143 	   SCIP_Bool locoptimal = *optimal;
3144 	   SCIP_Bool locstopped = *stopped;
3145 	
3146 	   SCIP_RETCODE retcode = SCIP_OKAY;
3147 	
3148 	   assert(benders != NULL);
3149 	   assert(set != NULL);
3150 	
3151 	   /* getting the number of threads to use when solving the subproblems. This will be either be
3152 	    * min(numthreads, maxnthreads).
3153 	    * NOTE: This may not be correct. The Benders' decomposition parallelisation should not take all minimum threads if
3154 	    * they are specified. The number of threads should be specified with the Benders' decomposition parameters.
3155 	    */
3156 	#ifdef _OPENMP
3157 	   SCIP_CALL( SCIPsetGetIntParam(set, "parallel/maxnthreads", &maxnthreads) );
3158 	   numthreads = MIN(benders->numthreads, maxnthreads);
3159 	#endif
3160 	
3161 	   /* in the case of an LNS check, only the convex relaxations of the subproblems will be solved. This is a performance
3162 	    * feature, since solving the convex relaxation is typically much faster than solving the corresponding CIP. While
3163 	    * the CIP is not solved during the LNS check, the solutions are still of higher quality than when Benders' is not
3164 	    * employed.
3165 	    */
3166 	   onlyconvexcheck = SCIPbendersOnlyCheckConvexRelax(benders, SCIPsetGetSubscipsOff(set));
3167 	
3168 	   SCIPsetDebugMsg(set, "Performing the subproblem solving process. Number of subproblems to check %d\n", nsolveidx);
3169 	
3170 	   SCIPsetDebugMsg(set, "Benders' decomposition - solve loop %d\n", solveloop);
3171 	
3172 	   if( type == SCIP_BENDERSENFOTYPE_CHECK && sol == NULL )
3173 	   {
3174 	      /* TODO: Check whether this is absolutely necessary. I think that this if statment can be removed. */
3175 	      locinfeasible = TRUE;
3176 	   }
3177 	   else
3178 	   {
3179 	      /* solving each of the subproblems for Benders' decomposition */
3180 	      /* TODO: ensure that the each of the subproblems solve and update the parameters with the correct return values
3181 	       */
3182 	#ifndef __INTEL_COMPILER
3183 	      #pragma omp parallel for num_threads(numthreads) private(i) reduction(&&:locoptimal) reduction(||:locinfeasible) reduction(+:locnverified) reduction(||:locstopped) reduction(min:retcode)
3184 	#endif
3185 	      for( j = 0; j < nsolveidx; j++ )
3186 	      {
3187 	         SCIP_Bool subinfeas = FALSE;
3188 	         SCIP_Bool convexsub;
3189 	         SCIP_Bool solvesub = TRUE;
3190 	         SCIP_Bool solved;
3191 	
3192 	         i = solveidx[j];
3193 	         convexsub = SCIPbendersGetSubproblemType(benders, i) == SCIP_BENDERSSUBTYPE_CONVEXCONT;;
3194 	
3195 	         /* the subproblem is initially flagged as not solved for this solving loop */
3196 	         (*subprobsolved)[i] = FALSE;
3197 	
3198 	         /* setting the subsystem status to UNKNOWN at the start of each solve loop */
3199 	         (*substatus)[i] = SCIP_BENDERSSUBSTATUS_UNKNOWN;
3200 	
3201 	         /* for the second solving loop, if the problem is an LP, it is not solved again. If the problem is a MIP,
3202 	          * then the subproblem objective function value is set to infinity. However, if the subproblem is proven
3203 	          * infeasible from the LP, then the IP loop is not performed.
3204 	          * If the solve loop is SCIP_BENDERSSOLVELOOP_USERCIP, then nothing is done. It is assumed that the user will
3205 	          * correctly update the objective function within the user-defined solving function.
3206 	          */
3207 	         if( solveloop == SCIP_BENDERSSOLVELOOP_CIP )
3208 	         {
3209 	            if( convexsub || (*substatus)[i] == SCIP_BENDERSSUBSTATUS_INFEAS )
3210 	               solvesub = FALSE;
3211 	            else
3212 	            {
3213 	               SCIPbendersSetSubproblemObjval(benders, i, SCIPbendersSubproblem(benders, i) != NULL ?
3214 	                  SCIPinfinity(SCIPbendersSubproblem(benders, i)) : SCIPsetInfinity(set));
3215 	            }
3216 	         }
3217 	
3218 	         /* if the subproblem is independent, then it does not need to be solved. In this case, the nverified flag will
3219 	          * increase by one. When the subproblem is not independent, then it needs to be checked.
3220 	          */
3221 	         if( !subproblemIsActive(benders, i) )
3222 	         {
3223 	            /* NOTE: There is no need to update the optimal flag. This is because optimal is always TRUE until a
3224 	             * non-optimal subproblem is found.
3225 	             */
3226 	            /* if the auxiliary variable value is infinity, then the subproblem has not been solved yet. Currently the
3227 	             * subproblem statue is unknown. */
3228 	            if( SCIPsetIsInfinity(set, SCIPbendersGetAuxiliaryVarVal(benders, set, sol, i))
3229 	               || SCIPsetIsInfinity(set, -SCIPbendersGetAuxiliaryVarVal(benders, set, sol, i))
3230 	               || SCIPsetIsInfinity(set, -SCIPbendersGetSubproblemLowerbound(benders, i)) )
3231 	            {
3232 	               SCIPbendersSetSubproblemObjval(benders, i, SCIPbendersSubproblem(benders, i) != NULL ?
3233 	                  SCIPinfinity(SCIPbendersSubproblem(benders, i)) : SCIPsetInfinity(set));
3234 	
3235 	               (*substatus)[i] = SCIP_BENDERSSUBSTATUS_UNKNOWN;
3236 	               locoptimal = FALSE;
3237 	
3238 	               SCIPsetDebugMsg(set, "Benders' decomposition: subproblem %d is not active, but has not been solved."
3239 	                 " setting status to UNKNOWN\n", i);
3240 	            }
3241 	            else
3242 	            {
3243 	               if( SCIPrelDiff(SCIPbendersGetSubproblemLowerbound(benders, i),
3244 	                     SCIPbendersGetAuxiliaryVarVal(benders, set, sol, i)) < benders->solutiontol )
3245 	               {
3246 	                  SCIPbendersSetSubproblemObjval(benders, i, SCIPbendersGetAuxiliaryVarVal(benders, set, sol, i));
3247 	                  (*substatus)[i] = SCIP_BENDERSSUBSTATUS_OPTIMAL;
3248 	               }
3249 	               else
3250 	               {
3251 	                  SCIPbendersSetSubproblemObjval(benders, i, SCIPbendersGetSubproblemLowerbound(benders, i));
3252 	                  (*substatus)[i] = SCIP_BENDERSSUBSTATUS_AUXVIOL;
3253 	               }
3254 	
3255 	               SCIPsetDebugMsg(set, "Benders' decomposition: subproblem %d is not active, setting status to OPTIMAL\n", i);
3256 	            }
3257 	
3258 	            (*subprobsolved)[i] = TRUE;
3259 	
3260 	            /* the nverified counter is only increased in the convex solving loop */
3261 	            if( solveloop == SCIP_BENDERSSOLVELOOP_CONVEX || solveloop == SCIP_BENDERSSOLVELOOP_USERCONVEX )
3262 	               locnverified++;
3263 	         }
3264 	         else if( solvesub )
3265 	         {
3266 	            retcode = SCIPbendersExecSubproblemSolve(benders, set, sol, i, solveloop, FALSE, &solved, &subinfeas, type);
3267 	
3268 	            /* the solution for the subproblem is only processed if the return code is SCIP_OKAY */
3269 	            if( retcode == SCIP_OKAY )
3270 	            {
3271 	#ifdef SCIP_DEBUG
3272 	               if( type == SCIP_BENDERSENFOTYPE_LP )
3273 	               {
3274 	               SCIPsetDebugMsg(set, "Enfo LP: Subproblem %d Type %d (%f < %f)\n", i,
3275 	                  SCIPbendersGetSubproblemType(benders, i), SCIPbendersGetAuxiliaryVarVal(benders, set, sol, i),
3276 	                     SCIPbendersGetSubproblemObjval(benders, i));
3277 	               }
3278 	#endif
3279 	               (*subprobsolved)[i] = solved;
3280 	
3281 	               locinfeasible = locinfeasible || subinfeas;
3282 	               if( subinfeas )
3283 	                  (*substatus)[i] = SCIP_BENDERSSUBSTATUS_INFEAS;
3284 	
3285 	               /* if the subproblems are solved to check integer feasibility, then the optimality check must be performed.
3286 	                * This will only be performed if checkint is TRUE and the subproblem was solved. The subproblem may not be
3287 	                * solved if the user has defined a solving function
3288 	                */
3289 	               if( checkint && (*subprobsolved)[i] )
3290 	               {
3291 	                  /* if the subproblem is feasible, then it is necessary to update the value of the auxiliary variable to the
3292 	                   * objective function value of the subproblem.
3293 	                   */
3294 	                  if( !subinfeas )
3295 	                  {
3296 	                     SCIP_Bool subproboptimal;
3297 	
3298 	                     subproboptimal = SCIPbendersSubproblemIsOptimal(benders, set, sol, i);
3299 	
3300 	                     if( subproboptimal )
3301 	                        (*substatus)[i] = SCIP_BENDERSSUBSTATUS_OPTIMAL;
3302 	                     else
3303 	                        (*substatus)[i] = SCIP_BENDERSSUBSTATUS_AUXVIOL;
3304 	
3305 	                     /* It is only possible to determine the optimality of a solution within a given subproblem in four
3306 	                      * different cases:
3307 	                      * i) solveloop == SCIP_BENDERSSOLVELOOP_CONVEX or USERCONVEX and the subproblem is convex.
3308 	                      * ii) solveloop == SCIP_BENDERSOLVELOOP_CONVEX  and only the convex relaxations will be checked.
3309 	                      * iii) solveloop == SCIP_BENDERSSOLVELOOP_USERCIP and the subproblem was solved, since the user has
3310 	                      * defined a solve function, it is expected that the solving is correctly executed.
3311 	                      * iv) solveloop == SCIP_BENDERSSOLVELOOP_CIP and the MIP for the subproblem has been solved.
3312 	                      */
3313 	                     if( convexsub || onlyconvexcheck
3314 	                        || solveloop == SCIP_BENDERSSOLVELOOP_CIP
3315 	                        || solveloop == SCIP_BENDERSSOLVELOOP_USERCIP )
3316 	                        locoptimal = locoptimal && subproboptimal;
3317 	
3318 	#ifdef SCIP_DEBUG
3319 	                     if( convexsub || solveloop >= SCIP_BENDERSSOLVELOOP_CIP )
3320 	                     {
3321 	                        if( subproboptimal )
3322 	                        {
3323 	                           SCIPsetDebugMsg(set, "Subproblem %d is Optimal (%f >= %f)\n", i,
3324 	                              SCIPbendersGetAuxiliaryVarVal(benders, set, sol, i), SCIPbendersGetSubproblemObjval(benders, i));
3325 	                        }
3326 	                        else
3327 	                        {
3328 	                           SCIPsetDebugMsg(set, "Subproblem %d is NOT Optimal (%f < %f)\n", i,
3329 	                              SCIPbendersGetAuxiliaryVarVal(benders, set, sol, i), SCIPbendersGetSubproblemObjval(benders, i));
3330 	                        }
3331 	                     }
3332 	#endif
3333 	
3334 	                     /* the nverified variable is only incremented when the original form of the subproblem has been solved.
3335 	                      * What is meant by "original" is that the LP relaxation of CIPs are solved to generate valid cuts. So
3336 	                      * if the subproblem is defined as a CIP, then it is only classified as checked if the CIP is solved.
3337 	                      * There are three cases where the "original" form is solved are:
3338 	                      * i) solveloop == SCIP_BENDERSSOLVELOOP_CONVEX or USERCONVEX and the subproblem is an LP
3339 	                      *    - the original form has been solved.
3340 	                      * ii) solveloop == SCIP_BENDERSSOLVELOOP_CIP or USERCIP and the CIP for the subproblem has been
3341 	                      *    solved.
3342 	                      * iii) or, only a convex check is performed.
3343 	                      */
3344 	                     if( ((solveloop == SCIP_BENDERSSOLVELOOP_CONVEX || solveloop == SCIP_BENDERSSOLVELOOP_USERCONVEX)
3345 	                           && convexsub)
3346 	                        || ((solveloop == SCIP_BENDERSSOLVELOOP_CIP || solveloop == SCIP_BENDERSSOLVELOOP_USERCIP)
3347 	                           && !convexsub)
3348 	                        || onlyconvexcheck )
3349 	                        locnverified++;
3350 	                  }
3351 	               }
3352 	            }
3353 	         }
3354 	
3355 	         /* checking whether the limits have been exceeded in the master problem */
3356 	         locstopped = SCIPisStopped(set->scip);
3357 	      }
3358 	   }
3359 	
3360 	   /* setting the input parameters to the local variables */
3361 	   SCIPsetDebugMsg(set, "Local variable values: nverified %d infeasible %u optimal %u stopped %u\n", locnverified,
3362 	      locinfeasible, locoptimal, locstopped);
3363 	   *nverified = locnverified;
3364 	   *infeasible = locinfeasible;
3365 	   *optimal = locoptimal;
3366 	   *stopped = locstopped;
3367 	
3368 	   return retcode;
3369 	}
3370 	
3371 	/** Calls the Benders' decompsition cuts for the given solve loop. There are four cases:
3372 	 *  i) solveloop == SCIP_BENDERSSOLVELOOP_CONVEX - only the LP Benders' cuts are called
3373 	 *  ii) solveloop == SCIP_BENDERSSOLVELOOP_CIP - only the CIP Benders' cuts are called
3374 	 *  iii) solveloop == SCIP_BENDERSSOLVELOOP_USERCONVEX - only the LP Benders' cuts are called
3375 	 *  iv) solveloop == SCIP_BENDERSSOLVELOOP_USERCIP - only the CIP Benders' cuts are called
3376 	 *
3377 	 *  The priority of the results are: SCIP_CONSADDED (SCIP_SEPARATED), SCIP_DIDNOTFIND, SCIP_FEASIBLE, SCIP_DIDNOTRUN. In
3378 	 *  this function, there are four levels of results that need to be assessed. These are:
3379 	 *  i) The result from the individual cut for the subproblem
3380 	 *  ii) The overall result for the subproblem from all cuts
3381 	 *  iii) the overall result for the solve loop from all cuts
3382 	 *  iv) the over all result from all solve loops.
3383 	 *  In each level, the priority of results must be adhered to.
3384 	 */
3385 	static
3386 	SCIP_RETCODE generateBendersCuts(
3387 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
3388 	   SCIP_SET*             set,                /**< global SCIP settings */
3389 	   SCIP_SOL*             sol,                /**< primal CIP solution */
3390 	   SCIP_RESULT*          result,             /**< result of the pricing process */
3391 	   SCIP_BENDERSENFOTYPE  type,               /**< the type of solution being enforced */
3392 	   SCIP_BENDERSSOLVELOOP solveloop,          /**< the current solve loop */
3393 	   SCIP_Bool             checkint,           /**< are the subproblems called during a check/enforce of integer sols? */
3394 	   SCIP_Bool*            subprobsolved,      /**< an array indicating the subproblems that were solved in this loop. */
3395 	   SCIP_BENDERSSUBSTATUS* substatus,         /**< array to store the status of the subsystem */
3396 	   int*                  solveidx,           /**< the indices of subproblems to be solved in this loop */
3397 	   int                   nsolveidx,          /**< the number of subproblems to be solved in this loop */
3398 	   int**                 mergecands,         /**< the subproblems that are merge candidates */
3399 	   int*                  npriomergecands,    /**< the number of priority merge candidates. */
3400 	   int*                  nmergecands,        /**< the number of merge candidates. */
3401 	   int*                  nsolveloops         /**< the number of solve loops, is updated w.r.t added cuts */
3402 	   )
3403 	{
3404 	   SCIP_BENDERSCUT** benderscuts;
3405 	   SCIP_RESULT solveloopresult;
3406 	   int nbenderscuts;
3407 	   SCIP_Longint addedcuts = 0;
3408 	   int i;
3409 	   int j;
3410 	   int k;
3411 	   SCIP_Bool onlyconvexcheck;
3412 	
3413 	   assert(benders != NULL);
3414 	   assert(set != NULL);
3415 	
3416 	   /* getting the Benders' decomposition cuts */
3417 	   benderscuts = SCIPbendersGetBenderscuts(benders);
3418 	   nbenderscuts = SCIPbendersGetNBenderscuts(benders);
3419 	
3420 	   solveloopresult = SCIP_DIDNOTRUN;
3421 	
3422 	   /* in the case of an LNS check, only the convex relaxations of the subproblems will be solved. This is a performance
3423 	    * feature, since solving the convex relaxation is typically much faster than solving the corresponding CIP. While
3424 	    * the CIP is not solved during the LNS check, the solutions are still of higher quality than when Benders' is not
3425 	    * employed.
3426 	    */
3427 	   onlyconvexcheck = SCIPbendersOnlyCheckConvexRelax(benders, SCIPsetGetSubscipsOff(set));
3428 	
3429 	   /* It is only possible to add cuts to the problem if it has not already been solved */
3430 	   if( SCIPsetGetStage(set) < SCIP_STAGE_SOLVED
3431 	      && SCIPsetGetStage(set) != SCIP_STAGE_TRANSFORMED && SCIPsetGetStage(set) != SCIP_STAGE_PRESOLVED
3432 	      && (benders->cutcheck || type != SCIP_BENDERSENFOTYPE_CHECK) )
3433 	   {
3434 	      /* This is done in two loops. The first is by subproblem and the second is by cut type. */
3435 	      for( k = 0; k < nsolveidx; k++ )
3436 	      {
3437 	         SCIP_RESULT subprobresult;
3438 	         SCIP_Bool convexsub;
3439 	
3440 	         i = solveidx[k];
3441 	
3442 	         convexsub = SCIPbendersGetSubproblemType(benders, i) == SCIP_BENDERSSUBTYPE_CONVEXCONT;
3443 	
3444 	         /* cuts can only be generated if the subproblem is not independent and if it has been solved. Additionally, the
3445 	          * status of the subproblem solving must not be INFEASIBLE while in a cut strengthening round.
3446 	          * The subproblem solved flag is important for the user-defined subproblem solving methods
3447 	          */
3448 	         if( subproblemIsActive(benders, i) && subprobsolved[i]
3449 	            && !(substatus[i] == SCIP_BENDERSSUBSTATUS_INFEAS && benders->strengthenround) )
3450 	         {
3451 	            subprobresult = SCIP_DIDNOTRUN;
3452 	            for( j = 0; j < nbenderscuts; j++ )
3453 	            {
3454 	               SCIP_RESULT cutresult;
3455 	               SCIP_Longint prevaddedcuts;
3456 	
3457 	               assert(benderscuts[j] != NULL);
3458 	
3459 	               prevaddedcuts = SCIPbenderscutGetNFound(benderscuts[j]);
3460 	               cutresult = SCIP_DIDNOTRUN;
3461 	
3462 	               /* the result is updated only if a Benders' cut is generated or one was not found. However, if a cut has
3463 	                * been found in a previous iteration, then the result is returned as SCIP_CONSADDED or SCIP_SEPARATED.
3464 	                * This result is permitted because if a constraint was added, the solution that caused the error in the cut
3465 	                * generation will be cutoff from the master problem.
3466 	                */
3467 	               if( (SCIPbenderscutIsLPCut(benderscuts[j]) && (solveloop == SCIP_BENDERSSOLVELOOP_CONVEX
3468 	                        || solveloop == SCIP_BENDERSSOLVELOOP_USERCONVEX))
3469 	                  || (!SCIPbenderscutIsLPCut(benderscuts[j]) && ((solveloop == SCIP_BENDERSSOLVELOOP_CIP && !convexsub)
3470 	                        || solveloop == SCIP_BENDERSSOLVELOOP_USERCIP)) )
3471 	                  SCIP_CALL( SCIPbenderscutExec(benderscuts[j], set, benders, sol, i, type, &cutresult) );
3472 	
3473 	               addedcuts += (SCIPbenderscutGetNFound(benderscuts[j]) - prevaddedcuts);
3474 	
3475 	               /* the result is updated only if a Benders' cut is generated */
3476 	               if( cutresult == SCIP_CONSADDED || cutresult == SCIP_SEPARATED )
3477 	               {
3478 	                  subprobresult = cutresult;
3479 	
3480 	                  benders->ncutsfound++;
3481 	
3482 	                  /* at most a single cut is generated for each subproblem */
3483 	                  break;
3484 	               }
3485 	               else
3486 	               {
3487 	                  /* checking from lowest priority result */
3488 	                  if( subprobresult == SCIP_DIDNOTRUN )
3489 	                     subprobresult = cutresult;
3490 	                  else if( subprobresult == SCIP_FEASIBLE && cutresult == SCIP_DIDNOTFIND )
3491 	                     subprobresult = cutresult;
3492 	                  /* if the subprobresult is SCIP_DIDNOTFIND, then it can't be updated. */
3493 	               }
3494 	            }
3495 	
3496 	            /* the highest priority for the results is CONSADDED and SEPARATED. The solveloopresult will always be
3497 	             * updated if the subprobresult is either of these.
3498 	             */
3499 	            if( subprobresult == SCIP_CONSADDED || subprobresult == SCIP_SEPARATED )
3500 	            {
3501 	               solveloopresult = subprobresult;
3502 	            }
3503 	            else if( subprobresult == SCIP_FEASIBLE )
3504 	            {
3505 	               /* updating the solve loop result based upon the priority */
3506 	               if( solveloopresult == SCIP_DIDNOTRUN )
3507 	                  solveloopresult = subprobresult;
3508 	            }
3509 	            else if( subprobresult == SCIP_DIDNOTFIND )
3510 	            {
3511 	               /* updating the solve loop result based upon the priority */
3512 	               if( solveloopresult == SCIP_DIDNOTRUN || solveloopresult == SCIP_FEASIBLE )
3513 	                  solveloopresult = subprobresult;
3514 	
3515 	               /* since a cut was not found, then merging could be useful to avoid this in subsequent iterations. The
3516 	                * candidate is labelled as a non-priority merge candidate
3517 	                */
3518 	               if( substatus[i] != SCIP_BENDERSSUBSTATUS_OPTIMAL )
3519 	               {
3520 	                  (*mergecands)[(*nmergecands)] = i;
3521 	                  (*nmergecands)++;
3522 	               }
3523 	            }
3524 	            else if( subprobresult == SCIP_DIDNOTRUN )
3525 	            {
3526 	               /* if the subproblem is infeasible and no cut generation methods were run, then the infeasibility will
3527 	                * never be resolved. As such, the subproblem will be merged into the master problem. If the subproblem
3528 	                * was not infeasible, then it is added as a possible merge candidate
3529 	                */
3530 	               if( substatus[i] == SCIP_BENDERSSUBSTATUS_INFEAS )
3531 	               {
3532 	                  (*mergecands)[(*nmergecands)] = (*mergecands)[(*npriomergecands)];
3533 	                  (*mergecands)[(*npriomergecands)] = i;
3534 	                  (*npriomergecands)++;
3535 	                  (*nmergecands)++;
3536 	               }
3537 	               else if( substatus[i] != SCIP_BENDERSSUBSTATUS_OPTIMAL )
3538 	               {
3539 	                  (*mergecands)[(*nmergecands)] = i;
3540 	                  (*nmergecands)++;
3541 	               }
3542 	            }
3543 	         }
3544 	      }
3545 	   }
3546 	
3547 	   /* updating the overall result based upon the priorities */
3548 	   if( solveloopresult == SCIP_CONSADDED || solveloopresult == SCIP_SEPARATED )
3549 	   {
3550 	      (*result) = solveloopresult;
3551 	   }
3552 	   else if( solveloopresult == SCIP_FEASIBLE )
3553 	   {
3554 	      /* updating the solve loop result based upon the priority */
3555 	      if( (*result) == SCIP_DIDNOTRUN )
3556 	         (*result) = solveloopresult;
3557 	   }
3558 	   else if( solveloopresult == SCIP_DIDNOTFIND )
3559 	   {
3560 	      /* updating the solve loop result based upon the priority */
3561 	      if( (*result) == SCIP_DIDNOTRUN || (*result) == SCIP_FEASIBLE )
3562 	         (*result) = solveloopresult;
3563 	   }
3564 	
3565 	   /* if no cuts were added, then the number of solve loops is increased */
3566 	   if( addedcuts == 0 && SCIPbendersGetNConvexSubproblems(benders) < SCIPbendersGetNSubproblems(benders)
3567 	      && checkint && !onlyconvexcheck )
3568 	      (*nsolveloops) = 2;
3569 	
3570 	   return SCIP_OKAY;
3571 	}
3572 	
3573 	/** Solves the subproblem using the current master problem solution.
3574 	 *
3575 	 *  The checkint flag indicates whether integer feasibility can be assumed. If it is not assumed, i.e. checkint ==
3576 	 *  FALSE, then only the convex relaxations of the subproblems are solved. If integer feasibility is assumed, i.e.
3577 	 *  checkint == TRUE, then the convex relaxations and the full CIP are solved to generate Benders' cuts and check
3578 	 *  solution feasibility.
3579 	 *
3580 	 *  TODO: consider allowing the possibility to pass solution information back from the subproblems instead of the scip
3581 	 *  instance. This would allow the use of different solvers for the subproblems, more importantly allowing the use of an
3582 	 *  LP solver for LP subproblems.
3583 	 */
3584 	SCIP_RETCODE SCIPbendersExec(
3585 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
3586 	   SCIP_SET*             set,                /**< global SCIP settings */
3587 	   SCIP_SOL*             sol,                /**< primal CIP solution */
3588 	   SCIP_RESULT*          result,             /**< result of the pricing process */
3589 	   SCIP_Bool*            infeasible,         /**< is the master problem infeasible with respect to the Benders' cuts? */
3590 	   SCIP_Bool*            auxviol,            /**< set to TRUE only if the solution is feasible but the aux vars are violated */
3591 	   SCIP_BENDERSENFOTYPE  type,               /**< the type of solution being enforced */
3592 	   SCIP_Bool             checkint            /**< should the integer solution be checked by the subproblems */
3593 	   )
3594 	{
3595 	   int nsubproblems;
3596 	   int subproblemcount;
3597 	   int nsolveloops;
3598 	   int nverified;
3599 	   int nsolved;
3600 	   int* mergecands;
3601 	   int npriomergecands;
3602 	   int nmergecands;
3603 	   int* solveidx;
3604 	   int* executedidx;
3605 	   int nsolveidx;
3606 	   int nexecutedidx;
3607 	   int nfree;
3608 	   SCIP_Bool* subprobsolved;
3609 	   SCIP_BENDERSSUBSTATUS* substatus;
3610 	   SCIP_Bool optimal;
3611 	   SCIP_Bool allverified;
3612 	   SCIP_Bool success;
3613 	   SCIP_Bool stopped;
3614 	   int i;
3615 	   int l;
3616 	
3617 	   success = TRUE;
3618 	   stopped = FALSE;
3619 	
3620 	   SCIPsetDebugMsg(set, "Starting Benders' decomposition subproblem solving. type %d checkint %u\n", type, checkint);
3621 	
3622 	#ifdef SCIP_MOREDEBUG
3623 	   SCIP_CALL( SCIPprintSol(set->scip, sol, NULL, FALSE) );
3624 	#endif
3625 	
3626 	   /* start timing */
3627 	   SCIPclockStart(benders->bendersclock, set);
3628 	
3629 	   nsubproblems = SCIPbendersGetNSubproblems(benders);
3630 	
3631 	   (*auxviol) = FALSE;
3632 	   (*infeasible) = FALSE;
3633 	
3634 	   /* It is assumed that the problem is optimal, until a subproblem is found not to be optimal. However, not all
3635 	    * subproblems could be checked in each iteration. As such, it is not possible to state that the problem is optimal
3636 	    * if not all subproblems are checked. Situations where this may occur is when a subproblem is a MIP and only the LP
3637 	    * is solved. Also, in a distributed computation, then it may be advantageous to only solve some subproblems before
3638 	    * resolving the master problem. As such, for a problem to be optimal, then (optimal && allverified) == TRUE
3639 	    */
3640 	   optimal = TRUE;
3641 	   nverified = 0;
3642 	   nsolved = 0;
3643 	
3644 	   assert(benders != NULL);
3645 	   assert(result != NULL);
3646 	   assert(infeasible != NULL);
3647 	   assert(auxviol != NULL);
3648 	
3649 	   /* if the Benders' decomposition is called from a sub-SCIP and the sub-SCIPs have been deactivated, then it is
3650 	    * assumed that this is an LNS heuristic. As such, the check is not performed and the solution is assumed to be
3651 	    * feasible
3652 	    */
3653 	   if( benders->iscopy && set->subscipsoff
3654 	      && (!benders->lnscheck
3655 	         || (benders->lnsmaxdepth > -1 && SCIPgetDepth(benders->sourcescip) >= benders->lnsmaxdepth)
3656 	         || (benders->lnsmaxcalls > -1 && SCIPbendersGetNCalls(benders) >= benders->lnsmaxcalls)
3657 	         || (type != SCIP_BENDERSENFOTYPE_CHECK && SCIPgetDepth(set->scip) == 0 && benders->lnsmaxcallsroot > -1
3658 	            && SCIPbendersGetNCalls(benders) >= benders->lnsmaxcallsroot)) )
3659 	   {
3660 	      (*result) = SCIP_DIDNOTRUN;
3661 	      return SCIP_OKAY;
3662 	   }
3663 	
3664 	   /* it is not necessary to check all primal solutions by solving the Benders' decomposition subproblems.
3665 	    * Only the improving solutions are checked to improve efficiency of the algorithm.
3666 	    * If the solution is non-improving, the result FEASIBLE is returned. While this may be incorrect w.r.t to the
3667 	    * Benders' subproblems, this solution will never be the optimal solution. A non-improving solution may be used
3668 	    * within LNS primal heuristics. If this occurs, the improving solution, if found, will be checked by the solving
3669 	    * the Benders' decomposition subproblems.
3670 	    * TODO: Add a parameter to control this behaviour.
3671 	    */
3672 	   if( checkint && SCIPsetIsLE(set, SCIPgetPrimalbound(set->scip)*(int)SCIPgetObjsense(set->scip),
3673 	         SCIPgetSolOrigObj(set->scip, sol)*(int)SCIPgetObjsense(set->scip)) )
3674 	   {
3675 	      (*result) = SCIP_DIDNOTRUN;
3676 	      return SCIP_OKAY;
3677 	   }
3678 	
3679 	   /* if the enforcement type is SCIP_BENDERSENFOTYPE_LP and the LP is currently unbounded. This could mean that there
3680 	    * is no lower bound on the auxiliary variables. In this case, we try to update the lower bound for the auxiliary
3681 	    * variables.
3682 	    */
3683 	   if( type == SCIP_BENDERSENFOTYPE_LP && SCIPgetLPSolstat(set->scip) == SCIP_LPSOLSTAT_UNBOUNDEDRAY
3684 	      && benders->updateauxvarbound )
3685 	   {
3686 	      SCIP_CALL( updateAuxiliaryVarLowerbound(benders, set, result) );
3687 	
3688 	      /* the auxiliary variable bound will only be updated once. */
3689 	      benders->updateauxvarbound = FALSE;
3690 	   }
3691 	
3692 	   /* sets the stored objective function values of the subproblems to infinity */
3693 	   resetSubproblemObjectiveValue(benders, set);
3694 	
3695 	   *result = SCIP_DIDNOTRUN;
3696 	
3697 	   if( benders->benderspresubsolve != NULL && !benders->strengthenround )
3698 	   {
3699 	      SCIP_Bool skipsolve;
3700 	
3701 	      skipsolve = FALSE;
3702 	      SCIP_CALL( benders->benderspresubsolve(set->scip, benders, sol, type, checkint, infeasible, auxviol, &skipsolve,
3703 	            result) );
3704 	
3705 	      /* evaluate result */
3706 	      if( (*result) != SCIP_DIDNOTRUN
3707 	         && (*result) != SCIP_FEASIBLE
3708 	         && (*result) != SCIP_INFEASIBLE
3709 	         && (*result) != SCIP_CONSADDED
3710 	         && (*result) != SCIP_SEPARATED )
3711 	      {
3712 	         SCIPerrorMessage("the user-defined pre subproblem solving method for the Benders' decomposition <%s> returned "
3713 	            "invalid result <%d>\n", benders->name, *result);
3714 	         return SCIP_INVALIDRESULT;
3715 	      }
3716 	
3717 	      /* if the solve must be skipped, then the solving loop is exited and the user defined result is returned */
3718 	      if( skipsolve )
3719 	      {
3720 	         SCIPsetDebugMsg(set, "skipping the subproblem solving for Benders' decomposition <%s>. "
3721 	            "returning result <%d>\n", benders->name, *result);
3722 	         return SCIP_OKAY;
3723 	      }
3724 	   }
3725 	
3726 	   /* the cut strengthening is performed before the regular subproblem solve is called. To avoid recursion, the flag
3727 	    * strengthenround is set to TRUE when the cut strengthening is performed. The cut strengthening is not performed as
3728 	    * part of the large neighbourhood Benders' search.
3729 	    *
3730 	    * NOTE: cut strengthening is only applied for fractional solutions and integer solutions if there are no CIP
3731 	    * subproblems.
3732 	    */
3733 	   if( benders->strengthenenabled && !benders->strengthenround && !benders->iscopy
3734 	      && (!checkint || SCIPbendersGetNConvexSubproblems(benders) == SCIPbendersGetNSubproblems(benders)) )
3735 	   {
3736 	      SCIP_Bool skipsolve;
3737 	
3738 	      benders->strengthenround = TRUE;
3739 	      /* if the user has not requested the solve to be skipped, then the cut strengthening is performed */
3740 	      SCIP_CALL( performInteriorSolCutStrengthening(benders, set, sol, type, checkint, FALSE, infeasible, auxviol,
3741 	            &skipsolve, result) );
3742 	      benders->strengthenround = FALSE;
3743 	
3744 	      /* if the solve must be skipped, then the solving loop is exited and the user defined result is returned */
3745 	      if( skipsolve )
3746 	      {
3747 	         SCIPsetDebugMsg(set, "skipping the subproblem solving because cut strengthening found a cut "
3748 	            "for Benders' decomposition <%s>. Returning result <%d>\n", benders->name, *result);
3749 	         return SCIP_OKAY;
3750 	      }
3751 	
3752 	      /* the result flag need to be reset to DIDNOTRUN for the main subproblem solve */
3753 	      (*result) = SCIP_DIDNOTRUN;
3754 	   }
3755 	
3756 	   /* allocating memory for the infeasible subproblem array */
3757 	   SCIP_CALL( SCIPallocClearBlockMemoryArray(set->scip, &subprobsolved, nsubproblems) );
3758 	   SCIP_CALL( SCIPallocClearBlockMemoryArray(set->scip, &substatus, nsubproblems) );
3759 	   SCIP_CALL( SCIPallocClearBlockMemoryArray(set->scip, &mergecands, nsubproblems) );
3760 	   npriomergecands = 0;
3761 	   nmergecands = 0;
3762 	
3763 	   /* allocating the memory for the subproblem solving and cut generation indices */
3764 	   SCIP_CALL( SCIPallocClearBlockMemoryArray(set->scip, &solveidx, nsubproblems) );
3765 	   SCIP_CALL( SCIPallocClearBlockMemoryArray(set->scip, &executedidx, nsubproblems) );
3766 	   nsolveidx = 0;
3767 	   nexecutedidx = 0;
3768 	
3769 	   /* only a subset of the subproblems are initially solved. Both solving loops are executed for the subproblems to
3770 	    * check whether any cuts are generated. If a cut is generated, then no further subproblems are solved. If a cut is
3771 	    * not generated, then an additional set of subproblems are solved.
3772 	    */
3773 	   while( nsolved < nsubproblems )
3774 	   {
3775 	      /* getting the indices for the subproblems that will be solved */
3776 	      createSolveSubproblemIndexList(benders, set, type, &solveidx, &nsolveidx);
3777 	
3778 	      /* by default the number of solve loops is 1. This is the case if all subproblems are LP or the user has defined a
3779 	       * benderssolvesub callback. If there is a subproblem that is not an LP, then 2 solve loops are performed. The first
3780 	       * loop is the LP solving loop, the second solves the subproblem to integer optimality.
3781 	       */
3782 	      nsolveloops = 1;
3783 	
3784 	      for( l = 0; l < nsolveloops; l++ )
3785 	      {
3786 	         SCIP_BENDERSSOLVELOOP solveloop;    /* identifies what problem type is solve in this solve loop */
3787 	
3788 	         /* if either benderssolvesubconvex or benderssolvesub are implemented, then the user callbacks are invoked */
3789 	         if( benders->benderssolvesubconvex != NULL || benders->benderssolvesub != NULL )
3790 	         {
3791 	            if( l == 0 )
3792 	               solveloop = SCIP_BENDERSSOLVELOOP_USERCONVEX;
3793 	            else
3794 	               solveloop = SCIP_BENDERSSOLVELOOP_USERCIP;
3795 	         }
3796 	         else
3797 	            solveloop = (SCIP_BENDERSSOLVELOOP) l;
3798 	
3799 	         /* solving the subproblems for this round of enforcement/checking. */
3800 	         SCIP_CALL( solveBendersSubproblems(benders, set, sol, type, solveloop, checkint, &nverified,
3801 	               solveidx, nsolveidx, &subprobsolved, &substatus, infeasible, &optimal, &stopped) );
3802 	
3803 	         /* if the solving has been stopped, then the subproblem solving and cut generation must terminate */
3804 	         if( stopped )
3805 	            break;
3806 	
3807 	         /* Generating cuts for the subproblems. Cuts are only generated when the solution is from primal heuristics,
3808 	          * relaxations or the LP
3809 	          */
3810 	         if( type != SCIP_BENDERSENFOTYPE_PSEUDO )
3811 	         {
3812 	            SCIP_CALL( generateBendersCuts(benders, set, sol, result, type, solveloop, checkint, subprobsolved,
3813 	                  substatus, solveidx, nsolveidx, &mergecands, &npriomergecands, &nmergecands, &nsolveloops) );
3814 	         }
3815 	         else
3816 	         {
3817 	            /* The first solving loop solves the convex subproblems and the convex relaxations of the CIP subproblems. The
3818 	             * second solving loop solves the CIP subproblems. The second solving loop is only called if the integer
3819 	             * feasibility is being checked and if the convex subproblems and convex relaxations are not infeasible.
3820 	             */
3821 	            if( !(*infeasible) && checkint && !SCIPbendersOnlyCheckConvexRelax(benders, SCIPsetGetSubscipsOff(set))
3822 	               && SCIPbendersGetNConvexSubproblems(benders) < SCIPbendersGetNSubproblems(benders))
3823 	               nsolveloops = 2;
3824 	         }
3825 	      }
3826 	
3827 	      nsolved += nsolveidx;
3828 	
3829 	      /* storing the indices of the subproblems for which the solving loop was executed */
3830 	      for( i = 0; i < nsolveidx; i++ )
3831 	         executedidx[nexecutedidx++] = solveidx[i];
3832 	
3833 	      /* if the result is CONSADDED or SEPARATED, then a cut is generated and no further subproblem processing is
3834 	       * required
3835 	       */
3836 	      if( (*result) == SCIP_CONSADDED || (*result) == SCIP_SEPARATED )
3837 	         break;
3838 	   }
3839 	
3840 	   /* inserting the subproblems into the priority queue for the next solve call */
3841 	   SCIP_CALL( updateSubproblemStatQueue(benders, executedidx, nexecutedidx, TRUE) );
3842 	
3843 	   if( stopped )
3844 	      goto TERMINATE;
3845 	
3846 	   allverified = (nverified == nsubproblems);
3847 	
3848 	   SCIPsetDebugMsg(set, "End Benders' decomposition subproblem solve. result %d infeasible %u auxviol %u nverified %d\n",
3849 	      *result, *infeasible, *auxviol, nverified);
3850 	
3851 	#ifdef SCIP_DEBUG
3852 	   if( (*result) == SCIP_CONSADDED )
3853 	   {
3854 	      SCIPsetDebugMsg(set, "Benders' decomposition: Cut added\n");
3855 	   }
3856 	#endif
3857 	
3858 	   /* if the number of checked pseudo solutions exceeds a set limit, then all subproblems are passed as merge
3859 	    * candidates. Currently, merging subproblems into the master problem is the only method for resolving numerical
3860 	    * troubles.
3861 	    *
3862 	    * We are only interested in the pseudo solutions that have been checked completely for integrality. This is
3863 	    * identified by checkint == TRUE. This means that the Benders' decomposition constraint is one of the last
3864 	    * constraint handlers that must resolve the infeasibility. If the Benders' decomposition framework can't resolve the
3865 	    * infeasibility, then this will result in an error.
3866 	    */
3867 	   if( type == SCIP_BENDERSENFOTYPE_PSEUDO && checkint )
3868 	   {
3869 	      benders->npseudosols++;
3870 	
3871 	      if( benders->npseudosols > BENDERS_MAXPSEUDOSOLS )
3872 	      {
3873 	         /* if a priority merge candidate already exists, then no other merge candidates need to be added.*/
3874 	         if( npriomergecands == 0 )
3875 	         {
3876 	            /* all subproblems are added to the merge candidate list. The first active subproblem is added as a
3877 	             * priority merge candidate
3878 	             */
3879 	            nmergecands = 0;
3880 	            npriomergecands = 1;
3881 	            for( i = 0; i < nsubproblems; i++ )
3882 	            {
3883 	               /* only active subproblems are added to the merge candidate list */
3884 	               if( subproblemIsActive(benders, i) )
3885 	               {
3886 	                  mergecands[nmergecands] = i;
3887 	                  nmergecands++;
3888 	               }
3889 	            }
3890 	
3891 	            SCIPverbMessage(set->scip, SCIP_VERBLEVEL_HIGH, NULL, "   The number of checked pseudo solutions exceeds the "
3892 	              "limit of %d. All active subproblems are merge candidates, with subproblem %d a priority candidate.\n",
3893 	              BENDERS_MAXPSEUDOSOLS, mergecands[0]);
3894 	         }
3895 	      }
3896 	   }
3897 	   else
3898 	      benders->npseudosols = 0;
3899 	
3900 	   /* if the result is SCIP_DIDNOTFIND, then there was a error in generating cuts in all subproblems that are not
3901 	    * optimal. This result does not cutoff any solution, so the Benders' decomposition algorithm will fail.
3902 	    *
3903 	    * It could happen that the cut strengthening approach causes an error the cut generation. In this case, an error
3904 	    * should not be thrown. So, this check will be skipped when in a strengthening round.
3905 	    * TODO: Work out a way to ensure Benders' decomposition does not terminate due to a SCIP_DIDNOTFIND result.
3906 	    */
3907 	   if( (*result) == SCIP_DIDNOTFIND && !benders->strengthenround )
3908 	   {
3909 	      if( type == SCIP_BENDERSENFOTYPE_PSEUDO )
3910 	         (*result) = SCIP_SOLVELP;
3911 	      else
3912 	         (*result) = SCIP_INFEASIBLE;
3913 	
3914 	      SCIPerrorMessage("An error was found when generating cuts for non-optimal subproblems of Benders' "
3915 	         "decomposition <%s>. Consider merging the infeasible subproblems into the master problem.\n", SCIPbendersGetName(benders));
3916 	
3917 	      /* since no other cuts are generated, then this error will result in a crash. It is possible to avoid the error,
3918 	       * by merging the affected subproblem into the master problem.
3919 	       *
3920 	       * NOTE: If the error occurs while checking solutions, i.e. SCIP_BENDERSENFOTYPE_CHECK, then it is valid to set
3921 	       * the result to SCIP_INFEASIBLE and the success flag to TRUE
3922 	       */
3923 	      if( type != SCIP_BENDERSENFOTYPE_CHECK )
3924 	         success = FALSE;
3925 	
3926 	      goto POSTSOLVE;
3927 	   }
3928 	
3929 	   if( type == SCIP_BENDERSENFOTYPE_PSEUDO )
3930 	   {
3931 	      if( (*infeasible) || !allverified )
3932 	         (*result) = SCIP_SOLVELP;
3933 	      else
3934 	      {
3935 	         (*result) = SCIP_FEASIBLE;
3936 	
3937 	         /* if the subproblems are not infeasible, but they are also not optimal. This means that there is a violation
3938 	          * in the auxiliary variable values. In this case, a feasible result is returned with the auxviol flag set to
3939 	          * TRUE.
3940 	          */
3941 	         (*auxviol) = !optimal;
3942 	      }
3943 	   }
3944 	   else if( checkint && (type == SCIP_BENDERSENFOTYPE_CHECK
3945 	         || ((*result) != SCIP_CONSADDED && (*result) != SCIP_SEPARATED)) )
3946 	   {
3947 	      /* if the subproblems are being solved as part of conscheck, then the results flag must be returned after the solving
3948 	       * has completed.
3949 	       */
3950 	      if( (*infeasible) || !allverified )
3951 	         (*result) = SCIP_INFEASIBLE;
3952 	      else
3953 	      {
3954 	         (*result) = SCIP_FEASIBLE;
3955 	
3956 	         /* if the subproblems are not infeasible, but they are also not optimal. This means that there is a violation
3957 	          * in the auxiliary variable values. In this case, a feasible result is returned with the auxviol flag set to
3958 	          * TRUE.
3959 	          */
3960 	         (*auxviol) = !optimal;
3961 	      }
3962 	   }
3963 	
3964 	POSTSOLVE:
3965 	   /* calling the post-solve call back for the Benders' decomposition algorithm. This allows the user to work directly
3966 	    * with the solved subproblems and the master problem */
3967 	   if( benders->benderspostsolve != NULL )
3968 	   {
3969 	      SCIP_Bool merged;
3970 	
3971 	      merged = FALSE;
3972 	
3973 	      SCIP_CALL( benders->benderspostsolve(set->scip, benders, sol, type, mergecands, npriomergecands, nmergecands,
3974 	            checkint, (*infeasible), &merged) );
3975 	
3976 	      if( merged )
3977 	      {
3978 	         (*result) = SCIP_CONSADDED;
3979 	
3980 	         /* since subproblems have been merged, then constraints have been added. This could resolve the unresolved
3981 	          * infeasibility, so the error has been corrected.
3982 	          */
3983 	         success = TRUE;
3984 	      }
3985 	      else if( !success )
3986 	      {
3987 	         SCIPerrorMessage("An error occurred during Benders' decomposition cut generations and no merging had been "
3988 	            "performed. It is not possible to continue solving the problem by Benders' decomposition\n");
3989 	      }
3990 	   }
3991 	
3992 	TERMINATE:
3993 	   /* if the solving process has stopped, then all subproblems need to be freed */
3994 	   if( stopped )
3995 	      nfree = nsubproblems;
3996 	   else
3997 	      nfree = nexecutedidx;
3998 	
3999 	   /* freeing the subproblems after the cuts are generated */
4000 	   subproblemcount = 0;
4001 	   while( subproblemcount < nfree )
4002 	   {
4003 	      int subidx;
4004 	
4005 	      if( stopped )
4006 	         subidx = subproblemcount;
4007 	      else
4008 	         subidx = executedidx[subproblemcount];
4009 	
4010 	      SCIP_CALL( SCIPbendersFreeSubproblem(benders, set, subidx) );
4011 	
4012 	      subproblemcount++;
4013 	   }
4014 	
4015 	#ifndef NDEBUG
4016 	   for( i = 0; i < nsubproblems; i++ )
4017 	      assert(SCIPbendersSubproblem(benders, i) == NULL
4018 	         || SCIPgetStage(SCIPbendersSubproblem(benders, i)) < SCIP_STAGE_TRANSFORMED
4019 	         || !SCIPinProbing(SCIPbendersSubproblem(benders, i))
4020 	         || !subproblemIsActive(benders, i));
4021 	#endif
4022 	
4023 	   /* increment the number of calls to the Benders' decomposition subproblem solve */
4024 	   benders->ncalls++;
4025 	
4026 	   SCIPsetDebugMsg(set, "End Benders' decomposition execution method. result %d infeasible %u auxviol %u\n", *result,
4027 	      *infeasible, *auxviol);
4028 	
4029 	   /* end timing */
4030 	   SCIPclockStop(benders->bendersclock, set);
4031 	
4032 	   /* freeing memory */
4033 	   SCIPfreeBlockMemoryArray(set->scip, &executedidx, nsubproblems);
4034 	   SCIPfreeBlockMemoryArray(set->scip, &solveidx, nsubproblems);
4035 	   SCIPfreeBlockMemoryArray(set->scip, &mergecands, nsubproblems);
4036 	   SCIPfreeBlockMemoryArray(set->scip, &substatus, nsubproblems);
4037 	   SCIPfreeBlockMemoryArray(set->scip, &subprobsolved, nsubproblems);
4038 	
4039 	   /* if there was an error in generating cuts and merging was not performed, then the solution is perturbed in an
4040 	    * attempt to generate a cut and correct the infeasibility
4041 	    */
4042 	   if( !success && !stopped )
4043 	   {
4044 	      SCIP_Bool skipsolve;
4045 	      SCIP_RESULT perturbresult;
4046 	
4047 	      skipsolve = FALSE;
4048 	
4049 	      benders->strengthenround = TRUE;
4050 	      /* if the user has not requested the solve to be skipped, then the cut strengthening is performed */
4051 	      SCIP_CALL( performInteriorSolCutStrengthening(benders, set, sol, type, checkint, TRUE, infeasible, auxviol,
4052 	            &skipsolve, &perturbresult) );
4053 	      benders->strengthenround = FALSE;
4054 	
4055 	      if( perturbresult == SCIP_CONSADDED || perturbresult == SCIP_SEPARATED )
4056 	         (*result) = perturbresult;
4057 	
4058 	      success = skipsolve;
4059 	   }
4060 	
4061 	   /* if the Benders' decomposition subproblem check stopped, then we don't have a valid result. In this case, the
4062 	    * safest thing to do is report INFEASIBLE.
4063 	    */
4064 	   if( stopped )
4065 	      (*result) = SCIP_INFEASIBLE;
4066 	
4067 	   /* if the subproblem verification identifies the solution as feasible, then a check whether slack variables have been
4068 	    * used is necessary. If any slack variables are non-zero, then the solution is reverified after the objective
4069 	    * coefficient for the slack variables is increased.
4070 	    */
4071 	   if( (*result) == SCIP_FEASIBLE )
4072 	   {
4073 	      SCIP_Bool activeslack;
4074 	
4075 	      SCIP_CALL( SCIPbendersSolSlackVarsActive(benders, &activeslack) );
4076 	      SCIPsetDebugMsg(set, "Type: %d Active slack: %u Feasibility Phase: %u\n", type, activeslack,
4077 	         benders->feasibilityphase);
4078 	      if( activeslack )
4079 	      {
4080 	         if( type == SCIP_BENDERSENFOTYPE_CHECK )
4081 	            (*result) = SCIP_INFEASIBLE;
4082 	         else
4083 	         {
4084 	            /* increasing the value of the slack variable by a factor of 10 */
4085 	            benders->slackvarcoef *= 10.0;
4086 	
4087 	            if( benders->slackvarcoef <= benders->maxslackvarcoef )
4088 	            {
4089 	               SCIPmessagePrintVerbInfo(SCIPgetMessagehdlr(set->scip), set->disp_verblevel, SCIP_VERBLEVEL_HIGH, "Increasing the slack variable coefficient to %g.\n", benders->slackvarcoef);
4090 	            }
4091 	            else
4092 	            {
4093 	               SCIPmessagePrintVerbInfo(SCIPgetMessagehdlr(set->scip), set->disp_verblevel, SCIP_VERBLEVEL_HIGH, "Fixing the slack variables to zero.\n");
4094 	            }
4095 	
4096 	            /* resolving the subproblems with an increased slack variable */
4097 	            SCIP_CALL( SCIPsolveBendersSubproblems(set->scip, benders, sol, result, infeasible, auxviol, type, checkint) );
4098 	         }
4099 	      }
4100 	      else if( benders->feasibilityphase )
4101 	      {
4102 	         if( type != SCIP_BENDERSENFOTYPE_CHECK )
4103 	         {
4104 	            /* disabling the feasibility phase */
4105 	            benders->feasibilityphase = FALSE;
4106 	
4107 	            /* resolving the subproblems with the slack variables set to zero */
4108 	            SCIP_CALL( SCIPsolveBendersSubproblems(set->scip, benders, sol, result, infeasible, auxviol, type, checkint) );
4109 	         }
4110 	      }
4111 	   }
4112 	
4113 	   if( !success )
4114 	      return SCIP_ERROR;
4115 	   else
4116 	      return SCIP_OKAY;
4117 	}
4118 	
4119 	/** solves the user-defined subproblem solving function */
4120 	static
4121 	SCIP_RETCODE executeUserDefinedSolvesub(
4122 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
4123 	   SCIP_SET*             set,                /**< global SCIP settings */
4124 	   SCIP_SOL*             sol,                /**< primal CIP solution */
4125 	   int                   probnumber,         /**< the subproblem number */
4126 	   SCIP_BENDERSSOLVELOOP solveloop,          /**< the solve loop iteration. The first iter is for LP, the second for IP */
4127 	   SCIP_Bool*            infeasible,         /**< returns whether the current subproblem is infeasible */
4128 	   SCIP_Real*            objective,          /**< the objective function value of the subproblem */
4129 	   SCIP_RESULT*          result              /**< the result from solving the subproblem */
4130 	   )
4131 	{
4132 	   assert(benders != NULL);
4133 	   assert(probnumber >= 0 && probnumber < benders->nsubproblems);
4134 	   assert(benders->benderssolvesubconvex != NULL || benders->benderssolvesub != NULL);
4135 	
4136 	   assert(solveloop == SCIP_BENDERSSOLVELOOP_USERCONVEX || solveloop == SCIP_BENDERSSOLVELOOP_USERCIP);
4137 	
4138 	   (*objective) = -SCIPsetInfinity(set);
4139 	
4140 	   /* calls the user defined subproblem solving method. Only the convex relaxations are solved during the Large
4141 	    * Neighbourhood Benders' Search. */
4142 	   if( solveloop == SCIP_BENDERSSOLVELOOP_USERCONVEX )
4143 	   {
4144 	      if( benders->benderssolvesubconvex != NULL )
4145 	      {
4146 	         SCIP_CALL( benders->benderssolvesubconvex(set->scip, benders, sol, probnumber,
4147 	               SCIPbendersOnlyCheckConvexRelax(benders, SCIPsetGetSubscipsOff(set)), objective, result) );
4148 	      }
4149 	      else
4150 	         (*result) = SCIP_DIDNOTRUN;
4151 	   }
4152 	   else if( solveloop == SCIP_BENDERSSOLVELOOP_USERCIP )
4153 	   {
4154 	      if( benders->benderssolvesub != NULL )
4155 	      {
4156 	         SCIP_CALL( benders->benderssolvesub(set->scip, benders, sol, probnumber, objective, result) );
4157 	      }
4158 	      else
4159 	         (*result) = SCIP_DIDNOTRUN;
4160 	   }
4161 	
4162 	   /* evaluate result */
4163 	   if( (*result) != SCIP_DIDNOTRUN
4164 	      && (*result) != SCIP_FEASIBLE
4165 	      && (*result) != SCIP_INFEASIBLE
4166 	      && (*result) != SCIP_UNBOUNDED )
4167 	   {
4168 	      SCIPerrorMessage("the user-defined solving method for the Benders' decomposition <%s> returned invalid result <%d>\n",
4169 	         benders->name, *result);
4170 	      return SCIP_INVALIDRESULT;
4171 	   }
4172 	
4173 	   if( (*result) == SCIP_INFEASIBLE )
4174 	      (*infeasible) = TRUE;
4175 	
4176 	   if( (*result) == SCIP_FEASIBLE
4177 	      && (SCIPsetIsInfinity(set, -(*objective)) || SCIPsetIsInfinity(set, (*objective))) )
4178 	   {
4179 	      SCIPerrorMessage("the user-defined solving method for the Benders' decomposition <%s> returned objective value %g\n",
4180 	         benders->name, (*objective));
4181 	      return SCIP_ERROR;
4182 	   }
4183 	
4184 	   /* if the result is SCIP_DIDNOTFIND, then an error is returned and SCIP will terminate. */
4185 	   if( (*result) == SCIP_DIDNOTFIND )
4186 	      return SCIP_ERROR;
4187 	   else
4188 	      return SCIP_OKAY;
4189 	}
4190 	
4191 	/** executes the subproblem solving process */
4192 	SCIP_RETCODE SCIPbendersExecSubproblemSolve(
4193 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
4194 	   SCIP_SET*             set,                /**< global SCIP settings */
4195 	   SCIP_SOL*             sol,                /**< primal CIP solution */
4196 	   int                   probnumber,         /**< the subproblem number */
4197 	   SCIP_BENDERSSOLVELOOP solveloop,          /**< the solve loop iteration. The first iter is for LP, the second for IP */
4198 	   SCIP_Bool             enhancement,        /**< is the solve performed as part of and enhancement? */
4199 	   SCIP_Bool*            solved,             /**< flag to indicate whether the subproblem was solved */
4200 	   SCIP_Bool*            infeasible,         /**< returns whether the current subproblem is infeasible */
4201 	   SCIP_BENDERSENFOTYPE  type                /**< the enforcement type calling this function */
4202 	   )
4203 	{  /*lint --e{715}*/
4204 	   SCIP* subproblem;
4205 	   SCIP_RESULT result;
4206 	   SCIP_Real objective;
4207 	   SCIP_STATUS solvestatus = SCIP_STATUS_UNKNOWN;
4208 	
4209 	   assert(benders != NULL);
4210 	   assert(probnumber >= 0 && probnumber < benders->nsubproblems);
4211 	
4212 	   SCIPsetDebugMsg(set, "Benders' decomposition: solving subproblem %d\n", probnumber);
4213 	
4214 	   result = SCIP_DIDNOTRUN;
4215 	   objective = SCIPsetInfinity(set);
4216 	
4217 	   subproblem = SCIPbendersSubproblem(benders, probnumber);
4218 	
4219 	   if( subproblem == NULL && (benders->benderssolvesubconvex == NULL || benders->benderssolvesub == NULL) )
4220 	   {
4221 	      SCIPerrorMessage("The subproblem %d is set to NULL, but both bendersSolvesubconvex%s and bendersSolvesub%s "
4222 	         "are not defined.\n", probnumber, benders->name, benders->name);
4223 	      SCIPABORT();
4224 	      return SCIP_ERROR;
4225 	   }
4226 	
4227 	   /* initially setting the solved flag to FALSE */
4228 	   (*solved) = FALSE;
4229 	
4230 	   /* if the subproblem solve callback is implemented, then that is used instead of the default setup */
4231 	   if( solveloop == SCIP_BENDERSSOLVELOOP_USERCONVEX || solveloop == SCIP_BENDERSSOLVELOOP_USERCIP )
4232 	   {
4233 	      /* calls the user defined subproblem solving method. Only the convex relaxations are solved during the Large
4234 	       * Neighbourhood Benders' Search. */
4235 	      SCIP_CALL( executeUserDefinedSolvesub(benders, set, sol, probnumber, solveloop, infeasible, &objective, &result) );
4236 	
4237 	      /* if the result is DIDNOTRUN, then the subproblem was not solved */
4238 	      (*solved) = (result != SCIP_DIDNOTRUN);
4239 	   }
4240 	   else if( subproblem != NULL )
4241 	   {
4242 	      /* setting up the subproblem */
4243 	      if( solveloop == SCIP_BENDERSSOLVELOOP_CONVEX )
4244 	      {
4245 	         SCIP_CALL( SCIPbendersSetupSubproblem(benders, set, sol, probnumber, type) );
4246 	
4247 	         /* if the limits of the master problem were hit during the setup process, then the subproblem will not have
4248 	          * been setup. In this case, the solving function must be exited.
4249 	          */
4250 	         if( !SCIPbendersSubproblemIsSetup(benders, probnumber) )
4251 	         {
4252 	            SCIPbendersSetSubproblemObjval(benders, probnumber, SCIPsetInfinity(set));
4253 	            (*solved) = FALSE;
4254 	            return SCIP_OKAY;
4255 	         }
4256 	      }
4257 	      else
4258 	      {
4259 	         SCIP_CALL( updateEventhdlrUpperbound(benders, probnumber, SCIPbendersGetAuxiliaryVarVal(benders, set, sol, probnumber)) );
4260 	      }
4261 	
4262 	      /* solving the subproblem
4263 	       * the LP of the subproblem is solved in the first solveloop.
4264 	       * In the second solve loop, the MIP problem is solved */
4265 	      if( solveloop == SCIP_BENDERSSOLVELOOP_CONVEX
4266 	         || SCIPbendersGetSubproblemType(benders, probnumber) == SCIP_BENDERSSUBTYPE_CONVEXCONT )
4267 	      {
4268 	         SCIP_CALL( SCIPbendersSolveSubproblemLP(set->scip, benders, probnumber, &solvestatus, &objective) );
4269 	
4270 	         /* if the (N)LP was solved without error, then the subproblem is labelled as solved */
4271 	         if( solvestatus == SCIP_STATUS_OPTIMAL || solvestatus == SCIP_STATUS_INFEASIBLE )
4272 	            (*solved) = TRUE;
4273 	
4274 	         if( solvestatus == SCIP_STATUS_INFEASIBLE )
4275 	            (*infeasible) = TRUE;
4276 	      }
4277 	      else
4278 	      {
4279 	         SCIP_SOL* bestsol;
4280 	
4281 	         SCIP_CALL( SCIPbendersSolveSubproblemCIP(set->scip, benders, probnumber, &solvestatus, FALSE) );
4282 	
4283 	         if( solvestatus == SCIP_STATUS_INFEASIBLE )
4284 	            (*infeasible) = TRUE;
4285 	
4286 	         /* if the generic subproblem solving methods are used, then the CIP subproblems are always solved. */
4287 	         (*solved) = TRUE;
4288 	
4289 	         bestsol = SCIPgetBestSol(subproblem);
4290 	         if( bestsol != NULL )
4291 	            objective = SCIPgetSolOrigObj(subproblem, bestsol)*(int)SCIPgetObjsense(set->scip);
4292 	         else
4293 	            objective = SCIPsetInfinity(set);
4294 	      }
4295 	   }
4296 	   else
4297 	   {
4298 	      SCIPABORT();
4299 	   }
4300 	
4301 	   if( !enhancement )
4302 	   {
4303 	      /* The following handles the cases when the subproblem is OPTIMAL, INFEASIBLE and UNBOUNDED.
4304 	       * If a subproblem is unbounded, then the auxiliary variables are set to -infinity and the unbounded flag is
4305 	       * returned as TRUE. No cut will be generated, but the result will be set to SCIP_FEASIBLE.
4306 	       */
4307 	      if( solveloop == SCIP_BENDERSSOLVELOOP_CONVEX || solveloop == SCIP_BENDERSSOLVELOOP_CIP )
4308 	      {
4309 	         /* TODO: Consider whether other solutions status should be handled */
4310 	         if( solvestatus == SCIP_STATUS_OPTIMAL )
4311 	            SCIPbendersSetSubproblemObjval(benders, probnumber, objective);
4312 	         else if( solvestatus == SCIP_STATUS_INFEASIBLE )
4313 	            SCIPbendersSetSubproblemObjval(benders, probnumber, SCIPsetInfinity(set));
4314 	         else if( solvestatus == SCIP_STATUS_USERINTERRUPT || solvestatus == SCIP_STATUS_BESTSOLLIMIT )
4315 	            SCIPbendersSetSubproblemObjval(benders, probnumber, objective);
4316 	         else if( solvestatus == SCIP_STATUS_MEMLIMIT || solvestatus == SCIP_STATUS_TIMELIMIT
4317 	            || solvestatus == SCIP_STATUS_UNKNOWN )
4318 	         {
4319 	            SCIPverbMessage(set->scip, SCIP_VERBLEVEL_FULL, NULL, "   Benders' decomposition: Error solving "
4320 	               "subproblem %d. No cut will be generated for this subproblem.\n", probnumber);
4321 	            SCIPbendersSetSubproblemObjval(benders, probnumber, SCIPsetInfinity(set));
4322 	         }
4323 	         else if( solvestatus == SCIP_STATUS_UNBOUNDED )
4324 	         {
4325 	            SCIPerrorMessage("The Benders' decomposition subproblem %d is unbounded. This should not happen.\n",
4326 	               probnumber);
4327 	            SCIPABORT();
4328 	         }
4329 	         else
4330 	         {
4331 	            SCIPerrorMessage("Invalid status returned from solving Benders' decomposition subproblem %d. Solution status: %d\n",
4332 	               probnumber, solvestatus);
4333 	            SCIPABORT();
4334 	         }
4335 	      }
4336 	      else
4337 	      {
4338 	         assert(solveloop == SCIP_BENDERSSOLVELOOP_USERCONVEX || solveloop == SCIP_BENDERSSOLVELOOP_USERCIP);
4339 	         if( result == SCIP_FEASIBLE )
4340 	            SCIPbendersSetSubproblemObjval(benders, probnumber, objective);
4341 	         else if( result == SCIP_INFEASIBLE )
4342 	            SCIPbendersSetSubproblemObjval(benders, probnumber, SCIPsetInfinity(set));
4343 	         else if( result == SCIP_UNBOUNDED )
4344 	         {
4345 	            SCIPerrorMessage("The Benders' decomposition subproblem %d is unbounded. This should not happen.\n",
4346 	               probnumber);
4347 	            SCIPABORT();
4348 	         }
4349 	         else if( result != SCIP_DIDNOTRUN )
4350 	         {
4351 	            SCIPerrorMessage("Invalid result <%d> from user-defined subproblem solving method. This should not happen.\n",
4352 	               result);
4353 	         }
4354 	      }
4355 	   }
4356 	
4357 	   return SCIP_OKAY;
4358 	}
4359 	
4360 	/** sets up the subproblem using the solution to the master problem  */
4361 	SCIP_RETCODE SCIPbendersSetupSubproblem(
4362 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
4363 	   SCIP_SET*             set,                /**< global SCIP settings */
4364 	   SCIP_SOL*             sol,                /**< primal CIP solution */
4365 	   int                   probnumber,         /**< the subproblem number */
4366 	   SCIP_BENDERSENFOTYPE  type                /**< the enforcement type calling this function */
4367 	   )
4368 	{
4369 	   SCIP* subproblem;
4370 	   SCIP_VAR** vars;
4371 	   SCIP_VAR* mastervar;
4372 	   SCIP_Real solval;
4373 	   int nvars;
4374 	   int i;
4375 	
4376 	   assert(benders != NULL);
4377 	   assert(set != NULL);
4378 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
4379 	
4380 	   subproblem = SCIPbendersSubproblem(benders, probnumber);
4381 	
4382 	   /* the subproblem setup can only be performed if the subproblem is not NULL */
4383 	   if( subproblem == NULL )
4384 	   {
4385 	      SCIPerrorMessage("The subproblem %d is NULL. Thus, the subproblem setup must be performed manually in either "
4386 	         "bendersSolvesubconvex%s or bendersSolvesub%s.\n", probnumber, benders->name, benders->name);
4387 	      return SCIP_ERROR;
4388 	   }
4389 	   assert(subproblem != NULL);
4390 	
4391 	   /* changing all of the master problem variable to continuous. */
4392 	   SCIP_CALL( SCIPbendersChgMastervarsToCont(benders, set, probnumber) );
4393 	
4394 	   /* if the Benders' decomposition subproblem is convex and has continuous variables, then probing mode
4395 	    * must be started.
4396 	    * If the subproblem contains non-convex constraints or discrete variables, then the problem must be initialised,
4397 	    * and then put into SCIP_STAGE_SOLVING to be able to change the variable bounds. The probing mode is entered once
4398 	    * the variable bounds are set.
4399 	    * In the latter case, the transformed problem is freed after each subproblem solve round. */
4400 	   if( SCIPbendersGetSubproblemType(benders, probnumber) == SCIP_BENDERSSUBTYPE_CONVEXCONT )
4401 	   {
4402 	      SCIP_CALL( SCIPstartProbing(subproblem) );
4403 	   }
4404 	   else
4405 	   {
4406 	      SCIP_Bool success;
4407 	
4408 	      SCIP_CALL( initialiseSubproblem(benders, set, probnumber, &success) );
4409 	
4410 	      if( !success )
4411 	      {
4412 	         /* set the flag to indicate that the subproblems have been set up */
4413 	         SCIPbendersSetSubproblemIsSetup(benders, probnumber, FALSE);
4414 	
4415 	         return SCIP_OKAY;
4416 	      }
4417 	   }
4418 	
4419 	   vars = SCIPgetVars(subproblem);
4420 	   nvars = SCIPgetNVars(subproblem);
4421 	
4422 	   /* looping over all variables in the subproblem to find those corresponding to the master problem variables. */
4423 	   /* TODO: It should be possible to store the pointers to the master variables to speed up the subproblem setup */
4424 	   for( i = 0; i < nvars; i++ )
4425 	   {
4426 	      SCIP_CALL( SCIPbendersGetVar(benders, set, vars[i], &mastervar, -1) );
4427 	
4428 	      if( mastervar != NULL )
4429 	      {
4430 	         /* It is possible due to numerics that the solution value exceeds the upper or lower bounds. When this
4431 	          * happens, it causes an error in the LP solver as a result of inconsistent bounds. So the following statements
4432 	          * are used to ensure that the bounds are not exceeded when applying the fixings for the Benders'
4433 	          * decomposition subproblems
4434 	          */
4435 	         solval = SCIPgetSolVal(set->scip, sol, mastervar);
4436 	         if( !SCIPisLT(set->scip, solval, SCIPvarGetUbLocal(vars[i])) )
4437 	            solval = SCIPvarGetUbLocal(vars[i]);
4438 	         else if( !SCIPisGT(set->scip, solval, SCIPvarGetLbLocal(vars[i])) )
4439 	            solval = SCIPvarGetLbLocal(vars[i]);
4440 	
4441 	         /* fixing the variable in the subproblem */
4442 	         if( !SCIPisEQ(subproblem, SCIPvarGetLbLocal(vars[i]), SCIPvarGetUbLocal(vars[i])) )
4443 	         {
4444 	            if( SCIPisGT(subproblem, solval, SCIPvarGetLbLocal(vars[i])) )
4445 	            {
4446 	               SCIP_CALL( SCIPchgVarLb(subproblem, vars[i], solval) );
4447 	            }
4448 	            if( SCIPisLT(subproblem, solval, SCIPvarGetUbLocal(vars[i])) )
4449 	            {
4450 	               SCIP_CALL( SCIPchgVarUb(subproblem, vars[i], solval) );
4451 	            }
4452 	         }
4453 	
4454 	         assert(SCIPisEQ(subproblem, SCIPvarGetLbLocal(vars[i]), SCIPvarGetUbLocal(vars[i])));
4455 	      }
4456 	      else if( strstr(SCIPvarGetName(vars[i]), SLACKVAR_NAME) != NULL )
4457 	      {
4458 	         /* if the slack variables have been added to help improve feasibility, then they remain unfixed with a large
4459 	          * objective coefficient. Once the root node has been solved to optimality, then the slack variables are
4460 	          * fixed to zero.
4461 	          */
4462 	         if( benders->feasibilityphase && SCIPgetDepth(set->scip) == 0 && type != SCIP_BENDERSENFOTYPE_CHECK )
4463 	         {
4464 	            /* The coefficient update or variable fixing can only be performed if the subproblem is in probing mode.
4465 	             * If the slack var coef gets very large, then we fix the slack variable to 0 instead.
4466 	             */
4467 	            if( SCIPinProbing(subproblem) )
4468 	            {
4469 	               if( benders->slackvarcoef <= benders->maxslackvarcoef )
4470 	               {
4471 	                  SCIP_CALL( SCIPchgVarObjProbing(subproblem, vars[i], benders->slackvarcoef) );
4472 	               }
4473 	               else
4474 	               {
4475 	                  SCIP_CALL( SCIPchgVarUbProbing(subproblem, vars[i], 0.0) );
4476 	               }
4477 	            }
4478 	         }
4479 	         else
4480 	         {
4481 	            /* if the subproblem is non-linear and convex, then slack variables have been added to the subproblem. These
4482 	             * need to be fixed to zero when first solving the subproblem. However, if the slack variables have been added
4483 	             * by setting the execfeasphase runtime parameter, then they must not get fixed to zero
4484 	             */
4485 	            assert( !SCIPisEQ(subproblem, SCIPvarGetLbLocal(vars[i]), SCIPvarGetUbLocal(vars[i])) );
4486 	            assert( SCIPisZero(subproblem, SCIPvarGetLbLocal(vars[i])) );
4487 	
4488 	            if( SCIPisLT(subproblem, 0.0, SCIPvarGetUbLocal(vars[i])) )
4489 	            {
4490 	               SCIP_CALL( SCIPchgVarUb(subproblem, vars[i], 0.0) );
4491 	            }
4492 	         }
4493 	      }
4494 	   }
4495 	
4496 	   /* if the subproblem contain non-convex constraints or discrete variables, then the probing mode is entered after
4497 	    * setting up the subproblem
4498 	    */
4499 	   if( SCIPbendersGetSubproblemType(benders, probnumber) != SCIP_BENDERSSUBTYPE_CONVEXCONT )
4500 	   {
4501 	      SCIP_CALL( SCIPstartProbing(subproblem) );
4502 	   }
4503 	
4504 	   /* set the flag to indicate that the subproblems have been set up */
4505 	   SCIPbendersSetSubproblemIsSetup(benders, probnumber, TRUE);
4506 	
4507 	   return SCIP_OKAY;
4508 	}
4509 	
4510 	/** Solve a Benders' decomposition subproblems. This will either call the user defined method or the generic solving
4511 	 *  methods. If the generic method is called, then the subproblem must be set up before calling this method. */
4512 	SCIP_RETCODE SCIPbendersSolveSubproblem(
4513 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
4514 	   SCIP_SET*             set,                /**< global SCIP settings */
4515 	   SCIP_SOL*             sol,                /**< primal CIP solution, can be NULL */
4516 	   int                   probnumber,         /**< the subproblem number */
4517 	   SCIP_Bool*            infeasible,         /**< returns whether the current subproblem is infeasible */
4518 	   SCIP_Bool             solvecip,           /**< directly solve the CIP subproblem */
4519 	   SCIP_Real*            objective           /**< the objective function value of the subproblem, can be NULL */
4520 	   )
4521 	{
4522 	   assert(benders != NULL);
4523 	   assert(set != NULL);
4524 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
4525 	
4526 	   (*infeasible) = FALSE;
4527 	
4528 	   /* the subproblem must be set up before this function is called. */
4529 	   if( SCIPbendersSubproblem(benders, probnumber) != NULL && !SCIPbendersSubproblemIsSetup(benders, probnumber)
4530 	      && !SCIPbendersSubproblemIsIndependent(benders, probnumber) )
4531 	   {
4532 	      SCIPerrorMessage("Benders' decomposition subproblem %d must be set up before calling SCIPbendersSolveSubproblem(). Call SCIPsetupSubproblem() first.\n", probnumber);
4533 	      return SCIP_ERROR;
4534 	   }
4535 	
4536 	   /* if the subproblem solve callback is implemented, then that is used instead of the default setup */
4537 	   if( benders->benderssolvesubconvex != NULL ||  benders->benderssolvesub != NULL)
4538 	   {
4539 	      SCIP_BENDERSSOLVELOOP solveloop;
4540 	      SCIP_RESULT result;
4541 	      SCIP_Real subobj;
4542 	
4543 	      if( solvecip )
4544 	         solveloop = SCIP_BENDERSSOLVELOOP_USERCIP;
4545 	      else
4546 	         solveloop = SCIP_BENDERSSOLVELOOP_USERCONVEX;
4547 	
4548 	      SCIP_CALL( executeUserDefinedSolvesub(benders, set, sol, probnumber, solveloop, infeasible, &subobj, &result) );
4549 	
4550 	      if( objective != NULL )
4551 	         (*objective) = subobj;
4552 	   }
4553 	   else
4554 	   {
4555 	      SCIP* subproblem;
4556 	
4557 	      subproblem = SCIPbendersSubproblem(benders, probnumber);
4558 	      assert(subproblem != NULL);
4559 	
4560 	      /* solving the subproblem */
4561 	      if( solvecip && SCIPbendersGetSubproblemType(benders, probnumber) != SCIP_BENDERSSUBTYPE_CONVEXCONT )
4562 	      {
4563 	         SCIP_STATUS solvestatus;
4564 	
4565 	         SCIP_CALL( SCIPbendersSolveSubproblemCIP(set->scip, benders, probnumber, &solvestatus, solvecip) );
4566 	
4567 	         if( solvestatus == SCIP_STATUS_INFEASIBLE )
4568 	            (*infeasible) = TRUE;
4569 	         if( objective != NULL )
4570 	            (*objective) = SCIPgetSolOrigObj(subproblem, SCIPgetBestSol(subproblem))*(int)SCIPgetObjsense(subproblem);
4571 	      }
4572 	      else
4573 	      {
4574 	         SCIP_Bool success;
4575 	
4576 	         /* if the subproblem has convex constraints and continuous variables, then it should have been initialised and
4577 	          * in SCIP_STAGE_SOLVING. In this case, the subproblem only needs to be put into probing mode.
4578 	          */
4579 	         if( SCIPbendersGetSubproblemType(benders, probnumber) == SCIP_BENDERSSUBTYPE_CONVEXCONT )
4580 	         {
4581 	            /* if the subproblem is not in probing mode, then it must be put into that mode for the LP solve. */
4582 	            if( !SCIPinProbing(subproblem) )
4583 	            {
4584 	               SCIP_CALL( SCIPstartProbing(subproblem) );
4585 	            }
4586 	
4587 	            success = TRUE;
4588 	         }
4589 	         else
4590 	         {
4591 	            SCIP_CALL( initialiseSubproblem(benders, set, probnumber, &success) );
4592 	         }
4593 	
4594 	         /* if setting up the subproblem was successful */
4595 	         if( success )
4596 	         {
4597 	            SCIP_STATUS solvestatus;
4598 	            SCIP_Real lpobjective;
4599 	
4600 	            SCIP_CALL( SCIPbendersSolveSubproblemLP(set->scip, benders, probnumber, &solvestatus, &lpobjective) );
4601 	
4602 	            if( solvestatus == SCIP_STATUS_INFEASIBLE )
4603 	               (*infeasible) = TRUE;
4604 	            else if( objective != NULL )
4605 	               (*objective) = lpobjective;
4606 	         }
4607 	         else
4608 	         {
4609 	            if( objective != NULL )
4610 	               (*objective) = SCIPinfinity(subproblem);
4611 	         }
4612 	      }
4613 	   }
4614 	
4615 	   return SCIP_OKAY;
4616 	}
4617 	
4618 	/** copies the time and memory limit from the master problem to the subproblem */
4619 	static
4620 	SCIP_RETCODE copyMemoryAndTimeLimits(
4621 	   SCIP*                 scip,               /**< the SCIP data structure */
4622 	   SCIP*                 subproblem          /**< the Benders' decomposition subproblem */
4623 	   )
4624 	{
4625 	   SCIP_Real mastertimelimit;
4626 	   SCIP_Real subtimelimit;
4627 	   SCIP_Real maxsubtimelimit;
4628 	   SCIP_Real mastermemorylimit;
4629 	   SCIP_Real submemorylimit;
4630 	   SCIP_Real maxsubmemorylimit;
4631 	
4632 	   assert(scip != NULL);
4633 	
4634 	   /* setting the time limit for the Benders' decomposition subproblems. It is set to 102% of the remaining time. */
4635 	   SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &mastertimelimit) );
4636 	   maxsubtimelimit = SCIPparamGetRealMax(SCIPgetParam(subproblem, "limits/time"));
4637 	   subtimelimit = (mastertimelimit - SCIPgetSolvingTime(scip)) * 1.02;
4638 	   subtimelimit = MIN(subtimelimit, maxsubtimelimit);
4639 	   SCIP_CALL( SCIPsetRealParam(subproblem, "limits/time", MAX(0.0, subtimelimit)) );
4640 	
4641 	   /* setting the memory limit for the Benders' decomposition subproblems. */
4642 	   SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &mastermemorylimit) );
4643 	   maxsubmemorylimit = SCIPparamGetRealMax(SCIPgetParam(subproblem, "limits/memory"));
4644 	   submemorylimit = mastermemorylimit - (SCIPgetMemUsed(scip) + SCIPgetMemExternEstim(scip))/1048576.0;
4645 	   submemorylimit = MIN(submemorylimit, maxsubmemorylimit);
4646 	   SCIP_CALL( SCIPsetRealParam(subproblem, "limits/memory", MAX(0.0, submemorylimit)) );
4647 	
4648 	   return SCIP_OKAY;
4649 	}
4650 	
4651 	/** stores the original parameters from the subproblem */
4652 	static
4653 	SCIP_RETCODE storeOrigSubproblemParams(
4654 	   SCIP*                 subproblem,         /**< the SCIP data structure */
4655 	   SCIP_SUBPROBPARAMS*   origparams          /**< the original subproblem parameters */
4656 	   )
4657 	{
4658 	   assert(subproblem != NULL);
4659 	   assert(origparams != NULL);
4660 	
4661 	   SCIP_CALL( SCIPgetRealParam(subproblem, "limits/memory", &origparams->limits_memory) );
4662 	   SCIP_CALL( SCIPgetRealParam(subproblem, "limits/time", &origparams->limits_time) );
4663 	   SCIP_CALL( SCIPgetBoolParam(subproblem, "conflict/enable", &origparams->conflict_enable) );
4664 	   SCIP_CALL( SCIPgetIntParam(subproblem, "lp/disablecutoff", &origparams->lp_disablecutoff) );
4665 	   SCIP_CALL( SCIPgetIntParam(subproblem, "lp/scaling", &origparams->lp_scaling) );
4666 	   SCIP_CALL( SCIPgetCharParam(subproblem, "lp/initalgorithm", &origparams->lp_initalg) );
4667 	   SCIP_CALL( SCIPgetCharParam(subproblem, "lp/resolvealgorithm", &origparams->lp_resolvealg) );
4668 	   SCIP_CALL( SCIPgetBoolParam(subproblem, "lp/alwaysgetduals", &origparams->lp_alwaysgetduals) );
4669 	   SCIP_CALL( SCIPgetBoolParam(subproblem, "misc/scaleobj", &origparams->misc_scaleobj) );
4670 	   SCIP_CALL( SCIPgetBoolParam(subproblem, "misc/catchctrlc", &origparams->misc_catchctrlc) );
4671 	   SCIP_CALL( SCIPgetIntParam(subproblem, "propagating/maxrounds", &origparams->prop_maxrounds) );
4672 	   SCIP_CALL( SCIPgetIntParam(subproblem, "propagating/maxroundsroot", &origparams->prop_maxroundsroot) );
4673 	   SCIP_CALL( SCIPgetIntParam(subproblem, "constraints/linear/propfreq", &origparams->cons_linear_propfreq) );
4674 	
4675 	   return SCIP_OKAY;
4676 	}
4677 	
4678 	/** sets the parameters for the subproblem */
4679 	static
4680 	SCIP_RETCODE setSubproblemParams(
4681 	   SCIP*                 scip,               /**< the SCIP data structure */
4682 	   SCIP*                 subproblem          /**< the subproblem SCIP instance */
4683 	   )
4684 	{
4685 	   assert(scip != NULL);
4686 	   assert(subproblem != NULL);
4687 	
4688 	   /* copying memory and time limits */
4689 	   SCIP_CALL( copyMemoryAndTimeLimits(scip, subproblem) );
4690 	
4691 	   /* Do we have to disable presolving? If yes, we have to store all presolving parameters. */
4692 	   SCIP_CALL( SCIPsetPresolving(subproblem, SCIP_PARAMSETTING_OFF, TRUE) );
4693 	
4694 	   /* Disabling heuristics so that the problem is not trivially solved */
4695 	   SCIP_CALL( SCIPsetHeuristics(subproblem, SCIP_PARAMSETTING_OFF, TRUE) );
4696 	
4697 	   /* store parameters that are changed for the generation of the subproblem cuts */
4698 	   SCIP_CALL( SCIPsetBoolParam(subproblem, "conflict/enable", FALSE) );
4699 	
4700 	   SCIP_CALL( SCIPsetIntParam(subproblem, "lp/disablecutoff", 1) );
4701 	   SCIP_CALL( SCIPsetIntParam(subproblem, "lp/scaling", 0) );
4702 	
4703 	   SCIP_CALL( SCIPsetCharParam(subproblem, "lp/initalgorithm", 'd') );
4704 	   SCIP_CALL( SCIPsetCharParam(subproblem, "lp/resolvealgorithm", 'd') );
4705 	
4706 	   SCIP_CALL( SCIPsetBoolParam(subproblem, "lp/alwaysgetduals", TRUE) );
4707 	   SCIP_CALL( SCIPsetBoolParam(subproblem, "misc/scaleobj", FALSE) );
4708 	
4709 	   /* do not abort subproblem on CTRL-C */
4710 	   SCIP_CALL( SCIPsetBoolParam(subproblem, "misc/catchctrlc", FALSE) );
4711 	
4712 	#ifndef SCIP_MOREDEBUG
4713 	   SCIP_CALL( SCIPsetIntParam(subproblem, "display/verblevel", (int)SCIP_VERBLEVEL_NONE) );
4714 	#endif
4715 	
4716 	   SCIP_CALL( SCIPsetIntParam(subproblem, "propagating/maxrounds", 0) );
4717 	   SCIP_CALL( SCIPsetIntParam(subproblem, "propagating/maxroundsroot", 0) );
4718 	
4719 	   SCIP_CALL( SCIPsetIntParam(subproblem, "constraints/linear/propfreq", -1) );
4720 	
4721 	   SCIP_CALL( SCIPsetIntParam(subproblem, "heuristics/alns/freq", -1) );
4722 	
4723 	   SCIP_CALL( SCIPsetIntParam(subproblem, "separating/aggregation/freq", -1) );
4724 	   SCIP_CALL( SCIPsetIntParam(subproblem, "separating/gomory/freq", -1) );
4725 	
4726 	   return SCIP_OKAY;
4727 	}
4728 	
4729 	/** resets the original parameters from the subproblem */
4730 	static
4731 	SCIP_RETCODE resetOrigSubproblemParams(
4732 	   SCIP*                 subproblem,         /**< the SCIP data structure */
4733 	   SCIP_SUBPROBPARAMS*   origparams          /**< the original subproblem parameters */
4734 	   )
4735 	{
4736 	   assert(subproblem != NULL);
4737 	   assert(origparams != NULL);
4738 	
4739 	   SCIP_CALL( SCIPsetRealParam(subproblem, "limits/memory", origparams->limits_memory) );
4740 	   SCIP_CALL( SCIPsetRealParam(subproblem, "limits/time", origparams->limits_time) );
4741 	   SCIP_CALL( SCIPsetBoolParam(subproblem, "conflict/enable", origparams->conflict_enable) );
4742 	   SCIP_CALL( SCIPsetIntParam(subproblem, "lp/disablecutoff", origparams->lp_disablecutoff) );
4743 	   SCIP_CALL( SCIPsetIntParam(subproblem, "lp/scaling", origparams->lp_scaling) );
4744 	   SCIP_CALL( SCIPsetCharParam(subproblem, "lp/initalgorithm", origparams->lp_initalg) );
4745 	   SCIP_CALL( SCIPsetCharParam(subproblem, "lp/resolvealgorithm", origparams->lp_resolvealg) );
4746 	   SCIP_CALL( SCIPsetBoolParam(subproblem, "lp/alwaysgetduals", origparams->lp_alwaysgetduals) );
4747 	   SCIP_CALL( SCIPsetBoolParam(subproblem, "misc/scaleobj", origparams->misc_scaleobj) );
4748 	   SCIP_CALL( SCIPsetBoolParam(subproblem, "misc/catchctrlc", origparams->misc_catchctrlc) );
4749 	   SCIP_CALL( SCIPsetIntParam(subproblem, "propagating/maxrounds", origparams->prop_maxrounds) );
4750 	   SCIP_CALL( SCIPsetIntParam(subproblem, "propagating/maxroundsroot", origparams->prop_maxroundsroot) );
4751 	   SCIP_CALL( SCIPsetIntParam(subproblem, "constraints/linear/propfreq", origparams->cons_linear_propfreq) );
4752 	
4753 	   return SCIP_OKAY;
4754 	}
4755 	
4756 	/** returns NLP solver parameters used for solving NLP subproblems */
4757 	SCIP_NLPPARAM SCIPbendersGetNLPParam(
4758 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
4759 	)
4760 	{
4761 	   assert(benders != NULL);
4762 	
4763 	   return benders->nlpparam;
4764 	}
4765 	
4766 	/** solves the LP of the Benders' decomposition subproblem
4767 	 *
4768 	 *  This requires that the subproblem is in probing mode.
4769 	 */
4770 	SCIP_RETCODE SCIPbendersSolveSubproblemLP(
4771 	   SCIP*                 scip,               /**< the SCIP data structure */
4772 	   SCIP_BENDERS*         benders,            /**< the Benders' decomposition data structure */
4773 	   int                   probnumber,         /**< the subproblem number */
4774 	   SCIP_STATUS*          solvestatus,        /**< status of subproblem solve */
4775 	   SCIP_Real*            objective           /**< optimal value of subproblem, if solved to optimality */
4776 	   )
4777 	{
4778 	   SCIP* subproblem;
4779 	   SCIP_SUBPROBPARAMS* origparams;
4780 	   SCIP_Bool solvenlp;
4781 	
4782 	   assert(benders != NULL);
4783 	   assert(solvestatus != NULL);
4784 	   assert(objective != NULL);
4785 	   assert(SCIPbendersSubproblemIsSetup(benders, probnumber));
4786 	
4787 	   /* TODO: This should be solved just as an LP, so as a MIP. There is too much overhead with the MIP.
4788 	    * Need to change status check for checking the LP. */
4789 	   subproblem = SCIPbendersSubproblem(benders, probnumber);
4790 	   assert(subproblem != NULL);
4791 	
4792 	   /* only solve the NLP relaxation if the NLP has been constructed and there exists an NLPI. If it is not possible to
4793 	    * solve the NLP relaxation, then the LP relaxation is used to generate Benders' cuts
4794 	    */
4795 	   solvenlp = FALSE;
4796 	   if( SCIPisNLPConstructed(subproblem) && SCIPgetNNlpis(subproblem) > 0
4797 	      && SCIPbendersGetSubproblemType(benders, probnumber) <= SCIP_BENDERSSUBTYPE_CONVEXDIS )
4798 	      solvenlp = TRUE;
4799 	
4800 	   *objective = SCIPinfinity(subproblem);
4801 	
4802 	   assert(SCIPisNLPConstructed(subproblem) || SCIPisLPConstructed(subproblem));
4803 	   assert(SCIPinProbing(subproblem));
4804 	
4805 	   /* allocating memory for the parameter storage */
4806 	   SCIP_CALL( SCIPallocBlockMemory(subproblem, &origparams) );
4807 	
4808 	   /* store the original parameters of the subproblem */
4809 	   SCIP_CALL( storeOrigSubproblemParams(subproblem, origparams) );
4810 	
4811 	   /* setting the subproblem parameters */
4812 	   SCIP_CALL( setSubproblemParams(scip, subproblem) );
4813 	
4814 	   if( solvenlp )
4815 	   {
4816 	      SCIP_NLPSOLSTAT nlpsolstat;
4817 	      SCIP_NLPTERMSTAT nlptermstat;
4818 	#ifdef SCIP_MOREDEBUG
4819 	      SCIP_SOL* nlpsol;
4820 	#endif
4821 	
4822 	      SCIP_CALL( SCIPsolveNLPParam(subproblem, benders->nlpparam) );
4823 	
4824 	      nlpsolstat = SCIPgetNLPSolstat(subproblem);
4825 	      nlptermstat = SCIPgetNLPTermstat(subproblem);
4826 	      SCIPdebugMsg(scip, "NLP solstat %d termstat %d\n", nlpsolstat, nlptermstat);
4827 	
4828 	      if( nlptermstat == SCIP_NLPTERMSTAT_OKAY && (nlpsolstat == SCIP_NLPSOLSTAT_LOCINFEASIBLE || nlpsolstat == SCIP_NLPSOLSTAT_GLOBINFEASIBLE) )
4829 	      {
4830 	         /* trust infeasible only if terminated "okay" */
4831 	         (*solvestatus) = SCIP_STATUS_INFEASIBLE;
4832 	      }
4833 	      else if( nlpsolstat == SCIP_NLPSOLSTAT_LOCOPT || nlpsolstat == SCIP_NLPSOLSTAT_GLOBOPT
4834 	         || nlpsolstat == SCIP_NLPSOLSTAT_FEASIBLE )
4835 	      {
4836 	#ifdef SCIP_MOREDEBUG
4837 	         SCIP_CALL( SCIPcreateNLPSol(subproblem, &nlpsol, NULL) );
4838 	         SCIP_CALL( SCIPprintSol(subproblem, nlpsol, NULL, FALSE) );
4839 	         SCIP_CALL( SCIPfreeSol(subproblem, &nlpsol) );
4840 	#endif
4841 	
4842 	         (*solvestatus) = SCIP_STATUS_OPTIMAL;
4843 	         (*objective) = SCIPretransformObj(subproblem, SCIPgetNLPObjval(subproblem));
4844 	      }
4845 	      else if( nlpsolstat == SCIP_NLPSOLSTAT_UNBOUNDED )
4846 	      {
4847 	         (*solvestatus) = SCIP_STATUS_UNBOUNDED;
4848 	         SCIPerrorMessage("The NLP of Benders' decomposition subproblem %d is unbounded. This should not happen.\n",
4849 	            probnumber);
4850 	         SCIPABORT();
4851 	      }
4852 	      else if( nlptermstat == SCIP_NLPTERMSTAT_TIMELIMIT )
4853 	      {
4854 	         (*solvestatus) = SCIP_STATUS_TIMELIMIT;
4855 	      }
4856 	      else if( nlptermstat == SCIP_NLPTERMSTAT_ITERLIMIT)
4857 	      {
4858 	         /* this is an approximation in lack of a better fitting SCIP_STATUS */
4859 	         SCIPwarningMessage(scip, "The NLP solver stopped due to an iteration limit for Benders' decomposition subproblem %d. Consider increasing benders/%s/nlpiterlimit.\n", probnumber, SCIPbendersGetName(benders));
4860 	         (*solvestatus) = SCIP_STATUS_TIMELIMIT;
4861 	      }
4862 	      else if( nlptermstat == SCIP_NLPTERMSTAT_INTERRUPT )
4863 	      {
4864 	         (*solvestatus) = SCIP_STATUS_USERINTERRUPT;
4865 	      }
4866 	      else
4867 	      {
4868 	         SCIPerrorMessage("Invalid solution status: %d. Termination status: %d. Solving the NLP relaxation of Benders' decomposition subproblem %d.\n",
4869 	            nlpsolstat, nlptermstat, probnumber);
4870 	         SCIPABORT();
4871 	      }
4872 	   }
4873 	   else
4874 	   {
4875 	      SCIP_Bool lperror;
4876 	      SCIP_Bool cutoff;
4877 	
4878 	      SCIP_CALL( SCIPsolveProbingLP(subproblem, -1, &lperror, &cutoff) );
4879 	
4880 	      switch( SCIPgetLPSolstat(subproblem) )
4881 	      {
4882 	         case SCIP_LPSOLSTAT_INFEASIBLE:
4883 	         {
4884 	            (*solvestatus) = SCIP_STATUS_INFEASIBLE;
4885 	            break;
4886 	         }
4887 	
4888 	         case SCIP_LPSOLSTAT_OPTIMAL :
4889 	         {
4890 	            (*solvestatus) = SCIP_STATUS_OPTIMAL;
4891 	            (*objective) = SCIPgetSolOrigObj(subproblem, NULL)*(int)SCIPgetObjsense(scip);
4892 	            break;
4893 	         }
4894 	
4895 	         case SCIP_LPSOLSTAT_UNBOUNDEDRAY :
4896 	         {
4897 	            (*solvestatus) = SCIP_STATUS_UNBOUNDED;
4898 	            SCIPerrorMessage("The LP of Benders' decomposition subproblem %d is unbounded. This should not happen.\n",
4899 	               probnumber);
4900 	            SCIPABORT();
4901 	            break;
4902 	         }
4903 	
4904 	         case SCIP_LPSOLSTAT_ERROR :
4905 	         case SCIP_LPSOLSTAT_NOTSOLVED :
4906 	         case SCIP_LPSOLSTAT_TIMELIMIT :
4907 	         {
4908 	            if( SCIPgetLPSolstat(subproblem) == SCIP_LPSOLSTAT_TIMELIMIT )
4909 	               (*solvestatus) = SCIP_STATUS_TIMELIMIT;
4910 	            else
4911 	               (*solvestatus) = SCIP_STATUS_UNKNOWN;
4912 	
4913 	            SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL, "   Benders' decomposition: Error solving LP "
4914 	               "relaxation of subproblem %d. No cut will be generated for this subproblem.\n", probnumber);
4915 	            break;
4916 	         }
4917 	
4918 	         case SCIP_LPSOLSTAT_OBJLIMIT:
4919 	         case SCIP_LPSOLSTAT_ITERLIMIT:
4920 	         default:
4921 	         {
4922 	            SCIPerrorMessage("Invalid status: %d. Solving the LP relaxation of Benders' decomposition subproblem %d.\n",
4923 	               SCIPgetLPSolstat(subproblem), probnumber);
4924 	            SCIPABORT();
4925 	            break;
4926 	         }
4927 	      }
4928 	   }
4929 	
4930 	   /* resetting the subproblem parameters */
4931 	   SCIP_CALL( resetOrigSubproblemParams(subproblem, origparams) );
4932 	
4933 	   /* freeing the parameter storage */
4934 	   SCIPfreeBlockMemory(subproblem, &origparams);
4935 	
4936 	   return SCIP_OKAY;
4937 	}
4938 	
4939 	/** solves the Benders' decomposition subproblem */
4940 	SCIP_RETCODE SCIPbendersSolveSubproblemCIP(
4941 	   SCIP*                 scip,               /**< the SCIP data structure */
4942 	   SCIP_BENDERS*         benders,            /**< the Benders' decomposition data structure */
4943 	   int                   probnumber,         /**< the subproblem number */
4944 	   SCIP_STATUS*          solvestatus,        /**< status of subproblem solve */
4945 	   SCIP_Bool             solvecip            /**< directly solve the CIP subproblem */
4946 	   )
4947 	{
4948 	   SCIP* subproblem;
4949 	   SCIP_SUBPROBPARAMS* origparams;
4950 	
4951 	   assert(benders != NULL);
4952 	   assert(solvestatus != NULL);
4953 	
4954 	   subproblem = SCIPbendersSubproblem(benders, probnumber);
4955 	   assert(subproblem != NULL);
4956 	
4957 	   /* allocating memory for the parameter storage */
4958 	   SCIP_CALL( SCIPallocBlockMemory(subproblem, &origparams) );
4959 	
4960 	   /* store the original parameters of the subproblem */
4961 	   SCIP_CALL( storeOrigSubproblemParams(subproblem, origparams) );
4962 	
4963 	   /* If the solve has been stopped for the subproblem, then we need to restart it to complete the solve. The subproblem
4964 	    * is stopped when it is a MIP so that LP cuts and IP cuts can be generated. */
4965 	   if( SCIPgetStage(subproblem) == SCIP_STAGE_SOLVING )
4966 	   {
4967 	      /* the subproblem should be in probing mode. Otherwise, the event handler did not work correctly */
4968 	      assert( SCIPinProbing(subproblem) );
4969 	
4970 	      /* the probing mode needs to be stopped so that the MIP can be solved */
4971 	      SCIP_CALL( SCIPendProbing(subproblem) );
4972 	
4973 	      /* the problem was interrupted in the event handler, so SCIP needs to be informed that the problem is to be restarted */
4974 	      SCIP_CALL( SCIPrestartSolve(subproblem) );
4975 	   }
4976 	   else if( solvecip )
4977 	   {
4978 	      /* if the MIP will be solved directly, then the probing mode needs to be skipped.
4979 	       * This is achieved by setting the solvecip flag in the event handler data to TRUE
4980 	       */
4981 	      SCIP_EVENTHDLR* eventhdlr;
4982 	      SCIP_EVENTHDLRDATA* eventhdlrdata;
4983 	
4984 	      eventhdlr = SCIPfindEventhdlr(subproblem, MIPNODEFOCUS_EVENTHDLR_NAME);
4985 	      eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
4986 	
4987 	      eventhdlrdata->solvecip = TRUE;
4988 	   }
4989 	   else
4990 	   {
4991 	      /* if the problem is not in probing mode, then we need to solve the LP. That requires all methods that will
4992 	       * modify the structure of the problem need to be deactivated */
4993 	
4994 	      /* setting the subproblem parameters */
4995 	      SCIP_CALL( setSubproblemParams(scip, subproblem) );
4996 	
4997 	#ifdef SCIP_EVENMOREDEBUG
4998 	      SCIP_CALL( SCIPsetBoolParam(subproblem, "display/lpinfo", TRUE) );
4999 	#endif
5000 	   }
5001 	
5002 	#ifdef SCIP_MOREDEBUG
5003 	      SCIP_CALL( SCIPsetIntParam(subproblem, "display/verblevel", (int)SCIP_VERBLEVEL_FULL) );
5004 	      SCIP_CALL( SCIPsetIntParam(subproblem, "display/freq", 1) );
5005 	#endif
5006 	
5007 	   SCIP_CALL( SCIPsolve(subproblem) );
5008 	
5009 	   *solvestatus = SCIPgetStatus(subproblem);
5010 	
5011 	   if( *solvestatus != SCIP_STATUS_OPTIMAL && *solvestatus != SCIP_STATUS_UNBOUNDED
5012 	      && *solvestatus != SCIP_STATUS_INFEASIBLE && *solvestatus != SCIP_STATUS_USERINTERRUPT
5013 	      && *solvestatus != SCIP_STATUS_BESTSOLLIMIT && *solvestatus != SCIP_STATUS_TIMELIMIT
5014 	      && *solvestatus != SCIP_STATUS_MEMLIMIT )
5015 	   {
5016 	      SCIPerrorMessage("Invalid status: %d. Solving the CIP of Benders' decomposition subproblem %d.\n",
5017 	         *solvestatus, probnumber);
5018 	      SCIPABORT();
5019 	   }
5020 	
5021 	   /* resetting the subproblem parameters */
5022 	   SCIP_CALL( resetOrigSubproblemParams(subproblem, origparams) );
5023 	
5024 	   /* freeing the parameter storage */
5025 	   SCIPfreeBlockMemory(subproblem, &origparams);
5026 	
5027 	   return SCIP_OKAY;
5028 	}
5029 	
5030 	/** frees the subproblems */
5031 	SCIP_RETCODE SCIPbendersFreeSubproblem(
5032 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5033 	   SCIP_SET*             set,                /**< global SCIP settings */
5034 	   int                   probnumber          /**< the subproblem number */
5035 	   )
5036 	{
5037 	   assert(benders != NULL);
5038 	   assert(benders->bendersfreesub != NULL
5039 	      || (benders->bendersfreesub == NULL && benders->benderssolvesubconvex == NULL && benders->benderssolvesub == NULL));
5040 	   assert(probnumber >= 0 && probnumber < benders->nsubproblems);
5041 	
5042 	   if( benders->bendersfreesub != NULL )
5043 	   {
5044 	      SCIP_CALL( benders->bendersfreesub(set->scip, benders, probnumber) );
5045 	   }
5046 	   else
5047 	   {
5048 	      /* the subproblem is only freed if it is not independent */
5049 	      if( subproblemIsActive(benders, probnumber) )
5050 	      {
5051 	         SCIP* subproblem = SCIPbendersSubproblem(benders, probnumber);
5052 	
5053 	         if( SCIPbendersGetSubproblemType(benders, probnumber) == SCIP_BENDERSSUBTYPE_CONVEXCONT )
5054 	         {
5055 	            /* ending probing mode to reset the current node. The probing mode will be restarted at the next solve */
5056 	            if( SCIPinProbing(subproblem) )
5057 	            {
5058 	               SCIP_CALL( SCIPendProbing(subproblem) );
5059 	            }
5060 	         }
5061 	         else
5062 	         {
5063 	            /* if the subproblems were solved as part of an enforcement stage, then they will still be in probing mode. The
5064 	             * probing mode must first be finished and then the problem can be freed */
5065 	            if( SCIPgetStage(subproblem) >= SCIP_STAGE_TRANSFORMED && SCIPinProbing(subproblem) )
5066 	            {
5067 	               SCIP_CALL( SCIPendProbing(subproblem) );
5068 	            }
5069 	
5070 	            SCIP_CALL( SCIPfreeTransform(subproblem) );
5071 	         }
5072 	      }
5073 	   }
5074 	
5075 	   /* setting the setup flag for the subproblem to FALSE */
5076 	   SCIPbendersSetSubproblemIsSetup(benders, probnumber, FALSE);
5077 	   return SCIP_OKAY;
5078 	}
5079 	
5080 	/** compares the subproblem objective value with the auxiliary variable value for optimality */
5081 	SCIP_Bool SCIPbendersSubproblemIsOptimal(
5082 	   SCIP_BENDERS*         benders,            /**< the benders' decomposition structure */
5083 	   SCIP_SET*             set,                /**< global SCIP settings */
5084 	   SCIP_SOL*             sol,                /**< primal CIP solution */
5085 	   int                   probnumber          /**< the subproblem number */
5086 	   )
5087 	{
5088 	   SCIP_Real auxiliaryvarval;
5089 	   SCIP_Bool optimal;
5090 	
5091 	   assert(benders != NULL);
5092 	   assert(set != NULL);
5093 	   assert(probnumber >= 0 && probnumber < benders->nsubproblems);
5094 	
5095 	   optimal = FALSE;
5096 	
5097 	   auxiliaryvarval = SCIPbendersGetAuxiliaryVarVal(benders, set, sol, probnumber);
5098 	
5099 	   SCIPsetDebugMsg(set, "Subproblem %d - Auxiliary Variable: %g Subproblem Objective: %g Reldiff: %g Soltol: %g\n",
5100 	      probnumber, auxiliaryvarval, SCIPbendersGetSubproblemObjval(benders, probnumber),
5101 	      SCIPrelDiff(SCIPbendersGetSubproblemObjval(benders, probnumber), auxiliaryvarval), benders->solutiontol);
5102 	
5103 	   if( SCIPrelDiff(SCIPbendersGetSubproblemObjval(benders, probnumber), auxiliaryvarval) < benders->solutiontol )
5104 	      optimal = TRUE;
5105 	
5106 	   return optimal;
5107 	}
5108 	
5109 	/** returns the value of the auxiliary variable value in a master problem solution */
5110 	SCIP_Real SCIPbendersGetAuxiliaryVarVal(
5111 	   SCIP_BENDERS*         benders,            /**< the benders' decomposition structure */
5112 	   SCIP_SET*             set,                /**< global SCIP settings */
5113 	   SCIP_SOL*             sol,                /**< primal CIP solution */
5114 	   int                   probnumber          /**< the subproblem number */
5115 	   )
5116 	{
5117 	   SCIP_VAR* auxiliaryvar;
5118 	
5119 	   assert(benders != NULL);
5120 	   assert(set != NULL);
5121 	
5122 	   auxiliaryvar = SCIPbendersGetAuxiliaryVar(benders, probnumber);
5123 	   assert(auxiliaryvar != NULL);
5124 	
5125 	   return SCIPgetSolVal(set->scip, sol, auxiliaryvar);
5126 	}
5127 	
5128 	/** Solves an independent subproblem to identify its lower bound. The lower bound is then used to update the bound on
5129 	 *  the auxiliary variable.
5130 	 */
5131 	SCIP_RETCODE SCIPbendersComputeSubproblemLowerbound(
5132 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5133 	   SCIP_SET*             set,                /**< global SCIP settings */
5134 	   int                   probnumber,         /**< the subproblem to be evaluated */
5135 	   SCIP_Real*            lowerbound,         /**< the lowerbound for the subproblem */
5136 	   SCIP_Bool*            infeasible          /**< was the subproblem found to be infeasible? */
5137 	   )
5138 	{
5139 	   SCIP* subproblem;
5140 	   SCIP_Real dualbound;
5141 	   SCIP_Real memorylimit;
5142 	   SCIP_Real timelimit;
5143 	   SCIP_Longint totalnodes;
5144 	   int disablecutoff;
5145 	   int verblevel;
5146 	   SCIP_Bool lperror;
5147 	   SCIP_Bool cutoff;
5148 	
5149 	   assert(benders != NULL);
5150 	   assert(set != NULL);
5151 	
5152 	   if( benders->benderssolvesub != NULL || benders->benderssolvesubconvex != NULL )
5153 	   {
5154 	      (*lowerbound) = SCIPvarGetLbGlobal(SCIPbendersGetAuxiliaryVar(benders, probnumber));
5155 	      (*infeasible) = FALSE;
5156 	
5157 	      SCIPinfoMessage(set->scip, NULL, "Benders' decomposition: a bendersSolvesub or bendersSolvesubconvex has been "
5158 	         "implemented. SCIPbendersComputeSubproblemLowerbound can not be executed.\n");
5159 	      SCIPinfoMessage(set->scip, NULL, "Set the auxiliary variable lower bound by calling "
5160 	         "SCIPbendersUpdateSubproblemLowerbound in bendersCreatesub. The auxiliary variable %d will remain as %g\n",
5161 	         probnumber, (*lowerbound));
5162 	
5163 	      return SCIP_OKAY;
5164 	   }
5165 	   else
5166 	   {
5167 	      SCIPverbMessage(set->scip, SCIP_VERBLEVEL_FULL, NULL, "Benders' decomposition: Computing a lower bound for"
5168 	         " subproblem %d\n", probnumber);
5169 	   }
5170 	
5171 	   /* getting the subproblem to evaluate */
5172 	   subproblem = SCIPbendersSubproblem(benders, probnumber);
5173 	
5174 	   (*lowerbound) = -SCIPinfinity(subproblem);
5175 	   (*infeasible) = FALSE;
5176 	
5177 	   SCIP_CALL( SCIPgetIntParam(subproblem, "display/verblevel", &verblevel) );
5178 	   SCIP_CALL( SCIPsetIntParam(subproblem, "display/verblevel", (int)SCIP_VERBLEVEL_NONE) );
5179 	#ifdef SCIP_MOREDEBUG
5180 	   SCIP_CALL( SCIPsetIntParam(subproblem, "display/verblevel", (int)SCIP_VERBLEVEL_HIGH) );
5181 	#endif
5182 	
5183 	   /* copying memory and time limits */
5184 	   SCIP_CALL( SCIPgetRealParam(subproblem, "limits/time", &timelimit) );
5185 	   SCIP_CALL( SCIPgetRealParam(subproblem, "limits/memory", &memorylimit) );
5186 	   SCIP_CALL( copyMemoryAndTimeLimits(set->scip, subproblem) );
5187 	
5188 	   /* if the subproblem is independent, then the default SCIP settings are used. Otherwise, only the root node is solved
5189 	    * to compute a lower bound on the subproblem
5190 	    */
5191 	   SCIP_CALL( SCIPgetLongintParam(subproblem, "limits/totalnodes", &totalnodes) );
5192 	   SCIP_CALL( SCIPgetIntParam(subproblem, "lp/disablecutoff", &disablecutoff) );
5193 	   if( !SCIPbendersSubproblemIsIndependent(benders, probnumber) )
5194 	   {
5195 	      SCIP_CALL( SCIPsetLongintParam(subproblem, "limits/totalnodes", 1LL) );
5196 	      SCIP_CALL( SCIPsetIntParam(subproblem, "lp/disablecutoff", 1) );
5197 	   }
5198 	
5199 	   /* if the subproblem not independent and is convex, then the probing LP is solved. Otherwise, the MIP is solved */
5200 	   dualbound = -SCIPinfinity(subproblem);
5201 	   if( SCIPbendersGetSubproblemType(benders, probnumber) == SCIP_BENDERSSUBTYPE_CONVEXCONT )
5202 	   {
5203 	      SCIP_Bool solvenlp = FALSE;
5204 	
5205 	      assert(SCIPisLPConstructed(subproblem) || SCIPisNLPConstructed(subproblem));
5206 	
5207 	      if( SCIPisNLPConstructed(subproblem) && SCIPgetNNlpis(subproblem) > 0
5208 	         && SCIPbendersGetSubproblemType(benders, probnumber) <= SCIP_BENDERSSUBTYPE_CONVEXDIS )
5209 	         solvenlp = TRUE;
5210 	
5211 	      SCIP_CALL( SCIPstartProbing(subproblem) );
5212 	      if( solvenlp )
5213 	      {
5214 	         SCIP_NLPSOLSTAT nlpsolstat;
5215 	         SCIP_NLPTERMSTAT nlptermstat;
5216 	
5217 	         SCIP_CALL( SCIPsolveNLPParam(subproblem, benders->nlpparam) );
5218 	
5219 	         nlpsolstat = SCIPgetNLPSolstat(subproblem);
5220 	         nlptermstat = SCIPgetNLPTermstat(subproblem);
5221 	         SCIPdebugMsg(set->scip, "NLP solstat %d termstat %d\n", nlpsolstat, nlptermstat);
5222 	
5223 	         if( nlptermstat == SCIP_NLPTERMSTAT_OKAY && (nlpsolstat == SCIP_NLPSOLSTAT_LOCINFEASIBLE || nlpsolstat == SCIP_NLPSOLSTAT_GLOBINFEASIBLE) )
5224 	         {
5225 	            /* trust infeasible only if terminated "okay" */
5226 	            (*infeasible) = TRUE;
5227 	         }
5228 	         else if( nlpsolstat == SCIP_NLPSOLSTAT_LOCOPT || nlpsolstat == SCIP_NLPSOLSTAT_GLOBOPT )
5229 	         {
5230 	            dualbound = SCIPretransformObj(subproblem, SCIPgetNLPObjval(subproblem));
5231 	         }
5232 	      }
5233 	      else
5234 	      {
5235 	         SCIP_CALL( SCIPsolveProbingLP(subproblem, -1, &lperror, &cutoff) );
5236 	
5237 	         if( SCIPgetLPSolstat(subproblem) == SCIP_LPSOLSTAT_INFEASIBLE )
5238 	            (*infeasible) = TRUE;
5239 	         else if( SCIPgetLPSolstat(subproblem) == SCIP_LPSOLSTAT_OPTIMAL )
5240 	            dualbound = SCIPgetSolOrigObj(subproblem, NULL)*(int)SCIPgetObjsense(set->scip);
5241 	      }
5242 	   }
5243 	   else
5244 	   {
5245 	      SCIP_EVENTHDLRDATA* eventhdlrdata;
5246 	
5247 	      /* if the subproblem is not convex, then event handlers have been added to interrupt the solve. These must be
5248 	       * disabled
5249 	       */
5250 	      eventhdlrdata = SCIPeventhdlrGetData(SCIPfindEventhdlr(subproblem, MIPNODEFOCUS_EVENTHDLR_NAME));
5251 	      eventhdlrdata->solvecip = TRUE;
5252 	
5253 	      SCIP_CALL( SCIPsolve(subproblem) );
5254 	
5255 	      if( SCIPgetStatus(subproblem) == SCIP_STATUS_INFEASIBLE )
5256 	         (*infeasible) = TRUE;
5257 	      else
5258 	         dualbound = SCIPgetDualbound(subproblem);
5259 	   }
5260 	
5261 	   /* getting the lower bound value */
5262 	   (*lowerbound) = dualbound;
5263 	
5264 	   if( !SCIPbendersSubproblemIsIndependent(benders, probnumber) )
5265 	   {
5266 	      SCIP_CALL( SCIPsetLongintParam(subproblem, "limits/totalnodes", totalnodes) );
5267 	      SCIP_CALL( SCIPsetIntParam(subproblem, "lp/disablecutoff", disablecutoff) );
5268 	   }
5269 	   SCIP_CALL( SCIPsetIntParam(subproblem, "display/verblevel", verblevel) );
5270 	   SCIP_CALL( SCIPsetRealParam(subproblem, "limits/memory", memorylimit) );
5271 	   SCIP_CALL( SCIPsetRealParam(subproblem, "limits/time", timelimit) );
5272 	
5273 	   /* the subproblem must be freed so that it is reset for the subsequent Benders' decomposition solves. If the
5274 	    * subproblems are independent, they are not freed. SCIPfreeBendersSubproblem must still be called, but in this
5275 	    * function the independent subproblems are not freed. However, they will still be freed at the end of the
5276 	    * solving process for the master problem.
5277 	    */
5278 	   SCIP_CALL( SCIPbendersFreeSubproblem(benders, set, probnumber) );
5279 	
5280 	   return SCIP_OKAY;
5281 	}
5282 	
5283 	/** Merges a subproblem into the master problem. This process just adds a copy of the subproblem variables and
5284 	 *  constraints to the master problem, but keeps the subproblem stored in the Benders' decomposition data structure. The reason for
5285 	 *  keeping the subproblem available is for when it is queried for solutions after the problem is solved.
5286 	 *
5287 	 *  Once the subproblem is merged into the master problem, then the subproblem is flagged as disabled. This means that
5288 	 *  it will not be solved in the subsequent subproblem solving loops.
5289 	 *
5290 	 *  The associated auxiliary variables are kept in the master problem. The objective function of the merged subproblem
5291 	 *  is added as an underestimator constraint.
5292 	 */
5293 	SCIP_RETCODE SCIPbendersMergeSubproblemIntoMaster(
5294 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5295 	   SCIP_SET*             set,                /**< global SCIP settings */
5296 	   SCIP_HASHMAP*         varmap,             /**< a hashmap to store the mapping of subproblem variables corresponding
5297 	                                              *   to the newly created master variables, or NULL */
5298 	   SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of subproblem constraints to the
5299 	                                              *   corresponding newly created constraints, or NULL */
5300 	   int                   probnumber          /**< the number of the subproblem that will be merged into the master problem*/
5301 	   )
5302 	{
5303 	   SCIP* subproblem;
5304 	   SCIP_HASHMAP* localvarmap;
5305 	   SCIP_HASHMAP* localconsmap;
5306 	   SCIP_VAR** vars;
5307 	   SCIP_VAR* auxiliaryvar;
5308 	   SCIP_CONS** conss;
5309 	   SCIP_CONS* objcons;
5310 	   int nvars;
5311 	   int nconss;
5312 	   int i;
5313 	   SCIP_Bool uselocalvarmap;
5314 	   SCIP_Bool uselocalconsmap;
5315 	   char varname[SCIP_MAXSTRLEN];
5316 	   char consname[SCIP_MAXSTRLEN];
5317 	   const char* origvarname;
5318 	
5319 	   assert(benders != NULL);
5320 	   assert(set != NULL);
5321 	   assert(probnumber >= 0 && probnumber < benders->nsubproblems);
5322 	
5323 	   SCIPverbMessage(set->scip, SCIP_VERBLEVEL_HIGH, NULL, "   Benders' decomposition: Infeasibility of subproblem %d can't "
5324 	      "be resolved. Subproblem %d is being merged into the master problem.\n", probnumber, probnumber);
5325 	
5326 	   /* freeing the subproblem because it will be flagged as independent. Since the subproblem is flagged as independent,
5327 	    * it will no longer be solved or freed within the solving loop.
5328 	    */
5329 	   SCIP_CALL( SCIPbendersFreeSubproblem(benders, set, probnumber) );
5330 	
5331 	   subproblem = SCIPbendersSubproblem(benders, probnumber);
5332 	
5333 	   uselocalvarmap = (varmap == NULL);
5334 	   uselocalconsmap = (consmap == NULL);
5335 	
5336 	   if( uselocalvarmap )
5337 	   {
5338 	      /* create the variable mapping hash map */
5339 	      SCIP_CALL( SCIPhashmapCreate(&localvarmap, SCIPblkmem(set->scip), SCIPgetNVars(subproblem)) );
5340 	   }
5341 	   else
5342 	      localvarmap = varmap;
5343 	
5344 	   if( uselocalconsmap )
5345 	   {
5346 	      /* create the constraint mapping hash map */
5347 	      SCIP_CALL( SCIPhashmapCreate(&localconsmap, SCIPblkmem(set->scip), SCIPgetNConss(subproblem)) );
5348 	   }
5349 	   else
5350 	      localconsmap = consmap;
5351 	
5352 	   /* retrieving the subproblem variable to build a subproblem mapping */
5353 	   vars = SCIPgetVars(subproblem);
5354 	   nvars = SCIPgetNVars(subproblem);
5355 	
5356 	   /* creating the objective function constraint that will be added to the master problem */
5357 	   /* setting the name of the transferred cut */
5358 	   (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "objectivecons_%d", probnumber );
5359 	   SCIP_CALL( SCIPcreateConsBasicLinear(set->scip, &objcons, consname, 0, NULL, NULL, -SCIPsetInfinity(set), 0.0) );
5360 	   SCIP_CALL( SCIPsetConsRemovable(set->scip, objcons, TRUE) );
5361 	
5362 	   for( i = 0; i < nvars; i++ )
5363 	   {
5364 	      SCIP_VAR* mastervar = NULL;
5365 	      SCIP_Bool releasevar = FALSE;
5366 	
5367 	      SCIP_CALL( SCIPgetBendersMasterVar(set->scip, benders, vars[i], &mastervar) );
5368 	
5369 	      /* if the master problem variable is not NULL, then there is a corresponding variable in the master problem for
5370 	       * the given subproblem variable. In this case, the variable is added to the hashmap.
5371 	       */
5372 	      if( mastervar == NULL )
5373 	      {
5374 	         SCIP_VAR* origvar;
5375 	         SCIP_Real scalar;
5376 	         SCIP_Real constant;
5377 	
5378 	         /* This is following the same process as in createVariableMappings. The original variable is used to map
5379 	          * between the subproblem and the master problem
5380 	          */
5381 	         origvar = vars[i];
5382 	         scalar = 1.0;
5383 	         constant = 0.0;
5384 	         SCIP_CALL( SCIPvarGetOrigvarSum(&origvar, &scalar, &constant) );
5385 	
5386 	         /* retrieving the var name */
5387 	         origvarname = SCIPvarGetName(origvar);
5388 	         (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s", origvarname);
5389 	
5390 	         /* creating and adding the variable to the Benders' decomposition master problem */
5391 	         SCIP_CALL( SCIPcreateVarBasic(set->scip, &mastervar, varname, SCIPvarGetLbOriginal(origvar),
5392 	            SCIPvarGetUbOriginal(origvar), 0.0, SCIPvarGetType(origvar)) );
5393 	
5394 	         /* adding the variable to the master problem */
5395 	         SCIP_CALL( SCIPaddVar(set->scip, mastervar) );
5396 	
5397 	         /* adds the variable to the objective function constraint */
5398 	         SCIP_CALL( SCIPaddCoefLinear(set->scip, objcons, mastervar, SCIPvarGetObj(origvar)) );
5399 	
5400 	         /* the variable must be released */
5401 	         releasevar = TRUE;
5402 	      }
5403 	
5404 	      /* creating the mapping betwen the subproblem var and the master var for the constraint copying */
5405 	      SCIP_CALL( SCIPhashmapInsert(localvarmap, vars[i], mastervar) );
5406 	
5407 	      /* releasing the variable */
5408 	      if( releasevar )
5409 	      {
5410 	         SCIP_CALL( SCIPreleaseVar(set->scip, &mastervar) );
5411 	      }
5412 	   }
5413 	
5414 	   /* getting the constraints from the subproblem that will be added to the master problem */
5415 	   conss = SCIPgetConss(subproblem);
5416 	   nconss = SCIPgetNConss(subproblem);
5417 	
5418 	   /* getting a copy of all constraints and adding it to the master problem */
5419 	   for( i = 0; i < nconss; i++ )
5420 	   {
5421 	      SCIP_CONS* targetcons;
5422 	      SCIP_Bool initial;
5423 	      SCIP_Bool valid;
5424 	
5425 	      /* NOTE: adding all subproblem constraints appears to cause an error when resolving the LP, which results in the
5426 	       * current incumbent being reported as optimal. To avoid this, only half of the subproblem constraints are added
5427 	       * the master problem. The remaining half are marked as lazy and are separated as required.
5428 	       */
5429 	      initial = (i < nconss/2);
5430 	
5431 	      SCIP_CALL( SCIPgetConsCopy(subproblem, set->scip, conss[i], &targetcons, SCIPconsGetHdlr(conss[i]),
5432 	         localvarmap, localconsmap, NULL, initial, SCIPconsIsSeparated(conss[i]),
5433 	         SCIPconsIsEnforced(conss[i]), SCIPconsIsChecked(conss[i]), SCIPconsIsPropagated(conss[i]), FALSE,
5434 	         SCIPconsIsModifiable(conss[i]), SCIPconsIsDynamic(conss[i]), SCIPconsIsRemovable(conss[i]),
5435 	         FALSE, TRUE, &valid) );
5436 	      assert(SCIPconsIsInitial(conss[i]));
5437 	      assert(valid);
5438 	
5439 	      SCIP_CALL( SCIPaddCons(set->scip, targetcons) );
5440 	
5441 	      SCIP_CALL( SCIPreleaseCons(set->scip, &targetcons) );
5442 	   }
5443 	
5444 	   /* freeing the hashmaps */
5445 	   if( uselocalvarmap )
5446 	   {
5447 	      /* free hash map */
5448 	      SCIPhashmapFree(&localvarmap);
5449 	   }
5450 	
5451 	   if( uselocalconsmap )
5452 	   {
5453 	      /* free hash map */
5454 	      SCIPhashmapFree(&localconsmap);
5455 	   }
5456 	
5457 	   /* adding the auxiliary variable to the objective constraint */
5458 	   auxiliaryvar = SCIPbendersGetAuxiliaryVar(benders, probnumber);
5459 	   SCIP_CALL( SCIPaddCoefLinear(set->scip, objcons, auxiliaryvar, -1.0) );
5460 	
5461 	   /* adding the objective function constraint to the master problem */
5462 	   SCIP_CALL( SCIPaddCons(set->scip, objcons) );
5463 	
5464 	   SCIP_CALL( SCIPreleaseCons(set->scip, &objcons) );
5465 	
5466 	   /* the merged subproblem is no longer solved. This is indicated by setting the subproblem as disabled. The
5467 	    * subproblem still exists, but it is not solved in the solving loop.
5468 	    */
5469 	   SCIPbendersSetSubproblemEnabled(benders, probnumber, FALSE);
5470 	
5471 	   return SCIP_OKAY;
5472 	}
5473 	
5474 	/** when applying a decomposition from a supplied format, constraints must be transferred from the master problem to the
5475 	 *  subproblem. This is achieved by adding new constraints to the subproblem
5476 	 */
5477 	static
5478 	SCIP_RETCODE addConstraintToBendersSubproblem(
5479 	   SCIP_SET*             set,                /**< global SCIP settings */
5480 	   SCIP*                 subproblem,         /**< the SCIP instance for the subproblem */
5481 	   SCIP_HASHMAP*         varmap,             /**< the variable hash map mapping the source variables to the target variables */
5482 	   SCIP_CONS*            sourcecons          /**< the constraint that being added to the subproblem */
5483 	   )
5484 	{
5485 	   SCIP* scip;
5486 	   SCIP_CONS* cons;
5487 	   SCIP_VAR** consvars;
5488 	   int nconsvars;
5489 	   int i;
5490 	   SCIP_Bool success;
5491 	
5492 	   assert(set != NULL);
5493 	   assert(subproblem != NULL);
5494 	   assert(varmap != NULL);
5495 	   assert(sourcecons != NULL);
5496 	
5497 	   SCIPdebugMessage("Adding constraint <%s> to Benders' decomposition subproblem\n", SCIPconsGetName(sourcecons));
5498 	
5499 	   scip = set->scip;
5500 	
5501 	   /* getting the variables that are in the constraint */
5502 	   SCIP_CALL( SCIPgetConsNVars(scip, sourcecons, &nconsvars, &success) );
5503 	   SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
5504 	
5505 	   SCIP_CALL( SCIPgetConsVars(scip, sourcecons, consvars, nconsvars, &success) );
5506 	   assert(success);
5507 	
5508 	   /* checking all variables to see whether they already exist in the subproblem. If they don't exist, then the variable
5509 	    * is created
5510 	    */
5511 	   for( i = 0; i < nconsvars; i++ )
5512 	   {
5513 	      /* if the variable is not in the hashmap, then it doesn't exist in the subproblem */
5514 	      if( !SCIPhashmapExists(varmap, consvars[i]) )
5515 	      {
5516 	         SCIP_VAR* var;
5517 	
5518 	         /* creating a variable as a copy of the original variable. */
5519 	         SCIP_CALL( SCIPcreateVar(subproblem, &var, SCIPvarGetName(consvars[i]), SCIPvarGetLbGlobal(consvars[i]),
5520 	               SCIPvarGetUbGlobal(consvars[i]), SCIPvarGetObj(consvars[i]), SCIPvarGetType(consvars[i]),
5521 	               SCIPvarIsInitial(consvars[i]), SCIPvarIsRemovable(consvars[i]), NULL, NULL, NULL, NULL, NULL) );
5522 	
5523 	         /* adding the variable to the subproblem */
5524 	         SCIP_CALL( SCIPaddVar(subproblem, var) );
5525 	
5526 	         /* adding the variable to the hash map so that it is copied correctly in the constraint */
5527 	         SCIP_CALL( SCIPhashmapInsert(varmap, consvars[i], var) );
5528 	
5529 	         /* releasing the variable */
5530 	         SCIP_CALL( SCIPreleaseVar(subproblem, &var) );
5531 	      }
5532 	   }
5533 	
5534 	   /* freeing the buffer memory for the consvars */
5535 	   SCIPfreeBufferArray(scip, &consvars);
5536 	
5537 	   /* copying the constraint from the master scip to the subproblem */
5538 	   SCIP_CALL( SCIPgetConsCopy(scip, subproblem, sourcecons, &cons, SCIPconsGetHdlr(sourcecons), varmap, NULL,
5539 	         SCIPconsGetName(sourcecons), SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
5540 	         SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons), SCIPconsIsMarkedPropagate(sourcecons),
5541 	         SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
5542 	         SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons), TRUE, &success) );
5543 	
5544 	   /* if the copy failed, then the subproblem for the decomposition could not be performed. */
5545 	   if( !success )
5546 	   {
5547 	      SCIPerrorMessage("It is not possible to copy constraint <%s>. Benders' decomposition could not be applied.\n",
5548 	         SCIPconsGetName(sourcecons));
5549 	      return SCIP_ERROR;
5550 	   }
5551 	
5552 	   SCIP_CALL( SCIPaddCons(subproblem, cons) );
5553 	   SCIP_CALL( SCIPreleaseCons(subproblem, &cons) );
5554 	
5555 	   return SCIP_OKAY;
5556 	}
5557 	
5558 	/** removes the variables and constraints from the master problem that have been transferred to a subproblem when the
5559 	 *  decomposition was applied.
5560 	 */
5561 	static
5562 	SCIP_RETCODE removeVariablesAndConstraintsFromMaster(
5563 	   SCIP*                 scip,               /**< the SCIP data structure */
5564 	   SCIP_CONS**           conss,              /**< the master problem constraints */
5565 	   SCIP_VAR**            vars,               /**< the master problem variables, can be NULL */
5566 	   int*                  conslabels,         /**< the labels indicating the block for each constraint */
5567 	   int*                  varslabels,         /**< the labels indicating the block for each variable, can be NULL */
5568 	   int                   nconss,             /**< the number of constraints */
5569 	   int                   nvars               /**< the number of variables */
5570 	   )
5571 	{
5572 	   int i;
5573 	
5574 	   assert(scip != NULL);
5575 	   assert(conss != NULL);
5576 	   assert(conslabels != NULL);
5577 	   assert((vars != NULL && varslabels != NULL) || (vars == NULL && varslabels == NULL));
5578 	
5579 	   /* removing constraints */
5580 	   for( i = nconss - 1; i >= 0; i-- )
5581 	   {
5582 	      if( conslabels[i] >= 0 && !SCIPconsIsDeleted(conss[i]) )
5583 	         SCIP_CALL( SCIPdelCons(scip, conss[i]) );
5584 	   }
5585 	
5586 	   /* removing variables */
5587 	   if( SCIPgetStage(scip) == SCIP_STAGE_PROBLEM && vars != NULL && varslabels != NULL )
5588 	   {
5589 	      for( i = nvars - 1; i >= 0; i-- )
5590 	      {
5591 	         if( varslabels[i] >= 0 && !SCIPvarIsDeleted(vars[i]) )
5592 	         {
5593 	            SCIP_Bool deleted;
5594 	
5595 	            SCIP_CALL( SCIPdelVar(scip, vars[i], &deleted) );
5596 	            assert(deleted);
5597 	         }
5598 	      }
5599 	   }
5600 	
5601 	   return SCIP_OKAY;
5602 	}
5603 	
5604 	/** Applies a Benders' decomposition to the problem based upon the decomposition selected from the storage */
5605 	SCIP_RETCODE SCIPbendersApplyDecomposition(
5606 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5607 	   SCIP_SET*             set,                /**< global SCIP settings */
5608 	   SCIP_DECOMP*          decomp              /**< the decomposition to apply to the problem */
5609 	   )
5610 	{
5611 	   SCIP** subproblems;
5612 	   SCIP_VAR** vars;
5613 	   SCIP_CONS** conss;
5614 	   SCIP_HASHMAP** varmaps;
5615 	   int* varslabels;
5616 	   int* conslabels;
5617 	   int nvars;
5618 	   int nconss;
5619 	   int nblocks;
5620 	   int i;
5621 	   char subprobname[SCIP_MAXSTRLEN];
5622 	
5623 	   assert(benders != NULL);
5624 	   assert(set != NULL);
5625 	   assert(decomp != NULL);
5626 	
5627 	   SCIPdebugMessage("Applying a Benders' decomposition to <%s>\n", SCIPgetProbName(set->scip));
5628 	
5629 	   /* retrieving the number of blocks for this decomposition */
5630 	   nblocks = SCIPdecompGetNBlocks(decomp);
5631 	   assert(nblocks > 0);
5632 	
5633 	   /* initialising the subproblems for the Benders' decomposition */
5634 	   SCIP_CALL( SCIPallocBufferArray(set->scip, &subproblems, nblocks) );
5635 	
5636 	   /* creating the subproblems before adding the constraints */
5637 	   for( i = 0; i < nblocks; i++ )
5638 	   {
5639 	      SCIP_Bool valid;
5640 	
5641 	      SCIP_CALL( SCIPcreate(&subproblems[i]) );
5642 	
5643 	      /* copying the plugins from the original SCIP instance to the subproblem SCIP */
5644 	      SCIP_CALL( SCIPcopyPlugins(set->scip, subproblems[i], TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
5645 	            TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, &valid) );
5646 	
5647 	      (void) SCIPsnprintf(subprobname, SCIP_MAXSTRLEN, "sub_%s_%d", SCIPgetProbName(set->scip), i);
5648 	      SCIP_CALL( SCIPcreateProbBasic(subproblems[i], subprobname) );
5649 	   }
5650 	
5651 	   /* TODO: Need to work out whether a check for original and transformed problem is necessary */
5652 	
5653 	   /* getting the variables and constraints from the problem */
5654 	   SCIP_CALL( SCIPgetVarsData(set->scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
5655 	   conss = SCIPgetConss(set->scip);
5656 	   nconss = SCIPgetNConss(set->scip);
5657 	
5658 	   /* allocating buffer memory for the labels arrays */
5659 	   SCIP_CALL( SCIPallocBufferArray(set->scip, &varslabels, nvars) );
5660 	   SCIP_CALL( SCIPallocBufferArray(set->scip, &conslabels, nconss) );
5661 	
5662 	   /* getting the labels for the variables and constraints from the decomposition */
5663 	   SCIPdecompGetVarsLabels(decomp, vars, varslabels, nvars);
5664 	   SCIPdecompGetConsLabels(decomp, conss, conslabels, nconss);
5665 	
5666 	   /* creating the variable maps for adding the constraints to the subproblems */
5667 	   SCIP_CALL( SCIPallocBufferArray(set->scip, &varmaps, nblocks) );
5668 	
5669 	   for( i = 0; i < nblocks; i++ )
5670 	   {
5671 	      SCIP_CALL( SCIPhashmapCreate(&varmaps[i], SCIPblkmem(subproblems[i]), nvars) );
5672 	   }
5673 	
5674 	   /* copying the constraints to the appropriate subproblems */
5675 	   for( i = 0; i < nconss; i++ )
5676 	   {
5677 	      /* we are only interested in the constraints that are in the blocks. These are identified by a label >= 0 */
5678 	      if( conslabels[i] >= 0 )
5679 	      {
5680 	         SCIP_CALL( addConstraintToBendersSubproblem(set, subproblems[conslabels[i]], varmaps[conslabels[i]],
5681 	               conss[i]) );
5682 	      }
5683 	   }
5684 	
5685 	   /* removing the variables and constraints from the master problem that have been added to the subproblem */
5686 	   SCIP_CALL( removeVariablesAndConstraintsFromMaster(set->scip, conss, vars, conslabels, varslabels, nconss, nvars) );
5687 	
5688 	   /* creating the Benders' decomposition my calling the default plugin */
5689 	   SCIP_CALL( SCIPcreateBendersDefault(set->scip, subproblems, nblocks) );
5690 	
5691 	   /* flag to the Benders' decomposition core that the subproblems need to be freed */
5692 	   benders->freesubprobs = TRUE;
5693 	
5694 	   /* activating the Benders' constraint handler for the scenario stages.
5695 	    * TODO: consider whether the two-phase method should be activated by default in the scenario stages.
5696 	    */
5697 	   SCIP_CALL( SCIPsetBoolParam(set->scip, "constraints/benders/active", TRUE) );
5698 	
5699 	   /* changing settings that are required for Benders' decomposition */
5700 	   SCIP_CALL( SCIPsetPresolving(set->scip, SCIP_PARAMSETTING_OFF, TRUE) );
5701 	   SCIP_CALL( SCIPsetIntParam(set->scip, "propagating/maxrounds", 0) );
5702 	   SCIP_CALL( SCIPsetIntParam(set->scip, "propagating/maxroundsroot", 0) );
5703 	   SCIP_CALL( SCIPsetIntParam(set->scip, "heuristics/trysol/freq", 1) );
5704 	
5705 	   /* disabling aggregation since it can affect the mapping between the master and subproblem variables */
5706 	   SCIP_CALL( SCIPsetBoolParam(set->scip, "presolving/donotaggr", TRUE) );
5707 	   SCIP_CALL( SCIPsetBoolParam(set->scip, "presolving/donotmultaggr", TRUE) );
5708 	
5709 	   /* freeing the allocated memory */
5710 	   for( i = nblocks - 1; i >= 0; i-- )
5711 	   {
5712 	      SCIPhashmapFree(&varmaps[i]);
5713 	   }
5714 	
5715 	   SCIPfreeBufferArray(set->scip, &varmaps);
5716 	   SCIPfreeBufferArray(set->scip, &conslabels);
5717 	   SCIPfreeBufferArray(set->scip, &varslabels);
5718 	   SCIPfreeBufferArray(set->scip, &subproblems);
5719 	
5720 	   return SCIP_OKAY;
5721 	}
5722 	
5723 	/** Returns the corresponding master or subproblem variable for the given variable.
5724 	 *  This provides a call back for the variable mapping between the master and subproblems. */
5725 	SCIP_RETCODE SCIPbendersGetVar(
5726 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5727 	   SCIP_SET*             set,                /**< global SCIP settings */
5728 	   SCIP_VAR*             var,                /**< the variable for which the corresponding variable is desired */
5729 	   SCIP_VAR**            mappedvar,          /**< the variable that is mapped to var */
5730 	   int                   probnumber          /**< the problem number for the desired variable, -1 for the master problem */
5731 	   )
5732 	{
5733 	   assert(benders != NULL);
5734 	   assert(set != NULL);
5735 	   assert(var != NULL);
5736 	   assert(mappedvar != NULL);
5737 	   assert(benders->bendersgetvar != NULL);
5738 	
5739 	   (*mappedvar) = NULL;
5740 	
5741 	   /* if the variable name matches the auxiliary variable, then the master variable is returned as NULL */
5742 	   if( strstr(SCIPvarGetName(var), AUXILIARYVAR_NAME) != NULL )
5743 	      return SCIP_OKAY;
5744 	
5745 	   SCIP_CALL( benders->bendersgetvar(set->scip, benders, var, mappedvar, probnumber) );
5746 	
5747 	   return SCIP_OKAY;
5748 	}
5749 	
5750 	/** gets user data of Benders' decomposition */
5751 	SCIP_BENDERSDATA* SCIPbendersGetData(
5752 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
5753 	   )
5754 	{
5755 	   assert(benders != NULL);
5756 	
5757 	   return benders->bendersdata;
5758 	}
5759 	
5760 	/** sets user data of Benders' decomposition; user has to free old data in advance! */
5761 	void SCIPbendersSetData(
5762 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5763 	   SCIP_BENDERSDATA*     bendersdata         /**< new Benders' decomposition user data */
5764 	   )
5765 	{
5766 	   assert(benders != NULL);
5767 	
5768 	   benders->bendersdata = bendersdata;
5769 	}
5770 	
5771 	/** sets copy callback of Benders' decomposition */
5772 	void SCIPbendersSetCopy(
5773 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5774 	   SCIP_DECL_BENDERSCOPY ((*benderscopy))    /**< copy callback of Benders' decomposition */
5775 	   )
5776 	{
5777 	   assert(benders != NULL);
5778 	
5779 	   benders->benderscopy = benderscopy;
5780 	}
5781 	
5782 	/** sets destructor callback of Benders' decomposition */
5783 	void SCIPbendersSetFree(
5784 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5785 	   SCIP_DECL_BENDERSFREE ((*bendersfree))    /**< destructor of Benders' decomposition */
5786 	   )
5787 	{
5788 	   assert(benders != NULL);
5789 	
5790 	   benders->bendersfree = bendersfree;
5791 	}
5792 	
5793 	/** sets initialization callback of Benders' decomposition */
5794 	void SCIPbendersSetInit(
5795 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5796 	   SCIP_DECL_BENDERSINIT((*bendersinit))     /**< initialize the Benders' decomposition */
5797 	   )
5798 	{
5799 	   assert(benders != NULL);
5800 	
5801 	   benders->bendersinit = bendersinit;
5802 	}
5803 	
5804 	/** sets deinitialization callback of Benders' decomposition */
5805 	void SCIPbendersSetExit(
5806 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5807 	   SCIP_DECL_BENDERSEXIT((*bendersexit))     /**< deinitialize the Benders' decomposition */
5808 	   )
5809 	{
5810 	   assert(benders != NULL);
5811 	
5812 	   benders->bendersexit = bendersexit;
5813 	}
5814 	
5815 	/** sets presolving initialization callback of Benders' decomposition */
5816 	void SCIPbendersSetInitpre(
5817 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5818 	   SCIP_DECL_BENDERSINITPRE((*bendersinitpre))/**< initialize presolving for Benders' decomposition */
5819 	   )
5820 	{
5821 	   assert(benders != NULL);
5822 	
5823 	   benders->bendersinitpre = bendersinitpre;
5824 	}
5825 	
5826 	/** sets presolving deinitialization callback of Benders' decomposition */
5827 	void SCIPbendersSetExitpre(
5828 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5829 	   SCIP_DECL_BENDERSEXITPRE((*bendersexitpre))/**< deinitialize presolving for Benders' decomposition */
5830 	   )
5831 	{
5832 	   assert(benders != NULL);
5833 	
5834 	   benders->bendersexitpre = bendersexitpre;
5835 	}
5836 	
5837 	/** sets solving process initialization callback of Benders' decomposition */
5838 	void SCIPbendersSetInitsol(
5839 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5840 	   SCIP_DECL_BENDERSINITSOL((*bendersinitsol))/**< solving process initialization callback of Benders' decomposition */
5841 	   )
5842 	{
5843 	   assert(benders != NULL);
5844 	
5845 	   benders->bendersinitsol = bendersinitsol;
5846 	}
5847 	
5848 	/** sets solving process deinitialization callback of Benders' decomposition */
5849 	void SCIPbendersSetExitsol(
5850 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5851 	   SCIP_DECL_BENDERSEXITSOL((*bendersexitsol))/**< solving process deinitialization callback of Benders' decomposition */
5852 	   )
5853 	{
5854 	   assert(benders != NULL);
5855 	
5856 	   benders->bendersexitsol = bendersexitsol;
5857 	}
5858 	
5859 	/** sets the pre subproblem solve callback of Benders' decomposition */
5860 	void SCIPbendersSetPresubsolve(
5861 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5862 	   SCIP_DECL_BENDERSPRESUBSOLVE((*benderspresubsolve))/**< called prior to the subproblem solving loop */
5863 	   )
5864 	{
5865 	   assert(benders != NULL);
5866 	
5867 	   benders->benderspresubsolve = benderspresubsolve;
5868 	}
5869 	
5870 	/** sets convex solve callback of Benders' decomposition */
5871 	void SCIPbendersSetSolvesubconvex(
5872 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5873 	   SCIP_DECL_BENDERSSOLVESUBCONVEX((*benderssolvesubconvex))/**< solving method for the convex Benders' decomposition subproblem */
5874 	   )
5875 	{
5876 	   assert(benders != NULL);
5877 	
5878 	   benders->benderssolvesubconvex = benderssolvesubconvex;
5879 	}
5880 	
5881 	/** sets solve callback of Benders' decomposition */
5882 	void SCIPbendersSetSolvesub(
5883 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5884 	   SCIP_DECL_BENDERSSOLVESUB((*benderssolvesub))/**< solving method for a Benders' decomposition subproblem */
5885 	   )
5886 	{
5887 	   assert(benders != NULL);
5888 	
5889 	   benders->benderssolvesub = benderssolvesub;
5890 	}
5891 	
5892 	/** sets post-solve callback of Benders' decomposition */
5893 	void SCIPbendersSetPostsolve(
5894 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5895 	   SCIP_DECL_BENDERSPOSTSOLVE((*benderspostsolve))/**< solving process deinitialization callback of Benders' decomposition */
5896 	   )
5897 	{
5898 	   assert(benders != NULL);
5899 	
5900 	   benders->benderspostsolve = benderspostsolve;
5901 	}
5902 	
5903 	/** sets post-solve callback of Benders' decomposition */
5904 	void SCIPbendersSetSubproblemComp(
5905 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5906 	   SCIP_DECL_SORTPTRCOMP((*benderssubcomp))  /**< a comparator for defining the solving order of the subproblems */
5907 	   )
5908 	{
5909 	   assert(benders != NULL);
5910 	
5911 	   benders->benderssubcomp = benderssubcomp;
5912 	}
5913 	
5914 	/** sets free subproblem callback of Benders' decomposition */
5915 	void SCIPbendersSetFreesub(
5916 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5917 	   SCIP_DECL_BENDERSFREESUB((*bendersfreesub))/**< the freeing callback for the subproblem */
5918 	   )
5919 	{
5920 	   assert(benders != NULL);
5921 	
5922 	   benders->bendersfreesub = bendersfreesub;
5923 	}
5924 	
5925 	/** gets name of Benders' decomposition */
5926 	const char* SCIPbendersGetName(
5927 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
5928 	   )
5929 	{
5930 	   assert(benders != NULL);
5931 	
5932 	   return benders->name;
5933 	}
5934 	
5935 	/** gets description of Benders' decomposition */
5936 	const char* SCIPbendersGetDesc(
5937 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
5938 	   )
5939 	{
5940 	   assert(benders != NULL);
5941 	
5942 	   return benders->desc;
5943 	}
5944 	
5945 	/** gets priority of Benders' decomposition */
5946 	int SCIPbendersGetPriority(
5947 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
5948 	   )
5949 	{
5950 	   assert(benders != NULL);
5951 	
5952 	   return benders->priority;
5953 	}
5954 	
5955 	/** sets priority of Benders' decomposition */
5956 	void SCIPbendersSetPriority(
5957 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
5958 	   SCIP_SET*             set,                /**< global SCIP settings */
5959 	   int                   priority            /**< new priority of the Benders' decomposition */
5960 	   )
5961 	{
5962 	   assert(benders != NULL);
5963 	   assert(set != NULL);
5964 	
5965 	   benders->priority = priority;
5966 	   set->benderssorted = FALSE;
5967 	}
5968 	
5969 	/** gets the number of subproblems for the Benders' decomposition */
5970 	int SCIPbendersGetNSubproblems(
5971 	   SCIP_BENDERS*         benders             /**< the Benders' decomposition data structure */
5972 	   )
5973 	{
5974 	   assert(benders != NULL);
5975 	
5976 	   return benders->nsubproblems;
5977 	}
5978 	
5979 	/** returns the SCIP instance for a given subproblem */
5980 	SCIP* SCIPbendersSubproblem(
5981 	   SCIP_BENDERS*         benders,            /**< the Benders' decomposition data structure */
5982 	   int                   probnumber          /**< the subproblem number */
5983 	   )
5984 	{
5985 	   assert(benders != NULL);
5986 	   assert(probnumber >= 0 && probnumber < benders->nsubproblems);
5987 	
5988 	   return benders->subproblems[probnumber];
5989 	}
5990 	
5991 	/** gets the number of times, the Benders' decomposition was called and tried to find a variable with negative reduced costs */
5992 	int SCIPbendersGetNCalls(
5993 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
5994 	   )
5995 	{
5996 	   assert(benders != NULL);
5997 	
5998 	   return benders->ncalls;
5999 	}
6000 	
6001 	/** gets the number of optimality cuts found by the collection of Benders' decomposition subproblems */
6002 	int SCIPbendersGetNCutsFound(
6003 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6004 	   )
6005 	{
6006 	   assert(benders != NULL);
6007 	
6008 	   return benders->ncutsfound;
6009 	}
6010 	
6011 	/** gets the number of cuts found from the strengthening round */
6012 	int SCIPbendersGetNStrengthenCutsFound(
6013 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6014 	   )
6015 	{
6016 	   assert(benders != NULL);
6017 	
6018 	   return benders->nstrengthencuts;
6019 	}
6020 	
6021 	/** gets the number of calls to the strengthening round */
6022 	int SCIPbendersGetNStrengthenCalls(
6023 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6024 	   )
6025 	{
6026 	   assert(benders != NULL);
6027 	
6028 	   return benders->nstrengthencalls;
6029 	}
6030 	
6031 	/** gets the number of calls to the strengthening round that fail */
6032 	int SCIPbendersGetNStrengthenFails(
6033 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6034 	   )
6035 	{
6036 	   assert(benders != NULL);
6037 	
6038 	   return benders->nstrengthenfails;
6039 	}
6040 	
6041 	/** gets time in seconds used in this Benders' decomposition for setting up for next stages */
6042 	SCIP_Real SCIPbendersGetSetupTime(
6043 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6044 	   )
6045 	{
6046 	   assert(benders != NULL);
6047 	
6048 	   return SCIPclockGetTime(benders->setuptime);
6049 	}
6050 	
6051 	/** gets time in seconds used in this Benders' decomposition */
6052 	SCIP_Real SCIPbendersGetTime(
6053 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6054 	   )
6055 	{
6056 	   assert(benders != NULL);
6057 	
6058 	   return SCIPclockGetTime(benders->bendersclock);
6059 	}
6060 	
6061 	/** enables or disables all clocks of the Benders' decomposition, depending on the value of the flag */
6062 	void SCIPbendersEnableOrDisableClocks(
6063 	   SCIP_BENDERS*         benders,            /**< the Benders' decomposition for which all clocks should be enabled or disabled */
6064 	   SCIP_Bool             enable              /**< should the clocks of the Benders' decomposition be enabled? */
6065 	   )
6066 	{
6067 	   assert(benders != NULL);
6068 	
6069 	   SCIPclockEnableOrDisable(benders->setuptime, enable);
6070 	   SCIPclockEnableOrDisable(benders->bendersclock, enable);
6071 	}
6072 	
6073 	/** is Benders' decomposition initialized? */
6074 	SCIP_Bool SCIPbendersIsInitialized(
6075 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6076 	   )
6077 	{
6078 	   assert(benders != NULL);
6079 	
6080 	   return benders->initialized;
6081 	}
6082 	
6083 	/** Are Benders' cuts generated from the LP solutions? */
6084 	SCIP_Bool SCIPbendersCutLP(
6085 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6086 	   )
6087 	{
6088 	   assert(benders != NULL);
6089 	
6090 	   return benders->cutlp;
6091 	}
6092 	
6093 	/** Are Benders' cuts generated from the pseudo solutions? */
6094 	SCIP_Bool SCIPbendersCutPseudo(
6095 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6096 	   )
6097 	{
6098 	   assert(benders != NULL);
6099 	
6100 	   return benders->cutpseudo;
6101 	}
6102 	
6103 	/** Are Benders' cuts generated from the relaxation solutions? */
6104 	SCIP_Bool SCIPbendersCutRelaxation(
6105 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6106 	   )
6107 	{
6108 	   assert(benders != NULL);
6109 	
6110 	   return benders->cutrelax;
6111 	}
6112 	
6113 	/** should this Benders' use the auxiliary variables from the highest priority Benders' */
6114 	SCIP_Bool SCIPbendersShareAuxVars(
6115 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6116 	   )
6117 	{
6118 	   assert(benders != NULL);
6119 	
6120 	   return benders->shareauxvars;
6121 	}
6122 	
6123 	/** adds a subproblem to the Benders' decomposition data. If a custom subproblem solving method is used, then the
6124 	 *  subproblem pointer can be set to NULL
6125 	 */
6126 	SCIP_RETCODE SCIPbendersAddSubproblem(
6127 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6128 	   SCIP*                 subproblem          /**< subproblem to be added to the data storage, can be NULL */
6129 	   )
6130 	{
6131 	   assert(benders != NULL);
6132 	   assert(benders->naddedsubprobs + 1 <= benders->nsubproblems);
6133 	
6134 	   /* if the subproblem pointer is NULL, then the subproblem solving callback functions must be set. */
6135 	   if( subproblem == NULL && (!benders->benderssolvesubconvex || !benders->benderssolvesub) )
6136 	   {
6137 	      SCIPerrorMessage("The subproblem can only be set to NULL if both bendersSolvesubconvex%s and bendersSolvesub%s "
6138 	         "are defined.\n", benders->name, benders->name);
6139 	      return SCIP_ERROR;
6140 	   }
6141 	
6142 	   benders->subproblems[benders->naddedsubprobs] = subproblem;
6143 	
6144 	   benders->naddedsubprobs++;
6145 	
6146 	   return SCIP_OKAY;
6147 	}
6148 	
6149 	/** removes the subproblems from the Benders' decomposition data */
6150 	void SCIPbendersRemoveSubproblems(
6151 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6152 	   )
6153 	{
6154 	   assert(benders != NULL);
6155 	   assert(benders->subproblems != NULL);
6156 	
6157 	   BMSclearMemoryArray(&benders->subproblems, benders->naddedsubprobs);
6158 	   benders->naddedsubprobs = 0;
6159 	}
6160 	
6161 	/** returns the auxiliary variable for the given subproblem */
6162 	SCIP_VAR* SCIPbendersGetAuxiliaryVar(
6163 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6164 	   int                   probnumber          /**< the subproblem number */
6165 	   )
6166 	{
6167 	   assert(benders != NULL);
6168 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6169 	
6170 	   return benders->auxiliaryvars[probnumber];
6171 	}
6172 	
6173 	/** returns all auxiliary variables */
6174 	SCIP_VAR** SCIPbendersGetAuxiliaryVars(
6175 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6176 	   )
6177 	{
6178 	   assert(benders != NULL);
6179 	
6180 	   return benders->auxiliaryvars;
6181 	}
6182 	
6183 	/** stores the objective function value of the subproblem for use in cut generation */
6184 	void SCIPbendersSetSubproblemObjval(
6185 	   SCIP_BENDERS*         benders,            /**< the Benders' decomposition structure */
6186 	   int                   probnumber,         /**< the subproblem number */
6187 	   SCIP_Real             objval              /**< the objective function value for the subproblem */
6188 	   )
6189 	{
6190 	   assert(benders != NULL);
6191 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6192 	
6193 	   /* updating the best objval */
6194 	   if( objval < benders->bestsubprobobjval[probnumber] )
6195 	      benders->bestsubprobobjval[probnumber] = objval;
6196 	
6197 	   benders->subprobobjval[probnumber] = objval;
6198 	}
6199 	
6200 	/** returns the objective function value of the subproblem for use in cut generation */
6201 	SCIP_Real SCIPbendersGetSubproblemObjval(
6202 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6203 	   int                   probnumber          /**< the subproblem number */
6204 	   )
6205 	{
6206 	   assert(benders != NULL);
6207 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6208 	
6209 	   return benders->subprobobjval[probnumber];
6210 	}
6211 	
6212 	/** returns whether the solution has non-zero slack variables */
6213 	SCIP_RETCODE SCIPbendersSolSlackVarsActive(
6214 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6215 	   SCIP_Bool*            activeslack         /**< flag to indicate whether a slack variable is active */
6216 	   )
6217 	{
6218 	   SCIP* subproblem;
6219 	   SCIP_SOL* sol;
6220 	   SCIP_VAR** vars;
6221 	   int nsubproblems;
6222 	   int nvars;
6223 	   int ncontvars;
6224 	   int i;
6225 	   int j;
6226 	   SCIP_Bool freesol = FALSE;
6227 	
6228 	   assert(benders != NULL);
6229 	   assert(activeslack != NULL);
6230 	
6231 	   (*activeslack) = FALSE;
6232 	
6233 	   /* if the slack variables have not been added, then we can immediately state that no slack variables are active */
6234 	   if( !benders->feasibilityphase )
6235 	   {
6236 	      return SCIP_OKAY;
6237 	   }
6238 	
6239 	   nsubproblems = SCIPbendersGetNSubproblems(benders);
6240 	
6241 	   /* checking all subproblems for active slack variables */
6242 	   for( i = 0; i < nsubproblems && !(*activeslack); i++ )
6243 	   {
6244 	      subproblem = SCIPbendersSubproblem(benders, i);
6245 	
6246 	      /* if the subproblem is convex and an NLP, then we need to create the NLP solution. Otherwise, the solution can be
6247 	       * retrieved from the LP or CIP.
6248 	       */
6249 	      if( SCIPbendersGetSubproblemType(benders, i) == SCIP_BENDERSSUBTYPE_CONVEXCONT )
6250 	      {
6251 	         if( SCIPisNLPConstructed(subproblem) && SCIPgetNNlpis(subproblem) > 0 )
6252 	         {
6253 	            SCIP_CALL( SCIPcreateNLPSol(subproblem, &sol, NULL) );
6254 	         }
6255 	         else
6256 	         {
6257 	            SCIP_CALL( SCIPcreateCurrentSol(subproblem, &sol, NULL) );
6258 	         }
6259 	         freesol = TRUE;
6260 	      }
6261 	      else
6262 	         sol = SCIPgetBestSol(subproblem);
6263 	
6264 	      /* getting the variable data. Only the continuous variables are important. */
6265 	      SCIP_CALL( SCIPgetVarsData(subproblem, &vars, &nvars, NULL, NULL, NULL, &ncontvars) );
6266 	
6267 	      /* checking all slack variables for non-zero solution values */
6268 	      for( j = nvars - 1; j >= nvars - ncontvars; j-- )
6269 	      {
6270 	         if( strstr(SCIPvarGetName(vars[j]), SLACKVAR_NAME) != NULL )
6271 	         {
6272 	            if( SCIPisPositive(subproblem, SCIPgetSolVal(subproblem, sol, vars[j])) )
6273 	            {
6274 	               (*activeslack) = TRUE;
6275 	               break;
6276 	            }
6277 	         }
6278 	      }
6279 	
6280 	      /* freeing the LP and NLP solutions */
6281 	      if( freesol )
6282 	      {
6283 	         SCIP_CALL( SCIPfreeSol(subproblem, &sol) );
6284 	      }
6285 	   }
6286 	
6287 	   return SCIP_OKAY;
6288 	}
6289 	
6290 	/** sets the subproblem type
6291 	 *
6292 	 * The subproblem types are:
6293 	 *    - Convex constraints with continuous variables
6294 	 *    - Convex constraints with discrete variables
6295 	 *    - Non-convex constraints with continuous variables
6296 	 *    - Non-convex constraints with discrete variables
6297 	 */
6298 	void SCIPbendersSetSubproblemType(
6299 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6300 	   int                   probnumber,         /**< the subproblem number */
6301 	   SCIP_BENDERSSUBTYPE   subprobtype         /**< the subproblem type */
6302 	   )
6303 	{
6304 	   assert(benders != NULL);
6305 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6306 	
6307 	   if( subprobtype == SCIP_BENDERSSUBTYPE_CONVEXCONT
6308 	      && benders->subprobtype[probnumber] != SCIP_BENDERSSUBTYPE_CONVEXCONT )
6309 	      benders->nconvexsubprobs++;
6310 	   else if( subprobtype != SCIP_BENDERSSUBTYPE_CONVEXCONT
6311 	      && benders->subprobtype[probnumber] == SCIP_BENDERSSUBTYPE_CONVEXCONT )
6312 	      benders->nconvexsubprobs--;
6313 	
6314 	   benders->subprobtype[probnumber] = subprobtype;
6315 	
6316 	   assert(benders->nconvexsubprobs >= 0 && benders->nconvexsubprobs <= benders->nsubproblems);
6317 	}
6318 	
6319 	/** returns the type of the subproblem
6320 	 *
6321 	 *  This type is used to determine whether the duals of the problem can be used to generate cuts
6322 	 */
6323 	SCIP_BENDERSSUBTYPE SCIPbendersGetSubproblemType(
6324 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6325 	   int                   probnumber          /**< the subproblem number */
6326 	   )
6327 	{
6328 	   assert(benders != NULL);
6329 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6330 	
6331 	   return benders->subprobtype[probnumber];
6332 	}
6333 	
6334 	/** sets the flag indicating whether a subproblem is convex
6335 	 *
6336 	 *  It is possible that this can change during the solving process. One example is when the three-phase method is
6337 	 *  employed, where the first phase solves the convex relaxation of both the master and subproblems, the second phase
6338 	 *  reintroduces the integrality constraints to the master problem and the third phase then reintroduces integrality
6339 	 *  constraints to the subproblems.
6340 	 */
6341 	void SCIPbendersSetSubproblemIsConvex(
6342 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6343 	   int                   probnumber,         /**< the subproblem number */
6344 	   SCIP_Bool             isconvex            /**< flag to indicate whether the subproblem is convex */
6345 	   )
6346 	{
6347 	   assert(benders != NULL);
6348 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6349 	
6350 	   if( isconvex && !benders->subprobisconvex[probnumber] )
6351 	      benders->nconvexsubprobs++;
6352 	   else if( !isconvex && benders->subprobisconvex[probnumber] )
6353 	      benders->nconvexsubprobs--;
6354 	
6355 	   benders->subprobisconvex[probnumber] = isconvex;
6356 	
6357 	   assert(benders->nconvexsubprobs >= 0 && benders->nconvexsubprobs <= benders->nsubproblems);
6358 	}
6359 	
6360 	/** returns whether the subproblem is convex
6361 	 *
6362 	 *  This means that the dual solution can be used to generate cuts.
6363 	 */
6364 	SCIP_Bool SCIPbendersSubproblemIsConvex(
6365 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6366 	   int                   probnumber          /**< the subproblem number */
6367 	   )
6368 	{
6369 	   assert(benders != NULL);
6370 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6371 	
6372 	   return benders->subprobisconvex[probnumber];
6373 	}
6374 	
6375 	/** returns the number of subproblems that are convex */
6376 	int SCIPbendersGetNConvexSubproblems(
6377 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6378 	   )
6379 	{
6380 	   assert(benders != NULL);
6381 	
6382 	   return benders->nconvexsubprobs;
6383 	}
6384 	
6385 	/** sets the flag indicating whether a subproblem contains non-linear constraints */
6386 	void SCIPbendersSetSubproblemIsNonlinear(
6387 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6388 	   int                   probnumber,         /**< the subproblem number */
6389 	   SCIP_Bool             isnonlinear         /**< flag to indicate whether the subproblem contains non-linear constraints */
6390 	   )
6391 	{
6392 	   assert(benders != NULL);
6393 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6394 	
6395 	   if( isnonlinear && !benders->subprobisnonlinear[probnumber] )
6396 	      benders->nnonlinearsubprobs++;
6397 	   else if( !isnonlinear && benders->subprobisnonlinear[probnumber] )
6398 	      benders->nnonlinearsubprobs--;
6399 	
6400 	   benders->subprobisnonlinear[probnumber] = isnonlinear;
6401 	
6402 	   assert(benders->nnonlinearsubprobs >= 0 && benders->nnonlinearsubprobs <= benders->nsubproblems);
6403 	}
6404 	
6405 	/** returns whether the subproblem contains non-linear constraints. */
6406 	SCIP_Bool SCIPbendersSubproblemIsNonlinear(
6407 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6408 	   int                   probnumber          /**< the subproblem number */
6409 	   )
6410 	{
6411 	   assert(benders != NULL);
6412 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6413 	
6414 	   return benders->subprobisnonlinear[probnumber];
6415 	}
6416 	
6417 	/** returns the number of subproblems that contain non-linear constraints  */
6418 	int SCIPbendersGetNNonlinearSubproblems(
6419 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6420 	   )
6421 	{
6422 	   assert(benders != NULL);
6423 	
6424 	   return benders->nnonlinearsubprobs;
6425 	}
6426 	
6427 	/** sets the flag indicating whether the master problem contains non-linear constraints */
6428 	void SCIPbendersSetMasterIsNonlinear(
6429 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6430 	   SCIP_Bool             isnonlinear         /**< flag to indicate whether the subproblem contains non-linear constraints */
6431 	   )
6432 	{
6433 	   assert(benders != NULL);
6434 	
6435 	   benders->masterisnonlinear = isnonlinear;
6436 	}
6437 	
6438 	/** returns whether the master problem contains non-linear constraints. */
6439 	SCIP_Bool SCIPbendersMasterIsNonlinear(
6440 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6441 	   )
6442 	{
6443 	   assert(benders != NULL);
6444 	
6445 	   return benders->masterisnonlinear;
6446 	}
6447 	
6448 	/** returns the flag indicating that Benders' decomposition is in a cut strengthening round */
6449 	SCIP_Bool SCIPbendersInStrengthenRound(
6450 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6451 	   )
6452 	{
6453 	   assert(benders != NULL);
6454 	
6455 	   return benders->strengthenround;
6456 	}
6457 	
6458 	/** changes all of the master problem variables in the given subproblem to continuous. */
6459 	SCIP_RETCODE SCIPbendersChgMastervarsToCont(
6460 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6461 	   SCIP_SET*             set,                /**< global SCIP settings */
6462 	   int                   probnumber          /**< the subproblem number */
6463 	   )
6464 	{
6465 	   SCIP* subproblem;
6466 	   SCIP_VAR** vars;
6467 	   int nbinvars;
6468 	   int nintvars;
6469 	   int nimplvars;
6470 	   int chgvarscount;
6471 	   int origintvars;
6472 	   int i;
6473 	   SCIP_Bool infeasible;
6474 	
6475 	   assert(benders != NULL);
6476 	   assert(set != NULL);
6477 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6478 	
6479 	   subproblem = SCIPbendersSubproblem(benders, probnumber);
6480 	   assert(subproblem != NULL);
6481 	
6482 	   /* only set the master problem variable to continuous if they have not already been changed. */
6483 	   if( !SCIPbendersGetMastervarsCont(benders, probnumber) )
6484 	   {
6485 	      SCIP_VAR* mastervar;
6486 	
6487 	      /* retrieving the variable data */
6488 	      SCIP_CALL( SCIPgetVarsData(subproblem, &vars, NULL, &nbinvars, &nintvars, &nimplvars, NULL) );
6489 	
6490 	      origintvars = nbinvars + nintvars + nimplvars;
6491 	
6492 	      chgvarscount = 0;
6493 	
6494 	      /* looping over all integer variables to change the master variables to continuous */
6495 	      i = 0;
6496 	      while( i < nbinvars + nintvars + nimplvars )
6497 	      {
6498 	         SCIP_CALL( SCIPbendersGetVar(benders, set, vars[i], &mastervar, -1) );
6499 	
6500 	         if( SCIPvarGetType(vars[i]) != SCIP_VARTYPE_CONTINUOUS && mastervar != NULL )
6501 	         {
6502 	            /* changing the type of the subproblem variable corresponding to mastervar to CONTINUOUS */
6503 	            SCIP_CALL( SCIPchgVarType(subproblem, vars[i], SCIP_VARTYPE_CONTINUOUS, &infeasible) );
6504 	
6505 	            assert(!infeasible);
6506 	
6507 	            chgvarscount++;
6508 	            SCIP_CALL( SCIPgetVarsData(subproblem, NULL, NULL, &nbinvars, &nintvars, &nimplvars, NULL) );
6509 	         }
6510 	         else
6511 	            i++;
6512 	      }
6513 	
6514 	      /* if all of the integer variables have been changed to continuous, then the subproblem could now be a convex
6515 	       * problem. This must be checked and if TRUE, then the LP subproblem is initialised and then put into probing
6516 	       * mode
6517 	       */
6518 	      if( chgvarscount > 0 && chgvarscount == origintvars )
6519 	      {
6520 	         /* checking the convexity of the subproblem */
6521 	         SCIP_CALL( checkSubproblemConvexity(benders, set, probnumber) );
6522 	
6523 	         /* if the subproblem has convex constraints and continuous variables, then it is initialised and put into
6524 	          * probing mode
6525 	          */
6526 	         if( SCIPbendersGetSubproblemType(benders, probnumber) == SCIP_BENDERSSUBTYPE_CONVEXCONT )
6527 	         {
6528 	            SCIP_CALL( initialiseLPSubproblem(benders, set, probnumber) );
6529 	         }
6530 	      }
6531 	
6532 	      SCIP_CALL( SCIPbendersSetMastervarsCont(benders, probnumber, TRUE) );
6533 	   }
6534 	
6535 	   return SCIP_OKAY;
6536 	}
6537 	
6538 	/** sets the subproblem setup flag */
6539 	void SCIPbendersSetSubproblemIsSetup(
6540 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6541 	   int                   probnumber,         /**< the subproblem number */
6542 	   SCIP_Bool             issetup             /**< flag to indicate whether the subproblem has been setup */
6543 	   )
6544 	{
6545 	   assert(benders != NULL);
6546 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6547 	
6548 	   benders->subprobsetup[probnumber] = issetup;
6549 	}
6550 	
6551 	/** returns the subproblem setup flag */
6552 	SCIP_Bool SCIPbendersSubproblemIsSetup(
6553 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6554 	   int                   probnumber          /**< the subproblem number */
6555 	   )
6556 	{
6557 	   assert(benders != NULL);
6558 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6559 	
6560 	   return benders->subprobsetup[probnumber];
6561 	}
6562 	
6563 	/** sets the independent subproblem flag */
6564 	void SCIPbendersSetSubproblemIsIndependent(
6565 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6566 	   int                   probnumber,         /**< the subproblem number */
6567 	   SCIP_Bool             isindep             /**< flag to indicate whether the subproblem is independent */
6568 	   )
6569 	{
6570 	   assert(benders != NULL);
6571 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6572 	
6573 	   /* if the user has defined solving or freeing functions, then it is not possible to declare a subproblem as
6574 	    * independent. This is because declaring a subproblem as independent changes the solving loop, so it would change
6575 	    * the expected behaviour of the user defined plugin. If a user calls this function, then an error will be returned.
6576 	    */
6577 	   if( benders->benderssolvesubconvex != NULL || benders->benderssolvesub != NULL || benders->bendersfreesub != NULL )
6578 	   {
6579 	      SCIPerrorMessage("The user has defined either bendersSolvesubconvex%s, bendersSolvesub%s or bendersFreesub%s. "
6580 	         "Thus, it is not possible to declare the independence of a subproblem.\n", benders->name, benders->name,
6581 	         benders->name);
6582 	      SCIPABORT();
6583 	   }
6584 	   else
6585 	   {
6586 	      SCIP_Bool activesubprob;
6587 	
6588 	      /* if the active status of the subproblem changes, then we must update the activesubprobs counter */
6589 	      activesubprob = subproblemIsActive(benders, probnumber);
6590 	
6591 	      benders->indepsubprob[probnumber] = isindep;
6592 	
6593 	      /* updating the activesubprobs counter */
6594 	      if( activesubprob && !subproblemIsActive(benders, probnumber) )
6595 	         benders->nactivesubprobs--;
6596 	      else if( !activesubprob && subproblemIsActive(benders, probnumber) )
6597 	         benders->nactivesubprobs++;
6598 	
6599 	      assert(benders->nactivesubprobs >= 0 && benders->nactivesubprobs <= SCIPbendersGetNSubproblems(benders));
6600 	   }
6601 	}
6602 	
6603 	/** returns whether the subproblem is independent */
6604 	SCIP_Bool SCIPbendersSubproblemIsIndependent(
6605 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6606 	   int                   probnumber          /**< the subproblem number */
6607 	   )
6608 	{
6609 	   assert(benders != NULL);
6610 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6611 	
6612 	   return benders->indepsubprob[probnumber];
6613 	}
6614 	
6615 	/** Sets whether the subproblem is enabled or disabled. A subproblem is disabled if it has been merged into the master
6616 	 *  problem.
6617 	 */
6618 	void SCIPbendersSetSubproblemEnabled(
6619 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6620 	   int                   probnumber,         /**< the subproblem number */
6621 	   SCIP_Bool             enabled             /**< flag to indicate whether the subproblem is enabled */
6622 	   )
6623 	{
6624 	   SCIP_Bool activesubprob;
6625 	
6626 	   assert(benders != NULL);
6627 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6628 	
6629 	   /* if the active status of the subproblem changes, then we must update the activesubprobs counter */
6630 	   activesubprob = subproblemIsActive(benders, probnumber);
6631 	
6632 	   benders->subprobenabled[probnumber] = enabled;
6633 	
6634 	   /* updating the activesubprobs counter */
6635 	   if( activesubprob && !subproblemIsActive(benders, probnumber) )
6636 	      benders->nactivesubprobs--;
6637 	   else if( !activesubprob && subproblemIsActive(benders, probnumber) )
6638 	      benders->nactivesubprobs++;
6639 	
6640 	   assert(benders->nactivesubprobs >= 0 && benders->nactivesubprobs <= SCIPbendersGetNSubproblems(benders));
6641 	}
6642 	
6643 	/** returns whether the subproblem is enabled, i.e. the subproblem is still solved in the solving loop. */
6644 	SCIP_Bool SCIPbendersSubproblemIsEnabled(
6645 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6646 	   int                   probnumber          /**< the subproblem number */
6647 	   )
6648 	{
6649 	   assert(benders != NULL);
6650 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6651 	
6652 	   return benders->subprobenabled[probnumber];
6653 	}
6654 	
6655 	/** sets a flag to indicate whether the master variables are all set to continuous */
6656 	SCIP_RETCODE SCIPbendersSetMastervarsCont(
6657 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6658 	   int                   probnumber,         /**< the subproblem number */
6659 	   SCIP_Bool             arecont             /**< flag to indicate whether the master problem variables are continuous */
6660 	   )
6661 	{
6662 	   assert(benders != NULL);
6663 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6664 	
6665 	   /* if the master variables were all continuous and now are not, then the subproblem must exit probing mode and be
6666 	    * changed to non-LP subproblem */
6667 	   if( benders->mastervarscont[probnumber] && !arecont )
6668 	   {
6669 	      SCIP_BENDERSSUBTYPE subtype;
6670 	
6671 	      if( SCIPinProbing(SCIPbendersSubproblem(benders, probnumber)) )
6672 	      {
6673 	         SCIP_CALL( SCIPendProbing(SCIPbendersSubproblem(benders, probnumber)) );
6674 	      }
6675 	
6676 	      subtype = SCIPbendersGetSubproblemType(benders, probnumber);
6677 	      assert(subtype == SCIP_BENDERSSUBTYPE_CONVEXCONT || subtype == SCIP_BENDERSSUBTYPE_NONCONVEXCONT);
6678 	
6679 	      if( subtype == SCIP_BENDERSSUBTYPE_CONVEXCONT )
6680 	         SCIPbendersSetSubproblemType(benders, probnumber, SCIP_BENDERSSUBTYPE_CONVEXDIS);
6681 	      else if( subtype == SCIP_BENDERSSUBTYPE_NONCONVEXCONT )
6682 	         SCIPbendersSetSubproblemType(benders, probnumber, SCIP_BENDERSSUBTYPE_NONCONVEXDIS);
6683 	   }
6684 	
6685 	   benders->mastervarscont[probnumber] = arecont;
6686 	
6687 	   return SCIP_OKAY;
6688 	}
6689 	
6690 	/** returns whether the master variables are all set to continuous */
6691 	SCIP_Bool SCIPbendersGetMastervarsCont(
6692 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6693 	   int                   probnumber          /**< the subproblem number */
6694 	   )
6695 	{
6696 	   assert(benders != NULL);
6697 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6698 	
6699 	   return benders->mastervarscont[probnumber];
6700 	}
6701 	
6702 	/** returns the number of cuts that have been transferred from sub SCIPs to the master SCIP */
6703 	int SCIPbendersGetNTransferredCuts(
6704 	   SCIP_BENDERS*         benders             /**< the Benders' decomposition data structure */
6705 	   )
6706 	{
6707 	   assert(benders != NULL);
6708 	
6709 	   return benders->ntransferred;
6710 	}
6711 	
6712 	/** updates the lower bound for the subproblem. If the lower bound is not greater than the previously stored lowerbound,
6713 	 *  then no update occurs.
6714 	 */
6715 	void SCIPbendersUpdateSubproblemLowerbound(
6716 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6717 	   int                   probnumber,         /**< the subproblem number */
6718 	   SCIP_Real             lowerbound          /**< the lower bound */
6719 	   )
6720 	{
6721 	   assert(benders != NULL);
6722 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6723 	
6724 	   if( EPSGE(lowerbound, benders->subproblowerbound[probnumber], 1e-06) )
6725 	      benders->subproblowerbound[probnumber] = lowerbound;
6726 	   else
6727 	   {
6728 	      SCIPdebugMessage("The lowerbound %g for subproblem %d is less than the currently stored lower bound %g\n",
6729 	         lowerbound, probnumber, benders->subproblowerbound[probnumber]);
6730 	   }
6731 	}
6732 	
6733 	/** returns the stored lower bound for the given subproblem */
6734 	SCIP_Real SCIPbendersGetSubproblemLowerbound(
6735 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6736 	   int                   probnumber          /**< the subproblem number */
6737 	   )
6738 	{
6739 	   assert(benders != NULL);
6740 	   assert(probnumber >= 0 && probnumber < SCIPbendersGetNSubproblems(benders));
6741 	
6742 	   return benders->subproblowerbound[probnumber];
6743 	}
6744 	
6745 	/** returns the number of cuts that have been added for storage */
6746 	int SCIPbendersGetNStoredCuts(
6747 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6748 	   )
6749 	{
6750 	   assert(benders != NULL);
6751 	
6752 	   return benders->nstoredcuts;
6753 	}
6754 	
6755 	/** returns the cuts that have been stored for transfer */
6756 	SCIP_RETCODE SCIPbendersGetStoredCutData(
6757 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6758 	   int                   cutidx,             /**< the index for the cut data that is requested */
6759 	   SCIP_VAR***           vars,               /**< the variables that have non-zero coefficients in the cut */
6760 	   SCIP_Real**           vals,               /**< the coefficients of the variables in the cut */
6761 	   SCIP_Real*            lhs,                /**< the left hand side of the cut */
6762 	   SCIP_Real*            rhs,                /**< the right hand side of the cut */
6763 	   int*                  nvars               /**< the number of variables with non-zero coefficients in the cut */
6764 	   )
6765 	{
6766 	   assert(benders != NULL);
6767 	   assert(vars != NULL);
6768 	   assert(vals != NULL);
6769 	   assert(lhs != NULL);
6770 	   assert(rhs != NULL);
6771 	   assert(nvars != NULL);
6772 	   assert(cutidx >= 0 && cutidx < benders->nstoredcuts);
6773 	
6774 	   (*vars) = benders->storedcuts[cutidx]->vars;
6775 	   (*vals) = benders->storedcuts[cutidx]->vals;
6776 	   (*lhs) = benders->storedcuts[cutidx]->lhs;
6777 	   (*rhs) = benders->storedcuts[cutidx]->rhs;
6778 	   (*nvars) = benders->storedcuts[cutidx]->nvars;
6779 	
6780 	   return SCIP_OKAY;
6781 	}
6782 	
6783 	/** returns the original problem data for the cuts that have been added by the Benders' cut plugin. The stored
6784 	 *  variables and values will populate the input vars and vals arrays. Thus, memory must be allocated for the vars and
6785 	 *  vals arrays
6786 	 */
6787 	SCIP_RETCODE SCIPbendersGetStoredCutOrigData(
6788 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition cut */
6789 	   int                   cutidx,             /**< the index for the cut data that is requested */
6790 	   SCIP_VAR***           vars,               /**< the variables that have non-zero coefficients in the cut */
6791 	   SCIP_Real**           vals,               /**< the coefficients of the variables in the cut */
6792 	   SCIP_Real*            lhs,                /**< the left hand side of the cut */
6793 	   SCIP_Real*            rhs,                /**< the right hand side of the cut */
6794 	   int*                  nvars,              /**< the number of variables with non-zero coefficients in the cut */
6795 	   int                   varssize            /**< the available slots in the array */
6796 	   )
6797 	{
6798 	   SCIP_VAR* origvar;
6799 	   SCIP_Real scalar;
6800 	   SCIP_Real constant;
6801 	   int i;
6802 	
6803 	   assert(benders != NULL);
6804 	   assert(vars != NULL);
6805 	   assert(vals != NULL);
6806 	   assert(lhs != NULL);
6807 	   assert(rhs != NULL);
6808 	   assert(nvars != NULL);
6809 	   assert(cutidx >= 0 && cutidx < benders->nstoredcuts);
6810 	
6811 	   (*lhs) = benders->storedcuts[cutidx]->lhs;
6812 	   (*rhs) = benders->storedcuts[cutidx]->rhs;
6813 	   (*nvars) = benders->storedcuts[cutidx]->nvars;
6814 	
6815 	   /* if there are enough slots, then store the cut variables and values */
6816 	   if( varssize >= *nvars )
6817 	   {
6818 	      for( i = 0; i < *nvars; i++ )
6819 	      {
6820 	         /* getting the original variable for the transformed variable */
6821 	         origvar = benders->storedcuts[cutidx]->vars[i];
6822 	         scalar = 1.0;
6823 	         constant = 0.0;
6824 	         SCIP_CALL( SCIPvarGetOrigvarSum(&origvar, &scalar, &constant) );
6825 	
6826 	         (*vars)[i] = origvar;
6827 	         (*vals)[i] = benders->storedcuts[cutidx]->vals[i];
6828 	      }
6829 	   }
6830 	
6831 	   return SCIP_OKAY;
6832 	}
6833 	
6834 	/** adds the data for the generated cuts to the Benders' cut storage */
6835 	SCIP_RETCODE SCIPbendersStoreCut(
6836 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition cut */
6837 	   SCIP_SET*             set,                /**< global SCIP settings */
6838 	   SCIP_VAR**            vars,               /**< the variables that have non-zero coefficients in the cut */
6839 	   SCIP_Real*            vals,               /**< the coefficients of the variables in the cut */
6840 	   SCIP_Real             lhs,                /**< the left hand side of the cut */
6841 	   SCIP_Real             rhs,                /**< the right hand side of the cut */
6842 	   int                   nvars               /**< the number of variables with non-zero coefficients in the cut */
6843 	   )
6844 	{
6845 	   SCIP_BENDERSCUTCUT* cut;
6846 	
6847 	   assert(benders != NULL);
6848 	   assert(set != NULL);
6849 	   assert(vars != NULL);
6850 	   assert(vals != NULL);
6851 	
6852 	   /* allocating the block memory for the cut storage */
6853 	   SCIP_CALL( SCIPallocBlockMemory(set->scip, &cut) );
6854 	
6855 	   /* storing the cut data */
6856 	   SCIP_CALL( SCIPduplicateBlockMemoryArray(set->scip, &cut->vars, vars, nvars) );
6857 	   SCIP_CALL( SCIPduplicateBlockMemoryArray(set->scip, &cut->vals, vals, nvars) );
6858 	   cut->lhs = lhs;
6859 	   cut->rhs = rhs;
6860 	   cut->nvars = nvars;
6861 	
6862 	   /* ensuring the required memory is available for the stored cuts array */
6863 	   if( benders->storedcutssize < benders->nstoredcuts + 1 )
6864 	   {
6865 	      int newsize;
6866 	
6867 	      newsize = SCIPsetCalcMemGrowSize(set, benders->nstoredcuts + 1);
6868 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(SCIPblkmem(set->scip), &benders->storedcuts,
6869 	            benders->storedcutssize, newsize) );
6870 	
6871 	      benders->storedcutssize = newsize;
6872 	   }
6873 	   assert(benders->storedcutssize >= benders->nstoredcuts + 1);
6874 	
6875 	   /* adding the cuts to the Benders' cut storage */
6876 	   benders->storedcuts[benders->nstoredcuts] = cut;
6877 	   benders->nstoredcuts++;
6878 	
6879 	   return SCIP_OKAY;
6880 	}
6881 	
6882 	/** sets the sorted flags in the Benders' decomposition */
6883 	void SCIPbendersSetBenderscutsSorted(
6884 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition structure */
6885 	   SCIP_Bool             sorted              /**< the value to set the sorted flag to */
6886 	   )
6887 	{
6888 	   assert(benders != NULL);
6889 	
6890 	   benders->benderscutssorted = sorted;
6891 	   benders->benderscutsnamessorted = sorted;
6892 	}
6893 	
6894 	/** inserts a Benders' cut into the Benders' cuts list */
6895 	SCIP_RETCODE SCIPbendersIncludeBenderscut(
6896 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition structure */
6897 	   SCIP_SET*             set,                /**< global SCIP settings */
6898 	   SCIP_BENDERSCUT*      benderscut          /**< Benders' cut */
6899 	   )
6900 	{
6901 	   assert(benders != NULL);
6902 	   assert(benderscut != NULL);
6903 	
6904 	   if( benders->nbenderscuts >= benders->benderscutssize )
6905 	   {
6906 	      benders->benderscutssize = SCIPsetCalcMemGrowSize(set, benders->nbenderscuts+1);
6907 	      SCIP_ALLOC( BMSreallocMemoryArray(&benders->benderscuts, benders->benderscutssize) );
6908 	   }
6909 	   assert(benders->nbenderscuts < benders->benderscutssize);
6910 	
6911 	   benders->benderscuts[benders->nbenderscuts] = benderscut;
6912 	   benders->nbenderscuts++;
6913 	   benders->benderscutssorted = FALSE;
6914 	
6915 	   return SCIP_OKAY;
6916 	}
6917 	
6918 	/** returns the Benders' cut of the given name, or NULL if not existing */
6919 	SCIP_BENDERSCUT* SCIPfindBenderscut(
6920 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6921 	   const char*           name                /**< name of Benderscut' decomposition */
6922 	   )
6923 	{
6924 	   int i;
6925 	
6926 	   assert(benders != NULL);
6927 	   assert(name != NULL);
6928 	
6929 	   for( i = 0; i < benders->nbenderscuts; i++ )
6930 	   {
6931 	      if( strcmp(SCIPbenderscutGetName(benders->benderscuts[i]), name) == 0 )
6932 	         return benders->benderscuts[i];
6933 	   }
6934 	
6935 	   return NULL;
6936 	}
6937 	
6938 	/** returns the array of currently available Benders' cuts; active Benders' decomposition are in the first slots of
6939 	 * the array
6940 	 */
6941 	SCIP_BENDERSCUT** SCIPbendersGetBenderscuts(
6942 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6943 	   )
6944 	{
6945 	   assert(benders != NULL);
6946 	
6947 	   if( !benders->benderscutssorted )
6948 	   {
6949 	      SCIPsortPtr((void**)benders->benderscuts, SCIPbenderscutComp, benders->nbenderscuts);
6950 	      benders->benderscutssorted = TRUE;
6951 	      benders->benderscutsnamessorted = FALSE;
6952 	   }
6953 	
6954 	   return benders->benderscuts;
6955 	}
6956 	
6957 	/** returns the number of currently available Benders' cuts */
6958 	int SCIPbendersGetNBenderscuts(
6959 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6960 	   )
6961 	{
6962 	   assert(benders != NULL);
6963 	
6964 	   return benders->nbenderscuts;
6965 	}
6966 	
6967 	/** sets the priority of a Benders' decomposition */
6968 	SCIP_RETCODE SCIPbendersSetBenderscutPriority(
6969 	   SCIP_BENDERS*         benders,            /**< Benders' decomposition */
6970 	   SCIP_BENDERSCUT*      benderscut,         /**< Benders' cut */
6971 	   int                   priority            /**< new priority of the Benders' decomposition */
6972 	   )
6973 	{
6974 	   assert(benders != NULL);
6975 	   assert(benderscut != NULL);
6976 	
6977 	   benderscut->priority = priority;
6978 	   benders->benderscutssorted = FALSE;
6979 	
6980 	   return SCIP_OKAY;
6981 	}
6982 	
6983 	/** sorts Benders' decomposition cuts by priorities */
6984 	void SCIPbendersSortBenderscuts(
6985 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
6986 	   )
6987 	{
6988 	   assert(benders != NULL);
6989 	
6990 	   if( !benders->benderscutssorted )
6991 	   {
6992 	      SCIPsortPtr((void**)benders->benderscuts, SCIPbenderscutComp, benders->nbenderscuts);
6993 	      benders->benderscutssorted = TRUE;
6994 	      benders->benderscutsnamessorted = FALSE;
6995 	   }
6996 	}
6997 	
6998 	/** sorts Benders' decomposition cuts by name */
6999 	void SCIPbendersSortBenderscutsName(
7000 	   SCIP_BENDERS*         benders             /**< Benders' decomposition */
7001 	   )
7002 	{
7003 	   assert(benders != NULL);
7004 	
7005 	   if( !benders->benderscutsnamessorted )
7006 	   {
7007 	      SCIPsortPtr((void**)benders->benderscuts, SCIPbenderscutCompName, benders->nbenderscuts);
7008 	      benders->benderscutssorted = FALSE;
7009 	      benders->benderscutsnamessorted = TRUE;
7010 	   }
7011 	}
7012