ILOG CPLEX 11.0 User's Manual > Advanced Programming Techniques > Using Goals > Example: Goals in Branch & Cut

Consider the following example to clarify the discussions of goals. This example is available as ilogoalex1.cpp in the examples/src subdirectory of your ILOG CPLEX distribution. The equivalent Java implementation can be found as GoalEx1.java in the same location. The C#.NET version is in Goalex1.cs and the VB.NET version is in Goalex1.vb.

This example shows how to implement and use a goal for controlling the branch strategy used by ILOG CPLEX. As discussed, goals are implemented as subclasses of the class IloCplex::GoalI (IloCplex.Goal or Cplex.Goal). The C++ implementation of that example uses the macro

ILOCPLEXGOAL1(MyBranchGoal, IloNumVarArray, vars)

instead. This macro defines two things, class MyBranchGoalI and the function

IloCplex::Goal MyBranchGoal(IloEnv env, IloNumVarArray vars);

The class MyBranchGoalI is defined as a subclass of class IloCplex::GoalI (IloCplex.Goal or Cplex.Goal) and has a private member IloNumVarArray vars. The function MyBranchGoal creates an instance of class MyBranchGoalI, initializes the member vars to the argument vars passed to the function, and returns a handle to the new goal object. The curly brackets "{ ... }" following the macro enclose the implementation of the method MyBranchGoalI::execute containing the actual code of the goal.

The use of the macro is very convenient as the amount of user code is equivalent to the amount for defining a function, but with a slightly unusual syntax. IloCplex provides seven such macros that can be used for defining goals with 0 to 6 private members. If more than 6 members are needed, IloCplex::GoalI (IloCplex.Goal or Cplex.Goal) must be subclassed by hand.

Since the Java programming language does not provide macros, a subclass of IloCplex.Goal must always be implemented by hand. In this example, this class is called MyBranchGoal and there is no helper function for creating an instance of that class (as the macro does in the case of C++).

The goal is then used for solving the extracted node by calling:

cplex.solve(MyBranchGoal(env, var));

for C++, or for Java:

cplex.solve(new MyBranchGoal(var));

instead of the usual cplex.solve. The rest of the main function contains nothing new and will not be discussed any further.

In the implementation of the goal, or more precisely its method execute, starts by declaring and initializing some arrays. These arrays are then used by methods of class IloCplex::GoalI (IloCplex.Goal or Cplex.Goal) to query information about the node subproblem and the solution of its relaxation. The method getValues is used to query the solution values for the variables in vars, method getObjCoefs is used to query the linear objective function coefficients for these variables, and method getFeasibilities is used to query feasibility statuses for them. The feasibility status of a variable indicates whether IloCplex considers the current solution value of the variable to be integer feasible or not. IloCplex::GoalI (IloCplex.Goal or Cplex.Goal) provides a wealth of other query methods. For details, see the ILOG CPLEX Reference Manuals.

Once you have gathered information about the variables, their objective coefficients, and their current feasibility statuses, compute the index of an integer infeasible variable in vars that has the largest objective coefficients among the variables with largest integer infeasibility. That index is recorded in variable bestj.

Then create a new goal handle object res. By default, this is initialized to an empty goal. However, if an integer infeasible variable was found among those in vars, then variable bestj will be 0 and a nonempty goal will be assigned to res:

res = AndGoal(OrGoal(vars[bestj] >= IloFloor(x[bestj])+1,
                     vars[bestj] <= IloFloor(x[bestj])),
                     this);

This goal creates two branches, one for images/goalsa5.gif and one for images/goalsa6.gif and continues branching in both subtrees with the same goal this. Finally, call method end for all temporary arrays and return goal res.

Since Java objects are garbage collected, there is no need for the variable res. Instead, depending on the availability of an integer infeasible variable, the null goal is returned or the returned goal is created in the return statement itself:

return cplex.and(cplex.or(cplex.geGoal(_vars[bestj],
                          Math.floor(x[bestj]))+1,
                          cplex.leGoal(_vars[bestj],
                          Math.floor(x[bestj]))),
                 this);