Scippy

SCIP

Solving Constraint Integer Programs

probdata_scflp.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2018 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scip.zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file probdata_scflp.c
17  * @brief Problem data for Stochastic Capacitated Facility Location problem
18  * @author Stephen J. Maher
19  *
20  * This file handles the main problem data used in that project. For more details see \ref SCFLP_PROBLEMDATA page.
21  *
22  * @page SCFLP_SOLVEPROB Solving the deterministic equivalent
23  *
24  * The probdata_scflp.c is used to store the global problem data and build the monolithic MIP and decomposed problems.
25  * First, the structure of the problem data is describe. This is followed by a description of how to solve the problem
26  * directly using SCIP or using Benders' decomposition.
27  *
28  * @section SCFLP_PROBLEMDATA The global problem data
29  *
30  * The problem data is accessible in all plugins. The function SCIPgetProbData() returns the pointer to that structure.
31  * We use this data structure to store all the information of the SCFLP. Since this structure is not visible in the
32  * other plugins, we implemented setter and getter functions to access this data. The problem data structure
33  * SCIP_ProbData is shown below.
34  *
35  * \code
36  * ** @brief Problem data which is accessible in all places
37  * *
38  * * This problem data is used to store the input of the cap instance, all variables which are created, and all
39  * * constraints. In addition, the probdata stores the data structures for the decomposed problem. This permits the
40  * * use of Benders' decomposition to solve the stochastic program.
41  * *
42  * struct SCIP_ProbData
43  * {
44  * SCIP** subproblems; **< the Benders' decomposition subproblems * SCIP_VAR**
45  * SCIP_VAR** facilityvars; **< all variables representing facilities *
46  * SCIP_VAR*** subfacilityvars; **< duplicates of the facility variables in the subproblems *
47  * SCIP_VAR**** customervars; **< all variables representing the satisfaction of demand per scenario *
48  * SCIP_CONS*** capconss; **< capacity constraints per facility per scenario *
49  * SCIP_CONS*** demandconss; **< demand constraints per customer per scenario *
50  * SCIP_CONS* sufficientcap; **< ensuring sufficient capacity is provided to satisfy demand (relatively complete recourse) *
51  * SCIP_Real** costs; **< the transportation costs to a customer from a facility *
52  * SCIP_Real** demands; **< the customer demands per scenario *
53  * SCIP_Real* capacity; **< the capacity of each facility *
54  * SCIP_Real* fixedcost; **< the fixed cost of opening each facility *
55  * int ncustomers; **< the number of customers *
56  * int nfacilities; **< the number of facilities *
57  * int nscenarios; **< the number of scenarios *
58  * SCIP_Bool usebenders; **< whether Benders' decomposition is used *
59  * };
60  * \endcode
61  *
62  * The function SCIPprobdataCreate() manages the creation of the SCFLP instance in SCIP. There are two types of
63  * formulations that can be produced in this example. The first is the monolithic deterministic equivalent. The second
64  * is the reformulated problem that decomposes the stochastic problem by scenarios. This alternative formulations is
65  * solved using Benders' decomposition. Depending on the solution method, some members of SCIP_ProbData will be unused.
66  * For example, subproblems and subfacilityvars are only used when Benders' decomposition is applied to solve the SCFLP.
67  *
68  * The probdata_scflp.c also provide interface methods to the global problem data. A list of all interface methods can be
69  * found in probdata_scflp.h.
70  *
71  * @section SCFLP_DETEQUIV Directly solving the deterministic equivalent using SCIP
72  *
73  * Within probdata_scflp.c, both the monolithic determinstic equivalent or the decomposed problem can be built within
74  * SCIP. The monolithic deterministic equivalent involve a since SCIP instances that is solved directly as a MIP. The
75  * problem that is build in SCIP is given in \ref SCFLP_DETEQUIVMODEL.
76  *
77  * @section SCFLP_BENDERS Solving the SCFLP using Benders' decomposition
78  *
79  * The model that is used to build the decomposed problem is given in \ref SCFLP_BENDERSMODEL. In this example, the
80  * default Benders' decomposition plugin is used to employ the Benders' decomposition framework, see
81  * src/scip/benders_default.h. Before calling SCIPcreateBendersDefault() to invoke the Benders' decomposition framework,
82  * the SCIP instances for the master problem and the subproblems must be created.
83  *
84  * The SCIP instance for the master problem includes only the first stage variables (the facility variables \f$x_{i}\f$)
85  * and the first stage constraints. Note, the auxiliary variables are not added to the master problem by the user, nor
86  * are any Benders' decomposition cuts.
87  *
88  * For each subproblem \f$s\f$, the SCIP instance is formulated with the second stage variables (the customer variables
89  * \f$y^{s}_{ij}\f$) and the second stage constraints. Also, the first stage variables are created for each scenario.
90  * These variables are copies of the master variables from the master SCIP instances and must be created by calling
91  * SCIPcreateVarBasic() or SCIPcreateVar(). The master problem variable copies that are created in the subproblem SCIP
92  * instances must have an objective coefficient of 0.0. This is inline with the classical application of Benders'
93  * decomposition.
94  *
95  * IMPORTANT: the master variables that are created for the subproblem SCIP instances must have the same name as the
96  * corresponding master variables in the master problem SCIP instance. This is because the mapping between the master
97  * and subproblem variables relies on the variable names. This mapping is used for setting up the subproblems to
98  * evaluate solutions from the master problem and generating Benders' cuts.
99  *
100  * Once the master and subproblem SCIP instances are created, the Benders' decomposition is invoked by calling the
101  * interface function SCIPcreateBendersDefault(). The parameters for this function are a SCIP instance for the master
102  * problem, an array of SCIP instances for the subproblems and the number of subproblems.
103  *
104  * The Benders' decomposition framework involves the use of constraint handlers within SCIP, src/scip/cons_benders.h and
105  * src/scip/cons_benderslp.h. In order to solve the master problem by adding Benders' cuts, src/scip/cons_benders.h and
106  * src/scip/cons_benderslp.h must be activated. This is done by setting the parameter "constraints/benders/active" and
107  * "constraints/benderslp/active" to TRUE.
108  *
109  * NOTE: it is not necessary to activate src/scip/cons_benderslp.h. The purpose of this constraint handler is to
110  * generate Benders' decomposition cut from solutions to the LP relaxation in the root node. These solutions are
111  * fractional, since the enforcement priority of benderslp is higher than the integer constraint handler. The benderslp
112  * constraint handler allows the user to employ the multi-phase algorithm of McDaniel and Devine (1977).
113  *
114  * McDaniel D, Devine M. A modified Benders’ partitioning algorithm for mixed integer programming. Management Science
115  * 1977;24(2):312–9
116  */
117 
118 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
119 
120 #include <string.h>
121 
122 #include "probdata_scflp.h"
123 
124 #include "scip/cons_linear.h"
125 #include "scip/benders_default.h"
126 #include "scip/scip.h"
127 #include "scip/scipdefplugins.h"
128 
129 /** @brief Problem data which is accessible in all places
130  *
131  * This problem data is used to store the input of the SCFLP, all variables which are created, and all constraints.
132  */
133 struct SCIP_ProbData
134 {
135  SCIP** subproblems; /**< the Benders' decomposition subproblems */
136  SCIP_VAR** facilityvars; /**< all variables representing facilities */
137  SCIP_VAR*** subfacilityvars; /**< duplicates of the facility variables in the subproblems */
138  SCIP_VAR**** customervars; /**< all variables representing the satisfaction of demand per scenario */
139  SCIP_CONS*** capconss; /**< capacity constraints per facility per scenario */
140  SCIP_CONS*** demandconss; /**< demand constraints per customer per scenario */
141  SCIP_CONS* sufficientcap; /**< ensuring sufficient capacity is provided to satisfy demand (relatively complete recourse) */
142  SCIP_Real** costs; /**< the transportation costs to a customer from a facility */
143  SCIP_Real** demands; /**< the customer demands per scenario */
144  SCIP_Real* capacity; /**< the capacity of each facility */
145  SCIP_Real* fixedcost; /**< the fixed cost of opening each facility */
146  int ncustomers; /**< the number of customers */
147  int nfacilities; /**< the number of facilities */
148  int nscenarios; /**< the number of scenarios */
149  SCIP_Bool usebenders; /**< whether Benders' decomposition is used */
150 };
151 
152 
153 
154 /**@name Local methods
155  *
156  * @{
157  */
158 
159 /** creates the original problem */
160 static
162  SCIP* scip, /**< SCIP data structure */
163  SCIP_VAR** facilityvars, /**< all variables representing facilities */
164  SCIP_VAR**** customervars, /**< all variables representing the satisfaction of demand */
165  SCIP_CONS*** capconss, /**< capacity constraints per facility */
166  SCIP_CONS*** demandconss, /**< demand constraints per customer */
167  SCIP_CONS** sufficientcap, /**< ensuring sufficient capacity is provided to satisfy demand */
168  SCIP_Real** costs, /**< the transportation costs from a facility to a customer */
169  SCIP_Real** demands, /**< the customer demands */
170  SCIP_Real* capacity, /**< the capacity of each facility */
171  SCIP_Real* fixedcost, /**< the fixed cost of opening a facility */
172  int ncustomers, /**< the number of customers */
173  int nfacilities, /**< the number of facilities */
174  int nscenarios /**< the number of scenarios */
175  )
176 {
177  SCIP_CONS* cons;
178  SCIP_VAR* var;
179  SCIP_Real maxdemand;
180  SCIP_Real coeff;
181  int i;
182  int j;
183  int k;
184  char name[SCIP_MAXSTRLEN];
185  assert(scip != NULL);
186 
187  /* adding the sufficient capacity constraints */
188  maxdemand = 0;
189  for( i = 0; i < nscenarios; i++)
190  {
191  SCIP_Real sumdemand = 0;
192  for( j = 0; j < ncustomers; j++ )
193  sumdemand += demands[j][i];
194 
195  if( sumdemand > maxdemand )
196  maxdemand = sumdemand;
197  }
198 
199  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "sufficientcapacity");
200  SCIP_CALL( SCIPcreateConsBasicLinear(scip, sufficientcap, name, 0, NULL, NULL, maxdemand, SCIPinfinity(scip)) );
201 
202  SCIP_CALL( SCIPaddCons(scip, (*sufficientcap)) );
203 
204  /* adds the capacity constraints to the scenario */
205  for( i = 0; i < nfacilities; i++ )
206  {
207  for( j = 0; j < nscenarios; j++ )
208  {
209  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "capacity_%d_%d", i, j);
210  SCIP_CALL( SCIPcreateConsBasicLinear(scip, &cons, name, 0, NULL, NULL, -SCIPinfinity(scip), 0.0) );
211 
212  SCIP_CALL( SCIPaddCons(scip, cons) );
213 
214  capconss[i][j] = cons;
215  }
216  }
217 
218  /* adds the demand constraints to the scenario */
219  for( i = 0; i < ncustomers; i++ )
220  {
221  for( j = 0; j < nscenarios; j++ )
222  {
223  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "demand_%d_%d", i, j);
224  SCIP_CALL( SCIPcreateConsBasicLinear(scip, &cons, name, 0, NULL, NULL, demands[i][j], SCIPinfinity(scip)) );
225 
226  SCIP_CALL( SCIPaddCons(scip, cons) );
227 
228  demandconss[i][j] = cons;
229  }
230  }
231 
232  for( i = 0; i < nfacilities; i++ )
233  {
234  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "facility_%d", i);
235  SCIP_CALL( SCIPcreateVarBasic(scip, &var, name, 0.0, 1.0, fixedcost[i], SCIP_VARTYPE_BINARY) );
236 
237  SCIP_CALL( SCIPaddVar(scip, var) );
238 
239  /* storing the variable in the facility variable list */
240  facilityvars[i] = var;
241 
242  /* adding the variable to the capacity constraints */
243  for( j = 0; j < nscenarios; j++ )
244  SCIP_CALL( SCIPaddCoefLinear(scip, capconss[i][j], var, -capacity[i]) );
245 
246  /* adding the variable to the sufficient capacity constraints */
247  SCIP_CALL( SCIPaddCoefLinear(scip, (*sufficientcap), var, capacity[i]) );
248  }
249 
250  /* adding the customer variables to the scenario */
251  for( i = 0; i < ncustomers; i++ )
252  {
253  for( j = 0; j < nfacilities; j++ )
254  {
255  for( k = 0; k < nscenarios; k++ )
256  {
257  coeff = costs[i][j]/(SCIP_Real)nscenarios;
258  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "customer(%d,%d,%d)", i, j, k);
259  SCIP_CALL( SCIPcreateVarBasic(scip, &var, name, 0.0, SCIPinfinity(scip), coeff, SCIP_VARTYPE_CONTINUOUS) );
260 
261  SCIP_CALL( SCIPaddVar(scip, var) );
262 
263  /* storing the customer variable in the list */
264  customervars[i][j][k] = var;
265 
266  if( costs[i][j] > 0 )
267  {
268  /* adding the variable to the capacity constraints */
269  SCIP_CALL( SCIPaddCoefLinear(scip, capconss[j][k], customervars[i][j][k], 1.0) );
270 
271  /* adding the variable to the demand constraints */
272  SCIP_CALL( SCIPaddCoefLinear(scip, demandconss[i][k], customervars[i][j][k], 1.0) );
273  }
274  }
275  }
276  }
277 
278  return SCIP_OKAY;
279 }
280 
281 /** creates the Benders' decomposition master problem */
282 static
284  SCIP* scip, /**< SCIP data structure */
285  SCIP_VAR** facilityvars, /**< all variables representing facilities */
286  SCIP_CONS** sufficientcap, /**< ensuring sufficient capacity is provided to satisfy demand */
287  SCIP_Real* capacity, /**< the capacity of each facility */
288  SCIP_Real* fixedcost, /**< the fixed cost of opening a facility */
289  SCIP_Real** demands, /**< the customer demands */
290  int ncustomers, /**< the number of customers */
291  int nfacilities, /**< the number of facilities */
292  int nscenarios /**< the number of scenarios */
293  )
294 {
295  SCIP_VAR* var;
296  SCIP_Real maxdemand;
297  int i;
298  int j;
299  char name[SCIP_MAXSTRLEN];
300  assert(scip != NULL);
301 
302  /* adding the sufficient capacity constraints */
303  maxdemand = 0;
304  for( i = 0; i < nscenarios; i++)
305  {
306  SCIP_Real sumdemand = 0;
307  for( j = 0; j < ncustomers; j++ )
308  sumdemand += demands[j][i];
309 
310  if( sumdemand > maxdemand )
311  maxdemand = sumdemand;
312  }
313 
314  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "sufficientcapacity");
315  SCIP_CALL( SCIPcreateConsBasicLinear(scip, sufficientcap, name, 0, NULL, NULL, maxdemand, SCIPinfinity(scip)) );
316 
317  SCIP_CALL( SCIPaddCons(scip, (*sufficientcap)) );
318 
319 
320  /* adding the facility variables */
321  for( i = 0; i < nfacilities; i++ )
322  {
323  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "facility_%d", i);
324  SCIP_CALL( SCIPcreateVarBasic(scip, &var, name, 0.0, 1.0, fixedcost[i], SCIP_VARTYPE_BINARY) );
325 
326  SCIP_CALL( SCIPaddVar(scip, var) );
327 
328  /* storing the variable in the facility variable list */
329  facilityvars[i] = var;
330 
331  /* adding the variable to the sufficient capacity constraints */
332  SCIP_CALL( SCIPaddCoefLinear(scip, (*sufficientcap), var, capacity[i]) );
333  }
334 
335  return SCIP_OKAY;
336 }
337 
338 /** creates the scenario subproblems */
339 static
341  SCIP* scip, /**< SCIP data structure */
342  SCIP** subproblems, /**< the Benders' decomposition subproblems */
343  SCIP_VAR** facilityvars, /**< all variables representing facilities */
344  SCIP_VAR*** subfacilityvars, /**< the copies of the facility variables in the subproblems */
345  SCIP_VAR**** customervars, /**< all variables representing the satisfaction of demand */
346  SCIP_CONS*** capconss, /**< capacity constraints per facility */
347  SCIP_CONS*** demandconss, /**< demand constraints per customer */
348  SCIP_Real** costs, /**< the transportation costs from a facility to a customer */
349  SCIP_Real** demands, /**< the customer demands */
350  SCIP_Real* capacity, /**< the capacity of each facility */
351  SCIP_Real* fixedcost, /**< the fixed cost of opening a facility */
352  int ncustomers, /**< the number of customers */
353  int nfacilities, /**< the number of facilities */
354  int nscenarios /**< the number of scenarios */
355  )
356 {
357  SCIP_CONS* cons;
358  SCIP_VAR* var;
359  SCIP_Real coeff;
360  int i;
361  int j;
362  int k;
363  char name[SCIP_MAXSTRLEN];
364  assert(scip != NULL);
365 
366  /* adds the capacity constraints to the scenario */
367  for( i = 0; i < nfacilities; i++ )
368  {
369  for( j = 0; j < nscenarios; j++ )
370  {
371  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "capacity_%d_%d", i, j);
372  SCIP_CALL( SCIPcreateConsBasicLinear(subproblems[j], &cons, name, 0, NULL, NULL, -SCIPinfinity(subproblems[j]), 0.0) );
373 
374  SCIP_CALL( SCIPaddCons(subproblems[j], cons) );
375 
376  capconss[i][j] = cons;
377  }
378  }
379 
380  /* adds the demand constraints to the scenario */
381  for( i = 0; i < ncustomers; i++ )
382  {
383  for( j = 0; j < nscenarios; j++ )
384  {
385  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "demand_%d_%d", i, j);
386  SCIP_CALL( SCIPcreateConsBasicLinear(subproblems[j], &cons, name, 0, NULL, NULL, demands[i][j], SCIPinfinity(subproblems[j])) );
387 
388  SCIP_CALL( SCIPaddCons(subproblems[j], cons) );
389 
390  demandconss[i][j] = cons;
391  }
392  }
393 
394  for( i = 0; i < nfacilities; i++ )
395  {
396  for( j = 0; j < nscenarios; j++ )
397  {
398  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "facility_%d", i);
399  SCIP_CALL( SCIPcreateVarBasic(subproblems[j], &var, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_CONTINUOUS) );
400 
401  SCIP_CALL( SCIPaddVar(subproblems[j], var) );
402 
403  /* storing the variable in the facility variable list */
404  subfacilityvars[i][j] = var;
405 
406  /* adding the variable to the capacity constraints */
407  SCIP_CALL( SCIPaddCoefLinear(subproblems[j], capconss[i][j], subfacilityvars[i][j], -capacity[i]) );
408  }
409  }
410 
411  /* adding the customer variables to the scenario */
412  for( i = 0; i < ncustomers; i++ )
413  {
414  for( j = 0; j < nfacilities; j++ )
415  {
416  for( k = 0; k < nscenarios; k++ )
417  {
418  coeff = costs[i][j]/(SCIP_Real)nscenarios;
419  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "customer(%d,%d,%d)", i, j, k);
420  SCIP_CALL( SCIPcreateVarBasic(subproblems[k], &var, name, 0.0, SCIPinfinity(subproblems[k]), coeff, SCIP_VARTYPE_CONTINUOUS) );
421 
422  SCIP_CALL( SCIPaddVar(subproblems[k], var) );
423 
424  /* storing the customer variable in the list */
425  customervars[i][j][k] = var;
426 
427  if( costs[i][j] > 0 )
428  {
429  /* adding the variable to the capacity constraints */
430  SCIP_CALL( SCIPaddCoefLinear(subproblems[k], capconss[j][k], customervars[i][j][k], 1.0) );
431 
432  /* adding the variable to the demand constraints */
433  SCIP_CALL( SCIPaddCoefLinear(subproblems[k], demandconss[i][k], customervars[i][j][k], 1.0) );
434  }
435  }
436  }
437  }
438 
439  return SCIP_OKAY;
440 }
441 
442 
443 /** creates problem data */
444 static
446  SCIP* scip, /**< SCIP data structure */
447  SCIP_PROBDATA** probdata, /**< pointer to problem data */
448  SCIP** subproblems, /**< the Benders' decomposition subproblems */
449  SCIP_VAR** facilityvars, /**< all variables representing facilities */
450  SCIP_VAR*** subfacilityvars, /**< the copies of the facility variables in the subproblems */
451  SCIP_VAR**** customervars, /**< all variables representing the satisfaction of demand */
452  SCIP_CONS*** capconss, /**< capacity constraints per facility per scenario */
453  SCIP_CONS*** demandconss, /**< demand constraints per customer per scenario */
454  SCIP_CONS* sufficientcap, /**< ensuring sufficient capacity is provided to satisfy demand */
455  SCIP_Real** costs, /**< the transportation costs to a customer from a facility */
456  SCIP_Real** demands, /**< the customer demands per scenario */
457  SCIP_Real* capacity, /**< the capacity of each facility */
458  SCIP_Real* fixedcost, /**< the fixed cost of opening a facility */
459  int ncustomers, /**< the number of customers */
460  int nfacilities, /**< the number of facilities */
461  int nscenarios, /**< the number of scenarios */
462  SCIP_Bool usebenders /**< whether Benders' decomposition is used */
463  )
464 {
465  int i;
466  int j;
467 
468  assert(scip != NULL);
469  assert(probdata != NULL);
470 
471  /* allocate memory */
472  SCIP_CALL( SCIPallocBlockMemory(scip, probdata) );
473 
474  /* copying the subproblem information */
475  if( usebenders )
476  {
477  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*probdata)->subproblems, subproblems, nscenarios) );
478 
479  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*probdata)->subfacilityvars, nfacilities) );
480  for( i = 0; i < nfacilities; i++ )
481  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*probdata)->subfacilityvars[i], subfacilityvars[i], nscenarios) );
482  }
483 
484  /* copy variable arrays */
485  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*probdata)->facilityvars, facilityvars, nfacilities) );
486  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*probdata)->customervars, ncustomers) );
487  for( i = 0; i < ncustomers; i++ )
488  {
489  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*probdata)->customervars[i], nfacilities) );
490  for( j = 0; j < nfacilities; j++ )
491  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*probdata)->customervars[i][j], customervars[i][j],
492  nscenarios) );
493  }
494 
495  /* duplicate the constraint arrays */
496  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*probdata)->capconss, nfacilities) );
497  for( i = 0; i < nfacilities; i++ )
498  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*probdata)->capconss[i], capconss[i], nscenarios) );
499 
500  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*probdata)->demandconss, ncustomers) );
501  for( i = 0; i < ncustomers; i++ )
502  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*probdata)->demandconss[i], demandconss[i], nscenarios) );
503 
504  /* duplicate the data arrays */
505  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*probdata)->demands, ncustomers) );
506  for( i = 0; i < ncustomers; i++ )
507  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*probdata)->demands[i], demands[i], nscenarios) );
508 
509  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*probdata)->costs, ncustomers) );
510  for( i = 0; i < ncustomers; i++ )
511  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*probdata)->costs[i], costs[i], nfacilities) );
512 
513  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*probdata)->capacity, capacity, nfacilities) );
514  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*probdata)->fixedcost, fixedcost, nfacilities) );
515 
516  (*probdata)->sufficientcap = sufficientcap;
517  (*probdata)->ncustomers = ncustomers;
518  (*probdata)->nfacilities = nfacilities;
519  (*probdata)->nscenarios = nscenarios;
520  (*probdata)->usebenders = usebenders;
521 
522  return SCIP_OKAY;
523 }
524 
525 /** frees the memory of the given problem data */
526 static
528  SCIP* scip, /**< SCIP data structure */
529  SCIP_PROBDATA** probdata /**< pointer to problem data */
530  )
531 {
532  int i;
533  int j;
534  int k;
535 
536  assert(scip != NULL);
537  assert(probdata != NULL);
538 
539 #if 1
540  /* release all variables */
541  for( i = 0; i < (*probdata)->nfacilities; i++ )
542  SCIP_CALL( SCIPreleaseVar(scip, &(*probdata)->facilityvars[i]) );
543 
544  for( i = 0; i < (*probdata)->nscenarios; i++ )
545  {
546  SCIP* varscip;
547  if( (*probdata)->usebenders )
548  varscip = (*probdata)->subproblems[i];
549  else
550  varscip = scip;
551 
552  for( j = 0; j < (*probdata)->nfacilities; j++ )
553  {
554  for( k = 0; k < (*probdata)->ncustomers; k++ )
555  SCIP_CALL( SCIPreleaseVar(varscip, &(*probdata)->customervars[k][j][i]) );
556  }
557  }
558 
559  /* release all constraints */
560  for( i = 0; i < (*probdata)->nscenarios; ++i )
561  {
562  SCIP* consscip;
563  if( (*probdata)->usebenders )
564  consscip = (*probdata)->subproblems[i];
565  else
566  consscip = scip;
567 
568  for( j = 0; j < (*probdata)->ncustomers; j++ )
569  SCIP_CALL( SCIPreleaseCons(consscip, &(*probdata)->demandconss[j][i]) );
570  }
571 
572  for( i = 0; i < (*probdata)->nscenarios; ++i )
573  {
574  SCIP* consscip;
575  if( (*probdata)->usebenders )
576  consscip = (*probdata)->subproblems[i];
577  else
578  consscip = scip;
579 
580  for( j = 0; j < (*probdata)->nfacilities; ++j )
581  SCIP_CALL( SCIPreleaseCons(consscip, &(*probdata)->capconss[j][i]) );
582  }
583 
584  SCIP_CALL( SCIPreleaseCons(scip, &(*probdata)->sufficientcap) );
585 #endif
586 
587  /* free memory of arrays */
588  SCIPfreeBlockMemoryArray(scip, &(*probdata)->fixedcost, (*probdata)->nfacilities);
589  SCIPfreeBlockMemoryArray(scip, &(*probdata)->capacity, (*probdata)->nfacilities);
590 
591  for( i = (*probdata)->ncustomers - 1; i >= 0; i-- )
592  SCIPfreeBlockMemoryArray(scip, &(*probdata)->costs[i], (*probdata)->nfacilities);
593  SCIPfreeBlockMemoryArray(scip, &(*probdata)->costs, (*probdata)->ncustomers);
594 
595 
596  for( i = (*probdata)->ncustomers - 1; i >= 0; i-- )
597  SCIPfreeBlockMemoryArray(scip, &(*probdata)->demands[i], (*probdata)->nscenarios);
598  SCIPfreeBlockMemoryArray(scip, &(*probdata)->demands, (*probdata)->ncustomers);
599 
600  /* freeing the constraint memory arrays */
601  for( i = (*probdata)->ncustomers - 1; i >= 0; i-- )
602  SCIPfreeBlockMemoryArray(scip, &(*probdata)->demandconss[i], (*probdata)->nscenarios);
603  SCIPfreeBlockMemoryArray(scip, &(*probdata)->demandconss, (*probdata)->ncustomers);
604 
605  for( i = (*probdata)->nfacilities - 1; i >= 0; i-- )
606  SCIPfreeBlockMemoryArray(scip, &(*probdata)->capconss[i], (*probdata)->nscenarios);
607  SCIPfreeBlockMemoryArray(scip, &(*probdata)->capconss, (*probdata)->nfacilities);
608 
609  /* freeing the variable memory arrays */
610  for( i = (*probdata)->ncustomers - 1; i >= 0; i-- )
611  {
612  for( j = (*probdata)->nfacilities - 1; j >= 0; j-- )
613  SCIPfreeBlockMemoryArray(scip, &(*probdata)->customervars[i][j], (*probdata)->nscenarios);
614 
615  SCIPfreeBlockMemoryArray(scip, &(*probdata)->customervars[i], (*probdata)->nfacilities);
616  }
617  SCIPfreeBlockMemoryArray(scip, &(*probdata)->customervars, (*probdata)->ncustomers);
618 
619  SCIPfreeBlockMemoryArray(scip, &(*probdata)->facilityvars, (*probdata)->nfacilities);
620 
621  /* freeing the subproblem information */
622  if( (*probdata)->usebenders )
623  {
624  /* freeing the sub facility variables */
625  for( i = 0; i < (*probdata)->nscenarios; i++ )
626  {
627  for( j = 0; j < (*probdata)->nfacilities; j++ )
628  SCIP_CALL( SCIPreleaseVar((*probdata)->subproblems[i], &(*probdata)->subfacilityvars[j][i]) );
629  }
630 
631  for( i = (*probdata)->nfacilities - 1; i >= 0; i-- )
632  SCIPfreeBlockMemoryArray(scip, &(*probdata)->subfacilityvars[i], (*probdata)->nscenarios);
633 
634  SCIPfreeBlockMemoryArray(scip, &(*probdata)->subfacilityvars, (*probdata)->nfacilities);
635 
636 
637  for( i = (*probdata)->nscenarios - 1; i >= 0 ; i-- )
638  SCIP_CALL( SCIPfree(&(*probdata)->subproblems[i]) );
639  SCIPfreeBlockMemoryArray(scip, &(*probdata)->subproblems, (*probdata)->nscenarios);
640  }
641 
642  /* free probdata */
643  SCIPfreeBlockMemory(scip, probdata);
644 
645  return SCIP_OKAY;
646 }
647 
648 /**@} */
649 
650 /**@name Callback methods of problem data
651  *
652  * @{
653  */
654 
655 /** frees user data of original problem (called when the original problem is freed) */
656 static
657 SCIP_DECL_PROBDELORIG(probdelorigScflp)
658 {
659  assert(scip != NULL);
660  assert(probdata != NULL);
661 
662  SCIPdebugMsg(scip, "free original problem data\n");
663 
664  SCIP_CALL( probdataFree(scip, probdata) );
665 
666  return SCIP_OKAY;
667 }
668 
669 /** creates user data of transformed problem by transforming the original user problem data
670  * (called after problem was transformed) */
671 static
672 SCIP_DECL_PROBTRANS(probtransScflp)
673 {
674  SCIPdebugMsg(scip, "transforming problem data\n");
675 
676  return SCIP_OKAY;
677 }
678 
679 /** frees user data of transformed problem (called when the transformed problem is freed) */
680 static
681 SCIP_DECL_PROBDELTRANS(probdeltransScflp)
682 {
683  SCIPdebugMsg(scip, "free transformed problem data\n");
684 
685  return SCIP_OKAY;
686 }
687 
688 /**@} */
689 
690 
691 /**@name Interface methods
692  *
693  * @{
694  */
695 
696 /** sets up the problem data */
698  SCIP* scip, /**< SCIP data structure */
699  const char* probname, /**< problem name */
700  SCIP_Real** costs, /**< the transportation costs from a facility to a customer */
701  SCIP_Real** demands, /**< the customer demands */
702  SCIP_Real* capacity, /**< the capacity of each facility */
703  SCIP_Real* fixedcost, /**< the fixed cost of opening a facility */
704  int ncustomers, /**< the number of customers */
705  int nfacilities, /**< the number of facilities */
706  int nscenarios, /**< the number of Benders' decomposition scenarios */
707  SCIP_Bool usebenders /**< will Benders' decomposition be used to solve the problem */
708  )
709 {
710  SCIP** subproblems;
711  SCIP_PROBDATA* probdata;
712  SCIP_CONS*** demandconss;
713  SCIP_CONS*** capconss;
714  SCIP_CONS* sufficientcap;
715  SCIP_VAR** facilityvars;
716  SCIP_VAR*** subfacilityvars;
717  SCIP_VAR**** customervars;
718  int i;
719  int j;
720 
721  assert(scip != NULL);
722 
723  /* create problem in SCIP and add non-NULL callbacks via setter functions */
724  SCIP_CALL( SCIPcreateProbBasic(scip, probname) );
725 
726  SCIP_CALL( SCIPsetProbDelorig(scip, probdelorigScflp) );
727  SCIP_CALL( SCIPsetProbTrans(scip, probtransScflp) );
728  SCIP_CALL( SCIPsetProbDeltrans(scip, probdeltransScflp) );
729 
730  /* set objective sense */
732 
733  SCIP_CALL( SCIPallocBufferArray(scip, &demandconss, ncustomers) );
734  for( i = 0; i < ncustomers; i++ )
735  SCIP_CALL( SCIPallocBufferArray(scip, &demandconss[i], nscenarios) );
736  SCIP_CALL( SCIPallocBufferArray(scip, &capconss, nfacilities) );
737  for( i = 0; i < nfacilities; i++ )
738  SCIP_CALL( SCIPallocBufferArray(scip, &capconss[i], nscenarios) );
739 
740  SCIP_CALL( SCIPallocBufferArray(scip, &facilityvars, nfacilities) );
741  SCIP_CALL( SCIPallocBufferArray(scip, &customervars, ncustomers) );
742  for( i = 0; i < ncustomers; i++ )
743  {
744  SCIP_CALL( SCIPallocBufferArray(scip, &customervars[i], nfacilities) );
745  for( j = 0; j < nfacilities; j++ )
746  SCIP_CALL( SCIPallocBufferArray(scip, &customervars[i][j], nscenarios) );
747  }
748 
749  sufficientcap = NULL;
750 
751  subproblems = NULL;
752  subfacilityvars = NULL;
753 
754  if( usebenders )
755  {
756  char subprobname[SCIP_MAXSTRLEN];
757 
758  /* allocting the memory for the subproblem specific information */
759  SCIP_CALL( SCIPallocBufferArray(scip, &subproblems, nscenarios) );
760  SCIP_CALL( SCIPallocBufferArray(scip, &subfacilityvars, nfacilities) );
761  for( i = 0; i < nfacilities; i++ )
762  SCIP_CALL( SCIPallocBufferArray(scip, &subfacilityvars[i], nscenarios) );
763 
764  /* creating the subproblems */
765  for( i = 0; i < nscenarios; i++ )
766  {
767  SCIP_CALL( SCIPcreate(&subproblems[i]) );
768 
769  /* include default SCIP plugins */
770  SCIP_CALL( SCIPincludeDefaultPlugins(subproblems[i]) );
771 
772  (void) SCIPsnprintf(subprobname, SCIP_MAXSTRLEN, "sub_%s_%d", probname, i);
773  SCIP_CALL( SCIPcreateProbBasic(subproblems[i], subprobname) );
774  }
775 
776  /* creating the master problem */
777  SCIP_CALL( createMasterproblem(scip, facilityvars, &sufficientcap, capacity, fixedcost, demands, ncustomers,
778  nfacilities, nscenarios) );
779  SCIP_CALL( createSubproblems(scip, subproblems, facilityvars, subfacilityvars, customervars, capconss,
780  demandconss, costs, demands, capacity, fixedcost, ncustomers, nfacilities, nscenarios) );
781 
782  /* including the Benders' decomposition plugin */
783  SCIP_CALL( SCIPcreateBendersDefault(scip, subproblems, nscenarios) );
784 
785  /* activating the Benders' decomposition constraint handlers */
786  SCIP_CALL( SCIPsetBoolParam(scip, "constraints/benders/active", TRUE) );
787  SCIP_CALL( SCIPsetBoolParam(scip, "constraints/benderslp/active", TRUE) );
788 
789  SCIP_CALL( SCIPsetIntParam(scip, "constraints/benders/maxprerounds", 1) );
790  SCIP_CALL( SCIPsetIntParam(scip, "presolving/maxrounds", 1) );
791  }
792  else
793  {
794  /* creating the original problem */
795  SCIP_CALL( createOriginalproblem(scip, facilityvars, customervars, capconss, demandconss, &sufficientcap, costs,
796  demands, capacity, fixedcost, ncustomers, nfacilities, nscenarios) );
797  }
798 
799  /* create problem data */
800  SCIP_CALL( probdataCreate(scip, &probdata, subproblems, facilityvars, subfacilityvars, customervars, capconss,
801  demandconss, sufficientcap, costs, demands, capacity, fixedcost, ncustomers, nfacilities, nscenarios, usebenders) );
802 
803  /* set user problem data */
804  SCIP_CALL( SCIPsetProbData(scip, probdata) );
805 
806  /* free local buffer arrays */
807  if( usebenders )
808  {
809  SCIPfreeBufferArray(scip, &subproblems);
810 
811  for( i = nfacilities - 1; i >= 0; i-- )
812  SCIPfreeBufferArray(scip, &subfacilityvars[i]);
813  SCIPfreeBufferArray(scip, &subfacilityvars);
814  }
815 
816  for( i = ncustomers - 1; i >= 0; i-- )
817  {
818  for( j = nfacilities - 1; j >= 0; j-- )
819  SCIPfreeBufferArray(scip, &customervars[i][j]);
820  SCIPfreeBufferArray(scip, &customervars[i]);
821  }
822  SCIPfreeBufferArray(scip, &customervars);
823  SCIPfreeBufferArray(scip, &facilityvars);
824 
825  for( i = nfacilities - 1; i >= 0; i-- )
826  SCIPfreeBufferArray(scip, &capconss[i]);
827  SCIPfreeBufferArray(scip, &capconss);
828 
829  for( i = ncustomers - 1; i >= 0; i-- )
830  SCIPfreeBufferArray(scip, &demandconss[i]);
831  SCIPfreeBufferArray(scip, &demandconss);
832 
833  return SCIP_OKAY;
834 }
835 
836 /** returns the number of facilities */
838  SCIP_PROBDATA* probdata /**< problem data */
839  )
840 {
841  assert(probdata != NULL);
842 
843  return probdata->nfacilities;
844 }
845 
846 /** returns the number of customers */
848  SCIP_PROBDATA* probdata /**< problem data */
849  )
850 {
851  assert(probdata != NULL);
852 
853  return probdata->ncustomers;
854 }
855 
856 /** returns the facility variables */
858  SCIP_PROBDATA* probdata /**< problem data */
859  )
860 {
861  assert(probdata != NULL);
862 
863  return probdata->facilityvars;
864 }
865 
866 /**@} */
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:116
static SCIP_RETCODE createSubproblems(SCIP *scip, SCIP **subproblems, SCIP_VAR **facilityvars, SCIP_VAR ***subfacilityvars, SCIP_VAR ****customervars, SCIP_CONS ***capconss, SCIP_CONS ***demandconss, SCIP_Real **costs, SCIP_Real **demands, SCIP_Real *capacity, SCIP_Real *fixedcost, int ncustomers, int nfacilities, int nscenarios)
#define NULL
Definition: def.h:239
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:99
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
static SCIP_RETCODE createOriginalproblem(SCIP *scip, SCIP_VAR **facilityvars, SCIP_VAR ****customervars, SCIP_CONS ***capconss, SCIP_CONS ***demandconss, SCIP_CONS **sufficientcap, SCIP_Real **costs, SCIP_Real **demands, SCIP_Real *capacity, SCIP_Real *fixedcost, int ncustomers, int nfacilities, int nscenarios)
#define SCIP_MAXSTRLEN
Definition: def.h:260
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1251
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_RETCODE SCIPcreateBendersDefault(SCIP *scip, SCIP **subproblems, int nsubproblems)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10017
#define TRUE
Definition: def.h:64
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
int SCIPprobdataGetNCustomers(SCIP_PROBDATA *probdata)
SCIP_RETCODE SCIPsetProbData(SCIP *scip, SCIP_PROBDATA *probdata)
Definition: scip_prob.c:1070
static SCIP_DECL_PROBDELORIG(probdelorigScflp)
SCIP_RETCODE SCIPcreateVarBasic(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype)
Definition: scip_var.c:184
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:114
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:142
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip_general.c:339
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:97
#define SCIPdebugMsg
Definition: scip_message.h:88
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_RETCODE SCIPcreateProbBasic(SCIP *scip, const char *name)
Definition: scip_prob.c:223
static SCIP_DECL_PROBTRANS(probtransScflp)
int SCIPprobdataGetNFacilities(SCIP_PROBDATA *probdata)
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:111
static SCIP_RETCODE probdataCreate(SCIP *scip, SCIP_PROBDATA **probdata, SCIP **subproblems, SCIP_VAR **facilityvars, SCIP_VAR ***subfacilityvars, SCIP_VAR ****customervars, SCIP_CONS ***capconss, SCIP_CONS ***demandconss, SCIP_CONS *sufficientcap, SCIP_Real **costs, SCIP_Real **demands, SCIP_Real *capacity, SCIP_Real *fixedcost, int ncustomers, int nfacilities, int nscenarios, SCIP_Bool usebenders)
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition: scip_prob.c:1298
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2822
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip_param.c:520
SCIP_RETCODE SCIPprobdataCreate(SCIP *scip, const char *probname, SCIP_Real **costs, SCIP_Real **demands, SCIP_Real *capacity, SCIP_Real *fixedcost, int ncustomers, int nfacilities, int nscenarios, SCIP_Bool usebenders)
#define SCIP_CALL(x)
Definition: def.h:351
Problem data for Stochastic Capacitated Facility Location problem.
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:130
#define SCIP_Bool
Definition: def.h:62
SCIP_RETCODE SCIPsetProbTrans(SCIP *scip, SCIP_DECL_PROBTRANS((*probtrans)))
Definition: scip_prob.c:264
SCIP_RETCODE SCIPincludeDefaultPlugins(SCIP *scip)
static SCIP_RETCODE probdataFree(SCIP *scip, SCIP_PROBDATA **probdata)
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip_param.c:578
Constraint handler for linear constraints in their most general form, .
SCIP_VAR ** SCIPprobdataGetFacilityVars(SCIP_PROBDATA *probdata)
static SCIP_DECL_PROBDELTRANS(probdeltransScflp)
struct SCIP_ProbData SCIP_PROBDATA
Definition: type_prob.h:44
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1724
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1187
#define SCIP_Real
Definition: def.h:150
default Benders&#39; decomposition plugin
static SCIP_RETCODE createMasterproblem(SCIP *scip, SCIP_VAR **facilityvars, SCIP_CONS **sufficientcap, SCIP_Real *capacity, SCIP_Real *fixedcost, SCIP_Real **demands, int ncustomers, int nfacilities, int nscenarios)
SCIP_RETCODE SCIPsetProbDeltrans(SCIP *scip, SCIP_DECL_PROBDELTRANS((*probdeltrans)))
Definition: scip_prob.c:285
SCIP_RETCODE SCIPsetProbDelorig(SCIP *scip, SCIP_DECL_PROBDELORIG((*probdelorig)))
Definition: scip_prob.c:243
default SCIP plugins
SCIP callable library.
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip_general.c:371