SCIP-SDP  2.1.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-2016 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-2016 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 
48 /* turn off lint warnings for whole file: */
49 /*lint --e{788,818}*/
50 
55 #define PROP_NAME "sdpredcost"
56 #define PROP_DESC "sdp reduced cost strengthening propagator"
57 #define PROP_TIMING (SCIP_PROPTIMING_DURINGLPLOOP | SCIP_PROPTIMING_AFTERLPLOOP)
58 #define PROP_PRIORITY +1000000
59 #define PROP_FREQ 1
60 #define PROP_DELAY FALSE
61 #define DEFAULT_SDPRCBIN TRUE
62 #define DEFAULT_SDPRCINTCONT TRUE
67 struct SCIP_PropData
68 {
69  /* these could also be freshly allocated for each node, but allocating them only once saves time */
70  SCIP_Real* lbvarvals;
71  SCIP_Real* ubvarvals;
72  int nvars;
73  SCIP_Bool forbins;
74  SCIP_Bool forintconts;
75 };
76 
83 static
85  SCIP* scip,
86  SCIP_VAR* var,
87  SCIP_Real primallbval,
88  SCIP_Real primalubval,
89  SCIP_Real cutoffbound,
90  SCIP_Real relaxval,
91  SCIP_RESULT* result
92  )
93 {
94  assert( scip != NULL );
95  assert( var != NULL );
96  assert( result != NULL );
97 
98  /* skip binary variable if it is locally fixed */
99  if (SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5)
100  {
101  *result = SCIP_DIDNOTRUN;
102  return SCIP_OKAY;
103  }
104 
105  /* check if variable can be fixed to zero */
106  if ( SCIPisGT(scip, primallbval, cutoffbound - relaxval) )
107  {
108  SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) );
109  SCIPdebugMessage("Variable %s fixed to zero by reduced cost fixing ! \n", SCIPvarGetName(var));
110  *result = SCIP_REDUCEDDOM;
111 
112  /* 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 */
113  if ( SCIPisGT(scip, primalubval, cutoffbound - relaxval) )
114  {
115  *result = SCIP_CUTOFF;
116  }
117 
118  return SCIP_OKAY;
119  }
120 
121  /* check if variable can be fixed to one */
122  if ( SCIPisGT(scip, primalubval, cutoffbound - relaxval) )
123  {
124  SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) );
125  SCIPdebugMessage("Variable %s fixed to one by reduced cost fixing ! \n", SCIPvarGetName(var));
126  *result = SCIP_REDUCEDDOM;
127  return SCIP_OKAY;
128  }
129 
130  *result = SCIP_DIDNOTFIND;
131  return SCIP_OKAY;
132 }
133 
145 static
147  SCIP* scip,
148  SCIP_VAR* var,
149  SCIP_Real primallbval,
150  SCIP_Real primalubval,
151  SCIP_Real cutoffbound,
152  SCIP_Real relaxval,
153  SCIP_RESULT* result
154  )
155 {
156  SCIP_Real lb;
157  SCIP_Real ub;
158 
159  assert( scip != NULL );
160  assert( var != NULL );
161  assert( result != NULL );
162 
163  *result = SCIP_DIDNOTFIND;
164 
165  /* 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 */
166  ub = SCIPisGT(scip, primallbval, 0.0) ? SCIPvarGetLbLocal(var) + (cutoffbound - relaxval) / primallbval : SCIPinfinity(scip);
167  lb = SCIPisGT(scip, primalubval, 0.0) ? SCIPvarGetUbLocal(var) - (cutoffbound - relaxval) / primalubval : -SCIPinfinity(scip);
168 
169  /* if either bound is infinite, we set it to the corresponding SCIP value */
170  if ( SCIPisInfinity(scip, ub) )
171  ub = SCIPinfinity(scip);
172  else if ( SCIPisInfinity(scip, -ub) )
173  ub = -SCIPinfinity(scip);
174  if ( SCIPisInfinity(scip, lb) )
175  lb = SCIPinfinity(scip);
176  else if ( SCIPisInfinity(scip, -lb) )
177  lb = -SCIPinfinity(scip);
178 
179 
180  /* if after propagation the upper bound is less than the lower bound, the current node is infeasible */
181  if ( SCIPisLT(scip, ub, lb) || SCIPisLT(scip, ub, SCIPvarGetLbLocal(var)) || SCIPisLT(scip, SCIPvarGetUbLocal(var), lb) )
182  {
183  SCIPdebugMessage("Infeasibility of current node detected by prop_sdpredcost! Updated bounds for variable %s: lb = %f > %f = ub !\n",
184  SCIPvarGetName(var), SCIPisGT(scip, lb, SCIPvarGetLbLocal(var))? lb : SCIPvarGetLbLocal(var),
185  SCIPisLT(scip, ub, SCIPvarGetLbLocal(var)) ? ub : SCIPvarGetUbLocal(var) );
186  *result = SCIP_CUTOFF;
187  return SCIP_OKAY;
188  }
189 
190  /* if the new upper bound is an enhancement, update it */
191  if ( SCIPisLT(scip, ub, SCIPvarGetUbLocal(var)) )
192  {
193  SCIPdebugMessage("Changing upper bound of variable %s from %f to %f because of prop_sdpredcost \n",
194  SCIPvarGetName(var), SCIPvarGetUbLocal(var), ub);
195  SCIP_CALL( SCIPchgVarUb(scip, var, ub) );
196  *result = SCIP_REDUCEDDOM;
197  }
198 
199  /* if the new lower bound is an enhancement, update it */
200  if ( SCIPisGT(scip, lb, SCIPvarGetLbLocal(var)) )
201  {
202  SCIPdebugMessage("Changing lower bound of variable %s from %f to %f because of prop_sdpredcost \n",
203  SCIPvarGetName(var), SCIPvarGetLbLocal(var), lb);
204  SCIP_CALL( SCIPchgVarLb(scip, var, lb) );
205  *result = SCIP_REDUCEDDOM;
206  }
207 
208  return SCIP_OKAY;
209 }
210 
212 static
213 SCIP_DECL_PROPEXEC(propExecSdpredcost)
214 {/*lint --e{715}*/
215  int v;
216  int nvars;
217  SCIP_VAR** vars;
218  SCIP_RELAX* relax;
219  SCIP_RESULT varresult;
220  SCIP_Real cutoffbound;
221  SCIP_Real relaxval;
222  SCIP_Bool sdpsolved;
223  SCIP_PROPDATA* propdata;
224  int length;
225 
226  SCIPdebugMessage("Calling propExecSdpredcost \n");
227 
228  assert( scip != NULL );
229  assert( prop != NULL );
230  assert( result != NULL );
231 
232  if ( SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING )
233  {
234  /* we can't run before the relaxator is properly initialized */
235  *result = SCIP_DIDNOTRUN;
236  return SCIP_OKAY;
237  }
238 
239  relax = SCIPfindRelax(scip, "SDP"); /* get SDP relaxation handler */
240  assert( relax != NULL );
241 
242  /* we can only propagate for the last node for which the SDP was solved */
243  if ( SCIPrelaxSdpGetSdpNode(relax) != SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) )
244  {
245  SCIPdebugMessage("Stopped propExecRedcost because current SDP-relaxation doesn't belong to the node the propagator was called for!\n");
246  *result = SCIP_DIDNOTRUN;
247  return SCIP_OKAY;
248  }
249 
250  /* we can only propagate if the SDP in the last node was solved in its original formulation */
251  if ( ! SCIPrelaxSdpSolvedOrig(relax) )
252  {
253  SCIPdebugMessage("Stopped propExecRedcost because current SDP-relaxation was solved using a penalty formulation!\n");
254  *result = SCIP_DIDNOTRUN;
255  return SCIP_OKAY;
256  }
257 
258  SCIP_CALL( SCIPrelaxSdpRelaxVal(relax, &sdpsolved, &relaxval) );
259  if ( ! sdpsolved )
260  {
261  SCIPdebugMessage("Stopped propExecRedcost because SDP-relaxation wasn't properly solved!\n");
262  *result = SCIP_DIDNOTRUN;
263  return SCIP_OKAY;
264  }
265 
266  propdata = SCIPpropGetData(prop);
267  assert( propdata != NULL );
268 
269  *result = SCIP_DIDNOTFIND;
270 
271  nvars = SCIPgetNVars(scip);
272  vars = SCIPgetVars(scip);
273 
274  cutoffbound = SCIPgetCutoffbound(scip);
275 
276  length = nvars;
277 
278  SCIP_CALL( SCIPrelaxSdpGetPrimalBoundVars(relax, propdata->lbvarvals, propdata->ubvarvals, &length) );
279 
280  assert( length == nvars ); /* we should get exactly one value for lower and upper bound-variable per variable in scip */
281 
282  for (v = 0; v < nvars; v++)
283  {
284  if ( SCIPvarIsBinary(vars[v]) && propdata->forbins )
285  {
286  SCIP_CALL( sdpRedcostFixingBinary(scip, vars[v], propdata->lbvarvals[v], propdata->ubvarvals[v], cutoffbound, relaxval, &varresult) );
287 
288  if ( varresult == SCIP_REDUCEDDOM )
289  *result = SCIP_REDUCEDDOM;
290  }
291  else if ( (! SCIPvarIsBinary(vars[v])) && propdata->forintconts )
292  {
293  SCIP_CALL( sdpRedcostFixingIntCont(scip, vars[v], propdata->lbvarvals[v], propdata->ubvarvals[v], cutoffbound, relaxval, &varresult) );
294 
295  if ( varresult == SCIP_REDUCEDDOM )
296  *result = SCIP_REDUCEDDOM;
297  }
298  }
299 
300  return SCIP_OKAY;
301 }
302 
304 static
305 SCIP_DECL_PROPFREE(propFreeSdpredcost)
306 {
307  SCIP_PROPDATA* propdata;
308 
309  propdata = SCIPpropGetData(prop);
310  assert( propdata != NULL );
311 
312  if ( propdata->nvars > 0 )
313  {
314  SCIPfreeBlockMemoryArrayNull(scip, &(propdata->lbvarvals), propdata->nvars);
315  SCIPfreeBlockMemoryArrayNull(scip, &(propdata->ubvarvals), propdata->nvars);
316  }
317 
318  SCIPfreeMemory(scip, &propdata);
319 
320  SCIPpropSetData(prop, NULL);
321 
322  return SCIP_OKAY;
323 }
324 
326 static
327 SCIP_DECL_PROPINITSOL(propInitsolSdpredcost)
328 {
329  SCIP_PROPDATA* propdata;
330  int nvars;
331 
332  propdata = SCIPpropGetData(prop);
333  assert(propdata != NULL);
334  nvars = SCIPgetNVars(scip);
335 
336  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->lbvarvals), nvars) );
337  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->ubvarvals), nvars) );
338  propdata->nvars = nvars;
339 
340  return SCIP_OKAY;
341 }
342 
344 static
345 SCIP_DECL_PROPCOPY(propCopySdpredcost)
346 {
347  assert( scip != NULL );
348  assert( prop != NULL );
349  assert( strcmp(SCIPpropGetName(prop), PROP_NAME) == 0 );
350 
351  /* call inclusion method of constraint handler */
352  SCIP_CALL( SCIPincludePropSdpredcost(scip) );
353 
354  return SCIP_OKAY;
355 }
356 
359  SCIP* scip
360  )
361 {
362  SCIP_PROPDATA* propdata = NULL;
363  SCIP_PROP* prop;
364 
365  /* create propagator data */
366  SCIP_CALL( SCIPallocMemory(scip, &propdata) );
367  propdata->nvars = 0;
368 
369  /* include propagator */
370  SCIP_CALL( SCIPincludePropBasic(scip, &prop, PROP_NAME, PROP_DESC, PROP_PRIORITY, PROP_FREQ, PROP_DELAY, PROP_TIMING,
371  propExecSdpredcost, propdata) );
372  assert( prop != NULL );
373 
374  /* set optional callbacks via setter functions */
375  SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopySdpredcost) );
376  SCIP_CALL( SCIPsetPropInitsol(scip, prop, propInitsolSdpredcost) );
377  SCIP_CALL( SCIPsetPropFree(scip, prop, propFreeSdpredcost) );
378 
379  /* add additional parameters */
380  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/sdpredcost/forbins", "Should SDP reduced cost fixing be executed for binary variables?",
381  &(propdata->forbins), TRUE, DEFAULT_SDPRCBIN, NULL, NULL) );
382  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/sdpredcost/forintconts", "Should SDP reduced cost fixing be executed for integer and continuous variables?",
383  &(propdata->forintconts), TRUE, DEFAULT_SDPRCINTCONT, NULL, NULL) );
384 
385  return SCIP_OKAY;
386 }
#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:1774
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:1829
SCIP_Bool SCIPrelaxSdpSolvedOrig(SCIP_RELAX *relax)
Definition: relax_sdp.c:1840
SCIP_RETCODE SCIPrelaxSdpGetPrimalBoundVars(SCIP_RELAX *relax, SCIP_Real *lbvars, SCIP_Real *ubvars, int *arraylength)
Definition: relax_sdp.c:1749
reduced cost / dual 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