64 #include "scip/cons_linear.h" 66 #define HEUR_NAME "sdpinnerlp" 67 #define HEUR_DESC "inner approximation LP heuristic for SDPs" 68 #define HEUR_DISPCHAR '!' 69 #define HEUR_PRIORITY -1001000 71 #define HEUR_FREQOFS 0 72 #define HEUR_MAXDEPTH -1 73 #define HEUR_TIMING SCIP_HEURTIMING_BEFOREPRESOL 74 #define HEUR_USESSUBSCIP TRUE 81 #define DEFAULT_STALLNODELIMIT 100L 82 #define DEFAULT_MAXSIZE 10000 88 SCIP_Longint stallnodelimit;
101 assert( scip != NULL );
102 assert( heur != NULL );
103 assert( strcmp(SCIPheurGetName(heur),
HEUR_NAME) == 0 );
115 SCIP_HEURDATA* heurdata;
117 assert( heur != NULL );
118 assert( strcmp(SCIPheurGetName(heur),
HEUR_NAME) == 0 );
119 assert( scip != NULL );
122 heurdata = SCIPheurGetData(heur);
123 assert(heurdata != NULL);
125 SCIPfreeBlockMemory(scip, &heurdata);
126 SCIPheurSetData(heur, NULL);
135 SCIP_HEURDATA* heurdata;
136 SCIP_HASHMAP* varmapfw;
137 SCIP_CONSHDLR* conshdlrsdp;
152 assert( heur != NULL );
153 assert( strcmp(SCIPheurGetName(heur),
HEUR_NAME) == 0 );
154 assert( scip != NULL );
155 assert( result != NULL );
157 *result = SCIP_DELAYED;
160 if ( nodeinfeasible )
163 *result = SCIP_DIDNOTRUN;
166 SCIP_CALL( SCIPgetRealParam(scip,
"limits/time", &timelimit) );
167 if ( ! SCIPisInfinity(scip, timelimit) )
169 timelimit = MAX(0, timelimit - SCIPgetSolvingTime(scip) );
171 if ( timelimit <= 0.01 )
175 heurdata = SCIPheurGetData(heur);
176 assert( heurdata != NULL );
179 nconss = SCIPgetNConss(scip);
180 conss = SCIPgetConss(scip);
182 conshdlrsdp = SCIPfindConshdlr(scip,
"SDP");
183 if ( conshdlrsdp == NULL )
186 for (c = 0; c < nconss && totalsize < heurdata->maxsize; ++c)
191 assert( conss[c] != NULL );
192 if ( SCIPconsGetHdlr(conss[c]) != conshdlrsdp )
196 totalsize += (blocksize * (blocksize - 1))/2;
199 if ( totalsize >= heurdata->maxsize )
201 SCIPdebugMsg(scip,
"Skipping <%s>, because size would be too large.\n", SCIPheurGetName(heur));
206 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
209 SCIP_CALL( SCIPcreate(&subscip) );
212 SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), nvars) );
215 SCIP_CALL( SCIPcopyLargeNeighborhoodSearch(scip, subscip, varmapfw,
"sdpinnerlp", NULL, NULL, 0, FALSE,
216 FALSE, &success, NULL) );
219 conshdlrsdp = SCIPfindConshdlr(subscip,
"SDP");
220 if ( conshdlrsdp == NULL )
222 SCIP_CALL( SCIPfree(&subscip) );
227 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
228 for( i = 0; i < nvars; i++ )
229 subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);
232 SCIPhashmapFree(&varmapfw);
235 nconss = SCIPgetNConss(subscip);
236 SCIP_CALL( SCIPduplicateBufferArray(scip, &conss, SCIPgetConss(subscip), nconss) );
239 for (c = 0; c < nconss; ++c)
241 char name[SCIP_MAXSTRLEN];
242 SCIP_Real** matrices = NULL;
243 SCIP_Real* constmatrix;
255 assert( conss[c] != NULL );
258 if ( SCIPconsGetHdlr(conss[c]) != conshdlrsdp )
266 SCIP_CALL( SCIPallocBufferArray(subscip, &constmatrix, blocksize * blocksize) );
269 SCIP_CALL( SCIPallocBufferArray(subscip, &matrices, nsdpvars) );
270 for (i = 0; i < nsdpvars; ++i)
272 SCIP_CALL( SCIPallocBufferArray(subscip, &matrices[i], blocksize * blocksize) );
276 SCIP_CALL( SCIPallocBufferArray(subscip, &consvars, nsdpvars + 2 * blocksize) );
277 SCIP_CALL( SCIPallocBufferArray(subscip, &consvals, nsdpvars + 2 * blocksize) );
278 SCIP_CALL( SCIPallocBufferArray(subscip, &rayvars, blocksize * blocksize) );
283 for (s = 0; s < blocksize; ++s)
285 for (t = 0; t <= s; ++t)
287 SCIP_Bool nonzero = FALSE;
290 if ( SCIPisZero(subscip, constmatrix[s * blocksize + t]) )
292 for (i = 0; i < nsdpvars; ++i)
294 val = matrices[i][s * blocksize + t];
295 if ( ! SCIPisZero(subscip, val) )
305 if ( nonzero || s == t )
307 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN,
"ray%d#%d", s, t);
308 SCIP_CALL( SCIPcreateVarBasic(subscip, &rayvars[s * blocksize + t], name, 0.0, SCIPinfinity(subscip), 0.0, SCIP_VARTYPE_CONTINUOUS) );
309 SCIP_CALL( SCIPaddVar(subscip, rayvars[s * blocksize + t]) );
313 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN,
"ray%d#%d", t, s);
314 SCIP_CALL( SCIPcreateVarBasic(subscip, &rayvars[t * blocksize + s], name, 0.0, SCIPinfinity(subscip), 0.0, SCIP_VARTYPE_CONTINUOUS) );
315 SCIP_CALL( SCIPaddVar(subscip, rayvars[t * blocksize + s]) );
320 rayvars[s * blocksize + t] = NULL;
321 rayvars[t * blocksize + s] = NULL;
327 for (s = 0; s < blocksize; ++s)
329 for (t = 0; t <= s; ++t)
334 if ( rayvars[s * blocksize + t] == NULL )
337 assert( rayvars[t * blocksize + s] != NULL );
340 for (i = 0; i < nsdpvars; ++i)
342 val = matrices[i][s * blocksize + t];
343 if ( ! SCIPisZero(subscip, val) )
345 consvars[cnt] = sdpvars[i];
346 consvals[cnt++] = val;
351 consvars[cnt] = rayvars[s * blocksize + t];
352 consvals[cnt++] = -1.0;
356 consvars[cnt] = rayvars[t * blocksize + s];
357 consvals[cnt++] = +1.0;
362 for (i = 0; i < blocksize; ++i)
366 if ( rayvars[s * blocksize + i] != NULL )
368 assert( rayvars[i * blocksize + s] != NULL );
370 consvars[cnt] = rayvars[s * blocksize + i];
371 consvals[cnt++] = -1.0;
373 consvars[cnt] = rayvars[i * blocksize + s];
374 consvals[cnt++] = -1.0;
381 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN,
"lin%d#%d", s, t);
382 SCIP_CALL( SCIPcreateConsLinear(subscip, &cons, name, cnt, consvars, consvals, constmatrix[s * blocksize + t], constmatrix[s * blocksize + t],
383 TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE) );
384 SCIP_CALL( SCIPaddCons(subscip, cons) );
385 #ifdef SCIP_MORE_DEBUG 386 SCIP_CALL( SCIPprintCons(subscip, cons, NULL) );
388 SCIP_CALL( SCIPreleaseCons(subscip, &cons) );
393 SCIP_CALL( SCIPdelCons(subscip, conss[c]) );
395 for (i = 0; i < blocksize * blocksize; ++i)
397 if ( rayvars[i] != NULL )
399 SCIP_CALL( SCIPreleaseVar(subscip, &rayvars[i]) );
402 SCIPfreeBufferArray(subscip, &rayvars);
403 SCIPfreeBufferArray(subscip, &consvals);
404 SCIPfreeBufferArray(subscip, &consvars);
406 for (i = nsdpvars-1; i >= 0; --i)
407 SCIPfreeBufferArray(subscip, &matrices[i]);
408 SCIPfreeBufferArray(subscip, &matrices);
409 SCIPfreeBufferArray(subscip, &constmatrix);
413 SCIP_CALL( SCIPwriteOrigProblem(subscip,
"debug.lp",
"lp", FALSE) );
417 if ( ! SCIPisInfinity(scip, timelimit) )
419 SCIP_CALL( SCIPsetRealParam(subscip,
"limits/time", timelimit) );
423 SCIP_CALL( SCIPsetLongintParam(subscip,
"limits/stallnodes", heurdata->stallnodelimit) );
425 #ifdef SCIP_MORE_DEBUG 426 SCIPinfoMessage(scip, NULL,
"\nSolving inner LP subproblem ...\n");
427 SCIP_CALL( SCIPsetIntParam(subscip,
"display/verblevel", 5) );
429 SCIPdebugMsg(scip,
"Solving inner LP subproblem ...\n");
430 SCIP_CALL( SCIPsetIntParam(subscip,
"display/verblevel", 0) );
434 SCIP_CALL( SCIPsetIntParam(subscip,
"heuristics/sdpinnerlp/freq", -1) );
436 SCIP_CALL( SCIPsolve(subscip) );
439 nsubsols = SCIPgetNSols(subscip);
440 subsols = SCIPgetSols(subscip);
442 for (i = 0; i < nsubsols && ! success; ++i)
446 SCIP_CALL( SCIPtranslateSubSol(scip, subscip, subsols[i], heur, subvars, &newsol) );
448 SCIP_CALL( SCIPtrySolFree(scip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
451 SCIPdebugMsg(scip,
"Found solution.\n");
452 *result = SCIP_FOUNDSOL;
456 SCIP_CALL( SCIPfree(&subscip) );
458 SCIPfreeBufferArray(scip, &subvars);
459 SCIPfreeBufferArray(scip, &conss);
474 SCIP_HEURDATA* heurdata;
478 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
481 SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
485 assert( heur != NULL );
488 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopySdpInnerlp) );
489 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeSdpInnerlp) );
491 SCIP_CALL( SCIPaddLongintParam(scip,
"heuristics/" HEUR_NAME "/stallnodelimit",
492 "limit on number of nodes since last improving incumbent solutions",
495 SCIP_CALL( SCIPaddIntParam(scip,
"heuristics/" HEUR_NAME "/maxsize",
496 "maximal size of the inner problem",
497 &heurdata->maxsize, FALSE,
DEFAULT_MAXSIZE, -1, INT_MAX, NULL, NULL) );
int SCIPconsSdpGetNVars(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_HEURCOPY(heurCopySdpInnerlp)
SCIP_RETCODE SCIPconsSdpGetFullAj(SCIP *scip, SCIP_CONS *cons, int j, SCIP_Real *Aj)
SCIP_RETCODE SCIPincludeHeurSdpInnerlp(SCIP *scip)
static SCIP_DECL_HEUREXEC(heurExecSdpInnerlp)
#define DEFAULT_STALLNODELIMIT
static SCIP_DECL_HEURFREE(heurFreeSdpInnerlp)
set up inner approximation LP formulation and run heuristics
Constraint handler for SDP-constraints.
SCIP_RETCODE SCIPconsSdpGetFullConstMatrix(SCIP *scip, SCIP_CONS *cons, SCIP_Real *mat)
SCIP_VAR ** SCIPconsSdpGetVars(SCIP *scip, SCIP_CONS *cons)
int SCIPconsSdpGetBlocksize(SCIP *scip, SCIP_CONS *cons)