我使用scipy.optimize.minimize来解决复杂的储层优化模型(SQSLP和COBYLA,因为问题受到边界和约束方程的约束)。每天有一个决策变量(存储),并且在目标函数内计算来自储层的释放作为存储变化的函数。然后应用基于释放和存储处罚的处罚,目的是最小化处罚(目标函数是所有处罚的总和)。我在此模型中添加了一些约束,以将存储的变化限制为物理系统限制,这是决策变量x(t + 1)和x(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"]
我出错的任何想法?我已经看到在其他应用程序中出现类似的约束,所以我无法弄清楚但是假设它很简单。我在我的完整版本的代码中启动了数百个约束,因此在第二个示例中将它们写出来并不理想。
答案 0 :(得分:0)
我不太了解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
使用,现在生成一系列正确的函数。