All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
branch.c
Go to the documentation of this file.
26 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
203 assert(SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY);
205 SCIPdebugMessage("calculating LP branching candidates: validlp=%"SCIP_LONGINT_FORMAT", lpcount=%"SCIP_LONGINT_FORMAT"\n",
240 /* construct the LP branching candidate set, moving the candidates with maximal priority to the front */
265 /* LP branching candidates are fractional binary and integer variables; implicit variables are kept at the end
272 /* ignore fixed variables (due to numerics, it is possible, that the LP solution of a fixed integer variable
359 branchcand->nlpcands, SCIPvarGetName(var), primsol, frac, branchpriority, branchcand->lpmaxpriority,
364 /* in debug mode we assert that the variables are positioned correctly (binaries and integers first,
369 assert(c >= branchcand->nlpcands || SCIPvarGetType(branchcand->lpcands[c]) != SCIP_VARTYPE_IMPLINT);
370 assert(c < branchcand->nlpcands || SCIPvarGetType(branchcand->lpcands[c]) == SCIP_VARTYPE_IMPLINT);
378 SCIPdebugMessage(" -> %d fractional variables (%d of maximal priority)\n", branchcand->nlpcands, branchcand->npriolpcands);
390 SCIP_Real** lpcandssol, /**< pointer to store the array of LP candidate solution values, or NULL */
391 SCIP_Real** lpcandsfrac, /**< pointer to store the array of LP candidate fractionalities, or NULL */
393 int* npriolpcands, /**< pointer to store the number of candidates with maximal priority, or NULL */
394 int* nfracimplvars /**< pointer to store the number of implicit fractional variables, or NULL */
410 *npriolpcands = (set->branch_preferbinary && branchcand->npriolpbins > 0 ? branchcand->npriolpbins
421 SCIP_VAR*** externcands, /**< pointer to store the array of external branching candidates, or NULL */
422 SCIP_Real** externcandssol, /**< pointer to store the array of external candidate solution values, or NULL */
423 SCIP_Real** externcandsscore, /**< pointer to store the array of external candidate scores, or NULL */
424 int* nexterncands, /**< pointer to store the number of external branching candidates, or NULL */
425 int* nprioexterncands, /**< pointer to store the number of candidates with maximal priority, or NULL */
426 int* nprioexternbins, /**< pointer to store the number of binary candidates with maximal priority, or NULL */
427 int* nprioexternints, /**< pointer to store the number of integer candidates with maximal priority, or NULL */
428 int* nprioexternimpls /**< pointer to store the number of implicit integer candidates with maximal priority,
496 /** gets number of implicit integer external branching candidates with maximal branch priority */
513 return branchcand->nprioexterncands - branchcand->nprioexternbins - branchcand->nprioexternints - branchcand->nprioexternimpls;
516 /** insert variable, its score and its solution value into the external branching candidate storage
517 * the absolute difference of the current lower and upper bounds of the variable must be at least epsilon
533 assert(!SCIPsetIsEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))); /* the variable should not be fixed yet */
534 assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || !SCIPsetIsEQ(set, SCIPsetCeil(set, SCIPvarGetLbLocal(var)), SCIPsetFloor(set, SCIPvarGetUbLocal(var)))); /* a discrete variable should also not be fixed, even after rounding bounds to integral values */
535 assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR || !SCIPsetIsEQ(set, SCIPvarGetMultaggrLbLocal(var, set), SCIPvarGetMultaggrUbLocal(var, set))); /* also the current bounds of a multi-aggregated variable should not be fixed yet */
545 SCIPdebugMessage("inserting external candidate <%s> of type %d and priority %d into candidate set (maxprio: %d), score = %g, solval = %g\n",
548 /* insert the variable into externcands, making sure, that the highest priority candidates are at the front
572 * slot (binaries first, integers next, implicit integers next, continuous last) and increase the number
578 branchcand->externcandsscore[insertpos] = branchcand->externcandsscore[branchcand->nprioexterncands];
579 branchcand->externcandssol[insertpos] = branchcand->externcandssol[branchcand->nprioexterncands];
584 if( vartype == SCIP_VARTYPE_BINARY || vartype == SCIP_VARTYPE_INTEGER || vartype == SCIP_VARTYPE_IMPLINT )
586 if( insertpos != branchcand->nprioexternbins + branchcand->nprioexternints + branchcand->nprioexternimpls )
589 branchcand->externcands[branchcand->nprioexternbins + branchcand->nprioexternints + branchcand->nprioexternimpls];
591 branchcand->externcandsscore[branchcand->nprioexternbins + branchcand->nprioexternints + branchcand->nprioexternimpls];
593 branchcand->externcandssol[branchcand->nprioexternbins + branchcand->nprioexternints + branchcand->nprioexternimpls];
595 insertpos = branchcand->nprioexternbins + branchcand->nprioexternints + branchcand->nprioexternimpls;
622 branchcand->externcandsscore[insertpos] = branchcand->externcandsscore[branchcand->nprioexternbins];
623 branchcand->externcandssol[insertpos] = branchcand->externcandssol[branchcand->nprioexternbins];
638 SCIPdebugMessage(" -> inserted at position %d (nprioexterncands=%d)\n", insertpos, branchcand->nprioexterncands);
640 assert(0 <= branchcand->nprioexterncands && branchcand->nprioexterncands <= branchcand->nexterncands);
641 assert(0 <= branchcand->nprioexternbins && branchcand->nprioexternbins <= branchcand->nprioexterncands);
642 assert(0 <= branchcand->nprioexternints && branchcand->nprioexternints <= branchcand->nprioexterncands);
643 assert(0 <= branchcand->nprioexternimpls && branchcand->nprioexternimpls <= branchcand->nprioexterncands);
663 /** checks whether the given variable is contained in the candidate storage for external branching */
679 /* look for the variable in the externcands, using the fact, that the highest priority candidates are at the front
684 /* the branching priority of the variable is higher than the maximal priority contained in the array;
695 * look for it in the correct slot (binaries first, integers next, implicit integers next, continuous last)
717 if( branchcand->externcands[branchcand->nprioexternbins + branchcand->nprioexternints + i] == var )
723 for( i = branchcand->nprioexternbins + branchcand->nprioexternints + branchcand->nprioexternimpls;
729 /* the branching priority of the variable is lower than the maximal priority contained in the array;
744 SCIP_VAR*** pseudocands, /**< pointer to store the array of pseudo branching candidates, or NULL */
746 int* npriopseudocands /**< pointer to store the number of candidates with maximal priority, or NULL */
766 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
795 *npriopseudocands = (set->branch_preferbinary && branchcand->npriopseudobins > 0 ? branchcand->npriopseudobins
811 /** gets number of branching candidates with maximal branch priority for pseudo solution branching */
821 /** gets number of binary branching candidates with maximal branch priority for pseudo solution branching */
831 /** gets number of integer branching candidates with maximal branch priority for pseudo solution branching */
841 /** gets number of implicit integer branching candidates with maximal branch priority for pseudo solution branching */
848 return branchcand->npriopseudocands - branchcand->npriopseudobins - branchcand->npriopseudoints;
851 /** insert pseudocand at given position, or to the first positions of the maximal priority candidates, using the
872 SCIPdebugMessage("inserting pseudo candidate <%s> of type %d and priority %d into candidate set at position %d (maxprio: %d)\n",
875 /* insert the variable into pseudocands, making sure, that the highest priority candidates are at the front
898 * slot (binaries first, integers next, implicit integers last) and increase the number of maximal priority candidates
934 SCIPdebugMessage(" -> inserted at position %d (npriopseudocands=%d)\n", insertpos, branchcand->npriopseudocands);
936 assert(0 <= branchcand->npriopseudocands && branchcand->npriopseudocands <= branchcand->npseudocands);
937 assert(0 <= branchcand->npriopseudobins && branchcand->npriopseudobins <= branchcand->npriopseudocands);
938 assert(0 <= branchcand->npriopseudoints && branchcand->npriopseudoints <= branchcand->npriopseudocands);
941 /** sorts the pseudo branching candidates, such that the candidates of maximal priority are at the front,
953 assert(branchcand->npriopseudocands == 0); /* is only be called after removal of last maximal candidate */
970 assert(0 <= branchcand->npriopseudocands && branchcand->npriopseudocands <= branchcand->npseudocands);
971 assert(0 <= branchcand->npriopseudobins && branchcand->npriopseudobins <= branchcand->npriopseudocands);
972 assert(0 <= branchcand->npriopseudoints && branchcand->npriopseudoints <= branchcand->npriopseudocands);
994 SCIPdebugMessage("removing pseudo candidate <%s> of type %d and priority %d at %d from candidate set (maxprio: %d)\n",
995 SCIPvarGetName(var), SCIPvarGetType(var), branchpriority, var->pseudocandindex, branchcand->pseudomaxpriority);
997 /* delete the variable from pseudocands, making sure, that the highest priority candidates are at the front
1021 assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY || SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
1051 assert(0 <= branchcand->npriopseudocands && branchcand->npriopseudocands <= branchcand->npseudocands);
1052 assert(0 <= branchcand->npriopseudobins && branchcand->npriopseudobins <= branchcand->npriopseudocands);
1053 assert(0 <= branchcand->npriopseudoints && branchcand->npriopseudoints <= branchcand->npriopseudocands);
1055 /* if all maximal priority candidates were removed, resort the array s.t. the new maximal priority candidates
1089 if( (SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN)
1093 /* variable is neither continuous nor fixed and has non-empty domain: make sure it is member of the pseudo branching candidate list */
1112 /* variable is continuous or fixed or has empty domain: make sure it is not member of the pseudo branching candidate list */
1119 /** updates branching priority of the given variable and update the pseude candidate array if needed */
1139 /* if the variable currently belongs to priority set or the new branching priority is larger than the current one,
1151 /* of the variable is not part of the pseudo branching candidate array; check if it is a pseudo branching candidate
1174 return strcmp(SCIPbranchruleGetName((SCIP_BRANCHRULE*)elem1), SCIPbranchruleGetName((SCIP_BRANCHRULE*)elem2));
1187 SCIP_CALL( SCIPsetBranchrulePriority(scip, (SCIP_BRANCHRULE*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/
1204 SCIPdebugMessage("including branching rule %s in subscip %p\n", SCIPbranchruleGetName(branchrule), (void*)set->scip);
1220 int maxdepth, /**< maximal depth level, up to which this branching rule should be used (or -1) */
1221 SCIP_Real maxbounddist, /**< maximal relative distance from current node's dual bound to primal bound
1228 SCIP_DECL_BRANCHINITSOL((*branchinitsol)),/**< solving process initialization method of branching rule */
1229 SCIP_DECL_BRANCHEXITSOL((*branchexitsol)),/**< solving process deinitialization method of branching rule */
1230 SCIP_DECL_BRANCHEXECLP((*branchexeclp)), /**< branching execution method for fractional LP solutions */
1231 SCIP_DECL_BRANCHEXECEXT((*branchexecext)),/**< branching execution method for external solutions */
1232 SCIP_DECL_BRANCHEXECPS((*branchexecps)), /**< branching execution method for not completely fixed pseudo solutions */
1278 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "maximal depth level, up to which branching rule <%s> should be used (-1 for no limit)", name);
1283 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for applying branching rule (0.0: only on current best node, 1.0: on all nodes)");
1467 if( SCIPsetIsLE(set, loclowerbound - glblowerbound, branchrule->maxbounddist * (cutoffbound - glblowerbound)) )
1499 SCIPerrorMessage("branching rule <%s> returned invalid result code <%d> from LP solution branching\n",
1505 SCIPerrorMessage("branching rule <%s> added a constraint in LP solution branching without permission\n",
1563 if( SCIPsetIsLE(set, loclowerbound - glblowerbound, branchrule->maxbounddist * (cutoffbound - glblowerbound)) )
1595 SCIPerrorMessage("branching rule <%s> returned invalid result code <%d> from external solution branching\n",
1601 SCIPerrorMessage("branching rule <%s> added a constraint in external solution branching without permission\n",
1656 if( SCIPsetIsLE(set, loclowerbound - glblowerbound, branchrule->maxbounddist * (cutoffbound - glblowerbound)) )
1685 SCIPerrorMessage("branching rule <%s> returned invalid result code <%d> from pseudo solution branching\n",
1691 SCIPerrorMessage("branching rule <%s> added a constraint in pseudo solution branching without permission\n",
1744 SCIP_DECL_BRANCHCOPY ((*branchcopy)) /**< copy method of branching rule or NULL if you don't want to copy your plugin into sub-SCIPs */
1788 SCIP_DECL_BRANCHINITSOL((*branchinitsol)) /**< solving process initialization method of branching rule */
1799 SCIP_DECL_BRANCHEXITSOL((*branchexitsol)) /**< solving process deinitialization method of branching rule */
1812 SCIP_DECL_BRANCHEXECLP((*branchexeclp)) /**< branching execution method for fractional LP solutions */
1823 SCIP_DECL_BRANCHEXECEXT((*branchexecext)) /**< branching execution method for external candidates */
1834 SCIP_DECL_BRANCHEXECPS((*branchexecps)) /**< branching execution method for not completely fixed pseudo solutions */
1886 /** gets maximal depth level, up to which this branching rule should be used (-1 for no limit) */
1896 /** sets maximal depth level, up to which this branching rule should be used (-1 for no limit) */
1908 /** gets maximal relative distance from current node's dual bound to primal bound for applying branching rule */
1918 /** sets maximal relative distance from current node's dual bound to primal bound for applying branching rule */
2000 /** gets the total number of constraints, the branching rule added to the respective local nodes (not counting constraints
2099 /** calculates the branching score out of the gain predictions for a branching with arbitrary many children */
2113 /* search for the two minimal gains in the child list and use these to calculate the branching score */
2133 * if this value is at infinity, then 0.0 projected onto the bounds and then moved inside the interval is used
2135 * for a continuous variable, the parameter branching/clamp defines how far a branching point need to be from the bounds of a variable
2136 * the latter is only applied if no point has been suggested, or the suggested point is not inside the variable's interval
2189 /* if no point is suggested and the value in LP solution is not too big, try the LP or pseudo LP solution
2234 * very tiny means here an interval where we could not create two branches with reldiff > eps */
2268 /* if selected branching point is close to 0.0 and bounds are away from 0.0, it often makes sense to branch exactly on 0.0 */
2269 if( SCIPsetIsFeasZero(set, branchpoint) && SCIPsetIsFeasNegative(set, lb) && SCIPsetIsFeasPositive(set, ub) )
2278 /* variable is almost fixed at -/+ infinity, so suggest this infinity as branching point, what else could we do? */
2287 /* if branching point is too close to the lower bound and there is no upper bound, then move it to somewhere above the lower bound, but not above infinity */
2301 /* if branching point is too close to the upper bound and there is no lower bound, then move it to somewhere away from the upper bound, but not below infinity */
2327 /* if branchpoint is integral but not on bounds, then it should be one of the value {lb+1, ..., ub-1} */
2331 * @todo could in the same way be x <= x' and x >= x'+1; is there some easy way to know which is better? */
2346 /** calls branching rules to branch on an LP solution; if no fractional variables exist, the result is SCIP_DIDNOTRUN;
2347 * if the branch priority of an unfixed variable is larger than the maximal branch priority of the fractional
2348 * variables, pseudo solution branching is applied on the unfixed variables with maximal branch priority
2379 SCIPdebugMessage("branching on LP solution with %d (+%d) fractional (+implicit fractional) variables (%d of maximal priority)\n",
2387 /* if there is a non-fixed variable with higher priority than the maximal priority of the fractional candidates,
2392 SCIP_CALL( SCIPbranchExecPseudo(blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cutoffbound,
2402 for( i = 0; i < set->nbranchrules && (*result == SCIP_DIDNOTRUN || *result == SCIP_DIDNOTFIND); ++i )
2404 SCIP_CALL( SCIPbranchruleExecLPSol(set->branchrules[i], set, stat, tree, sepastore, cutoffbound, allowaddcons, result) );
2416 /* no branching method succeeded in choosing a branching: just branch on the first fractional variable with maximal
2441 SCIP_CALL( SCIPtreeBranchVar(tree, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue, var, SCIP_INVALID,
2450 /** calls branching rules to branch on an external solution; if no external branching candidates exist, the result is SCIP_DIDNOTRUN */
2471 assert(0 <= branchcand->nprioexterncands && branchcand->nprioexterncands <= branchcand->nexterncands);
2476 SCIPdebugMessage("branching on external solution with %d branching candidates (%d of maximal priority)\n",
2483 /* if there is a non-fixed variable with higher priority than the maximal priority of the external candidates,
2488 /* @todo: adjust this, that also LP branching might be called, if lpmaxpriority != externmaxpriority.
2491 SCIP_CALL( SCIPbranchExecPseudo(blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, cutoffbound,
2501 for( i = 0; i < set->nbranchrules && (*result == SCIP_DIDNOTRUN || *result == SCIP_DIDNOTFIND); ++i )
2503 SCIP_CALL( SCIPbranchruleExecExternSol(set->branchrules[i], set, stat, tree, sepastore, cutoffbound, allowaddcons, result) );
2515 /* if all branching rules did nothing, then they should also not have cleared all branching candidates */
2518 /* no branching method succeeded in choosing a branching: just branch on the first branching candidates with maximal
2519 * priority, and out of these on the one with maximal branch factor, and out of these on the one with largest domain
2537 if( SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(cand)) || SCIPsetIsInfinity(set, SCIPvarGetUbLocal(cand)) )
2543 if( priority > bestpriority || (priority == bestpriority && factor > bestfactor) || (priority == bestpriority && factor == bestfactor && domain > bestdomain) ) /*lint !e777*/
2559 SCIPdebugMessage("no branching method succeeded; fallback selected to branch on variable <%s> with bounds [%g, %g] on value %g\n",
2562 SCIP_CALL( SCIPtreeBranchVar(tree, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue, var, val,
2571 /** calls branching rules to branch on a pseudo solution; if no unfixed variables exist, the result is SCIP_DIDNOTRUN */
2592 SCIPdebugMessage("branching on pseudo solution with %d unfixed variables\n", branchcand->npseudocands);
2604 for( i = 0; i < set->nbranchrules && (*result == SCIP_DIDNOTRUN || *result == SCIP_DIDNOTFIND); ++i )
2606 SCIP_CALL( SCIPbranchruleExecPseudoSol(set->branchrules[i], set, stat, tree, cutoffbound, allowaddcons, result) );
2618 /* no branching method succeeded in choosing a branching: just branch on the first unfixed variable with maximal
2641 SCIP_CALL( SCIPtreeBranchVar(tree, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue, var, SCIP_INVALID,
|