在不使用for循环的情况下检索Pyomo解决方案

时间:2018-01-27 11:40:18

标签: pyomo

我正在努力寻找一种有效的方法来检索优化问题的解决方案。该解决方案包含大约200K个变量,我想在pandas DataFrame中使用。在线搜索后,我发现访问变量的唯一方法是通过for循环看起来像这样:

instance = M.create_instance('input.dat') # reading in a datafile
results = opt.solve(instance, tee=True)
results.write()
instance.solutions.load_from(results)

for v in instance.component_objects(Var, active=True): 
    print ("Variable",v)
    varobject = getattr(instance, str(v))
    for index in varobject:
        print ("   ",index, varobject[index].value)

我知道我可以使用for循环将它们存储在数据帧中,但效率非常低。 我找到了如何使用

访问索引
import pandas as pd
index = pd.DataFrame(instance.component_objects(Var, active=True))

但我不知道如何获得解决方案

4 个答案:

答案 0 :(得分:0)

当然,您可以使用instance.some_var.pprint()在屏幕上打印它。 但是如果你有一个由大集索引的变量。你也可以写它 单独的文件。以下代码将结果写入.txt文件:

f = open('Result.txt', 'a')
instance.some_var.pprint(f)
f.close()

答案 1 :(得分:0)

为了简化代码并在很大程度上避免for循环,我在urbs project中找到了pyomoio模块,该模块已接管了pandaspyomo.py稍有过时的代码。它依赖于每个pyomo对象的iteritem()方法,并优雅地处理多个维度。它可以提取集,参数,变量作为熊猫对象。

如果我建立一个小型pyomo模型

from pyomo.environ import *
import pyomoio as po
import pandas as pd

# Define a model with 200k values
m = ConcreteModel()
m.ix = RangeSet(200000)
def idem(model, i):
    return i
m.a = Param(m.ix, rule=idem)

我只需一行代码就可以读取参数

%%timeit
a_po = po.get_entity(m, 'a')

# 110 ms ± 1.88 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

但是,如果将其与原始问题中的方法进行比较,它的速度不是更快,甚至更慢:

%%timeit
val = []
ix = []
varobject = getattr(m, 'a')
for index in varobject:
    ix.append(index)
    val.append(varobject[index])
a = pd.Series(index=ix, data=val)
# 92.5 ms ± 1.57 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

答案 2 :(得分:0)

结合使用pandas.DataFrame.from_dict方法和Var.extract_values()方法,实际上是一个非常简单而优雅的解决方案。

from pyomo.environ import *
import pandas as pd
m = ConcreteModel()
m.N = RangeSet(5)
m.x = Var(m.N, rule=lambda _, el: el**2)  # x = [1,4,9,16,25]

df = pd.DataFrame.from_dict(m.x.extract_values(), orient='index', columns=[str(m.x)])
print(df)

收益

    x
1   1
2   4
3   9
4  16
5  25

请注意,对于Var,我们可以同时使用get_values()extract_values(),它们似乎一样。对于Param,只有extract_values()

答案 3 :(得分:0)

我遇到了与Jasper相同的问题,并尝试了建议的解决方案。通过这样做,我注意到编写结果的部分花费了很多时间。在贾斯珀的案子中也许也是如此。

results.write()
instance.solutions.load_from(results)

因此,如果可以的话,我建议压住这两行。也许有人对如何加快速度提出了建议?或另一种方法。

我也看到了这篇文章(Pyomo:将结果保存到CSV文件),建议使用“ for循环”方法。 pyomo开发人员指出:“我认为选项2中的索引和变量slice可能以不同的顺序进行迭代,这会使结果数组无效。”