/** free heuristic data */ static SCIP_RETCODE heurdataFreeArrays( SCIP* scip, /**< SCIP data structure */ SCIP_HEURDATA* heurdata /**< heuristic data */ ) { assert(heurdata->memsize == 0 || heurdata->rowmeans != NULL); assert(heurdata->memsize >= 0); if( heurdata->memsize > 0 ) { SCIPfreeBufferArray(scip, &heurdata->rowmeans); SCIPfreeBufferArray(scip, &heurdata->rowvariances); SCIPfreeBufferArray(scip, &heurdata->rowinfinitiesup); SCIPfreeBufferArray(scip, &heurdata->rowinfinitiesdown); heurdata->memsize = 0; } if( heurdata->varpossmemsize > 0 ) { SCIP_VAR** vars; int v; assert(heurdata->varpossmemsize == SCIPgetNVars(scip)); vars = SCIPgetVars(scip); for( v = heurdata->varpossmemsize - 1; v >= 0; --v ) { SCIP_VAR* var; var = vars[v]; assert(var != NULL); assert(v == SCIPvarGetProbindex(var)); SCIP_CALL( SCIPdropVarEvent(scip, var, EVENT_DISTRIBUTION, heurdata->eventhdlr, NULL, heurdata->varfilterposs[v]) ); } SCIPfreeBufferArray(scip, &heurdata->currentlbs); SCIPfreeBufferArray(scip, &heurdata->currentubs); SCIPfreeBufferArray(scip, &heurdata->updatedvars); SCIPfreeBufferArray(scip, &heurdata->varposs); SCIPfreeBufferArray(scip, &heurdata->varfilterposs); } /* allocate variable update event processing array storage */ heurdata->varpossmemsize = 0; heurdata->nupdatedvars = 0; return SCIP_OKAY; }
/** generate point for close cut separation * * The constructed point is the convex combination of the point stored in set->closesol and the * current LP solution. The convexity parameter is set->sepa_closecombvalue. If this parameter is * 0, the point coincides with the LP solution. */ static SCIP_RETCODE generateCloseCutPoint( SCIP* scip, /**< SCIP data structure */ SCIP_SEPADATA* sepadata, /**< separator data */ SCIP_SOL** point /**< point to be generated (or NULL if unsuccessful) */ ) { SCIP_VAR** vars; SCIP_VAR* var; SCIP_Real val; SCIP_Real alpha; SCIP_Real onealpha; int nvars; int i; assert( scip != NULL ); assert( point != NULL ); *point = NULL; if ( sepadata->sepasol == NULL ) return SCIP_OKAY; alpha = sepadata->sepacombvalue; if ( alpha < 0.001 ) return SCIP_OKAY; onealpha = 1.0 - alpha; /* create solution */ SCIP_CALL( SCIPcreateSol(scip, point, NULL) ); /* generate convex combination */ vars = SCIPgetVars(scip); nvars = SCIPgetNVars(scip); for (i = 0; i < nvars; ++i) { var = vars[i]; val = alpha * SCIPgetSolVal(scip, sepadata->sepasol, var) + onealpha * SCIPvarGetLPSol(var); if ( ! SCIPisZero(scip, val) ) { SCIP_CALL( SCIPsetSolVal(scip, *point, var, val) ); } } return SCIP_OKAY; }
/** reads the objective section */ static SCIP_RETCODE readObjective( SCIP* scip, /**< SCIP data structure */ LPINPUT* lpinput /**< LP reading data */ ) { char name[LP_MAX_LINELEN]; SCIP_VAR** vars; SCIP_Real* coefs; int ncoefs; SCIP_Bool newsection; assert(lpinput != NULL); /* read the objective coefficients */ SCIP_CALL( readCoefficients(scip, lpinput, TRUE, name, &vars, &coefs, &ncoefs, &newsection) ); if( !hasError(lpinput) ) { int i; SCIP_VAR** oldvars; /* set all linear coefficients to 0 */ oldvars = SCIPgetVars(scip); for( i = 0; i < SCIPgetNVars(scip); i++ ) { SCIP_CALL( SCIPchgVarObj(scip, oldvars[i], 0.0) ); } /* set the linear objective values */ for( i = 0; i < ncoefs; ++i ) { SCIP_CALL( SCIPchgVarObj(scip, vars[i], coefs[i]) ); } } /* free memory */ SCIPfreeMemoryArrayNull(scip, &vars); SCIPfreeMemoryArrayNull(scip, &coefs); return SCIP_OKAY; }
/** presolving execution method */ static SCIP_DECL_PRESOLEXEC(presolExecInttobinary) { /*lint --e{715}*/ SCIP_VAR** scipvars; SCIP_VAR** vars; int nbinvars; int nintvars; int v; assert(result != NULL); *result = SCIP_DIDNOTRUN; if( SCIPdoNotAggr(scip) ) return SCIP_OKAY; /* get the problem variables */ scipvars = SCIPgetVars(scip); nbinvars = SCIPgetNBinVars(scip); nintvars = SCIPgetNIntVars(scip); if( nintvars == 0 ) return SCIP_OKAY; *result = SCIP_DIDNOTFIND; /* copy the integer variables into an own array, since adding binary variables affects the left-most slots in the * array and thereby interferes with our search loop */ SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &scipvars[nbinvars], nintvars) ); /* scan the integer variables for possible conversion into binaries; * we have to collect the variables first in an own */ for( v = 0; v < nintvars; ++v ) { SCIP_Real lb; SCIP_Real ub; assert(SCIPvarGetType(vars[v]) == SCIP_VARTYPE_INTEGER); /* get variable's bounds */ lb = SCIPvarGetLbGlobal(vars[v]); ub = SCIPvarGetUbGlobal(vars[v]); /* check if bounds are exactly one apart */ if( SCIPisEQ(scip, lb, ub - 1.0) ) { SCIP_VAR* binvar; char binvarname[SCIP_MAXSTRLEN]; SCIP_Bool infeasible; SCIP_Bool redundant; SCIP_Bool aggregated; SCIPdebugMessage("converting <%s>[%g,%g] into binary variable\n", SCIPvarGetName(vars[v]), lb, ub); /* create binary variable */ (void) SCIPsnprintf(binvarname, SCIP_MAXSTRLEN, "%s_bin", SCIPvarGetName(vars[v])); SCIP_CALL( SCIPcreateVar(scip, &binvar, binvarname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY, SCIPvarIsInitial(vars[v]), SCIPvarIsRemovable(vars[v]), NULL, NULL, NULL, NULL, NULL) ); SCIP_CALL( SCIPaddVar(scip, binvar) ); /* aggregate integer and binary variable */ SCIP_CALL( SCIPaggregateVars(scip, vars[v], binvar, 1.0, -1.0, lb, &infeasible, &redundant, &aggregated) ); /* release binary variable */ SCIP_CALL( SCIPreleaseVar(scip, &binvar) ); /* it can be the case that this aggregation detects an infeasibility; for example, during the copy of the * variable bounds from the integer variable to the binary variable, infeasibility can be detected; this can * happen because an upper bound or a lower bound of such a variable bound variable was "just" changed and the * varbound constraint handler, who would detect that infeasibility (since it was creating it from a varbound * constraint), was called before that bound change was detected due to the presolving priorities; */ if( infeasible ) { *result = SCIP_CUTOFF; break; } assert(redundant); assert(aggregated); (*nchgvartypes)++; *result = SCIP_SUCCESS; } } /* free temporary memory */ SCIPfreeBufferArray(scip, &vars); return SCIP_OKAY; }
/** perform dual presolving */ static SCIP_RETCODE performDualfix( SCIP* scip, /**< SCIP data structure */ int* nfixedvars, /**< pointer to store number of fixed variables */ SCIP_Bool* unbounded, /**< pointer to store if an unboundness was detected */ SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */ ) { SCIP_VAR** vars; int nvars; int v; /* get active problem variables */ vars = SCIPgetVars(scip); nvars = SCIPgetNVars(scip); /* look for fixable variables * loop backwards, since a variable fixing can change the current and the subsequent slots in the vars array */ for( v = nvars - 1; v >= 0; --v ) { SCIP_VAR* var; SCIP_Real bound; SCIP_Real obj; SCIP_Bool infeasible; SCIP_Bool fixed; var = vars[v]; assert(var != NULL); /* don't perform dual presolving operations on deleted variables */ if( SCIPvarIsDeleted(var) ) continue; /* ignore already fixed variables (use feasibility tolerance since this is used in SCIPfixVar() */ if( SCIPisFeasEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) ) continue; obj = SCIPvarGetObj(var); /* if the objective coefficient of the variable is 0 and it may be rounded both * up and down, then fix it to the closest feasible value to 0 */ if( SCIPisZero(scip, obj) && SCIPvarMayRoundDown(var) && SCIPvarMayRoundUp(var) ) { SCIP_Real roundbound; bound = SCIPvarGetLbGlobal(var); if( SCIPisLT(scip, bound, 0.0) ) { if( SCIPisLE(scip, 0.0, SCIPvarGetUbGlobal(var)) ) bound = 0.0; else { /* try to take an integer value, only for polishing */ roundbound = SCIPfloor(scip, SCIPvarGetUbGlobal(var)); if( roundbound < bound ) bound = SCIPvarGetUbGlobal(var); else bound = roundbound; } } else { /* try to take an integer value, only for polishing */ roundbound = SCIPceil(scip, bound); if( roundbound < SCIPvarGetUbGlobal(var) ) bound = roundbound; } SCIPdebugMessage("fixing variable <%s> with objective 0 to %g\n", SCIPvarGetName(var), bound); } else { /* if it is always possible to round variable in direction of objective value, fix it to its proper bound */ if( SCIPvarMayRoundDown(var) && !SCIPisNegative(scip, obj) ) { bound = SCIPvarGetLbGlobal(var); if ( SCIPisInfinity(scip, -bound) ) { /* variable can be fixed to -infinity */ if ( SCIPgetStage(scip) > SCIP_STAGE_PRESOLVING ) { /* Fixing variables to infinity is not allowed after presolving, since LP-solvers cannot handle this * consistently. We thus have to ignore this (should better be handled in presolving). */ continue; } if ( SCIPisZero(scip, obj) && SCIPvarGetNLocksUp(var) == 1 ) { /* Variable is only contained in one constraint: we hope that the corresponding constraint handler is * clever enough to set/aggregate the variable to something more useful than -infinity and do nothing * here. */ continue; } } SCIPdebugMessage("fixing variable <%s> with objective %g and %d uplocks to lower bound %g\n", SCIPvarGetName(var), SCIPvarGetObj(var), SCIPvarGetNLocksUp(var), bound); } else if( SCIPvarMayRoundUp(var) && !SCIPisPositive(scip, obj) ) { bound = SCIPvarGetUbGlobal(var); if ( SCIPisInfinity(scip, bound) ) { /* variable can be fixed to infinity */ if ( SCIPgetStage(scip) > SCIP_STAGE_PRESOLVING ) { /* Fixing variables to infinity is not allowed after presolving, since LP-solvers cannot handle this * consistently. We thus have to ignore this (should better be handled in presolving). */ continue; } if ( SCIPisZero(scip, obj) && SCIPvarGetNLocksDown(var) == 1 ) { /* Variable is only contained in one constraint: we hope that the corresponding constraint handler is * clever enough to set/aggregate the variable to something more useful than +infinity and do nothing * here */ continue; } } SCIPdebugMessage("fixing variable <%s> with objective %g and %d downlocks to upper bound %g\n", SCIPvarGetName(var), SCIPvarGetObj(var), SCIPvarGetNLocksDown(var), bound); } else continue; } if( SCIPisInfinity(scip, REALABS(bound)) && !SCIPisZero(scip, obj) ) { SCIPdebugMessage(" -> unbounded fixing\n"); SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "problem infeasible or unbounded: variable <%s> with objective %.15g can be made infinitely %s\n", SCIPvarGetName(var), SCIPvarGetObj(var), bound < 0.0 ? "small" : "large"); *unbounded = TRUE; return SCIP_OKAY; } /* apply the fixing */ SCIPdebugMessage("apply fixing of variable %s to %g\n", SCIPvarGetName(var), bound); SCIP_CALL( SCIPfixVar(scip, var, bound, &infeasible, &fixed) ); if( infeasible ) { SCIPdebugMessage(" -> infeasible fixing\n"); *cutoff = TRUE; return SCIP_OKAY; } assert(fixed || (SCIPgetStage(scip) == SCIP_STAGE_SOLVING && SCIPisFeasEQ(scip, bound, SCIPvarGetLbLocal(var)) && SCIPisFeasEQ(scip, bound, SCIPvarGetUbLocal(var)))); (*nfixedvars)++; } return SCIP_OKAY; }
/** execution method of presolver */ static SCIP_DECL_PRESOLEXEC(presolExecDualfix) { /*lint --e{715}*/ SCIP_VAR** vars; SCIP_Real bound; SCIP_Real roundbound; SCIP_Real obj; SCIP_Bool infeasible; SCIP_Bool fixed; int nvars; int v; assert(presol != NULL); assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0); assert(result != NULL); *result = SCIP_DIDNOTFIND; /* get active problem variables */ vars = SCIPgetVars(scip); nvars = SCIPgetNVars(scip); /* look for fixable variables * loop backwards, since a variable fixing can change the current and the subsequent slots in the vars array */ for( v = nvars - 1; v >= 0; --v ) { /* don't perform dual presolving operations on deleted variables */ if( SCIPvarIsDeleted(vars[v]) ) continue; obj = SCIPvarGetObj(vars[v]); /* if the objective coefficient of the variable is 0 and it may be rounded both * up and down, then fix it to the closest feasible value to 0 */ if( SCIPisZero(scip, obj) && SCIPvarMayRoundDown(vars[v]) && SCIPvarMayRoundUp(vars[v]) ) { bound = SCIPvarGetLbGlobal(vars[v]); if( SCIPisLT(scip, bound, 0.0) ) { if( SCIPisLE(scip, 0.0, SCIPvarGetUbGlobal(vars[v])) ) bound = 0.0; else { /* try to take an integer value, only for polishing */ roundbound = SCIPfloor(scip, SCIPvarGetUbGlobal(vars[v])); if( roundbound < bound ) bound = SCIPvarGetUbGlobal(vars[v]); else bound = roundbound; } } else { /* try to take an integer value, only for polishing */ roundbound = SCIPceil(scip, bound); if( roundbound < SCIPvarGetUbGlobal(vars[v]) ) bound = roundbound; } SCIPdebugMessage("variable <%s> with objective 0 fixed to %g\n", SCIPvarGetName(vars[v]), bound); } else { /* if it is always possible to round variable in direction of objective value, * fix it to its proper bound */ if( SCIPvarMayRoundDown(vars[v]) && !SCIPisNegative(scip, obj) ) { bound = SCIPvarGetLbGlobal(vars[v]); if( SCIPisZero(scip, obj) && SCIPvarGetNLocksUp(vars[v]) == 1 && SCIPisInfinity(scip, -bound) ) { /* variable can be set to -infinity, and it is only contained in one constraint: * we hope that the corresponding constraint handler is clever enough to set/aggregate the variable * to something more useful than -infinity and do nothing here */ continue; } SCIPdebugMessage("variable <%s> with objective %g and %d uplocks fixed to lower bound %g\n", SCIPvarGetName(vars[v]), SCIPvarGetObj(vars[v]), SCIPvarGetNLocksUp(vars[v]), bound); } else if( SCIPvarMayRoundUp(vars[v]) && !SCIPisPositive(scip, obj) ) { bound = SCIPvarGetUbGlobal(vars[v]); if( SCIPisZero(scip, obj) && SCIPvarGetNLocksDown(vars[v]) == 1 && SCIPisInfinity(scip, bound) ) { /* variable can be set to +infinity, and it is only contained in one constraint: * we hope that the corresponding constraint handler is clever enough to set/aggregate the variable * to something more useful than +infinity and do nothing here */ continue; } SCIPdebugMessage("variable <%s> with objective %g and %d downlocks fixed to upper bound %g\n", SCIPvarGetName(vars[v]), SCIPvarGetObj(vars[v]), SCIPvarGetNLocksDown(vars[v]), bound); } else continue; } /* apply the fixing */ if( SCIPisInfinity(scip, REALABS(bound)) && !SCIPisZero(scip, obj) ) { SCIPdebugMessage(" -> unbounded fixing\n"); SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "problem infeasible or unbounded: variable <%s> with objective %.15g can be made infinitely %s\n", SCIPvarGetName(vars[v]), SCIPvarGetObj(vars[v]), bound < 0.0 ? "small" : "large"); *result = SCIP_UNBOUNDED; return SCIP_OKAY; } SCIP_CALL( SCIPfixVar(scip, vars[v], bound, &infeasible, &fixed) ); if( infeasible ) { SCIPdebugMessage(" -> infeasible fixing\n"); *result = SCIP_CUTOFF; return SCIP_OKAY; } assert(fixed); (*nfixedvars)++; *result = SCIP_SUCCESS; } return SCIP_OKAY; }
/** presolving execution method */ static SCIP_DECL_PRESOLEXEC(presolExecBoundshift) { /*lint --e{715}*/ SCIP_PRESOLDATA* presoldata; SCIP_VAR** scipvars; SCIP_VAR** vars; int nbinvars; int nvars; int v; assert(scip != NULL); assert(presol != NULL); assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0); assert(result != NULL); *result = SCIP_DIDNOTRUN; /* get presolver data */ presoldata = SCIPpresolGetData(presol); assert(presoldata != NULL); /* get the problem variables */ scipvars = SCIPgetVars(scip); nbinvars = SCIPgetNBinVars(scip); nvars = SCIPgetNVars(scip) - nbinvars; if( nvars == 0 ) return SCIP_OKAY; if( SCIPdoNotAggr(scip) ) return SCIP_OKAY; *result = SCIP_DIDNOTFIND; /* copy the integer variables into an own array, since adding new integer variables affects the left-most slots in * the array and thereby interferes with our search loop */ SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &scipvars[nbinvars], nvars) ); /* scan the integer, implicit, and continuous variables for possible conversion */ for( v = nvars - 1; v >= 0; --v ) { SCIP_VAR* var = vars[v]; SCIP_Real lb; SCIP_Real ub; assert(SCIPvarGetType(var) != SCIP_VARTYPE_BINARY); /* get current variable's bounds */ lb = SCIPvarGetLbGlobal(var); ub = SCIPvarGetUbGlobal(var); assert( SCIPisLE(scip, lb, ub) ); if( SCIPisEQ(scip, lb, ub) ) continue; if( presoldata->integer && !SCIPisIntegral(scip, ub - lb) ) continue; /* check if bounds are shiftable */ if( !SCIPisEQ(scip, lb, 0.0) && /* lower bound != 0.0 */ SCIPisLT(scip, ub, SCIPinfinity(scip)) && /* upper bound != infinity */ SCIPisGT(scip, lb, -SCIPinfinity(scip)) && /* lower bound != -infinity */ #if 0 SCIPisLT(scip, ub - lb, SCIPinfinity(scip)) && /* interval length less than SCIPinfinity(scip) */ #endif SCIPisLT(scip, ub - lb, (SCIP_Real) presoldata->maxshift) ) /* less than max shifting */ { SCIP_VAR* newvar; char newvarname[SCIP_MAXSTRLEN]; SCIP_Bool infeasible; SCIP_Bool redundant; SCIP_Bool aggregated; SCIPdebugMessage("convert range <%s>[%g,%g] to [%g,%g]\n", SCIPvarGetName(var), lb, ub, 0.0, (ub - lb) ); /* create new variable */ (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_shift", SCIPvarGetName(var)); SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, 0.0, (ub - lb), 0.0, SCIPvarGetType(var), SCIPvarIsInitial(var), SCIPvarIsRemovable(var), NULL, NULL, NULL, NULL, NULL) ); SCIP_CALL( SCIPaddVar(scip, newvar) ); /* aggregate old variable with new variable */ if( presoldata->flipping ) { if( REALABS(ub) < REALABS(lb) ) { SCIP_CALL( SCIPaggregateVars(scip, var, newvar, 1.0, 1.0, ub, &infeasible, &redundant, &aggregated) ); } else { SCIP_CALL( SCIPaggregateVars(scip, var, newvar, 1.0, -1.0, lb, &infeasible, &redundant, &aggregated) ); } } else { SCIP_CALL( SCIPaggregateVars(scip, var, newvar, 1.0, -1.0, lb, &infeasible, &redundant, &aggregated) ); } assert(!infeasible); assert(redundant); assert(aggregated); SCIPdebugMessage("var <%s> with bounds [%f,%f] has obj %f\n", SCIPvarGetName(newvar),SCIPvarGetLbGlobal(newvar),SCIPvarGetUbGlobal(newvar),SCIPvarGetObj(newvar)); /* release variable */ SCIP_CALL( SCIPreleaseVar(scip, &newvar) ); /* take care of statistic */ (*naggrvars)++; *result = SCIP_SUCCESS; } } /* free temporary memory */ SCIPfreeBufferArray(scip, &vars); 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; }
/** presolving execution method */ static SCIP_DECL_PRESOLEXEC(presolExecTrivial) { /*lint --e{715}*/ SCIP_VAR** vars; int nvars; int v; assert(result != NULL); *result = SCIP_DIDNOTFIND; /* get the problem variables */ vars = SCIPgetVars(scip); nvars = SCIPgetNVars(scip); /* scan the variables for trivial bound reductions * (loop backwards, since a variable fixing can change the current and the subsequent slots in the vars array) */ for( v = nvars-1; v >= 0; --v ) { SCIP_Real lb; SCIP_Real ub; SCIP_Bool infeasible; SCIP_Bool fixed; /* get variable's bounds */ lb = SCIPvarGetLbGlobal(vars[v]); ub = SCIPvarGetUbGlobal(vars[v]); /* is variable integral? */ if( SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS ) { SCIP_Real newlb; SCIP_Real newub; /* round fractional bounds on integer variables */ newlb = SCIPfeasCeil(scip, lb); newub = SCIPfeasFloor(scip, ub); /* check bounds on variable for infeasibility */ if( newlb > newub + 0.5 ) { SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "problem infeasible: integral variable <%s> has bounds [%.17f,%.17f] rounded to [%.17f,%.17f]\n", SCIPvarGetName(vars[v]), lb, ub, newlb, newub); *result = SCIP_CUTOFF; return SCIP_OKAY; } /* fix variables with equal bounds */ if( newlb > newub - 0.5 ) { SCIPdebugMessage("fixing integral variable <%s>: [%.17f,%.17f] -> [%.17f,%.17f]\n", SCIPvarGetName(vars[v]), lb, ub, newlb, newub); SCIP_CALL( SCIPfixVar(scip, vars[v], newlb, &infeasible, &fixed) ); if( infeasible ) { SCIPdebugMessage(" -> infeasible fixing\n"); *result = SCIP_CUTOFF; return SCIP_OKAY; } assert(fixed); (*nfixedvars)++; } else { /* round fractional bounds */ if( !SCIPisFeasEQ(scip, lb, newlb) ) { SCIPdebugMessage("rounding lower bound of integral variable <%s>: [%.17f,%.17f] -> [%.17f,%.17f]\n", SCIPvarGetName(vars[v]), lb, ub, newlb, ub); SCIP_CALL( SCIPchgVarLb(scip, vars[v], newlb) ); (*nchgbds)++; } if( !SCIPisFeasEQ(scip, ub, newub) ) { SCIPdebugMessage("rounding upper bound of integral variable <%s>: [%.17f,%.17f] -> [%.17f,%.17f]\n", SCIPvarGetName(vars[v]), newlb, ub, newlb, newub); SCIP_CALL( SCIPchgVarUb(scip, vars[v], newub) ); (*nchgbds)++; } } } else { /* check bounds on continuous variable for infeasibility */ if( SCIPisFeasGT(scip, lb, ub) ) { SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "problem infeasible: continuous variable <%s> has bounds [%.17f,%.17f]\n", SCIPvarGetName(vars[v]), lb, ub); *result = SCIP_CUTOFF; return SCIP_OKAY; } /* fix variables with equal bounds */ if( SCIPisEQ(scip, lb, ub) ) { SCIP_Real fixval; #ifdef FIXSIMPLEVALUE fixval = SCIPselectSimpleValue(lb - 0.9 * SCIPepsilon(scip), ub + 0.9 * SCIPepsilon(scip), MAXDNOM); #else fixval = (lb + ub)/2; #endif SCIPdebugMessage("fixing continuous variable <%s>[%.17f,%.17f] to %.17f\n", SCIPvarGetName(vars[v]), lb, ub, fixval); SCIP_CALL( SCIPfixVar(scip, vars[v], fixval, &infeasible, &fixed) ); if( infeasible ) { SCIPdebugMessage(" -> infeasible fixing\n"); *result = SCIP_CUTOFF; return SCIP_OKAY; } assert(fixed); (*nfixedvars)++; } } } return SCIP_OKAY; }
/** avoid to generate columns which are fixed to zero; therefore add for each variable which is fixed to zero a * corresponding logicor constraint to forbid this column * * @note variable which are fixed locally to zero should not be generated again by the pricing MIP */ static SCIP_RETCODE addFixedVarsConss( SCIP* scip, /**< SCIP data structure */ SCIP* subscip, /**< pricing SCIP data structure */ SCIP_VAR** vars, /**< variable array of the subscuip */ SCIP_CONS** conss, /**< array of setppc constraint for each item one */ int nitems /**< number of items */ ) { SCIP_VAR** origvars; int norigvars; SCIP_CONS* cons; int* consids; int nconsids; int consid; int nvars; SCIP_VAR** logicorvars; SCIP_VAR* var; SCIP_VARDATA* vardata; SCIP_Bool needed; int nlogicorvars; int v; int c; int o; /* collect all variable which are currently existing */ origvars = SCIPgetVars(scip); norigvars = SCIPgetNVars(scip); /* loop over all these variables and check if they are fixed to zero */ for( v = 0; v < norigvars; ++v ) { assert(SCIPvarGetType(origvars[v]) == SCIP_VARTYPE_BINARY); /* if the upper bound is smaller than 0.5 if follows due to the integrality that the binary variable is fixed to zero */ if( SCIPvarGetUbLocal(origvars[v]) < 0.5 ) { SCIPdebugMessage("variable <%s> glb=[%.15g,%.15g] loc=[%.15g,%.15g] is fixed to zero\n", SCIPvarGetName(origvars[v]), SCIPvarGetLbGlobal(origvars[v]), SCIPvarGetUbGlobal(origvars[v]), SCIPvarGetLbLocal(origvars[v]), SCIPvarGetUbLocal(origvars[v]) ); /* coolect the constraints/items the variable belongs to */ vardata = SCIPvarGetData(origvars[v]); nconsids = SCIPvardataGetNConsids(vardata); consids = SCIPvardataGetConsids(vardata); needed = TRUE; SCIP_CALL( SCIPallocBufferArray(subscip, &logicorvars, nitems) ); nlogicorvars = 0; consid = consids[0]; nvars = 0; /* loop over these items and create a linear (logicor) constraint which forbids this item combination in the * pricing problem; thereby check if this item combination is already forbidden */ for( c = 0, o = 0; o < nitems && needed; ++o ) { assert(o <= consid); cons = conss[o]; if( SCIPconsIsEnabled(cons) ) { assert( SCIPgetNFixedonesSetppc(scip, cons) == 0 ); var = vars[nvars]; nvars++; assert(var != NULL); if( o == consid ) { SCIP_CALL( SCIPgetNegatedVar(subscip, var, &var) ); } logicorvars[nlogicorvars] = var; nlogicorvars++; } else if( o == consid ) needed = FALSE; if( o == consid ) { c++; if ( c == nconsids ) consid = nitems + 100; else { assert(consid < consids[c]); consid = consids[c]; } } } if( needed ) { SCIP_CALL( SCIPcreateConsBasicLogicor(subscip, &cons, SCIPvarGetName(origvars[v]), nlogicorvars, logicorvars) ); SCIP_CALL( SCIPsetConsInitial(subscip, cons, FALSE) ); SCIP_CALL( SCIPaddCons(subscip, cons) ); SCIP_CALL( SCIPreleaseCons(subscip, &cons) ); } SCIPfreeBufferArray(subscip, &logicorvars); } } return SCIP_OKAY; }
/** execution method of primal heuristic */ static SCIP_DECL_HEUREXEC(heurExecSimplerounding) /*lint --e{715}*/ { /*lint --e{715}*/ SCIP_HEURDATA* heurdata; SCIP_SOL* sol; SCIP_VAR** lpcands; SCIP_Real* lpcandssol; SCIP_Longint nlps; int nlpcands; int c; assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0); assert(result != NULL); assert(SCIPhasCurrentNodeLP(scip)); *result = SCIP_DIDNOTRUN; /* only call heuristic, if an optimal LP solution is at hand */ if( SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL ) return SCIP_OKAY; /* get heuristic data */ heurdata = SCIPheurGetData(heur); assert(heurdata != NULL); /* on our first call or after each pricing round, calculate the number of roundable variables */ if( heurdata->nroundablevars == -1 || heurtiming == SCIP_HEURTIMING_DURINGPRICINGLOOP ) { SCIP_VAR** vars; int nvars; int nroundablevars; int i; vars = SCIPgetVars(scip); nvars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip); nroundablevars = 0; for( i = 0; i < nvars; ++i ) { if( SCIPvarMayRoundDown(vars[i]) || SCIPvarMayRoundUp(vars[i]) ) nroundablevars++; } heurdata->nroundablevars = nroundablevars; } /* don't call heuristic if there are no roundable variables; except we are called during pricing, in this case we * want to detect a (mixed) integer (LP) solution which is primal feasible */ if( heurdata->nroundablevars == 0 && heurtiming != SCIP_HEURTIMING_DURINGPRICINGLOOP ) return SCIP_OKAY; /* don't call heuristic, if we have already processed the current LP solution */ nlps = SCIPgetNLPs(scip); if( nlps == heurdata->lastlp ) return SCIP_OKAY; heurdata->lastlp = nlps; /* get fractional variables, that should be integral */ SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, NULL, &nlpcands, NULL) ); /* only call heuristic, if LP solution is fractional; except we are called during pricing, in this case we * want to detect a (mixed) integer (LP) solution which is primal feasible */ if( nlpcands == 0 && heurtiming != SCIP_HEURTIMING_DURINGPRICINGLOOP ) return SCIP_OKAY; /* don't call heuristic, if there are more fractional variables than roundable ones */ if( nlpcands > heurdata->nroundablevars ) return SCIP_OKAY; *result = SCIP_DIDNOTFIND; SCIPdebugMessage("executing simple rounding heuristic: %d fractionals\n", nlpcands); /* get the working solution from heuristic's local data */ sol = heurdata->sol; assert(sol != NULL); /* copy the current LP solution to the working solution */ SCIP_CALL( SCIPlinkLPSol(scip, sol) ); /* round all roundable fractional columns in the corresponding direction as long as no unroundable column was found */ for( c = 0; c < nlpcands; ++c ) { SCIP_VAR* var; SCIP_Real oldsolval; SCIP_Real newsolval; SCIP_Bool mayrounddown; SCIP_Bool mayroundup; oldsolval = lpcandssol[c]; assert(!SCIPisFeasIntegral(scip, oldsolval)); var = lpcands[c]; assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); mayrounddown = SCIPvarMayRoundDown(var); mayroundup = SCIPvarMayRoundUp(var); SCIPdebugMessage("simple rounding heuristic: var <%s>, val=%g, rounddown=%u, roundup=%u\n", SCIPvarGetName(var), oldsolval, mayrounddown, mayroundup); /* choose rounding direction */ if( mayrounddown && mayroundup ) { /* we can round in both directions: round in objective function direction */ if( SCIPvarGetObj(var) >= 0.0 ) newsolval = SCIPfeasFloor(scip, oldsolval); else newsolval = SCIPfeasCeil(scip, oldsolval); } else if( mayrounddown ) newsolval = SCIPfeasFloor(scip, oldsolval); else if( mayroundup ) newsolval = SCIPfeasCeil(scip, oldsolval); else break; /* store new solution value */ SCIP_CALL( SCIPsetSolVal(scip, sol, var, newsolval) ); } /* check, if rounding was successful */ if( c == nlpcands ) { SCIP_Bool stored; /* check solution for feasibility, and add it to solution store if possible * neither integrality nor feasibility of LP rows has to be checked, because all fractional * variables were already moved in feasible direction to the next integer */ SCIP_CALL( SCIPtrySol(scip, sol, FALSE, FALSE, FALSE, FALSE, &stored) ); if( stored ) { #ifdef SCIP_DEBUG SCIPdebugMessage("found feasible rounded solution:\n"); SCIPprintSol(scip, sol, NULL, FALSE); #endif *result = SCIP_FOUNDSOL; } } return SCIP_OKAY; }
/** ensure that maxindex + 1 rows can be represented in data arrays; memory gets reallocated with 10% extra space * to save some time for future allocations */ static SCIP_RETCODE heurdataEnsureArraySize( SCIP* scip, /**< SCIP data structure */ SCIP_HEURDATA* heurdata, /**< heuristic data */ int maxindex /**< row index at hand (size must be at least this large) */ ) { int newsize; int r; /* maxindex fits in current array -> nothing to do */ if( maxindex < heurdata->memsize ) return SCIP_OKAY; /* new memory size is the max index + 1 plus 10% additional space */ newsize = (int)SCIPfeasCeil(scip, (maxindex + 1) * 1.1); assert(newsize > heurdata->memsize); assert(heurdata->memsize >= 0); /* alloc memory arrays for row information */ if( heurdata->memsize == 0 ) { SCIP_VAR** vars; int v; int nvars; SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowinfinitiesdown, newsize) ); SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowinfinitiesup, newsize) ); SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowmeans, newsize) ); SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowvariances, newsize) ); assert(SCIPgetStage(scip) == SCIP_STAGE_SOLVING); vars = SCIPgetVars(scip); nvars = SCIPgetNVars(scip); assert(nvars > 0); /* allocate variable update event processing array storage */ SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->varfilterposs, nvars) ); SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->varposs, nvars) ); SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->updatedvars, nvars) ); SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->currentubs, nvars) ); SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->currentlbs, nvars) ); heurdata->varpossmemsize = nvars; heurdata->nupdatedvars = 0; /* init variable event processing data */ for( v = 0; v < nvars; ++v ) { assert(SCIPvarIsActive(vars[v])); assert(SCIPvarGetProbindex(vars[v]) == v); /* set up variable events to catch bound changes */ SCIP_CALL( SCIPcatchVarEvent(scip, vars[v], EVENT_DISTRIBUTION, heurdata->eventhdlr, NULL, &(heurdata->varfilterposs[v])) ); assert(heurdata->varfilterposs[v] >= 0); heurdata->varposs[v] = -1; heurdata->updatedvars[v] = NULL; heurdata->currentlbs[v] = SCIP_INVALID; heurdata->currentubs[v] = SCIP_INVALID; } } else { SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowinfinitiesdown, newsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowinfinitiesup, newsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowmeans, newsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowvariances, newsize) ); } /* loop over extended arrays and invalidate data to trigger initialization of this row when necessary */ for( r = heurdata->memsize; r < newsize; ++r ) { heurdata->rowmeans[r] = SCIP_INVALID; heurdata->rowvariances[r] = SCIP_INVALID; heurdata->rowinfinitiesdown[r] = 0; heurdata->rowinfinitiesup[r] = 0; } /* adjust memsize */ heurdata->memsize = newsize; return SCIP_OKAY; }
/** 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; }