行列の固有値


11

正方行列が与えられた場合、行列の固有値を出力します。各固有値は、その代数多重度に等しい回数だけ繰り返される必要があります。

行列の固有値は、いくつかの列ベクトルに対して、などのAスカラー値です。これらは、次の特性多項式の解でもあります(は、と同じ次元の単位行列です)。λvA*v = λ*vAdet(A - λ*I) = 0IA

出力は、有効数字3桁まで正確でなければなりません。すべての入力と出力は、選択した言語の表現可能な数値範囲内にあります。

組み込みは許容されますが、組み込みを使用しないソリューションを含めることをお勧めします。

テストケース

これらのテストケースでIは、虚数単位を表します。複素数はの形式で記述されa + b*Iます。すべての出力の有効桁数は3桁です。

[[42.0]] -> [42.0]
[[1.0, 0.0], [0.0, 1.0]] -> [1.00, 1.00]
[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]] -> [16.1, -1.12, -1.24e-15]
[[1.2, 3.4, 5.6, 7.8], [6.3, 0.9, -5.4, -2.3], [-12.0, -9.7, 7.3, 5.9], [-2.5, 7.9, 5.3, 4.4]] -> [7.20 + 5.54*I, 7.20 - 5.54*I, -4.35, 3.75]
[[-3.22 - 9.07*I, 0.193 + 9.11*I, 5.59 + 1.33*I, -3.0 - 6.51*I, -3.73 - 6.42*I], [8.49 - 3.46*I, -1.12 + 6.39*I, -8.25 - 0.455*I, 9.37 - 6.43*I, -6.82 + 8.34*I], [-5.26 + 8.07*I, -6.68 + 3.72*I, -3.21 - 5.63*I, 9.31 + 3.86*I, 4.11 - 8.82*I], [-1.24 + 9.04*I, 8.87 - 0.0352*I, 8.35 + 4.5*I, -9.62 - 2.21*I, 1.76 - 5.72*I], [7.0 - 4.79*I, 9.3 - 2.31*I, -2.41 - 7.3*I, -7.77 - 6.85*I, -9.32 + 2.71*I]] -> [5.18 + 16.7*I, -24.9 - 2.01*I, -5.59 - 13.8*I, 0.0438 - 10.6*I, -1.26 + 1.82*I]
[[-30.6 - 73.3*I, 1.03 - 15.6*I, -83.4 + 72.5*I, 24.1 + 69.6*I, 52.3 + 2.68*I, 23.8 + 98.0*I, 96.8 + 49.7*I, -26.2 - 5.87*I, -52.4 + 98.2*I, 78.1 + 6.69*I], [-59.7 - 66.9*I, -26.3 + 65.0*I, 5.71 + 4.75*I, 91.9 + 82.5*I, -94.6 + 51.8*I, 61.7 + 82.3*I, 54.8 - 27.8*I, 45.7 + 59.2*I, -28.3 + 78.1*I, -59.9 - 54.5*I], [-36.0 + 22.9*I, -51.7 + 10.8*I, -46.6 - 88.0*I, -52.8 - 32.0*I, -75.7 - 23.4*I, 96.2 - 71.2*I, -15.3 - 32.7*I, 26.9 + 6.31*I, -59.2 + 25.8*I, -0.836 - 98.3*I], [-65.2 - 90.6*I, 65.6 - 24.1*I, 72.5 + 33.9*I, 1.47 - 93.8*I, -0.143 + 39.0*I, -3.71 - 30.1*I, 60.1 - 42.4*I, 55.6 + 5.65*I, 48.2 - 53.0*I, -3.9 - 33.0*I], [7.04 + 0.0326*I, -12.8 - 50.4*I, 70.1 - 30.3*I, 42.7 - 76.3*I, -3.24 - 64.1*I, 97.3 + 66.8*I, -11.0 + 16.5*I, -40.6 - 90.7*I, 71.5 - 26.2*I, 83.1 - 49.4*I], [-59.5 + 8.08*I, 74.6 + 29.1*I, -65.8 + 26.3*I, -76.7 - 83.2*I, 26.2 + 99.0*I, -54.8 + 33.3*I, 2.79 - 16.6*I, -85.2 - 3.64*I, 98.4 - 12.4*I, -27.6 - 62.3*I], [82.6 - 95.3*I, 55.8 - 73.6*I, -49.9 + 42.1*I, 53.4 + 16.5*I, 80.2 - 43.6*I, -43.3 - 3.9*I, -2.26 - 58.3*I, -19.9 + 98.1*I, 47.2 + 62.4*I, -63.3 - 54.0*I], [-88.7 + 57.7*I, 55.6 + 70.9*I, 84.1 - 52.8*I, 71.3 - 29.8*I, -3.74 - 19.6*I, 29.7 + 1.18*I, -70.6 - 10.5*I, 37.6 + 99.9*I, 87.0 + 19.0*I, -26.1 - 82.0*I], [69.5 - 47.1*I, 11.3 - 59.0*I, -84.3 - 35.1*I, -3.61 - 35.7*I, 88.0 + 88.1*I, -47.5 + 0.956*I, 14.1 + 89.8*I, 51.3 + 0.14*I, -78.5 - 66.5*I, 2.12 - 53.2*I], [0.599 - 71.2*I, 21.7 + 10.8*I, 19.9 - 97.1*I, 20.5 + 37.4*I, 24.7 + 40.6*I, -82.7 - 29.1*I, 77.9 + 12.5*I, 94.1 - 87.4*I, 78.6 - 89.6*I, 82.6 - 69.6*I]] -> [262. - 180.*I, 179. + 117.*I, 10.3 + 214.*I, 102. - 145.*I, -36.5 + 97.7*I, -82.2 + 89.8*I, -241. - 104.*I, -119. - 26.0*I, -140. - 218.*I, -56.0 - 160.*I]



関連おそらく関連?(アプローチに依存)
-user202729

回答:


12

Haskell576554532507バイト

組み込みなし!

import Data.Complex
s=sum
l=length
m=magnitude
i=fromIntegral
(&)=zip
t=zipWith
(x!a)b=x*a+b
a#b=[[s$t(*)x y|y<-foldr(t(:))([]<$b)b]|x<-a]
f a|let c=[1..l a];g(u,d)k|m<-[t(+)a b|(a,b)<-a#u&[[s[d|x==y]|y<-c]|x<-c]]=(m,-s[s[b|(n,b)<-c&a,n==m]|(a,m)<-a#m&c]/i k)=snd<$>scanl g(0<$c<$c,1)c
p?x|let f=foldl1(x!);c=l p-1;n=i c;q p=init$t(*)p$i<$>[c,c-1..];o=f(q p)/f p;a|d<-sqrt$(n-1)*(n*(o^2-f(q$q p)/f p)-o^2)=n/last(o-d:[o+d|m(o-d)<m(o+d)])=last$p?(x-a):[x|m a<1e-9]
z[a,b]=[-b/a]
z p=p?0:z(init$scanl1(p?0!)p)

オンラインでお試しください!

合計-47バイト、@ØrjanJohansenに感謝します!

説明

まず、関数であるFaddeev–LeVerrierアルゴリズム使用して特性多項式を計算しますf。次に、関数は、ルートを見つけるためのラゲールの方法を実装zする反復により、その多項式のすべてのルートを計算します。ggz[a,b]=[-b/a]

非ゴルフ

I再インライン関数sumlengthmagnitudefromIntegralzipWith(&)少しヘルパーなど(!)。機能faddeevLeVerrierに対応frootszglaguerre夫々 。

-- Transpose a matrix/list
transpose a = foldr (zipWith(:)) (replicate (length a) []) a

-- Straight forward implementation for matrix-matrix multiplication
(#) :: [[Complex Double]] -> [[Complex Double]] -> [[Complex Double]]
a # b = [[sum $ zipWith (*) x y | y <- transpose b]|x<-a]


-- Faddeev-LeVerrier algorithm
faddeevLeVerrier :: [[Complex Double]] -> [Complex Double]
faddeevLeVerrier a = snd <$> scanl go (zero,1) [1..n]
  where n = length a
        zero = replicate n (replicate n 0)
        trace m = sum [sum [b|(n,b)<-zip [1..n] a,n==m]|(m,a)<-zip [1..n] m]
        diag d = [[sum[d|x==y]|y<-[1..n]]|x<-[1..n]]
        add as bs = [[x+y | (x,y) <- zip a b] | (b,a) <- zip as bs]
        go (u,d) k = (m, -trace (a#m) / fromIntegral k)
          where m = add (diag d) (a#u)


-- Compute roots by succesively removing newly computed roots
roots :: [Complex Double] -> [Complex Double]
roots [a,b] = [-b/a]
roots   p   = root : roots (removeRoot p)
  where root = laguerre p 0
        removeRoot = init . scanl1 (\a b -> root*a + b)

-- Compute a root of a polynomial p with an initial guess x
laguerre :: [Complex Double] -> Complex Double -> Complex Double
laguerre p x = if magnitude a < 1e-9 then x else laguerre p new_x
  where evaluate = foldl1 (\a b -> x*a+b)
        order' = length p - 1
        order  = fromIntegral $ length p - 1
        derivative p = init $ zipWith (*) p $ map fromIntegral [order',order'-1..]
        g  = evaluate (derivative p) / evaluate p
        h  = (g ** 2 - evaluate (derivative (derivative p)) / evaluate p)
        d  = sqrt $ (order-1) * (order*h - g**2)
        ga = g - d
        gb = g + d
        s = if magnitude ga < magnitude gb then gb else ga
        a = order /s
        new_x = x - a

1
ビルトインを使用しない唯一の提出物として、これが最も投票数の多い答えになるはずです。
エソランジングフルーツ

決定子に関連する何かを時間内に計算するための+1 n!
user202729

みんなありがとう!@ user202729:当初、私は監督!と本当に混乱していた:D
ბიმო

6

オクターブ、4バイト

@eig

オンラインでお試しください!

MATLゴルフ言語の同等品よりも2バイト多いだけです!

eig組み込みの匿名関数ハンドルを定義します。興味深いことに、MATLABの設計哲学は、を使用することを好む多くのハイエンド言語に反していますDescripteFunctionNamesTakingArguments()が、MATLABとOctaveは、可能な限り最短の明確な関数名を取得する傾向があります。たとえば、固有値 ubset(n絶対絶対値の最小値など)を取得するには、を使用しますeigs

ボーナスとして、solveビルトインを使用せず、代わりに固有値問題をシンボリックに解決し、det(A-λI)=0変換する関数(MATLABで動作し、理論的にはOctaveで動作しますが、実際にはタスクに依存しません)がありますを使用して数値形式にvpa

@(A)vpa(solve(det(A-sym('l')*eye(size(A)))))

3

MATL、2バイト

Yv

オンラインでお試しください!

説明

数値線形代数の通常のアドバイスに従いました。独自の関数を作成する代わりに、数値の不安定性を回避するために特別に設計された組み込み関数を使用します。

ちなみに、短いです。¯\ _(ツ)_ /¯


これは質問を請う、それはどれくらい長くないYvでしょうか?
-Sanchises

@Sanchisesよく分かりません。おそらくZQ、特性多項式の根()を見つけることによって、それについて行くでしょう。しかし、明示的に多項式のcoeffientsを計算することは多くの仕事かもしれ
ルイスMendo

2

Mathematica、11バイト

Eigenvalues

オンラインでお試しください!


はい、「この質問に対する1つの新しい回答」をクリックする前に、組み込みの回答を期待していました。組み込みでない答えを待ちましょう... /基本的にMathematicaソリューションはしばしば<タイトルの最初の単語>
-user202729

最短非純粋内蔵のI得ているFirst@Eigensystem@#&(20バイト)
ミスターXcoder

7
私は実際にここでuser202729に同意します。Mathematicaがすべての組み込み機能を持っていることを冗談で言うのは楽しいですが、チャレンジポスターとして、またあなたが比較的一生懸命やろうとしたことに相当する組み込みの答えを見るのに非常に迷惑です。Golfing(IMO)は最短のアルゴリズムとそのアルゴリズムの実装を見つけることを試みていますが、組み込みの答えがそれを「スポーツ」から奪います。
コイナーリンガーアーイング

2
@cairdcoinheringaahing本当にxnorの提案を実行に移すべきです。
マーティンエンダー

1

R、22バイト

function(m)eigen(m)$va

オンラインでお試しください!

mマトリックスとして受け取ります。イライラするeigenことに、R の関数はclassのオブジェクトを返します。このオブジェクトには、固有値と固有ベクトルというeigen2つのフィールドがあります。valuesvectors

しかし、もっとうるさく、オプションの引数がonly.values返されlist、2つのフィールドを持つのvalues固有値を含む、およびvectors、に設定しNULLたが、以降eigen(m,,T)も22バイトであり、それは洗浄です。




弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.