Decision Optimization

Decision Optimization

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

 View Only
  • 1.  makeBranch(IloInt,NodeData*)

    Posted Sun January 27, 2019 08:59 AM

    Originally posted by: istenc


    Hello,

    I want to inherit data from parents to children. To this end, I use 'makeBranch' and 'NodeData'. At each node, I call makeBranch twice to generate two children as below. Since I don't want to interfere with the branching scheme of Cplex, I use 'makeBranch(IloInt,NodeData*)' constructor. Note that this code is only for test purpose and does not make much sense, accordingly. When I use the callback named as 'MyBranch', I get error on the first call of the second 'makeBranch' command in the callback.

     

    I couldn't figure out why it gives error and appreciate if you can help me.

    Best, İstenç

     

    IloInt current_branch_id = 0;

    class myNodeData : public IloCplex::MIPCallbackI::NodeData {
    public:
        IloInt Id; 

        myNodeData(IloInt i) : Id(i){};

    };


    ILOBRANCHCALLBACK0(MyBranch) {

        myNodeData * a_new_node_data;


        if (getNodeId()._id == 0) {

            a_new_node_data = new  myNodeData(current_branch_id);

            this->setNodeData(a_new_node_data);    

        }
        else 
        { 
            a_new_node_data = dynamic_cast <myNodeData *> (getNodeData());
        }


        if (getBranchType() != BranchOnVariable)
            return;


        current_branch_id++;
        myNodeData * myNodeData01 = new  myNodeData(current_branch_id);
        
        current_branch_id++;
        myNodeData * myNodeData02 = new  myNodeData(current_branch_id);
        
        makeBranch(myNodeData01->Id,  myNodeData01);
        makeBranch(myNodeData02->Id,  myNodeData02);    //ERROR OCCURS UPON THE FIRST CALL OF THİS MAKEBRANCH
        
    }


    #CPLEXOptimizers
    #DecisionOptimization


  • 2.  Re: makeBranch(IloInt,NodeData*)

    Posted Sun January 27, 2019 09:22 AM

    There are two bugs in your code:

    1. You assume that CPLEX always creates two branches. That may be wrong. You have to use the callbacks's getNbranches() function to query the number of branches CPLEX would create at this node.
    2. makeBranch(IloInt num, NodeData *data) can be invoked with num=0..getNbranches()-1 (note that branch indices start at 0!). You invoke this with num=1 and num=2 (since you increment current_branch_id before using it in the myNodeData contructor). So the second call will always fail since 2 is never a legal value for num.

    #CPLEXOptimizers
    #DecisionOptimization


  • 3.  Re: makeBranch(IloInt,NodeData*)

    Posted Mon January 28, 2019 08:11 AM

    Originally posted by: istenc


    Thanks for your quick reply. No error has occurred after fixing the second bug you specified. But now I have a new problem, some questions actually.

    I need to use 3 callback, specifically: branch, user cut and heuristic callback. As far as I understand, callbacks cannot be nested, so I am trying to figure out in what order these callbacks are called. To this end, I run the code at below:

    ILOHEURISTICCALLBACK0(MyHeuristic){
        cout << getNodeId() << ": heuristic is called" << endl;
    }

    ILOUSERCUTCALLBACK0(MyCut){
        cout << getNodeId() << ": cut is called" << endl;
    }

    ILOBRANCHCALLBACK0(MyBranch) {
        cout << getNodeId() << ": branch is called" << endl;
    }

    Output of my code after the root node is as such:


    2: cut is called
    2: cut is called
    2: branch is called
    2: heuristic is called
    1: cut is called
    1: cut is called
    1: branch is called
    1: heuristic is called
    4: cut is called
    4: cut is called
    4: branch is called
    4: heuristic is called

    ....

    I have two questions regarding my problem.

    i) Why user cut is called twice at each node?
    ii) I assumed cut callback is called firstly and heuristic callback follows it; lastly, branch callback is called. However, it seems that branch callback follows cut callback and heuristic callback is the last called one. Is this sequence always valid?

    Best,
    İstenç


    #CPLEXOptimizers
    #DecisionOptimization


  • 4.  Re: makeBranch(IloInt,NodeData*)

    Posted Mon January 28, 2019 08:28 AM

    The user cut callback may actually be called any number of times at each node. It is invoked during the cut loop. The cut loop does solve-separate-solve as long as new cuts are found. The callback has a method to check whether CPLEX is done with its own cuts. If you want to separate your cuts only once per node then it is a good idea to separate if this function (isAfterCutLoop()) returns true.

    It is correct that currently the heuristic callback is invoked after the branch callback (and both are invoked after the user cut callback).


    #CPLEXOptimizers
    #DecisionOptimization


  • 5.  Re: makeBranch(IloInt,NodeData*)

    Posted Mon January 28, 2019 10:13 AM

    Originally posted by: istenc


    Thanks again for your worthful help.


    #CPLEXOptimizers
    #DecisionOptimization