简体   繁体   English

拉盖尔获得多根的方法(Matlab)

[英]Laguerre's method to obtain poly roots (Matlab)

I must write using Laguerre's method a piece of code to find the real and complex roots of poly:我必须使用 Laguerre 的方法编写一段代码来找到 poly 的实数和复数根:

P=X^5-5*X^4-6*X^3+6*X^2-3*X+1 P=X^5-5*X^4-6*X^3+6*X^2-3*X+1

I have little doubt.我几乎没有怀疑。 I did the algorithm in the matlab, but 3 out of 5 roots are the same and I don't think that is correct.我在 matlab 中做了算法,但是 5 个根中有 3 个是相同的,我认为这是不正确的。

syms X                     %Declearing x as a variabl
P=X^5-5*X^4-6*X^3+6*X^2-3*X+1;    %Equation we interest to solve
n=5;                        % The eq. order
Pd1 = diff(P,X,1);          % first differitial of f
Pd2 = diff(P,X,2);          %second differitial of f
err=0.00001;                  %Answear tollerance

N=100;                      %Max. # of Iterations
x(1)=1e-3;                  % Initial Value
for k=1:N
    G=double(vpa(subs(Pd1,X,x(k))/subs(P,X,x(k))));
    H=G^2 - double(subs(Pd2,X,x(k))) /subs(P,X,x(k));
    D1= (G+sqrt((n-1)*(n*H-G^2)));
    D2= (G-sqrt((n-1)*(n*H-G^2)));
    D = max(D1,D2);
    a=n/D;
    x(k+1)=x(k)-a   
    Err(k) = abs(x(k+1)-x(k));
    if Err(k) <=err
        break
    end
end

output (roots of polynomial):输出(多项式的根):

x = x =

0.0010 + 0.0000i 0.1434 + 0.4661i 0.1474 + 0.4345i 0.1474 + 0.4345i 0.1474 + 0.4345i 0.0010 + 0.0000i 0.1434 + 0.4661i 0.1474 + 0.4345i 0.1474 + 0.4345i 0.1474 + 0.4345i

What you actually see are all the values x(k) which arose in the loop.您实际看到的是循环中出现的所有值x(k) The last one, 0.1474 + 0.4345i is the end result of this loop - the approximation of the root which is in your given tolerance threshold.最后一个0.1474 + 0.4345i是这个循环的最终结果 - 根的近似值,它在给定的容差阈值中。 The code编码

syms X                                                  %Declaring x as a variable
P = X^5 - 5 * X^4 - 6 * X^3 + 6 * X^2 - 3 * X + 1;      %Polynomial
n=5;                                                    %Degree of the polynomial
Pd1 = diff(P,X,1);                                      %First derivative of P
Pd2 = diff(P,X,2);                                      %Second derivative of P
err = 0.00001;                                          %Answer tolerance

N = 100;                                                  %Maximal number of iterations
x(1) = 0;                                               %Initial value
for k = 1:N
    G = double(vpa(subs(Pd1,X,x(k)) / subs(P,X,x(k))));
    H = G^2 - double(subs(Pd2,X,x(k))) / subs(P,X,x(k));
    D1 = (G + sqrt((n-1) * (n * H-G^2)));
    D2 = (G - sqrt((n-1) * (n * H-G^2)));
    D = max(D1,D2);
    a = n/D;
    x(k+1) = x(k) - a;   
    Err(k) = abs(x(k+1)-x(k));
    if Err(k) <=err
        fprintf('Initial value %f, result %f%+fi', x(1), real(x(k)), imag(x(k)))
        break
    end
end

results in结果是

Initial value -2.000000, result -1.649100+0.000000i

If you want to get other roots, you have to use other initial values.如果你想得到其他的根,你必须使用其他的初始值。 For example one can obtain例如可以得到

Initial value 10.000000, result 5.862900+0.000000i
Initial value -2.000000, result -1.649100+0.000000i
Initial value 3.000000, result 0.491300+0.000000i
Initial value 0.000000, result 0.147400+0.434500i
Initial value 1.000000, result 0.147400-0.434500i

These are all zeros of the polynomial.这些都是多项式的零。

A method for calculating the next root when you have found another one would be that you divide through the corresponding linear factor and use your loop for the resulting new polynomial.当您找到另一个根时,计算下一个根的一种方法是除以相应的线性因子,然后将循环用于生成的新多项式。 Note that this is in general not very easy to handle since rounding errors can have a big influence on the result.请注意,这通常不太容易处理,因为舍入误差会对结果产生很大影响。

Problems with the existing code现有代码的问题

You do not implement the Laguerre method properly as a method in complex numbers.您没有将 Laguerre 方法正确实现为复数中的方法。 The denominator candidates D1,D2 are in general complex numbers, it is inadvisable to use the simple max which only has sensible results for real inputs.分母候选D1,D2通常是复数,不建议使用简单的max ,它只对实际输入有合理的结果。 The aim is to have a=n/D be the smaller of both variants, so that one has to look for the D in [D1,D2] with the larger absolute value.目的是使a=n/D成为两个变体中较小的一个,以便必须D in [D1,D2]寻找具有较大绝对值的D in [D1,D2] If there were a conditional assignment as in C, this would look like如果像在 C 中那样有条件赋值,这看起来像

D = (abs(D_1)>abs(D2)) ? D1 : D2;

As that does not exist, one has to use commands with a similar result由于不存在,因此必须使用具有类似结果的命令

D = D1; if (abs(D_1)<abs(D2)) D=D2; end

The resulting sequence of approximation points is逼近点的结果序列是

x(0) = 0.0010000
x(1) = 0.143349512707684+0.466072958423667i
x(2) = 0.164462212064089+0.461399841949893i
x(3) = 0.164466373475316+0.461405404094130i

There is a point where one can not expect the (residual) polynomial value at the root approximation to substantially decrease.在某一点上,人们不能期望根近似处的(残差)多项式值会大幅减少。 The value close to zero is obtained by adding and subtracting rather large terms in the sum expression of the polynomial.接近于零的值是通过在多项式的和表达式中加减相当大的项而获得的。 The accuracy lost in these catastrophic cancellation events can not be recovered.在这些灾难性取消事件中损失的准确性无法恢复。

The threshold for polynomial values that are effectively zero can be estimated as the machine constant of the double type times the polynomial value where all coefficients and the evaluation point are replaced by their absolute values.有效为零的多项式值的阈值可以估计为double类型的机器常数乘以多项式值,其中所有系数和评估点都由它们的绝对值代替。 This test serves in the code primarily to avoid divisions by zero or near-zero.此测试在代码中主要用于避免被零或接近零的除法。

Finding all roots找到所有的根

One approach is to apply the method to a sufficiently large number of initial points along some circle containing all the roots, with some strict rules for early termination at too slow convergence.一种方法是将该方法应用于沿包含所有根的某个圆的足够多的初始点,对在收敛速度过慢时提前终止有一些严格的规则。 One would have to make the list of the roots found unique, but keep the multiplicity,...人们必须使找到的根列表唯一,但要保持多样性,...

The other standard method is to apply deflation, that is, divide out the linear factor of the root found.另一种标准方法是应用紧缩,即除掉找到的根的线性因子。 This works well in low degrees.这在低度数下效果很好。

There is no need for the slower symbolic operations as there are functions that work directly on the coefficient array, such as polyval and polyder .不需要较慢的符号运算,因为有直接作用于系数数组的函数,例如polyvalpolyder Deflation by division with remainder can be achieved using the deconv function.使用deconv函数可以通过除法和余数来实现deconv

For real polynomials, we know that the complex conjugate of a root is also a root.对于实数多项式,我们知道根的复共轭也是根。 Thus initialize the next iteration with the deflated polynomial with it.因此用它的压缩多项式初始化下一次迭代。

Other points:其他要点:

  • There is no point in the double conversions as at no point there is a conversion into the single type. double转换没有意义,因为在任何时候都没有转换为single类型。
  • If you don't do anything with it, it makes no sense to create an array, especially not for Err .如果您不对它做任何事情,那么创建数组是没有意义的,尤其是对于Err

Roots of the example例子的根源

Implementing all this I get a log of实现这一切,我得到了一个日志

x(0) = 0.001000000000000+0.000000000000000i,  |Pn(x(0))| =  0.99701
x(1) = 0.143349512707684+0.466072958423667i, |dx|= 0.48733
x(2) = 0.164462212064089+0.461399841949893i, |dx|=0.021624
x(3) = 0.164466373475316+0.461405404094130i, |dx|=6.9466e-06
root found x=0.164466373475316+0.461405404094130i with value P0(x)=-2.22045e-16+9.4369e-16i
Deflation
x(0) = 0.164466373475316-0.461405404094130i,  |Pn(x(0))| = 2.1211e-15
root found x=0.164466373475316-0.461405404094130i with value P0(x)=-2.22045e-16-9.4369e-16i
Deflation
x(0) = 0.164466373475316+0.461405404094130i,  |Pn(x(0))| =   4.7452
x(1) = 0.586360702193454+0.016571894375927i, |dx|= 0.61308
x(2) = 0.562204173408499+0.000003168181059i, |dx|=0.029293
x(3) = 0.562204925474889+0.000000000000000i, |dx|=3.2562e-06
root found x=0.562204925474889+0.000000000000000i with value P0(x)=2.22045e-16-1.33554e-17i
Deflation
x(0) = 0.562204925474889-0.000000000000000i,  |Pn(x(0))| =   7.7204
x(1) = 3.332994579372812-0.000000000000000i, |dx|=  2.7708
root found x=3.332994579372812-0.000000000000000i with value P0(x)=6.39488e-14-3.52284e-15i
Deflation
x(0) = 3.332994579372812+0.000000000000000i,  |Pn(x(0))| =   5.5571
x(1) = -2.224132251798332+0.000000000000000i, |dx|=  5.5571
root found x=-2.224132251798332+0.000000000000000i with value P0(x)=-3.33067e-14+1.6178e-15i

for the modified code对于修改后的代码

P = [1, -2, -6, 6, -3, 1];
P0 = P;

deg=length(P)-1;           % The eq. degree
err=1e-05;                 %Answer tolerance

N=10;                      %Max. # of Iterations
x=1e-3;                    % Initial Value
for n=deg:-1:1
  dP = polyder(P);          % first derivative of P
  d2P = polyder(dP);        %second derivative of P
  fprintf("x(0) = %.15f%+.15fi,  |Pn(x(0))| = %8.5g\n",  real(x),imag(x), abs(polyval(P,x)));
  for k=1:N
    Px = polyval(P,x);
    dPx = polyval(dP,x);
    d2Px = polyval(d2P,x);
    if abs(Px) < 1e-14*polyval(abs(P),abs(x)) 
      break    % if value is zero in relative accuracy
    end
    G = dPx/Px;
    H=G^2 - d2Px / Px;
    D1= (G+sqrt((n-1)*(n*H-G^2)));
    D2= (G-sqrt((n-1)*(n*H-G^2)));
    D = D1;
    if abs(D2)>abs(D1) D=D2; end    % select the larger denominator
    a=n/D;
    x=x-a;
    fprintf("x(%d) = %.15f%+.15fi, |dx|=%8.5g\n",k,real(x),imag(x), abs(a));
    if abs(a) < err*(err+abs(x))
        break
    end
  end
  y = polyval(P0,x);   % check polynomial value of the original polynomial
  fprintf("root found x=%.15f%+.15fi with value P0(x)=%.6g%+.6gi\n", real(x),imag(x),real(y),imag(y));
  disp("Deflation");
  [ P,R ] = deconv(P,[1,-x]);  % division with remainder
  x = conj(x);  % shortcut for conjugate pairs and clustered roots
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM