Как создать двумерный набор объектов в модуле pyomo.environ

Я попытался создать модель LP с помощью pyomo.environ. Однако мне сложно создавать декорации. Для моей задачи мне нужно создать два набора. Один набор состоит из группы узлов, а другой - из нескольких дуг между узлами. Я создаю сеть, используя Networkx для хранения моих узлов и дуг. Данные узла сохраняются как (Долгота, Широта) в форме кортежа. Дуги сохраняются как (nodeA, nodeB), где nodeA и nodeB являются координатами в кортеже.

Итак, узел выглядит примерно так:

(-97.97516252657978, 30.342243012086083)

А дуга - это что-то вроде:

((-97.97516252657978, 30.342243012086083), (-97.976196300350608, 30.34247219922803))

Я пытался создать набор следующим образом:

# import pyomo.envrion as pe
# create a model m 
m = pe.ConcreteModel()
# network is an object I created by Networkx module
m.node_set = pe.Set(initialize= self.network.nodes()) 
m.arc_set = pe.Set(initialize= self.network.edges())

Однако я продолжал получать сообщение об ошибке на arc_set.

ValueError: The value=(-97.97516252657978, 30.342243012086083,
-97.976196300350608, 30.34247219922803) does not have dimension=2, 
which is needed for set=arc_set

Мне показалось странным, что каким-то образом мой arc_set превратился в один кортеж вместо двух. Затем я попытался преобразовать свои узлы и дуги в строку, но все равно получил ошибку. Может кто-нибудь показать мне намек? Или как удалить этот баг? Спасибо!


person whh1294    schedule 25.10.2016    source источник


Ответы (1)


Под капотом Pyomo «выравнивает» все наборы индексации. То есть он удаляет вложенные кортежи, так что каждый член набора представляет собой один кортеж скалярных значений. Это обычно согласуется с другими языками алгебраического моделирования и помогает убедиться, что мы можем последовательно (и правильно) извлекать элементы компонентов независимо от того, как пользователь пытался их запросить.

В вашем случае Pyomo захочет, чтобы каждый член дуги был установлен как один кортеж из 4 элементов. В PyUtilib есть утилита, которую вы можете использовать для сглаживания кортежей при построении набора:

from pyutilib.misc import flatten
m.arc_set = pe.Set(initialize=(tuple(flatten(x)) for x in self.network.edges())

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

from pyutilib.misc import flatten
m.node_set = pe.Set( initialize=self.network.nodes() ) 
m.arc_set = pe.Set(
    within=m.node_set*m.node_set,
    initialize=(tuple(flatten(x)) for x in self.network.edges() )

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

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

person jsiirola    schedule 25.10.2016