Python 求解非线性方程组的信赖域折线法

Python 求解非线性方程组的信赖域折线法,python,Python,您好,我正在尝试为我拥有的一个类编写一个信赖域算法,该算法使用python中的dogleg方法。我有一个牛顿法算法和布罗登法算法,它们彼此一致,但我似乎无法让这个狗腿法工作 以下是我试图找到解决方案的函数: def test_function(x): x1 = float(x[0]) x2 = float(x[1]) r = np.array([[x2**2 - 1], [np.sin(x1) - x2]]) return r

您好,我正在尝试为我拥有的一个类编写一个信赖域算法,该算法使用python中的dogleg方法。我有一个牛顿法算法和布罗登法算法,它们彼此一致,但我似乎无法让这个狗腿法工作

以下是我试图找到解决方案的函数:

def test_function(x):
    x1 = float(x[0])
    x2 = float(x[1])
    r = np.array([[x2**2 - 1],
                  [np.sin(x1) - x2]])
    return r
这是我写的雅可比矩阵

def Test_Jacobian(x, size):
    e = create_ID_vec(size)
    #print(e[0])
    epsilon = 10e-8
    J = np.zeros([size,size])
    #print (J)
    for i in range(0, size):
        for j in range(0, size):
            J[i][j] = ((test_function(x[i]*e[j] + epsilon*e[j])[i] - test_function(x[i]*e[j])[i])/epsilon)
    return J
这是我的信赖域算法:

def Trust_Region(x):
    trust_radius = 1
    max_trust = 300
    eta = rand.uniform(0,.25)
    r = test_function(x) # change to correspond with the function you want
    J = Test_Jacobian(r, r.size) # change to correspond with function
    i = 0
    iteration_table = [i]
    function_table = [vector_norm(r, r.size)]
    while vector_norm(r, r.size) > 10e-10:
        print(x, 'at iteration', i, "norm of r is", vector_norm(r, r.size))
        p = dogleg(x, r, J, trust_radius)
        rho = ratio(x, J, p)
        
        if rho < 0.25:
            print('first')
            trust_radius = 0.25*vector_norm(p,p.size)
        elif rho > 0.75 and vector_norm(p,p.size) == trust_radius:
            print('second')
            trust_radius = min(2*trust_radius, max_trust)
        else:
            print('third')
            trust_radius = trust_radius
            
        if rho > eta:
            print('x changed')
            x = x + p
            #r = test_function(x)
            #J = Test_Jacobian(r, r.size)
        else:
            print('x did not change')
            x = x
            
        r = test_function(x) # change to correspond with the function you want
        J = Test_Jacobian(r, r.size) # change to correspond with function
        i = i + 1
        #print(r)
        #print(J)
        #print(vector_norm(p,p.size))
        print(rho)
        #print(trust_radius)
        iteration_table.append(i)
        function_table.append(vector_norm(r,r.size))
    print ('The solution to the non-linear equation is: ', x)
    print ('This solution was obtained in ', i, 'iteratations')
    plt.figure(figsize=(10,10))
    plt.plot(iteration_table, np.log10(function_table))
    plt.xlabel('iteration number')
    plt.ylabel('function value')
    plt.title('Semi-Log Plot for Convergence')
    return x, iteration_table, function_table

def dogleg(x, r, J, trust_radius):
    tau_k = min(1, vector_norm(J.transpose().dot(r), r.size)**3/(trust_radius*r.transpose().dot(J).dot(J.transpose().dot(J)).dot(J.transpose()).dot(r)))
    p_c = -tau_k*(trust_radius/vector_norm(J.transpose().dot(r), r.size))*J.transpose().dot(r)
    
    if vector_norm(p_c, p_c.size) == trust_radius:
        print('using p_c')
        p_k = p_c
    else:
        p_j = -np.linalg.inv(J.transpose().dot(J)).dot(J.transpose().dot(r))
        print ('using p_j')
        tau = tau_finder(x, p_c, p_j, trust_radius, r.size)
        p_k = p_c + tau*(p_j-p_c)
    return p_k

def ratio(x, J, p):
    r = test_function(x)
    r_p = test_function(x + p)
    print (vector_norm(r, r.size)**2)
    print (vector_norm(r_p, r_p.size)**2)
    print (vector_norm(r + J.dot(p), r.size)**2)
    rho_k =(vector_norm(r, r.size)**2 - vector_norm(r_p, r_p.size)**2)/(vector_norm(r, r.size)**2 - vector_norm(r + J.dot(p), r.size)**2)
    return rho_k

def tau_finder(x, p_c, p_j, trust_radius, size):
    a = 0
    b = 0
    c = 0
    for i in range(0, size):
        a = a + (p_j[i] - p_c[i])**2
        b = b + 2*(p_j[i] - p_c[i])*(p_c[i] - x[i])
        c = (p_c[i] - x[i])**2
    c = c - trust_radius**2
    tau_p = (-b + np.sqrt(b**2 - 4*a*c))/(2*a)
    tau_m = (-b - np.sqrt(b**2 - 4*a*c))/(2*a)
    #print(tau_p)
    #print(tau_m)
    if tau_p <= 1 and tau_p >=0:
        return tau_p
    elif tau_m <= 1 and tau_m >=0:
        return tau_m
    else:
        print('error')
        return 'error'

def model_function(p):
    r = test_function(x)
    J = Test_Jacobian(r, r.size)
    return 0.5*vector_norm(r + J.dot(p), r.size)**2
def信任区域(x):
信任半径=1
最大信任度=300
eta=平均兰特(0.25)
r=测试功能(x)#更改以符合所需的功能
J=测试_雅可比矩阵(r,r.size)#与函数相对应的变化
i=0
迭代_表=[i]
函数\u表=[向量\u范数(r,r.size)]
当向量_范数(r,r.size)>10e-10时:
打印(x,‘在迭代中’,i,“r的范数为”,向量_范数(r,r.size))
p=狗腿(x,r,J,信赖半径)
rho=比率(x,J,p)
如果rho<0.25:
打印('第一个')
信任半径=0.25*向量标准(p,p.size)
elifρ>0.75且向量_范数(p,p.size)=信任半径:
打印('秒')
信任半径=最小值(2*信任半径,最大信任)
其他:
打印('第三')
信任半径=信任半径
如果rho>eta:
打印('x已更改')
x=x+p
#r=测试功能(x)
#J=测试_雅可比矩阵(r,r.尺寸)
其他:
打印('x未更改')
x=x
r=测试功能(x)#更改以符合所需的功能
J=测试_雅可比矩阵(r,r.size)#与函数相对应的变化
i=i+1
#印刷品(r)
#印刷品(J)
#打印(向量_范数(p,p.size))
打印(rho)
#打印(信任半径)
迭代_table.append(i)
函数\表.追加(向量\范数(r,r.size))
print('非线性方程的解为:',x)
print('此解决方案是在'i'迭代'中获得的)
plt.图(figsize=(10,10))
plt.plot(迭代表,np.log10(函数表))
plt.xlabel('迭代编号')
plt.ylabel('函数值')
plt.title(‘收敛的半对数图’)
返回x,迭代表,函数表
def狗腿(x,r,J,信赖半径):
tau_k=min(1,向量_范数(J.transpose().dot(r),r.size)**3/(信任半径*r.transpose().dot(J.transpose().dot(J)).dot(J.transpose().dot(J)).dot(J.transpose().dot(r)))
p_c=-tau_k*(信赖半径/向量_范数(J.transpose().dot(r),r.size))*J.transpose().dot(r)
如果向量_范数(p_c,p_c.size)=信任半径:
打印('使用p_c')
p_k=p_c
其他:
p_j=-np.linalg.inv(j.transpose().dot(j)).dot(j.transpose().dot(r))
打印('使用p_j')
tau=tau_查找器(x,p_c,p_j,信任半径,r.size)
p_k=p_c+tau*(p_j-p_c)
返回Pk
def比率(x,J,p):
r=测试功能(x)
r_p=测试函数(x+p)
打印(向量_范数(r,r.尺寸)**2)
打印(矢量规格(r\U p,r\U p.尺寸)**2)
打印(矢量_范数(r+J点(p),r尺寸)**2)
rho_k=(向量_范数(r,r.size)**2-向量_范数(r_p,r_p.size)**2)/(向量_范数(r,r.size)**2-向量_范数(r+J.dot(p),r.size)**2)
返回rho_k
def tau_finder(x、p_c、p_j、信任半径、大小):
a=0
b=0
c=0
对于范围内的i(0,大小):
a=a+(p_j[i]-p_c[i])**2
b=b+2*(p_j[i]-p_c[i])*(p_c[i]-x[i])
c=(p_c[i]-x[i])**2
c=c-信任半径**2
tau_p=(-b+np.sqrt(b**2-4*a*c))/(2*a)
tau_m=(-b-np.sqrt(b**2-4*a*c))/(2*a)
#印刷品(陶普)
#印刷品(头像)
如果tau_p=0:
返回头p
elif tau_m=0:
返回塔乌姆
其他:
打印('错误')
返回“错误”
def型号_功能(p):
r=测试功能(x)
J=测试_雅可比矩阵(r,r.尺寸)
返回0.5*向量_范数(r+J.dot(p),r.size)**2
答案应该是[1.57076525],[1.]] 但这是大约28-30次迭代后的输出:

ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-359-a414711a1671> in <module>
      1 x = create_point(2,1)
----> 2 Trust_Region(x)

<ipython-input-358-7cb77bd44d7b> in Trust_Region(x)
     11         print(x, 'at iteration', i, "norm of r is", vector_norm(r, r.size))
     12         p = dogleg(x, r, J, trust_radius)
---> 13         rho = ratio(x, J, p)
     14 
     15         if rho < 0.25:

<ipython-input-358-7cb77bd44d7b> in ratio(x, J, p)
     71     print (vector_norm(r_p, r_p.size)**2)
     72     print (vector_norm(r + J.dot(p), r.size)**2)
---> 73     rho_k =(vector_norm(r, r.size)**2 - vector_norm(r_p, r_p.size)**2)/(vector_norm(r, r.size)**2 - vector_norm(r + J.dot(p), r.size)**2)
     74     return rho_k
     75 

ZeroDivisionError: float division by zero
ZeroDivisionError回溯(最近一次调用)
在里面
1 x=创建_点(2,1)
---->2信任区(x)
在信任区(x)
11打印(x,'在迭代',i,“r的范数为”,向量_范数(r,r.size))
12 p=狗腿(x,r,J,信赖半径)
--->13ρ=比值(x,J,p)
14
15如果rho<0.25:
比例(x,J,p)
71打印(矢量标准(r\u p,r\u p.大小)**2)
72打印(矢量_范数(r+J点(p),r尺寸)**2)
--->73 rho_k=(向量_范数(r,r.大小)**2-向量_范数(r_p,r.大小)**2)/(向量_范数(r,r.大小)**2-向量_范数(r+J.点(p),r.大小)**2)
74返回rho_k
75
ZeroDivisionError:浮点除以零