Python错误:在给定的容差内找不到根?

huangapple go评论82阅读模式
英文:

Python Error: Could not find root within given tolerance?

问题

我尝试找到方程f的根,该方程是矩阵行列式的结果。通过以下代码生成了这个方程:

from sympy import *
from math import sqrt

# ...(代码省略)...

f = matrix.det()

我尝试了两种方法找到根:

第一种

我使用了mpmath函数,将符号方程转化为数值方程,然后猜测了值。参考值为(-0.17792, -0.74734*I)

import mpmath as mp

f = lambdify(rho, matrix.det())

mp.findroot(f, -0.17-0.75j)

但是我遇到了以下错误:

ValueError: Could not find root within given tolerance. (2.01839854512653723801e-14 > 2.16840434497100886801e-19) Try another starting point or tweak arguments.

第二种

我使用了solve函数:

f = matrix.det()
sol = solve(f, rho)
sol = 
展开收缩
for s in sol: print(s)

但是这次,即使在代码开头使用了较低的迭代次数(N=4),单元格仍然不停地加载,没有生成任何结果或代码。

如何解决这个问题并轻松生成复数根?

英文:

I'm trying to find the roots of an equation f that is the result of the determinant of a matrix. Arriving at this equation was simple, I generated the following code:

from sympy import *
from math import sqrt

def Rec_Coef(n, l, Q, rho, i):
    r1 = (1/2)*(1+sqrt(1-4*Q**2))
    r2 = (1/2)*(1-sqrt(1-4*Q**2))
    
    b = (rho*r1**2)/(r1-r2)
    
    if i == 1:
        q = (1/2)*(3+sqrt(9+16*Q**2*(l-1)*(l+2)))
    if i == 2: 
        q = (1/2)*(3-sqrt(9+16*Q**2*(l-1)*(l+2)))
        
    A = l*(l+1)    
        
    alpha = (n**2 + 2*(b+1)*n + 2*b + 1)*r1
    beta = (-2 + r2)*n**2 + (-2 - 2*b*(2-r2) - 4*rho*r1**2 + 6*r2)*n + (q - 2*(rho**2)*(r1**3) - 4*rho*r1**2*(1+b) - 2*b**2*(2-r1**(-1)) - r1*A - (3-2*b)*r2)
    gamma = (1+r2)*n**2 + (2*rho*r1*(1+2*r2)+2*b*(1+r2)-10*r2)*n + (rho*r1*(2 -12*r2 + (rho+2*b)*(1+2*r2)) -1 -q -2*b*(1+3*r2) + b**2*(16 + 8*r2 - (15 - 38*r2 + 26*r2**2)*r1**(-3)) + (A+13)*r2)
    delta = (-n**2 + 2*(3 - rho -b)*n - (9 + 4*rho*b - 6*b - 6*rho))*r2
    
    return alpha, beta, gamma, delta

N=4

α = []
β = []
γ = []
δ = []

l = 2 
Q = 0.2
i = 2

rho = symbols("𝜌")

for j in range(N):
    alpha, beta, gamma, delta = simplify(Rec_Coef(j, 2, 0.2, rho, 2))
    α.append(alpha)
    β.append(beta)
    γ.append(gamma)
    δ.append(delta)  

array = [[0]*(N+1) for row in range(N)]

array[0][0] = β[0]
array[0][1] = α[0]
array[1][0] = γ[1]
array[1][1] = β[1]
array[1][2] = α[1]

for i in range(2,N):
    array[i][i-1] = γ[i] - (array[i-1][i-1]/array[i-1][i-2])*δ[i]
    array[i][i] = β[i] - (array[i-1][i]/array[i-1][i-2])*δ[i]
    array[i][i+1] = α[i] 
    
matrix_aux = simplify(Matrix(array))

M_aux = [[0]*(N) for row in range(N)] 

for i in range(N):
    for j in range(N):
        M_aux[i][j]=(array[i][j])  

matrix = Matrix(M_aux)

f = matrix.det()

So I tried to find the roots in a few ways:

First

I used the mpmath function, turned my symbolic equation into a numerical equation, and then I guessed at the value. The reference value is (-0.17792, -0.74734*I).

import mpmath as mp

f = lambdify(rho, matrix.det())

mp.findroot(f, -0.17-0.75j)

However, I got the following error:

ValueError: Could not find root within given tolerance. (2.01839854512653723801e-14 > 2.16840434497100886801e-19) Try another starting point or tweak arguments.

Second

I used the solve function

f = matrix.det()
sol = solve(f, rho)
sol = 
展开收缩
for s in sol: print(s)

But this time, even with a low number of iterations used at the beginning of the code (N=4), the cell keeps loading without stopping and does not generate any result or code.

How can I solve this problem and generate the complex roots easily?

答案1

得分: 1

首先,让我说一下,我不知道你试图解决什么问题,因此我将假设你的方程 f 被正确构建。此外,我无法解决你的问题,但希望你能对为什么尝试失败有一些了解。

为了更好地理解这个函数,我在复平面上绘制了它的绝对值,使用了 sympy plot backends 模块

import numpy as np
plot_complex(f, (rho, -2-2j, 2+2j), threed=True, backend=KB,
             tz=lambda t: np.log(t)/10, n=500)

Python错误:在给定的容差内找不到根?

请注意,上述命令在 500*500=250000 个点上评估函数。注意内存消耗!在上图中,底部的每个尖峰都是一个零点。

在以下区域更仔细查看,并大大增加绘图的分辨率(3000*3000=9M 个评估点,不要运行此命令,因为它会消耗超过 15GB 的内存):

plot_complex(f, (rho, -0.1-1j, -0.35-0.75j), threed=True, backend=KB,
             tz=lambda t: np.log(t)/30, n=3000)

Python错误:在给定的容差内找不到根?

看到那些噪音了吗?让我们进一步放大:

Python错误:在给定的容差内找不到根?

在这个区域,似乎你的函数具有“无穷多个零点”和“无穷多个鞍点”。这是一种噩梦般的情况:无论你的初始条件如何,我认为使用任何数值算法都不可能找到零点,更不用说类似 solvesolveset 这样的符号算法。零点之间的距离是如此之小,以至于我看不到算法如何正确解决这种情况…也许 findroot 有一些选项可以指定容差???

顺便说一下,sympy 的 nsolve 是 mpmath 的 findroot 的包装器,因此你可以避免使用 lambdification 步骤!

现在,让我们放大到另一个区域:

plot_complex(log(f), (rho, -0.65-0.95j, -0.6-0.9j), threed=True, backend=KB,
             tz=lambda t: np.log(t)/100, n=3000)

Python错误:在给定的容差内找不到根?

看到那些噪音了吗?让我们再放大一点:

Python错误:在给定的容差内找不到根?

似乎这是一个具有无穷多个零点的区域,因此具有无穷多个鞍点…再次是一场噩梦…

英文:

Let me start by saying that I have no idea what problem you are trying to solve, hence I'm going to assume that your equation f is built correctly.
Also, I'm unable to solve your problem, but hopefully you'll gain some insight about why your attempts failed.

To gain more intuition about the function, I plotted its absolute value in the complex plane using the sympy plot backends module:

import numpy as np
plot_complex(f, (rho, -2-2j, 2+2j), threed=True, backend=KB,
             tz=lambda t: np.log(t)/10, n=500)

Python错误:在给定的容差内找不到根?

Note that the above command evaluates the function over 500*500=250000 points. Watch out for memory consumption! In the above picture, every spike towards the bottom is a zero.

Looking closer in the following region, and increasing a lot the resolution of the plot (3000*3000=9M evaluation points, don't run this command as it consumes over 15GB of memory):

plot_complex(f, (rho, -0.1-1j, -0.35-0.75j), threed=True, backend=KB,
             tz=lambda t: np.log(t)/30, n=3000)

Python错误:在给定的容差内找不到根?

See that noise? Let's zoom in:

Python错误:在给定的容差内找不到根?

In this region, it appears that your functions has "infinitely many zeros" and "infinitely many saddle points". This is a nightmare situation: no matter your initial condition, I believe it's impossible to find a zero with any numerical algorithm, let alone symbolic algorithms like solve or solveset. The distance between zeros is sooo small that I don't see how an algorithm can properly resolve the situation... Maybe findroot has some option to specify the tolerance???

By the way, sympy's nsolve is a wrapper to mpmath's findroot, so you can avoid the lambdification step!

Now, let's zoom into a different region:

plot_complex(log(f), (rho, -0.65-0.95j, -0.6-0.9j), threed=True, backend=KB,
             tz=lambda t: np.log(t)/100, n=3000)

Python错误:在给定的容差内找不到根?

See that noise? Let's zoom in a little bit:

Python错误:在给定的容差内找不到根?

It appears that this is a region with infinitely many zeros, hence infinitely many saddle points... Again, a nightmare...

huangapple
  • 本文由 发表于 2023年4月4日 07:05:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/75924333.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定