Decision Optimization

Decision Optimization

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

 View Only
Expand all | Collapse all

Optimal way to add Equations to IloCplex

  • 1.  Optimal way to add Equations to IloCplex

    Posted Wed September 26, 2018 09:31 AM

    Originally posted by: Muhammad.Ahmed


    Hi to all . 
    I am working with Cplex and I found that the following code is extremely slow

            for (int j = 1 ; j <mapData.getTotalNumber()+1; j++ )        
                            {
                                    IloLinearNumExpr exp = cplex.linearNumExpr();
                                    exp.addTerms(mapData.getLHSRow(j), cplexVars);
                                    
                                    cplex.addEq(exp, mapData.getRHS().get(j-1, 0));
                            }
    

    cplex.addEq takes alot of time when I try to add bigger expressions. Is there any other method that is faster than this ?

    Thanks 

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 2.  Re: Optimal way to add Equations to IloCplex

    Posted Wed September 26, 2018 11:11 AM

    It seems like you could use IloCplex.scalProd() instead of building up the expression explicitly. Not sure this will speed up things, though.

    Can you try using IloLPMatrix? First build up the matrix for all equations and then add the matrix with a single call to IloCplex.add(). Is the add() still slow or is building the matrix slow?


    #CPLEXOptimizers
    #DecisionOptimization


  • 3.  Re: Optimal way to add Equations to IloCplex

    Posted Thu September 27, 2018 04:32 AM

    Originally posted by: Muhammad.Ahmed


    The cplex.addEq() takes alot of time if I have larger IloLinearNumExpr size. 
    I have modified a little as per your instructions . this is how it looks after modifications

     
        loLPMatrix matrix = cplex.LPMatrix();
        
        for (int j = 1 ; j <mapData.getTotalNumber()+1; j++ )        
        {
            IloLinearNumExpr exp = cplex.linearNumExpr();
            exp.addTerms(mapData.getLHSRow(j), cplexVars);
                                
                                
            IloRange range = cplex.range(0, mapData.getRHS().get(j-1, 0));
                range.setExpr( exp);
                                    
                matrix.addRow(range);
        }
            cplex.add(matrix);
    

     

    I am not sure this is what you mean, but with this it got more worst . 


    #CPLEXOptimizers
    #DecisionOptimization


  • 4.  Re: Optimal way to add Equations to IloCplex

    Posted Thu October 04, 2018 01:48 AM

    Is the time spent in the loop or in the call to cplex.add(matrix)?

    Do you have an example code to reproduce this issue? And what version of CPLEX do you use?


    #CPLEXOptimizers
    #DecisionOptimization


  • 5.  Re: Optimal way to add Equations to IloCplex

    Posted Mon November 19, 2018 10:43 AM

    Originally posted by: Muhammad.Ahmed


    Most of the time is takken by range.setExpr (exp). Also it throws "java.lang.OutOfMemoryError: Java heap space" exception. I have 4gb reserved for it with 8gb as total memory of my system. with same configuration i am able to run using IloCplex.addEq(..) method. 

    I thought of saving the model and reuse it afterwords , Since Equality constraints are constant. I am only changing objective function and inequality constraint.

           IloCplex cplex = new IloCplex();
                if(mapData.getModel == null){
                    for (int j = 1 ; j <mapData.getNumberOfNodes()+1 ; j++ )     
                                    {
                                            IloLinearNumExpr exp = cplex.linearNumExpr();
                                                exp.addTerms(mapData.LHS(j), cplexVars);
                                            
                                            cplex.addEq(exp, mapData.RHS().get(j-1, 0));
                                            
                                        }      
                                    mapData.setCplexModel(cplex);
                            }
                            else 
                                    cplex.setModel(mapData.getCplexModel());
    

    I tried to use the above code and it throws IloException. Kindly suggest a way to save the model and reuse it with different objective function and inequality constraints. 
    Thanks 

    Ahmed


    #CPLEXOptimizers
    #DecisionOptimization


  • 6.  Re: Optimal way to add Equations to IloCplex

    Posted Mon November 19, 2018 03:49 PM

    You could try the following. Build the model once and save the IloCplex instance someplace. Also save the return values of addLe() and addGe() (the functions that add the inequality constraints) in a memory structure (array, ArrayList, Map, whatever). They should be instances of IloRange. Finally, save the return value of the function that creates the objective (addMinimize() or addMaximize()) in a variable. It will be an instance of IloObjective.

    When you want to modify the model, call the remove() method on the IloCplex object to remove each of the things you want to change, created and add a new objective and new inequality constraints, and save the pointers to the new versions where you previously had the pointers to the old versions. You can also keep the old constraints and objective and call setLinearCoef() or setLinearCoefs() on them to modify the coefficients as needed. If you are making more than one or two changes to a coefficient or constraint, though, my guess is that removing the old one and building a new one from scratch will be faster.


    #CPLEXOptimizers
    #DecisionOptimization


  • 7.  Re: Optimal way to add Equations to IloCplex

    Posted Tue November 20, 2018 07:53 AM

    Originally posted by: Muhammad.Ahmed


    Thanks for the quick response. 

    I saved the instances of IloRange in an array from the addEq() method. But than when I try to add that IloRange array to a new model using IloCplex.add(..), it throws IloCplex.MultipleUseException . 
    Here is the modified code for more clarity.

        if(mapData.getCplexModelRange() == null) {
                    IloRange[] Range = new IloRange[mapData.getTotalNumber()];
                                    
            for (int j = 1 ; j <mapData.getTotalNumber()+1; j++ )        
                    {
                            IloLinearNumExpr exp = cplex.linearNumExpr();
                            exp.addTerms(mapData.getLHS(j), cplexVars);             
                                    
                            Range[j-1] = cplex.addEq(exp, mapData.RHS().get(j-1, 0));
                    }
                                    
                    mapData.setCplexModelRange(Range);
            }
            else {
                    IloRange[] Range = new IloRange[mapData.getTotalNumber()];
                    Range = mapData.getCplexModelRange().clone();
                    cplex.add(Range);
            }
    

    Is this the right way to do it or ?


    #CPLEXOptimizers
    #DecisionOptimization


  • 8.  Re: Optimal way to add Equations to IloCplex

    Posted Tue November 20, 2018 07:59 AM

    No, you cannot take elements of one model and introduce them into a different model. My answer assumed that you were modifying and reusing the same IloCplex object each time. If you really want to use a new IloCplex object, you will need to build it from scratch, the same way you built the original model (but presumably with some differences in the coefficients).


    #CPLEXOptimizers
    #DecisionOptimization


  • 9.  Re: Optimal way to add Equations to IloCplex

    Posted Tue November 20, 2018 09:41 AM

    Originally posted by: Muhammad.Ahmed


    Building the model from scratch takes a lot of time. That is why I am thinking of saving the model in IloCplex instance and reuse it afterwords. But due to some strange reason it throws IloException with no description , when I try to set  model using IloCplex.setModel(). Any idea why its not working ?

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 10.  Re: Optimal way to add Equations to IloCplex

    Posted Wed November 21, 2018 01:31 AM

    Usually calling setModel() should not be required. How exactly are you using this? Are you using multiple IloCplex instances here? Or are you trying to add an IloCplex instance to itself? Can you show your code (or an outline of it) that creates the IloCplex instance and the IloModel instance and then calls setModel()?


    #CPLEXOptimizers
    #DecisionOptimization


  • 11.  Re: Optimal way to add Equations to IloCplex

    Posted Wed November 21, 2018 08:21 AM

    Originally posted by: Muhammad.Ahmed


                            IloCplex cplex = new IloCplex();
                            IloLinearNumExpr objective = cplex.linearNumExpr();
                            IloNumVar [] cplexVars = new IloNumVar[ObjectiveFunction.numCols()];
                    
    
                            for (int i = 0 ; i< ObjectiveFunction.numCols() ; i++)
                            {
                                    cplexVars[i] = cplex.boolVar();
                                    objective.addTerm( ObjectiveFunction.get(0, i), cplexVars[i]);
                            }
                            
                            if(mapData.getCplexModel() == null) {
                            
                                    for (int j = 1 ; j <mapData.getTotalNumber()+1; j++ )        
            
                                    {
                                            IloLinearNumExpr exp = cplex.linearNumExpr();
                                            exp.addTerms(mapData.getLHS(j), cplexVars);             
                                            
                                            cplex.addEq(exp, mapData.getRHS().get(j-1, 0));
                                            
                                    }
                                    
                                    mapData.setCplexModel(cplex);
                            }
                            else {
                                    cplex.setModel(mapData.getCplexModel());
                            }
                                    
    
                            cplex.addMinimize(objective);
    

    In the above function is call multiple time with different objective function. 
    The most time consuming line is cplex.addEq(..) in the above code . The problem I am facing is I am getting IloException when at cplex.setModel(mapData.getCplexModel). 

    Here are the get and set method  

     

    public IloCplex getCplexModel() {
                    return cplexModel;
            }
    
            public void setCplexMode(IloCplex model) {
                    if(cplexModel == null){
                            try {
                                    cplexModel = new IloCplex();
                                    cplexModel = model ;
                            } catch (IloException e) {
                                    e.printStackTrace();
                            }
                }        
            }
    

    Thanks

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 12.  Re: Optimal way to add Equations to IloCplex

    Posted Wed November 21, 2018 09:15 AM

    You cannot do cplex.setModel(model) if 'cplex' and 'model' are not the same object, and if they are the same object then the call to setModel() is redundant. However, as I suspected, there is no need to call setModel().

    You can keep most of your code as it is but to handle the objective function you can proceed as follows:

    IloObjective old = cplex.getObjective(); // If there is an objective function then remove it
    if (old != null)
       cplex.remove(old);
    cplex.addMinimize(objective);
    // Same as before

    In other words, before adding the new objective function, you just remove the old one. No need to call setModel() or anything else.


    #CPLEXOptimizers
    #DecisionOptimization


  • 13.  Re: Optimal way to add Equations to IloCplex

    Posted Wed November 21, 2018 09:41 AM

    Originally posted by: Muhammad.Ahmed


    Thanks for the response. Is it possible to modify ineq constraints as-well 

    for (int k = 0 ; k < Aineq.numRows() ;k++)
    {     
            IloLinearNumExpr expr = cplex.linearNumExpr();
            DMatrixRMaj rowAineq = Aineq.extractVector(true, k).getMatrix();
            double [] row = rowAineq.getData();
            expr.addTerms(row, cplexVars);
                                                                    
            cplex.addLe(expr, Bineq.get(k,0));
            }
    

    The above lines I put in to add ineq constraints. I don't find any method to get ineq constraints if they are linked or not ?


     


    #CPLEXOptimizers
    #DecisionOptimization


  • 14.  Re: Optimal way to add Equations to IloCplex

    Posted Wed November 21, 2018 10:45 AM

    cplex.addLe() returns the constraint that was added. You can keep a reference to that constraint and using that reference either modify or remove the constraint later.


    #CPLEXOptimizers
    #DecisionOptimization


  • 15.  Re: Optimal way to add Equations to IloCplex

    Posted Wed November 21, 2018 09:17 AM

    And by the way, your setCplexModel() looks fishy:

    cplexModel = new IloCplex();
    cplexModel = model;

    Why allocate a new instance of IloCplex() if the only reference to that instance is immediately discarded?


    #CPLEXOptimizers
    #DecisionOptimization