/** 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; }
/** 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; }
/** gets value of given variable in debugging solution */ static SCIP_RETCODE getSolutionValue( SCIP_SET* set, /**< global SCIP settings */ SCIP_VAR* var, /**< variable to get solution value for */ SCIP_Real* val /**< pointer to store solution value */ ) { SCIP_VAR* solvar; SCIP_Real scalar; SCIP_Real constant; const char* name; int left; int right; int middle; int cmp; assert(set != NULL); assert(var != NULL); assert(val != NULL); SCIP_CALL( readSolution(set) ); SCIPdebugMessage("Now handling variable <%s>, which has status %d, is of type %d, and was deleted: %d, negated: %d, transformed: %d\n", SCIPvarGetName(var), SCIPvarGetStatus(var), SCIPvarGetType(var), SCIPvarIsDeleted(var), SCIPvarIsNegated(var),SCIPvarIsTransformedOrigvar(var)); /* ignore deleted variables */ if( SCIPvarIsDeleted(var) ) { SCIPdebugMessage("**** unknown solution value for deleted variable <%s>\n", SCIPvarGetName(var)); *val = SCIP_UNKNOWN; return SCIP_OKAY; } /* retransform variable onto original variable space */ solvar = var; scalar = 1.0; constant = 0.0; if( SCIPvarIsNegated(solvar) ) { scalar = -1.0; constant = SCIPvarGetNegationConstant(solvar); solvar = SCIPvarGetNegationVar(solvar); } if( SCIPvarIsTransformed(solvar) ) { SCIP_CALL( SCIPvarGetOrigvarSum(&solvar, &scalar, &constant) ); if( solvar == NULL ) { /* if no original counterpart, then maybe someone added a value for the transformed variable, so search for var (or its negation) */ SCIPdebugMessage("variable <%s> has no original counterpart\n", SCIPvarGetName(var)); solvar = var; scalar = 1.0; constant = 0.0; if( SCIPvarIsNegated(solvar) ) { scalar = -1.0; constant = SCIPvarGetNegationConstant(solvar); solvar = SCIPvarGetNegationVar(solvar); } } } /* perform a binary search for the variable */ name = SCIPvarGetName(solvar); left = 0; right = nsolvals-1; while( left <= right ) { middle = (left+right)/2; cmp = strcmp(name, solnames[middle]); if( cmp < 0 ) right = middle-1; else if( cmp > 0 ) left = middle+1; else { *val = scalar * solvals[middle] + constant; return SCIP_OKAY; } } *val = constant; if( *val < SCIPvarGetLbGlobal(var) - 1e-06 || *val > SCIPvarGetUbGlobal(var) + 1e-06 ) { SCIPwarningMessage("invalid solution value %.15g for variable <%s>[%.15g,%.15g]\n", *val, SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)); } return SCIP_OKAY; }