【发布时间】:2021-10-23 10:12:52
【问题描述】:
我正在尝试在我的目标函数中使用 Pyomo 的分段线性函数。这个分段线性函数实际上是对一个名为macc 的值数组进行插值,该数组有 401 个值(macc[i],i 从 0 到 400)。你可以在附图中看到macc的值
我的目标函数正在寻找 i 的值 macc[i] 尊重约束。为此,我对数组 macc 进行插值,使其具有连续函数 f。见下文:
c = np.arange(401)
f = pyopiecewise.piecewise(c,macc,validate=False)
model = pyo.ConcreteModel()
#Declare variable
model.x = pyo.Var(domain=pyo.NonNegativeReals, bounds=(5,395), initialize = cp0)
#Declare parameters
model.s = pyo.Param(domain=pyo.NonNegativeReals,initialize=s0)
model.b = pyo.Param(domain=pyo.NonNegativeReals,initialize=b0)
model.tnac = pyo.Param(domain=pyo.NonNegativeReals,initialize=tnac0)
#Objective function
def objective_(m):
ab = f(m.x)
e = m.b - ab
return (e * m.x)
#Constraints
def constraint1(m):
ab = f(m.x)
e = m.b - ab
return e <= (m.tnac + m.s)
但是当我尝试在上面的目标函数中调用此函数 f 时,我收到以下消息,表示目标函数中的表达式 ab = f(m.x):
ERROR: Rule failed when generating expression for Objective Obj with index
None: PyomoException: Cannot convert non-constant expression to bool. This
error is usually caused by using an expression in a boolean context such
as an if statement. For example,
m.x = Var() if m.x <= 0:
...
would cause this exception.
ERROR: Constructing component 'Obj' from data=None failed: PyomoException:
Cannot convert non-constant expression to bool. This error is usually
caused by using an expression in a boolean context such as an if
statement. For example,
m.x = Var() if m.x <= 0:
...
would cause this exception.
非常欢迎任何关于如何解决这个问题的想法。
如果需要,这里是完整的代码。对于这个示例,我使用函数创建了数组 macc,但实际上它不是来自函数,而是来自内部数据。
import numpy as np
import pyomo.environ as pyo
import pyomo.core.kernel.piecewise_library.transforms as pyopiecewise
#Create macc
# logistic sigmoid function
def logistic(x, L=1, x_0=0, k=1):
return L / (1 + np.exp(-k * (x - x_0)))
c = np.arange(401)
macc = 2000*logistic(c,L=0.5,x_0 = 60,k=0.02)
macc = macc -macc[0]
f = pyopiecewise.piecewise(c,macc,validate=False)
s0 = 800
b0 = 1000
tnac0 = 100
cp0 = 10
ab0 = 100
model = pyo.ConcreteModel()
#Declare variable
model.x = pyo.Var(domain=pyo.NonNegativeReals, bounds=(5,395), initialize = cp0)
#Declare parameters
model.s = pyo.Param(domain=pyo.NonNegativeReals,initialize=s0)
model.b = pyo.Param(domain=pyo.NonNegativeReals,initialize=b0)
model.tnac = pyo.Param(domain=pyo.NonNegativeReals,initialize=tnac0)
#Objective function
def objective_(m):
ab = f(m.x)
e = m.b - ab
return (e * m.x)
model.Obj = pyo.Objective(rule=objective_)
#Constraints
def constraint1(m):
ab = f(m.x)
e = m.b - ab
return e <= (m.tnac + m.s)
def constraint2(m):
ab = f(m.x)
e = m.b - ab
return e >= 1
def constraint3(m):
ab = f(m.x)
return ab >= 0
model.con1 = pyo.Constraint(rule = constraint1)
model.con2 = pyo.Constraint(rule = constraint2)
model.con3 = pyo.Constraint(rule = constraint3)
【问题讨论】:
-
您是否尝试使用替代变量(比如
model.y = pyo.Var())?您不需要评估 Varmodel.x中的分段,只需在分段函数中使用输入和输出参数即可。f = piecewise(c, macc, input=model.x, output=model.y, ,validate=False)然后只需使用model.y来使用评估的分段函数 -
这个之前的解决方案可能会有所帮助:stackoverflow.com/questions/68626937/… 您正在混合使用
pyomo.environ和pyomo.kernel库,该帖子说这是不行的。它也有一些示例参考。不确定这是否是您的问题。您可能想尝试使用kernel库构建一个“玩具”分段模型(非常简单的模型)并从那里重建,因为您的模型非常小/简单。 -
@pybegginer 感谢您的建议,但我不确定如何实施。你能再扩大一点吗?如果你能告诉我在上面的模型中在哪里写,那会更清楚。谢谢!