• 検索結果がありません。

対角化とその応用

ドキュメント内 if if-else if-elif-else (ページ 127-131)

と行列を定義してその固有値を計算させたとしても,実行結果は

実行結果の例 [ 1 1/2 1/3 1/4 1/5]

[1/2 1/3 1/4 1/5 1/6]

[1/3 1/4 1/5 1/6 1/7]

[1/4 1/5 1/6 1/7 1/8]

[1/5 1/6 1/7 1/8 1/9]

Traceback (click to the left of this block for traceback) ...

ArithmeticError: could not determine eigenvalues exactly using symbolic matrices; try using a different type of matrix via self.change_ring(), if possible

となって,固有値を具体的に決定できなかったことが分かります*17。この行列の固有値は5次方程式であ り,一般解を具体的に表すことはできません。しかし,数値的には固有値を求めることはできます*18

そこで,例えば上で作った2×2行列の係数体をCDFにして計算します:

1 mat = m a t r i x ( CDF , mat ) # b a s e _ r i n gC D Fに 変 更 2 p r i n t mat . e i g e n v a l u e s ()

実行結果の例 [-0.372281323269, 5.37228132327]

固有値の数値のリストが表示されました。はじめから数値結果だけ得られればよい場合にはSRを使わずに RDFやCDFを使いましょう。そのほうがSRで固有値を計算するよりもずっと高速に計算できます。

固有ベクトルは行列に対するメソッドeigenvectors_right()で求めます。

1 m a t 2 = m a t r i x ( SR , 2 ,2 ,[1 ,2 ,3 ,4]) # b a s e _ r i n gS Rに 設 定 2 e i g v = m a t 2 . e i g e n v e c t o r s _ r i g h t () # 固 有 ベ ク ト ル の 組 を 定 義 3 p r i n t ei g v

実行結果の例 [(-1/2*sqrt(33) + 5/2, [(1, -1/4*sqrt(33) + 3/4)], 1), (1/2*sqrt(33) +

5/2, [(1, 1/4*sqrt(33) + 3/4)], 1)]

これは,次を意味しています:

[ (第1固有値,[対応する固有ベクトル],多重度), (第2固有値,[対応する固有ベクトル],多重度) ] なので,少し面倒ですが,固有ベクトルを取り出すには,上のプログラムに続けて次のようにします。

1 p r i n t ei g v [ 0 ] [ 1 ] [ 0 ] # 一 つ 目 の 固 有 ベ ク ト ル 2 p r i n t ei g v [ 1 ] [ 1 ] [ 0 ] # 二 つ 目 の 固 有 ベ ク ト ル

実行結果の例 (1, -1/4*sqrt(33) + 3/4)

(1, 1/4*sqrt(33) + 3/4)

49.7 対角化とその応用

49.7.1 行列の対角化

行列の対角化は,行列の冪や指数関数を計算するために必要な手順の一つです。行列Aを対角化するとは,

ある正則行列Pを見つけて

P1AP = diag[λ1,· · ·, λn] : 対角行列

を計算することです。通常,対角化行列Pを作るためには,Aの固有ベクトルを計算すればよいのですが,

Sageでは,eigenmatrix_right()で対角化を簡単に行うことができます。

*175×5行列であるところを4×4行列にすると厳密な固有値が得られます。

*18もちろん結果は誤差を含む近似値になりますが。

行列 (1 4

2 3 )

を対角化してみましょう。

1 A = m a t r i x ( SR , [[1 ,4] ,[2 ,3]] ) # 行 列 の 定 義

2 A . e i g e n m a t r i x _ r i g h t () # 固 有 値 と 対 角 化 行 列 を 求 め る

実行結果の例 (

[ 5 0] [ 1 1]

[ 0 -1], [ 1 -1/2]

)

これはAの固有値が5,1で

P1AP = (5 0

0 1 )

, P =

(1 1 1 1/2

)

となることを意味しています。実際 (1 1

1 1/2 )1(

1 4 2 3

) (1 1 1 1/2

)

=

(1/3 2/3 2/3 2/3

) (1 4 2 3

) (1 1 1 1/2

)

= (5 0

0 1 )

となり,ちゃんと対角化されているのが分かります。

49.7.2 行列の指数関数と線形微分方程式

行列Aに対して,その指数関数exp(tA)を exp(tA) =

n=0

tn

n!An, t∈C (29)

によって定義します。Sageで行列の指数関数を計算することができますが,以下ではこれを応用して微分方 程式を解きます。

最も簡単な例に対して,具体的な計算を行ってみましょう。ばねにつながれた質量mからなる1次元の力 学系を考えます。ばねのつり合いの位置を原点としましょう。このとき運動方程式から

md2x(t)

dt2 =−kx(t)

が成り立ちます。ここでkはバネ定数です。粒子は時刻0に位置X にいて,速度V であるとします。こ こでの目標は時刻t での位置x(t)を求めることです。この微分方程式は定数変化法などにより解くこと ができますが,いまは行列を用いて解いてみます。まず方程式を線形化します。√

k/m = wと置きます。

v(t) =dx(t)/dtとすると上の微分方程式は d

dt (x(t)

v(t) )

=

( v(t)

−w2x(t) )

=

( 0 1

−w2 0 ) (x(t)

v(t) )

と同値です。つまり

A=

( 0 1

−w2 0 )

と置けば,

d dt

(x(t) v(t) )

=A (x(t)

v(t) )

です,これはベクトル(x(t), v(t))tを一回微分するごとに行列Aが前に出てくることを意味しているので,

(x(0), v(0)) = (X, V)を思い出すと

(x(t) v(t) )

= exp(tA) (X

V )

49.7 対角化とその応用 49 行列計算

となります。微分方程式を解く問題は行列の指数関数exp(tA)を求める問題に置き換わりました。Sageで行 列T の指数関数exp(T)を求める命令がT.exp()です。具体的にSageに行列を計算させて微分方程式を解 いてみましょう:

1 var (’ t w ’) # t wを 変 数 と す る

2 A = m a t r i x ([[0 ,1] ,[ - w ^2 ,0]]) # 行 列 Aを 定 義 す る

3 B = t * A # Bt Aと す る

4 e x p o = B . exp () # e x p oe x p ( B )と す る

これで,B= exp(tA)が求まりました。つぎに

1 var (" X V ") # X , Vを 変 数 と す る

2 y = v e c t o r ([ X , V ]) # y を ベ ク ト ル( X , V )と す る

3 sol = e x p o * y # solexp ( tA )( X , V )に 作 用 さ せ た も の と す る

とします。最後得られた量sol[0]は(x(t), v(t))なのでその最初の成分(第0成分)が時刻tの位置を与え ます。つまり微分方程式の解x(t)はsol[0]です。得られる関数は実なので実部を取って(これは何の変化 ももたらしません)full_simplifyを用いて整理します。上のプログラムに続けて

1 p r i n t r e a l _ p a r t ( sol [ 0 ] ) . f u l l _ s i m p l i f y () と入力すると最終的な答え

1 ( X * w * cos ( t * w ) + V * sin ( t * w ))/ w

が得られます。これが微分方程式の解x(t)です。通常の数学の記法で書けば,微分方程式の解は x(t) =Xcos(wt) + V

W sin(wt), x(0) =X, x(0) =V

となるという事を意味しています。

49.7.3 行列の対角化とその応用:フィボナッチ数列の一般項

フィボナッチ数列a1= 1, a2= 1,

an+2=an+1+an, n= 1,2,3,· · · (30) を考えます。まず,上の関係式は

(an+2 an+1 )

= (1 1

1 0

) (an+1 an

)

となる事に注意します。右辺の行列をAとします。すると (an+1

an

)

=A ( an

an1

)

=A2 (an1

an2

)

=· · ·=An1 (a2

a1

)

=An1 (1

1 )

(31) なのでAnが具体的に計算できれば,数列の一般項anが求まる事になります。Anを求めるために,Aを対 角化してみましょう。

1 A = m a t r i x ( SR , [ [1 ,1] ,[1 ,0] ]) 2 sol = A . e i g e n m a t r i x _ r i g h t () 3 P = sol [1]

4 D = P ^( -1)* A * P

5 p r i n t ’ P = ’, P , ’ ’ 6 p r i n t ’ D = P ^( -1) AP = ’ 7 p r i n t D . e x p a n d ()

実行結果の例 P =

[ 1 1]

[-1/2*sqrt(5) - 1/2 1/2*sqrt(5) - 1/2]

D = P^(-1)AP =

[-1/2*sqrt(5) + 1/2 0]

[ 0 1/2*sqrt(5) + 1/2]

ここでDを単純化するためにexpand()を行いました。この事からAを対角化する行列は P =

( 1 1

(

5 + 1)/2 (

51)/2 )

であり,P1AP = diag[(−√

5 + 1)/2,(

5 + 1)/2]となることが分かります。この式の両辺をn乗すると

(

(1+25)n 0 0 (5+12 )n

)

=P1AnP となります。したがってAn

An=P (

(1+25)n 0 0 (5+12 )n

)

P1 (32)

と計算する事ができます。これをつかってAn1を計算させてみましょう:

1 var (’ n ’)

2 Dn = m a t r i x ([ [ D [ 0 ] [ 0 ] ^ ( n -1) , 0] , [0 , D [ 1 ] [ 1 ] ^ ( n - 1 ) ] ] ) # Dn -1乗 を 作 る

3 An = P * Dn * P ^( -1) # こ れ がAn -1

4 p r i n t e x p a n d ( An ) # A nを 少 し 単 純 化 し て プ リ ン ト

実行結果の例 [ 1/5*sqrt(5)*(1/2*sqrt(5) + 1/2)^n/(sqrt(5) + 1) +

1/5*sqrt(5)*(-1/2*sqrt(5) + 1/2)^n/(sqrt(5) - 1) + (1/2*sqrt(5) + 1/2)^n/(sqrt(5) + 1) - (-1/2*sqrt(5) + 1/2)^n/(sqrt(5) - 1) 2/5*sqrt(5)*(1/2*sqrt(5) + 1/2)^n/(sqrt(5) + 1) +

2/5*sqrt(5)*(-1/2*sqrt(5) + 1/2)^n/(sqrt(5) - 1)]

[

2/5*sqrt(5)*(1/2*sqrt(5) + 1/2)^n/(sqrt(5) + 1) + 2/5*sqrt(5)*(-1/2*sqrt(5) + 1/2)^n/(sqrt(5) - 1) 1/5*sqrt(5)*(1/2*sqrt(5) + 1/2)^n/(sqrt(5) + 1)

-1/5*sqrt(5)*(-1/2*sqrt(5) + 1/2)^n/(sqrt(5) - 1) + (1/2*sqrt(5) + 1/2)^n/(sqrt(5) + 1) - (-1/2*sqrt(5) + 1/2)^n/(sqrt(5) - 1)]

Dn1, An1をDn, Anと定義しました。複雑ですが正しく計算できています。上の行列にベクトル

(1 1 )

(33) を掛けて得られるベクトルの第2成分が一般項anとなります。上のプログラムに続けて次を実行します。

1 a s s u m e ( n ,’ i n t e g e r ’) # nを 整 数 と 仮 定 す る

2 v = v e c t o r ([1 ,1]) # ベ ク ト ル( 1 , 1 )vと 定 義

3 aa = An * v # A ^ nvに 掛 け る と

4 aa [ 1 ] . s i m p l i f y _ f u l l () # そ の 第2成 分 が 一 般 項 と な る

実行結果の例 -1/5*((sqrt(5) - 1)^n*(-1)^n - (sqrt(5) + 1)^n)*sqrt(5)/2^n

最後の結果が,フィボナッチ数列の一般項anとなります。これを整理すれば,

an = (

512n(1)n(√

51)n

(√

5 + 5)n)

512n12

2n = 1

5

{(1 + 5 2

)n

(1−√ 5 2

)n} となります。

実際,最後の出力の結果をn=1,2,...に対して表示させると

ドキュメント内 if if-else if-elif-else (ページ 127-131)