Decision Optimization

Decision Optimization

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

 View Only
  • 1.  continuous relaxation on oplrun

    Posted 4 days ago

    Previously, I was using OPL Script, but I decided to switch to Python in order to incorporate machine learning. However, since I still want to use the existing OPL model, I am calling the oplrun command from Python using the subprocessmodule. The OPL model is an MIQP.

    In the previous OPL Script, there was a part where the convertAllIntVars method was used to solve a continuous relaxation of the problem. I am having trouble figuring out how to solve the continuous relaxation using the oplruncommand. Do I have no choice but to manually convert the model into its relaxed form?



    ------------------------------
    Toshiyuki Miyamoto
    ------------------------------


  • 2.  RE: continuous relaxation on oplrun

    Posted 4 days ago

    Hi

    in docplex you can relax integrity constraints as can be seen at https://github.com/AlexFleischerParis/zoodocplex/blob/master/zoorelaxintegrity.py

    from docplex.mp.model import Model
    from docplex.mp.relax_linear import LinearRelaxer
    
    def make_bus_model():
        mdl = Model(name='buses')
        nbbus40 = mdl.integer_var(name='nbBus40')
        nbbus30 = mdl.integer_var(name='nbBus30')
    
        mdl.add_constraint(nbbus40 * 40 + nbbus30 * 30 >= 300, 'kids')
        mdl.minimize(nbbus40 * 500 + nbbus30 * 400)
        return mdl
    
    if __name__ == '__main__':
        bm1 = make_bus_model()
        bm1.print_information()
        s1 = bm1.solve(log_output=True)
        s1.display()
    
        bmr = LinearRelaxer.make_relaxed_model(bm1)
        bmr.print_information()
        rs = bmr.solve(log_output=True)
        rs.display()
    
        duals = bmr.get_constraint_by_name("kids").dual_value
    
        print("dual of the 300 kids constraint = ",duals)
    
        for v in bmr.iter_continuous_vars():
           print(v," = ",v.solution_value)
           rc=v.reduced_cost
           print("reduced cost =",rc)

    You can also do that directly in OPL as can be seen at https://github.com/AlexFleischerParis/zooopl/blob/master/zoorelaxinteger.mod

        int nbKids=300;
        float costBus40=500;
        float costBus30=400;
         
        dvar int+ nbBus40;
        dvar int+ nbBus30;
         
        minimize
         costBus40*nbBus40  +nbBus30*costBus30;
         
        subject to
        {
         ctKids:40*nbBus40+nbBus30*30>=nbKids;
    
        }
    
        main {
          var status = 0;
          thisOplModel.generate();
          if (cplex.solve()) {
            writeln("Integer Model");   
            writeln("OBJECTIVE: ",cplex.getObjValue());   
            
          }
    
          // relax integrity constraint
          thisOplModel.convertAllIntVars();
         
          if (cplex.solve()) {
            writeln("Relaxed Model");   
            writeln("OBJECTIVE: ",cplex.getObjValue());  
            
            writeln("dual of the kids constraint = ",thisOplModel.ctKids.dual);
            writeln("reduced costs for nbbus40 : ",thisOplModel.nbBus40.reducedCost);
            writeln("reduced costs for nbbus30 : ",thisOplModel.nbBus30.reducedCost);
          }
           
         
        }

    regards



    ------------------------------
    [Alex] [Fleischer]
    [Data and AI Technical Sales]
    [IBM]
    ------------------------------



  • 3.  RE: continuous relaxation on oplrun

    Posted yesterday

    Dear Alex

    Thank you for your reply.

    My previous program is written in OPL Script and uses the ConvertAllIntVars() method for continuous relaxation, as in the second example you showed. However, OPL Script is not well-suited for integration with machine learning. I am planning to use the output of a random forest for some of the decisions, and Python is much more convenient for implementing this part. I also considered using docplex, but it would require translating the contents of the existing .modfile into Python, which is time-consuming.

    Since performing continuous relaxation via the oplrun command seems difficult, directly editing the existing .mod file for continuous relaxation appears to be the easier approach.



    ------------------------------
    Toshiyuki Miyamoto
    ------------------------------



  • 4.  RE: continuous relaxation on oplrun

    Posted yesterday

    Hi,

    from python you can call oplrun but you can also rely on doopl

    See this example

    from doopl.factory import *
    # Data
    
    Buses=[
            (40,500),
            (30,400)
            ]
    
    # Create an OPL model from a .mod file
    with create_opl_model(model="zootupleset.mod") as opl:
        # tuple can be a list of tuples, a pandas dataframe...
        opl.set_input("buses", Buses)
    
        # Generate the problem and solve it.
        opl.run()
    
        # Get the names of post processing tables
        print("Table names are: "+ str(opl.output_table_names))
    
        # Get all the post processing tables as dataframes.
        for name, table in iteritems(opl.report):
            print("Table : " + name)
        for t in table.itertuples(index=False):
                print(t)
    
        # nicer display
        for t in table.itertuples(index=False):
            print(t[0]," buses ",t[1], "seats")

    You can also import a model generated with opl in a docplex model : https://github.com/AlexFleischerParis/zoodocplex/blob/master/zooimportoplmodelandaddpythonobjectiveandconstraint.py

    from docplex.mp.model import Model
    from docplex.mp.model_reader import ModelReader
    from doopl.factory import *
    
    # Create an OPL model from a .mod file
    with create_opl_model(model="zoooplwithoutobjective.mod") as opl:
        # Generate the problem and solve it.
        opl.run()
    
    mdl = ModelReader.read_model('zoowithoutobj.lp', model_name='zoo')
    
    nbbus40 = mdl.find_matching_vars('nbBus40')[0]
    nbbus30 = mdl.find_matching_vars('nbBus30')[0]
    
    #add docplex constraint        
    mdl.add(nbbus40<=4)
    #add docplex objective
    mdl.minimize(nbbus40*500 + nbbus30*400)
    
    msol=mdl.solve()
    
    print(msol[nbbus40]," buses 40 seats")
    print(msol[nbbus30]," buses 30 seats")

    and you can also turn an integer decision variable to a float decision variable in docplex

    from docplex.mp.model import Model
    
    mdl = Model(name='buses')
    nbbus40 = mdl.integer_var(name='nbBus40')
    nbbus30 = mdl.integer_var(name='nbBus30')
    mdl.add_constraint(nbbus40*40 + nbbus30*30 >= 300, 'kids')
    mdl.minimize(nbbus40*500 + nbbus30*400)
    
    mdl.solve(log_output=False,)
    
    for v in mdl.iter_integer_vars():
        print(v," = ",v.solution_value)
    
    nbbus30.set_vartype('C')
    
    print("relax nbbus30 to continuous")
    
    mdl.solve(log_output=False,)
    
    for v in mdl.iter_integer_vars():
        print(v," = ",v.solution_value)
    for v in mdl.iter_continuous_vars():
        print(v," = ",v.solution_value)
    
    print("set  nbbus30 back to integer")
    
    nbbus30.set_vartype('I')
    
    mdl.solve(log_output=False,)
    
    for v in mdl.iter_integer_vars():
        print(v," = ",v.solution_value)
    


    ------------------------------
    [Alex] [Fleischer]
    [Data and AI Technical Sales]
    [IBM]
    ------------------------------



  • 5.  RE: continuous relaxation on oplrun

    Posted 21 hours ago

    Dear Alex

    Thanks! That is what I wanted.



    ------------------------------
    Toshiyuki Miyamoto
    ------------------------------