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-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 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_TIMING SCIP_PRESOLTIMING_FAST /* timing of the presolver (fast, medium, or exhaustive) */
37 
38 #define MAXABSBOUND 1000.0 /**< maximum absolute variable bounds for aggregation */
39 
40 /*
41  * Default parameter settings
42  */
43 
44 #define DEFAULT_MAXSHIFT SCIP_LONGINT_MAX /**< absolute value of maximum shift */
45 #define DEFAULT_FLIPPING TRUE /**< is flipping allowed? */
46 #define DEFAULT_INTEGER TRUE /**< are only integer ranges shifted */
47 
48 /*
49  * Data structures
50  */
51 
52 /** presolver data */
53 struct SCIP_PresolData
54 {
55  SCIP_Longint maxshift; /**< absolute value of maximum shift */
56  SCIP_Bool flipping; /**< is flipping allowed? */
57  SCIP_Bool integer; /**< shift only integer values? */
58 };
59 
60 
61 /*
62  * Local methods
63  */
64 
65 /** initializes the presolver data */
66 static
68  SCIP_PRESOLDATA* presoldata /**< presolver data */
69  )
70 {
71  assert(presoldata != NULL);
72 
73  presoldata->maxshift = DEFAULT_MAXSHIFT;
74  presoldata->flipping = DEFAULT_FLIPPING;
75  presoldata->integer = DEFAULT_INTEGER;
76 }
77 
78 /*
79  * Callback methods of presolver
80  */
81 
82 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
83 static
84 SCIP_DECL_PRESOLCOPY(presolCopyBoundshift)
85 { /*lint --e{715}*/
86  assert(scip != NULL);
87  assert(presol != NULL);
88  assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
89 
90  /* call inclusion method of presolver */
92 
93  return SCIP_OKAY;
94 }
95 
96 
97 /** destructor of presolver to free user data (called when SCIP is exiting) */
98 /**! [SnippetPresolFreeBoundshift] */
99 static
100 SCIP_DECL_PRESOLFREE(presolFreeBoundshift)
101 { /*lint --e{715}*/
102  SCIP_PRESOLDATA* presoldata;
103 
104  /* free presolver data */
105  presoldata = SCIPpresolGetData(presol);
106  assert(presoldata != NULL);
107 
108  SCIPfreeBlockMemory(scip, &presoldata);
109  SCIPpresolSetData(presol, NULL);
110 
111  return SCIP_OKAY;
112 }
113 /**! [SnippetPresolFreeBoundshift] */
114 
115 
116 /** presolving execution method */
117 static
118 SCIP_DECL_PRESOLEXEC(presolExecBoundshift)
119 { /*lint --e{715}*/
120  SCIP_PRESOLDATA* presoldata;
121  SCIP_VAR** scipvars;
122  SCIP_VAR** vars;
123  int nbinvars;
124  int nvars;
125  int v;
126 
127  assert(scip != NULL);
128  assert(presol != NULL);
129  assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
130  assert(result != NULL);
131 
132  *result = SCIP_DIDNOTRUN;
133 
134  /* get presolver data */
135  presoldata = SCIPpresolGetData(presol);
136  assert(presoldata != NULL);
137 
138  /* get the problem variables */
139  scipvars = SCIPgetVars(scip);
140  nbinvars = SCIPgetNBinVars(scip);
141  nvars = SCIPgetNVars(scip) - nbinvars;
142 
143  if( nvars == 0 )
144  return SCIP_OKAY;
145 
146  if( SCIPdoNotAggr(scip) )
147  return SCIP_OKAY;
148 
149  *result = SCIP_DIDNOTFIND;
150 
151  /* copy the integer variables into an own array, since adding new integer variables affects the left-most slots in
152  * the array and thereby interferes with our search loop
153  */
154  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &scipvars[nbinvars], nvars) );
155 
156  /* scan the integer, implicit, and continuous variables for possible conversion */
157  for( v = nvars - 1; v >= 0; --v )
158  {
159  SCIP_VAR* var = vars[v];
160  SCIP_Real lb;
161  SCIP_Real ub;
162 
163  assert(SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
164 
165  /* get current variable's bounds */
166  lb = SCIPvarGetLbGlobal(var);
167  ub = SCIPvarGetUbGlobal(var);
168 
169  /* it can happen that the variable bounds of integer variables have not been propagated yet or contain
170  * some small noise; this will result in an aggregation that might trigger assertions when updating bounds of
171  * aggregated variables (see #1817)
172  */
173  if( SCIPvarIsIntegral(var) )
174  {
175  assert(SCIPisIntegral(scip, lb));
176  assert(SCIPisIntegral(scip, ub));
177 
178  lb = SCIPadjustedVarLb(scip, var, lb);
179  ub = SCIPadjustedVarUb(scip, var, ub);
180  }
181 
182  assert( SCIPisLE(scip, lb, ub) );
183  if( SCIPisEQ(scip, lb, ub) )
184  continue;
185  if( presoldata->integer && !SCIPisIntegral(scip, ub - lb) )
186  continue;
187 
188  /* check if bounds are shiftable */
189  if( !SCIPisEQ(scip, lb, 0.0) && /* lower bound != 0.0 */
190  SCIPisLT(scip, ub, SCIPinfinity(scip)) && /* upper bound != infinity */
191  SCIPisGT(scip, lb, -SCIPinfinity(scip)) && /* lower bound != -infinity */
192 #if 0
193  SCIPisLT(scip, ub - lb, SCIPinfinity(scip)) && /* interval length less than SCIPinfinity(scip) */
194 #endif
195  SCIPisLT(scip, ub - lb, (SCIP_Real) presoldata->maxshift) && /* less than max shifting */
196  SCIPisLE(scip, REALABS(lb), MAXABSBOUND) && /* ensures a small constant in aggregation */
197  SCIPisLE(scip, REALABS(ub), MAXABSBOUND) ) /* ensures a small constant in aggregation */
198  {
199  SCIP_VAR* newvar;
200  char newvarname[SCIP_MAXSTRLEN];
201  SCIP_Bool infeasible;
202  SCIP_Bool redundant;
203  SCIP_Bool aggregated;
204 
205  SCIPdebugMsg(scip, "convert range <%s>[%g,%g] to [%g,%g]\n", SCIPvarGetName(var), lb, ub, 0.0, (ub - lb) );
206 
207  /* create new variable */
208  (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_shift", SCIPvarGetName(var));
209  SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, 0.0, (ub - lb), 0.0, SCIPvarGetType(var),
210  SCIPvarIsInitial(var), SCIPvarIsRemovable(var), NULL, NULL, NULL, NULL, NULL) );
211  SCIP_CALL( SCIPaddVar(scip, newvar) );
212 
213  /* aggregate old variable with new variable */
214  if( presoldata->flipping )
215  {
216  if( REALABS(ub) < REALABS(lb) )
217  {
218  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, 1.0, 1.0, ub, &infeasible, &redundant, &aggregated) );
219  }
220  else
221  {
222  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, 1.0, -1.0, lb, &infeasible, &redundant, &aggregated) );
223  }
224  }
225  else
226  {
227  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, 1.0, -1.0, lb, &infeasible, &redundant, &aggregated) );
228  }
229 
230  assert(!infeasible);
231  assert(redundant);
232  assert(aggregated);
233  SCIPdebugMsg(scip, "var <%s> with bounds [%f,%f] has obj %f\n",
234  SCIPvarGetName(newvar),SCIPvarGetLbGlobal(newvar),SCIPvarGetUbGlobal(newvar),SCIPvarGetObj(newvar));
235 
236  /* release variable */
237  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
238 
239  /* take care of statistic */
240  (*naggrvars)++;
241  *result = SCIP_SUCCESS;
242  }
243  }
244 
245  /* free temporary memory */
246  SCIPfreeBufferArray(scip, &vars);
247 
248  return SCIP_OKAY;
249 }
250 
251 
252 /*
253  * presolver specific interface methods
254  */
255 
256 /** creates the boundshift presolver and includes it in SCIP */
258  SCIP* scip /**< SCIP data structure */
259  )
260 {
261  SCIP_PRESOLDATA* presoldata;
262  SCIP_PRESOL* presolptr;
263 
264  /* create boundshift presolver data */
265  SCIP_CALL( SCIPallocBlockMemory(scip, &presoldata) );
266  initPresoldata(presoldata);
267 
268  /* include presolver */
270  presolExecBoundshift,
271  presoldata) );
272 
273  assert(presolptr != NULL);
274 
275  SCIP_CALL( SCIPsetPresolCopy(scip, presolptr, presolCopyBoundshift) );
276  SCIP_CALL( SCIPsetPresolFree(scip, presolptr, presolFreeBoundshift) );
277 
278  /* add probing presolver parameters */
280  "presolving/boundshift/maxshift",
281  "absolute value of maximum shift",
282  &presoldata->maxshift, TRUE, DEFAULT_MAXSHIFT, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
284  "presolving/boundshift/flipping",
285  "is flipping allowed (multiplying with -1)?",
286  &presoldata->flipping, TRUE, DEFAULT_FLIPPING, NULL, NULL) );
288  "presolving/boundshift/integer",
289  "shift only integer ranges?",
290  &presoldata->integer, TRUE, DEFAULT_INTEGER, NULL, NULL) );
291 
292  return SCIP_OKAY;
293 }
SCIP_RETCODE SCIPincludePresolBasic(SCIP *scip, SCIP_PRESOL **presolptr, const char *name, const char *desc, int priority, int maxrounds, SCIP_PRESOLTIMING timing, SCIP_DECL_PRESOLEXEC((*presolexec)), SCIP_PRESOLDATA *presoldata)
Definition: scip.c:6917
struct SCIP_PresolData SCIP_PRESOLDATA
Definition: type_presol.h:37
#define PRESOL_NAME
#define PRESOL_MAXROUNDS
SCIP_RETCODE SCIPsetPresolFree(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLFREE((*presolfree)))
Definition: scip.c:6968
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17276
#define SCIP_MAXSTRLEN
Definition: def.h:259
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:16863
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18766
#define DEFAULT_FLIPPING
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition: scip.c:21985
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4293
#define PRESOL_PRIORITY
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:47028
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10011
#define TRUE
Definition: def.h:63
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPincludePresolBoundshift(SCIP *scip)
SCIP_PRESOLDATA * SCIPpresolGetData(SCIP_PRESOL *presol)
Definition: presol.c:466
static SCIP_DECL_PRESOLEXEC(presolExecBoundshift)
static void initPresoldata(SCIP_PRESOLDATA *presoldata)
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:22602
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:22628
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46963
#define SCIP_LONGINT_MAX
Definition: def.h:135
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22632
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip.c:21953
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:16873
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:22585
#define SCIPdebugMsg
Definition: scip.h:455
static SCIP_DECL_PRESOLCOPY(presolCopyBoundshift)
#define PRESOL_TIMING
static SCIP_DECL_PRESOLFREE(presolFreeBoundshift)
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17286
#define DEFAULT_INTEGER
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46976
void SCIPpresolSetData(SCIP_PRESOL *presol, SCIP_PRESOLDATA *presoldata)
Definition: presol.c:476
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16662
#define REALABS(x)
Definition: def.h:173
#define SCIP_CALL(x)
Definition: def.h:350
#define PRESOL_DESC
#define SCIP_Bool
Definition: def.h:61
#define DEFAULT_MAXSHIFT
const char * SCIPpresolGetName(SCIP_PRESOL *presol)
Definition: presol.c:553
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17124
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip.c:17619
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:11857
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:11812
#define MAXABSBOUND
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47002
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:47112
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:11492
SCIP_RETCODE SCIPsetPresolCopy(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLCOPY((*presolcopy)))
Definition: scip.c:6952
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:11767
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition: scip.c:25684
#define SCIP_Real
Definition: def.h:149
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip.c:25848
#define SCIP_Longint
Definition: def.h:134
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16827
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46989
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16853
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4239
presolver that converts integer variables with domain [a,b] to integer variables with domain [0...