| Overview | Group | Tree | Graph | Index | 
| Branch & Cut | 
| Goals | 
IloCplex, 
like all CPLEX technologies, uses 
branch & cut search 
when solving mixed integer programming (MIP) models. 
The branch & cut search procedure manages a search tree 
consisting of nodes. Every node represents 
an LP or QP subproblem to be processed; that is, to be solved, 
to be checked for integrality, and perhaps to be analyzed further. 
Nodes are called active if they have not yet 
been processed. After a node has been processed, it is no longer active. 
IloCplex processes active nodes in the tree until 
either no more active nodes are available or some limit has been reached.
A branch is the creation of two new nodes from a parent node. Typically, a branch occurs when the bounds on a single variable are modified, with the new bounds remaining in effect for that new node and for any of its descendants. For example, if a branch occurs on a binary variable, that is, one with a lower bound of 0 (zero) and an upper bound of 1 (one), then the result will be two new nodes, one node with a modified upper bound of 0 (the downward branch, in effect requiring this variable to take only the value 0), and the other node with a modified lower bound of 1 (the upward branch, placing the variable at 1). The two new nodes will thus have completely distinct solution domains.
A cut is a constraint added to the model. The purpose of adding any cut is to limit the size of the solution domain for the continuous LP or QP problems represented at the nodes, while not eliminating legal integer solutions. The outcome is thus to reduce the number of branches required to solve the MIP.
As an example of a cut, first consider the following constraint involving three binary (0-1) variables:
20x + 25y + 30z <= 40
That sample constraint can be strengthened by adding the following cut to the model:
1x + 1y + 1z <= 1
No feasible integer solutions are ruled out by the cut, but some fractional solutions, for example (0.0, 0.4, 1.0), can no longer be obtained in any LP or QP subproblems at the nodes, possibly reducing the amount of searching needed.
The branch & cut method, then, consists of performing branches and applying cuts at the nodes of the tree. Here is a more detailed outline of the steps involved.
First, the branch & cut tree is initialized to contain the root node 
as the only active node. The root node of the tree represents the entire 
problem, ignoring all of the explicit integrality requirements. Potential 
cuts are generated for the root node but, in the interest of keeping the 
problem size reasonable, not all such cuts are applied to the model 
immediately. An incumbent solution, that is, the best known 
solution that satisfies all the integrality requirements, is established 
at this point for later use in the algorithm. Ordinarily, no such solution 
is available at this stage, but the user can specify a starting solution 
using the method setVectors. 
Alternatively, when solving a sequence of modified problems, 
the user can set the parameter MIPStart 
to the value 1 (one) to indicate that the solution of the previous problem 
should be used as a starting incumbent for the present problem.
When processing a node, IloCplex 
starts by solving the continuous relaxation of its subproblem. 
that is, the subproblem without integrality constraints. 
If the solution violates any cuts, IloCplex 
may add some or all of them to the node problem and resolves it. 
This procedure is iterated until no more violated cuts are detected 
(or deemed worth adding at this time) by the algorithm. 
If at any point in the addition of cuts the node becomes infeasible, 
the node is pruned (that is, it is removed from the tree).
Otherwise, IloCplex 
checks whether the solution of the node-problem satisfies the 
integrality constraints. If so, and if its objective value is better 
than that of the current incumbent, the solution of the node-problem 
is used as the new incumbent. If not, branching will occur, but first 
a heuristic method may be tried at this point to see if a new incumbent 
can be inferred from the LP/QP solution at this node, 
and other methods of analysis may be performed on this node. 
The branch, when it occurs, is performed on a variable where the
value of the present solution violates its integrality requirement. 
This practice results in two new nodes being added to the tree for 
later processing.
Each node, after its relaxation is solved, possesses an optimal objective function value Z. At any given point in the algorithm, there is a node whose Z value is better (less, in the case of a minimization problem, or greater for a maximization problem) than all the others. This Best Node value can be compared to the objective function value of the incumbent solution. The resulting MIP Gap, expressed as a percentage of the incumbent solution, serves as a measure of progress toward finding and proving optimality. When active nodes no longer exist, then these two values will have converged toward each other, and the MIP Gap will thus be zero, signifying that optimality of the incumbent has been proven.
It is possible to tell IloCplex 
to terminate the branch & cut procedure sooner 
than a completed proof of optimality. For example, a user can set
a time limit or a limit on the number of nodes to be processed. 
Indeed, with default settings, IloCplex 
will terminate the search when the MIP Gap has been brought 
lower than 0.0001 (0.01%), because it is often the case that 
much computation is invested in moving the Best Node value after 
the eventual optimal incumbent has been located. This termination 
criterion for the MIP Gap can be changed by the user, of course.
Goals can be used to control the branch and cut search in 
IloCplex
. Goals are implemented in the class 
IloCplex::GoalI
. The class 
IloCplex::Goal
 is the handle class. That is, it contains a pointer to an instance of 
IloCplex::GoalI
along with accessors of objects in the implmenetation class.
To implement your own goal, you need to subclass 
IloCplex::GoalI
 and implement its virtual member functions execute
 and duplicateGoal. The method execute
 controls the branch & cut search. The method duplicateGoal
 creates a copy of the invoking goal object to be used for 
parallel branch & cut search. Implementing your goal can be greatly 
simplified if you use one  of the macros 
ILOCPLEXGOALn.
Every branch & cut node maintains a goal stack, possibly containing 
IloCplex::GoalI
 objects. After 
IloCplex
 solves the relaxation of a node, it pops the top goal 
from the goal stack and calls its method execute. 
There are several types of goals:
OrGoal is executed, 
IloCplex
 will create child nodes. Each of the child nodes will be 
initialized with a copy of the goal stack of the current node. 
Then, for each child node, the specified goal in the OrGoal
 is pushed onto the corresponding goal stack of the child node. 
Finally, the current node is deleted. (See 
IloCplex#GoalI::OrGoal
 for a more detailed discussion.)AndGoal
 is executed, its subgoals are simply pushed onto the stack. (See 
IloCplex::GoalI::AndGoal
 for a more detailed discussion.)
IloCplex::GoalI::FailGoal
 is executed, 
IloCplex
 will prune the current node; that is,  
it will discontinue the search at the current node. 
IloCplex
 will continue with another node 
if there is one still available in the tree.
IloCplex::GoalI::SolutionGoal
 is executed, 
IloCplex
 will attempt to inject a user-provided solution as a new incumbent. 
Before ILOG CPLEX accepts the injected solution, 
it first tests whether the injected solution is feasible with respect to 
the model and goals.IloCplex
 continues popping goals from the goal stack until OrGoal
 or FailGoal is executed, 
or until the stack becomes empty; in the case of an empty stack, 
it will continue with a built-in search strategy.
The predefined goals OrGoal
 and AndGoal
 allow you to combine goals. AndGoal
 allows you to execute different goals at one node, 
while OrGoal
 allows you to execute different goals on different, newly created nodes. 
A conventional use of these two goals in a return statement of a 
user-written goal looks like this:
return AndGoal ( OrGoal (branch1, branch2), this);
This AndGoal
 first pushes this
 (the goal currently being executed) onto the goal stack, 
 and then it pushes the OrGoal. 
Thus the OrGoal
 is on top of the stack and will be executed next. 
When the OrGoal executes, 
it creates two new nodes and copies the remaining goal stack to both of them. 
Thus both new nodes will have this
 goal on top of the goal stack at this point. Then the OrGoal
 proceeds to push branch1
 onto the goal stack of the first child node and branch2
 onto the goal stack of the second goal child node. 
Conventionally, branch1 and branch2
 contain cut goals, so by executing branch1
 and branch2
 at the respective child nodes, 
the child nodes will be restricted to represent smaller subproblems 
than their parent. After branch1
 and branch2 have been executed, this
 is on top of the node stack of both child nodes; 
that is, both child nodes will continue branching according to the same rule. 
In summary, this example creates the branches branch1
 and branch2
 and continues in both branches to control the same search strategy 
this.
 
To perform a search using a goal, you need to solve the extracted model 
by calling the method IloCplex::solve(goal)
 with the goal to use as an argument instead of the standard 
IloCplex::solve. The method solve(goal)
 simply pushes the goal
 onto the goal stack of the root node before calling the standard  
solve.
See Also
IloCplex::Goal and IloCplex::GoalI