SCIP Doxygen Documentation
Loading...
Searching...
No Matches
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-2026 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 presol_boundshift.c
26 * @ingroup DEFPLUGINS_PRESOL
27 * @brief presolver that converts variables with domain [a,b] to variables with domain [0,b-a]
28 * @author Stefan Heinz
29 * @author Michael Winkler
30 */
31
32/**@todo test this presolving step to decide whether to turn it in default mode on or off */
33
34/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35
38#include "scip/pub_message.h"
39#include "scip/pub_misc.h"
40#include "scip/pub_presol.h"
41#include "scip/pub_var.h"
42#include "scip/scip_mem.h"
43#include "scip/scip_message.h"
44#include "scip/scip_numerics.h"
45#include "scip/scip_param.h"
46#include "scip/scip_presol.h"
47#include "scip/scip_prob.h"
48#include "scip/scip_var.h"
49#include "scip/debug.h"
50
51
52#define PRESOL_NAME "boundshift"
53#define PRESOL_DESC "converts variables with domain [a,b] to variables with domain [0,b-a]"
54#define PRESOL_PRIORITY 7900000 /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */
55#define PRESOL_MAXROUNDS 0 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
56#define PRESOL_TIMING SCIP_PRESOLTIMING_FAST /* timing of the presolver (fast, medium, or exhaustive) */
57
58#define MAXABSBOUND 1000.0 /**< maximum absolute variable bounds for aggregation */
59
60/*
61 * Default parameter settings
62 */
63
64#define DEFAULT_MAXSHIFT SCIP_LONGINT_MAX /**< absolute value of maximum shift */
65#define DEFAULT_FLIPPING TRUE /**< is flipping allowed? */
66#define DEFAULT_INTEGER TRUE /**< are only integer ranges shifted */
67
68/*
69 * Data structures
70 */
71
72/** presolver data */
73struct SCIP_PresolData
74{
75 SCIP_Longint maxshift; /**< absolute value of maximum shift */
76 SCIP_Bool flipping; /**< is flipping allowed? */
77 SCIP_Bool integer; /**< shift only integer values? */
78};
79
80
81/*
82 * Local methods
83 */
84
85/*
86 * Callback methods of presolver
87 */
88
89/** copy method for constraint handler plugins (called when SCIP copies plugins) */
90static
91SCIP_DECL_PRESOLCOPY(presolCopyBoundshift)
92{ /*lint --e{715}*/
93 assert(scip != NULL);
94 assert(presol != NULL);
95
97
98 /* call inclusion method of presolver */
100
101 return SCIP_OKAY;
102}
103
104
105/** destructor of presolver to free user data (called when SCIP is exiting) */
106/**! [SnippetPresolFreeBoundshift] */
107static
108SCIP_DECL_PRESOLFREE(presolFreeBoundshift)
109{ /*lint --e{715}*/
110 SCIP_PRESOLDATA* presoldata;
111
112 /* free presolver data */
113 presoldata = SCIPpresolGetData(presol);
114 assert(presoldata != NULL);
115
116 SCIPfreeBlockMemory(scip, &presoldata);
117 SCIPpresolSetData(presol, NULL);
118
119 return SCIP_OKAY;
120}
121/**! [SnippetPresolFreeBoundshift] */
122
123
124/** presolving execution method */
125static
126SCIP_DECL_PRESOLEXEC(presolExecBoundshift)
127{ /*lint --e{715}*/
128 SCIP_PRESOLDATA* presoldata;
129 SCIP_VAR** scipvars;
130 SCIP_VAR** vars;
131 int nbinvars;
132 int nvars;
133 int v;
134
135 assert(scip != NULL);
136 assert(presol != NULL);
137 assert(result != NULL);
138
140
142
143 if( SCIPdoNotAggr(scip) )
144 return SCIP_OKAY;
145
146 /* get presolver data */
147 presoldata = SCIPpresolGetData(presol);
148 assert(presoldata != NULL);
149
150 /* get the problem variables */
151 scipvars = SCIPgetVars(scip);
152 nbinvars = SCIPgetNBinVars(scip);
153 nvars = SCIPgetNVars(scip) - nbinvars;
154
155 if( nvars == 0 )
156 return SCIP_OKAY;
157
159
160 /* copy the integer/continuous variables into an own array, since adding new variables affects the left-most slots in
161 * the array and thereby interferes with our search loop
162 */
163 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &scipvars[nbinvars], nvars) );
164
165 /* scan the integer, implicit, and continuous variables for possible conversion */
166 for( v = nvars - 1; v >= 0; --v )
167 {
168 SCIP_VAR* var = vars[v];
169 SCIP_Real lb;
170 SCIP_Real ub;
171
173
174 /* do not shift non-active (fixed or (multi-)aggregated) variables */
175 if( !SCIPvarIsActive(var) )
176 continue;
177
178 /* get current variable's bounds */
181
182 /* it can happen that the variable bounds of integer variables have not been propagated yet or contain
183 * some small noise; this will result in an aggregation that might trigger assertions when updating bounds of
184 * aggregated variables (see #1817)
185 */
187 {
190
191 lb = SCIPadjustedVarLb(scip, var, lb);
192 ub = SCIPadjustedVarUb(scip, var, ub);
193 }
194
195 assert( SCIPisLE(scip, lb, ub) );
196 if( SCIPisEQ(scip, lb, ub) )
197 continue;
198 if( presoldata->integer && !SCIPisIntegral(scip, ub - lb) )
199 continue;
200
201 /* check if bounds are shiftable */
202 if( !SCIPisEQ(scip, lb, 0.0) && /* lower bound != 0.0 */
203 SCIPisLT(scip, ub, SCIPinfinity(scip)) && /* upper bound != infinity */
204 SCIPisGT(scip, lb, -SCIPinfinity(scip)) && /* lower bound != -infinity */
205 SCIPisLT(scip, ub - lb, (SCIP_Real) presoldata->maxshift) && /* less than max shifting */
206 SCIPisLE(scip, REALABS(lb), MAXABSBOUND) && /* ensures a small constant in aggregation */
207 SCIPisLE(scip, REALABS(ub), MAXABSBOUND) ) /* ensures a small constant in aggregation */
208 {
209 SCIP_VAR* newvar;
210 char newvarname[SCIP_MAXSTRLEN];
211 SCIP_Bool infeasible;
212 SCIP_Bool redundant;
213 SCIP_Bool aggregated;
214
215 SCIPdebugMsg(scip, "convert range <%s>[%g,%g] to [%g,%g]\n", SCIPvarGetName(var), lb, ub, 0.0, (ub - lb) );
216
217 /* create new variable */
218 (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_shift", SCIPvarGetName(var));
219 SCIP_CALL( SCIPcreateVarImpl(scip, &newvar, newvarname, 0.0, (ub - lb), 0.0, SCIPvarGetType(var), SCIPvarGetImplType(var),
221 SCIP_CALL( SCIPaddVar(scip, newvar) );
222
223#ifdef WITH_DEBUG_SOLUTION
224 if( SCIPdebugIsMainscip(scip) )
225 {
226 /* calculate and store debug solution value of shift variable */
227 SCIP_Real val;
228
230 SCIPdebugMsg(scip, "debug solution value: <%s> = %g", SCIPvarGetName(var), val);
231
232 if( presoldata->flipping )
233 {
234 if( REALABS(ub) < REALABS(lb) )
235 val = ub - val;
236 else
237 val = val - lb;
238 }
239 else
240 {
241 val = val - lb;
242 }
243 SCIPdebugMsgPrint(scip, " -> <%s> = %g\n", SCIPvarGetName(newvar), val);
244
245 SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, val) );
246 }
247#endif
248
249 /* aggregate old variable with new variable */
250 if( presoldata->flipping )
251 {
252 if( REALABS(ub) < REALABS(lb) )
253 {
254 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, 1.0, 1.0, ub, &infeasible, &redundant, &aggregated) );
255 }
256 else
257 {
258 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, 1.0, -1.0, lb, &infeasible, &redundant, &aggregated) );
259 }
260 }
261 else
262 {
263 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, 1.0, -1.0, lb, &infeasible, &redundant, &aggregated) );
264 }
265
266 if( infeasible )
268 else
269 {
270 assert(redundant);
271 assert(aggregated);
272 SCIPdebugMsg(scip, "var <%s> with bounds [%f,%f] has obj %f\n",
273 SCIPvarGetName(newvar), SCIPvarGetLbGlobal(newvar), SCIPvarGetUbGlobal(newvar), SCIPvarGetObj(newvar));
274
275 /* take care of statistics */
276 (*naggrvars)++;
278 }
279
280 /* release variable */
281 SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
282 }
283 }
284
285 /* free temporary memory */
287
288 return SCIP_OKAY;
289}
290
291
292/*
293 * presolver specific interface methods
294 */
295
296/** creates the boundshift presolver and includes it in SCIP */
298 SCIP* scip /**< SCIP data structure */
299 )
300{
301 SCIP_PRESOLDATA* presoldata;
302 SCIP_PRESOL* presolptr;
303
304 /* create boundshift presolver data */
305 SCIP_CALL( SCIPallocBlockMemory(scip, &presoldata) );
306
307 /* include presolver */
309 presolExecBoundshift,
310 presoldata) );
311
312 assert(presolptr != NULL);
313
314 SCIP_CALL( SCIPsetPresolCopy(scip, presolptr, presolCopyBoundshift) );
315 SCIP_CALL( SCIPsetPresolFree(scip, presolptr, presolFreeBoundshift) );
316
317 /* add probing presolver parameters */
319 "presolving/boundshift/maxshift",
320 "absolute value of maximum shift",
321 &presoldata->maxshift, TRUE, DEFAULT_MAXSHIFT, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
322
324 "presolving/boundshift/flipping",
325 "is flipping allowed (multiplying with -1)?",
326 &presoldata->flipping, TRUE, DEFAULT_FLIPPING, NULL, NULL) );
327
329 "presolving/boundshift/integer",
330 "shift only integer ranges?",
331 &presoldata->integer, TRUE, DEFAULT_INTEGER, NULL, NULL) );
332
333 return SCIP_OKAY;
334}
methods for debugging
#define SCIPdebugGetSolVal(scip, var, val)
Definition debug.h:313
#define SCIPdebugAddSolVal(scip, var, val)
Definition debug.h:312
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_Longint
Definition def.h:150
#define SCIP_Bool
Definition def.h:100
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define REALABS(x)
Definition def.h:191
#define SCIP_LONGINT_MAX
Definition def.h:151
#define SCIP_CALL(x)
Definition def.h:364
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition scip_prob.c:1907
int SCIPgetNVars(SCIP *scip)
Definition scip_prob.c:2246
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition scip_prob.c:2201
int SCIPgetNBinVars(SCIP *scip)
Definition scip_prob.c:2293
#define SCIPdebugMsgPrint
#define SCIPdebugMsg
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_param.c:111
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_param.c:57
SCIP_RETCODE SCIPincludePresolBoundshift(SCIP *scip)
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition scip_mem.h:132
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
SCIP_RETCODE SCIPsetPresolFree(SCIP *scip, SCIP_PRESOL *presol,)
void SCIPpresolSetData(SCIP_PRESOL *presol, SCIP_PRESOLDATA *presoldata)
Definition presol.c:538
SCIP_PRESOLDATA * SCIPpresolGetData(SCIP_PRESOL *presol)
Definition presol.c:528
SCIP_RETCODE SCIPsetPresolCopy(SCIP *scip, SCIP_PRESOL *presol,)
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)
const char * SCIPpresolGetName(SCIP_PRESOL *presol)
Definition presol.c:625
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition var.c:23546
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:23674
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition scip_var.c:10909
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition var.c:23530
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_var.c:10550
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23932
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23485
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24174
SCIP_RETCODE SCIPcreateVarImpl(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_IMPLINTTYPE impltype, 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_var.c:225
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1887
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition scip_var.c:5634
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition scip_var.c:5570
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:23522
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition var.c:23556
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
Definition var.c:23495
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
return SCIP_OKAY
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
static SCIP_VAR ** vars
memory allocation routines
#define PRESOL_NAME
#define DEFAULT_FLIPPING
#define DEFAULT_INTEGER
#define PRESOL_PRIORITY
#define DEFAULT_MAXSHIFT
#define MAXABSBOUND
#define PRESOL_MAXROUNDS
#define PRESOL_TIMING
#define PRESOL_DESC
presolver that converts integer variables with domain [a,b] to integer variables with domain [0,...
public methods for message output
public data structures and miscellaneous methods
public methods for presolvers
public methods for problem variables
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for presolving plugins
public methods for global and local (sub)problems
public methods for SCIP variables
#define SCIP_DECL_PRESOLCOPY(x)
Definition type_presol.h:60
struct SCIP_PresolData SCIP_PRESOLDATA
Definition type_presol.h:51
#define SCIP_DECL_PRESOLFREE(x)
Definition type_presol.h:68
struct SCIP_Presol SCIP_PRESOL
Definition type_presol.h:50
#define SCIP_DECL_PRESOLEXEC(x)
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_CUTOFF
Definition type_result.h:48
@ SCIP_DIDNOTFIND
Definition type_result.h:44
@ SCIP_SUCCESS
Definition type_result.h:58
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_VARTYPE_BINARY
Definition type_var.h:64