1

我尝试使用 pyomo.environ 创建一个 LP 模型。但是,我很难创建集合。对于我的问题,我必须创建两组。一组来自一堆节点,另一组来自节点之间的几个弧。我通过使用 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 不知何故变成了一个元组而不是两个元组,这很奇怪。然后我尝试将我的节点和弧转换为字符串,但仍然出现错误。有人可以给我一些提示吗?或者如何删除这个错误?谢谢!

4

1 回答 1

4

在引擎盖下,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() )

这对于像这样使用浮点数作为索引的模型尤其重要,并且细微的舍入误差会产生几乎相同但在数学上不相等的索引。

开发人员之间已经进行了一些讨论,以支持结构化和扁平化索引,但我们尚未就如何以向后兼容的方式最好地支持它达成共识。

于 2016-10-25T09:02:34.260 回答