Decision Optimization

Decision Optimization

Delivers prescriptive analytics capabilities and decision intelligence to improve decision-making.


#Analytics
#DecisionOptimization
#DecisionOptimization
 View Only
  • 1.  CutCallback, Node Depth and C++

    Posted 09/24/10 04:56 AM

    Originally posted by: RodrigoLinfati


    Hi to all.

    How i can determine the node depth inside of a CutCallback ?

    thanks.
    #CPLEXOptimizers
    #DecisionOptimization


  • 2.  Re: CutCallback, Node Depth and C++

    Posted 09/24/10 05:32 AM

    Originally posted by: SystemAdmin


    Unfortunately, there is no direct way to do this. However, you can keep track of that depth using a branch callback and a subclass of NodeData.
    This thread discusses how to know on which variable you branched in a cut callback. Keeping track of the depth of a node should work analogously.
    If you cannot work out the details from this thread then please tell me and I will post some code here.
    #CPLEXOptimizers
    #DecisionOptimization


  • 3.  Re: CutCallback, Node Depth and C++

    Posted 09/24/10 07:10 AM

    Originally posted by: RodrigoLinfati


    thanks, if you can show some example how to get the Depth of the CURRENT node in a CutCallback.
    #CPLEXOptimizers
    #DecisionOptimization


  • 4.  Re: CutCallback, Node Depth and C++

    Posted 09/24/10 07:12 AM

    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


  • 5.  Re: CutCallback, Node Depth and C++

    Posted 09/27/10 05:52 AM

    Originally posted by: RodrigoLinfati


    Thbaks, work great.

    only one ask... when i add only the brachcallback cplex show a diferent log... why? the branch callback disable some heuristic or presolver of cplex?
    #CPLEXOptimizers
    #DecisionOptimization


  • 6.  Re: CutCallback, Node Depth and C++

    Posted 09/27/10 07:54 AM

    Originally posted by: SystemAdmin


    Adding a branch and/or cut callback disables dynamic search (you should see a warning message about that in the output) and this will produce a while different log.
    Moreover, in very rare cases the mere presence of a callback may change the path but I think this is unlikely in your case. Probably you are simply seeing a different log as dynamic search is disabled.
    #CPLEXOptimizers
    #DecisionOptimization