/** fills the whole Decomp struct after the dec file has been read */ static SCIP_RETCODE fillDecompStruct( SCIP* scip, /**< SCIP data structure */ DECINPUT* decinput, /**< DEC reading data */ DEC_DECOMP* decomp, /**< DEC_DECOMP structure to fill */ SCIP_READERDATA* readerdata /**< reader data*/ ) { SCIP_HASHMAP* constoblock; SCIP_CONS** allcons; int i; int j; int nblockconss; int nconss; int nblocks; SCIP_Bool valid; assert(scip != NULL); assert(decinput != NULL); assert(decomp != NULL); assert(readerdata != NULL); valid = FALSE; allcons = SCIPgetConss(scip); nconss = SCIPgetNConss(scip); nblocks = decinput->nblocks; DECdecompSetPresolved(decomp, decinput->presolved); DECdecompSetNBlocks(decomp, nblocks); DECdecompSetDetector(decomp, NULL); DECdecompSetType(decomp, DEC_DECTYPE_ARROWHEAD, &valid); assert(valid); /* hashmaps */ SCIP_CALL( SCIPhashmapCreate(&constoblock, SCIPblkmem(scip), nconss) ); for( i = 0; i < nconss; i ++ ) { SCIP_CALL( SCIPhashmapInsert(constoblock, allcons[i], (void*) (size_t) (nblocks+1)) ); } for( i = 0; i < nblocks; i ++ ) { nblockconss = readerdata->nblockconss[i]; for( j = 0; j < nblockconss; j ++ ) { /* hashmap */ SCIPdebugMessage("cons %s is in block %d\n", SCIPconsGetName(readerdata->blockconss[i][j]), i); SCIP_CALL( SCIPhashmapSetImage(constoblock, readerdata->blockconss[i][j], (void*) (size_t) (i+1)) ); } } SCIP_CALL( DECfilloutDecdecompFromConstoblock(scip, decomp, constoblock, nblocks, SCIPgetVars(scip), SCIPgetNVars(scip), SCIPgetConss(scip), SCIPgetNConss(scip), FALSE) ); return SCIP_OKAY; }
/** output method of display column to output file stream 'file' */ static SCIP_DECL_DISPOUTPUT(SCIPdispOutputConss) { /*lint --e{715}*/ assert(disp != NULL); assert(strcmp(SCIPdispGetName(disp), DISP_NAME_CONSS) == 0); assert(scip != NULL); SCIPdispInt(SCIPgetMessagehdlr(scip), file, SCIPgetNConss(GCGpricerGetOrigprob(scip)), DISP_WIDT_CONSS); return SCIP_OKAY; }
/** problem reading method of reader */ static SCIP_DECL_READERREAD(readerReadBlk) { /*lint --e{715} */ if( SCIPgetStage(scip) == SCIP_STAGE_INIT || SCIPgetNVars(scip) == 0 || SCIPgetNConss(scip) == 0 ) { SCIPverbMessage(scip, SCIP_VERBLEVEL_DIALOG, NULL, "Please read in a problem before reading in the corresponding structure file!\n"); return SCIP_OKAY; } SCIP_CALL( SCIPreadBlk(scip, filename, result) ); return SCIP_OKAY; }
/** reads an BLK file */ static SCIP_RETCODE readBLKFile( SCIP* scip, /**< SCIP data structure */ SCIP_READER* reader, /**< reader data structure */ BLKINPUT* blkinput, /**< BLK reading data */ const char* filename /**< name of the input file */ ) { DEC_DECOMP *decdecomp; int i; int nconss; int nblocksread; int nvars; SCIP_READERDATA* readerdata; SCIP_CONS** conss; nblocksread = FALSE; assert(scip != NULL); assert(reader != NULL); assert(blkinput != NULL); if( SCIPgetStage(scip) < SCIP_STAGE_TRANSFORMED ) SCIP_CALL( SCIPtransformProb(scip) ); readerdata = SCIPreaderGetData(reader); assert(readerdata != NULL); readerdata->nlinkingcons = SCIPgetNConss(scip); readerdata->nlinkingvars = 0; nvars = SCIPgetNVars(scip); conss = SCIPgetConss(scip); nconss = SCIPgetNConss(scip); /* alloc: var -> block mapping */ SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->varstoblock, nvars) ); for( i = 0; i < nvars; i ++ ) { readerdata->varstoblock[i] = NOVALUE; } /* alloc: linkingvar -> blocks mapping */ SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->linkingvarsblocks, nvars) ); SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->nlinkingvarsblocks, nvars) ); BMSclearMemoryArray(readerdata->linkingvarsblocks, nvars); BMSclearMemoryArray(readerdata->nlinkingvarsblocks, nvars); /* cons -> block mapping */ SCIP_CALL( SCIPhashmapCreate(&readerdata->constoblock, SCIPblkmem(scip), nconss) ); for( i = 0; i < SCIPgetNConss(scip); i ++ ) { SCIP_CALL( SCIPhashmapInsert(readerdata->constoblock, conss[i], (void*)(size_t) NOVALUE) ); } /* open file */ blkinput->file = SCIPfopen(filename, "r"); if( blkinput->file == NULL ) { SCIPerrorMessage("cannot open file <%s> for reading\n", filename); SCIPprintSysError(filename); return SCIP_NOFILE; } /* parse the file */ blkinput->section = BLK_START; while( blkinput->section != BLK_END && !hasError(blkinput) ) { switch( blkinput->section ) { case BLK_START: SCIP_CALL( readStart(scip, blkinput) ); break; case BLK_PRESOLVED: SCIP_CALL( readPresolved(scip, blkinput) ); if( blkinput->presolved && SCIPgetStage(scip) < SCIP_STAGE_PRESOLVED ) { assert(blkinput->haspresolvesection); /** @bug GCG should be able to presolve the problem first */ SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "decomposition belongs to the presolved problem, please presolve the problem first.\n"); goto TERMINATE; } break; case BLK_NBLOCKS: SCIP_CALL( readNBlocks(scip, blkinput) ); if( blkinput->haspresolvesection && !blkinput->presolved && SCIPgetStage(scip) >= SCIP_STAGE_PRESOLVED ) { SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "decomposition belongs to the unpresolved problem, please re-read the problem and read the decomposition without presolving.\n"); goto TERMINATE; } if( !blkinput->haspresolvesection ) { SCIPwarningMessage(scip, "decomposition has no presolve section at beginning. The behaviour is undefined. See the FAQ for further information.\n"); } break; case BLK_BLOCK: if( nblocksread == FALSE ) { /* alloc n vars per block */ SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->nblockvars, blkinput->nblocks) ); SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->nblockcons, blkinput->nblocks) ); SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->blockcons, blkinput->nblocks) ); for( i = 0; i < blkinput->nblocks; ++i ) { readerdata->nblockvars[i] = 0; readerdata->nblockcons[i] = 0; SCIP_CALL( SCIPallocMemoryArray(scip, &(readerdata->blockcons[i]), nconss) ); /*lint !e866*/ } nblocksread = TRUE; } SCIP_CALL( readBlock(scip, blkinput, readerdata) ); break; case BLK_MASTERCONSS: SCIP_CALL( readMasterconss(scip, blkinput, readerdata) ); break; case BLK_END: /* this is already handled in the while() loop */ default: SCIPerrorMessage("invalid BLK file section <%d>\n", blkinput->section); return SCIP_INVALIDDATA; } } SCIP_CALL( DECdecompCreate(scip, &decdecomp) ); /* fill decomp */ SCIP_CALL( fillDecompStruct(scip, blkinput, decdecomp, readerdata) ); /* add decomp to cons_decomp */ SCIP_CALL( SCIPconshdlrDecompAddDecdecomp(scip, decdecomp) ); for( i = 0; i < nvars; ++i ) { assert(readerdata->linkingvarsblocks[i] != NULL || readerdata->nlinkingvarsblocks[i] == 0); if( readerdata->nlinkingvarsblocks[i] > 0 ) { SCIPfreeMemoryArray(scip, &readerdata->linkingvarsblocks[i]); } } TERMINATE: if( nblocksread ) { for( i = blkinput->nblocks - 1; i >= 0; --i ) { SCIPfreeMemoryArray(scip, &(readerdata->blockcons[i])); } SCIPfreeMemoryArray(scip, &readerdata->blockcons); SCIPfreeMemoryArray(scip, &readerdata->nblockcons); SCIPfreeMemoryArray(scip, &readerdata->nblockvars); } SCIPhashmapFree(&readerdata->constoblock); SCIPfreeMemoryArray(scip, &readerdata->nlinkingvarsblocks); SCIPfreeMemoryArray(scip, &readerdata->linkingvarsblocks); SCIPfreeMemoryArray(scip, &readerdata->varstoblock); /* close file */ SCIPfclose(blkinput->file); return SCIP_OKAY; }
/** fills the whole Decomp struct after the blk file has been read */ static SCIP_RETCODE fillDecompStruct( SCIP* scip, /**< SCIP data structure */ BLKINPUT* blkinput, /**< blk reading data */ DEC_DECOMP* decomp, /**< DEC_DECOMP structure to fill */ SCIP_READERDATA* readerdata /**< reader data*/ ) { SCIP_HASHMAP* constoblock; SCIP_CONS** allcons; SCIP_VAR** consvars; int i; int j; int nvars; int blocknr; int nconss; int nblocks; SCIP_Bool valid; assert(scip != NULL); assert(blkinput != NULL); assert(readerdata != NULL); allcons = SCIPgetConss(scip); nvars = SCIPgetNVars(scip); nconss = SCIPgetNConss(scip); nblocks = blkinput->nblocks; DECdecompSetPresolved(decomp, blkinput->presolved); DECdecompSetNBlocks(decomp, nblocks); DECdecompSetDetector(decomp, NULL); DECdecompSetType(decomp, DEC_DECTYPE_ARROWHEAD, &valid); assert(valid); /* hashmaps */ SCIP_CALL( SCIPhashmapCreate(&constoblock, SCIPblkmem(scip), nconss) ); SCIP_CALL( SCIPallocMemoryArray(scip, &consvars, nvars) ); /* assign constraints to blocks or declare them linking */ for( i = 0; i < nconss; i ++ ) { SCIP_CONS* cons; cons = allcons[i]; if( SCIPhashmapGetImage(readerdata->constoblock, cons) == (void*) (size_t) LINKINGVALUE ) { SCIP_CALL( SCIPhashmapInsert(constoblock, cons, (void*) (size_t) (nblocks+1)) ); SCIPdebugMessage("cons %s is linking\n", SCIPconsGetName(cons)); } /* check whether all variables in the constraint belong to one block */ else { int nconsvars; nconsvars = SCIPgetNVarsXXX(scip, cons); assert(nconsvars < nvars); SCIP_CALL( SCIPgetVarsXXX(scip, cons, consvars, nvars) ); blocknr = -1; /* find the first unique assignment of a contained variable to a block */ for( j = 0; j < nconsvars; ++j ) { /* if a contained variables is directly transferred to the master, the constraint is a linking constraint */ if( readerdata->varstoblock[SCIPvarGetProbindex(consvars[j])] == NOVALUE ) { blocknr = -1; break; } /* assign the constraint temporarily to the block of the variable, if it is unique */ if( blocknr == -1 && readerdata->varstoblock[SCIPvarGetProbindex(consvars[j])] != LINKINGVALUE ) { blocknr = readerdata->varstoblock[SCIPvarGetProbindex(consvars[j])]; } } if( blocknr != -1 ) { int varidx; int varblock; /* check whether all contained variables are copied into the assigned block; * if not, the constraint is treated as a linking constraint */ for( j = 0; j < nconsvars; ++j ) { varidx = SCIPvarGetProbindex(consvars[j]); varblock = readerdata->varstoblock[varidx]; assert(varblock != NOVALUE); if( varblock != LINKINGVALUE && varblock != blocknr ) { blocknr = -1; break; } else if( varblock == LINKINGVALUE ) { int k; for( k = 0; k < readerdata->nlinkingvarsblocks[varidx]; ++k ) { if( readerdata->linkingvarsblocks[varidx][k] == blocknr ) break; } /* we did not break, so the variable is not assigned to the block */ if( k == readerdata->nlinkingvarsblocks[varidx] ) { blocknr = -1; break; } } } } if( blocknr == -1 ) { SCIP_CALL( SCIPhashmapInsert(constoblock, cons, (void*) (size_t) (nblocks+1)) ); SCIPdebugMessage("constraint <%s> is a linking constraint\n", SCIPconsGetName(cons)); } else { SCIP_CALL( SCIPhashmapInsert(constoblock, cons, (void*) (size_t) (blocknr+1)) ); SCIPdebugMessage("constraint <%s> is assigned to block %d\n", SCIPconsGetName(cons), blocknr); } } } SCIP_CALL( DECfilloutDecdecompFromConstoblock(scip, decomp, constoblock, nblocks, SCIPgetVars(scip), SCIPgetNVars(scip), SCIPgetConss(scip), SCIPgetNConss(scip), FALSE) ); SCIPfreeMemoryArray(scip, &consvars); return SCIP_OKAY; }
/** execution method of event handler */ static SCIP_DECL_EVENTEXEC(eventExecBoundwriting) { /*lint --e{715}*/ SCIP_EVENTHDLRDATA* eventhdlrdata; assert(scip != NULL); assert(eventhdlr != NULL); assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0); assert(event != NULL); assert(((SCIPeventGetType(event) & SCIP_EVENTTYPE_NODESOLVED) == SCIP_EVENTTYPE_NODEFEASIBLE) || ((SCIPeventGetType(event) & SCIP_EVENTTYPE_NODESOLVED) == SCIP_EVENTTYPE_NODEINFEASIBLE) || ((SCIPeventGetType(event) & SCIP_EVENTTYPE_NODESOLVED) == SCIP_EVENTTYPE_NODEBRANCHED)); SCIPdebugMessage("exec method of event handler for writing primal- and dualbounds\n"); eventhdlrdata = SCIPeventhdlrGetData(eventhdlr); assert(eventhdlrdata != NULL); #ifdef ONEFILE /* check if we need to open the file */ if( strlen(eventhdlrdata->filename) > 0 && !eventhdlrdata->isopen ) { assert(eventhdlrdata->file == NULL); assert(eventhdlrdata->oldfilename[0] == '\0'); eventhdlrdata->file = fopen(eventhdlrdata->filename, "w"); (void)strncpy(eventhdlrdata->oldfilename, eventhdlrdata->filename, SCIP_MAXSTRLEN); if( eventhdlrdata->file == NULL ) { SCIPerrorMessage("cannot create file <%s> for writing\n", eventhdlrdata->filename); SCIPprintSysError(eventhdlrdata->filename); return SCIP_FILECREATEERROR; } eventhdlrdata->isopen = TRUE; #ifdef LONGSTATS SCIPinfoMessage(scip, eventhdlrdata->file, "Problem: %s (%d Original Constraints, %d Original Variables)\n", SCIPgetProbName(scip), SCIPgetNOrigConss(scip), SCIPgetNOrigVars(scip) ); SCIPinfoMessage(scip, eventhdlrdata->file, "\t (%d Presolved Constraints, %d Presolved Variables, (%d binary, %d integer, %d implicit integer, %d continuous))\n", SCIPgetNConss(scip), SCIPgetNVars(scip), SCIPgetNBinVars(scip), SCIPgetNIntVars(scip), SCIPgetNImplVars(scip), SCIPgetNContVars(scip)); SCIPinfoMessage(scip, eventhdlrdata->file, "\n"); #endif } #endif /* call writing only at right moment */ if( eventhdlrdata->freq == 0 || (SCIPgetNNodes(scip) % eventhdlrdata->freq) != 0 ) return SCIP_OKAY; #ifndef ONEFILE if( strlen(eventhdlrdata->filename) > 0 ) { char name[SCIP_MAXSTRLEN]; char number[SCIP_MAXSTRLEN]; char* pch; int n; assert(eventhdlrdata->file == NULL); assert(!eventhdlrdata->isopen); if( eventhdlrdata->oldfilename[0] == '\0' ) (void)strncpy(eventhdlrdata->oldfilename, eventhdlrdata->filename, SCIP_MAXSTRLEN); /* find last '.' to append filenumber */ pch=strrchr(eventhdlrdata->filename,'.'); assert(eventhdlrdata->filenumber > 0); n=sprintf(number, "%"SCIP_LONGINT_FORMAT"", eventhdlrdata->filenumber * eventhdlrdata->freq); assert(n > 0); assert(n < SCIP_MAXSTRLEN); /* if no point is found, extend directly */ if( pch == NULL ) { (void)strncpy(name, eventhdlrdata->filename, (unsigned int)(SCIP_MAXSTRLEN - n)); strncat(name, number, (unsigned int)n); } else { int len; if( (pch-(eventhdlrdata->filename)) > (SCIP_MAXSTRLEN - n) ) /*lint !e776*/ len = SCIP_MAXSTRLEN - n; else len = (int) (pch-(eventhdlrdata->filename)); (void)strncpy(name, eventhdlrdata->filename, (unsigned int)len); name[len] = '\0'; strncat(name, number, (unsigned int)n); assert(len+n < SCIP_MAXSTRLEN); name[len+n] = '\0'; if( len + n + strlen(&(eventhdlrdata->filename[len])) < SCIP_MAXSTRLEN ) /*lint !e776*/ { strncat(name, &(eventhdlrdata->filename[len]), strlen(&(eventhdlrdata->filename[len]))); name[strlen(eventhdlrdata->filename)+n] = '\0'; } } eventhdlrdata->file = fopen(name, "w"); if( eventhdlrdata->file == NULL ) { SCIPerrorMessage("cannot create file <%s> for writing\n", eventhdlrdata->filename); SCIPprintSysError(eventhdlrdata->filename); return SCIP_FILECREATEERROR; } eventhdlrdata->isopen = TRUE; #ifdef LONGSTATS SCIPinfoMessage(scip, eventhdlrdata->file, "Problem: %s (%d Original Constraints, %d Original Variables)\n", SCIPgetProbName(scip), SCIPgetNOrigConss(scip), SCIPgetNOrigVars(scip) ); SCIPinfoMessage(scip, eventhdlrdata->file, "\t (%d Active Constraints, %d Active Variables, (%d binary, %d integer, %d implicit integer, %d continuous))\n", SCIPgetNConss(scip), SCIPgetNVars(scip), SCIPgetNBinVars(scip), SCIPgetNIntVars(scip), SCIPgetNImplVars(scip), SCIPgetNContVars(scip)); SCIPinfoMessage(scip, eventhdlrdata->file, "\n"); #endif } #endif #ifndef NDEBUG /* check the filename did not change during the solving */ if( strlen(eventhdlrdata->filename) > 0 && eventhdlrdata->isopen ) { char tmp[SCIP_MAXSTRLEN]; (void)strncpy(tmp, eventhdlrdata->filename, SCIP_MAXSTRLEN); /* the name should stay the same */ assert(strcmp(tmp, eventhdlrdata->oldfilename) == 0); } #endif #ifdef FOCUSNODE /* call writing method */ SCIP_CALL( writeBoundsFocusNode(scip, eventhdlrdata) ); #else /* call writing method */ SCIP_CALL( writeBounds(scip, eventhdlrdata->file, eventhdlrdata->writesubmipdualbound) ); #endif #ifndef ONEFILE if( strlen(eventhdlrdata->filename) > 0 ) { assert(eventhdlrdata->isopen); (void) fclose(eventhdlrdata->file); eventhdlrdata->isopen = FALSE; eventhdlrdata->file = NULL; ++(eventhdlrdata->filenumber); } #endif return SCIP_OKAY; }
/** main procedure of the RENS heuristic, creates and solves a subMIP */ SCIP_RETCODE SCIPapplyGcgrens( SCIP* scip, /**< original SCIP data structure */ SCIP_HEUR* heur, /**< heuristic data structure */ SCIP_RESULT* result, /**< result data structure */ SCIP_Real minfixingrate, /**< minimum percentage of integer variables that have to be fixed */ SCIP_Real minimprove, /**< factor by which RENS should at least improve the incumbent */ SCIP_Longint maxnodes, /**< maximum number of nodes for the subproblem */ SCIP_Longint nstallnodes, /**< number of stalling nodes for the subproblem */ SCIP_Bool binarybounds, /**< should general integers get binary bounds [floor(.),ceil(.)]? */ SCIP_Bool uselprows /**< should subproblem be created out of the rows in the LP rows? */ ) { SCIP* subscip; /* the subproblem created by RENS */ SCIP_HASHMAP* varmapfw; /* mapping of SCIP variables to sub-SCIP variables */ SCIP_VAR** vars; /* original problem's variables */ SCIP_VAR** subvars; /* subproblem's variables */ SCIP_Real cutoff; /* objective cutoff for the subproblem */ SCIP_Real timelimit; SCIP_Real memorylimit; int nvars; int i; SCIP_Bool success; SCIP_RETCODE retcode; assert(scip != NULL); assert(heur != NULL); assert(result != NULL); assert(maxnodes >= 0); assert(nstallnodes >= 0); assert(0.0 <= minfixingrate && minfixingrate <= 1.0); assert(0.0 <= minimprove && minimprove <= 1.0); SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) ); /* initialize the subproblem */ SCIP_CALL( SCIPcreate(&subscip) ); /* create the variable mapping hash map */ SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), SCIPcalcHashtableSize(5 * nvars)) ); SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) ); if( uselprows ) { char probname[SCIP_MAXSTRLEN]; /* copy all plugins */ SCIP_CALL( SCIPincludeDefaultPlugins(subscip) ); /* get name of the original problem and add the string "_gcgrenssub" */ (void) SCIPsnprintf(probname, SCIP_MAXSTRLEN, "%s_gcgrenssub", SCIPgetProbName(scip)); /* create the subproblem */ SCIP_CALL( SCIPcreateProb(subscip, probname, NULL, NULL, NULL, NULL, NULL, NULL, NULL) ); /* copy all variables */ SCIP_CALL( SCIPcopyVars(scip, subscip, varmapfw, NULL, TRUE) ); } else { SCIP_Bool valid; SCIP_HEURDATA* heurdata; valid = FALSE; SCIP_CALL( SCIPcopy(scip, subscip, varmapfw, NULL, "gcgrens", TRUE, FALSE, TRUE, &valid) ); /** @todo check for thread safeness */ /* get heuristic's data */ heurdata = SCIPheurGetData(heur); assert( heurdata != NULL ); if( heurdata->copycuts ) { /** copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */ SCIP_CALL( SCIPcopyCuts(scip, subscip, varmapfw, NULL, TRUE, NULL) ); } SCIPdebugMessage("Copying the SCIP instance was %s complete.\n", valid ? "" : "not "); } for( i = 0; i < nvars; i++ ) subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]); /* free hash map */ SCIPhashmapFree(&varmapfw); /* create a new problem, which fixes variables with same value in bestsol and LP relaxation */ SCIP_CALL( createSubproblem(scip, subscip, subvars, minfixingrate, binarybounds, uselprows, &success) ); SCIPdebugMessage("RENS subproblem: %d vars, %d cons, success=%u\n", SCIPgetNVars(subscip), SCIPgetNConss(subscip), success); /* do not abort subproblem on CTRL-C */ SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) ); /* disable output to console */ SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) ); /* check whether there is enough time and memory left */ timelimit = 0.0; memorylimit = 0.0; SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) ); if( !SCIPisInfinity(scip, timelimit) ) timelimit -= SCIPgetSolvingTime(scip); SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) ); if( !SCIPisInfinity(scip, memorylimit) ) memorylimit -= SCIPgetMemUsed(scip)/1048576.0; if( timelimit <= 0.0 || memorylimit <= 0.0 ) goto TERMINATE; /* set limits for the subproblem */ SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", nstallnodes) ); SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", maxnodes) ); SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) ); SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) ); /* forbid recursive call of heuristics and separators solving sub-SCIPs */ SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) ); /* disable cutting plane separation */ SCIP_CALL( SCIPsetSeparating(subscip, SCIP_PARAMSETTING_OFF, TRUE) ); /* disable expensive presolving */ SCIP_CALL( SCIPsetPresolving(subscip, SCIP_PARAMSETTING_FAST, TRUE) ); /* use best estimate node selection */ if( SCIPfindNodesel(scip, "estimate") != NULL ) { SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) ); } /* use inference branching */ if( SCIPfindBranchrule(scip, "inference") != NULL ) { SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) ); } /* disable conflict analysis */ SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useprop", FALSE) ); SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useinflp", FALSE) ); SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useboundlp", FALSE) ); SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/usesb", FALSE) ); SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/usepseudo", FALSE) ); #ifdef SCIP_DEBUG /* for debugging RENS, enable MIP output */ SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) ); SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) ); #endif /* if the subproblem could not be created, free memory and return */ if( !success ) { *result = SCIP_DIDNOTRUN; SCIPfreeBufferArray(scip, &subvars); SCIP_CALL( SCIPfree(&subscip) ); return SCIP_OKAY; } /* if there is already a solution, add an objective cutoff */ if( SCIPgetNSols(scip) > 0 ) { SCIP_Real upperbound; assert( !SCIPisInfinity(scip,SCIPgetUpperbound(scip)) ); upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip); if( !SCIPisInfinity(scip,-1.0*SCIPgetLowerbound(scip)) ) { cutoff = (1-minimprove)*SCIPgetUpperbound(scip) + minimprove*SCIPgetLowerbound(scip); } else { if( SCIPgetUpperbound ( scip ) >= 0 ) cutoff = ( 1 - minimprove ) * SCIPgetUpperbound ( scip ); else cutoff = ( 1 + minimprove ) * SCIPgetUpperbound ( scip ); } cutoff = MIN(upperbound, cutoff); SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) ); } /* presolve the subproblem */ retcode = SCIPpresolve(subscip); /* Errors in solving the subproblem should not kill the overall solving process * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */ if( retcode != SCIP_OKAY ) { #ifndef NDEBUG SCIP_CALL( retcode ); #endif SCIPwarningMessage(scip, "Error while presolving subproblem in GCG RENS heuristic; sub-SCIP terminated with code <%d>\n",retcode); } SCIPdebugMessage("GCG RENS presolved subproblem: %d vars, %d cons, success=%u\n", SCIPgetNVars(subscip), SCIPgetNConss(subscip), success); /* after presolving, we should have at least reached a certain fixing rate over ALL variables (including continuous) * to ensure that not only the MIP but also the LP relaxation is easy enough */ if( ( nvars - SCIPgetNVars(subscip) ) / (SCIP_Real)nvars >= minfixingrate / 2.0 ) { SCIP_SOL** subsols; int nsubsols; /* solve the subproblem */ SCIPdebugMessage("solving subproblem: nstallnodes=%"SCIP_LONGINT_FORMAT", maxnodes=%"SCIP_LONGINT_FORMAT"\n", nstallnodes, maxnodes); retcode = SCIPsolve(subscip); /* Errors in solving the subproblem should not kill the overall solving process * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */ if( retcode != SCIP_OKAY ) { #ifndef NDEBUG SCIP_CALL( retcode ); #endif SCIPwarningMessage(scip, "Error while solving subproblem in GCG RENS heuristic; sub-SCIP terminated with code <%d>\n",retcode); } /* check, whether a solution was found; * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted */ nsubsols = SCIPgetNSols(subscip); subsols = SCIPgetSols(subscip); success = FALSE; for( i = 0; i < nsubsols && !success; ++i ) { SCIP_CALL( createNewSol(scip, subscip, subvars, heur, subsols[i], &success) ); } if( success ) *result = SCIP_FOUNDSOL; } TERMINATE: /* free subproblem */ SCIPfreeBufferArray(scip, &subvars); SCIP_CALL( SCIPfree(&subscip) ); return SCIP_OKAY; }
/** LP solution separation method of separator */ static SCIP_DECL_SEPAEXECLP(sepaExeclpRapidlearning) {/*lint --e{715}*/ SCIP* subscip; /* the subproblem created by rapid learning */ SCIP_SEPADATA* sepadata; /* separator's private data */ SCIP_VAR** vars; /* original problem's variables */ SCIP_VAR** subvars; /* subproblem's variables */ SCIP_HASHMAP* varmapfw; /* mapping of SCIP variables to sub-SCIP variables */ SCIP_HASHMAP* varmapbw; /* mapping of sub-SCIP variables to SCIP variables */ SCIP_CONSHDLR** conshdlrs; /* array of constraint handler's that might that might obtain conflicts */ int* oldnconss; /* number of constraints without rapid learning conflicts */ SCIP_Longint nodelimit; /* node limit for the subproblem */ SCIP_Real timelimit; /* time limit for the subproblem */ SCIP_Real memorylimit; /* memory limit for the subproblem */ int nconshdlrs; /* size of conshdlr and oldnconss array */ int nfixedvars; /* number of variables that could be fixed by rapid learning */ int nvars; /* number of variables */ int restartnum; /* maximal number of conflicts that should be created */ int i; /* counter */ SCIP_Bool success; /* was problem creation / copying constraint successful? */ SCIP_RETCODE retcode; /* used for catching sub-SCIP errors in debug mode */ int nconflicts; /* statistic: number of conflicts applied */ int nbdchgs; /* statistic: number of bound changes applied */ int n1startinfers; /* statistic: number of one side infer values */ int n2startinfers; /* statistic: number of both side infer values */ SCIP_Bool soladded; /* statistic: was a new incumbent found? */ SCIP_Bool dualboundchg; /* statistic: was a new dual bound found? */ SCIP_Bool disabledualreductions; /* TRUE, if dual reductions in sub-SCIP are not valid for original SCIP, * e.g., because a constraint could not be copied or a primal solution * could not be copied back */ int ndiscvars; soladded = FALSE; assert(sepa != NULL); assert(scip != NULL); assert(result != NULL); *result = SCIP_DIDNOTRUN; ndiscvars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip)+SCIPgetNImplVars(scip); /* only run when still not fixed binary variables exists */ if( ndiscvars == 0 ) return SCIP_OKAY; /* get separator's data */ sepadata = SCIPsepaGetData(sepa); assert(sepadata != NULL); /* only run for integer programs */ if( !sepadata->contvars && ndiscvars != SCIPgetNVars(scip) ) return SCIP_OKAY; /* only run if there are few enough continuous variables */ if( sepadata->contvars && SCIPgetNContVars(scip) > sepadata->contvarsquot * SCIPgetNVars(scip) ) return SCIP_OKAY; /* do not run if pricers are present */ if( SCIPgetNActivePricers(scip) > 0 ) return SCIP_OKAY; /* if the separator should be exclusive to the root node, this prevents multiple calls due to restarts */ if( SCIPsepaGetFreq(sepa) == 0 && SCIPsepaGetNCalls(sepa) > 0) return SCIP_OKAY; /* call separator at most once per node */ if( SCIPsepaGetNCallsAtNode(sepa) > 0 ) return SCIP_OKAY; /* do not call rapid learning, if the problem is too big */ if( SCIPgetNVars(scip) > sepadata->maxnvars || SCIPgetNConss(scip) > sepadata->maxnconss ) return SCIP_OKAY; if( SCIPisStopped(scip) ) return SCIP_OKAY; *result = SCIP_DIDNOTFIND; SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) ); /* initializing the subproblem */ SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) ); SCIP_CALL( SCIPcreate(&subscip) ); SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), SCIPcalcHashtableSize(5 * nvars)) ); success = FALSE; /* copy the subproblem */ SCIP_CALL( SCIPcopy(scip, subscip, varmapfw, NULL, "rapid", FALSE, FALSE, &success) ); if( sepadata->copycuts ) { /** copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */ SCIP_CALL( SCIPcopyCuts(scip, subscip, varmapfw, NULL, FALSE) ); } for( i = 0; i < nvars; i++ ) subvars[i] = (SCIP_VAR*) (size_t) SCIPhashmapGetImage(varmapfw, vars[i]); SCIPhashmapFree(&varmapfw); /* this avoids dual presolving */ if( !success ) { for( i = 0; i < nvars; i++ ) { SCIP_CALL( SCIPaddVarLocks(subscip, subvars[i], 1, 1 ) ); } } SCIPdebugMessage("Copying SCIP was%s successful.\n", success ? "" : " not"); /* mimic an FD solver: DFS, no LP solving, 1-FUIP instead of all-FUIP */ SCIP_CALL( SCIPsetIntParam(subscip, "lp/solvefreq", -1) ); SCIP_CALL( SCIPsetIntParam(subscip, "conflict/fuiplevels", 1) ); SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/dfs/stdpriority", INT_MAX/4) ); SCIP_CALL( SCIPsetBoolParam(subscip, "constraints/disableenfops", TRUE) ); SCIP_CALL( SCIPsetIntParam(subscip, "propagating/pseudoobj/freq", -1) ); /* use inference branching */ SCIP_CALL( SCIPsetBoolParam(subscip, "branching/inference/useweightedsum", FALSE) ); /* only create short conflicts */ SCIP_CALL( SCIPsetRealParam(subscip, "conflict/maxvarsfac", 0.05) ); /* set limits for the subproblem */ nodelimit = SCIPgetNLPIterations(scip); nodelimit = MAX(sepadata->minnodes, nodelimit); nodelimit = MIN(sepadata->maxnodes, nodelimit); restartnum = 1000; /* check whether there is enough time and memory left */ SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) ); if( !SCIPisInfinity(scip, timelimit) ) timelimit -= SCIPgetSolvingTime(scip); SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) ); if( !SCIPisInfinity(scip, memorylimit) ) memorylimit -= SCIPgetMemUsed(scip)/1048576.0; if( timelimit <= 0.0 || memorylimit <= 0.0 ) goto TERMINATE; SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nodelimit/5) ); SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) ); SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) ); SCIP_CALL( SCIPsetIntParam(subscip, "limits/restarts", 0) ); SCIP_CALL( SCIPsetIntParam(subscip, "conflict/restartnum", restartnum) ); /* forbid recursive call of heuristics and separators solving subMIPs */ SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) ); /* disable cutting plane separation */ SCIP_CALL( SCIPsetSeparating(subscip, SCIP_PARAMSETTING_OFF, TRUE) ); /* disable expensive presolving */ SCIP_CALL( SCIPsetPresolving(subscip, SCIP_PARAMSETTING_FAST, TRUE) ); /* do not abort subproblem on CTRL-C */ SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) ); #ifndef SCIP_DEBUG /* disable output to console */ SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) ); #endif /* add an objective cutoff */ SCIP_CALL( SCIPsetObjlimit(subscip, SCIPgetUpperbound(scip)) ); /* create the variable mapping hash map */ SCIP_CALL( SCIPhashmapCreate(&varmapbw, SCIPblkmem(scip), SCIPcalcHashtableSize(5 * nvars)) ); /* store reversing mapping of variables */ SCIP_CALL( SCIPtransformProb(subscip) ); for( i = 0; i < nvars; ++i) { SCIP_CALL( SCIPhashmapInsert(varmapbw, SCIPvarGetTransVar(subvars[i]), vars[i]) ); } /** allocate memory for constraints storage. Each constraint that will be created from now on will be a conflict. * Therefore, we need to remember oldnconss to get the conflicts from the FD search. */ nconshdlrs = 4; SCIP_CALL( SCIPallocBufferArray(scip, &conshdlrs, nconshdlrs) ); SCIP_CALL( SCIPallocBufferArray(scip, &oldnconss, nconshdlrs) ); /* store number of constraints before rapid learning search */ conshdlrs[0] = SCIPfindConshdlr(subscip, "bounddisjunction"); conshdlrs[1] = SCIPfindConshdlr(subscip, "setppc"); conshdlrs[2] = SCIPfindConshdlr(subscip, "linear"); conshdlrs[3] = SCIPfindConshdlr(subscip, "logicor"); /* redundant constraints might be eliminated in presolving */ SCIP_CALL( SCIPpresolve(subscip)); for( i = 0; i < nconshdlrs; ++i) { if( conshdlrs[i] != NULL ) oldnconss[i] = SCIPconshdlrGetNConss(conshdlrs[i]); } nfixedvars = SCIPgetNFixedVars(scip); /* solve the subproblem */ retcode = SCIPsolve(subscip); /* Errors in solving the subproblem should not kill the overall solving process * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */ if( retcode != SCIP_OKAY ) { #ifndef NDEBUG SCIP_CALL( retcode ); #endif SCIPwarningMessage("Error while solving subproblem in rapid learning separator; sub-SCIP terminated with code <%d>\n",retcode); } /* abort solving, if limit of applied conflicts is reached */ if( SCIPgetNConflictConssApplied(subscip) >= restartnum ) { SCIPdebugMessage("finish after %lld successful conflict calls.\n", SCIPgetNConflictConssApplied(subscip)); } /* if the first 20% of the solution process were successful, proceed */ else if( (sepadata->applyprimalsol && SCIPgetNSols(subscip) > 0 && SCIPisFeasLT(scip, SCIPgetUpperbound(subscip), SCIPgetUpperbound(scip) ) ) || (sepadata->applybdchgs && SCIPgetNFixedVars(subscip) > nfixedvars) || (sepadata->applyconflicts && SCIPgetNConflictConssApplied(subscip) > 0) ) { SCIPdebugMessage("proceed solving after the first 20%% of the solution process, since:\n"); if( SCIPgetNSols(subscip) > 0 && SCIPisFeasLE(scip, SCIPgetUpperbound(subscip), SCIPgetUpperbound(scip) ) ) { SCIPdebugMessage(" - there was a better solution (%f < %f)\n",SCIPgetUpperbound(subscip), SCIPgetUpperbound(scip)); } if( SCIPgetNFixedVars(subscip) > nfixedvars ) { SCIPdebugMessage(" - there were %d variables fixed\n", SCIPgetNFixedVars(scip)-nfixedvars ); } if( SCIPgetNConflictConssFound(subscip) > 0 ) { SCIPdebugMessage(" - there were %lld conflict constraints created\n", SCIPgetNConflictConssApplied(subscip)); } /* set node limit to 100% */ SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nodelimit) ); /* solve the subproblem */ retcode = SCIPsolve(subscip); /* Errors in solving the subproblem should not kill the overall solving process * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */ if( retcode != SCIP_OKAY ) { #ifndef NDEBUG SCIP_CALL( retcode ); #endif SCIPwarningMessage("Error while solving subproblem in rapid learning separator; sub-SCIP terminated with code <%d>\n",retcode); } } else { SCIPdebugMessage("do not proceed solving after the first 20%% of the solution process.\n"); } #ifdef SCIP_DEBUG SCIP_CALL( SCIPprintStatistics(subscip, NULL) ); #endif disabledualreductions = FALSE; /* check, whether a solution was found */ if( sepadata->applyprimalsol && SCIPgetNSols(subscip) > 0 && SCIPfindHeur(scip, "trysol") != NULL ) { SCIP_HEUR* heurtrysol; SCIP_SOL** subsols; int nsubsols; /* check, whether a solution was found; * due to numerics, it might happen that not all solutions are feasible -> try all solutions until was declared to be feasible */ nsubsols = SCIPgetNSols(subscip); subsols = SCIPgetSols(subscip); soladded = FALSE; heurtrysol = SCIPfindHeur(scip, "trysol"); /* sequentially add solutions to trysol heuristic */ for( i = 0; i < nsubsols && !soladded; ++i ) { SCIPdebugMessage("Try to create new solution by copying subscip solution.\n"); SCIP_CALL( createNewSol(scip, subscip, subvars, heurtrysol, subsols[i], &soladded) ); } if( !soladded || !SCIPisEQ(scip, SCIPgetSolOrigObj(subscip, subsols[i-1]), SCIPgetSolOrigObj(subscip, subsols[0])) ) disabledualreductions = TRUE; } /* if the sub problem was solved completely, we update the dual bound */ dualboundchg = FALSE; if( sepadata->applysolved && !disabledualreductions && (SCIPgetStatus(subscip) == SCIP_STATUS_OPTIMAL || SCIPgetStatus(subscip) == SCIP_STATUS_INFEASIBLE) ) { /* we need to multiply the dualbound with the scaling factor and add the offset, * because this information has been disregarded in the sub-SCIP */ SCIPdebugMessage("Update old dualbound %g to new dualbound %g.\n", SCIPgetDualbound(scip), SCIPgetTransObjscale(scip) * SCIPgetDualbound(subscip) + SCIPgetTransObjoffset(scip)); SCIP_CALL( SCIPupdateLocalDualbound(scip, SCIPgetDualbound(subscip) * SCIPgetTransObjscale(scip) + SCIPgetTransObjoffset(scip)) ); dualboundchg = TRUE; } /* check, whether conflicts were created */ nconflicts = 0; if( sepadata->applyconflicts && !disabledualreductions && SCIPgetNConflictConssApplied(subscip) > 0 ) { SCIP_HASHMAP* consmap; int hashtablesize; assert(SCIPgetNConflictConssApplied(subscip) < (SCIP_Longint) INT_MAX); hashtablesize = (int) SCIPgetNConflictConssApplied(subscip); assert(hashtablesize < INT_MAX/5); hashtablesize *= 5; /* create the variable mapping hash map */ SCIP_CALL( SCIPhashmapCreate(&consmap, SCIPblkmem(scip), SCIPcalcHashtableSize(hashtablesize)) ); /* loop over all constraint handlers that might contain conflict constraints */ for( i = 0; i < nconshdlrs; ++i) { /* copy constraints that have been created in FD run */ if( conshdlrs[i] != NULL && SCIPconshdlrGetNConss(conshdlrs[i]) > oldnconss[i] ) { SCIP_CONS** conss; int c; int nconss; nconss = SCIPconshdlrGetNConss(conshdlrs[i]); conss = SCIPconshdlrGetConss(conshdlrs[i]); /* loop over all constraints that have been added in sub-SCIP run, these are the conflicts */ for( c = oldnconss[i]; c < nconss; ++c) { SCIP_CONS* cons; SCIP_CONS* conscopy; cons = conss[c]; assert(cons != NULL); success = FALSE; SCIP_CALL( SCIPgetConsCopy(subscip, scip, cons, &conscopy, conshdlrs[i], varmapbw, consmap, NULL, SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), TRUE, FALSE, SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons), FALSE, TRUE, &success) ); if( success ) { nconflicts++; SCIP_CALL( SCIPaddCons(scip, conscopy) ); SCIP_CALL( SCIPreleaseCons(scip, &conscopy) ); } else { SCIPdebugMessage("failed to copy conflict constraint %s back to original SCIP\n", SCIPconsGetName(cons)); } } } } SCIPhashmapFree(&consmap); } /* check, whether tighter global bounds were detected */ nbdchgs = 0; if( sepadata->applybdchgs && !disabledualreductions ) for( i = 0; i < nvars; ++i ) { SCIP_Bool infeasible; SCIP_Bool tightened; assert(SCIPisLE(scip, SCIPvarGetLbGlobal(vars[i]), SCIPvarGetLbGlobal(subvars[i]))); assert(SCIPisLE(scip, SCIPvarGetLbGlobal(subvars[i]), SCIPvarGetUbGlobal(subvars[i]))); assert(SCIPisLE(scip, SCIPvarGetUbGlobal(subvars[i]), SCIPvarGetUbGlobal(vars[i]))); /* update the bounds of the original SCIP, if a better bound was proven in the sub-SCIP */ SCIP_CALL( SCIPtightenVarUb(scip, vars[i], SCIPvarGetUbGlobal(subvars[i]), FALSE, &infeasible, &tightened) ); if( tightened ) nbdchgs++; SCIP_CALL( SCIPtightenVarLb(scip, vars[i], SCIPvarGetLbGlobal(subvars[i]), FALSE, &infeasible, &tightened) ); if( tightened ) nbdchgs++; } n1startinfers = 0; n2startinfers = 0; /* install start values for inference branching */ if( sepadata->applyinfervals && (!sepadata->reducedinfer || soladded || nbdchgs+nconflicts > 0) ) { for( i = 0; i < nvars; ++i ) { SCIP_Real downinfer; SCIP_Real upinfer; SCIP_Real downvsids; SCIP_Real upvsids; SCIP_Real downconflen; SCIP_Real upconflen; /* copy downwards branching statistics */ downvsids = SCIPgetVarVSIDS(subscip, subvars[i], SCIP_BRANCHDIR_DOWNWARDS); downconflen = SCIPgetVarAvgConflictlength(subscip, subvars[i], SCIP_BRANCHDIR_DOWNWARDS); downinfer = SCIPgetVarAvgInferences(subscip, subvars[i], SCIP_BRANCHDIR_DOWNWARDS); /* copy upwards branching statistics */ upvsids = SCIPgetVarVSIDS(subscip, subvars[i], SCIP_BRANCHDIR_UPWARDS); upconflen = SCIPgetVarAvgConflictlength(subscip, subvars[i], SCIP_BRANCHDIR_UPWARDS); upinfer = SCIPgetVarAvgInferences(subscip, subvars[i], SCIP_BRANCHDIR_UPWARDS); /* memorize statistics */ if( downinfer+downconflen+downvsids > 0.0 || upinfer+upconflen+upvsids != 0 ) n1startinfers++; if( downinfer+downconflen+downvsids > 0.0 && upinfer+upconflen+upvsids != 0 ) n2startinfers++; SCIP_CALL( SCIPinitVarBranchStats(scip, vars[i], 0.0, 0.0, downvsids, upvsids, downconflen, upconflen, downinfer, upinfer, 0.0, 0.0) ); } } SCIPdebugPrintf("XXX Rapidlearning added %d conflicts, changed %d bounds, %s primal solution, %s dual bound improvement.\n", nconflicts, nbdchgs, soladded ? "found" : "no", dualboundchg ? "found" : "no"); SCIPdebugPrintf("YYY Infervalues initialized on one side: %5.2f %% of variables, %5.2f %% on both sides\n", 100.0 * n1startinfers/(SCIP_Real)nvars, 100.0 * n2startinfers/(SCIP_Real)nvars); /* change result pointer */ if( nconflicts > 0 || dualboundchg ) *result = SCIP_CONSADDED; else if( nbdchgs > 0 ) *result = SCIP_REDUCEDDOM; /* free local data */ SCIPfreeBufferArray(scip, &oldnconss); SCIPfreeBufferArray(scip, &conshdlrs); SCIPhashmapFree(&varmapbw); TERMINATE: /* free subproblem */ SCIPfreeBufferArray(scip, &subvars); SCIP_CALL( SCIPfree(&subscip) ); return SCIP_OKAY; }
/** write the data optionally using the decomposition data */ static SCIP_RETCODE writeData( SCIP* scip, /**< SCIP data structure */ FILE* file, /**< File pointer to write to */ DEC_DECOMP* decdecomp /**< Decomposition pointer */ ) { SCIP_CONS*** subscipconss; SCIP_CONS** linkingconss; int* nsubscipconss; int nlinkingconss; int nblocks; SCIP_Bool presolved; int i; int j; assert(scip != NULL); assert(decdecomp != NULL); assert(DECdecompGetType(decdecomp) == DEC_DECTYPE_ARROWHEAD || DECdecompGetType(decdecomp) == DEC_DECTYPE_BORDERED || DECdecompGetType(decdecomp) == DEC_DECTYPE_DIAGONAL || DECdecompGetType(decdecomp) == DEC_DECTYPE_UNKNOWN || DECdecompGetType(decdecomp) == DEC_DECTYPE_STAIRCASE); SCIPdebugMessage("DEC_DECOMP Type: %s\n", DECgetStrType(DECdecompGetType(decdecomp))); /* if we don't have staicase, but something else, go through the blocks and create the indices */ /* subscip conss */ subscipconss = DECdecompGetSubscipconss(decdecomp); nsubscipconss = DECdecompGetNSubscipconss(decdecomp); assert(subscipconss != NULL); assert(nsubscipconss != NULL); /* linking cons */ linkingconss = DECdecompGetLinkingconss(decdecomp); nlinkingconss = DECdecompGetNLinkingconss(decdecomp); assert(nlinkingconss >= 0 && nlinkingconss < SCIPgetNConss(scip)); assert(linkingconss != NULL || nlinkingconss == 0 ); presolved = DECdecompGetPresolved(decdecomp); SCIPinfoMessage(scip, file, "PRESOLVED\n"); SCIPinfoMessage(scip, file, "%d\n", presolved ? 1 : 0); nblocks = DECdecompGetNBlocks(decdecomp); SCIPinfoMessage(scip, file, "NBLOCKS\n"); SCIPinfoMessage(scip, file, "%d\n", nblocks); for( i = 0; i < nblocks; i ++ ) { SCIPinfoMessage(scip, file, "BLOCK %d\n", i + 1); for( j = 0; j < nsubscipconss[i]; j ++ ) { SCIPinfoMessage(scip, file, "%s\n", SCIPconsGetName(subscipconss[i][j])); } } if( nlinkingconss > 0 ) { assert(linkingconss != NULL); /* for flexelint */ SCIPinfoMessage(scip, file, "MASTERCONSS\n"); for( i = 0; i < nlinkingconss; i ++ ) { SCIPinfoMessage(scip, file, "%s\n", SCIPconsGetName(linkingconss[i])); } } return SCIP_OKAY; }