繁体   English   中英

scipy.optimize.minimize(COBYLA和SLSQP)忽略for循环内启动的约束

[英]scipy.optimize.minimize (COBYLA and SLSQP) ignores constraints initiated within for loop

我正在使用scipy.optimize.minimize来解决复杂的储层优化模型(SQSLP和COBYLA,因为问题受到边界和约束方程的约束)。 每天有一个决策变量(存储),并且在目标函数内计算来自储层的释放作为存储变化的函数。 然后应用基于释放和存储处罚的处罚,目的是最小化处罚(目标函数是所有处罚的总和)。 我在这个模型中添加了一些约束来限制存储器到物理系统限制的变化,这是决策变量x(t + 1)和x(t)之间的差异,也取决于当时步骤I的流入量( T)。 使用for循环将这些约束添加到约束字典列表中。 在for循环函数之外添加的约束应该如此。 但是,在for循环内启动的涉及时间的约束却没有。

显然问题很复杂,所以我重新创建了一个更简单的版本来说明问题。 这个问题有四个决策变量,并试图通过约束稳态(I =流入必须等于x =流出)和非负性(即流出x不能为负)来最小化目标函数(我称之为函数):

    import numpy as np
    from scipy.optimize import minimize

    def function(x):
        return -1*(18*x[0]+16*x[1]+12*x[2]+11*x[3])

    I=np.array((20,50,50,80))
    x0=I

    cons=[]
    steadystate={'type':'eq', 'fun': lambda x: x.sum()-I.sum() }
    cons.append(steadystate)


    for t in range (4):
        def const(x):    
            y=x[t]
            return y
        cons.append({'type':'ineq', 'fun': const})

    out=minimize(function, x0, method="SLSQP", constraints=cons)
    x=out["x"]

在for循环中启动的约束是非负性约束,但优化给出了决策变量的负值。 但它确实遵守了稳态约束。

当我使用以下代码计算问题时,值被正确约束:

    import numpy as np
    from scipy.optimize import minimize

    def function(x):
        return -1*(18*x[0]+16*x[1]+12*x[2]+11*x[3])

    I=np.array((20,50,50,80))
    x0=I

    cons=[]
    steadystate1={'type':'eq', 'fun': lambda x: x.sum()-I.sum() }
    cons.append(steadystate1)


    nonneg0 = {'type':'ineq', 'fun': lambda x: x[0]}
    nonneg1= {'type':'ineq', 'fun': lambda x: x[1]} 
    nonneg2 = {'type':'ineq', 'fun': lambda x: x[2]} 
    nonneg3 = {'type':'ineq', 'fun': lambda x: x[3]} 
    cons.append(nonneg0)
    cons.append(nonneg1)
    cons.append(nonneg2)
    cons.append(nonneg3)

    out=minimize(function, x0, method="SLSQP", constraints=cons)
    x=out["x"]

我出错的任何想法? 我已经看到在其他应用程序中类似地启动了约束,所以我无法弄明白但是假设它很简单。 我在我的完整版本的代码中启动了数百个约束,因此在第二个示例中将它们写出来并不理想。

我真的不懂Python,但我知道如何解决你的问题。 在你的第一个代码片段中, const函数使用对t本身的引用(因为内部函数与外部共享作用域),因此产生相当于:

cons[0] = {'type':'ineq', 'fun': lambda x: x[t]}
cons[1] = {'type':'ineq', 'fun': lambda x: x[t]} 
cons[2] = {'type':'ineq', 'fun': lambda x: x[t]} 
cons[3] = {'type':'ineq', 'fun': lambda x: x[t]}

这是错的。 这可以通过使用咖喱来解决:

import numpy as np
from scipy.optimize import minimize

def function(x):
    return -1*(18*x[0]+16*x[1]+12*x[2]+11*x[3])

I=np.array((20,50,50,80))
x0=I

cons=[]
steadystate={'type':'eq', 'fun': lambda x: x.sum()-I.sum() }
cons.append(steadystate)

def f(a):
    def g(x):
        return x[a]
    return g

for t in range (4):
    cons.append({'type':'ineq', 'fun': f(t)})

out=minimize(function, x0, method="SLSQP", constraints=cons)
x=out["x"]

在窗帘下,这种方法创建了对t所持有的值的新引用(当您将其作为参数传递给f )并存储此引用以用于g ,现在生成一系列正确的函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM