SCIP-SDP  2.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
prop_sdpredcost.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of SCIPSDP - a solving framework for mixed-integer */
4 /* semidefinite programms based on SCIP. */
5 /* */
6 /* Copyright (C) 2011-2013 Discrete Optimization, TU Darmstadt */
7 /* EDOM, FAU Erlangen-Nürnberg */
8 /* 2014-2015 Discrete Optimization, TU Darmstadt */
9 /* */
10 /* */
11 /* This program is free software; you can redistribute it and/or */
12 /* modify it under the terms of the GNU Lesser General Public License */
13 /* as published by the Free Software Foundation; either version 3 */
14 /* of the License, or (at your option) any later version. */
15 /* */
16 /* This program is distributed in the hope that it will be useful, */
17 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
19 /* GNU Lesser General Public License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with this program; if not, write to the Free Software */
23 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
24 /* */
25 /* */
26 /* Based on SCIP - Solving Constraint Integer Programs */
27 /* Copyright (C) 2002-2015 Zuse Institute Berlin */
28 /* SCIP is distributed under the terms of the SCIP Academic Licence, */
29 /* see file COPYING in the SCIP distribution. */
30 /* */
31 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
32 
38 /*#define SCIP_DEBUG*/
39 
40 #include "prop_sdpredcost.h"
41 #include "scip/def.h" /* for SCIP_Real, _Bool, ... */
42 #include "relax_sdp.h" /* to get relaxation value */
43 #include "sdpi/sdpi.h" /* to get values of primal variables */
44 
45 #include <string.h>
46 #include <assert.h> /*lint !e451*/
47 
52 #define PROP_NAME "sdpredcost"
53 #define PROP_DESC "sdp reduced cost strengthening propagator"
54 #define PROP_TIMING (SCIP_PROPTIMING_DURINGLPLOOP | SCIP_PROPTIMING_AFTERLPLOOP)
55 #define PROP_PRIORITY +1000000
56 #define PROP_FREQ 1
57 #define PROP_DELAY FALSE
58 #define DEFAULT_SDPRCBIN TRUE
59 #define DEFAULT_SDPRCINTCONT TRUE
64 struct SCIP_PropData
65 {
66  /* these could also be freshly allocated for each node, but allocating them only once saves time */
67  SCIP_Real* lbvarvals;
68  SCIP_Real* ubvarvals;
69  int nvars;
70  SCIP_Bool forbins;
71  SCIP_Bool forintconts;
72 };
73 
80 static
82  SCIP* scip,
83  SCIP_VAR* var,
84  SCIP_Real primallbval,
85  SCIP_Real primalubval,
86  SCIP_Real cutoffbound,
87  SCIP_Real relaxval,
88  SCIP_RESULT* result
89  )
90 {
91  assert( scip != NULL );
92  assert( var != NULL );
93  assert( result != NULL );
94 
95  /* skip binary variable if it is locally fixed */
96  if (SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5)
97  {
98  *result = SCIP_DIDNOTRUN;
99  return SCIP_OKAY;
100  }
101 
102  /* check if variable can be fixed to zero */
103  if ( SCIPisGT(scip, primallbval, cutoffbound - relaxval) )
104  {
105  SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) );
106  SCIPdebugMessage("Variable %s fixed to zero by reduced cost fixing ! \n", SCIPvarGetName(var));
107  *result = SCIP_REDUCEDDOM;
108 
109  /* check if we would also have to fix the variable to one, in that case, we can cut the node off, as there can't be a new optimal solution */
110  if ( SCIPisGT(scip, primalubval, cutoffbound - relaxval) )
111  {
112  *result = SCIP_CUTOFF;
113  }
114 
115  return SCIP_OKAY;
116  }
117 
118  /* check if variable can be fixed to one */
119  if ( SCIPisGT(scip, primalubval, cutoffbound - relaxval) )
120  {
121  SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) );
122  SCIPdebugMessage("Variable %s fixed to one by reduced cost fixing ! \n", SCIPvarGetName(var));
123  *result = SCIP_REDUCEDDOM;
124  return SCIP_OKAY;
125  }
126 
127  *result = SCIP_DIDNOTFIND;
128  return SCIP_OKAY;
129 }
130 
142 static
144  SCIP* scip,
145  SCIP_VAR* var,
146  SCIP_Real primallbval,
147  SCIP_Real primalubval,
148  SCIP_Real cutoffbound,
149  SCIP_Real relaxval,
150  SCIP_RESULT* result
151  )
152 {
153  SCIP_Real lb;
154  SCIP_Real ub;
155 
156  assert( scip != NULL );
157  assert( var != NULL );
158  assert( result != NULL );
159 
160  *result = SCIP_DIDNOTFIND;
161 
162  /* compute the new lower and upper bound, if we divide by zero (checking > 0 is sufficient, as the variabls are non-negative), the bounds are infinity */
163  ub = SCIPisGT(scip, primallbval, 0.0) ? SCIPvarGetLbLocal(var) + (cutoffbound - relaxval) / primallbval : SCIPinfinity(scip);
164  lb = SCIPisGT(scip, primalubval, 0.0) ? SCIPvarGetUbLocal(var) - (cutoffbound - relaxval) / primalubval : -SCIPinfinity(scip);
165 
166  /* if either bound is infinite, we set it to the corresponding SCIP value */
167  if ( SCIPisInfinity(scip, ub) )
168  ub = SCIPinfinity(scip);
169  else if ( SCIPisInfinity(scip, -ub) )
170  ub = -SCIPinfinity(scip);
171  if ( SCIPisInfinity(scip, lb) )
172  lb = SCIPinfinity(scip);
173  else if ( SCIPisInfinity(scip, -lb) )
174  lb = -SCIPinfinity(scip);
175 
176 
177  /* if after propagation the upper bound is less than the lower bound, the current node is infeasible */
178  if ( SCIPisLT(scip, ub, lb) || SCIPisLT(scip, ub, SCIPvarGetLbLocal(var)) || SCIPisLT(scip, SCIPvarGetUbLocal(var), lb) )
179  {
180  SCIPdebugMessage("Infeasibility of current node detected by prop_sdpredcost! Updated bounds for variable %s: lb = %f > %f = ub !\n",
181  SCIPvarGetName(var), SCIPisGT(scip, lb, SCIPvarGetLbLocal(var))? lb : SCIPvarGetLbLocal(var),
182  SCIPisLT(scip, ub, SCIPvarGetLbLocal(var)) ? ub : SCIPvarGetUbLocal(var) );
183  *result = SCIP_CUTOFF;
184  return SCIP_OKAY;
185  }
186 
187  /* if the new upper bound is an enhancement, update it */
188  if ( SCIPisLT(scip, ub, SCIPvarGetUbLocal(var)) )
189  {
190  SCIPdebugMessage("Changing upper bound of variable %s from %f to %f because of prop_sdpredcost \n",
191  SCIPvarGetName(var), SCIPvarGetUbLocal(var), ub);
192  SCIP_CALL( SCIPchgVarUb(scip, var, ub) );
193  *result = SCIP_REDUCEDDOM;
194  }
195 
196  /* if the new lower bound is an enhancement, update it */
197  if ( SCIPisGT(scip, lb, SCIPvarGetLbLocal(var)) )
198  {
199  SCIPdebugMessage("Changing lower bound of variable %s from %f to %f because of prop_sdpredcost \n",
200  SCIPvarGetName(var), SCIPvarGetLbLocal(var), lb);
201  SCIP_CALL( SCIPchgVarLb(scip, var, lb) );
202  *result = SCIP_REDUCEDDOM;
203  }
204 
205  return SCIP_OKAY;
206 }
207 
209 static
210 SCIP_DECL_PROPEXEC(propExecSdpredcost)
211 {/*lint --e{715}*/
212  int v;
213  int nvars;
214  SCIP_VAR** vars;
215  SCIP_RELAX* relax;
216  SCIP_RESULT varresult;
217  SCIP_Real cutoffbound;
218  SCIP_Real relaxval;
219  SCIP_Bool sdpsolved;
220  SCIP_PROPDATA* propdata;
221  int length;
222 
223  SCIPdebugMessage("Calling propExecSdpredcost \n");
224 
225  assert( scip != NULL );
226  assert( prop != NULL );
227  assert( result != NULL );
228 
229  if ( SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING )
230  {
231  /* we can't run before the relaxator is properly initialized */
232  *result = SCIP_DIDNOTRUN;
233  return SCIP_OKAY;
234  }
235 
236  relax = SCIPfindRelax(scip, "SDP"); /* get SDP relaxation handler */
237  assert( relax != NULL );
238 
239  /* we can only propagate for the last node for which the SDP was solved */
240  if ( SCIPrelaxSdpGetSdpNode(relax) != SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) )
241  {
242  SCIPdebugMessage("Stopped propExecRedcost because current SDP-relaxation doesn't belong to the node the propagator was called for!\n");
243  *result = SCIP_DIDNOTRUN;
244  return SCIP_OKAY;
245  }
246 
247  /* we can only propagate if the SDP in the last node was solved in its original formulation */
248  if ( ! SCIPrelaxSdpSolvedOrig(relax) )
249  {
250  SCIPdebugMessage("Stopped propExecRedcost because current SDP-relaxation was solved using a penalty formulation!\n");
251  *result = SCIP_DIDNOTRUN;
252  return SCIP_OKAY;
253  }
254 
255  SCIP_CALL( SCIPrelaxSdpRelaxVal(relax, &sdpsolved, &relaxval) );
256  if ( ! sdpsolved )
257  {
258  SCIPdebugMessage("Stopped propExecRedcost because SDP-relaxation wasn't properly solved!\n");
259  *result = SCIP_DIDNOTRUN;
260  return SCIP_OKAY;
261  }
262 
263  propdata = SCIPpropGetData(prop);
264  assert( propdata != NULL );
265 
266  *result = SCIP_DIDNOTFIND;
267 
268  nvars = SCIPgetNVars(scip);
269  vars = SCIPgetVars(scip);
270 
271  cutoffbound = SCIPgetCutoffbound(scip);
272 
273  length = nvars;
274 
275  SCIP_CALL( SCIPrelaxSdpGetPrimalBoundVars(relax, propdata->lbvarvals, propdata->ubvarvals, &length) );
276 
277  assert( length == nvars ); /* we should get exactly one value for lower and upper bound-variable per variable in scip */
278 
279  for (v = 0; v < nvars; v++)
280  {
281  if ( SCIPvarIsBinary(vars[v]) && propdata->forbins )
282  {
283  SCIP_CALL( sdpRedcostFixingBinary(scip, vars[v], propdata->lbvarvals[v], propdata->ubvarvals[v], cutoffbound, relaxval, &varresult) );
284 
285  if ( varresult == SCIP_REDUCEDDOM )
286  *result = SCIP_REDUCEDDOM;
287  }
288  else if ( (! SCIPvarIsBinary(vars[v])) && propdata->forintconts )
289  {
290  SCIP_CALL( sdpRedcostFixingIntCont(scip, vars[v], propdata->lbvarvals[v], propdata->ubvarvals[v], cutoffbound, relaxval, &varresult) );
291 
292  if ( varresult == SCIP_REDUCEDDOM )
293  *result = SCIP_REDUCEDDOM;
294  }
295  }
296 
297  return SCIP_OKAY;
298 }
299 
301 static
302 SCIP_DECL_PROPFREE(propFreeSdpredcost)
303 {
304  SCIP_PROPDATA* propdata;
305 
306  propdata = SCIPpropGetData(prop);
307  assert( propdata != NULL );
308 
309  if ( propdata->nvars > 0 )
310  {
311  SCIPfreeBlockMemoryArrayNull(scip, &(propdata->lbvarvals), propdata->nvars);
312  SCIPfreeBlockMemoryArrayNull(scip, &(propdata->ubvarvals), propdata->nvars);
313  }
314 
315  SCIPfreeMemory(scip, &propdata);
316 
317  SCIPpropSetData(prop, NULL);
318 
319  return SCIP_OKAY;
320 }
321 
323 static
324 SCIP_DECL_PROPINITSOL(propInitsolSdpredcost)
325 {
326  SCIP_PROPDATA* propdata;
327  int nvars;
328 
329  propdata = SCIPpropGetData(prop);
330  assert(propdata != NULL);
331  nvars = SCIPgetNVars(scip);
332 
333  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->lbvarvals), nvars) );
334  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->ubvarvals), nvars) );
335  propdata->nvars = nvars;
336 
337  return SCIP_OKAY;
338 }
339 
341 static
342 SCIP_DECL_PROPCOPY(propCopySdpredcost)
343 {
344  assert( scip != NULL );
345  assert( prop != NULL );
346  assert( strcmp(SCIPpropGetName(prop), PROP_NAME) == 0 );
347 
348  /* call inclusion method of constraint handler */
349  SCIP_CALL( SCIPincludePropSdpredcost(scip) );
350 
351  return SCIP_OKAY;
352 }
353 
356  SCIP* scip
357  )
358 {
359  SCIP_PROPDATA* propdata = NULL;
360  SCIP_PROP* prop;
361 
362  /* create propagator data */
363  SCIP_CALL( SCIPallocMemory(scip, &propdata) );
364  propdata->nvars = 0;
365 
366  /* include propagator */
367  SCIP_CALL( SCIPincludePropBasic(scip, &prop, PROP_NAME, PROP_DESC, PROP_PRIORITY, PROP_FREQ, PROP_DELAY, PROP_TIMING,
368  propExecSdpredcost, propdata) );
369  assert( prop != NULL );
370 
371  /* set optional callbacks via setter functions */
372  SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopySdpredcost) );
373  SCIP_CALL( SCIPsetPropInitsol(scip, prop, propInitsolSdpredcost) );
374  SCIP_CALL( SCIPsetPropFree(scip, prop, propFreeSdpredcost) );
375 
376  /* add additional parameters */
377  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/sdpredcost/forbins", "should sdp reduced cost fixing be executed for binary variables?",
378  &(propdata->forbins), TRUE, DEFAULT_SDPRCBIN, NULL, NULL) );
379  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/sdpredcost/forintconts", "should sdp reduced cost fixing be executed for integer and continuous variables?",
380  &(propdata->forintconts), TRUE, DEFAULT_SDPRCINTCONT, NULL, NULL) );
381 
382  return SCIP_OKAY;
383 }
#define DEFAULT_SDPRCBIN
static SCIP_DECL_PROPFREE(propFreeSdpredcost)
static SCIP_DECL_PROPINITSOL(propInitsolSdpredcost)
#define PROP_DELAY
#define PROP_TIMING
#define PROP_FREQ
SDP relaxator.
SCIP_RETCODE SCIPrelaxSdpRelaxVal(SCIP_RELAX *relax, SCIP_Bool *success, SCIP_Real *objval)
Definition: relax_sdp.c:1050
General interface methods for SDP-preprocessing (mainly fixing variables and removing empty rows/cols...
static SCIP_DECL_PROPEXEC(propExecSdpredcost)
#define PROP_PRIORITY
static SCIP_DECL_PROPCOPY(propCopySdpredcost)
long int SCIPrelaxSdpGetSdpNode(SCIP_RELAX *relax)
Definition: relax_sdp.c:1103
SCIP_Bool SCIPrelaxSdpSolvedOrig(SCIP_RELAX *relax)
Definition: relax_sdp.c:1114
SCIP_RETCODE SCIPrelaxSdpGetPrimalBoundVars(SCIP_RELAX *relax, SCIP_Real *lbvars, SCIP_Real *ubvars, int *arraylength)
Definition: relax_sdp.c:1025
reduced cost fixing for SDPs
static SCIP_RETCODE sdpRedcostFixingIntCont(SCIP *scip, SCIP_VAR *var, SCIP_Real primallbval, SCIP_Real primalubval, SCIP_Real cutoffbound, SCIP_Real relaxval, SCIP_RESULT *result)
#define PROP_NAME
#define PROP_DESC
static SCIP_RETCODE sdpRedcostFixingBinary(SCIP *scip, SCIP_VAR *var, SCIP_Real primallbval, SCIP_Real primalubval, SCIP_Real cutoffbound, SCIP_Real relaxval, SCIP_RESULT *result)
SCIP_RETCODE SCIPincludePropSdpredcost(SCIP *scip)
#define DEFAULT_SDPRCINTCONT