Scippy

SCIP

Solving Constraint Integer Programs

presol_boundshift.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-2014 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 email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file presol_boundshift.c
17  * @brief presolver that converts variables with domain [a,b] to variables with domain [0,b-a]
18  * @author Stefan Heinz
19  * @author Michael Winkler
20  */
21 
22 /**@todo test this presolving step to decide whether to turn it in default mode on or off */
23 
24 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
25 
26 #include <assert.h>
27 #include <string.h>
28 
29 #include "scip/presol_boundshift.h"
30 
31 
32 #define PRESOL_NAME "boundshift"
33 #define PRESOL_DESC "converts variables with domain [a,b] to variables with domain [0,b-a]"
34 #define PRESOL_PRIORITY 7900000 /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */
35 #define PRESOL_MAXROUNDS 0 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
36 #define PRESOL_DELAY FALSE /**< should presolver be delayed, if other presolvers found reductions? */
37 
38 
39 /*
40  * Default parameter settings
41  */
42 
43 #define DEFAULT_MAXSHIFT SCIP_LONGINT_MAX /**< absolute value of maximum shift */
44 #define DEFAULT_FLIPPING TRUE /**< is flipping allowed? */
45 #define DEFAULT_INTEGER TRUE /**< are only integer ranges shifted */
46 
47 /*
48  * Data structures
49  */
50 
51 /** presolver data */
52 struct SCIP_PresolData
53 {
54  SCIP_Longint maxshift; /**< absolute value of maximum shift */
55  SCIP_Bool flipping; /**< is flipping allowed? */
56  SCIP_Bool integer; /**< shift only integer values? */
57 };
58 
59 
60 /*
61  * Local methods
62  */
63 
64 /** initializes the presolver data */
65 static
67  SCIP_PRESOLDATA* presoldata /**< presolver data */
68  )
69 {
70  assert(presoldata != NULL);
71 
72  presoldata->maxshift = DEFAULT_MAXSHIFT;
73  presoldata->flipping = DEFAULT_FLIPPING;
74  presoldata->integer = DEFAULT_INTEGER;
75 }
76 
77 /*
78  * Callback methods of presolver
79  */
80 
81 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
82 static
83 SCIP_DECL_PRESOLCOPY(presolCopyBoundshift)
84 { /*lint --e{715}*/
85  assert(scip != NULL);
86  assert(presol != NULL);
87  assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
88 
89  /* call inclusion method of presolver */
91 
92  return SCIP_OKAY;
93 }
94 
95 
96 /** destructor of presolver to free user data (called when SCIP is exiting) */
97 static
98 SCIP_DECL_PRESOLFREE(presolFreeBoundshift)
99 { /*lint --e{715}*/
100  SCIP_PRESOLDATA* presoldata;
101 
102  /* free presolver data */
103  presoldata = SCIPpresolGetData(presol);
104  assert(presoldata != NULL);
105 
106  SCIPfreeMemory(scip, &presoldata);
107  SCIPpresolSetData(presol, NULL);
108 
109  return SCIP_OKAY;
110 }
111 
112 
113 /** presolving execution method */
114 static
115 SCIP_DECL_PRESOLEXEC(presolExecBoundshift)
116 { /*lint --e{715}*/
117  SCIP_PRESOLDATA* presoldata;
118  SCIP_VAR** scipvars;
119  SCIP_VAR** vars;
120  int nbinvars;
121  int nvars;
122  int v;
123 
124  assert(scip != NULL);
125  assert(presol != NULL);
126  assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
127  assert(result != NULL);
128 
129  *result = SCIP_DIDNOTRUN;
130 
131  /* get presolver data */
132  presoldata = SCIPpresolGetData(presol);
133  assert(presoldata != NULL);
134 
135  /* get the problem variables */
136  scipvars = SCIPgetVars(scip);
137  nbinvars = SCIPgetNBinVars(scip);
138  nvars = SCIPgetNVars(scip) - nbinvars;
139 
140  if( nvars == 0 )
141  return SCIP_OKAY;
142 
143  if( SCIPdoNotAggr(scip) )
144  return SCIP_OKAY;
145 
146  *result = SCIP_DIDNOTFIND;
147 
148  /* copy the integer variables into an own array, since adding new integer variables affects the left-most slots in
149  * the array and thereby interferes with our search loop
150  */
151  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &scipvars[nbinvars], nvars) );
152 
153  /* scan the integer, implicit, and continuous variables for possible conversion */
154  for( v = nvars - 1; v >= 0; --v )
155  {
156  SCIP_VAR* var = vars[v];
157  SCIP_Real lb;
158  SCIP_Real ub;
159 
160  assert(SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
161 
162  /* get current variable's bounds */
163  lb = SCIPvarGetLbGlobal(var);
164  ub = SCIPvarGetUbGlobal(var);
165 
166  assert( SCIPisLE(scip, lb, ub) );
167  if( SCIPisEQ(scip, lb, ub) )
168  continue;
169  if( presoldata->integer && !SCIPisIntegral(scip, ub - lb) )
170  continue;
171 
172  /* check if bounds are shiftable */
173  if( !SCIPisEQ(scip, lb, 0.0) && /* lower bound != 0.0 */
174  SCIPisLT(scip, ub, SCIPinfinity(scip)) && /* upper bound != infinity */
175  SCIPisGT(scip, lb, -SCIPinfinity(scip)) && /* lower bound != -infinity */
176 #if 0
177  SCIPisLT(scip, ub - lb, SCIPinfinity(scip)) && /* interval length less than SCIPinfinity(scip) */
178 #endif
179  SCIPisLT(scip, ub - lb, (SCIP_Real) presoldata->maxshift) ) /* less than max shifting */
180  {
181  SCIP_VAR* newvar;
182  char newvarname[SCIP_MAXSTRLEN];
183  SCIP_Bool infeasible;
184  SCIP_Bool redundant;
185  SCIP_Bool aggregated;
186 
187  SCIPdebugMessage("convert range <%s>[%g,%g] to [%g,%g]\n", SCIPvarGetName(var), lb, ub, 0.0, (ub - lb) );
188 
189  /* create new variable */
190  (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_shift", SCIPvarGetName(var));
191  SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, 0.0, (ub - lb), 0.0, SCIPvarGetType(var),
193  SCIP_CALL( SCIPaddVar(scip, newvar) );
194 
195  /* aggregate old variable with new variable */
196  if( presoldata->flipping )
197  {
198  if( REALABS(ub) < REALABS(lb) )
199  {
200  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, 1.0, 1.0, ub, &infeasible, &redundant, &aggregated) );
201  }
202  else
203  {
204  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, 1.0, -1.0, lb, &infeasible, &redundant, &aggregated) );
205  }
206  }
207  else
208  {
209  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, 1.0, -1.0, lb, &infeasible, &redundant, &aggregated) );
210  }
211 
212  assert(!infeasible);
213  assert(redundant);
214  assert(aggregated);
215  SCIPdebugMessage("var <%s> with bounds [%f,%f] has obj %f\n",
216  SCIPvarGetName(newvar),SCIPvarGetLbGlobal(newvar),SCIPvarGetUbGlobal(newvar),SCIPvarGetObj(newvar));
217 
218  /* release variable */
219  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
220 
221  /* take care of statistic */
222  (*naggrvars)++;
223  *result = SCIP_SUCCESS;
224  }
225  }
226 
227  /* free temporary memory */
228  SCIPfreeBufferArray(scip, &vars);
229 
230  return SCIP_OKAY;
231 }
232 
233 
234 /*
235  * presolver specific interface methods
236  */
237 
238 /** creates the boundshift presolver and includes it in SCIP */
240  SCIP* scip /**< SCIP data structure */
241  )
242 {
243  SCIP_PRESOLDATA* presoldata;
244  SCIP_PRESOL* presolptr;
245 
246  /* create boundshift presolver data */
247  SCIP_CALL( SCIPallocMemory(scip, &presoldata) );
248  initPresoldata(presoldata);
249 
250  /* include presolver */
252  presolExecBoundshift,
253  presoldata) );
254 
255  assert(presolptr != NULL);
256 
257  SCIP_CALL( SCIPsetPresolCopy(scip, presolptr, presolCopyBoundshift) );
258  SCIP_CALL( SCIPsetPresolFree(scip, presolptr, presolFreeBoundshift) );
259 
260  /* add probing presolver parameters */
262  "presolving/boundshift/maxshift",
263  "absolute value of maximum shift",
264  &presoldata->maxshift, TRUE, DEFAULT_MAXSHIFT, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
266  "presolving/boundshift/flipping",
267  "is flipping allowed (multiplying with -1)?",
268  &presoldata->flipping, TRUE, DEFAULT_FLIPPING, NULL, NULL) );
270  "presolving/boundshift/integer",
271  "shift only integer ranges?",
272  &presoldata->integer, TRUE, DEFAULT_INTEGER, NULL, NULL) );
273 
274  return SCIP_OKAY;
275 }
276