TypeError PYOMO:基于 pandas 数据框定义约束

Posted

技术标签:

【中文标题】TypeError PYOMO:基于 pandas 数据框定义约束【英文标题】:TypeError PYOMO: Defining constraints based on pandas dataframe 【发布时间】:2021-06-28 08:50:23 【问题描述】:

对于优化问题,我试图在 PYOMO 中定义一个约束,其中约束表达式包含来自 pandas DataFrame 的一些特定值。

我会尽量简明扼要地解释我的问题。

以下是导入。

from pyomo.environ import *
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt 
from pyomo.opt import SolverFactory

model = ConcreteModel()

以下是决策变量。

model.d1 = Var(bounds=(0.8,1.0), initialize = 0.9)
model.t1 = Var(bounds=(0.1,0.3))

目标函数如下:

model.Total_weight = Objective(expr=  model.t1*model.d1, sense= minimize )

为了制定约束表达式,我使用了 DataFrame 中的一些值。

DataFrame 如下所示:

r1 = [50.05,60.0,70]
r2 = [100,150,200]

df = pd.DataFrame([r1,r2])

        0      1    2
0   50.05   60.0   70
1  100.00  150.0  200

当前想法:

我将 df 中的一些值分配给变量,以便在约束表达式中使用(如下所示)。

v1 = df.iloc[0, 1]
v2 = df.iloc[1,1]

v1 和 v2 的唯一目的是为约束表达式输入值。与优化模型无关。

model.C1 = Constraint(expr =  v1 +  v2 *model.d1 <= 2.1)

但是我在执行这个idea时遇到了如下错误

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-a9a7f2887bcb> in <module>
----> 1 model.C1 = Constraint(expr = v1 +  v2 *model.d1)

TypeError: unsupported operand type(s) for *: 'float' and 'NoneType'

据我了解,python 将 v1 和 v2 视为“float”,而 model.d1 被视为“NoneType”。我尝试通过将initialize 添加到变量model.d1 来运行模型。但它似乎仍然是“NoneType”。

有人可以帮我解决这个问题吗?

非常感谢您。

PS:model.d1.display() 给出以下输出。

d1 : Size=1, Index=None
    Key  : Lower : Value : Upper : Fixed : Stale : Domain
    None :   0.8 :   0.9 :   1.0 : False : False :  Reals

【问题讨论】:

你能在这里补充一点信息或者更完整的代码sn-p。目前尚不清楚您要做什么,也不清楚model.dispmodel.d1 是什么类型的东西以及df 中的内容。请编辑您的帖子,定义所有内容并提供df 的示例。 @AirSquid 感谢您的评论。我已经修改了描述以使其更清晰。如果仍然缺少任何信息,请告诉我。 尝试索引以获取不带内括号的 v1 和 v2。像在 pandas 中那样做会得到一个 Series 对象。所以,试试这个:v1 = df.iloc[0,1] @AirSquid 感谢您的支持。我试过你的建议。不幸的是,它给出了另一种类型的错误。 TypeError: unsupported operand type(s) for *: 'float' and 'NoneType' 好的。您需要发布更多代码来弄清楚为什么 python 认为您的 model.d1 是 NoneType。根据需要发布尽可能多的代码以在对帖子的编辑中重现错误,包括导入等。并包括显示相同错误行的堆栈跟踪。 【参考方案1】:

所以当pyomo 变量是单例时,您可能偶然发现了pyomo 如何与numpy 值交互的一个小错误......我认为这不会像问题那样经常出现在处理索引的pyomo 变量时不会暴露自己,这是迄今为止的大多数情况。你的是非索引单例。

首先,让您的模型开始工作。将来自您的 df 的值转换为浮点数,这可以正常工作。

from pyomo.environ import *
#import numpy as np
import pandas as pd
import matplotlib.pyplot as plt 
#from pyomo.opt import SolverFactory

model = ConcreteModel()

model.d1 = Var(bounds=(0.8,1.0), domain=NonNegativeReals)
model.t1 = Var(bounds=(0.1,0.3), domain=NonNegativeReals)

r1 = [50.05,60.0,70]
r2 = [100,150,200]

df = pd.DataFrame([r1,r2])

v1 = float(df.iloc[0, 1])   # NOTE the float() conversion
v2 = float(df.iloc[1, 1])   # NOTE the float() conversion

model.C1 = Constraint(expr=v1 + v2 * model.d1 <= 2.1)

model.pprint()

可疑的错误...

这两个都应该按照我的理解来执行。我几乎从不处理单例变量(未编入索引),所以这里可能还有其他事情要做。我会尝试将此作为错误提交给 pyomo 人,看看会发生什么。

from pyomo.environ import *
import numpy as np

c = np.float64(1.5)  # a numpy float like what comes out of a pd dataframe...

model_1 = ConcreteModel()

model_1.x = Var()

# a simple expression
e = c * model_1.x     # FAILS!  TypeError: unsupported operand type(s) for *: 'float' and 'NoneType'


model_2 = ConcreteModel()

model_2.S = Set(initialize = [1,])   # indexing set with 1 member

model_2.x = Var(model_2.S)

# same expression
e2 = c * model_2.x[1]  # Works fine...

【讨论】:

这是一个绝妙的调试。效果很好。

以上是关于TypeError PYOMO:基于 pandas 数据框定义约束的主要内容,如果未能解决你的问题,请参考以下文章

JModelica 中的 Python/Pyomo 错误

Pandas :TypeError: float() 参数必须是字符串或数字,而不是 'pandas._libs.interval.Interval'

Pandas:TypeError:sort_values() 缺少 1 个必需的位置参数:'by'

pandas.DataFrame.fillna - TypeError:只有整数标量数组可以转换为标量索引

Pandas/BigQuery - TypeError:“str”和“int”实例之间不支持“<”

将 Pandas 数据帧转换为 Spark 数据帧的 TypeError