我想根据请求的电源配置文件优化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 != 0scipy.optimize.LinearConstraings
但是NonlinearConstraings需要一个jac(据我在github上阅读的内容,这似乎是一个错误),因此我无法使其正常工作。

有什么办法可以使我工作?特别是指定多个边界很重要。

提前致谢!

真诚的
斯科蒂

最佳答案

代码中的profile * x0
“ ValueError:操作数不能与形状(131,)(200,)一起广播”。

只是猜测,是x_t产品onoff_t * xon_t
onoff_t = 0或1
0.3 <= xon_t <= 1t中的每个0 .. T上?
即对于T = 5有2 ^ 5个可能的onoff序列,00000 00001 00010 .. 11111?

如果是这样,请最大化sum 0:T w_t * onoff_t * xon_t
具有固定权重函数w_t的方法很简单:
其中w_t <= 0onoff_t = 0,关闭
其中w_t > 0onoff_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/

10-09 17:09