/** reduced cost pricing method of variable pricer for feasible LPs */ static SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking) { /*lint --e{715}*/ SCIP* subscip; SCIP_PRICERDATA* pricerdata; SCIP_CONS** conss; SCIP_VAR** vars; int* ids; SCIP_Bool addvar; SCIP_SOL** sols; int nsols; int s; int nitems; SCIP_Longint capacity; SCIP_Real timelimit; SCIP_Real memorylimit; assert(scip != NULL); assert(pricer != NULL); (*result) = SCIP_DIDNOTRUN; /* get the pricer data */ pricerdata = SCIPpricerGetData(pricer); assert(pricerdata != NULL); capacity = pricerdata->capacity; conss = pricerdata->conss; ids = pricerdata->ids; nitems = pricerdata->nitems; /* get the remaining time and memory limit */ 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; /* initialize SCIP */ SCIP_CALL( SCIPcreate(&subscip) ); SCIP_CALL( SCIPincludeDefaultPlugins(subscip) ); /* create problem in sub SCIP */ SCIP_CALL( SCIPcreateProbBasic(subscip, "pricing") ); SCIP_CALL( SCIPsetObjsense(subscip, SCIP_OBJSENSE_MAXIMIZE) ); /* 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) ); /* set time and memory limit */ SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) ); SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) ); SCIP_CALL( SCIPallocMemoryArray(subscip, &vars, nitems) ); /* initialization local pricing problem */ SCIP_CALL( initPricing(scip, pricerdata, subscip, vars) ); SCIPdebugMessage("solve pricer problem\n"); /* solve sub SCIP */ SCIP_CALL( SCIPsolve(subscip) ); sols = SCIPgetSols(subscip); nsols = SCIPgetNSols(subscip); addvar = FALSE; /* loop over all solutions and create the corresponding column to master if the reduced cost are negative for master, * that is the objective value i greater than 1.0 */ for( s = 0; s < nsols; ++s ) { SCIP_Bool feasible; SCIP_SOL* sol; /* the soultion should be sorted w.r.t. the objective function value */ assert(s == 0 || SCIPisFeasGE(subscip, SCIPgetSolOrigObj(subscip, sols[s-1]), SCIPgetSolOrigObj(subscip, sols[s]))); sol = sols[s]; assert(sol != NULL); /* check if solution is feasible in original sub SCIP */ SCIP_CALL( SCIPcheckSolOrig(subscip, sol, &feasible, FALSE, FALSE ) ); if( !feasible ) { SCIPwarningMessage(scip, "solution in pricing problem (capacity <%d>) is infeasible\n", capacity); continue; } /* check if the solution has a value greater than 1.0 */ if( SCIPisFeasGT(subscip, SCIPgetSolOrigObj(subscip, sol), 1.0) ) { SCIP_VAR* var; SCIP_VARDATA* vardata; int* consids; char strtmp[SCIP_MAXSTRLEN]; char name[SCIP_MAXSTRLEN]; int nconss; int o; int v; SCIPdebug( SCIP_CALL( SCIPprintSol(subscip, sol, NULL, FALSE) ) ); nconss = 0; (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "items"); SCIP_CALL( SCIPallocBufferArray(scip, &consids, nitems) ); /* check which variables are fixed -> which item belongs to this packing */ for( o = 0, v = 0; o < nitems; ++o ) { if( !SCIPconsIsEnabled(conss[o]) ) continue; assert(SCIPgetNFixedonesSetppc(scip, conss[o]) == 0); if( SCIPgetSolVal(subscip, sol, vars[v]) > 0.5 ) { (void) SCIPsnprintf(strtmp, SCIP_MAXSTRLEN, "_%d", ids[o]); strcat(name, strtmp); consids[nconss] = o; nconss++; } else assert( SCIPisFeasEQ(subscip, SCIPgetSolVal(subscip, sol, vars[v]), 0.0) ); v++; } SCIP_CALL( SCIPvardataCreateBinpacking(scip, &vardata, consids, nconss) ); /* create variable for a new column with objective function coefficient 0.0 */ SCIP_CALL( SCIPcreateVarBinpacking(scip, &var, name, 1.0, FALSE, TRUE, vardata) ); /* add the new variable to the pricer store */ SCIP_CALL( SCIPaddPricedVar(scip, var, 1.0) ); addvar = TRUE; /* change the upper bound of the binary variable to lazy since the upper bound is already enforced due to * the objective function the set covering constraint; The reason for doing is that, is to avoid the bound * of x <= 1 in the LP relaxation since this bound constraint would produce a dual variable which might have * a positive reduced cost */ SCIP_CALL( SCIPchgVarUbLazy(scip, var, 1.0) ); /* check which variable are fixed -> which orders belong to this packing */ for( v = 0; v < nconss; ++v ) { assert(SCIPconsIsEnabled(conss[consids[v]])); SCIP_CALL( SCIPaddCoefSetppc(scip, conss[consids[v]], var) ); } SCIPdebug(SCIPprintVar(scip, var, NULL) ); SCIP_CALL( SCIPreleaseVar(scip, &var) ); SCIPfreeBufferArray(scip, &consids); } else break; } /* free pricer MIP */ SCIPfreeMemoryArray(subscip, &vars); if( addvar || SCIPgetStatus(subscip) == SCIP_STATUS_OPTIMAL ) (*result) = SCIP_SUCCESS; /* free sub SCIP */ SCIP_CALL( SCIPfree(&subscip) ); return SCIP_OKAY; }
/** execution method of primal heuristic */ static SCIP_DECL_HEUREXEC(heurExecReoptsols) {/*lint --e{715}*/ SCIP_HEURDATA* heurdata; SCIP_SOL** sols; SCIP_Real objsimsol; SCIP_Bool sepabestsol; int allocmem; int nchecksols; int nsolsadded; #ifdef SCIP_MORE_DEBUG int nsolsaddedrun; #endif int run; int max_run; assert(heur != NULL); assert(scip != NULL); *result = SCIP_DIDNOTRUN; if( !SCIPisReoptEnabled(scip) ) return SCIP_OKAY; heurdata = SCIPheurGetData(heur); assert(heurdata != NULL); max_run = heurdata->maxruns == -1 ? 0 : MAX(0, SCIPgetNReoptRuns(scip)-1-heurdata->maxruns); /*lint !e666*/ nchecksols = heurdata->maxsols == -1 ? INT_MAX : heurdata->maxsols; SCIP_CALL( SCIPgetRealParam(scip, "reoptimization/objsimsol", &objsimsol) ); SCIP_CALL( SCIPgetBoolParam(scip, "reoptimization/sepabestsol", &sepabestsol) ); /* allocate a buffer array to store the solutions */ allocmem = 20; SCIP_CALL( SCIPallocBufferArray(scip, &sols, allocmem) ); nsolsadded = 0; for( run = SCIPgetNReoptRuns(scip); run > max_run && nchecksols > 0; run-- ) { SCIP_Real sim; int nsols; #ifdef SCIP_MORE_DEBUG nsolsaddedrun = 0; #endif nsols = 0; if( objsimsol == -1 ) sim = 1; else sim = SCIPgetReoptSimilarity(scip, run, SCIPgetNReoptRuns(scip)-1); if( sim >= objsimsol ) { int s; /* get solutions of a specific run */ SCIP_CALL( SCIPgetReopSolsRun(scip, run, sols, allocmem, &nsols) ); /* check memory and reallocate */ if( nsols > allocmem ) { allocmem = nsols; SCIP_CALL( SCIPreallocBufferArray(scip, &sols, allocmem) ); SCIP_CALL( SCIPgetReopSolsRun(scip, run, sols, allocmem, &nsols) ); } assert(nsols <= allocmem); /* update the solutions * stop, if the maximal number of solutions to be checked is reached */ for( s = 0; s < nsols && nchecksols > 0; s++ ) { SCIP_SOL* sol; SCIP_Real objsol; sol = sols[s]; SCIP_CALL( SCIPrecomputeSolObj(scip, sol) ); objsol = SCIPgetSolTransObj(scip, sol); /* we do not want to add solutions with objective value +infinity. * moreover, the solution should improve the current primal bound */ if( !SCIPisInfinity(scip, objsol) && !SCIPisInfinity(scip, -objsol) && SCIPisFeasLT(scip, objsol, SCIPgetCutoffbound(scip)) ) { SCIP_Bool stored; SCIP_Bool feasible; if( sepabestsol ) { SCIP_CALL( SCIPcheckSolOrig(scip, sol, &feasible, FALSE, TRUE) ); } else feasible = TRUE; if( feasible) { /* create a new solution */ SCIP_CALL( createNewSol(scip, heur, sol, &stored) ); if( stored ) { nsolsadded++; #ifdef SCIP_MORE_DEBUG nsolsaddedrun++; #endif heurdata->nimprovingsols++; } } } nchecksols--; heurdata->ncheckedsols++; } } #ifdef SCIP_MORE_DEBUG printf(">> heuristic <%s> found %d of %d improving solutions from run %d.\n", HEUR_NAME, nsolsaddedrun, nsols, run); #endif } SCIPdebugMessage(">> heuristic <%s> found %d improving solutions.\n", HEUR_NAME, nsolsadded); if( nsolsadded > 0 ) *result = SCIP_FOUNDSOL; else *result = SCIP_DIDNOTFIND; /* reset the marks of the checked solutions */ SCIPresetReoptSolMarks(scip); /* free the buffer array */ SCIPfreeBufferArray(scip, &sols); return SCIP_OKAY; }