矩阵的特征值


11

给定一个正方形矩阵,输出矩阵的特征值。每个特征值应重复与其代数多重性相等的次数。

矩阵的特征值A是标量值λ,使得对于某些列向量vA*v = λ*v。它们也是的特征多项式的解决方案A:(det(A - λ*I) = 0其中I与相同的维的单位矩阵A)。

输出必须精确到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

Answers:


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)

在线尝试!

非常感谢@ØrjanJohansen总共-47个字节!

说明

首先,使用函数Faddeev-LeVerrier算法计算特征多项式f。然后,该函数z通过迭代g来计算该多项式的所有根,该迭代实现了Laguerre的方法来寻找根,一旦找到根,将其删除并g再次调用,直到多项式的阶次为1为止z[a,b]=[-b/a]

不打高尔夫球

我再内联函数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 '17

谢谢你们!@ user202729:起初,我负责监督!d:和真的困惑
ბიმო

6

八度,4字节

@eig

在线尝试!

仅比MATL打高尔夫球语言多两个字节!

定义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我不确定。我可能会通过找到ZQ特征多项式的根()来解决这个问题。但是,明确计算多项式的系数可能是一件繁重的工作
Luis

2

Mathematica,11个字节

Eigenvalues

在线尝试!


是的,我希望在单击“此问题的一个新答案”之前有一个内置的答案。让我们等待一些非内置的答案... /基本上,Mathematica解决方案通常是<标题中的第一个单词>
user202729

我得到的最短的非纯内置文件是First@Eigensystem@#&(20字节)
Xcoder先生,2017年

7
我实际上在这里同意user202729。虽然开玩笑地讲Mathematica具有所有功能的内置功能,但作为挑战性海报和回答看到与您尝试相对困难的功能相对应的内置答案,这非常令人讨厌。高尔夫(IMO)是关于尝试找到最短的算法和该算法的实现,但是内置的答案使它脱离了“运动”。
caird coinheringaahing

2
@cairdcoinheringaahing我们应该真正开始将xnor的建议付诸实践
Martin Ender's

1

R,22字节

function(m)eigen(m)$va

在线尝试!

采用m作为基质。eigen令人沮丧的是,R中的函数返回class的对象eigen,该对象具有两个字段:values,特征值和vectors,特征向量。

但是,更令人讨厌的是,可选参数only.values返回一个list带有两个字段的,values其中包含特征值,并且vectors设置为NULL,但是由于eigen(m,,T)也是22个字节,因此很麻烦。


1

朱莉娅,12字节

n->eig(n)[1]

在线尝试!

不幸的是,eig本征值和本征向量都作为一个元组返回,因此我们浪费了另外9个字节来对它进行lambd化并获取第一项。


0

Python + numpy,33个字节

from numpy.linalg import*
eigvals

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.