3

我正在使用 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"]

有什么想法我哪里出错了吗?我已经看到在其他应用程序中类似地启动了约束,所以我无法弄清楚,但假设它很简单。我有数百个约束要在此代码的完整版本中启动,因此像第二个示例中那样将它们写出来并不理想。

4

1 回答 1

1

我不太了解 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,现在生成一系列正确的函数。

于 2016-03-09T21:16:14.707 回答