Pyomo: как передать None в качестве значения параметра - PullRequest
0 голосов
/ 05 августа 2020

Надеюсь, на этот вопрос легко ответить. Я пытаюсь создать модель, которая позволяет пользователю передавать None в качестве значения параметра. Это сделано для того, чтобы они могли определить верхнюю / нижнюю границу или выбрать отсутствие границы. Ниже приведен пример проблемы (проблема диеты) с определениями set / param, разделом файла данных в стиле AMPL и функцией ограничения:

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)

Раздел файла данных

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? Я знаю, что могу использовать просто огромные положительные / отрицательные числа, но должен быть способ получше.

1 Ответ

0 голосов
/ 05 августа 2020

Если вы собираетесь go вперед с абстрактной моделью, я думаю, вы застряли, используя значение по умолчанию, и это нормально. Если вы использовали конкретную модель, вы могли бы условно построить ограничение, потому что данные известны на момент создания.

Кроме того, в вашем файле данных вам необходимо представить значения None в этом формате как точку .. Если вы используете слово «None», он будет заблокирован, поскольку он не распознается как Python s 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;
...