Example: deriving the simplex callback ilolpex4.cpp
Illustrates derivation of a simplex callback in the C++ API.
Example ilolpex4.cpp
demonstrates
the use of the simplex callback to print logging information at each
iteration. It is a modification of example ilolpex1.cpp
,
so this discussion concentrates on the differences. The following
code:
ILOSIMPLEXCALLBACK0(MyCallback) {
cout << "Iteration " << getNiterations() << ": ";
if ( isFeasible() ) {
cout << "Objective = " << getObjValue() << endl;
}
else {
cout << "Infeasibility measure = " << getInfeasibility() << endl;
}
}
defines the callback MyCallback
without arguments with the code enclosed in the outer {}
.
In Java, the same callback is defined
like this:
static class MyCallback extends IloCplex.ContinuousCallback {
public void main() throws IloException {
System.out.print("Iteration " + getNiterations() + ": ");
if ( isFeasible() )
System.out.println("Objective = " + getObjValue());
else
System.out.println("Infeasibility measure = "
+ getInfeasibility());
}
}
The callback prints the iteration number. Then, depending
on whether the current solution is feasible or not, it prints the
objective value or infeasibility measure. The methods getNiterations
, isFeasible
, getObjValue
,
and getInfeasibility
are methods provided
in the base class of the callback, IloCplex::ContinuousCallbackI
(IloCplex.ContinuousCallback
or Cplex.ContinuousCallback
).
See the Reference Manual of the C++
API for the complete list of methods provided for
each callback class.
Here is the previous sample of code, with the macro ILOSIMPLEXCALLBACK0
expanded:
class MyCallbackI : public IloCplex::SimplexCallbackI {
void main();
IloCplex::CallbackI* duplicateCallback() const {
return (new (getEnv()) MyCallbackI(*this));
}
};
IloCplex::Callback MyCallback(IloEnv env) {
return (IloCplex::Callback(new (env) MyCallbackI()));
}
void MyCallbackI::main() {
cout << "Iteration " << getNiterations() << ": ";
if ( isFeasible() ) {
cout << "Objective = " << getObjValue() << endl;
}
else {
cout << "Infeasibility measure = " << getInfeasibility() << endl;
}
}
The 0
(zero) in the macro
indicates that no arguments are passed to the constructor of the callback.
For callbacks requiring up to 7 arguments, similar macros are defined
where the 0
is replaced by the number
of arguments, ranging from 1 through 7. For an example using the cut
callback, see Example: controlling cuts iloadmipex5.cpp.
If you need more than 7 arguments, you will need to derive your callback
class yourself without the help of a macro.
After the callback MyCallback
is defined, it can be used with the line:
cplex.use(MyCallback(env));
in C++cplex.use(new MyCallback());
in Javacplex.Use(new MyCallback());
in .NET
In the case of C++, the function MyCallback
creates
an instance of the implementation class MyCallbackI
.
A handle to this implementation object is passed to the method IloCplex::use
.
If your application defines more than one simplex callback
object (possibly with different subclasses), only the last one passed
to CPLEX with the use
method is actually
used during simplex. On the other hand, IloCplex
can
manage one callback for each callback class at the same time. For
example, a simplex callback and a MIP callback can be used at the
same time.
The complete program, ilolpex4.cpp
,
appears online in the standard distribution at yourCPLEXinstallation/examples/src
.
In the same location, there are also samples in Java (LPex4.java
)
and in the .NET API (LPex4.cs
and LPex4.vb
).