FindRootAll.mw

fsolve

次のような二次方程式
x*x-4.0*x+1=0

の根を求める.先ず,関数の概形を表示してみる.

> plot(x*x-4.0*x+1,x=-1..5);

[Plot]

Mapleで根を求めるには,solveを用いる.

> (xp,xm):=solve(x^2-4*x+1=0);

xp, xm := 2+3^(1/2), 2-3^(1/2)

> evalf(xm);

.267949192

> fsolve(x*x-4.0*x+1=0);

.2679491924, 3.732050808

ニュートン法の視覚化

> with(Student[Calculus1]):
NewtonsMethodTutor(x^2-4*x+1, x=-1..2);

Schematic illustrations for bisection method

> restart:
with(plots):

with(plottools):

Warning, the name changecoords has been redefined

Warning, the name arrow has been redefined

> f1:=x->x^2-4*x+1;

f1 := proc (x) options operator, arrow; x^2-4*x+1 end proc

> p1:=plot(f1(x),x=0..2):

> c0:=pointplot([0,1],symbolsize=20,symbol=circle):
c1:=pointplot([2,f1(2)],symbolsize=20,symbol=circle):

c2:=pointplot([1,0],symbolsize=20,symbol=circle):

c3:=pointplot([1,f1(1)],symbolsize=20,symbol=circle):

c4:=pointplot([0.5,0],symbolsize=20,symbol=circle):

c5:=pointplot([0.5,f1(0.5)],symbolsize=20,symbol=circle):

l0:=arrow([0,f1(0)],[0,0],.05,.1,.2,color=green):

l1:=arrow([2,f1(2)],[2,0],.05,.1,.2,color=green):

l2:=arrow([1,0],[1,f1(1)],.05,.1,.2,color=green):

l3:=arrow([0.5,0],[0.5,f1(0.5)],.05,.1,.2,color=green):

> d1:=display(p1):
d2:=display(p1,c0,c1):

d3:=display(l0,l1,p1,c0,c1,c2):

d4:=display(l0,l1,p1,c0,c1,c2,c3,l2):

d5:=display(l0,p1,c0,c2,c3,l2,c4,c5,l3):

> display([d1,d2,d3,d4,d5],insequence=true,view=[-0.2..2.2,-3.2..1.2]);

[Plot]

> display([d1,d2,d3,d4,d5],view=[-0.2..2.2,-3.2..1.2]);

[Plot]

Schematic illustrations for Newton-Raphson method

> restart:
with(plots):

with(plottools):

Warning, the name changecoords has been redefined

Warning, the name arrow has been redefined

> f1:=x->x^2-4*x+1;
df1:=(x,x0)->(2*x0-4)*(x-x0)+f1(x0);

f1 := proc (x) options operator, arrow; x^2-4*x+1 end proc

df1 := proc (x, x0) options operator, arrow; (2*x0-4)*(x-x0)+f1(x0) end proc

> df1(x,0);

-4*x+1

> p1:=plot({f1(x)},x=-0.5..2):
p2:=plot({df1(x,1),f1(x)},x=-0.5..2):

p3:=plot({df1(x,0),f1(x)},x=-0.5..2):

> c0:=pointplot([1,f1(1)],symbolsize=20,symbol=circle):
a1:=arrow([0,0],[0,f1(0)],.05,.1,.2,color=green):

c1:=pointplot([0,f1(0)],symbolsize=20,symbol=circle):

a2:=arrow([0.25,0],[0.25,f1(0.25)],.02,.04,.01,color=green):

c2:=pointplot([0.25,f1(0.25)],symbolsize=20,symbol=circle):

d1:=display(p1):

d2:=display(p1,c0):

d3:=display(p2,c0):

d35:=display(p2,c0,a1):

d4:=display(p2,c1):

d5:=display(p3,a2):

d6:=display(p3,a2,c2):

> display([d1,d2,d3,d35,d4,d5,d6],insequence=true,view=[-0.1..1.1,-2.1..1.1]);

[Plot]

> display([d1,d2,d3,d35,d4,d5,d6],view=[-0.1..1.1,-2.1..1.1]);

[Plot]

>

Derivation of eq.(3.11) on p.19

解の収束の速さ

> restart;
#for bisection method

e[n+1]=e[n]/2;

e[n+1] = 1/2*e[n]

> s1:=series(f(xp-e),e,2);

s1 := series(f(xp)-D(f)(xp)*e+O(e^2),e,2)

> ee:=solve(convert(s1,polynom)=0,e);

ee := f(xp)/D(f)(xp)

> xpp:=xp-ee;

xpp := xp-f(xp)/D(f)(xp)

> f:=x->a*(x-x0)*(x-x1);

f := proc (x) options operator, arrow; a*(x-x0)*(x-x1) end proc

> xpp:=xp-f(xp)/subs(x=xp,diff(f(x),x));

xpp := xp-a*(xp-x0)*(xp-x1)/(a*(xp-x1)+a*(xp-x0))

> xpp2:=subs({xp-x1=dx1,xp-x0=dx0},xpp);

xpp2 := xp-a*dx0*dx1/(a*dx1+a*dx0)

> simplify(subs(dx1=dx0/alpha,xpp2-xp));

-dx0/(1+alpha)

> series(%,alpha,3);

series(-dx0+dx0*alpha-dx0*alpha^2+O(alpha^3),alpha,3)

> subs({dx0=xp-x0,dx1=xp-x1},subs(alpha=dx0/dx1,series(simplify(subs(dx1=dx0/alpha,xpp2)),alpha,3)));

x0+(xp-x0)^2/(xp-x1)-(xp-x0)^3/(xp-x1)^2+O((xp-x0)^3/(xp-x1)^3)

Bairstow-Hitchcock method

Simplest explanation

> restart;

> P:=sort(sum('x^i*a[i]','i'=0..n),x);

P := sum(x^i*a[i], i = (0 .. n))

> n:=3;
a:=array(0..n+1,[-40,62,-23,1]):

sort(P,x);

n := 3

x^3-23*x^2+62*x-40

> factor(P);

(x-20)*(x-1)*(x-2)

> plot(P,x=-10..30);
plot(P,x=-1..21,y=-10..10);

[Plot]

[Plot]

> fsolve(P=0,x);

1.000000000, 2.000000000, 20.

Analytical solution

Bairstow-Hitchcock法の基本的な考え方の導出.

> restart:
n:=3;

n := 3

> P1:=sort(sum(x^i*a[i],i=0..n),x);

P1 := a[3]*x^3+a[2]*x^2+a[1]*x+a[0]

> Q:=sum(x^i*b[i],i=0..n-2);

Q := b[0]+x*b[1]

> P2:=sort(expand((x^2+B*x+C)*Q+R*x+S),x);

P2 := x^3+a[2]*x^2+B*a[2]*x-B^2*x+C*x+R*x+C*a[2]-C*B+S

二つの式f1とf2を等値して,係数が満たすべき方程式を導出.

> for i from 0 to n do
eq||i:=coeff(P1,x,i)=coeff(P2,x,i);

end do;

eq0 := a[0] = C*a[2]-C*B+S

eq1 := a[1] = B*a[2]-B^2+C+R

eq2 := a[2] = a[2]

eq3 := a[3] = 1

係数の下の方のbの満たすべき式を導出.

> b[n-2]:=1;
for i from n-3 to 0 by -1 do

b[i]:=solve(eq||(i+2),b[i]);

end do;

b[1] := 1

b[0] := a[2]-B

r,sが0となる方程式をたてる.

> Eq_R:=solve(expand(eq1),R)=0;
Eq_S:=solve(expand(eq0),S)=0;

Eq_R := a[1]-B*a[2]+B^2-C = 0

Eq_S := a[0]-C*a[2]+C*B = 0

> a:=array(0..n,[-40,62,-23,1]);

a := ARRAY([0 .. 3], [(0) = -40, (1) = 62, (2) = -23, (3) = 1])

上のような係数を与えて,p,qを求める.

> fsolve({Eq_R,Eq_S},{B,C});

{B = -3.000000000, C = 2.000000000}

Numerical solution

数値解を求めるコード

初期値の代入.係数の添え字が逆になっている事に注意.

> restart;
n:=3;

a:=array(0..n+2,[0,1,-23,62,-40]):

b:=array(0..n+2,[0,1,0,0,0,0]):

d:=array(0..n+2,[0,1,0,0,0,0]):

n := 3

> B:=1.0;
C:=1.0;

B := 1.0

C := 1.0

以下の二つのコマンド領域を収束するまで繰り返す.

> for i from 2 to n+2 do
j:=i-1;

k:=i-2;

     b[i]:=a[i]-B*b[j]-C*b[k];

     d[i]:=b[i]-B*d[j]-C*d[k];

od:

> j:=n-1;
k:=n-2;

det1:=d[j]*d[j]-(d[n]-b[n])*d[k];

dB:=(b[n]*d[j]-b[n+1]*d[k])/det1;

dC:=(b[n+1]*d[j]-(d[n]-b[n])*b[n])/det1;

B:=B+dB;

C:=C+dC;

j := 2

k := 1

det1 := 342.0000000

dB := -0.

dC := 0.

B := -3.000000000

C := 2.000000000

> print(convert(b,list));

[0, 1, -20.00000000, 0., 0., a[5]]

Note for Numerical solution

det1, dB, とdCはテキスト(3.41)式の逆行列から出てきた式.

> with(LinearAlgebra):

> A:=Matrix(1..2,1..2,[[a11,a12],[a21,a22]]);

A := Matrix([[a11, a12], [a21, a22]])

> MatrixInverse(A);

Matrix([[a22/(a11*a22-a12*a21), -a12/(a11*a22-a12*a21)], [-a21/(a11*a22-a12*a21), a11/(a11*a22-a12*a21)]])

ちょっと込み入った例をMapleで扱うと...

> restart:
n:=4;

P:=sort(sum('x^i*a[i]','i'=0..n),x);

a:=array(0..n+1,[-41,62,-23,1,1]):

sort(f1,x);

n := 4

P := a[4]*x^4+a[3]*x^3+a[2]*x^2+a[1]*x+a[0]

f1

> fsolve(P=0,x,complex);

-6.335834399, 1.000000000, 2.167917199-1.330888330*I, 2.167917199+1.330888330*I

> x1,x2:=fsolve(P=0,x);

x1, x2 := -6.335834399, 1.000000000

> Q:=x^2-(x1+x2)*x+x1*x2;

Q := x^2+5.335834399*x-6.335834399

> R:=factor(P/Q);

R := x^2-4.335834398*x+6.471128729

> expand(R*Q);

x^4+1.000000001*x^3-23.00000000*x^2-41.00000000+62.00000000*x