Decision Optimization

Decision Optimization

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

 View Only
Expand all | Collapse all

setLinearCoef() Method in Java OPL API

  • 1.  setLinearCoef() Method in Java OPL API

    Posted Fri March 20, 2015 06:34 PM

    Originally posted by: mathygirl


    I have a constraint of the following form in an OPL model:
     
    myConstraint:
    sum(k in mySet) myDecisionVariable[k]  == 10000;
     
    In my Java OPL API code, I augment the "myDecisionVariable" array using the following code:
     
    IloNumVar newVar = masterCplex.numVar(0, Double.MAX_VALUE);
    IloRange myConstraint = (IloRange) masterOpl.getElement("myConstraint").asConstraint();
    masterCplex.setLinearCoef(myConstraint, newVar, 1.0);
     
    I get the following error message:
     
    Caused by: ilog.concert.IloException: You can not change the coefficient of an aggregate expression
     
    refering to the line that contains the command "masterCplex.setLinearCoef(myConstraint, newVar, 1.0);"
     
    What is wrong with my implementation?

    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 2.  Re: setLinearCoef() Method in Java OPL API

    Posted Mon March 23, 2015 05:28 AM

    Hi,

    indeed when you have a sum then you cannot change a coef, but what you can do is add an empty decision variable and then change this decision variable with setcoef.

     

    Let me give you an example:

    range r=1..4;
    dvar int x[1..4] in 0..10;
    dvar int e;
    maximize sum(i in r) x[i];
    subject to
    {
    ct:e==0;

    sum(i in r) x[i]+e<=10;
    }

    execute
    {
    writeln(x);
    }

    main
    {

    thisOplModel.generate();
    cplex.solve();
    thisOplModel.postProcess();
    for(var i in thisOplModel.r ) thisOplModel.ct.setCoef(thisOplModel.x[i],i);
    thisOplModel.e.UB=-4;
    thisOplModel.e.LB=-4;
    cplex.solve();
    thisOplModel.postProcess();

    }

     

     

     

    which gives

     [10 0 0 0]
     [4 0 0 0]

    regards


    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 3.  Re: setLinearCoef() Method in Java OPL API

    Posted Mon March 23, 2015 02:41 PM

    Originally posted by: mathygirl


    Thank you, this makes sense. What is the equivalent of thisOplModel.x[i] in the OPL Java API?


    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 4.  Re: setLinearCoef() Method in Java OPL API

    Posted Tue March 24, 2015 03:37 AM

    Hi

    in CPLEX_Studio1261\opl\examples\opl_interfaces\java\cutstock_change\src\cutstock_change

    you have an example : Cutstock_change.java

    You will see:

    IloObjective masterObj = masterOpl.getObjective();
                    masterCplex.setLinearCoef(masterObj, newVar, 1);
                    for (int i = 1; i < nWdth + 1; i++) {
                        double coef = subCplex.getValue(subOpl.getElement("Use")
                                .asIntVarMap().get(i));
                        IloForAllRange forAll = (IloForAllRange) masterOpl.getElement(
                                "ctFill").asConstraintMap().get(i);
                        masterCplex.setLinearCoef(forAll, newVar, coef);
                    }
                    masterVars.add(newVar);

    regards


    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 5.  Re: setLinearCoef() Method in Java OPL API

    Posted Tue March 24, 2015 02:56 PM

    Originally posted by: mathygirl


    Yes, there is a constraint of the form

    forall( i in Items )
        ctFill:
          sum( p in Patterns )
            Fill[p][i] * Cut[p] >= Amount[i];

    that is modified with the Java API code above.

    In my implementation, I have no problem with the setLinearCoef() method on such constraints.

    What I am having problems with is modifying constraints of the form:

    myConstraint:

        sum(s in mySet) decisionVar[s] == 47;

    where there is no "forall" and I am augmenting the decisionVar array, and therefore the sum, by one more term on each iteration.

     

     


    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 6.  Re: setLinearCoef() Method in Java OPL API

    Posted Tue March 24, 2015 04:51 PM

    Hi,

    this is why  introduced e yesterday in this thread!

    In a sum you cannot change a coef, you get You can not change the coefficient of an aggregate expression

    So a workaround is to add a decision variable e that is in an empty constraint and then you CAN change the coef of this cmpty constraint in order to set any decision variable coefficient.

    Regards


    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 7.  Re: setLinearCoef() Method in Java OPL API

    Posted Tue March 24, 2015 05:44 PM

    Originally posted by: mathygirl


    Your workaround works. Most likely you're aware that the workaround is not needed in OPL script. This works:

    for(var i in thisOplModel.r ) cplex.setCoef(thisOplModel.ct,thisOplModel.x[i],2.0);

    I am trying to confirm that there is no fix in Java that doesn't involve going in and modifying the model.


    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 8.  Re: setLinearCoef() Method in Java OPL API



  • 9.  Re: setLinearCoef() Method in Java OPL API

    Posted Sat January 11, 2020 02:44 AM

    Originally posted by: qtbgo


    Dear Alex,

      I am learning opl java interface. In the expample  located in "opl_interfaces\java\mulprod". I modified the mulprod.mod a little as follows:

    dvar float+ obj;

    minimize obj;
    subject to {
      
      obj ==   sum( p in Products, t in Periods ) 
          (InsideCost[p]*Inside[p][t] + 
           OutsideCost[p]*Outside[p][t] +
           InvCost[p]*Inv[p][t]);

     

    Then In Mulprod.java, I want to change the coef of obj to 0 and solve the model. Could you tell me how to do it? The framework is as follows:

            IloOplFactory oplF = new IloOplFactory();
            IloOplErrorHandler errHandler = oplF.createOplErrorHandler();
            IloOplModelSource modelSource = oplF.createOplModelSource(DATADIR
                    + "/mulprod.mod");
            IloOplSettings settings = oplF.createOplSettings(errHandler);
            IloOplModelDefinition def = oplF.createOplModelDefinition(modelSource,settings);
            IloCplex cplex = oplF.createCplex();
            cplex.setOut(null);
            IloOplModel opl = oplF.createOplModel(def, cplex);
            IloOplDataSource dataSource = oplF.createOplDataSource(DATADIR
                    + "/mulprod.dat");
            opl.addDataSource(dataSource);       
            opl.generate();        
            
         
     //TODO how to set the coef of the obj to 0 ?        
            
            
            if (cplex.solve())
    

     


    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 10.  Re: setLinearCoef() Method in Java OPL API

    Posted Sun January 12, 2020 01:20 PM

    Hi,

    why not having a look at cutstock_change where you ll see

    IloObjective masterObj = masterOpl.getObjective();
                    masterCplex.setLinearCoef(masterObj, newVar, 1);

     

    ?

     

    regards

    https://medium.com/@alexfleischer_84755/optimization-simply-do-more-with-less-zoo-buses-and-kids-66940178db6


    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 11.  Re: setLinearCoef() Method in Java OPL API

    Posted Tue January 14, 2020 03:12 AM

    Originally posted by: qtbgo


    Yes, I had tried  like:

     

            IloObjective masterObj = opl.getObjective();
            IloNumVar newVar = cplex.numVar(0, Double.MAX_VALUE);
            cplex.setLinearCoef(masterObj, newVar, 0);

     

    But it doesn't affect the result. I don't understand why introduce the newVar, and how it is related to the obj variable in tht mod file.


    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 12.  Re: setLinearCoef() Method in Java OPL API

    Posted Tue January 14, 2020 05:47 AM

    Hi,

    so let me share a complete tiny example.

    Consider the very good example in opl\examples\opl_interfaces\java\mulprod and change the model into

    {string} Products = ...;
    {string} Resources = ...;
    int NbPeriods = ...;
    range Periods = 1..NbPeriods;

    float Consumption[Resources][Products] = ...;
    float Capacity[Resources] = ...;
    float Demand[Products][Periods] = ...;
    float InsideCost[Products] = ...;
    float OutsideCost[Products]  = ...;
    float Inventory[Products]  = ...;
    float InvCost[Products]  = ...;
    range Periods0 = 0..NbPeriods;

    dvar float+ Inside[Products][Periods];
    dvar float+ Outside[Products][Periods];
    dvar float+ Inv[Products][Periods0];

    dvar float costInside;
    dvar float costOutside;
    dvar float costInv;


    /*minimize
      sum( p in Products, t in Periods )
          (InsideCost[p]*Inside[p][t] +
           OutsideCost[p]*Outside[p][t] +
           InvCost[p]*Inv[p][t]);*/

    minimize costInside+costOutside+costInv;

    subject to {

    costInside==
    sum( p in Products, t in Periods )
          InsideCost[p]*Inside[p][t];
    costOutside==
    sum( p in Products, t in Periods )
          OutsideCost[p]*Outside[p][t] ;

    costInv==
    sum( p in Products, t in Periods )
                 InvCost[p]*Inv[p][t];

      forall( r in Resources, t in Periods )
        ctCapacity:
          sum( p in Products )
            Consumption[r][p] * Inside[p][t] <= Capacity[r];
      forall( p in Products , t in Periods )
        ctDemand:
          Inv[p][t-1] + Inside[p][t] + Outside[p][t] == Demand[p][t] + Inv[p][t];
      forall( p in Products )
        ctInventory:
          Inv[p][0] == Inventory[p];
    };
    tuple plan {
       float inside;
       float outside;
       float inv;
    }
    plan Plan[p in Products][t in Periods] = <Inside[p,t],Outside[p,t],Inv[p,t]>;
    execute DISPLAY {
      writeln("plan=",Plan);
    }


    tuple InsideSolutionT{
        string Products;
        int Periods;
        float value;
    };
    {InsideSolutionT} InsideSolution = {<i0,i1,Inside[i0][i1]> | i0 in Products,i1 in Periods};
    tuple OutsideSolutionT{
        string Products;
        int Periods;
        float value;
    };
    {OutsideSolutionT} OutsideSolution = {<i0,i1,Outside[i0][i1]> | i0 in Products,i1 in Periods};
    tuple InvSolutionT{
        string Products;
        int Periods0;
        float value;
    };
    {InvSolutionT} InvSolution = {<i0,i1,Inv[i0][i1]> | i0 in Products,i1 in Periods0};

     

    in order to have 3 KPIs in the objective

     

    Then when you run you get

     

     [java] costInside = 22.333;
         [java] costOutside = 434.67;
         [java] costInv = 0;
         [java] Inside = [[10 0 0]
         [java]              [0 0 0]
         [java]              [50 66.667 66.667]];
         [java] Outside = [[0 100 50]
         [java]              [20 200 100]
         [java]              [0 33.333 33.333]];
         [java] Inv = [[0 0 0 0]
         [java]              [0 0 0 0]
         [java]              [0 0 0 0]];

    but then if in mulprod.java

     

    you change

    opl.generate();

          

            if (cplex.solve())
            {
                System.out.println("OBJECTIVE: " + opl.getCplex().getObjValue());
                opl.postProcess();
                opl.printSolution(System.out);
            }

    into

    opl.generate();

            IloObjective masterObj = opl.getObjective();
            IloNumVar insideCost = opl.getElement("costInside").asNumVar();
            cplex.setLinearCoef(masterObj, insideCost, 10);

            if (cplex.solve())
            {
                System.out.println("OBJECTIVE: " + opl.getCplex().getObjValue());
                opl.postProcess();
                opl.printSolution(System.out);
            }

    then you ll get

     

     [java] costInside = 0;
         [java] costOutside = 516;
         [java] costInv = 0;
         [java] Inside = [[0 0 0]
         [java]              [0 0 0]
         [java]              [0 0 0]];
         [java] Outside = [[10 100 50]
         [java]              [20 200 100]
         [java]              [50 100 100]];
         [java] Inv = [[0 0 0 0]
         [java]              [0 0 0 0]
         [java]              [0 0 0 0]];

    we simply changed the coefficient of the inside cost in the orbjective

     

    regards

     

    https://www.linkedin.com/pulse/making-decision-optimization-simple-alex-fleischer/


    #DecisionOptimization
    #OPLusingCPLEXOptimizer


  • 13.  Re: setLinearCoef() Method in Java OPL API

    Posted Tue January 14, 2020 07:35 AM

    Originally posted by: qtbgo


    Thank you Alex so much. This is exactly what I want.


    #DecisionOptimization
    #OPLusingCPLEXOptimizer