For an optimization problem, I am trying to define a constraint in PYOMO, where the the constraint expression includes some specific values from a pandas DataFrame.
I will try to explain my problem in a concise way.
Following are the imports.
from pyomo.environ import *
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from pyomo.opt import SolverFactory
model = ConcreteModel()
The following are the decision variables.
model.d1 = Var(bounds=(0.8,1.0), initialize = 0.9)
model.t1 = Var(bounds=(0.1,0.3))
The objective function is given below:
model.Total_weight = Objective(expr= model.t1*model.d1, sense= minimize )
To formulate a constraint expression, I am using some values from a DataFrame.
The DataFrame would look like this:
r1 = [50.05,60.0,70]
r2 = [100,150,200]
df = pd.DataFrame([r1,r2])
0 1 2
0 50.05 60.0 70
1 100.00 150.0 200
Current Idea:
I am assigning some of the values from the df to variables, in order to be used in the constraint expression (as shown below).
v1 = df.iloc[0, 1]
v2 = df.iloc[1,1]
The only purpose of v1 and v2 is to input value to the constraint expression. It has nothing to do with the optimization model.
model.C1 = Constraint(expr = v1 + v2 *model.d1 <= 2.1)
But I got the following error while executing this idea
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-9-a9a7f2887bcb> in <module>
----> 1 model.C1 = Constraint(expr = v1 + v2 *model.d1)
TypeError: unsupported operand type(s) for *: 'float' and 'NoneType'
To my understanding, python considers v1 and v2 as 'float' and model.d1 is considered as 'NoneType'. I tried to run the model by adding initialize
to the variable model.d1. But still it seems 'NoneType'.
Can someone please help me to solve this?
Thank you very much in advance.
PS: model.d1.display()
gives following output.
d1 : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : 0.8 : 0.9 : 1.0 : False : False : Reals
So you might have stumbled onto a small bug in how pyomo
interacts with numpy
values when the pyomo
variable is a singleton.... I don't think this comes up too often as the problem does not expose itself when dealing with indexed pyomo
variables, which is by far the majority case. Yours are non-indexed singletons.
First, let's get your model working. Convert the values coming out of your df
into floats and this works fine.
from pyomo.environ import *
#import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#from pyomo.opt import SolverFactory
model = ConcreteModel()
model.d1 = Var(bounds=(0.8,1.0), domain=NonNegativeReals)
model.t1 = Var(bounds=(0.1,0.3), domain=NonNegativeReals)
r1 = [50.05,60.0,70]
r2 = [100,150,200]
df = pd.DataFrame([r1,r2])
v1 = float(df.iloc[0, 1]) # NOTE the float() conversion
v2 = float(df.iloc[1, 1]) # NOTE the float() conversion
model.C1 = Constraint(expr=v1 + v2 * model.d1 <= 2.1)
model.pprint()
The suspected bug...
Both of these should execute by my understanding. I almost never deal w/ singleton variables (that are not indexed) so perhaps there is something else afoot here. I'll try to submit this to pyomo folks as a bug and see what comes of it.
from pyomo.environ import *
import numpy as np
c = np.float64(1.5) # a numpy float like what comes out of a pd dataframe...
model_1 = ConcreteModel()
model_1.x = Var()
# a simple expression
e = c * model_1.x # FAILS! TypeError: unsupported operand type(s) for *: 'float' and 'NoneType'
model_2 = ConcreteModel()
model_2.S = Set(initialize = [1,]) # indexing set with 1 member
model_2.x = Var(model_2.S)
# same expression
e2 = c * model_2.x[1] # Works fine...