[英]Using piecewise function in objective function in Pyomo
I am trying to use a piecewise linear function from Pyomo in my objective function.我试图在我的目标函数中使用 Pyomo 的分段线性函数。 This piecewise linear function is actually interpolating an array of values called
macc
, having 401 values (macc[i], i from 0 to 400).这个分段线性函数实际上是插入一个名为
macc
的值数组,它有 401 个值(macc[i], i 从 0 到 400)。 You can see the values of macc in the picture attached您可以在附图中看到 macc 的值
My objective function is looking for the value i
for which macc[i]
respect the constraints.我的目标函数正在寻找
macc[i]
遵守约束的值i
。 To do that I interpolate the array macc to have a continuous function f.为此,我插入数组 macc 以获得连续函数 f。 See below:
见下文:
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)
But when I try to call this function f in my objective function above, I get the message below for the expression ab = f(mx)
in the objective function:但是,当我尝试在上面的目标函数中调用此函数 f 时,我收到以下关于目标函数中表达式
ab = f(mx)
的消息:
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.
Any idea on how to solve that would be very welcome.关于如何解决这个问题的任何想法都会非常受欢迎。
Here is the complete code if needed.如果需要,这里是完整的代码。 For this example I created the array macc with a function, but in reality it does not come from a function but from internal data.
对于这个例子,我用一个函数创建了数组 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)
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)
@RonB @罗恩
As AirSquid commented, you're using the kernel
and environ
namespace.正如 AirSquid 评论的那样,您正在使用
kernel
和environ
命名空间。 You should avoid this mixing, since several approach may not be compatible.您应该避免这种混合,因为几种方法可能不兼容。
Instead of explicit evaluating the piecewised funtion using the __call__()
( f(model.x)
) method you can use the input, output args (in environ layer are called xvar
, yvar
) to output the evaluation in a defined variable.无需使用
__call__()
( f(model.x)
) 方法显式评估分段函数,您可以使用输入、输出参数(在环境层中称为xvar
、 yvar
)在定义的变量中输出评估。
Using the environ layer, piecewise function are available in pyo.Piecewise使用environ层,分段函数在pyo.Piecewise中可用
import numpy as np
import pyomo.environ as pyo
#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.linspace(0,400,4)
macc = 2000*logistic(c,L=0.5,x_0 = 60,k=0.02)
s0 = 800
b0 = 1000
tnac0 = 100
cp0 = 10
ab0 = 100
#Start modeling
model = pyo.ConcreteModel()
#Declare variable
model.x = pyo.Var(domain=pyo.NonNegativeReals, bounds=(5,395), initialize = cp0)
model.y = pyo.Var() #The output of piecewise. Equivalent to model.y=piecewise(model.x)
model.piecewise = pyo.Piecewise(
model.y,
model.x,
pw_pts=list(c),
f_rule=list(macc),
pw_constr_type='EQ'
)
#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
model.Obj = pyo.Objective(expr= (model.b - model.y)*model.x, sense=pyo.minimize)
#Constraints
model.con1 = pyo.Constraint(expr=model.b - model.y <= model.tnac + model.s)
model.con2 = pyo.Constraint(expr=model.b - model.y >= 1)
model.con3 = pyo.Constraint(expr= model.y >= 0)
In this modeling approach you don't have the problem of evaluate model.piecewise(model.x)
in each equation (constraint or objective), instead you will just use model.y
which is equivalent to evaluate.在这种建模方法中,您没有在每个方程(约束或目标)中评估
model.piecewise(model.x)
的问题,相反,您将只使用等效于评估的model.y
。
Now, I don't know your problem, but that I guess your objective is not convex, which may be a further problem in the optimization.现在,我不知道你的问题,但我猜你的目标不是凸的,这可能是优化中的另一个问题。 you can use
Gurobi
to solve such problems, but in this case, as model.y
depends upon model.x
and model.x
is bounded, is going to the model.x
upper bound in order to make objective as low as possible (since you don't declare any sense in the objective, I assume that you want to minimize).您可以使用
Gurobi
来解决此类问题,但在这种情况下,由于model.y
依赖于model.x
并且model.x
是有界的,因此会到达model.x
上限以使目标尽可能低(因为您没有在目标中声明任何意义,我假设您想最小化)。 I think you should check your objective if it represents what you think.我认为你应该检查你的目标是否代表你的想法。
Your objective function is doint something like this你的目标函数是这样的
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.