我想根据请求的电源配置文件优化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
中的任何值>0.3
和<= 1
。但是我可以指定下限 OR 。仅指定上限,就不可能将“ CHP关闭”,而将下限设置为
bnds_lo = opt.Bounds(0, 1)
bounds=[bnds_lo, bnds_hi]
?以及我要使用的约束:
np.sum(x*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,因为将边界设置为(0, 1)
。但是其他问题也可能是原因)...
x != 0
是有利的。我考虑过尝试与上一点类似的操作(限制启动次数),但也无法解决一些有用的问题。这是迄今为止最不重要的问题。为了解决这些问题,我也尝试使用
scipy.optimize.LinearConstraings
和NonlinearConstraings
但是method='trust-constr'
需要一个jac(就我在github上阅读的内容来看,这似乎是一个错误),因此我无法使其正常工作。
有什么办法可以使我工作?特别是指定多个边界很重要。
谢谢!
此致, 斯科蒂
答案 0 :(得分:2)
profile * x0
给出了
“ ValueError:操作数不能与形状(131,)(200,)一起广播”。
仅凭猜测,x_t
是产品onoff_t * xon_t
onoff_t
= 0或1
和{{1}中每个0.3 <= xon_t <= 1
处的t
吗?
即对于0 .. T
,有2 ^ 5个可能的T = 5
序列,00000 00001 00010 .. 11111吗?
如果是,则最大化onoff
具有固定权重函数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
仅切换两次,则0 ... 1 ... 0 ...,
那么可能序列的数量就很小,可以全部尝试,
大致而言:
onoff_t
切换4次,0 ... 1 ... 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
有多少个这样的脉冲?
参见维基百科Stars and bars-
很棒。)
另请参阅: 谷歌“离散优化”多重网格...和 Grid search。