使用 scipy.minimize 迭代约束

Iterating constraints with scipy.minimize

我正在尝试最小化具有 2 个变量 x[0]、x[1] 的函数。 A、B 和 C 是尺寸为 10x10 的数据框。当我不使用约束时,优化会按预期工作,但我也关心受约束的情况。对于受约束的情况,我想要

A.iloc[i,j]*x[0]*B.iloc[i,j]*x[1]*C.iloc[i,j]

对于 i 和 j 的所有组合都等于或大于零。为此,我按以下方式定义了约束:

cons=[]
def f(a):
    def g(x):
        return A.iloc[i,j]*x[0]*B.iloc[i,j]*x[1]*C.iloc[i,j]
    return g

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

虽然我获得了正确数量的约束(即 len(cons) = 100),但优化结果不满足我想到的约束,这意味着它会导致 x[0]、x [1] 和 x[2]

A.iloc[i,j]*x[0]*B.iloc[i,j]*x[1]*C.iloc[i,j]

对于许多 j,i 小于零。我已经确定 result.success = True,因此可以排除优化突然停止的潜在问题。在寻找这个问题的解决方案时,我发现 也有人试图在 scipy 中迭代约束,但他们只迭代了一个范围而不是两个范围,我无法修改他们的解决方案适用于我的案例。

您的函数 f 没有任何意义,因为函数 g 不依赖于 a。如果你真的想要 f 到 return 一个新函数取决于索引 itf 应该是两个索引的函数:

cons=[]
def f(t, i):
    def g(x):
        return A.iloc[t,i]+(x[0]*B.iloc[t,i]+x[1]*C.iloc[t,i]+x[2]*D.iloc[t,i])/33
    return g

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

另请注意,由于 lambda 表达式,您可以轻松地动态定义约束函数:

cons = []
for t in range(72):
    for i in range(33):
        cons.append({'type': 'ineq', 'fun': lambda x, t=t, i=i: A.iloc[t,i]+(x[0]*B.iloc[t,i]+x[1]*C.iloc[t,i]+x[2]*D.iloc[t,i])/33})