/** 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; }
/** 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; }
/** execution method of presolver */ static SCIP_DECL_PRESOLEXEC(presolExecDualagg) { /*lint --e{715}*/ SCIPMILPMATRIX* matrix; SCIP_Bool initialized; SCIP_Bool complete; assert(result != NULL); *result = SCIP_DIDNOTRUN; if( (SCIPgetStage(scip) != SCIP_STAGE_PRESOLVING) || SCIPinProbing(scip) || SCIPisNLPEnabled(scip) ) return SCIP_OKAY; if( SCIPisStopped(scip) || SCIPgetNActivePricers(scip) > 0 ) return SCIP_OKAY; if( SCIPgetNBinVars(scip) == 0 ) return SCIP_OKAY; if( !SCIPallowDualReds(scip) ) return SCIP_OKAY; *result = SCIP_DIDNOTFIND; matrix = NULL; SCIP_CALL( SCIPmatrixCreate(scip, &matrix, &initialized, &complete) ); /* we only work on pure MIPs currently */ if( initialized && complete ) { AGGRTYPE* aggtypes; SCIP_VAR** binvars; int nvaragg; int ncols; ncols = SCIPmatrixGetNColumns(matrix); nvaragg = 0; SCIP_CALL( SCIPallocBufferArray(scip, &aggtypes, ncols) ); BMSclearMemoryArray(aggtypes, ncols); SCIP_CALL( SCIPallocBufferArray(scip, &binvars, ncols) ); SCIPdebug( BMSclearMemoryArray(binvars, ncols) ); /* search for aggregations */ SCIP_CALL( findUplockAggregations(scip, matrix, &nvaragg, aggtypes, binvars) ); SCIP_CALL( findDownlockAggregations(scip, matrix, &nvaragg, aggtypes, binvars) ); /* apply aggregations, if we found any */ if( nvaragg > 0 ) { int v; for( v = 0; v < ncols; v++ ) { if( aggtypes[v] != NOAGG ) { SCIP_Bool infeasible; SCIP_Bool redundant; SCIP_Bool aggregated; SCIP_Real ub; SCIP_Real lb; ub = SCIPmatrixGetColUb(matrix, v); lb = SCIPmatrixGetColLb(matrix, v); /* aggregate variable */ assert(binvars[v] != NULL); if( aggtypes[v] == BIN0UBOUND ) { SCIP_CALL( SCIPaggregateVars(scip, SCIPmatrixGetVar(matrix, v), binvars[v], 1.0, ub-lb, ub, &infeasible, &redundant, &aggregated) ); } else { assert(aggtypes[v] == BIN0LBOUND); SCIP_CALL( SCIPaggregateVars(scip, SCIPmatrixGetVar(matrix, v), binvars[v], 1.0, lb-ub, lb, &infeasible, &redundant, &aggregated) ); } /* infeasible aggregation */ if( infeasible ) { SCIPdebugMessage(" -> infeasible aggregation\n"); *result = SCIP_CUTOFF; return SCIP_OKAY; } if( aggregated ) (*naggrvars)++; } } /* set result pointer */ if( (*naggrvars) > 0 ) *result = SCIP_SUCCESS; } SCIPfreeBufferArray(scip, &binvars); SCIPfreeBufferArray(scip, &aggtypes); } SCIPmatrixFree(scip, &matrix); return SCIP_OKAY; }