Search code examples
pythoncplexopl

Proper way to use opl.set_input() of doopl for parameters (not tuple)


I'm trying to run the CPLEX .mod file within Python. An instructor on how to do this exists in the following link:

How to run a .mod file (CPLEX) using python?

But it seems that (maybe) only the tuple is sent from Python into CPLEX. In my case, there is a loop in the CPLEX .mod file like the following:

for (var i = lowerBound; i <= upperBound; i++) {
...
} 

I want to send parameters lowerBound and upperBound from Python to CPLEX .mod file. For this aim, I define a variable inside the CPLEX .mod file, before the for loop, as follows:

var lowerBound = ...;
var upperBound = ...;

Then, I use the following command in Python:

from doopl.factory import *
with create_opl_model(model="model.mod") as opl:
    opl.set_input("upperBound", 50)
    opl.set_input("lowerBound", 1)
    opl.run()

but the following error comes out:

ERROR at 17:18 model.mod: Scripting parser error: missing expression.

I would like to say that in the CPLEX .mod lines 17 and 18 are:

var lowerBound = ...; 
var upperBound = ...;

Question: I wonder if only tuples are sent with opl.set_input ()? To understand this, I did something like the followings:

Inside CPLEX .mod:

tuple bounds {
        int lowerBound;
        int upperBound;
        
    }

    
for (var i = lowerBound; i <= upperBound; i++) {
    ...
}

Inside Python:

from doopl.factory import *

Bounds = [
    (1, 50),
    ]

with create_opl_model(model=" model.mod") as opl:
    opl.set_input("bounds", Bounds)
    opl.run()

But this time, there is an error like the following:

ERROR at 20:7 model.mod: Scripting parser error: missing ';' or newline between statements.

I would like to say that in the CPLEX .mod file line 20 is related to the definition of tuple bounds, which is:

tuple bounds {
        int lowerBound;
        int upperBound;
        
    }

What could be the solution to this?


Solution

  • you need to use tuple sets but in

    tuple bounds {
            int lowerBound;
            int upperBound;
            
        }
    

    that s not what you do.

    You should write

    tuple typebounds {
            int lowerBound;
            int upperBound;
            
        }
    
    {typebounds} bounds=...;
    

    in your .mod file

    Let me share a full example:

    from doopl.factory import *
    # Data
    
    Buses=[
            (40,500),
            (30,400)
            ]
    
    MinAndMax=[(1,5)]
    
    # Create an OPL model from a .mod file
    with create_opl_model(model="zootuplesetwithminandmax.mod") as opl:
        # tuple can be a list of tuples, a pandas dataframe...
        opl.set_input("buses", Buses)
        opl.set_input("singletonMinAndMax", MinAndMax)
    
        # 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")
    

    with zootuplesetwithminandmax.mod

    int nbKids=300;
    
    // a tuple is like a struct in C, a class in C++ or a record in Pascal
    tuple bus
    {
    key int nbSeats;
    float cost;
    }
    
    // This is a tuple set
    {bus} buses=...;
    
    tuple minandmax
    {
    int m;
    int M;
    }
    
    {minandmax} singletonMinAndMax=...;
    
    int minBuses=first(singletonMinAndMax).m;
    int maxBuses=first(singletonMinAndMax).M;
    
    
    // asserts help make sure data is fine
    assert forall(b in buses) b.nbSeats>0;
    assert forall(b in buses) b.cost>0;
    
    // decision variable array
    dvar int+ nbBus[buses] in minBuses..maxBuses;
    
    // objective
    minimize
     sum(b in buses) b.cost*nbBus[b];
     
    // constraints
    subject to
    {
     sum(b in buses) b.nbSeats*nbBus[b]>=nbKids;
    }
    
    tuple solution
    {
      int nbBus;
      int sizeBus;
    }
    
    {solution} solutions={<nbBus[b],b.nbSeats> | b in buses};