Python 具有多个边界、约束和连续字段的scipy.optimize
我想根据请求的电源配置文件优化电源的操作。因此,我定义了热电厂应尽可能遵循的功率曲线。 必须应用多个边界和约束来表示热电联产装置的实际运行。例如,这包括CHP可以打开或关闭,并且在打开时,其功率调制只能设置为特定的百分比范围 下面是一个简单的工作示例,并附有简短的说明:Python 具有多个边界、约束和连续字段的scipy.optimize,python,numpy,optimization,scipy,Python,Numpy,Optimization,Scipy,我想根据请求的电源配置文件优化电源的操作。因此,我定义了热电厂应尽可能遵循的功率曲线。 必须应用多个边界和约束来表示热电联产装置的实际运行。例如,这包括CHP可以打开或关闭,并且在打开时,其功率调制只能设置为特定的百分比范围 下面是一个简单的工作示例,并附有简短的说明: import scipy.optimize as opt import numpy as np x = np.arange(200) # dummy x vector poly_profile = np.array( #
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)或(0.3
给出了profile*x0
ValueError:操作数无法与形状(131、)(200、)一起广播 仅凭猜测,
是一种产品x\u t
onoff\u t*xon\t
当
=0或1时onoff\u t
由于问题(开关决策)的离散性,这些类型的电力调度模型通常采用混合整数规划模型进行求解(0.3感谢您的回答。我希望避免使用诸如pyomo之类的MILP工具,以减少我的程序对其他模块的依赖性。这种优化在一个更大的模拟程序中每隔几步就被称为一次,并将用于在模拟中设置一些变量。因此,我确实希望避免使用过于复杂的优化,而无法同时使用保持良好的性能。如果没有直接的方法来实现离散边界,我仍然可以在优化后手动剪裁这些边界。这当然是最坏的情况,但仍然可以,因为优化每隔几步执行一次,因此错误将很小。但我也无法确定如何限制启动次数。有没有关于如何o这?只关注约束(x==0)或(0.3好吧,我想我只能用
0来做了。嗨,丹尼斯。非常感谢你的帮助。是的,现在你给了我一个例子,在
和onoff\t
中分离xon\u t
,这看起来很小。但我在试图自己解决它时没有考虑到这种可能性。)脉冲发生器也非常有用。但是我不能让它在任意数量的脉冲下工作,因为只有最大数量的脉冲是有限的,但允许使用较少的脉冲。例如,最多4个脉冲,但最佳解决方案仅使用2个脉冲。我是否要就此主题提出一个新问题?x
does在我的代码中没有引起任何错误。看起来您使用的是python 2.x。在python 3和2.x之间使用numpy数组可能有一些不同。因为行profile*x0
profile=poly_-fun(x[65:196])
应该清楚地避免x0=np.zeros\u like(profile)
和轮廓
@Scotty1的任何形状不匹配-假设您如上所述定义x0
和pulsegen2
。运行它们的一种方法是:pulsegen3
对于大型发电机来说,使用更少内存的一种更奇特的方法是用于列表中的脉冲(pulsegene2)+列表(pulsegen3):…
,请参见。任何数量的脉冲都是code golf,首先要做2 3 4。此外,“固定权重函数…微不足道”?感谢您提供的更多信息。是的,砰砰控制并不是处理控制的好方法,但在许多领域,它仍然是一种常见的控制策略。此外,正如您所建议的,叠加“砰砰”具有连续变量的脉冲发生器听起来像是一个可接受的解决方法,因为这种情况下的优化问题相当小,并且结果被输入到一个具有高惯性的非刚性常微分方程系统中,导致整个系统对优化结果突变的灵敏度较低。关于功能pr编程:在我的理解中,函数编程意味着编写一个通用的脉冲发生器函数,可以在脉冲发生器中为任意数量的脉冲重复使用,而不必为特定数量的脉冲编写脉冲发生器。itertools.chain
似乎仍然是处理脉冲发生器的好方法对于特定数量的脉冲。Itertools.chain
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')
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