Originally posted by: SystemAdmin
Here you go. Just compile the code and provide a model on the command line:
#include <iostream>
#include <ilcplex/ilocplex.h>
namespace {
/** A subclass of IloCplex::MIPCallbackI::NodeData that keeps track * of the depth of the current node. */
class DepthData : public IloCplex::MIPCallbackI::NodeData {
unsigned int const depth; /**< Depth of node at which this data * is stored. */
public:
DepthData(unsigned int idepth) : depth(idepth) {}
unsigned int getDepth() const { return depth; }
};
/** A global instance of DepthData that specifies the depth of the * root node. The API does not allow specifying node data for the * root node so we have to have an explicit instance for that * special case. */
DepthData const rootDepth(0);
/** Branch callback that keeps track of node depth. * The callback creates exactly the same branches as CPLEX would do. * Additionally, it uses the NodeData mechanism to store at each node * its depth in the branch and bound tree. */
struct BranchCallback : public IloCplex::BranchCallbackI {
BranchCallback(IloEnv env) : IloCplex::BranchCallbackI(env) {}
IloCplex::CallbackI *duplicateCallback() const {
return new (getEnv()) BranchCallback(getEnv());
}
void main() {
// How many branches would CPLEX create?
IloInt const nbranch = getNbranches();
if (nbranch > 0) {
// CPLEX would branch. Get the branches CPLEX would create
// and create exactly those branches. With each branch store
// its depth in the tree.
// Note that getNodeData() returns NULL for the root node.
DepthData const *data = dynamic_cast<DepthData *>(getNodeData());
if ( !data )
data = &rootDepth;
IloNumVarArray vars(getEnv());
IloNumArray bounds(getEnv());
IloCplex::BranchDirectionArray dirs(getEnv());
for (IloInt i = 0; i < nbranch; ++i) {
IloNum const est = getBranch(vars, bounds, dirs, i);
makeBranch(vars, bounds, dirs, est,
new DepthData(data->getDepth() + 1U));
}
dirs.end();
bounds.end();
vars.end();
}
else {
// CPLEX would not create any branch here. Prune the node.
prune();
}
}
};
/** Cut callback that reports the depth of the node on which it is invoked. */
struct CutCallback : public IloCplex::CutCallbackI {
CutCallback(IloEnv env) : IloCplex::CutCallbackI(env) {}
IloCplex::CallbackI *duplicateCallback() const {
return new (getEnv()) CutCallback(getEnv());
}
void main() {
// Get the depth of the current node. Note that getNodeData()
// returns NULL for the root node.
DepthData const *data = dynamic_cast<DepthData *>(getNodeData());
if ( !data )
data = &rootDepth;
std::cout << "Cut callback at node of depth "
<< data->getDepth() << std::endl;
}
};
}
/** A small example program that uses the callbacks defined above. * To run the program pass the name of a model file on the command line. */
int
main(int argc, char **argv)
{
for (int i = 1; i < argc; ++i) {
try {
IloEnv env;
IloModel model(env);
IloCplex cplex(model);
cplex.importModel(model, argv[i]);
cplex.use(new (env) BranchCallback(env));
cplex.use(new (env) CutCallback(env));
cplex.solve();
env.end();
} catch (IloException& e) {
std::cerr << "IloException: " << e << std::endl;
return -1;
}
}
return 0;
}
#CPLEXOptimizers#DecisionOptimization