Scippy

SCIP

Solving Constraint Integer Programs

prop_dualfix.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-2025 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 prop_dualfix.c
26 * @ingroup DEFPLUGINS_PROP
27 * @brief fixing roundable variables to best bound
28 * @author Tobias Achterberg
29 * @author Stefan Heinz
30 */
31
32/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33
34#include "scip/prop_dualfix.h"
35#include "scip/pub_message.h"
36#include "scip/pub_prop.h"
37#include "scip/pub_var.h"
38#include "scip/scip_general.h"
39#include "scip/scip_message.h"
40#include "scip/scip_numerics.h"
41#include "scip/scip_prob.h"
42#include "scip/scip_probing.h"
43#include "scip/scip_prop.h"
44#include "scip/scip_tree.h"
45#include "scip/scip_var.h"
46#include <string.h>
47
48#define PROP_NAME "dualfix"
49#define PROP_DESC "roundable variables dual fixing"
50#define PROP_TIMING SCIP_PROPTIMING_BEFORELP
51#define PROP_PRIORITY +8000000 /**< propagation priority */
52#define PROP_FREQ 0 /**< propagation frequency */
53#define PROP_DELAY FALSE /**< should propagation method be delayed, if other propagators found
54 * reductions? */
55#define PROP_PRESOL_PRIORITY +8000000 /**< priority of the propagator (>= 0: before, < 0: after constraint handlers) */
56#define PROP_PRESOL_MAXROUNDS -1 /**< maximal number of propving rounds the propver participates in (-1: no limit) */
57#define PROP_PRESOLTIMING SCIP_PRESOLTIMING_FAST /* timing of the presolving method (fast, medium, or exhaustive) */
58
59
60/**@name Local methods
61 *
62 * @{
63 */
64
65/** perform dual presolving */
66static
68 SCIP* scip, /**< SCIP data structure */
69 int* nfixedvars, /**< pointer to store number of fixed variables */
70 SCIP_Bool* unbounded, /**< pointer to store if an unboundness was detected */
71 SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */
72 )
73{
74 SCIP_VAR** vars;
75 int nvars;
76 int v;
77
78 assert(nfixedvars != NULL);
79 assert(unbounded != NULL);
80 assert(cutoff != NULL);
81
82 /* get active problem variables */
83 vars = SCIPgetVars(scip);
84 nvars = SCIPgetNVars(scip);
85
86 /* look for fixable variables
87 * loop backwards, since a variable fixing can change the current and the subsequent slots in the vars array
88 */
89 for( v = nvars - 1; v >= 0; --v )
90 {
91 SCIP_VAR* var;
93 SCIP_Real obj;
94 SCIP_Bool infeasible;
95 SCIP_Bool fixed;
96
97 var = vars[v];
98 assert(var != NULL);
99
100 /* don't perform dual presolving operations on deleted variables */
101 if( SCIPvarIsDeleted(var) )
102 continue;
103
104 /* ignore already fixed variables */
106 continue;
107
108 obj = SCIPvarGetObj(var);
109
110 /* if the objective coefficient of the variable is 0 and it may be rounded both
111 * up and down, then fix it to the closest feasible value to 0 */
112 if( SCIPisZero(scip, obj) && SCIPvarMayRoundDown(var) && SCIPvarMayRoundUp(var) )
113 {
114 SCIP_Real roundbound;
115
117 if( SCIPisLT(scip, bound, 0.0) )
118 {
119 if( SCIPisLE(scip, 0.0, SCIPvarGetUbGlobal(var)) )
120 bound = 0.0;
121 else
122 {
123 /* try to take an integer value, only for polishing */
124 roundbound = SCIPfloor(scip, SCIPvarGetUbGlobal(var));
125
126 if( roundbound < bound )
128 else
129 bound = roundbound;
130 }
131 }
132 else
133 {
134 /* try to take an integer value, only for polishing */
135 roundbound = SCIPceil(scip, bound);
136
137 if( roundbound < SCIPvarGetUbGlobal(var) )
138 bound = roundbound;
139 }
140 SCIPdebugMsg(scip, "fixing variable <%s> with objective 0 to %g\n", SCIPvarGetName(var), bound);
141 }
142 else
143 {
144 /* if it is always possible to round variable in direction of objective value, fix it to its proper bound */
145 if( SCIPvarMayRoundDown(var) && !SCIPisNegative(scip, obj) )
146 {
148 if ( SCIPisInfinity(scip, -bound) )
149 {
150 /* variable can be fixed to -infinity */
152 {
153 /* Fixing variables to infinity is not allowed after presolving, since LP-solvers cannot handle this
154 * consistently. We thus have to ignore this (should better be handled in presolving). */
155 continue;
156 }
158 {
159 /* Variable is only contained in one constraint: we hope that the corresponding constraint handler is
160 * clever enough to set/aggregate the variable to something more useful than -infinity and do nothing
161 * here. */
162 continue;
163 }
164 }
165 SCIPdebugMsg(scip, "fixing variable <%s> with objective %g and %d uplocks to lower bound %g\n",
167 }
168 else if( SCIPvarMayRoundUp(var) && !SCIPisPositive(scip, obj) )
169 {
171 if ( SCIPisInfinity(scip, bound) )
172 {
173 /* variable can be fixed to infinity */
175 {
176 /* Fixing variables to infinity is not allowed after presolving, since LP-solvers cannot handle this
177 * consistently. We thus have to ignore this (should better be handled in presolving). */
178 continue;
179 }
181 {
182 /* Variable is only contained in one constraint: we hope that the corresponding constraint handler is
183 * clever enough to set/aggregate the variable to something more useful than +infinity and do nothing
184 * here */
185 continue;
186 }
187 }
188 SCIPdebugMsg(scip, "fixing variable <%s> with objective %g and %d downlocks to upper bound %g\n",
190 }
191 else
192 continue;
193 }
194
196 {
197 if( !SCIPisZero(scip, obj) )
198 {
199 SCIPdebugMsg(scip, " -> unbounded fixing\n");
201 "problem infeasible or unbounded: variable <%s> with objective %.15g can be made infinitely %s\n",
202 SCIPvarGetName(var), SCIPvarGetObj(var), bound < 0.0 ? "small" : "large");
203
204 *unbounded = TRUE;
205 }
206
207 SCIPdebugMsg(scip, "changed my mind; not applying fixing of variable <%s> to infinity\n", SCIPvarGetName(var));
208 return SCIP_OKAY;
209 }
210
211 /* apply the fixing */
212 SCIPdebugMsg(scip, "apply fixing of variable %s to %g\n", SCIPvarGetName(var), bound);
213 SCIP_CALL( SCIPfixVar(scip, var, bound, &infeasible, &fixed) );
214
215 if( infeasible )
216 {
217 SCIPdebugMsg(scip, " -> infeasible fixing\n");
218 *cutoff = TRUE;
219 return SCIP_OKAY;
220 }
221
222 /* SCIPfixVar only changes bounds if not already feaseq.
223 * Only if in presolve and not probing, variables will always be fixed.
224 */
225 assert(fixed || (SCIPisFeasEQ(scip, bound, SCIPvarGetLbLocal(var))
227 (*nfixedvars)++;
228 }
229
230 return SCIP_OKAY;
231}
232
233/**@} */
234
235/**@name Callback methods
236 *
237 * @{
238 */
239
240/** copy method for constraint handler plugins (called when SCIP copies plugins) */
241static
242SCIP_DECL_PROPCOPY(propCopyDualfix)
243{ /*lint --e{715}*/
244 assert(scip != NULL);
245 assert(prop != NULL);
246 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
247
248 /* call inclusion method of propagator */
250
251 return SCIP_OKAY;
252}
253
254/** presolving method of propagator */
255static
256SCIP_DECL_PROPPRESOL(propPresolDualfix)
257{ /*lint --e{715}*/
258 SCIP_Bool cutoff;
259 SCIP_Bool unbounded;
260 int oldnfixedvars;
261
262 assert(prop != NULL);
263 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
264 assert(result != NULL);
265
266 *result = SCIP_DIDNOTRUN;
267
269 return SCIP_OKAY;
270
271 cutoff = FALSE;
272 unbounded = FALSE;
273 oldnfixedvars = *nfixedvars;
274
275 SCIP_CALL( performDualfix(scip, nfixedvars, &unbounded, &cutoff) );
276
277 /* evaluate propagation result */
278 if( cutoff )
279 *result = SCIP_CUTOFF;
280 else if( unbounded )
281 *result = SCIP_UNBOUNDED;
282 else if( *nfixedvars > oldnfixedvars )
283 *result = SCIP_SUCCESS;
284 else
285 *result = SCIP_DIDNOTFIND;
286
287 return SCIP_OKAY;
288}
289
290/** execution method of propagator */
291static
292SCIP_DECL_PROPEXEC(propExecDualfix)
293{ /*lint --e{715}*/
294 int nfixedvars;
295 SCIP_Bool cutoff;
296 SCIP_Bool unbounded;
297
298 assert(prop != NULL);
299 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
300 assert(result != NULL);
301
302 *result = SCIP_DIDNOTRUN;
303
304 /** @warning Don't run in probing or in repropagation since this can lead to wrong conclusion
305 *
306 * do not run if propagation w.r.t. current objective is not allowed
307 */
309 return SCIP_OKAY;
310
311 cutoff = FALSE;
312 unbounded = FALSE;
313 nfixedvars = 0;
314
315 SCIP_CALL( performDualfix(scip, &nfixedvars, &unbounded, &cutoff) );
316
317 /* evaluate propagation result */
318 if( cutoff )
319 *result = SCIP_CUTOFF;
320 else if( unbounded )
321 *result = SCIP_UNBOUNDED;
322 else if( nfixedvars > 0 )
323 *result = SCIP_REDUCEDDOM;
324 else
325 *result = SCIP_DIDNOTFIND;
326
327 return SCIP_OKAY;
328}
329
330
331/**@} */
332
333
334/** creates the dual fixing propagator and includes it in SCIP */
336 SCIP* scip /**< SCIP data structure */
337 )
338{
339 SCIP_PROP* prop;
340
341 /* include propagator */
343 assert(prop != NULL);
344
345 SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopyDualfix) );
347
348 return SCIP_OKAY;
349}
static long bound
#define NULL
Definition: def.h:248
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define REALABS(x)
Definition: def.h:182
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:444
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:2246
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:2201
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:225
#define SCIPdebugMsg
Definition: scip_message.h:78
SCIP_RETCODE SCIPincludePropDualfix(SCIP *scip)
Definition: prop_dualfix.c:335
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:98
SCIP_RETCODE SCIPsetPropPresol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPPRESOL((*proppresol)), int presolpriority, int presolmaxrounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip_prop.c:283
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:951
SCIP_RETCODE SCIPsetPropCopy(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPCOPY((*propcopy)))
Definition: scip_prop.c:155
SCIP_RETCODE SCIPincludePropBasic(SCIP *scip, SCIP_PROP **propptr, const char *name, const char *desc, int priority, int freq, SCIP_Bool delay, SCIP_PROPTIMING timingmask, SCIP_DECL_PROPEXEC((*propexec)), SCIP_PROPDATA *propdata)
Definition: scip_prop.c:118
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip_tree.c:146
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:23534
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:4484
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4386
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:24268
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:4473
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:23900
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:24234
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:24120
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:10318
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4328
SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
Definition: scip_var.c:10984
#define PROP_PRESOL_MAXROUNDS
Definition: prop_dualfix.c:56
#define PROP_PRESOLTIMING
Definition: prop_dualfix.c:57
#define PROP_DESC
Definition: prop_dualfix.c:49
static SCIP_DECL_PROPPRESOL(propPresolDualfix)
Definition: prop_dualfix.c:256
#define PROP_NAME
Definition: prop_dualfix.c:48
static SCIP_DECL_PROPCOPY(propCopyDualfix)
Definition: prop_dualfix.c:242
#define PROP_DELAY
Definition: prop_dualfix.c:53
#define PROP_TIMING
Definition: prop_dualfix.c:50
static SCIP_RETCODE performDualfix(SCIP *scip, int *nfixedvars, SCIP_Bool *unbounded, SCIP_Bool *cutoff)
Definition: prop_dualfix.c:67
static SCIP_DECL_PROPEXEC(propExecDualfix)
Definition: prop_dualfix.c:292
#define PROP_FREQ
Definition: prop_dualfix.c:52
#define PROP_PRIORITY
Definition: prop_dualfix.c:51
#define PROP_PRESOL_PRIORITY
Definition: prop_dualfix.c:55
fixing roundable variables to best bound
public methods for message output
public methods for propagators
public methods for problem variables
general public methods
public methods for message handling
public methods for numerical tolerances
public methods for global and local (sub)problems
public methods for the probing mode
public methods for propagator plugins
public methods for the branch-and-bound tree
public methods for SCIP variables
@ SCIP_VERBLEVEL_NORMAL
Definition: type_message.h:60
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_CUTOFF
Definition: type_result.h:48
@ SCIP_REDUCEDDOM
Definition: type_result.h:51
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_UNBOUNDED
Definition: type_result.h:47
@ SCIP_SUCCESS
Definition: type_result.h:58
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_PRESOLVING
Definition: type_set.h:49
@ SCIP_LOCKTYPE_MODEL
Definition: type_var.h:141