scipy.optimize.minimize(COBYLA和SLSQP)忽略在for循环中启动的约束 [英] scipy.optimize.minimize (COBYLA and SLSQP) ignores constraints initiated within for loop

查看:266
本文介绍了scipy.optimize.minimize(COBYLA和SLSQP)忽略在for循环中启动的约束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用scipy.optimize.minimize解决一个复杂的油藏优化模型(SQSLP和COBYLA,因为问题受边界和约束方程式约束).每天有一个决策变量(存储量),在目标函数内,根据存储量的变化来计算存储库的释放量.然后基于释放和存储罚则的罚则被应用,目的是使罚分最小化(目标函数是所有罚分的总和).我在此模型中添加了一些约束,以将存储更改限制为物理系统限制,这是决策变量x(t + 1)和x(t)之间的差,并且还取决于当时的流入量I( t).使用for循环将这些约束添加到约束字典列表中.在此for循环功能之外添加的约束应按其应有的方式进行.但是,不是在for循环中启动的涉及时间的约束.

I'm using scipy.optimize.minimize to solve a complex reservoir optimization model (SQSLP and COBYLA as the problem is constrained by both bounds and constraint equations). There is one decision variable per day (storage), and releases from the reservoir are calculated as a function of change in storage, within the objective function. Penalties based on releases and storage penalties are then applied with the goal of minimizing penalties (the objective function is a summation of all penalties). I've added some constraints within this model to limit the change in storage to the physical system limits which is the difference between decision variable x(t+1) and x(t), and also depends on inflows at that time step I(t). These constraints are added to the list of constraint dictionaries using a for loop. Constraints added outside of this for loop function as they should. However the constraints involving time that are initiated within the for loop, do not.

显然,问题很复杂,因此我重新创建了一个更简单的版本来说明问题.这个问题有四个决策变量,力求在稳态(I =流入必须等于x =流出)和非负(即流出x不能为负)的约束下,最小化目标函数(我称之为函数): /p>

Obviously the problem is complex so I've recreated a simpler version to illustrate the problem. This problem has four decision variables and seeks to minimize the objective function (which I've called function) with constraints of steady state (I = inflow must equal x = outflow) and non negativity (ie. outflows x cannot be negative):

    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循环中启动的约束是非负约束,但是优化为决策变量提供了负值.但是,它确实遵守稳态约束.

The constraints initiated in the for loop are non-negativity constraints but the optimization gives negative values for the decision variables. It does adhere to the steadystate constraint, however.

当我使用以下代码计算问题时,值受到了适当的约束:

When I calculate the problem using the following code, values are constrained properly:

    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"]

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

Any ideas where I'm going wrong? I've seen constraints initiated similarly in other applications so I can't figure it out but assume it's something simple. I have hundreds of constraints to initiate in my full-scale version of this code so writing them out as in the second example will not be ideal.

推荐答案

我不太了解Python,但我知道如何解决您的问题.在您的第一个代码段中,const函数使用对t本身的引用(因为内部函数与外部共享作用域),因此产生了等同于:

I don't really know Python, but i know how to solve your problem. In your first snippet const function uses reference to t itself (because inner function shares scope with outer), thus producing equivalent of:

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]}

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

which is wrong. This could be fixed by using curry:

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中使用,现在生成了一系列正确的函数.

Under the curtains, this approach creates a new reference to value held by t (when you pass it as argument to f) and stores this reference for use in g, now generating series of correct functions.

这篇关于scipy.optimize.minimize(COBYLA和SLSQP)忽略在for循环中启动的约束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆