void scip_branch_around_val(SCIP* scip, SCIP_VAR* v, llint x) { #ifdef DEBUG cout << "[SU] branching around " << x << " for " << var_id(v) << endl; #endif fflush(stdout); SCIP_NODE* left; SCIP_NODE* middle; SCIP_NODE* right; assert(SCIPvarGetLbLocal(v) <= x); assert(x <= SCIPvarGetUbLocal(v)); sa(SCIPbranchVarVal(scip, v, x, &left, &middle, &right)); #ifdef DEBUG cout << "created children " << left << " < " << middle << " < " << right << endl; #endif }
/** branching execution method for external candidates */ static SCIP_DECL_BRANCHEXECEXT(branchExecextLeastinf) { /*lint --e{715}*/ SCIP_VAR** externcands; SCIP_Real* externcandssol; SCIP_Real* externcandsscore; int nexterncands; SCIP_VAR* bestcand; SCIP_Real bestscore; SCIP_Real bestobj; SCIP_Real bestsol; SCIP_Real brpoint; int i; 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("Execext method of leastinf branching\n"); /* get branching candidates */ SCIP_CALL( SCIPgetExternBranchCands(scip, &externcands, &externcandssol, &externcandsscore, NULL, &nexterncands, NULL, NULL, NULL) ); assert(nexterncands > 0); /* search the least infeasible candidate */ bestscore = SCIPinfinity(scip); bestobj = 0.0; bestcand = NULL; bestsol = SCIP_INVALID; for( i = 0; i < nexterncands; ++i ) { updateBestCandidate(scip, &bestcand, &bestscore, &bestobj, &bestsol, externcands[i], externcandsscore[i], externcandssol[i]); } if( bestcand == NULL ) { SCIPerrorMessage("branchExecextLeastinf failed to select a branching variable from %d candidates\n", nexterncands); *result = SCIP_DIDNOTRUN; return SCIP_OKAY; } brpoint = SCIPgetBranchingPoint(scip, bestcand, bestsol); SCIPdebugMessage(" -> %d candidates, selected variable <%s> (infeas=%g, obj=%g, factor=%g, score=%g), branching point=%g\n", nexterncands, SCIPvarGetName(bestcand), bestsol, bestobj, SCIPvarGetBranchFactor(bestcand), bestscore, brpoint); /* perform the branching */ 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; }
/** 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; }
/** selects a variable out of the given candidate array and performs the branching */ static SCIP_RETCODE performBranching( SCIP* scip, /**< SCIP data structure */ SCIP_VAR** cands, /**< candidate array */ SCIP_Real* candsols, /**< array of candidate solution values, or NULL */ int ncands, /**< number of candidates */ SCIP_Real conflictweight, /**< weight in score calculations for conflict score */ SCIP_Real inferenceweight, /**< weight in score calculations for inference score */ SCIP_Real cutoffweight, /**< weight in score calculations for cutoff score */ SCIP_Real reliablescore, /**< score which is seen to be reliable for a branching decision */ SCIP_Bool useweightedsum, /**< should a weighted sum of inference, conflict and cutoff weights be used? */ SCIP_RESULT* result /**< buffer to store result (branched, reduced domain, ...) */ ) { SCIP_VAR* bestaggrcand; SCIP_VAR* bestvaluecand; SCIP_Real bestval; SCIP_Real bestaggrscore; SCIP_Real bestvaluescore; SCIP_Real bestbranchpoint; SCIP_BRANCHDIR bestbranchdir; SCIP_NODE* downchild; SCIP_NODE* eqchild; SCIP_NODE* upchild; bestbranchpoint = SCIP_UNKNOWN; bestbranchdir = SCIP_BRANCHDIR_DOWNWARDS; bestvaluescore = 0.0; bestvaluecand = NULL; assert(ncands > 0); assert(result != NULL); *result = SCIP_DIDNOTFIND; /* check if the weighted sum between the average inferences and conflict score should be used */ if( useweightedsum ) { int c; bestaggrcand = cands[0]; bestvaluecand = cands[0]; assert(cands[0] != NULL); if( candsols == NULL ) { bestval = SCIP_UNKNOWN; /* get domain value score for the first candidate */ bestvaluescore = getValueScore(scip, cands[0], conflictweight, cutoffweight, reliablescore, &bestbranchpoint, &bestbranchdir); SCIPdebugMessage("current best value candidate <%s>[%g,%g] %s <%g> (value %g)\n", SCIPvarGetName(bestvaluecand), SCIPvarGetLbLocal(bestvaluecand), SCIPvarGetUbLocal(bestvaluecand), bestbranchdir == SCIP_BRANCHDIR_DOWNWARDS ? "<=" : ">=", bestbranchpoint, bestvaluescore); } else bestval = candsols[0]; /* get aggregated score for the first candidate */ bestaggrscore = getAggrScore(scip, cands[0], conflictweight, inferenceweight, cutoffweight, reliablescore); for( c = 1; c < ncands; ++c ) { SCIP_VAR* cand; SCIP_Real val; SCIP_Real aggrscore; SCIP_Real branchpoint; SCIP_BRANCHDIR branchdir; cand = cands[c]; assert(cand != NULL); if( candsols == NULL ) { SCIP_Real valuescore; val = SCIP_UNKNOWN; /* get domain value score for the candidate */ valuescore = getValueScore(scip, cand, conflictweight, cutoffweight, reliablescore, &branchpoint, &branchdir); /* evaluate the candidate against the currently best candidate w.r.t. domain value score */ evaluateValueCand(cand, valuescore, branchpoint, branchdir, &bestvaluecand, &bestvaluescore, &bestbranchpoint, &bestbranchdir); SCIPdebugMessage("current best value candidate <%s>[%g,%g] %s <%g> (value %g)\n", SCIPvarGetName(bestvaluecand), SCIPvarGetLbLocal(bestvaluecand), SCIPvarGetUbLocal(bestvaluecand), bestbranchdir == SCIP_BRANCHDIR_DOWNWARDS ? "<=" : ">=", bestbranchpoint, bestvaluescore); } else val = candsols[c]; /* get aggregated score for the candidate */ aggrscore = getAggrScore(scip, cand, conflictweight, inferenceweight, cutoffweight, reliablescore); SCIPdebugMessage(" -> cand <%s>: prio=%d, solval=%g, score=%g\n", SCIPvarGetName(cand), SCIPvarGetBranchPriority(cand), val == SCIP_UNKNOWN ? SCIPgetVarSol(scip, cand) : val, aggrscore); /*lint !e777*/ /* evaluate the candidate against the currently best candidate w.r.t. aggregated score */ evaluateAggrCand(cand, aggrscore, val, &bestaggrcand, &bestaggrscore, &bestval); } } else { int c; bestaggrcand = cands[0]; assert(cands[0] != NULL); if( candsols != NULL ) bestval = candsols[0]; else bestval = SCIP_UNKNOWN; bestaggrscore = SCIPgetVarAvgInferenceScore(scip, cands[0]); /* search for variable with best score w.r.t. average inferences per branching */ for( c = 1; c < ncands; ++c ) { SCIP_VAR* cand; SCIP_Real val; SCIP_Real aggrscore; cand = cands[c]; assert(cand != NULL); if( candsols != NULL ) val = candsols[c]; else val = SCIP_UNKNOWN; aggrscore = SCIPgetVarAvgInferenceScore(scip, cand); /* in case the average inferences score is below the reliable score we set it to zero since it is seen to be * unreliable */ if( aggrscore < reliablescore ) aggrscore = 0.0; SCIPdebugMessage(" -> cand <%s>: prio=%d, solval=%g, score=%g\n", SCIPvarGetName(cand), SCIPvarGetBranchPriority(cand), val == SCIP_UNKNOWN ? SCIPgetVarSol(scip, cand) : val, aggrscore); /*lint !e777*/ /* evaluate the candidate against the currently best candidate */ evaluateAggrCand(cand, aggrscore, val, &bestaggrcand, &bestaggrscore, &bestval); } } assert(bestaggrcand != NULL); SCIPdebugMessage(" -> %d candidates, selected variable <%s>[%g,%g] (prio=%d, solval=%.12f, score=%g, conflict=%g cutoff=%g, inference=%g)\n", ncands, SCIPvarGetName(bestaggrcand), SCIPvarGetLbLocal (bestaggrcand), SCIPvarGetUbLocal(bestaggrcand), SCIPvarGetBranchPriority(bestaggrcand), bestval == SCIP_UNKNOWN ? SCIPgetVarSol(scip, bestaggrcand) : bestval, bestaggrscore, /*lint !e777*/ SCIPgetVarConflictScore(scip, bestaggrcand), SCIPgetVarAvgInferenceCutoffScore(scip, bestaggrcand, cutoffweight), SCIPgetVarAvgInferenceScore(scip, bestaggrcand)); /* perform the branching */ if( candsols != NULL ) { SCIP_CALL( SCIPbranchVarVal(scip, bestaggrcand, SCIPgetBranchingPoint(scip, bestaggrcand, bestval), &downchild, &eqchild, &upchild) ); } else if( bestbranchpoint == SCIP_UNKNOWN ) /*lint !e777*/ { SCIP_CALL( SCIPbranchVar(scip, bestaggrcand, &downchild, &eqchild, &upchild) ); } else { SCIP_Real estimate; SCIP_Real downprio; SCIP_Real upprio; SCIP_Real downub; SCIP_Real uplb; assert(bestvaluecand != NULL); downprio = 0.0; upprio = 0.0; if( bestbranchdir == SCIP_BRANCHDIR_DOWNWARDS ) { downprio = 1.0; downub = bestbranchpoint; uplb = bestbranchpoint + 1.0; } else { upprio = 1.0; downub = bestbranchpoint - 1.0; uplb = bestbranchpoint; } /* calculate the child estimate */ estimate = SCIPcalcChildEstimate(scip, bestvaluecand, downub); /* create down child */ SCIP_CALL( SCIPcreateChild(scip, &downchild, downprio, estimate) ); /* change upper bound in down child */ SCIP_CALL( SCIPchgVarUbNode(scip, downchild, bestvaluecand, downub) ); /* calculate the child estimate */ estimate = SCIPcalcChildEstimate(scip, bestvaluecand, uplb); /* create up child */ SCIP_CALL( SCIPcreateChild(scip, &upchild, upprio, estimate) ); /* change lower bound in up child */ SCIP_CALL( SCIPchgVarLbNode(scip, upchild, bestvaluecand, uplb) ); SCIPdebugMessage("branch on variable <%s> and value <%g>\n", SCIPvarGetName(bestvaluecand), bestbranchpoint); eqchild = NULL; } if( downchild != NULL || eqchild != NULL || upchild != NULL ) { *result = SCIP_BRANCHED; } else { /* if there are no children, then variable should have been fixed by SCIPbranchVar(Val) */ assert(SCIPisEQ(scip, SCIPvarGetLbLocal(bestaggrcand), SCIPvarGetUbLocal(bestaggrcand))); *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; }