3

私は scipy.optimize.minimize を使用して、複雑な貯水池最適化モデルを解決しています (問題は境界方程式と制約方程式の両方によって制約されているため、SQSLP と COBYLA)。1 日 (貯留) ごとに 1 つの決定変数があり、貯留層からの放出は目的関数内の貯留の変化の関数として計算されます。次に、ペナルティを最小限に抑えることを目的として、リリースとストレージのペナルティに基づくペナルティが適用されます (目的関数はすべてのペナルティの合計です)。このモデル内にいくつかの制約を追加して、ストレージの変更を決定変数 x(t+1) と x(t) の差である物理システム制限に制限し、その時間ステップ I( t)。これらの制約は、for ループを使用して制約辞書のリストに追加されます。この for ループの外側に追加された制約は、必要に応じて機能します。ただし、for ループ内で開始される時間に関する制約は、そうではありません。

明らかに問題は複雑なので、問題を説明するために単純なバージョンを再作成しました。この問題には 4 つの決定変数があり、定常状態 (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"]

私が間違っているアイデアはありますか?他のアプリケーションでも同様に制約が開始されるのを見たことがあるので、それを理解することはできませんが、単純なものだと思います。このコードの本格的なバージョンでは何百もの制約を開始する必要があるため、2 番目の例のようにそれらを書き出すのは理想的ではありません。

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 に答える