Branch and cut
Branch and cut
Algorithm
This description assumes the ILP is a maximization problem.
The method solves the
At this point, the
The algorithm is summarized below.
- Add the initial ILP to , the list of active problems
- Set and
- while is not empty
- Select and remove (de-queue) a problem from
- Solve the LP relaxation of the problem.
- If the solution is infeasible, go back to 3 (while). Otherwise denote the solution by with objective value .
- If , go back to 3.
- If is integer, set and go back to 3.
- If desired, search for cutting planes that are violated by . If any are found, add them to the LP relaxation and return to 3.2.
- Branch to partition the problem into new problems with restricted feasible regions. Add these problem to and go back to 3
- return
Pseudocode
In C++-like pseudocode, this could be written:
// ILP branch and cut solution pseudocode, assuming objective is to be maximized
ILP_solution branch_and_cut_ILP(IntegerLinearProgram initial_problem) {
queue active_list; // L, above
active_list.enqueue(initial_problem); // step 1
// step 2
ILP_solution optimal_solution; // this will hold x* above
double best_objective = -std::numeric_limits<double>::infinity; // will hold v* above
while (!active_list.empty()) { // step 3 above
LinearProgram& curr_prob = active_list.dequeue(); // step 3.1
do { // steps 3.2-3.7
RelaxedLinearProgram& relaxed_prob = LP_relax(curr_prob); // step 3.2
LP_solution curr_relaxed_soln = LP_solve(relaxed_prob); // this is x above
bool cutting_planes_found = false;
if (!curr_relaxed_soln.is_feasible()) { // step 3.3
continue; // try another solution; continues at step 3
}
double current_objective_value = curr_relaxed_soln.value(); // v above
if (current_objective_value <= best_objective) { // step 3.4
continue; // try another solution; continues at step 3
}
if (curr_relaxed_soln.is_integer()) { // step 3.5
best_objective = current_objective_value;
optimal_solution = cast_as_ILP_solution(curr_relaxed_soln);
continue; // continues at step 3
}
// current relaxed solution isn't integral
if (hunting_for_cutting_planes) { // step 3.6
violated_cutting_planes = search_for_violated_cutting_planes(curr_relaxed_soln);
if (!violated_cutting_planes.empty()) { // step 3.6
cutting_planes_found = true; // will continue at step 3.2
for (auto&& cutting_plane : violated_cutting_planes) {
active_list.enqueue(LP_relax(curr_prob, cutting_plane));
}
continue; // continues at step 3.2
}
}
// step 3.7: either violated cutting planes not found, or we weren't looking for them
auto&& branched_problems = branch_partition(curr_prob);
for (auto&& branch : branched_problems) {
active_list.enqueue(branch);
}
continue; // continues at step 3
} while (hunting_for_cutting_planes /* parameter of the algorithm; see 3.6 */
&& cutting_planes_found);
// end step 3.2 do-while loop
} // end step 3 while loop
return optimal_solution; // step 4
}
In the above pseudocode, the functions LP_relax
, LP_solve
and branch_partition
called as subroutines must be provided as applicable to the problem. For example, LP_solve
could call the
branch_partition
are discussed below.
Branching strategies
An important step in the branch and cut algorithm is the branching step. At this step, there are a variety of branching heuristics that can be used. The branching strategies described below all involve what is called branching on a variable.[3] Branching on a variable involves choosing a variable, , with a fractional value, , in the optimal solution to the current LP relaxation and then adding the constraints and
- Most infeasible branching
- This branching strategy chooses the variable with the fractional part closest to 0.5.
- Pseudo cost branching
- The basic idea of this strategy is to keep track for each variable the change in the objective function when this variable was previously chosen as the variable to branch on. The strategy then chooses the variable that is predicted to have the most change on the objective function based on past changes when it was chosen as the branching variable. Note that pseudo cost branching is initially uninformative in the search since few variables have been branched on.
- Strong branching
- Strong branching involves testing which of the candidate variable gives the best improvement to the objective function before actually branching on them. Full strong branching tests all candidate variables and can be computationally expensive. The computational cost can be reduced by only considering a subset of the candidate variables and not solving each of the corresponding LP relaxations to completion.
There are also a large number of variations of these branching strategies, such as using strong branching early on when pseudo cost branching is relatively uninformative and then switching to pseudo cost branching later when there is enough branching history for pseudo cost to be informative.
References
- ISSN 0036-1445.
- ^ John E., Mitchell (2002). "Branch-and-Cut Algorithms for Combinatorial Optimization Problems" (PDF). Handbook of Applied Optimization: 65–77.
- .
External links
- Mixed Integer Programming
- SCIP: framework for branch-cut-and-price and a mixed integer programming solver
- ABACUS – A Branch-And-CUt System – open source software
- COIN-OR Cbc – open source software on GitHub