我正在使用牛顿方法,所以我想找到六阶多项式的所有六个根的位置,基本上是函数为零的点。
我在下面的代码中找到了我的图表上的粗略值,但是想要输出所有六个根的那些位置。我正在考虑使用x作为数组输入值来查找这些位置但不确定。我现在使用1.0来定位粗略值。这里有什么建议??
def P(x):
return 924*x**6 - 2772*x**5 + 3150*x**4 - 1680*x**3 + 420*x**2 - 42*x + 1
def dPdx(x):
return 5544*x**5 - 13860*x**4 + 12600*x**3 - 5040*x**2 + 840*x - 42
accuracy = 1**-10
x = 1.0
xlast = float("inf")
while np.abs(x - xlast) > accuracy:
xlast = x
x = xlast - P(xlast)/dPdx(xlast)
print(x)
p_points = []
x_points = np.linspace(0, 1, 100)
y_points = np.zeros(len(x_points))
for i in range(len(x_points)):
y_points[i] = P(x_points[i])
p_points.append(P(x_points))
plt.plot(x_points,y_points)
plt.savefig("roots.png")
plt.show()
答案 0 :(得分:1)
传统的方法是利用通货紧缩来分解已经找到的根源。如果你想避免操纵系数数组,那么你必须将根分开。
找到z [1],...,z [k]作为根近似,形成
g(x)=(x-z[1])*(x-z[2])*...*(x-z[k])
并使用h(x)=f(x)/g(x)
将牛顿方法应用于h'(x)=f'/g-fg'/g^2
。在牛顿迭代中,这给出了
xnext = x - f(x)/( f'(x) - f(x)*g'(x)/g(x) )
幸运的是,商g'/g
有一个简单的形式
g'(x)/g(x) = 1/(x-z[1])+1/(x-z[2])+...+1/(x-z[k])
因此,稍微修改牛顿步骤就可以避免再次找到相同的根。
这一切仍然保持迭代真实。要获得复数根,请使用复数来开始迭代。
概念证明,将eps=1e-8j
添加到g'(x)/g(x)
允许迭代变得复杂而不会阻止实际值。解决等效问题0=exp(-eps*x)*f(x)/g(x)
import numpy as np
import matplotlib.pyplot as plt
def P(x):
return 924*x**6 - 2772*x**5 + 3150*x**4 - 1680*x**3 + 420*x**2 - 42*x + 1
def dPdx(x):
return 5544*x**5 - 13860*x**4 + 12600*x**3 - 5040*x**2 + 840*x - 42
accuracy = 1e-10
roots = []
for k in range(6):
x = 1.0
xlast = float("inf")
x_points = np.linspace(0.0, 1.0, 200)
y_points = P(x_points)
for rt in roots:
y_points /= (x_points - rt)
y_points = np.array([ max(-1.0,min(1.0,np.real(y))) for y in y_points ])
plt.plot(x_points,y_points,x_points,0*y_points)
plt.show()
while np.abs(x - xlast) > accuracy:
xlast = x
corr = 1e-8j
for rt in roots:
corr += 1/(xlast-rt)
Px = P(xlast)
dPx = dPdx(xlast)
x = xlast - Px/(dPx - Px*corr)
print(x)
roots.append(x)