/** branching execution method for not completely fixed pseudo solutions */ static SCIP_DECL_BRANCHEXECPS(branchExecpsRandom) { /*lint --e{715}*/ SCIP_BRANCHRULEDATA* branchruledata; SCIP_VAR** pseudocands; int npseudocands; int bestcand; assert(branchrule != NULL); assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0); assert(scip != NULL); assert(result != NULL); SCIPdebugMessage("Execps method of random branching\n"); branchruledata = SCIPbranchruleGetData(branchrule); assert(branchruledata != NULL); /* get branching candidates */ SCIP_CALL( SCIPgetPseudoBranchCands(scip, &pseudocands, NULL, &npseudocands) ); assert(npseudocands > 0); /* get random branching candidate */ bestcand = SCIPgetRandomInt(0, npseudocands-1, &branchruledata->seed); assert(bestcand >= 0); SCIPdebugMessage(" -> %d candidates, selected candidate %d: variable <%s>\n", npseudocands, bestcand, SCIPvarGetName(pseudocands[bestcand])); /* perform the branching */ SCIP_CALL( SCIPbranchVar(scip, pseudocands[bestcand], NULL, NULL, NULL) ); *result = SCIP_BRANCHED; return SCIP_OKAY; }
/** branching execution method for fractional LP solutions */ static SCIP_DECL_BRANCHEXECLP(branchExeclpInference) { /*lint --e{715}*/ SCIP_BRANCHRULEDATA* branchruledata; SCIP_VAR** cands; int ncands; SCIPdebugMessage("Execlp method of inference branching\n"); /* get branching rule data */ branchruledata = SCIPbranchruleGetData(branchrule); assert(branchruledata != NULL); if( branchruledata->fractionals ) { /* get LP candidates (fractional integer variables) */ SCIP_CALL( SCIPgetLPBranchCands(scip, &cands, NULL, NULL, NULL, &ncands, NULL) ); } else { /* get pseudo candidates (non-fixed integer variables) */ SCIP_CALL( SCIPgetPseudoBranchCands(scip, &cands, NULL, &ncands) ); } /* perform the branching */ SCIP_CALL( performBranching(scip, cands, NULL, ncands, branchruledata->conflictweight, branchruledata->inferenceweight, branchruledata->cutoffweight, branchruledata->reliablescore, branchruledata->useweightedsum, result) ); return SCIP_OKAY; }
/** branching execution method for external candidates */ static SCIP_DECL_BRANCHEXECEXT(branchExecextInference) { /*lint --e{715}*/ SCIP_BRANCHRULEDATA* branchruledata; SCIP_VAR** cands; SCIP_Real* candsols; int ncands; SCIPdebugMessage("Execext method of inference branching\n"); /* get branching rule data */ branchruledata = SCIPbranchruleGetData(branchrule); assert(branchruledata != NULL); /* get branching candidates */ SCIP_CALL( SCIPgetExternBranchCands(scip, &cands, &candsols, NULL, &ncands, NULL, NULL, NULL, NULL) ); assert(ncands > 0); /* perform the branching */ SCIP_CALL( performBranching(scip, cands, candsols, ncands, branchruledata->conflictweight, branchruledata->inferenceweight, branchruledata->cutoffweight, branchruledata->reliablescore, branchruledata->useweightedsum, result) ); return SCIP_OKAY; }
/** initialization method of branching rule (called after problem was transformed) */ static SCIP_DECL_BRANCHINIT(branchInitAllfullstrong) { /*lint --e{715}*/ SCIP_BRANCHRULEDATA* branchruledata; /* initialize branching rule data */ branchruledata = SCIPbranchruleGetData(branchrule); branchruledata->lastcand = 0; return SCIP_OKAY; }
/** destructor of branching rule to free user data (called when SCIP is exiting) */ static SCIP_DECL_BRANCHFREE(branchFreePscost) { /*lint --e{715}*/ SCIP_BRANCHRULEDATA* branchruledata; /* free branching rule data */ branchruledata = SCIPbranchruleGetData(branchrule); SCIPfreeMemory(scip, &branchruledata); SCIPbranchruleSetData(branchrule, NULL); return SCIP_OKAY; }
/** initialization method of branching rule (called after problem was transformed) */ static SCIP_DECL_BRANCHINIT(branchInitStp) { /*lint --e{715}*/ SCIP_BRANCHRULEDATA* branchruledata; branchruledata = SCIPbranchruleGetData(branchrule); assert(branchruledata != NULL); branchruledata->lastcand = 0; return SCIP_OKAY; }
/** initialization method of branching rule (called after problem was transformed) */ static SCIP_DECL_BRANCHINIT(branchInitRandom) { /*lint --e{715}*/ SCIP_BRANCHRULEDATA* branchruledata; branchruledata = SCIPbranchruleGetData(branchrule); assert(branchruledata != NULL); /* set the seed value to the initial random seed value */ branchruledata->seed = (unsigned int) branchruledata->initseed; return SCIP_OKAY; }
/** destructor of branching rule to free user data (called when SCIP is exiting) */ static SCIP_DECL_BRANCHFREE(branchFreeMyfullstrong) { /*lint --e{715}*/ SCIP_BRANCHRULEDATA* branchruledata; branchruledata = SCIPbranchruleGetData(branchrule); assert(branchruledata != NULL); SCIPfreeMemory(scip, &branchruledata); SCIPbranchruleSetData(branchrule, NULL); return SCIP_OKAY; }
/** deinitialization method of branching rule (called before transformed problem is freed) */ static SCIP_DECL_BRANCHEXIT(branchExitStp) { /*lint --e{715}*/ #if 0 SCIP_BRANCHRULEDATA* branchruledata; #endif SCIPstatistic(int j = 0); #if 0 /* initialize branching rule data */ branchruledata = SCIPbranchruleGetData(branchrule); assert(branchruledata != NULL); #endif return SCIP_OKAY; }
/** destructor of branching rule to free user data (called when SCIP is exiting) */ static SCIP_DECL_BRANCHFREE(branchFreeAllfullstrong) { /*lint --e{715}*/ SCIP_BRANCHRULEDATA* branchruledata; /* free branching rule data */ branchruledata = SCIPbranchruleGetData(branchrule); SCIPfreeMemoryArrayNull(scip, &branchruledata->skipdown); SCIPfreeMemoryArrayNull(scip, &branchruledata->skipup); SCIPfreeMemory(scip, &branchruledata); SCIPbranchruleSetData(branchrule, NULL); return SCIP_OKAY; }
/** branching execution method for external candidates */ static SCIP_DECL_BRANCHEXECEXT(branchExecextPscost) { /*lint --e{715}*/ SCIP_BRANCHRULEDATA* branchruledata; SCIP_VAR** externcands; SCIP_Real* externcandssol; SCIP_Real* externcandsscore; int nprioexterncands; SCIP_VAR* brvar; SCIP_Real brpoint; int nchildren; assert(branchrule != NULL); assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0); assert(scip != NULL); assert(result != NULL); branchruledata = SCIPbranchruleGetData(branchrule); assert(branchruledata != NULL); SCIPdebugMessage("Execext method of pscost branching\n"); /* get branching candidates */ SCIP_CALL( SCIPgetExternBranchCands(scip, &externcands, &externcandssol, &externcandsscore, NULL, &nprioexterncands, NULL, NULL, NULL) ); assert(nprioexterncands > 0); /* get current update strategy for pseudo costs, if our multiplier rule is 'u' */ if( branchruledata->strategy == 'u' ) { SCIP_CALL( SCIPgetCharParam(scip, "branching/lpgainnormalize", &branchruledata->updatestrategy) ); } /* select branching variable */ SCIP_CALL( selectBranchVar(scip, branchrule, externcands, externcandssol, externcandsscore, nprioexterncands, &brvar, &brpoint) ); if( brvar == NULL ) { SCIPerrorMessage("branchExecextPscost failed to select a branching variable from %d candidates\n", nprioexterncands); *result = SCIP_DIDNOTRUN; return SCIP_OKAY; } assert(SCIPvarIsActive(SCIPvarGetProbvar(brvar))); SCIPdebugMessage("branching on variable <%s>: new intervals: [%g, %g] and [%g, %g]\n", SCIPvarGetName(brvar), SCIPvarGetLbLocal(brvar), SCIPadjustedVarUb(scip, brvar, brpoint), SCIPadjustedVarLb(scip, brvar, brpoint), SCIPvarGetUbLocal(brvar)); if( branchruledata->nchildren > 2 && SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) <= branchruledata->narymaxdepth ) { /* do n-ary branching */ SCIP_Real minwidth; minwidth = 0.0; if( !SCIPisInfinity(scip, -SCIPvarGetLbGlobal(brvar)) && !SCIPisInfinity(scip, SCIPvarGetUbGlobal(brvar)) ) minwidth = branchruledata->naryminwidth * (SCIPvarGetUbGlobal(brvar) - SCIPvarGetLbGlobal(brvar)); SCIP_CALL( SCIPbranchVarValNary(scip, brvar, brpoint, branchruledata->nchildren, minwidth, branchruledata->narywidthfactor, &nchildren) ); } else { /* do binary branching */ SCIP_CALL( SCIPbranchVarValNary(scip, brvar, brpoint, 2, 0.0, 1.0, &nchildren) ); } if( nchildren > 1 ) { *result = SCIP_BRANCHED; } else { /* if there are no children, then variable should have been fixed by SCIPbranchVarVal */ assert(SCIPisEQ(scip, SCIPvarGetLbLocal(brvar), SCIPvarGetUbLocal(brvar))); *result = SCIP_REDUCEDDOM; } return SCIP_OKAY; }
/** selects the branching variable from given candidate array */ static SCIP_RETCODE selectBranchVar( SCIP* scip, /**< SCIP data structure */ SCIP_BRANCHRULE* branchrule, /**< branching rule */ SCIP_VAR** cands, /**< array of branching candidates */ SCIP_Real* candssol, /**< array of candidate solution values */ SCIP_Real* candsscore, /**< array of candidate scores */ int ncands, /**< the number of candidates */ SCIP_VAR** brvar, /**< pointer to store the selected branching candidate or NULL if none */ SCIP_Real* brpoint /**< pointer to store branching point of selected branching variable */ ) { /*lint --e{850}*/ SCIP_BRANCHRULEDATA* branchruledata; SCIP_VAR* cand; SCIP_Real candsol; SCIP_Real bestbranchscore; SCIP_Real scoremin; SCIP_Real scoresum; SCIP_Real scoremax; SCIP_VAR** candssorted; int* candsorigidx; int i; int j; assert(brvar != NULL); assert(brpoint != NULL); (*brvar) = NULL; (*brpoint) = SCIP_INVALID; if( ncands == 0 ) return SCIP_OKAY; branchruledata = SCIPbranchruleGetData(branchrule); assert(branchruledata != NULL); /* sort branching candidates (in a copy), such that same variables are on consecutive positions */ SCIP_CALL( SCIPduplicateBufferArray(scip, &candssorted, cands, ncands) ); SCIP_CALL( SCIPallocBufferArray(scip, &candsorigidx, ncands) ); for( i = 0; i < ncands; ++i ) candsorigidx[i] = i; SCIPsortPtrInt((void**)candssorted, candsorigidx, SCIPvarComp, ncands); bestbranchscore = -1.0; for( i = 0; i < ncands; ++i ) { cand = candssorted[i]; /* there should be no fixed branching candidates */ assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(cand), SCIPvarGetUbLocal(cand))); /* compute min, sum, and max of all registered scores for this variables * set candsol to a valid value, if someone registered one */ scoremin = candsscore[candsorigidx[i]]; scoresum = scoremin; scoremax = scoremin; candsol = candssol[candsorigidx[i]]; for( j = i+1 ; j < ncands && SCIPvarCompare(candssorted[j], cand) == 0; ++j ) { assert(candsscore[candsorigidx[j]] >= 0.0); scoresum += candsscore[candsorigidx[j]]; if( candsscore[candsorigidx[j]] < scoremin ) scoremin = candsscore[candsorigidx[j]]; else if( candsscore[candsorigidx[j]] > scoremax ) scoremax = candsscore[candsorigidx[j]]; /* @todo if there are two valid externcandssol available for the same variable, should we take the one closer to the middle of the domain? */ if( SCIPisInfinity(scip, REALABS(candsol)) ) candsol = candssol[candsorigidx[j]]; } /* set i to last occurrence of cand in candssorted (instead of first one as before), so in next round we look at another variable */ i = j-1; assert(candssorted[i] == cand); /* check if new candidate is better than previous candidate (if any) */ SCIP_CALL( updateBestCandidate(scip, branchruledata, brvar, brpoint, &bestbranchscore, cand, scoremin, scoremax, scoresum, candsol) ); } /* there were candidates, but no variable was selected; this can only happen if the branching points are huge values * for all variables on which we cannot branch * @todo delay the node? */ if( (*brvar) == NULL ) { SCIPerrorMessage("no branching could be created: all external candidates have huge bounds\n"); SCIPABORT(); return SCIP_BRANCHERROR; /*lint !e527*/ } /* free buffer arrays */ SCIPfreeBufferArray(scip, &candssorted); SCIPfreeBufferArray(scip, &candsorigidx); return SCIP_OKAY; }
/** branching execution method for external candidates */ static SCIP_DECL_BRANCHEXECEXT(branchExecextRandom) { /*lint --e{715}*/ SCIP_BRANCHRULEDATA* branchruledata; SCIP_VAR** externcands; SCIP_Real* externcandssol; int nprioexterncands; SCIP_VAR* bestcand; SCIP_Real bestcandsol; SCIP_Real brpoint; SCIP_NODE* downchild; SCIP_NODE* eqchild; SCIP_NODE* upchild; assert(branchrule != NULL); assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0); assert(scip != NULL); assert(result != NULL); SCIPdebugMessage("Execrel method of random branching\n"); branchruledata = SCIPbranchruleGetData(branchrule); assert(branchruledata != NULL); bestcand = NULL; bestcandsol = 0.0; /* get branching candidates */ SCIP_CALL( SCIPgetExternBranchCands(scip, &externcands, &externcandssol, NULL, NULL, &nprioexterncands, NULL, NULL, NULL) ); assert(nprioexterncands > 0); /* get random branching candidate * * since variables can occur several times in the list of candidates, variables that have been added more often have * a higher probability to be chosen for branching */ getRandomVariable(scip, externcands, externcandssol, nprioexterncands, &bestcand, &bestcandsol, &branchruledata->seed); if( bestcand == NULL ) { SCIPerrorMessage("branchExecrelRandom failed to select a branching variable from %d candidates\n", nprioexterncands); *result = SCIP_DIDNOTRUN; return SCIP_OKAY; } brpoint = SCIPgetBranchingPoint(scip, bestcand, bestcandsol); SCIPdebugMessage(" -> %d candidates, selected variable <%s> with solution value %g, branching point=%g\n", nprioexterncands, SCIPvarGetName(bestcand), bestcandsol, brpoint); SCIP_CALL( SCIPbranchVarVal(scip, bestcand, brpoint, &downchild, &eqchild, &upchild) ); if( downchild != NULL || eqchild != NULL || upchild != NULL ) { *result = SCIP_BRANCHED; } else { /* if there are no children, then variable should have been fixed by SCIPbranchVarVal */ assert(SCIPisEQ(scip, SCIPvarGetLbLocal(bestcand), SCIPvarGetUbLocal(bestcand))); *result = SCIP_REDUCEDDOM; } return SCIP_OKAY; }
/** performs the all fullstrong branching */ static SCIP_RETCODE branch( SCIP* scip, /**< SCIP data structure */ SCIP_BRANCHRULE* branchrule, /**< branching rule */ SCIP_Bool allowaddcons, /**< should adding constraints be allowed to avoid a branching? */ SCIP_RESULT* result /**< pointer to store the result of the callback method */ ) { SCIP_BRANCHRULEDATA* branchruledata; SCIP_VAR** pseudocands; SCIP_Real bestdown; SCIP_Real bestup; SCIP_Real bestscore; SCIP_Real provedbound; SCIP_Bool exactsolve; SCIP_Bool allcolsinlp; SCIP_Bool bestdownvalid; SCIP_Bool bestupvalid; int npseudocands; int npriopseudocands; int bestpseudocand; #ifndef NDEBUG SCIP_Real cutoffbound; cutoffbound = SCIPgetCutoffbound(scip); #endif assert(branchrule != NULL); assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0); assert(scip != NULL); assert(result != NULL); /* check, if all existing columns are in LP, and thus the strong branching results give lower bounds */ allcolsinlp = SCIPallColsInLP(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); /* get branching rule data */ branchruledata = SCIPbranchruleGetData(branchrule); assert(branchruledata != NULL); if( branchruledata->skipdown == NULL ) { int nvars; nvars = SCIPgetNVars(scip); assert(branchruledata->skipup == NULL); SCIP_CALL( SCIPallocMemoryArray(scip, &branchruledata->skipdown, nvars) ); SCIP_CALL( SCIPallocMemoryArray(scip, &branchruledata->skipup, nvars) ); BMSclearMemoryArray(branchruledata->skipdown, nvars); BMSclearMemoryArray(branchruledata->skipup, nvars); } /* get all non-fixed variables (not only the fractional ones) */ SCIP_CALL( SCIPgetPseudoBranchCands(scip, &pseudocands, &npseudocands, &npriopseudocands) ); assert(npseudocands > 0); assert(npriopseudocands > 0); SCIP_CALL( SCIPselectVarPseudoStrongBranching(scip, pseudocands, branchruledata->skipdown, branchruledata->skipup, npseudocands, npriopseudocands, allowaddcons, &bestpseudocand, &bestdown, &bestup, &bestscore, &bestdownvalid, &bestupvalid, &provedbound, result) ); if( *result != SCIP_CUTOFF && *result != SCIP_REDUCEDDOM && *result != SCIP_CONSADDED ) { SCIP_NODE* downchild; SCIP_NODE* eqchild; SCIP_NODE* upchild; SCIP_VAR* var; assert(*result == SCIP_DIDNOTRUN); assert(0 <= bestpseudocand && bestpseudocand < npseudocands); assert(SCIPisLT(scip, provedbound, cutoffbound)); var = pseudocands[bestpseudocand]; /* perform the branching */ SCIPdebugMessage(" -> %d candidates, selected candidate %d: variable <%s>[%g,%g] (solval=%g, down=%g, up=%g, score=%g)\n", npseudocands, bestpseudocand, SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), SCIPvarGetLPSol(var), bestdown, bestup, bestscore); SCIP_CALL( SCIPbranchVarVal(scip, var, SCIPvarGetLPSol(var), &downchild, &eqchild, &upchild) ); /* update the lower bounds in the children */ if( allcolsinlp && !exactsolve ) { if( downchild != NULL ) { SCIP_CALL( SCIPupdateNodeLowerbound(scip, downchild, bestdownvalid ? MAX(bestdown, provedbound) : provedbound) ); SCIPdebugMessage(" -> down child's lowerbound: %g\n", SCIPnodeGetLowerbound(downchild)); } if( eqchild != NULL ) { SCIP_CALL( SCIPupdateNodeLowerbound(scip, eqchild, provedbound) ); SCIPdebugMessage(" -> eq child's lowerbound: %g\n", SCIPnodeGetLowerbound(eqchild)); } if( upchild != NULL ) { SCIP_CALL( SCIPupdateNodeLowerbound(scip, upchild, bestupvalid ? MAX(bestup, provedbound) : provedbound) ); SCIPdebugMessage(" -> up child's lowerbound: %g\n", SCIPnodeGetLowerbound(upchild)); } } *result = SCIP_BRANCHED; } 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; }