Python中scipy库的minimize函数响应不正确的问题

6vl6ewon  于 7个月前  发布在  Python
关注(0)|答案(1)|浏览(126)

为了计算电路,我在计算具有并联连接的电路时遇到了最小化函数的不正确响应的问题。例如:

创建连接矩阵并填写电阻矩阵:形式的等式:A*x = V,其中函数sum(F * x**3)-> minimum

import numpy as np
from scipy.optimize import minimize, LinearConstraint

def CreateArrays(A,V):
    A = np.array(A) #matrix of connections
    V = np.array(V)
    buf = [0.1 for i in range(len(A[0]))]
    x0 = np.array(buf)
    return A,V,x0

def start(A,V,F):
    def obj_func(x):
        return np.sum(F * x**3)
    A,V,x0 = CreateArrays(A,V)
    lincon = LinearConstraint(A, lb=V, ub=V)
    
    res = minimize(obj_func, x0, method='trust-constr', constraints=lincon)
    return res.x
#Matrix of connections, vector V, vector F
I = start([[1, 0, 1], [0, -1, -1], [-1, 1, 0]], 
      [100, -100, 0],[1e-4, 1e-4, 8e-4])
print(I)

结果是[33.36666667 33.36666667 66.63333333],但这是一个错误;真正的结果是[66.6333333,66.6333333,33.36666667],其中函数的值是最小值。电阻越大,电流越小。
我发现最小与此代码:

f = [1e-4,1e-4,8e-4]
s=0

save = 0.5
x = [0.5,0.5,99.5]
for i in range(len(x)):
    s = s + f[i] * x[i]**3
mini = s                     #start minimum
print(mini)
j = 0.5
while j < 100:
    x = [j, j, 100-j]  
    s=0
    for i in range(len(x)):
        s = s + f[i] * x[i]**3 
    if s < mini:
        mini = s
        save = x  
    j =j +  0.5
print(mini,save)
iibxawm4

iibxawm41#

问题似乎就在这里:

lincon = LinearConstraint(A, lb=V, ub=V)

这个约束似乎打乱了SLSQP、COBYLA和trust-constr。SLSQP抱怨奇异约束矩阵。COBYLA抱怨它只支持ineq约束,而不支持eq约束。trust-constr可以工作,但是一旦找到了满足约束的解决方案,就不会有任何进展。
我发现有两件事很有帮助。
第一个是对x 0使用一个更好的初始猜测,从服从约束的东西开始。

def CreateArrays(A,V):
    A = np.array(A) #matrix of connections
    V = np.array(V)
    x0 = np.linalg.lstsq(A, V, rcond=None)[0]
    return A,V,x0

第二件事是给给予线性约束一些摆动的空间,并允许它在任何方向上偏离一个方向。最初,允许线性约束变化0.001,并从那里减少。

def start(A,V,F):
    def obj_func(x):
        ret = np.sum(F * x**3)
        return ret
    A,V,x0 = CreateArrays(A,V)
    for eps in [1e-3, 1e-6, 1e-9, 0]:
        lincon = LinearConstraint(A, lb=V - eps, ub=V + eps)
        res = minimize(obj_func, x0, method='trust-constr', constraints=lincon)
        x0 = res.x
    return res.x

通过这些更改,trust-constr和COBYLA都可以解决这个问题。

相关问题