我想根据请求的电源配置文件优化CHP plant的操作。因此,我定义了功率曲线,CHP工厂应尽可能地遵循该功率曲线。
必须应用多个界限和约束条件来代表CHP工厂的实际运行。例如,这包括CHP可以打开或关闭,并且在打开时,其功率调制只能设置为特定百分比范围。
这是一个带有简短说明的最小工作示例:
import scipy.optimize as opt
import numpy as np
x = np.arange(200) # dummy x vector
poly_profile = np.array( # 7th degree polynome fit of profile
[-2.14104340e-11, 1.85108903e-08, -6.66697810e-06, 1.29239710e-03,
-1.45110876e-01, 9.40324129e+00, -3.24548750e+02, 4.60006330e+03])
poly_fun = np.poly1d(poly_profile) # make poly fun
profile = poly_fun(x[65:196])
x0 = np.zeros_like(profile) # all zeros as starting values
def optifun(x, profile): # define minimization fun
return - np.sum(profile * x)
bnds_hi = opt.Bounds(0.3, 1) # upper bounds
bnds_lo = opt.Bounds(0, 0) # lower bounds
res = opt.minimize(
optifun, x0, args=(profile), bounds=bnds_hi,
constraints={'type': 'eq', 'fun': lambda x: np.sum(x*40) - 2000},
method='SLSQP')
plt.plot(res.x)
plt.plot(profile)
所以这些是我要使用的界限:
(x == 0) or (0.3 <= x <= 1)
,用于数组x
中的任何值这意味着总CHP功率的调制度x可以为0(关闭),也可以为
>0.3
和<= 1
。但是我可以指定下限或上限。仅指定上限,就不可能将“ CHP关闭”,而将下限设置为bnds_lo = opt.Bounds(0, 1)
将使热电联产厂能够在非现实的运行点(功率调制的0%至30%之间)下运行。
有什么方法可以按照最小工作示例中指定的范围进行这项工作?具体来说:是否可以同时设置两种边界,例如
bounds=[bnds_lo, bnds_hi]
?我猜这是一个混合整数线性编程问题,但是COBYLA或SLSQP是否应该能够解决这个问题?如果没有:有任何解决方法吗?
和我想使用的约束:
np.sum(x*40) - 450
将热量输出限制为一定的热量存储容量。这里40是热输出功率,而450是剩余存储容量。这相当容易实现。
限制CHP工厂的启动次数。作为一个例子,让我们假设
bnds_lo = opt.Bounds(0, 1) # lower bounds
res = opt.minimize(
optifun, x0, args=(profile), bounds=bnds_lo,
constraints={'type': 'eq', 'fun': lambda x: np.sum(x*40) - 1000},
method='SLSQP')
这导致了热电联产工厂运行的三个阶段。有什么办法可以限制这个?我当时正在考虑添加一个特殊的约束函数,该函数在前导0之后对正差值进行计数,但是我无法进行类似的工作(例如,由于大多数
x
都不完全是0,因为边界设置为。但是其他问题也可能是原因)...设置CHP工厂的最小连续运行时间。这意味着至少有5个连续的
(0, 1)
应该是有利的。我曾考虑过尝试与上一点类似的操作(限制启动次数),但也无法解决一些有用的问题。到目前为止,这是最不重要的问题。为了解决这些问题,我也尝试使用
x != 0
和scipy.optimize.LinearConstraings
但是
NonlinearConstraings
需要一个jac(据我在github上阅读的内容,这似乎是一个错误),因此我无法使其正常工作。有什么办法可以使我工作?特别是指定多个边界很重要。
提前致谢!
真诚的
斯科蒂
最佳答案
代码中的profile * x0
“ ValueError:操作数不能与形状(131,)(200,)一起广播”。
只是猜测,是x_t
产品onoff_t * xon_t
onoff_t
= 0或1
和0.3 <= xon_t <= 1
在t
中的每个0 .. T
上?
即对于T = 5
有2 ^ 5个可能的onoff
序列,00000 00001 00010 .. 11111?
如果是这样,请最大化sum 0:T w_t * onoff_t * xon_t
具有固定权重函数w_t
的方法很简单:
其中w_t <= 0
:onoff_t = 0
,关闭
其中w_t > 0
:onoff_t = 1
,打开,xon_t = 1
,最大值。
因此,这不是您的问题-请澄清。
如果进一步限制onoff_t
仅切换两次,则0 ... 1 ... 0 ...,
那么可能序列的数量就足够小,可以全部尝试,
大致而言:
def pulse_generator( T=200, minwidth=5 ):
""" -> arrays of T floats, 0... 1... 0... """
for t0 in xrange( 1, T ):
for t1 in xrange( t0 + minwidth, T ):
pulse = np.zeros( T )
pulse[t0:t1] = 1
yield pulse
for pulse in pulse_generator( T ):
print "pulse:", pulse
optimize myfunction( pulse * xon ), 0.3 <= xon <= 1
切换4次,0 ... 1 ... 0 ... 1 ... 0 ...是相似的。
(给定的
T
有多少个这样的脉冲?参见维基百科Stars and bars-
惊人。)
补充:我不是专家,但又不是开关
bang-bang control
对微小的变化非常敏感,是早一点还是晚一点?
一个程序(mer)可能花很多时间抖动,从而降低噪音。
分为两阶段,粗电网然后细电网
将时间0:T分成10个片段,全部运行2 ^ 10 = 1024个开关序列
1a。仔细观察最好的-有什么模式吗?
将其边缘移动一半,T / 20。
也可以看看:
谷歌“离散优化”多重网格...和
Grid search。
关于python - scipy.optimize具有多个范围,约束和连续字段,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52781901/