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;
97 char rowname[SCIP_MAXSTRLEN];
101 assert( scip != NULL );
102 assert( SCIPinProbing(scip) );
104 SCIPdebugMsg(scip,
"create objective cutoff and add it to the LP-constraints\n");
106 nvars = SCIPgetNVars(scip);
107 vars = SCIPgetVars(scip);
110 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN,
"obbtsdp_objcutoff");
111 SCIP_CALL( SCIPcreateEmptyRowUnspec(scip, &row, rowname, -SCIPinfinity(scip), SCIPgetCutoffbound(scip), FALSE, FALSE, FALSE) );
112 SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
114 for( v = 0; v < nvars; v++ )
116 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[v], SCIPvarGetObj(vars[v])) );
118 SCIP_CALL( SCIPflushRowExtensions(scip, row) );
121 SCIP_CALL( SCIPaddRowProbing(scip, row) );
123 SCIP_CALL( SCIPreleaseRow(scip, &row) );
137 assert( scip != NULL );
138 assert( prop != NULL );
139 assert( strcmp(SCIPpropGetName(prop),
PROP_NAME) == 0 );
152 SCIP_PROPDATA* propdata;
154 propdata = SCIPpropGetData(prop);
155 assert(propdata != NULL);
157 SCIPfreeMemory(scip, &propdata);
158 SCIPpropSetData(prop, NULL);
167 SCIP_PROPDATA* propdata;
169 assert( prop != NULL );
171 propdata = SCIPpropGetData(prop);
173 propdata->lastnode = -1;
182 SCIP_PROPDATA* propdata;
184 assert( prop != NULL );
186 propdata = SCIPpropGetData(prop);
188 if ( SCIPfindRelax(scip,
"SDP") == NULL )
189 propdata->propenabled = FALSE;
192 propdata->propenabled = TRUE;
193 SCIP_CALL( SCIPgetRealParam(scip,
"relaxing/SDP/sdpsolvergaptol", &(propdata->sdpsolvergaptol)) );
206 SCIP_PROPDATA* propdata;
209 SCIP_Bool oldobjlimitparam;
210 SCIP_Real probingval;
212 SCIP_RELAX* relaxsdp;
215 SCIP_Real* newbounds;
220 assert( scip != NULL );
221 assert( prop != NULL );
222 assert( result != NULL );
224 propdata = SCIPpropGetData(prop);
226 assert( propdata != NULL );
228 *result = SCIP_DIDNOTRUN;
230 if ( ! propdata->propenabled )
233 SCIPdebugMsg(scip,
"Executing propExecSdpObbt! \n");
236 if ( SCIPgetStage(scip) != SCIP_STAGE_SOLVING || SCIPinRepropagation(scip) || SCIPinProbing(scip) || !SCIPallowWeakDualReds(scip) || (SCIPgetSubscipDepth(scip) > 0) )
238 SCIPdebugMsg(scip,
"Aborting propExecSdpObbt because we are in presolving, repropagation, probing mode, a subscip or no objective " 239 "propagation is allowed!\n");
244 if ( SCIPisInfinity(scip, SCIPgetCutoffbound(scip)) || (! SCIPisRelaxSolValid(scip)) )
247 if ( propdata->delayed )
249 SCIPdebugMsg(scip,
"Aborting propExecSdpObbt since still cutoffbound is infinite or no relaxation solution exists\n");
252 *result = SCIP_DELAYED;
253 propdata->delayed = TRUE;
254 SCIPdebugMsg(scip,
"Delaying propExecSdpObbt since cutoffbound is infinite or no relaxation solution exists\n");
259 if ( (SCIPgetBestSol(scip) == NULL) || ((SCIPsolGetHeur(SCIPgetBestSol(scip)) != NULL) && (strcmp(SCIPheurGetName(SCIPsolGetHeur(SCIPgetBestSol(scip))),
"trivial") == 0)) )
262 if ( propdata->delayed )
264 SCIPdebugMsg(scip,
"Aborting propExecSdpObbt since still best solution was found by trivial heuristic or simple objective propagation, which will not be good enough\n");
267 *result = SCIP_DELAYED;
268 propdata->delayed = TRUE;
269 SCIPdebugMsg(scip,
"Delaying propExecSdpObbt since best solution was found by trivial heuristic or simple objective propagation, which will not be good enough\n");
273 if ( (SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) == propdata->lastnode) && (SCIPisEQ(scip, SCIPgetCutoffbound(scip), propdata->lastcufoffbound)) )
275 SCIPdebugMsg(scip,
"Not running again for node %" SCIP_LONGINT_FORMAT
" with cutoffbound %g!\n", propdata->lastnode, propdata->lastcufoffbound);
280 propdata->lastnode = SCIPnodeGetNumber(SCIPgetCurrentNode(scip));
281 propdata->lastcufoffbound = SCIPgetCutoffbound(scip);
284 propdata->delayed = FALSE;
286 vars = SCIPgetVars(scip);
287 nvars = SCIPgetNVars(scip);
290 SCIP_CALL( SCIPstartProbing(scip) );
291 SCIPdebugMsg(scip,
"start probing\n");
296 SCIP_CALL( SCIPgetBoolParam(scip,
"relaxing/SDP/objlimit", &oldobjlimitparam) );
297 SCIP_CALL( SCIPsetBoolParam(scip,
"relaxing/SDP/objlimit", FALSE) );
300 SCIP_CALL( SCIPallocBufferArray(scip, &newbounds, 2*nvars) );
301 SCIP_CALL( SCIPallocBufferArray(scip, &newboundinds, 2*nvars) );
303 *result = SCIP_DIDNOTFIND;
306 for( v = 0; v < nvars; ++v )
308 SCIP_CALL( SCIPchgVarObjProbing(scip, vars[v], 0.0) );
313 for (v = 0; v < nvars; v++)
316 if ( (( ! propdata->propbin ) && SCIPvarIsBinary(vars[v])) || (( ! propdata->propcont ) && ( ! SCIPvarIsIntegral(vars[v]))) )
318 #ifdef SCIP_MORE_DEBUG 319 if ( SCIPvarIsBinary(vars[v]) )
321 SCIPdebugMsg(scip,
"Skipping binary variable %s\n", SCIPvarGetName(vars[v]));
325 SCIPdebugMsg(scip,
"Skipping continuous variable %s\n", SCIPvarGetName(vars[v]));
332 relaxval = SCIPgetRelaxSolVal(scip, vars[v]);
335 if ( SCIPisFeasGT(scip, relaxval, SCIPvarGetLbLocal(vars[v])) )
338 SCIP_CALL( SCIPchgVarObjProbing(scip, vars[v], 1.0) );
341 SCIP_CALL( SCIPsolveProbingRelax(scip, &cutoff) );
345 relaxsdp = SCIPfindRelax(scip,
"SDP");
349 SCIPdebugMsg(scip,
"Aborting sdp-obbt, as we were unable to solve a probing sdp!\n");
350 if ( *result != SCIP_REDUCEDDOM )
351 *result = SCIP_DIDNOTRUN;
358 SCIPdebugMsg(scip,
"Probing sdp infeasible, so there can't be a better solution for this problem!\n");
359 *result = SCIP_CUTOFF;
371 if ( SCIPisGT(scip, probingval -
TOLERANCE_FACTOR * propdata->sdpsolvergaptol, SCIPvarGetLbLocal(vars[v])) )
374 SCIPdebugMsg(scip,
"Obbt-Sdp tightened lower bound of variable %s from %f to %f !\n",
375 SCIPvarGetName(vars[v]), SCIPvarGetLbLocal(vars[v]), probingval - propdata->sdpsolvergaptol);
377 newbounds[nnewbounds] = probingval;
378 newboundinds[nnewbounds] = -1 * (v+1);
380 *result = SCIP_REDUCEDDOM;
382 #ifdef SCIP_MORE_DEBUG 385 SCIPdebugMsg(scip,
"Obbt-Sdp found lower bound of %f for variable %s, worse than old bound %f !\n",
386 probingval, SCIPvarGetName(vars[v]), SCIPvarGetLbLocal(vars[v]));
390 #ifdef SCIP_MORE_DEBUG 393 SCIPdebugMsg(scip,
"Obbt-Sdp problem unbounded for variable %s!\n", SCIPvarGetName(vars[v]));
397 #ifdef SCIP_MORE_DEBUG 400 SCIPdebugMsg(scip,
"Skipping obbt for lower bound %f of variable %s, as current relaxation's solution is tight.\n",
401 SCIPvarGetLbLocal(vars[v]), SCIPvarGetName(vars[v]));
406 if ( SCIPisFeasLT(scip, relaxval, SCIPvarGetUbLocal(vars[v])) )
409 SCIP_CALL( SCIPchgVarObjProbing(scip, vars[v], -1.0) );
412 SCIP_CALL( SCIPsolveProbingRelax(scip, &cutoff) );
416 relaxsdp = SCIPfindRelax(scip,
"SDP");
420 SCIPdebugMsg(scip,
"Aborting sdp-obbt, as we were unable to solve a probing sdp!\n");
421 if ( *result != SCIP_REDUCEDDOM )
422 *result = SCIP_DIDNOTRUN;
429 SCIPdebugMsg(scip,
"Probing sdp infeasible, so there can't be a better solution for this problem!\n");
430 *result = SCIP_CUTOFF;
443 if ( SCIPisLT(scip, -probingval +
TOLERANCE_FACTOR * propdata->sdpsolvergaptol, SCIPvarGetUbLocal(vars[v])) )
445 SCIPdebugMsg(scip,
"Obbt-Sdp tightened upper bound of variable %s from %f to %f !\n",
446 SCIPvarGetName(vars[v]), SCIPvarGetUbLocal(vars[v]), -probingval + propdata->sdpsolvergaptol);
448 newbounds[nnewbounds] = -probingval;
449 newboundinds[nnewbounds] = v + 1;
452 #ifdef SCIP_MORE_DEBUG 455 SCIPdebugMsg(scip,
"Obbt-Sdp found upper bound of %f for variable %s, worse than old bound %f !\n",
456 -probingval, SCIPvarGetName(vars[v]), SCIPvarGetUbLocal(vars[v]));
460 #ifdef SCIP_MORE_DEBUG 463 SCIPdebugMsg(scip,
"Obbt-Sdp problem unbounded for variable %s!\n", SCIPvarGetName(vars[v]));
467 #ifdef SCIP_MORE_DEBUG 470 SCIPdebugMsg(scip,
"Skipping obbt for upper bound %f of variable %s, as current relaxation's solution is tight.\n",
471 SCIPvarGetUbLocal(vars[v]), SCIPvarGetName(vars[v]));
476 SCIP_CALL( SCIPchgVarObjProbing(scip, vars[v], 0.0) );
480 SCIP_CALL( SCIPendProbing(scip) );
481 SCIPdebugMsg(scip,
"end probing\n");
482 SCIP_CALL( SCIPsetBoolParam(scip,
"relaxing/SDP/objlimit", oldobjlimitparam) );
484 for (i = 0; i < nnewbounds; i++)
486 if ( newboundinds[i] < 0)
488 SCIP_CALL( SCIPchgVarLb(scip, vars[-1 * newboundinds[i] - 1], newbounds[i]) );
489 *result = SCIP_REDUCEDDOM;
496 if ( SCIPvarIsBinary(vars[newboundinds[i] - 1]) && SCIPisLT(scip, SCIPfeasFloor(scip, newbounds[i]),
497 SCIPvarGetLbLocal(vars[newboundinds[i] - 1]) ))
499 SCIPdebugMsg(scip,
"Probing sdp founded conflicting bounds for integer variable %s -> cutoff!\n",
500 SCIPvarGetName(vars[newboundinds[i] - 1]));
501 *result = SCIP_CUTOFF;
504 SCIP_CALL( SCIPchgVarUb(scip, vars[newboundinds[i] - 1], newbounds[i]) );
505 *result = SCIP_REDUCEDDOM;
509 SCIPfreeBufferArray(scip, &newboundinds);
510 SCIPfreeBufferArray(scip, &newbounds);
526 SCIP_PROPDATA* propdata;
531 SCIP_CALL( SCIPallocMemory(scip, &propdata) );
532 propdata->lastnode = -1;
533 propdata->propenabled = TRUE;
540 propExecSdpObbt, propdata) );
542 assert(prop != NULL);
545 SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopySdpObbt) );
546 SCIP_CALL( SCIPsetPropFree(scip, prop, propFreeSdpObbt) );
547 SCIP_CALL( SCIPsetPropExit(scip, prop, propExitSdpObbt) );
548 SCIP_CALL( SCIPsetPropInitsol(scip, prop, propInitsolSdpObbt) );
551 SCIP_CALL( SCIPaddBoolParam(scip,
"propagating/" PROP_NAME "/propbin",
552 "Should optimization-based bound tightening be performed for binary variables?",
555 SCIP_CALL( SCIPaddBoolParam(scip,
"propagating/" PROP_NAME "/propcont",
556 "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
static SCIP_RETCODE addObjCutoff(SCIP *scip)
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)