Decision Optimization

Decision Optimization

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

 View Only
Expand all | Collapse all

How can I add cuts

Archive User

Archive UserWed June 10, 2015 11:33 AM

Archive User

Archive UserWed June 17, 2015 05:46 AM

Archive User

Archive UserTue July 07, 2015 08:33 AM

  • 1.  How can I add cuts

    Posted Wed June 03, 2015 09:43 AM

    Originally posted by: Namal


    Hello,

    how can I add custom cutting planes to get integer solutions of a problem? There is one example in C, but I want to use the c++ version. Can someone give me a link or a quick guide? Thanks a lot.


    #CPLEXOptimizers
    #DecisionOptimization


  • 2.  Re: How can I add cuts

    Posted Wed June 03, 2015 10:26 AM

    The iloadmipex5.cpp example shipped with CPLEX illustrates how to do that.


    #CPLEXOptimizers
    #DecisionOptimization


  • 3.  Re: How can I add cuts

    Posted Thu June 04, 2015 09:02 AM

    Originally posted by: Namal


    Ok, I tried this out with a simple example:

     

    #include <ilcplex/ilocplex.h>
    ILOSTLBEGIN
    
    
    ILOUSERCUTCALLBACK0(CtCallback) {
    
            IloRange cut;
            IloNumVar x1, x2;
            x1.setName("x");
            x2.setName("y");
            cut = (x1+ 2*x2 <= 6);
            add(cut).end();
    }
    
    
    
    
    
    static void populatebynonzero (IloModel model, IloNumVarArray x, IloRangeArray c)
    {
       IloEnv env = model.getEnv();
    
       IloObjective obj = IloMaximize(env);
       c.add(IloRange(env, -IloInfinity, 1.0));
       c.add(IloRange(env, -IloInfinity, 12.0));
       c.add(IloRange(env, -IloInfinity, 12.0));
    
       x.add(IloNumVar(env, 0, IloInfinity, ILOINT));
       x.add(IloNumVar(env, 0, IloInfinity, ILOINT));
       
    
       obj.setLinearCoef(x[1], 1.0);
       
       c[0].setLinearCoef(x[0], -1.0);
       c[0].setLinearCoef(x[1],  1.0);   
    
       c[1].setLinearCoef(x[0],  3.0);
       c[1].setLinearCoef(x[1],  2.0);
    
       c[2].setLinearCoef(x[0],  2.0);
       c[2].setLinearCoef(x[1],  3.0);
    
    
       c[0].setName("c1");
       c[1].setName("c2");
       c[2].setName("c3");
    
       x[0].setName("x");
       x[1].setName("y");
    
    
       model.add(obj);
       model.add(c);
    }
    
    
    
    int main (int argc, char **argv){
       
       IloEnv   env;
       try {
          IloModel model(env);
          
          IloCplex cplex(model);
          cplex.setParam(IloCplex::RootAlg, IloCplex::Primal);
          
          IloNumVarArray var(env);
          IloRangeArray con(env);
          
          populatebynonzero (model, var, con);
          
          cplex.use(CtCallback(env));
          
          if ( !cplex.solve() ) {
             env.error() << "Failed to optimize LP" << endl;
             throw(-1);
          }
    
          IloNumArray vals(env);
          env.out() << "Solution status = " << cplex.getStatus() << endl;
          env.out() << "Solution value  = " << cplex.getObjValue() << endl;
          cplex.getValues(vals, var);
          env.out() << "Values        = " << vals << endl;
          cplex.getSlacks(vals, con);
          env.out() << "Slacks        = " << vals << endl;
    
                    
       }
       catch (IloException& e) {
          cerr << "Concert exception caught: " << e << endl;
       }
       catch (...) {
          cerr << "Unknown exception caught" << endl;
       }
    
       env.end();
    
       return 0;
    }
    

    How can I get the (float) values after the computation with that cut or stop further calculation at all?


    #CPLEXOptimizers
    #DecisionOptimization


  • 4.  Re: How can I add cuts

    Posted Mon June 08, 2015 01:43 AM

    The cut callback is invoked during the cut loop. After the callback completes, CPLEX resolves the (potentially augmented) relaxation and invokes the cut callback again. So you can grab the new relaxation values in the next invocation of the callback using the callback's getValue() method. You may also want to check the return value of the callback's isAfterCutLoop() function to identify where in the loop you are. To stop the cut loop use abortCutLoop().


    #CPLEXOptimizers
    #DecisionOptimization


  • 5.  Re: How can I add cuts

    Posted Tue June 09, 2015 06:54 AM

    Originally posted by: Namal


    Hello Daniel, I have changed in the 28/29 ILOINT to ILOFLOAT, but after adding the cut I don't get  a (worse) solution, does cplex decide not to add a cut if the solution is getting worse?


    #CPLEXOptimizers
    #DecisionOptimization


  • 6.  Re: How can I add cuts

    Posted Wed June 10, 2015 01:57 AM

    Whether CPLEX is allowed to potentially ignore your cut depends on the 'purgeable' argument of the add() function, please see the reference documentation.

    Please also note that adding a violated cut does not necessarily increase the objective function value of the relaxation. It is well possible that adding a violated cut only changes the solution vector but not the objective value.

    I am not sure what you tried to achieve by changing all your variables to ILOFLOAT. That turns your problem into a pure LP and for pure LPs the cut callback is not even invoked.


    #CPLEXOptimizers
    #DecisionOptimization


  • 7.  Re: How can I add cuts

    Posted Wed June 10, 2015 11:33 AM

    Originally posted by: Namal


    Hello Daniel, 

     

    actually yes, I am trying to solve a problem with LP (simplex) only. But I am not interested in the optimal solution, just any integer solution. And for low number of constraints cplex gives me an integer solution.  Or is there a better way to get some integer solution?


    #CPLEXOptimizers
    #DecisionOptimization


  • 8.  Re: How can I add cuts

    Posted Wed June 10, 2015 04:13 PM

    If you leave your model as a MIP and set the relative MIP gap parameter (IloCplex::Param::MIP::Tolerances::MIPGap) to 1.0, CPLEX should accept the first integer-feasible solution it finds as the winner and stop.


    #CPLEXOptimizers
    #DecisionOptimization


  • 9.  Re: How can I add cuts

    Posted Fri June 12, 2015 10:11 AM

    Originally posted by: Namal


    Hello again,

     

    if I make the problem a MIP, how can I stop further calculation after the first relaxation. Also, how can I test whether the variables I get this way are integer or not?


    #CPLEXOptimizers
    #DecisionOptimization


  • 10.  Re: How can I add cuts

    Posted Tue June 16, 2015 04:12 PM

    if I make the problem a MIP, how can I stop further calculation after the first relaxation.

    Set the NodeLimit parameter (IloCplex::Param::MIP::Limits::Nodes) to 0. CPLEX will stop after processing the "root node" (the original LP).

    Also, how can I test whether the variables I get this way are integer or not?

    Get their values, round to the nearest integer, take the absolute difference between the rounded and rounded values, and see if the absolute differences are small enough for your purposes.


    #CPLEXOptimizers
    #DecisionOptimization


  • 11.  Re: How can I add cuts

    Posted Tue June 23, 2015 12:21 AM

    In order to stop after the first integer solution found, set CPX_PARAM_INTSOLLIM to 1. Note that this may stop even before the initial relaxation is solved since heuristics may find solutions earlier than that. If you don't want that to happen you can disable heuristics.


    #CPLEXOptimizers
    #DecisionOptimization


  • 12.  Re: How can I add cuts

    Posted Wed June 17, 2015 05:46 AM

    Originally posted by: Namal


    Hello Paul,

     

    well I believe I have two options.

     

    1) I leave my variables as ILOFLOAT solve the LP and just test then for integer values.

    2) I define them as ILOINT and abort cplex after first relaxation before branching starts. Then I believe I can just test it with cplex.getStatus(). It should return optimal if I have integers only? I have to abort in the callback, right? (IloCplex::Param::MIP::Limits::Nodes) to 0 didn't help, I still get integer values where I shouldn't.


    #CPLEXOptimizers
    #DecisionOptimization


  • 13.  Re: How can I add cuts

    Posted Thu June 18, 2015 03:27 PM

    2) I define them as ILOINT and abort cplex after first relaxation before branching starts. Then I believe I can just test it with cplex.getStatus(). It should return optimal if I have integers only?

    No. If the solution at the root node is integer feasible, CPLEX should return "Feasible" as the status, not "Optimal".

    I have to abort in the callback, right? (IloCplex::Param::MIP::Limits::Nodes) to 0 didn't help, I still get integer values where I shouldn't.

    I'm not sure how to interpret "where I shouldn't". Are you saying that there are variables that cannot take integer values? Variables not constrained to be integer may still take integer values by chance (if the optimal vertex at the root node, after CPLEX is done adding cuts, happens to have integer values for those variables).


    #CPLEXOptimizers
    #DecisionOptimization


  • 14.  Re: How can I add cuts

    Posted Tue July 07, 2015 08:33 AM

    Originally posted by: Namal


    Hello,

     

    well I mean if I have a simple problem like this

     

       x.add(IloNumVar(env, 0.0, IloInfinity, ILOINT));
       x.add(IloNumVar(env, 0.0, IloInfinity, ILOINT));
    
       model.add(IloMaximize(env, x[1]));
    
       c.add(   -x[0] +     x[1]  <= 1);
       c.add(3 * x[0] + 2 * x[1]  <= 12);
       c.add(2 * x[0] + 3 * x[1]  <= 12);
    

    cplex gives me the solution [2,2]

     

    if I add

     

          cplex.setParam(IloCplex::RootAlg, IloCplex::Dual);
          cplex.setParam(IloCplex::Param::MIP::Tolerances::MIPGap, 1.0);
    

    it gives me the solution [1,2]

    but the first relaxation to this problem is [1.8, 2.8]

    It seems like the decimals are cut off. How can I get these values as floats?


    #CPLEXOptimizers
    #DecisionOptimization


  • 15.  Re: How can I add cuts

    Posted Tue July 07, 2015 04:00 PM

    You could attach a heuristic callback (which will be called after the node LP is solved, including CPLEX's cut loop). In it, you can call getValue() or getValues() to get the values of the node LP solution.

    With this approach, I think you do not want to set the integer solution limit to 1. If you do, and a root node heuristic finds an integer-feasible solution, I don't think the heuristic callback will be entered. Setting the node limit is fine.


    #CPLEXOptimizers
    #DecisionOptimization