/** prints all stable sets to standart output */ void COLORprobPrintStableSets( SCIP* scip /**< SCIP data structure */ ) { SCIP_PROBDATA* probdata; int i; int j; assert(scip != NULL); probdata = SCIPgetProbData(scip); assert(probdata != NULL); for ( i = 0; i < probdata->nstablesets; i++ ) { printf( "Set %d: ", i); for ( j = 0; j < probdata->stablesetlengths[i]; j++ ) { printf("%d, ", probdata->stablesets[i][j]+1); } printf("ub = %f", SCIPvarGetUbLocal(probdata->stablesetvars[i])); printf(", inLP = %u", SCIPvarIsInLP(probdata->stablesetvars[i])); printf("\n"); } }
/** * 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; }