【问题标题】:Retrieving Pyomo solution without using for loop在不使用 for 循环的情况下检索 Pyomo 解决方案
【发布时间】:2018-07-06 14:57:25
【问题描述】:

我正在努力寻找一种有效的方法来检索优化问题的解决方案。该解决方案包含大约 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))

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

【问题讨论】:

  • 您可以通过model.some_var.pprint() 单独检查变量。您需要将.pprint() 添加到末尾,然后您可能会看到带有所有索引的变量。

标签: pyomo


【解决方案1】:

其实有一个非常简单优雅的解决方案,使用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()

【讨论】:

  • 非常感谢!拉格朗日乘数的提取呢?
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

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

    所以如果可以的话,我建议取消这两行。也许有人建议如何加快速度?或者另一种方法。

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

    【讨论】:

      【解决方案4】:

      为了简化代码并在很大程度上避免 for 循环,我在 urbs project 中找到了 pyomoio 模块,它取代了 pandaspyomo.py 的略微弃用的代码。它依赖于每个 pyomo 对象的iteritem() 方法,优雅地处理多个维度。它可以将集合、参数、变量提取为pandas对象。

      如果我建立一个小型 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)
      

      【讨论】:

        猜你喜欢
        • 2021-03-15
        • 1970-01-01
        • 2021-04-03
        • 2013-02-21
        • 2021-12-23
        • 1970-01-01
        • 2017-02-17
        • 2020-08-12
        • 2017-04-27
        相关资源
        最近更新 更多