SCIP-SDP  3.2.0
prop_sdpobbt.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 programs based on SCIP. */
5 /* */
6 /* Copyright (C) 2011-2013 Discrete Optimization, TU Darmstadt */
7 /* EDOM, FAU Erlangen-Nürnberg */
8 /* 2014-2020 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-2020 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 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
39 
40 /*#define SCIP_DEBUG*/
41 /*#define SCIP_MORE_DEBUG*/
42 
43 #include <assert.h>
44 #include <string.h>
45 
46 #include "prop_sdpobbt.h"
47 #include "relax_sdp.h"
48 
49 /* turn off lint warnings for whole file: */
50 /*lint --e{788,818}*/
51 
52 /* fundamental propagator properties */
53 #define PROP_NAME "sdp-obbt"
54 #define PROP_DESC "optimization-based bound tightening for SDPs"
55 #define PROP_PRIORITY -1100000
56 #define PROP_FREQ -1
57 #define PROP_DELAY FALSE
58 #define PROP_TIMING SCIP_PROPTIMING_AFTERLPLOOP
60 #define DEFAULT_PROPBIN FALSE
61 #define DEFAULT_PROPCONT TRUE
63 /* TODO: maybe make this a parameter and/or have different values for integral and continuous variables */
64 #define TOLERANCE_FACTOR 2000
66 /* TODO: fix memory error */
67 
68 
69 /*
70  * Data structures
71  */
72 
74 struct SCIP_PropData
75 {
76  SCIP_Bool propbin;
77  SCIP_Bool propcont;
78  SCIP_Bool delayed;
79  long long int lastnode;
80  SCIP_Real lastcufoffbound;
81  SCIP_Real sdpsolvergaptol;
82  SCIP_Bool propenabled;
83 };
84 
85 
86 /*
87  * Local methods
88  */
89 
90 /* the current bugfix branch (3.2.1) does not have SCIPsolveProbingRelax() -> do nothing */
91 #if ( (SCIP_VERSION > 321 || SCIP_SUBVERSION > 0) )
92 static
93 SCIP_RETCODE addObjCutoff(
94  SCIP* scip
95  )
96 {
97  SCIP_ROW* row;
98  SCIP_VAR** vars;
99  char rowname[SCIP_MAXSTRLEN];
100  int nvars;
101  int v;
102 
103  assert( scip != NULL );
104  assert( SCIPinProbing(scip) );
105 
106  SCIPdebugMsg(scip, "create objective cutoff and add it to the LP-constraints\n");
107 
108  nvars = SCIPgetNVars(scip);
109  vars = SCIPgetVars(scip);
110 
111  /* create objective cutoff row; set local flag to FALSE since primal cutoff is globally valid */
112  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "obbtsdp_objcutoff");
113  SCIP_CALL( SCIPcreateEmptyRowUnspec(scip, &row, rowname, -SCIPinfinity(scip), SCIPgetCutoffbound(scip), FALSE, FALSE, FALSE) );
114  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
115 
116  for( v = 0; v < nvars; v++ )
117  {
118  SCIP_CALL( SCIPaddVarToRow(scip, row, vars[v], SCIPvarGetObj(vars[v])) );
119  }
120  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
121 
122  /* add row to the LP-constraints */
123  SCIP_CALL( SCIPaddRowProbing(scip, row) );
124 
125  SCIP_CALL( SCIPreleaseRow(scip, &row) );
126 
127  return SCIP_OKAY;
128 }
129 #endif
130 
131 /*
132  * Callback methods of propagator
133  */
134 
135 
137 static
138 SCIP_DECL_PROPCOPY(propCopySdpObbt)
139 { /*lint --e{715}*/
140  assert( scip != NULL );
141  assert( prop != NULL );
142  assert( strcmp(SCIPpropGetName(prop), PROP_NAME) == 0 );
143 
144  /* call inclusion method of constraint handler */
145  SCIP_CALL( SCIPincludePropSdpObbt(scip) );
146 
147  return SCIP_OKAY;
148 }
149 
150 
152 static
153 SCIP_DECL_PROPFREE(propFreeSdpObbt)
154 { /*lint --e{715}*/
155  SCIP_PROPDATA* propdata;
156 
157  propdata = SCIPpropGetData(prop);
158  assert(propdata != NULL);
159 
160  SCIPfreeMemory(scip, &propdata);
161  SCIPpropSetData(prop, NULL);
162 
163  return SCIP_OKAY;
164 }
165 
167 static
168 SCIP_DECL_PROPEXIT(propExitSdpObbt)
169 { /*lint --e{715}*/
170  SCIP_PROPDATA* propdata;
171 
172  assert( prop != NULL );
173 
174  propdata = SCIPpropGetData(prop);
175 
176  propdata->lastnode = -1; /* we reset this to be able to run again if a new problem is read */
177 
178  return SCIP_OKAY;
179 }
180 
182 static
183 SCIP_DECL_PROPINITSOL(propInitsolSdpObbt)
184 { /*lint --e{715}*/
185  SCIP_PROPDATA* propdata;
186 
187  assert( prop != NULL );
188 
189  propdata = SCIPpropGetData(prop);
190 
191  if ( SCIPfindRelax(scip, "SDP") == NULL )
192  propdata->propenabled = FALSE;
193  else
194  {
195  propdata->propenabled = TRUE;
196  SCIP_CALL( SCIPgetRealParam(scip, "relaxing/SDP/sdpsolvergaptol", &(propdata->sdpsolvergaptol)) );
197  }
198 
199  return SCIP_OKAY;
200 }
201 
203 static
204 SCIP_DECL_PROPEXEC(propExecSdpObbt)
205 { /*lint --e{715}*/
206  /* the current bugfix branch (3.2.1) does not have SCIPsolveProbingRelax() -> do nothing */
207 #if ( (SCIP_VERSION > 321 || SCIP_SUBVERSION > 0) )
208  int nvars;
209  SCIP_VAR** vars;
210  int v;
211  SCIP_PROPDATA* propdata;
212  SCIP_Real relaxval;
213  SCIP_Bool cutoff;
214  SCIP_Bool oldobjlimitparam;
215  SCIP_Real probingval;
216  SCIP_Bool success;
217  SCIP_RELAX* relaxsdp;
218  /* newbounds and newboundinds save the bound tightenings that should be inserted after probing ends, newboundinds saves the bounds the entries of newbounds
219  * belong to, for this the variables are sorted 1 to nvars (and entry i means vars[i-1]), with negative entry for the lower bound and positive for the upper */
220  SCIP_Real* newbounds;
221  int* newboundinds;
222  int nnewbounds;
223  int i;
224 
225  assert( scip != NULL );
226  assert( prop != NULL );
227  assert( result != NULL );
228 
229  propdata = SCIPpropGetData(prop);
230 
231  assert( propdata != NULL );
232 
233  *result = SCIP_DIDNOTRUN;
234 
235  if ( ! propdata->propenabled )
236  return SCIP_OKAY;
237 
238  SCIPdebugMsg(scip, "Executing propExecSdpObbt! \n");
239 
240  /* do not run in: presolving, repropagation, probing mode, subscips, if no objective propagation is allowed */
241 #if ( SCIP_VERSION >= 700 || (SCIP_VERSION >= 602 && SCIP_SUBVERSION > 0) )
242  if ( SCIPgetStage(scip) != SCIP_STAGE_SOLVING || SCIPinRepropagation(scip) || SCIPinProbing(scip) || !SCIPallowWeakDualReds(scip) || (SCIPgetSubscipDepth(scip) > 0) )
243 #else
244  if ( SCIPgetStage(scip) != SCIP_STAGE_SOLVING || SCIPinRepropagation(scip) || SCIPinProbing(scip) || !SCIPallowObjProp(scip) || (SCIPgetSubscipDepth(scip) > 0) )
245 #endif
246  {
247  SCIPdebugMsg(scip, "Aborting propExecSdpObbt because we are in presolving, repropagation, probing mode, a subscip or no objective "
248  "propagation is allowed!\n");
249  return SCIP_OKAY;
250  }
251 
252  /* delay if cutoffbound is infinite or no relaxation solution exists */
253  if ( SCIPisInfinity(scip, SCIPgetCutoffbound(scip)) || (! SCIPisRelaxSolValid(scip)) )
254  {
255  /* if we already delayed in the last call, abort to prevent an infinite loop */
256  if ( propdata->delayed )
257  {
258  SCIPdebugMsg(scip, "Aborting propExecSdpObbt since still cutoffbound is infinite or no relaxation solution exists\n");
259  return SCIP_OKAY;
260  }
261  *result = SCIP_DELAYED;
262  propdata->delayed = TRUE;
263  SCIPdebugMsg(scip, "Delaying propExecSdpObbt since cutoffbound is infinite or no relaxation solution exists\n");
264  return SCIP_OKAY;
265  }
266 
267  /* delay if best solution was found by trivial heuristic (since in this case the cutoffbound will generally not be good enough) or objective propagation onky */
268  if ( (SCIPgetBestSol(scip) == NULL) || ((SCIPsolGetHeur(SCIPgetBestSol(scip)) != NULL) && (strcmp(SCIPheurGetName(SCIPsolGetHeur(SCIPgetBestSol(scip))), "trivial") == 0)) )
269  {
270  /* if we already delayed in the last call, abort to prevent an infinite loop */
271  if ( propdata->delayed )
272  {
273  SCIPdebugMsg(scip, "Aborting propExecSdpObbt since still best solution was found by trivial heuristic or simple objective propagation, which will not be good enough\n");
274  return SCIP_OKAY;
275  }
276  *result = SCIP_DELAYED;
277  propdata->delayed = TRUE;
278  SCIPdebugMsg(scip, "Delaying propExecSdpObbt since best solution was found by trivial heuristic or simple objective propagation, which will not be good enough\n");
279  return SCIP_OKAY;
280  }
281 
282  if ( (SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) == propdata->lastnode) && (SCIPisEQ(scip, SCIPgetCutoffbound(scip), propdata->lastcufoffbound)) )
283  {
284  SCIPdebugMsg(scip, "Not running again for node %lld with cutoffbound &f!\n", propdata->lastnode, propdata->lastcufoffbound);
285  return SCIP_OKAY;
286  }
287  else
288  {
289  propdata->lastnode = SCIPnodeGetNumber(SCIPgetCurrentNode(scip));
290  propdata->lastcufoffbound = SCIPgetCutoffbound(scip);
291  }
292 
293  propdata->delayed = FALSE;
294 
295  vars = SCIPgetVars(scip);
296  nvars = SCIPgetNVars(scip);
297 
298  /* start probing */
299  SCIP_CALL( SCIPstartProbing(scip) );
300  SCIPdebugMsg(scip, "start probing\n");
301 
302  SCIP_CALL( addObjCutoff(scip) );
303 
304  /* make sure that we don't use the objective cutoff for the changed objective */
305  SCIP_CALL( SCIPgetBoolParam(scip, "relaxing/SDP/objlimit", &oldobjlimitparam) );
306  SCIP_CALL( SCIPsetBoolParam(scip, "relaxing/SDP/objlimit", FALSE) );
307 
308  /* allocate memory to save bounds */
309  SCIP_CALL( SCIPallocBufferArray(scip, &newbounds, 2*nvars) );/*lint !e647*/
310  SCIP_CALL( SCIPallocBufferArray(scip, &newboundinds, 2*nvars) );/*lint !e647*/
311 
312  *result = SCIP_DIDNOTFIND;
313 
314  /* set objective coefficients to zero */
315  for( v = 0; v < nvars; ++v )
316  {
317  SCIP_CALL( SCIPchgVarObjProbing(scip, vars[v], 0.0) );
318  }
319 
320  nnewbounds = 0;
321 
322  for (v = 0; v < nvars; v++)
323  {
324  /* do not propagate binary or continous variables if the corresponding flag is set to false */
325  if ( (( ! propdata->propbin ) && SCIPvarIsBinary(vars[v])) || (( ! propdata->propcont ) && ( ! SCIPvarIsIntegral(vars[v]))) )
326  {
327 #ifdef SCIP_MORE_DEBUG
328  if ( SCIPvarIsBinary(vars[v]) )
329  {
330  SCIPdebugMsg(scip, "Skipping binary variable %s\n", SCIPvarGetName(vars[v]));
331  }
332  else
333  {
334  SCIPdebugMsg(scip, "Skipping continuous variable %s\n", SCIPvarGetName(vars[v]));
335  }
336 #endif
337  continue;
338  }
339 
340  /* get the value of this variable for the current relaxation */
341  relaxval = SCIPgetRelaxSolVal(scip, vars[v]);
342 
343  /* only try obbt for the lower bound if it is not tight for the current relaxation's solution */
344  if ( SCIPisFeasGT(scip, relaxval, SCIPvarGetLbLocal(vars[v])) )
345  {
346  /* set the objective to minimize y_v */
347  SCIP_CALL( SCIPchgVarObjProbing(scip, vars[v], 1.0) );
348 
349  /* solve the probing problem */
350  SCIP_CALL( SCIPsolveProbingRelax(scip, &cutoff) );
351 
352  /* as cutoff doesn't work for relax sdp, we have to check ourselves, if we didn't manage to solve successfully, we abort (as this will
353  * probably not get better for the other variables as we only change the objective */
354  relaxsdp = SCIPfindRelax(scip, "SDP");
355 
356  if (! SCIPrelaxSdpSolvedProbing(relaxsdp))
357  {
358  SCIPdebugMsg(scip, "Aborting sdp-obbt, as we were unable to solve a probing sdp!\n");
359  if ( *result != SCIP_REDUCEDDOM )
360  *result = SCIP_DIDNOTRUN;
361  break;
362  }
363 
364  /* if the problem is infeasible, return with cutoff */
365  if ( ! SCIPrelaxSdpIsFeasible(relaxsdp) )
366  {
367  SCIPdebugMsg(scip, "Probing sdp infeasible, so there can't be a better solution for this problem!\n");
368  *result = SCIP_CUTOFF;
369  break;
370  }
371 
372  /* only check objective value if problem was bounded */
373  if ( ! SCIPrelaxSdpIsUnbounded(relaxsdp) )
374  {
375  /* check if we managed to tighten the bound */
376  success = FALSE; /* this will be ignored, we check solvedProbing instead */
377  SCIP_CALL( SCIPrelaxSdpRelaxVal(relaxsdp, &success, &probingval) );
378 
379  /* only update if we improved the bound by at least gaptol, everything else might be inexactness of the solver */
380  if ( SCIPisGT(scip, probingval - TOLERANCE_FACTOR * propdata->sdpsolvergaptol, SCIPvarGetLbLocal(vars[v])) )
381  {
382  /* update bound */
383  SCIPdebugMsg(scip, "Obbt-Sdp tightened lower bound of variable %s from %f to %f !\n",
384  SCIPvarGetName(vars[v]), SCIPvarGetLbLocal(vars[v]), probingval - propdata->sdpsolvergaptol);
385 
386  newbounds[nnewbounds] = probingval;
387  newboundinds[nnewbounds] = -1 * (v+1);
388  nnewbounds++;
389  *result = SCIP_REDUCEDDOM;
390  }
391  #ifdef SCIP_MORE_DEBUG
392  else
393  {
394  SCIPdebugMsg(scip, "Obbt-Sdp found lower bound of %f for variable %s, worse than old bound %f !\n",
395  probingval, SCIPvarGetName(vars[v]), SCIPvarGetLbLocal(vars[v]));
396  }
397  #endif
398  }
399 #ifdef SCIP_MORE_DEBUG
400  else
401  {
402  SCIPdebugMsg(scip, "Obbt-Sdp problem unbounded for variable %s!\n", SCIPvarGetName(vars[v]));
403  }
404 #endif
405  }
406 #ifdef SCIP_MORE_DEBUG
407  else
408  {
409  SCIPdebugMsg(scip, "Skipping obbt for lower bound %f of variable %s, as current relaxation's solution is tight.\n",
410  SCIPvarGetLbLocal(vars[v]), SCIPvarGetName(vars[v]));
411  }
412 #endif
413 
414  /* only try obbt for the upper bound if it is not tight for the current relaxation's solution */
415  if ( SCIPisFeasLT(scip, relaxval, SCIPvarGetUbLocal(vars[v])) )
416  {
417  /* set the objective to maximize y_v (minimize -y_v) */
418  SCIP_CALL( SCIPchgVarObjProbing(scip, vars[v], -1.0) );
419 
420  /* solve the probing problem */
421  SCIP_CALL( SCIPsolveProbingRelax(scip, &cutoff) );
422 
423  /* as cutoff doesn't work for relax sdp, we have to check ourselves, if we didn't manage to solve successfully, we abort (as this will
424  * probably not get better for the other variables as we only change the objective */
425  relaxsdp = SCIPfindRelax(scip, "SDP");
426 
427  if (! SCIPrelaxSdpSolvedProbing(relaxsdp))
428  {
429  SCIPdebugMsg(scip, "Aborting sdp-obbt, as we were unable to solve a probing sdp!\n");
430  if ( *result != SCIP_REDUCEDDOM )
431  *result = SCIP_DIDNOTRUN;
432  goto ENDPROBING;
433  }
434 
435  /* if the problem is infeasible, return with cutoff */
436  if ( ! SCIPrelaxSdpIsFeasible(relaxsdp) )
437  {
438  SCIPdebugMsg(scip, "Probing sdp infeasible, so there can't be a better solution for this problem!\n");
439  *result = SCIP_CUTOFF;
440  nnewbounds = 0;
441  goto ENDPROBING;
442  }
443 
444  /* only check objective value if problem was bounded */
445  if ( ! SCIPrelaxSdpIsUnbounded(relaxsdp) )
446  {
447  /* check if we managed to tighten the bound */
448  success = FALSE; /* this will be ignored, we check solvedProbing instead */
449  SCIP_CALL( SCIPrelaxSdpRelaxVal(relaxsdp, &success, &probingval) );
450 
451  /* only update if we improved the bound by at least gaptol, everything else might be inexactness of the solver */
452  if ( SCIPisLT(scip, -probingval + TOLERANCE_FACTOR * propdata->sdpsolvergaptol, SCIPvarGetUbLocal(vars[v])) )
453  {
454  SCIPdebugMsg(scip, "Obbt-Sdp tightened upper bound of variable %s from %f to %f !\n",
455  SCIPvarGetName(vars[v]), SCIPvarGetUbLocal(vars[v]), -probingval + propdata->sdpsolvergaptol);
456 
457  newbounds[nnewbounds] = -probingval;
458  newboundinds[nnewbounds] = v + 1;
459  nnewbounds++;
460  }
461  #ifdef SCIP_MORE_DEBUG
462  else
463  {
464  SCIPdebugMsg(scip, "Obbt-Sdp found upper bound of %f for variable %s, worse than old bound %f !\n",
465  -probingval, SCIPvarGetName(vars[v]), SCIPvarGetUbLocal(vars[v]));
466  }
467  #endif
468  }
469 #ifdef SCIP_MORE_DEBUG
470  else
471  {
472  SCIPdebugMsg(scip, "Obbt-Sdp problem unbounded for variable %s!\n", SCIPvarGetName(vars[v]));
473  }
474 #endif
475  }
476 #ifdef SCIP_MORE_DEBUG
477  else
478  {
479  SCIPdebugMsg(scip, "Skipping obbt for upper bound %f of variable %s, as current relaxation's solution is tight.\n",
480  SCIPvarGetUbLocal(vars[v]), SCIPvarGetName(vars[v]));
481  }
482 #endif
483 
484  /* reset the objective coefficient to zero for the next variable */
485  SCIP_CALL( SCIPchgVarObjProbing(scip, vars[v], 0.0) );
486  }
487 
488  ENDPROBING:
489  SCIP_CALL( SCIPendProbing(scip) );
490  SCIPdebugMsg(scip, "end probing\n");
491  SCIP_CALL( SCIPsetBoolParam(scip, "relaxing/SDP/objlimit", oldobjlimitparam) );
492 
493  for (i = 0; i < nnewbounds; i++)
494  {
495  if ( newboundinds[i] < 0)
496  {
497  SCIP_CALL( SCIPchgVarLb(scip, vars[-1 * newboundinds[i] - 1], newbounds[i]) ); /*lint !e679*/
498  *result = SCIP_REDUCEDDOM;
499  }
500  else
501  {
502  /* Check if the (rounded) new upper bound is smaller than the updated lower bound, in that case return cutoff.
503  * Note that this can only happen for integer variables, since by construction the lower bound computed by obbt
504  * has to be smaller than the upper bound, but it can happen through rounding. */
505  if ( SCIPvarIsBinary(vars[newboundinds[i] - 1]) && SCIPisLT(scip, SCIPfeasFloor(scip, newbounds[i]),
506  SCIPvarGetLbLocal(vars[newboundinds[i] - 1]) ))
507  {
508  SCIPdebugMsg(scip, "Probing sdp founded conflicting bounds for integer variable %s -> cutoff!\n",
509  SCIPvarGetName(vars[newboundinds[i] - 1]));
510  *result = SCIP_CUTOFF;
511  break;
512  }
513  SCIP_CALL( SCIPchgVarUb(scip, vars[newboundinds[i] - 1], newbounds[i]) );
514  *result = SCIP_REDUCEDDOM;
515  }
516  }
517 
518  SCIPfreeBufferArray(scip, &newboundinds);
519  SCIPfreeBufferArray(scip, &newbounds);
520 
521  return SCIP_OKAY;
522 
523 #else
524  *result = SCIP_DIDNOTRUN;
525 
526  return SCIP_OKAY;
527 #endif
528 }
529 
530 
531 
532 /*
533  * propagator specific interface methods
534  */
535 
538  SCIP* scip
539  )
540 {
541  SCIP_PROPDATA* propdata;
542  SCIP_PROP* prop;
543 
544  /* create SdpObbt propagator data */
545  propdata = NULL;
546  SCIP_CALL( SCIPallocMemory(scip, &propdata) );
547  propdata->lastnode = -1;
548  propdata->propenabled = TRUE;
549 
550  /* include propagator */
551  /* use SCIPincludePropBasic() plus setter functions if you want to set callbacks one-by-one and your code should
552  * compile independent of new callbacks being added in future SCIP versions
553  */
554  SCIP_CALL( SCIPincludePropBasic(scip, &prop, PROP_NAME, PROP_DESC, PROP_PRIORITY, PROP_FREQ, PROP_DELAY, PROP_TIMING,
555  propExecSdpObbt, propdata) );
556 
557  assert(prop != NULL);
558 
559  /* set optional callbacks via setter functions */
560  SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopySdpObbt) );
561  SCIP_CALL( SCIPsetPropFree(scip, prop, propFreeSdpObbt) );
562  SCIP_CALL( SCIPsetPropExit(scip, prop, propExitSdpObbt) );
563  SCIP_CALL( SCIPsetPropInitsol(scip, prop, propInitsolSdpObbt) );
564 
565  /* add SdpObbt propagator parameters */
566  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/propbin",
567  "Should optimization-based bound tightening be performed for binary variables?",
568  &propdata->propbin, TRUE, DEFAULT_PROPBIN, NULL, NULL) );
569 
570  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/propcont",
571  "Should optimization-based bound tightening be performed for continuous variables?",
572  &propdata->propcont, TRUE, DEFAULT_PROPCONT, NULL, NULL) );
573 
574  return SCIP_OKAY;
575 }
#define PROP_TIMING
Definition: prop_sdpobbt.c:58
SCIP_RETCODE SCIPincludePropSdpObbt(SCIP *scip)
Definition: prop_sdpobbt.c:537
#define PROP_NAME
Definition: prop_sdpobbt.c:53
static SCIP_DECL_PROPEXIT(propExitSdpObbt)
Definition: prop_sdpobbt.c:168
static SCIP_DECL_PROPEXEC(propExecSdpObbt)
Definition: prop_sdpobbt.c:204
static SCIP_DECL_PROPCOPY(propCopySdpObbt)
Definition: prop_sdpobbt.c:138
SDP-relaxator.
#define PROP_DESC
Definition: prop_sdpobbt.c:54
optimization-based bound tightening propagator for semidefinite programs
SCIP_RETCODE SCIPrelaxSdpRelaxVal(SCIP_RELAX *relax, SCIP_Bool *success, SCIP_Real *objval)
Definition: relax_sdp.c:4997
static SCIP_DECL_PROPINITSOL(propInitsolSdpObbt)
Definition: prop_sdpobbt.c:183
#define PROP_FREQ
Definition: prop_sdpobbt.c:56
static SCIP_DECL_PROPFREE(propFreeSdpObbt)
Definition: prop_sdpobbt.c:153
#define TOLERANCE_FACTOR
Definition: prop_sdpobbt.c:64
SCIP_Bool SCIPrelaxSdpSolvedProbing(SCIP_RELAX *relax)
Definition: relax_sdp.c:5080
#define DEFAULT_PROPBIN
Definition: prop_sdpobbt.c:60
#define DEFAULT_PROPCONT
Definition: prop_sdpobbt.c:61
#define PROP_PRIORITY
Definition: prop_sdpobbt.c:55
#define PROP_DELAY
Definition: prop_sdpobbt.c:57
SCIP_Bool SCIPrelaxSdpIsFeasible(SCIP_RELAX *relax)
Definition: relax_sdp.c:5097
SCIP_Bool SCIPrelaxSdpIsUnbounded(SCIP_RELAX *relax)
Definition: relax_sdp.c:5108