Pyomo:如何将 None 作为参数值传递
Pyomo: How to pass None as parameter value
希望这是一个容易回答的问题。我正在尝试创建一个模型,允许用户为参数值传递 None。这样他们就可以定义 upper/lower 边界,或者选择没有边界。具有 set/param 定义、AMPL 样式数据文件部分和约束函数的示例问题(饮食问题)如下:
Set/Param 定义
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)
数据文件部分
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;
约束函数
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])
不幸的是,当我尝试这样做时,我收到错误消息:TypeError: Cannot treat the value 'None' as a constant.
是否有另一种方法可以将参数定义为 None?我知道我可以只使用巨大的正数/负数,但必须有更好的方法。
如果您打算继续使用抽象模型,我认为您会被困在默认值中,这很好。如果您使用的是具体模型,则可以有条件地构造约束,因为数据在构造时是已知的。
此外,在您的数据文件中,您需要将此格式的 None 个值表示为句点 .
。如果你使用 'None' 这个词,它会呕吐,因为它不被识别为 Python 的 None
这个试用版对我来说效果很好...
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;
希望这是一个容易回答的问题。我正在尝试创建一个模型,允许用户为参数值传递 None。这样他们就可以定义 upper/lower 边界,或者选择没有边界。具有 set/param 定义、AMPL 样式数据文件部分和约束函数的示例问题(饮食问题)如下:
Set/Param 定义
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)
数据文件部分
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;
约束函数
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])
不幸的是,当我尝试这样做时,我收到错误消息:TypeError: Cannot treat the value 'None' as a constant.
是否有另一种方法可以将参数定义为 None?我知道我可以只使用巨大的正数/负数,但必须有更好的方法。
如果您打算继续使用抽象模型,我认为您会被困在默认值中,这很好。如果您使用的是具体模型,则可以有条件地构造约束,因为数据在构造时是已知的。
此外,在您的数据文件中,您需要将此格式的 None 个值表示为句点 .
。如果你使用 'None' 这个词,它会呕吐,因为它不被识别为 Python 的 None
这个试用版对我来说效果很好...
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;