This is hopefully an easy question to answer. I'm trying to create a model that allows the user to pass None for a parameter value. This is so that they can define the upper/lower bound, or choose to have no bound. An example problem (diet problem) with set/param definitions, AMPL style data file section, and constraint function are below:
Set/Param Defs
model.Ingredients = pyo.Set()
model.Properties = pyo.Set()
model.IngredientProperties = pyo.Param(model.Ingredients, model.Properties)
model.MinProperty = pyo.Param(model.Properties, within=pyo.Any)
model.MaxProperty = pyo.Param(model.Properties, within=pyo.Any)
Data File Section
set Ingredients := Banana Milk Yogurt ;
set Properties := Fat Protein Carbs ;
param: MinProperty MaxProperty :=
Fat 0.009 0.013
Protein 0.200 None
Carbs None 0.070;
param IngredientProperties: Fat Protein Carbs :=
Banana 0.375 0.020 0.010
Milk 0.003 0.075 0.015
Yogurt 0.015 0.650 0.075;
Constraint Function
def _property_constraint_rule(model, p):
return (model.MinProperty[p], sum(
model.IngredientProperties[i, p]
* model.Blend[i]
for i in model.Ingredients
), model.MaxProperty[p])
Unfortunately, when I try this, I get the error message: TypeError: Cannot treat the value 'None' as a constant.
Is there another way to define parameters as None? I know that I could just use huge positive / negative numbers, but there has to be a better way.
If you are going to go forward with an Abstract model, I think you are stuck using a default value, which is fine. If you were using a concrete model, you could conditionally construct the constraint because the data is known at time of construction.
Also, in your data file, you need to represent None values in this format as a period .
. If you use the word 'None' it will barf as it is not recognized as Python's None
This trial build worked fine for me...
import pyomo.environ as pyo
model = pyo.AbstractModel()
model.Ingredients = pyo.Set()
model.Properties = pyo.Set()
model.IngredientProperties = pyo.Param(model.Ingredients, model.Properties)
model.MinProperty = pyo.Param(model.Properties, within=pyo.Any, default=0.0)
model.MaxProperty = pyo.Param(model.Properties, within=pyo.Any, default=100)
model.Blend = pyo.Var(model.Ingredients, domain=pyo.NonNegativeReals)
def _property_constraint_rule(model, p):
return (model.MinProperty[p], sum(
model.IngredientProperties[i, p] * model.Blend[i]
for i in model.Ingredients), model.MaxProperty[p])
model.c1 = pyo.Constraint(model.Properties, rule=_property_constraint_rule)
data = pyo.DataPortal()
data.load(filename='data.dat')
instance = model.create_instance(data)
instance.pprint()
3 Set Declarations
IngredientProperties_index : Dim=0, Dimen=2, Size=9, Domain=None, Ordered=False, Bounds=None
Virtual
Ingredients : Dim=0, Dimen=1, Size=3, Domain=None, Ordered=False, Bounds=None
['Banana', 'Milk', 'Yogurt']
Properties : Dim=0, Dimen=1, Size=3, Domain=None, Ordered=False, Bounds=None
['Carbs', 'Fat', 'Protein']
3 Param Declarations
IngredientProperties : Size=9, Index=IngredientProperties_index, Domain=Any, Default=None, Mutable=False
Key : Value
('Banana', 'Carbs') : 0.01
('Banana', 'Fat') : 0.375
('Banana', 'Protein') : 0.02
('Milk', 'Carbs') : 0.015
('Milk', 'Fat') : 0.003
('Milk', 'Protein') : 0.075
('Yogurt', 'Carbs') : 0.075
('Yogurt', 'Fat') : 0.015
('Yogurt', 'Protein') : 0.65
MaxProperty : Size=3, Index=Properties, Domain=Any, Default=100, Mutable=False
Key : Value
Carbs : 0.07
Fat : 0.013
MinProperty : Size=3, Index=Properties, Domain=Any, Default=0.0, Mutable=False
Key : Value
Fat : 0.009
Protein : 0.2
1 Var Declarations
Blend : Size=3, Index=Ingredients
Key : Lower : Value : Upper : Fixed : Stale : Domain
Banana : 0 : None : None : False : True : NonNegativeReals
Milk : 0 : None : None : False : True : NonNegativeReals
Yogurt : 0 : None : None : False : True : NonNegativeReals
1 Constraint Declarations
c1 : Size=3, Index=Properties, Active=True
Key : Lower : Body : Upper : Active
Carbs : 0.0 : 0.01*Blend[Banana] + 0.015*Blend[Milk] + 0.075*Blend[Yogurt] : 0.07 : True
Fat : 0.009 : 0.375*Blend[Banana] + 0.003*Blend[Milk] + 0.015*Blend[Yogurt] : 0.013 : True
Protein : 0.2 : 0.02*Blend[Banana] + 0.075*Blend[Milk] + 0.65*Blend[Yogurt] : 100.0 : True
8 Declarations: Ingredients Properties IngredientProperties_index IngredientProperties MinProperty MaxProperty Blend c1
data.dat
set Ingredients := Banana Milk Yogurt ;
set Properties := Fat Protein Carbs ;
param: MinProperty MaxProperty :=
Fat 0.009 0.013
Protein 0.200 .
Carbs . 0.070;
param IngredientProperties: Fat Protein Carbs :=
Banana 0.375 0.020 0.010
Milk 0.003 0.075 0.015
Yogurt 0.015 0.650 0.075;