PYOMO: операция над множествами абстрактной модели - PullRequest
0 голосов
/ 06 апреля 2019

Я хочу оперировать абстрактными множествами. Но это не работает.

from pyomo.environ import *
m = AbstractModel()
m.A = Set(initialize=[0,1,2])
m.B = Set(initialize=[0])
m.C = m.A-m.B
instance = m.create_instance()
for c in instance.C.value:
    print(c)

TypeError: объект 'NoneType' не повторяется

Ответы [ 3 ]

0 голосов
/ 08 апреля 2019

Так что, может быть, я должен сказать, какова моя мотивация.Я хочу определить ограничение на основе подмножества mC внутри моей AbstractModel, например

def rule_name(m, c):
    return something depends on c
m.rule_name = Constraint(m.C, rule=rule_name)
0 голосов
/ 08 апреля 2019

На основании того, что вы сказали Ци Чену, вот рабочий пример вашего кода, если вы использовали формулировку AbstractModel.С абстрактными моделями дело в том, что это не намного больше, чем задержка инициализации вашей модели в конкретной модели.Итак, он знает , какие наборы будут использоваться, но у него нет возможности узнать его содержимое, пока вы его не инициализируете.Например, он знает, что param p использует набор s в качестве домена, но нет способа узнать, каковы значения p и элементы s.

При этом вы пытаетесь заполнить ваш m.C набор из унитизированных наборов m.a и m.b.Я поддерживаю Ци Чена, ConcreteModels - лучший вариант для вас.Однако есть три способа использования AbstractModels.

Опция 1 Здесь вы заполняете свой m.C набор после инициализации вашей модели.create_instance() в основном превратит вашу абстрактную модель в конкретную модель, заполнив ее.Возвращает соответствующий ConcreteModel.Таким образом, у вас достаточно AbstractModel (помните, AbstractModel не обязательно иметь заполненные наборы, только чтобы знать, какие наборы используются).Итак, следующий код заполняет ваш m.C набор в ConcreteModel после его инициализации:

m = AbstractModel()
m.A = Set(initialize=[0, 1, 2])
m.B = Set(initialize=[0])
m.C = Set()
instance = m.create_instance() # Here instance becomes your ConcreteModel
instance.C = instance.A - instance.B # The equivalent of line "m.C = m.A-m.B" but with your ConcreteModel
for c in instance.C:
    print(c)

Option 2 Здесь, так как вы, кажется, знаете, что такоесодержание ваших наборов, вы можете определить его еще до того, как сделать AbstractModel.Это просто напоминание о том, что каждый набор обычно инициализируется с помощью Python list или set.Итак, просто создайте свои наборы сначала (на этот раз используя встроенные наборы Python), в момент определения вашей модели 'Наборы.Вот код:

from pyomo.environ import *
# Define the content of your model' Sets using built-in set
A = {0,1,2}
B = {0}
C = A - B

# You have all you need now to continue
m = AbstractModel()
m.A = Set(initialize=A)
m.B = Set(initialize=B)
m.C = Set(initialize=C)
instance = m.create_instance()
for c in instance.C:
    print(c)

Но, опять же, поскольку ваши наборы уже определены, то, что я только что показал вам, это просто более изощренный и сложный способ создания ConcreteModel, поскольку в основном он выполняетТо же самое, то есть создать модель с заполненными значениями и наборами.

Вариант 3 Используя способ Варианта 1 и Варианта 2, вы не сможете впоследствии изменить элементы своих наборов.Например, следующий код

from pyomo.environ import *
A = {0, 1, 2}
B = {0}
C = A - B
m = AbstractModel()
m.A = Set(initialize=A)
m.B = Set(initialize=B)
m.C = Set(initialize=C)

# Pyomo's Sets are initialized, now, let's try to change their value:
A = {4, 5, 6}
B = {4}

instance = m.create_instance()
for c in instance.C:
    print(c)

будет по-прежнему печатать

1
2 

, даже если мы попытались напечатать

5
6

Это очень неудобно, особенно когда мыпопробуйте использовать класс AbstractModel в качестве пустой модели для ввода данных. Если вы хотите использовать его таким образом, и ИМХО, это единственная веская причина для использования AbstractModel, тогда вам следует рассмотреть возможность чтенияэта страница: https://pyomo.readthedocs.io/en/latest/working_abstractmodels/data/index.html, а затем перейдите к этой странице: https://pyomo.readthedocs.io/en/latest/working_abstractmodels/data/raw_dicts.html, где он показывает пример заполнения пробела AbstractModel из данных, в данном случае данные предоставляютсяв форме словаря Python.В первой ссылке, которую я показал вам, говорится, что это не единственный способ предоставления данных для модели, но там есть полный рабочий пример.

Основная идея состоит в том, чтобы построить ваш проект следующим образом:

from pyomo.environ import *
A = {0, 1, 2}
B = {0}

m = AbstractModel()
m.A = Set()
m.B = Set()
m.C = Set()

# ...

# Let's suppose you have completed your AbstractModel here (Params, Vars, Constraints and so on). 
# This is the part where you put your data into a dictionary. 
data = {None: {
    'A': {None: A},
    'B': {None: B},
    'C': {None: A - B}
}}

# And here is the part where you initialize your model:
instance = m.create_instance(data)
for c in instance.C:
    print(c)

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

0 голосов
/ 07 апреля 2019

Если вы хотите смоделировать таким образом, вы должны использовать ConcreteModel и пропустить необходимость создания строки экземпляра. Ваша модель и экземпляр будут одинаковыми.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...