Decision Optimization

Decision Optimization

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


#Analytics
#DecisionOptimization
#DecisionOptimization
 View Only
  • 1.  Solving MIP model as an LP

    Posted 04/16/19 10:23 AM

    Originally posted by: JorisK


    Given an IloCplex MIP model, I'm trying to solve the LP relaxation. One could set the nodeLim=0, but that is not exactly the same as solving the LP relaxation because: 

    • with nodeLim=0, cplex still creates cuts and applies heuristics at the root
    • dual values and reduced costs can only be queried if the problem is an actual LP, not a MIP

    So in order to solve the pure LP relaxation, all variables must be of the type ILOFLOAT. One easy way to fix this is to iterate over all integer variables in the model and to apply an IloConversion to those variable. This works if you store a reference to each integer variable. Interestingly, the following does not work:

     

    public static void solveLP(IloCplex cplex) throws IloException {
        //Convert all integer variables into continuous variables
        List<IloConversion> conversions=new LinkedList<>();
        for(Iterator it = cplex.iterator(); it.hasNext(); ){
            Object o=it.next();
            if(o instanceof IloIntVar){
                IloIntVar var=(IloIntVar) o;
                IloConversion conv=cplex.conversion(var, IloNumVarType.Float);
                conversions.add(conv);
                cplex.add(conv);
            }
        }
        //Do something with the model, e.g. solve
        cplex.solve();
    
        //Restore original model
        for(IloConversion conv : conversions)
            cplex.remove(conv);
    }
    
    public static IloCplex buildModel() throws IloException {
        IloCplex cplex = new IloCplex();
        IloNumVar[] vars = new IloNumVar[3];
        vars[0] = cplex.intVar(-3, 5, "x");
        vars[1] = cplex.intVar(0, 10, "y");
        vars[2] = cplex.intVar(-5, 5, "z");
        cplex.addMaximize(
                cplex.scalProd(new double[]{1., 2., 3.}, vars),"Obj"
        );
    
        cplex.addLe(cplex.sum(vars), 5., "Con1");
        cplex.addLe(cplex.scalProd(new double[]{0., 1., 2.}, vars),3., "Con2");
        cplex.addEq(vars[0], vars[2], "Con3");
        return cplex;
    }
    
    public static void main(String[] args) throws IloException {
        IloCplex model=buildModel();
        solveLP(model);
    }
    

    The reason this doesn't work is that the iterator in solveLP does not return any of the variables in the model! I could fix this by manually adding all variables to the model, i.e. by explicitly adding the line `cplex.add(vars)` at the end of buildModel. This is quite weird though, since the variables are already part of the model (they are in the constraints).
    Is there a cleaner way of fixing this, i.e. how can I iterate over all variables in my model? I could use the rangeIterator and iterate over all constraints and then iterate over all variables in each constraint, but that's even worse since many variables appear in multiple constraints.

     

    Edit: Paul has a blogpost about obtaining a set of variables from the cplex model: https://orinanobworld.blogspot.com/2011/12/extracting-variables-in-cplex.html However, this still seems rather cumbersome to simply compute a pure LP solution.


    #CPLEXOptimizers
    #DecisionOptimization


  • 2.  Re: Solving MIP model as an LP

    Posted 04/16/19 10:44 AM

    Unfortunately, the iterator returned by IloCplex.iterator() only iterates over the things that were explicitly added. Note that it will also find the conversions you added, so it is a bad idea to add the conversions within the loop as that will be modifying the collection the iterator is currently iterating over.

    This code should find all variables referenced by the model (and unforunately it has to iterate over all non-zeros):

       public static void solveLP(IloCplex cplex) throws IloException {
          //Convert all integer variables into continuous variables
          HashSet<IloNumVar> vars = new HashSet<>();
          for(Iterator it = cplex.iterator(); it.hasNext(); ){
             Object o=it.next();
             if (o instanceof IloRange) {
                IloRange r = (IloRange)o;
                IloLinearNumExpr expr = (IloLinearNumExpr)r.getExpr();
                for (IloLinearNumExprIterator et = expr.linearIterator(); et.hasNext(); ) {
                   IloNumVar v = et.nextNumVar();
                   vars.add(v);
                }
             }
             else if (o instanceof IloLPMatrix) {
                IloLPMatrix m = (IloLPMatrix)o;
                for (IloNumVar v : m.getNumVars())
                   vars.add(v);
             }
             else if (o instanceof IloNumVar) {
                // Note that IloIntVar is a subclass of IloNumVar
                vars.add((IloNumVar)o);
             }
          }
    
          List<IloConversion> conversions=new LinkedList<>();
          for (IloNumVar var : vars) {
             IloConversion conv=cplex.conversion(var, IloNumVarType.Float);
             conversions.add(conv);
             cplex.add(conv);
          }
    
          //Do something with the model, e.g. solve
          cplex.solve();
    
          //Restore original model
          for(IloConversion conv : conversions)
             cplex.remove(conv);
       }
    

    The code does not catch special constraints like the ones created by IloCplex.ifThen(). So it is best to add an "else if (! (o instanceof IloObjective)) { throw SomeException(); }" in the end.


    #CPLEXOptimizers
    #DecisionOptimization