/** 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; }
/** fixes a variable to zero if the corresponding packings are not valid for this constraint/node (due to branching) */ static SCIP_RETCODE checkVariable( SCIP* scip, /**< SCIP data structure */ SCIP_CONSDATA* consdata, /**< constraint data */ SCIP_VAR* var, /**< variables to check */ int* nfixedvars, /**< pointer to store the number of fixed variables */ SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */ ) { SCIP_VARDATA* vardata; int* consids; int nconsids; SCIP_Bool existid1; SCIP_Bool existid2; CONSTYPE type; SCIP_Bool fixed; SCIP_Bool infeasible; int pos; assert(scip != NULL); assert(consdata != NULL); assert(var != NULL); assert(nfixedvars != NULL); assert(cutoff != NULL); /* if variables is locally fixed to zero continue */ if( SCIPvarGetUbLocal(var) < 0.5 ) return SCIP_OKAY; /* check if the packing which corresponds to the variable feasible for this constraint */ vardata = SCIPvarGetData(var); nconsids = SCIPvardataGetNConsids(vardata); consids = SCIPvardataGetConsids(vardata); existid1 = SCIPsortedvecFindInt(consids, consdata->itemid1, nconsids, &pos); existid2 = SCIPsortedvecFindInt(consids, consdata->itemid2, nconsids, &pos); type = consdata->type; if( (type == SAME && existid1 != existid2) || (type == DIFFER && existid1 && existid2) ) { SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) ); if( infeasible ) { assert( SCIPvarGetLbLocal(var) > 0.5 ); SCIPdebugMessage("-> cutoff\n"); (*cutoff) = TRUE; } else { assert(fixed); (*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(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; }
/** * Selects a variable from a set of candidates by strong branching * * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. * * @note The variables in the lpcands array must have a fractional value in the current LP solution */ SCIP_RETCODE SCIPselectVarPseudoStrongBranching( SCIP* scip, /**< original SCIP data structure */ SCIP_VAR** pseudocands, /**< branching candidates */ SCIP_Bool* skipdown, /**< should down branchings be skipped? */ SCIP_Bool* skipup, /**< should up branchings be skipped? */ int npseudocands, /**< number of branching candidates */ int npriopseudocands, /**< number of priority branching candidates */ SCIP_Bool allowaddcons, /**< is the branching rule allowed to add constraints? */ int* bestpseudocand, /**< best candidate for branching */ SCIP_Real* bestdown, /**< objective value of the down branch for bestcand */ SCIP_Real* bestup, /**< objective value of the up branch for bestcand */ SCIP_Real* bestscore, /**< score for bestcand */ SCIP_Bool* bestdownvalid, /**< is bestdown a valid dual bound for the down branch? */ SCIP_Bool* bestupvalid, /**< is bestup a valid dual bound for the up branch? */ SCIP_Real* provedbound, /**< proved dual bound for current subtree */ SCIP_RESULT* result /**< result pointer */ ) { SCIP_Real lpobjval; SCIP_Bool allcolsinlp; SCIP_Bool exactsolve; #ifndef NDEBUG SCIP_Real cutoffbound; cutoffbound = SCIPgetCutoffbound(scip); #endif assert(scip != NULL); assert(pseudocands != NULL); assert(bestpseudocand != NULL); assert(skipdown != NULL); assert(skipup != NULL); assert(bestdown != NULL); assert(bestup != NULL); assert(bestscore != NULL); assert(bestdownvalid != NULL); assert(bestupvalid != NULL); assert(provedbound != NULL); assert(result != NULL); assert(SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL); /* get current LP objective bound of the local sub problem and global cutoff bound */ lpobjval = SCIPgetLPObjval(scip); /* check, if we want to solve the problem exactly, meaning that strong branching information is not useful * for cutting off sub problems and improving lower bounds of children */ exactsolve = SCIPisExactSolve(scip); /* check, if all existing columns are in LP, and thus the strong branching results give lower bounds */ allcolsinlp = SCIPallColsInLP(scip); /* if only one candidate exists, choose this one without applying strong branching */ *bestpseudocand = 0; *bestdown = lpobjval; *bestup = lpobjval; *bestdownvalid = TRUE; *bestupvalid = TRUE; *bestscore = -SCIPinfinity(scip); *provedbound = lpobjval; if( npseudocands > 1 ) { SCIP_BRANCHRULE* branchrule; SCIP_BRANCHRULEDATA* branchruledata; SCIP_Real solval; SCIP_Real down; SCIP_Real up; SCIP_Real downgain; SCIP_Real upgain; SCIP_Real score; SCIP_Bool integral; SCIP_Bool lperror; SCIP_Bool downvalid; SCIP_Bool upvalid; SCIP_Bool downinf; SCIP_Bool upinf; SCIP_Bool downconflict; SCIP_Bool upconflict; int nsbcalls; int i; int c; branchrule = SCIPfindBranchrule(scip, BRANCHRULE_NAME); assert(branchrule != NULL); /* get branching rule data */ branchruledata = SCIPbranchruleGetData(branchrule); assert(branchruledata != NULL); /* initialize strong branching */ SCIP_CALL( SCIPstartStrongbranch(scip, FALSE) ); /* search the full strong candidate: * cycle through the candidates, starting with the position evaluated in the last run */ nsbcalls = 0; for( i = 0, c = branchruledata->lastcand; i < npseudocands; ++i, ++c ) { c = c % npseudocands; assert(pseudocands[c] != NULL); /* we can only apply strong branching on COLUMN variables that are in the current LP */ if( !SCIPvarIsInLP(pseudocands[c]) ) continue; solval = SCIPvarGetLPSol(pseudocands[c]); integral = SCIPisFeasIntegral(scip, solval); SCIPdebugMessage("applying strong branching on %s variable <%s>[%g,%g] with solution %g\n", integral ? "integral" : "fractional", SCIPvarGetName(pseudocands[c]), SCIPvarGetLbLocal(pseudocands[c]), SCIPvarGetUbLocal(pseudocands[c]), solval); up = -SCIPinfinity(scip); down = -SCIPinfinity(scip); if( integral ) { SCIP_CALL( SCIPgetVarStrongbranchInt(scip, pseudocands[c], INT_MAX, skipdown[c] ? NULL : &down, skipup[c] ? NULL : &up, &downvalid, &upvalid, &downinf, &upinf, &downconflict, &upconflict, &lperror) ); } else { SCIP_CALL( SCIPgetVarStrongbranchFrac(scip, pseudocands[c], INT_MAX, skipdown[c] ? NULL : &down, skipup[c] ? NULL : &up, &downvalid, &upvalid, &downinf, &upinf, &downconflict, &upconflict, &lperror) ); } nsbcalls++; /* display node information line in root node */ if( SCIPgetDepth(scip) == 0 && nsbcalls % 100 == 0 ) { SCIP_CALL( SCIPprintDisplayLine(scip, NULL, SCIP_VERBLEVEL_HIGH, TRUE) ); } /* check for an error in strong branching */ if( lperror ) { SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "(node %"SCIP_LONGINT_FORMAT") error in strong branching call for variable <%s> with solution %g\n", SCIPgetNNodes(scip), SCIPvarGetName(pseudocands[c]), solval); break; } /* evaluate strong branching */ down = MAX(down, lpobjval); up = MAX(up, lpobjval); downgain = down - lpobjval; upgain = up - lpobjval; assert(!allcolsinlp || exactsolve || !downvalid || downinf == SCIPisGE(scip, down, cutoffbound)); assert(!allcolsinlp || exactsolve || !upvalid || upinf == SCIPisGE(scip, up, cutoffbound)); assert(downinf || !downconflict); assert(upinf || !upconflict); /* check if there are infeasible roundings */ if( downinf || upinf ) { assert(allcolsinlp); assert(!exactsolve); /* if for both infeasibilities, a conflict constraint was created, we don't need to fix the variable by hand, * but better wait for the next propagation round to fix them as an inference, and potentially produce a * cutoff that can be analyzed */ if( allowaddcons && downinf == downconflict && upinf == upconflict ) { *result = SCIP_CONSADDED; break; /* terminate initialization loop, because constraint was added */ } else if( downinf && upinf ) { if( integral ) { SCIP_Bool infeasible; SCIP_Bool fixed; /* both bound changes are infeasible: variable can be fixed to its current value */ SCIP_CALL( SCIPfixVar(scip, pseudocands[c], solval, &infeasible, &fixed) ); assert(!infeasible); assert(fixed); *result = SCIP_REDUCEDDOM; SCIPdebugMessage(" -> integral variable <%s> is infeasible in both directions\n", SCIPvarGetName(pseudocands[c])); break; /* terminate initialization loop, because LP was changed */ } else { /* both roundings are infeasible: the node is infeasible */ *result = SCIP_CUTOFF; SCIPdebugMessage(" -> fractional variable <%s> is infeasible in both directions\n", SCIPvarGetName(pseudocands[c])); break; /* terminate initialization loop, because node is infeasible */ } } else if( downinf ) { SCIP_Real newlb; /* downwards rounding is infeasible -> change lower bound of variable to upward rounding */ newlb = SCIPfeasCeil(scip, solval); if( SCIPvarGetLbLocal(pseudocands[c]) < newlb - 0.5 ) { SCIP_CALL( SCIPchgVarLb(scip, pseudocands[c], newlb) ); *result = SCIP_REDUCEDDOM; SCIPdebugMessage(" -> variable <%s> is infeasible in downward branch\n", SCIPvarGetName(pseudocands[c])); break; /* terminate initialization loop, because LP was changed */ } } else { SCIP_Real newub; /* upwards rounding is infeasible -> change upper bound of variable to downward rounding */ assert(upinf); newub = SCIPfeasFloor(scip, solval); if( SCIPvarGetUbLocal(pseudocands[c]) > newub + 0.5 ) { SCIP_CALL( SCIPchgVarUb(scip, pseudocands[c], newub) ); *result = SCIP_REDUCEDDOM; SCIPdebugMessage(" -> variable <%s> is infeasible in upward branch\n", SCIPvarGetName(pseudocands[c])); break; /* terminate initialization loop, because LP was changed */ } } } else if( allcolsinlp && !exactsolve && downvalid && upvalid ) { SCIP_Real minbound; /* the minimal lower bound of both children is a proved lower bound of the current subtree */ minbound = MIN(down, up); *provedbound = MAX(*provedbound, minbound); } /* check for a better score, if we are within the maximum priority candidates */ if( c < npriopseudocands ) { if( integral ) { if( skipdown[c] ) { downgain = 0.0; score = SCIPgetBranchScore(scip, pseudocands[c], downgain, upgain); } else if( skipup[c] ) { upgain = 0.0; score = SCIPgetBranchScore(scip, pseudocands[c], downgain, upgain); } else { SCIP_Real gains[3]; gains[0] = downgain; gains[1] = 0.0; gains[2] = upgain; score = SCIPgetBranchScoreMultiple(scip, pseudocands[c], 3, gains); } } else score = SCIPgetBranchScore(scip, pseudocands[c], downgain, upgain); if( score > *bestscore ) { *bestpseudocand = c; *bestdown = down; *bestup = up; *bestdownvalid = downvalid; *bestupvalid = upvalid; *bestscore = score; } } else score = 0.0; /* update pseudo cost values */ if( !downinf ) { SCIP_CALL( SCIPupdateVarPseudocost(scip, pseudocands[c], solval-SCIPfeasCeil(scip, solval-1.0), downgain, 1.0) ); } if( !upinf ) { SCIP_CALL( SCIPupdateVarPseudocost(scip, pseudocands[c], solval-SCIPfeasFloor(scip, solval+1.0), upgain, 1.0) ); } SCIPdebugMessage(" -> var <%s> (solval=%g, downgain=%g, upgain=%g, score=%g) -- best: <%s> (%g)\n", SCIPvarGetName(pseudocands[c]), solval, downgain, upgain, score, SCIPvarGetName(pseudocands[*bestpseudocand]), *bestscore); } /* remember last evaluated candidate */ branchruledata->lastcand = c; /* end strong branching */ SCIP_CALL( SCIPendStrongbranch(scip) ); } return SCIP_OKAY; }
/** reads the given solution file */ static SCIP_RETCODE readSol( SCIP* scip, /**< SCIP data structure */ const char* filename /**< name of the input file */ ) { SCIP_FILE* file; SCIP_Bool error; SCIP_Bool unknownvariablemessage; int lineno; int nfixed; assert(scip != NULL); assert(filename != NULL); /* open input file */ file = SCIPfopen(filename, "r"); if( file == NULL ) { SCIPerrorMessage("cannot open file <%s> for reading\n", filename); SCIPprintSysError(filename); return SCIP_NOFILE; } /* read the file */ error = FALSE; unknownvariablemessage = FALSE; lineno = 0; nfixed = 0; while( !SCIPfeof(file) && !error ) { char buffer[SCIP_MAXSTRLEN]; char varname[SCIP_MAXSTRLEN]; char valuestring[SCIP_MAXSTRLEN]; char objstring[SCIP_MAXSTRLEN]; SCIP_VAR* var; SCIP_Real value; SCIP_Bool infeasible; SCIP_Bool fixed; int nread; /* get next line */ if( SCIPfgets(buffer, (int) sizeof(buffer), file) == NULL ) break; lineno++; /* the lines "solution status: ..." and "objective value: ..." may preceed the solution information */ if( strncasecmp(buffer, "solution status:", 16) == 0 || strncasecmp(buffer, "objective value:", 16) == 0 ) continue; /* parse the line */ nread = sscanf(buffer, "%s %s %s\n", varname, valuestring, objstring); if( nread < 2 ) { SCIPerrorMessage("invalid input line %d in solution file <%s>: <%s>\n", lineno, filename, buffer); error = TRUE; break; } /* find the variable */ var = SCIPfindVar(scip, varname); if( var == NULL ) { if( !unknownvariablemessage ) { SCIPwarningMessage(scip, "unknown variable <%s> in line %d of solution file <%s>\n", varname, lineno, filename); SCIPwarningMessage(scip, " (further unknown variables are ignored)\n"); unknownvariablemessage = TRUE; } continue; } /* cast the value */ if( strncasecmp(valuestring, "inv", 3) == 0 ) continue; else if( strncasecmp(valuestring, "+inf", 4) == 0 || strncasecmp(valuestring, "inf", 3) == 0 ) value = SCIPinfinity(scip); else if( strncasecmp(valuestring, "-inf", 4) == 0 ) value = -SCIPinfinity(scip); else { nread = sscanf(valuestring, "%lf", &value); if( nread != 1 ) { SCIPerrorMessage("invalid solution value <%s> for variable <%s> in line %d of solution file <%s>\n", valuestring, varname, lineno, filename); error = TRUE; break; } } /* fix the variable */ SCIP_CALL( SCIPfixVar(scip, var, value, &infeasible, &fixed) ); if( infeasible ) { SCIPerrorMessage("infeasible solution value of <%s>[%.15g,%.15g] to %.15g in line %d of solution file <%s>\n", varname, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), value, lineno, filename); error = TRUE; break; } if( fixed ) nfixed++; } /* close input file */ SCIPfclose(file); /* display result */ SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "fixed %d variables from solution file <%s>\n", nfixed, filename); if( error ) return SCIP_READERROR; else return SCIP_OKAY; }
/** propagator to force finding the debugging solution */ static SCIP_DECL_PROPEXEC(propExecDebug) { /*lint --e{715}*/ SCIP_VAR** vars; int nvars; int i; assert(scip != NULL); assert(result != NULL); *result = SCIP_DIDNOTFIND; /* check if we are in the original problem and not in a sub MIP */ if( !isSolutionInMip(scip->set) ) return SCIP_OKAY; if( SCIPgetStage(scip) != SCIP_STAGE_SOLVING ) return SCIP_OKAY; /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */ if( debugSolIsAchieved(scip->set) ) return SCIP_OKAY; #if 1 /* solve at least one LP */ if( SCIPgetNLPIterations(scip) == 0 ) return SCIP_OKAY; #endif vars = SCIPgetOrigVars(scip); nvars = SCIPgetNOrigVars(scip); for( i = 0; i < nvars; ++i ) { SCIP_Real solval; SCIP_Real lb; SCIP_Real ub; SCIP_Bool infeasible; SCIP_Bool fixed; SCIP_CALL( getSolutionValue(scip->set, vars[i], &solval) ); if( solval == SCIP_UNKNOWN ) /*lint !e777*/ { SCIPerrorMessage("original variable without debugging solution value\n"); SCIPABORT(); } lb = SCIPvarGetLbGlobal(vars[i]); ub = SCIPvarGetUbGlobal(vars[i]); if( SCIPisLT(scip, solval, lb) || SCIPisGT(scip, solval, ub) ) { SCIPerrorMessage("solution value %.15g of <%s> outside bounds loc=[%.15g,%.15g], glb=[%.15g,%.15g]\n", solval, SCIPvarGetName(vars[i]), lb, ub, SCIPvarGetLbGlobal(vars[i]), SCIPvarGetUbGlobal(vars[i])); SCIPABORT(); } SCIP_CALL( SCIPfixVar(scip, vars[i], solval, &infeasible, &fixed) ); if( infeasible ) *result = SCIP_CUTOFF; else if( fixed ) *result = SCIP_REDUCEDDOM; } return SCIP_OKAY; }