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-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 prop_dualfix.c
17  * @brief fixing roundable variables to best bound
18  * @author Tobias Achterberg
19  * @author Stefan Heinz
20  */
21 
22 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
23 
24 #include <assert.h>
25 #include <string.h>
26 
27 #include "scip/prop_dualfix.h"
28 
29 
30 #define PROP_NAME "dualfix"
31 #define PROP_DESC "roundable variables dual fixing"
32 #define PROP_TIMING SCIP_PROPTIMING_BEFORELP
33 #define PROP_PRIORITY +8000000 /**< propagation priority */
34 #define PROP_FREQ 0 /**< propagation frequency */
35 #define PROP_DELAY FALSE /**< should propagation method be delayed, if other propagators found
36  * reductions? */
37 #define PROP_PRESOL_PRIORITY +8000000 /**< priority of the propagator (>= 0: before, < 0: after constraint handlers) */
38 #define PROP_PRESOL_MAXROUNDS -1 /**< maximal number of propving rounds the propver participates in (-1: no limit) */
39 #define PROP_PRESOL_DELAY FALSE /**< should propver be delayed, if other propvers found reductions? */
40 
41 
42 /**@name Local methods
43  *
44  * @{
45  */
46 
47 /** perform dual presolving */
48 static
50  SCIP* scip, /**< SCIP data structure */
51  int* nfixedvars, /**< pointer to store number of fixed variables */
52  SCIP_Bool* unbounded, /**< pointer to store if an unboundness was detected */
53  SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */
54  )
55 {
56  SCIP_VAR** vars;
57  int nvars;
58  int v;
59 
60  /* get active problem variables */
61  vars = SCIPgetVars(scip);
62  nvars = SCIPgetNVars(scip);
63 
64  /* look for fixable variables
65  * loop backwards, since a variable fixing can change the current and the subsequent slots in the vars array
66  */
67  for( v = nvars - 1; v >= 0; --v )
68  {
69  SCIP_VAR* var;
70  SCIP_Real bound;
71  SCIP_Real obj;
72  SCIP_Bool infeasible;
73  SCIP_Bool fixed;
74 
75  var = vars[v];
76  assert(var != NULL);
77 
78  /* don't perform dual presolving operations on deleted variables */
79  if( SCIPvarIsDeleted(var) )
80  continue;
81 
82  /* ignore already fixed variables (use feasibility tolerance since this is used in SCIPfixVar() */
83  if( SCIPisFeasEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) )
84  continue;
85 
86  obj = SCIPvarGetObj(var);
87 
88  /* if the objective coefficient of the variable is 0 and it may be rounded both
89  * up and down, then fix it to the closest feasible value to 0 */
90  if( SCIPisZero(scip, obj) && SCIPvarMayRoundDown(var) && SCIPvarMayRoundUp(var) )
91  {
92  SCIP_Real roundbound;
93 
94  bound = SCIPvarGetLbGlobal(var);
95  if( SCIPisLT(scip, bound, 0.0) )
96  {
97  if( SCIPisLE(scip, 0.0, SCIPvarGetUbGlobal(var)) )
98  bound = 0.0;
99  else
100  {
101  /* try to take an integer value, only for polishing */
102  roundbound = SCIPfloor(scip, SCIPvarGetUbGlobal(var));
103 
104  if( roundbound < bound )
105  bound = SCIPvarGetUbGlobal(var);
106  else
107  bound = roundbound;
108  }
109  }
110  else
111  {
112  /* try to take an integer value, only for polishing */
113  roundbound = SCIPceil(scip, bound);
114 
115  if( roundbound < SCIPvarGetUbGlobal(var) )
116  bound = roundbound;
117  }
118  SCIPdebugMessage("fixing variable <%s> with objective 0 to %g\n", SCIPvarGetName(var), bound);
119  }
120  else
121  {
122  /* if it is always possible to round variable in direction of objective value, fix it to its proper bound */
123  if( SCIPvarMayRoundDown(var) && !SCIPisNegative(scip, obj) )
124  {
125  bound = SCIPvarGetLbGlobal(var);
126  if ( SCIPisZero(scip, obj) && SCIPisInfinity(scip, -bound) )
127  {
128  /* variable can be fixed to -infinity */
129  if ( SCIPgetStage(scip) > SCIP_STAGE_PRESOLVING )
130  {
131  /* Fixing variables to infinity is not allowed after presolving, since LP-solvers cannot handle this
132  * consistently. We thus have to ignore this (should better be handled in presolving). */
133  continue;
134  }
135  if ( SCIPvarGetNLocksUp(var) == 1 )
136  {
137  /* Variable is only contained in one constraint: we hope that the corresponding constraint handler is
138  * clever enough to set/aggregate the variable to something more useful than -infinity and do nothing
139  * here. */
140  continue;
141  }
142  }
143  SCIPdebugMessage("fixing variable <%s> with objective %g and %d uplocks to lower bound %g\n",
144  SCIPvarGetName(var), SCIPvarGetObj(var), SCIPvarGetNLocksUp(var), bound);
145  }
146  else if( SCIPvarMayRoundUp(var) && !SCIPisPositive(scip, obj) )
147  {
148  bound = SCIPvarGetUbGlobal(var);
149  if ( SCIPisZero(scip, obj) && SCIPisInfinity(scip, bound) )
150  {
151  /* variable can be fixed to infinity */
152  if ( SCIPgetStage(scip) > SCIP_STAGE_PRESOLVING )
153  {
154  /* Fixing variables to infinity is not allowed after presolving, since LP-solvers cannot handle this
155  * consistently. We thus have to ignore this (should better be handled in presolving). */
156  continue;
157  }
158  if ( SCIPvarGetNLocksDown(var) == 1 )
159  {
160  /* Variable is only contained in one constraint: we hope that the corresponding constraint handler is
161  * clever enough to set/aggregate the variable to something more useful than +infinity and do nothing
162  * here */
163  continue;
164  }
165  }
166  SCIPdebugMessage("fixing variable <%s> with objective %g and %d downlocks to upper bound %g\n",
167  SCIPvarGetName(var), SCIPvarGetObj(var), SCIPvarGetNLocksDown(var), bound);
168  }
169  else
170  continue;
171  }
172 
173  if( SCIPisInfinity(scip, REALABS(bound)) && !SCIPisZero(scip, obj) )
174  {
175  SCIPdebugMessage(" -> unbounded fixing\n");
177  "problem infeasible or unbounded: variable <%s> with objective %.15g can be made infinitely %s\n",
178  SCIPvarGetName(var), SCIPvarGetObj(var), bound < 0.0 ? "small" : "large");
179  *unbounded = TRUE;
180  return SCIP_OKAY;
181  }
182 
183  /* apply the fixing */
184  SCIPdebugMessage("apply fixing of variable %s to %g\n", SCIPvarGetName(var), bound);
185  SCIP_CALL( SCIPfixVar(scip, var, bound, &infeasible, &fixed) );
186 
187  if( infeasible )
188  {
189  SCIPdebugMessage(" -> infeasible fixing\n");
190  *cutoff = TRUE;
191  return SCIP_OKAY;
192  }
193 
194  assert(fixed || (SCIPgetStage(scip) == SCIP_STAGE_SOLVING && SCIPisFeasEQ(scip, bound, SCIPvarGetLbLocal(var))
195  && SCIPisFeasEQ(scip, bound, SCIPvarGetUbLocal(var))));
196  (*nfixedvars)++;
197  }
198 
199  return SCIP_OKAY;
200 }
201 
202 /**@} */
203 
204 /**@name Callback methods
205  *
206  * @{
207  */
208 
209 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
210 static
211 SCIP_DECL_PROPCOPY(propCopyDualfix)
212 { /*lint --e{715}*/
213  assert(scip != NULL);
214  assert(prop != NULL);
215  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
216 
217  /* call inclusion method of propagator */
219 
220  return SCIP_OKAY;
221 }
222 
223 /** presolving method of propagator */
224 static
225 SCIP_DECL_PROPPRESOL(propPresolDualfix)
226 { /*lint --e{715}*/
227  SCIP_Bool cutoff;
228  SCIP_Bool unbounded;
229  int oldnfixedvars;
230 
231  assert(prop != NULL);
232  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
233  assert(result != NULL);
234 
235  cutoff = FALSE;
236  unbounded = FALSE;
237  oldnfixedvars = *nfixedvars;
238 
239  SCIP_CALL( performDualfix(scip, nfixedvars, &unbounded, &cutoff) );
240 
241  /* evaluate propagation result */
242  if( cutoff )
243  *result = SCIP_CUTOFF;
244  else if( unbounded )
245  *result = SCIP_UNBOUNDED;
246  else if( *nfixedvars > oldnfixedvars )
247  *result = SCIP_SUCCESS;
248  else
249  *result = SCIP_DIDNOTFIND;
250 
251  return SCIP_OKAY;
252 }
253 
254 /** execution method of propagator */
255 static
256 SCIP_DECL_PROPEXEC(propExecDualfix)
257 { /*lint --e{715}*/
258  int nfixedvars;
259  SCIP_Bool cutoff;
260  SCIP_Bool unbounded;
261 
262  assert(prop != NULL);
263  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
264  assert(result != NULL);
265 
266  *result = SCIP_DIDNOTRUN;
267 
268  /** @warning Don't run in probing or in repropagation since this can lead to wrong conclusion */
269  if( SCIPinProbing(scip) || SCIPinRepropagation(scip) )
270  return SCIP_OKAY;
271 
272  cutoff = FALSE;
273  unbounded = FALSE;
274  nfixedvars = 0;
275 
276  SCIP_CALL( performDualfix(scip, &nfixedvars, &unbounded, &cutoff) );
277 
278  /* evaluate propagation result */
279  if( cutoff )
280  *result = SCIP_CUTOFF;
281  else if( unbounded )
282  *result = SCIP_UNBOUNDED;
283  else if( nfixedvars > 0 )
284  *result = SCIP_REDUCEDDOM;
285  else
286  *result = SCIP_DIDNOTFIND;
287 
288  return SCIP_OKAY;
289 }
290 
291 
292 /**@} */
293 
294 /**@name Interface methods
295  *
296  * @{
297  */
298 
299 /** creates the dual fixing propagator and includes it in SCIP */
301  SCIP* scip /**< SCIP data structure */
302  )
303 {
304  SCIP_PROPDATA* propdata;
305  SCIP_PROP* prop;
306 
307  /* create dualfix propagator data */
308  propdata = NULL;
309 
310  /* include propagator */
312  propExecDualfix, propdata) );
313  assert(prop != NULL);
314 
315  SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopyDualfix) );
318 
319  return SCIP_OKAY;
320 }
321 
322 /**@} */
323