53 #define PROP_NAME "sdp-obbt" 54 #define PROP_DESC "optimization-based bound tightening for SDPs" 55 #define PROP_PRIORITY -1100000 57 #define PROP_DELAY FALSE 58 #define PROP_TIMING SCIP_PROPTIMING_AFTERLPLOOP 60 #define DEFAULT_PROPBIN FALSE 61 #define DEFAULT_PROPCONT TRUE 64 #define TOLERANCE_FACTOR 2000 79 long long int lastnode;
80 SCIP_Real lastcufoffbound;
81 SCIP_Real sdpsolvergaptol;
82 SCIP_Bool propenabled;
91 #if ( (SCIP_VERSION > 321 || SCIP_SUBVERSION > 0) ) 93 SCIP_RETCODE addObjCutoff(
99 char rowname[SCIP_MAXSTRLEN];
103 assert( scip != NULL );
104 assert( SCIPinProbing(scip) );
106 SCIPdebugMsg(scip,
"create objective cutoff and add it to the LP-constraints\n");
108 nvars = SCIPgetNVars(scip);
109 vars = SCIPgetVars(scip);
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) );
116 for( v = 0; v < nvars; v++ )
118 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[v], SCIPvarGetObj(vars[v])) );
120 SCIP_CALL( SCIPflushRowExtensions(scip, row) );
123 SCIP_CALL( SCIPaddRowProbing(scip, row) );
125 SCIP_CALL( SCIPreleaseRow(scip, &row) );
140 assert(
scip != NULL );
141 assert( prop != NULL );
142 assert( strcmp(SCIPpropGetName(prop),
PROP_NAME) == 0 );
155 SCIP_PROPDATA* propdata;
157 propdata = SCIPpropGetData(prop);
158 assert(propdata != NULL);
160 SCIPfreeMemory(
scip, &propdata);
161 SCIPpropSetData(prop, NULL);
170 SCIP_PROPDATA* propdata;
172 assert( prop != NULL );
174 propdata = SCIPpropGetData(prop);
176 propdata->lastnode = -1;
185 SCIP_PROPDATA* propdata;
187 assert( prop != NULL );
189 propdata = SCIPpropGetData(prop);
191 if ( SCIPfindRelax(
scip,
"SDP") == NULL )
192 propdata->propenabled = FALSE;
195 propdata->propenabled = TRUE;
196 SCIP_CALL( SCIPgetRealParam(
scip,
"relaxing/SDP/sdpsolvergaptol", &(propdata->sdpsolvergaptol)) );
207 #if ( (SCIP_VERSION > 321 || SCIP_SUBVERSION > 0) ) 211 SCIP_PROPDATA* propdata;
214 SCIP_Bool oldobjlimitparam;
215 SCIP_Real probingval;
217 SCIP_RELAX* relaxsdp;
220 SCIP_Real* newbounds;
225 assert(
scip != NULL );
226 assert( prop != NULL );
227 assert( result != NULL );
229 propdata = SCIPpropGetData(prop);
231 assert( propdata != NULL );
233 *result = SCIP_DIDNOTRUN;
235 if ( ! propdata->propenabled )
238 SCIPdebugMsg(
scip,
"Executing propExecSdpObbt! \n");
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) )
244 if ( SCIPgetStage(
scip) != SCIP_STAGE_SOLVING || SCIPinRepropagation(
scip) || SCIPinProbing(
scip) || !SCIPallowObjProp(
scip) || (SCIPgetSubscipDepth(
scip) > 0) )
247 SCIPdebugMsg(
scip,
"Aborting propExecSdpObbt because we are in presolving, repropagation, probing mode, a subscip or no objective " 248 "propagation is allowed!\n");
253 if ( SCIPisInfinity(
scip, SCIPgetCutoffbound(
scip)) || (! SCIPisRelaxSolValid(
scip)) )
256 if ( propdata->delayed )
258 SCIPdebugMsg(
scip,
"Aborting propExecSdpObbt since still cutoffbound is infinite or no relaxation solution exists\n");
261 *result = SCIP_DELAYED;
262 propdata->delayed = TRUE;
263 SCIPdebugMsg(
scip,
"Delaying propExecSdpObbt since cutoffbound is infinite or no relaxation solution exists\n");
268 if ( (SCIPgetBestSol(
scip) == NULL) || ((SCIPsolGetHeur(SCIPgetBestSol(
scip)) != NULL) && (strcmp(SCIPheurGetName(SCIPsolGetHeur(SCIPgetBestSol(
scip))),
"trivial") == 0)) )
271 if ( propdata->delayed )
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");
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");
282 if ( (SCIPnodeGetNumber(SCIPgetCurrentNode(
scip)) == propdata->lastnode) && (SCIPisEQ(
scip, SCIPgetCutoffbound(
scip), propdata->lastcufoffbound)) )
284 SCIPdebugMsg(
scip,
"Not running again for node %lld with cutoffbound &f!\n", propdata->lastnode, propdata->lastcufoffbound);
289 propdata->lastnode = SCIPnodeGetNumber(SCIPgetCurrentNode(
scip));
290 propdata->lastcufoffbound = SCIPgetCutoffbound(
scip);
293 propdata->delayed = FALSE;
295 vars = SCIPgetVars(
scip);
296 nvars = SCIPgetNVars(
scip);
299 SCIP_CALL( SCIPstartProbing(
scip) );
300 SCIPdebugMsg(
scip,
"start probing\n");
302 SCIP_CALL( addObjCutoff(
scip) );
305 SCIP_CALL( SCIPgetBoolParam(
scip,
"relaxing/SDP/objlimit", &oldobjlimitparam) );
306 SCIP_CALL( SCIPsetBoolParam(
scip,
"relaxing/SDP/objlimit", FALSE) );
309 SCIP_CALL( SCIPallocBufferArray(
scip, &newbounds, 2*nvars) );
310 SCIP_CALL( SCIPallocBufferArray(
scip, &newboundinds, 2*nvars) );
312 *result = SCIP_DIDNOTFIND;
315 for( v = 0; v < nvars; ++v )
317 SCIP_CALL( SCIPchgVarObjProbing(
scip, vars[v], 0.0) );
322 for (v = 0; v < nvars; v++)
325 if ( (( ! propdata->propbin ) && SCIPvarIsBinary(vars[v])) || (( ! propdata->propcont ) && ( ! SCIPvarIsIntegral(vars[v]))) )
327 #ifdef SCIP_MORE_DEBUG 328 if ( SCIPvarIsBinary(vars[v]) )
330 SCIPdebugMsg(
scip,
"Skipping binary variable %s\n", SCIPvarGetName(vars[v]));
334 SCIPdebugMsg(
scip,
"Skipping continuous variable %s\n", SCIPvarGetName(vars[v]));
341 relaxval = SCIPgetRelaxSolVal(
scip, vars[v]);
344 if ( SCIPisFeasGT(
scip, relaxval, SCIPvarGetLbLocal(vars[v])) )
347 SCIP_CALL( SCIPchgVarObjProbing(
scip, vars[v], 1.0) );
350 SCIP_CALL( SCIPsolveProbingRelax(
scip, &cutoff) );
354 relaxsdp = SCIPfindRelax(
scip,
"SDP");
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;
367 SCIPdebugMsg(
scip,
"Probing sdp infeasible, so there can't be a better solution for this problem!\n");
368 *result = SCIP_CUTOFF;
380 if ( SCIPisGT(
scip, probingval -
TOLERANCE_FACTOR * propdata->sdpsolvergaptol, SCIPvarGetLbLocal(vars[v])) )
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);
386 newbounds[nnewbounds] = probingval;
387 newboundinds[nnewbounds] = -1 * (v+1);
389 *result = SCIP_REDUCEDDOM;
391 #ifdef SCIP_MORE_DEBUG 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]));
399 #ifdef SCIP_MORE_DEBUG 402 SCIPdebugMsg(
scip,
"Obbt-Sdp problem unbounded for variable %s!\n", SCIPvarGetName(vars[v]));
406 #ifdef SCIP_MORE_DEBUG 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]));
415 if ( SCIPisFeasLT(
scip, relaxval, SCIPvarGetUbLocal(vars[v])) )
418 SCIP_CALL( SCIPchgVarObjProbing(
scip, vars[v], -1.0) );
421 SCIP_CALL( SCIPsolveProbingRelax(
scip, &cutoff) );
425 relaxsdp = SCIPfindRelax(
scip,
"SDP");
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;
438 SCIPdebugMsg(
scip,
"Probing sdp infeasible, so there can't be a better solution for this problem!\n");
439 *result = SCIP_CUTOFF;
452 if ( SCIPisLT(
scip, -probingval +
TOLERANCE_FACTOR * propdata->sdpsolvergaptol, SCIPvarGetUbLocal(vars[v])) )
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);
457 newbounds[nnewbounds] = -probingval;
458 newboundinds[nnewbounds] = v + 1;
461 #ifdef SCIP_MORE_DEBUG 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]));
469 #ifdef SCIP_MORE_DEBUG 472 SCIPdebugMsg(
scip,
"Obbt-Sdp problem unbounded for variable %s!\n", SCIPvarGetName(vars[v]));
476 #ifdef SCIP_MORE_DEBUG 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]));
485 SCIP_CALL( SCIPchgVarObjProbing(
scip, vars[v], 0.0) );
489 SCIP_CALL( SCIPendProbing(
scip) );
490 SCIPdebugMsg(
scip,
"end probing\n");
491 SCIP_CALL( SCIPsetBoolParam(
scip,
"relaxing/SDP/objlimit", oldobjlimitparam) );
493 for (i = 0; i < nnewbounds; i++)
495 if ( newboundinds[i] < 0)
497 SCIP_CALL( SCIPchgVarLb(
scip, vars[-1 * newboundinds[i] - 1], newbounds[i]) );
498 *result = SCIP_REDUCEDDOM;
505 if ( SCIPvarIsBinary(vars[newboundinds[i] - 1]) && SCIPisLT(
scip, SCIPfeasFloor(
scip, newbounds[i]),
506 SCIPvarGetLbLocal(vars[newboundinds[i] - 1]) ))
508 SCIPdebugMsg(
scip,
"Probing sdp founded conflicting bounds for integer variable %s -> cutoff!\n",
509 SCIPvarGetName(vars[newboundinds[i] - 1]));
510 *result = SCIP_CUTOFF;
513 SCIP_CALL( SCIPchgVarUb(
scip, vars[newboundinds[i] - 1], newbounds[i]) );
514 *result = SCIP_REDUCEDDOM;
518 SCIPfreeBufferArray(
scip, &newboundinds);
519 SCIPfreeBufferArray(
scip, &newbounds);
524 *result = SCIP_DIDNOTRUN;
541 SCIP_PROPDATA* propdata;
546 SCIP_CALL( SCIPallocMemory(scip, &propdata) );
547 propdata->lastnode = -1;
548 propdata->propenabled = TRUE;
555 propExecSdpObbt, propdata) );
557 assert(prop != NULL);
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) );
566 SCIP_CALL( SCIPaddBoolParam(scip,
"propagating/" PROP_NAME "/propbin",
567 "Should optimization-based bound tightening be performed for binary variables?",
570 SCIP_CALL( SCIPaddBoolParam(scip,
"propagating/" PROP_NAME "/propcont",
571 "Should optimization-based bound tightening be performed for continuous variables?",
SCIP_RETCODE SCIPincludePropSdpObbt(SCIP *scip)
static SCIP_DECL_PROPEXIT(propExitSdpObbt)
static SCIP_DECL_PROPEXEC(propExecSdpObbt)
static SCIP_DECL_PROPCOPY(propCopySdpObbt)
optimization-based bound tightening propagator for semidefinite programs
SCIP_RETCODE SCIPrelaxSdpRelaxVal(SCIP_RELAX *relax, SCIP_Bool *success, SCIP_Real *objval)
static SCIP_DECL_PROPINITSOL(propInitsolSdpObbt)
static SCIP_DECL_PROPFREE(propFreeSdpObbt)
SCIP_Bool SCIPrelaxSdpSolvedProbing(SCIP_RELAX *relax)
SCIP_Bool SCIPrelaxSdpIsFeasible(SCIP_RELAX *relax)
SCIP_Bool SCIPrelaxSdpIsUnbounded(SCIP_RELAX *relax)