Decision Optimization

Decision Optimization

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

 View Only
  • 1.  Setting bounds on variables within BranchCallback

    Posted Tue March 19, 2019 11:28 AM

    Originally posted by: Rafael Colares


    Hi,

     

    I'm dealing with a binary IP and I'm trying to implement a BranchCallback within the C++ interface.

    Given a node of the Branch and Cut tree, I would like this callback to get the set of already-fixed variables and run an algorithm capable of yielding a set S of not-yet fixed variables that can be fixed for that node and its descendants.

     

    Until here, every thing is fine. However, when I try to actually impose the lower and upper bounds of the variables in S, (by stating x[i].setUB(0.0), to fix x[i] to 0 for instance), I get a segmentation fault problem. Notice that I am sure that the index i is within my ranges. I even tried to make a silly callback like the one below and the same error popped up:

    ILOBRANCHCALLBACK1(myFixing, const IloNumVarArray &, X) {
        X[1].setUB(0.0);
    }
    

    I guess using the method setUB is not the right way of doing such operation within a Callback... But then, how can I achieve this?

     

    Thank you in advance!


    #CPLEXOptimizers
    #DecisionOptimization


  • 2.  Re: Setting bounds on variables within BranchCallback

    Posted Tue March 19, 2019 12:42 PM

    You cannot modify the model that is being optmized from a callback. That will result in undefined behavior.

    The way to do these fixings is to include them into the branches you create with the callback's makeBranch() method: pass not only the branching variable but also all the variables to be fixed together with their fixing values as bounds.


    #CPLEXOptimizers
    #DecisionOptimization


  • 3.  Re: Setting bounds on variables within BranchCallback

    Posted Tue March 19, 2019 12:51 PM

    Originally posted by: Rafael Colares


    Thanks Daniel,

     

    I had thought of this, but then another question is raised:

    the set of variables I must pass as parameter for the makeBranch method is my set S of  variables to be fixed, plus the variable on which I want to effectively branch. I would like to not interfere too much on CPLEX's branching decision... But how can I obtain the variable that CPLEX initially wanted to branch on?

     

    Thanks.


    #CPLEXOptimizers
    #DecisionOptimization


  • 4.  Re: Setting bounds on variables within BranchCallback

    Posted Tue March 19, 2019 02:24 PM

    The branch callback has functions for this, see the reference documentation here.

    getNbranches() returns the number of branches CPLEX would create at this node, getBranch() can be used to obtain the intended branches.


    #CPLEXOptimizers
    #DecisionOptimization


  • 5.  Re: Setting bounds on variables within BranchCallback

    Posted Tue March 19, 2019 03:48 PM

    Originally posted by: Rafael Colares


    I'm sorry to insist Daniel. I have seen the doc but it remains unclear to me how I should procede to solve my problem.

    The getBranch() method requires IloNumVarArray vars, IloNumArray bounds, IloCplex::BranchDirectionArray dirs, IloInt i as entry parameters, where i is the i-th branch and thus must be between 0 and getNbranches()-1. 

    Consider that IloNumVarArray S_vec is my vector of not-yet fixed variables with corresponding new bounds stored in IloNumArray S_bounds and the respective directions on which to branch stored in IloCplex::BranchDirectionArray S_dirs. Then, I should call getBranch(S_vec, S_bounds, S_dirs, n) for n in 0...getNbranches()-1?

    The return value would be the num with which I should call makeBranch(IloInt num, NodeData * data=0) ? Or should I somehow pass the information of S_vec, S_bounds, S_dirs as a NodeData * data? 

     

    Initially, I thought I could just use makeBranch(const IloIntVarArray vars, const IloNumArray bounds, const IloCplex::BranchDirectionArray dirs, IloNum objestimate, NodeData * data=0) with vars = S_vec U cplexVar, where cplexVar is the branching variable selected by CPLEX...

     

    Again, I am sorry to be so insistent, but unfortunately the doc could not help me and I could not find any examples using getBranch method...

     

    Thanks for your attention.

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 6.  Re: Setting bounds on variables within BranchCallback

    Posted Wed March 20, 2019 08:05 AM

    getBranch() will resize the arrays passed to it! So don't call this with S_vec. Instead do something like this (untested code):

    int n = getNbranches();
    for (int b = 0; b < n; ++b) {
       IloNumVarArray vars(getEnv());
       IloNumArray bounds(getEnv());
       IloCplex::BranchDirectionArray dirs(getEnv());
       // Get CPLEX branch
       IloNum estimate = getBranch(vars, bounds, dirs, b);
       // Append variable fixings
       for (IloInt i = 0; i < S_vec.getSize(); ++i) {
          vars.add(S_vec[i]);
          bounds.add(S_bounds[i]);
          dirs.append(S_dirs[i]);
       }
       // Create branch with CPLEX variables and fixed variables
       makeBranch(vars, bounds, dirs, estimate);
       dirs.end();
       bounds.end();
       vars.end();
    }

     


    #CPLEXOptimizers
    #DecisionOptimization