Собственные значения матрицы

11

Учитывая квадратную матрицу, выведите собственные значения матрицы. Каждое собственное значение должно повторяться количество раз, равное его алгебраической кратности.

Собственные значения матрицы Aявляются скалярным значением , λтакими , что для некоторого вектора - столбца v, A*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]
Mego
источник
Связанные ? Возможно связано ? (зависит от подхода)
user202729

Ответы:

12

Haskell , 576 554 532 507 байт

Нет встроенных модулей!

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 байтов!

объяснение

Сначала вычисляется характеристический многочлен с помощью алгоритма Фаддеева – ЛеВерье, который является функцией f. Затем функция zвычисляет все корни этого полинома путем итерации, gкоторая реализует метод Лагерра для нахождения корня, как только корень найден, он удаляется и вызывается gснова, пока у полинома не будет степени 1, которая тривиально решается с помощью z[a,b]=[-b/a].

Ungolfed

Я снова встраиваемые функции sum, length, magnitude, fromIntegral, zipWithи (&), а также маленький помощник (!). Функция faddeevLeVerrierсоответствует , чтобы f, rootsчтобы zи gк laguerreсоответственно.

-- 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
Как единственное представление, в котором не используются встроенные функции, это должен быть ответ с наибольшим количеством голосов.
Esolanging Fruit
+1 за вычисление чего-то связанного с определителем во времени меньше чем n!!
user202729
Спасибо ребята! @ user202729: Первоначально я наблюдал за этим !и был действительно смущен: D
ბიმო
6

Октава , 4 байта

@eig

Попробуйте онлайн!

Всего на два байта больше, чем эквивалент языка игры в гольф MATL!

Определяет дескриптор анонимной функции для eigвстроенного. Интересно, что философия дизайна MATLAB идет вразрез со многими высококлассными языками, которые нравится использовать DescripteFunctionNamesTakingArguments(), тогда как MATLAB и, следовательно, Octave стремятся получить самое короткое однозначное имя из возможных. Например, чтобы получить ы ubset собственных значений (например, наименьший nпо абсолютной величине), вы используете eigs.

В качестве бонуса, вот функция (работает в MATLAB, и теоретически может работать в Octave, но solveэто не совсем соответствует задаче), которая не использует встроенные модули, но вместо этого символически решает проблему собственных значений det(A-λI)=0и преобразует ее в числовой форме с использованиемvpa

@(A)vpa(solve(det(A-sym('l')*eye(size(A)))))
Sanchises
источник
3

MATL , 2 байта

Yv

Попробуйте онлайн!

объяснение

Я следовал обычному совету по числовой линейной алгебре: вместо написания своей собственной функции используйте встроенную функцию, специально разработанную для избежания нестабильности чисел.

Кстати, это короче. ¯ \ _ (ツ) _ / ¯

Луис Мендо
источник
Возникает вопрос, как долго это будет без Yv?
Sanchises
@ Санчизы, я не уверен. Вероятно, я бы пошел на это, найдя корни ( ZQ) характеристического полинома. Но явное вычисление коэффициентов многочлена может быть очень
Луис Мендо
2

Mathematica, 11 байт

Eigenvalues

Попробуйте онлайн!

J42161217
источник
Да, я ожидал встроенного ответа, прежде чем нажать «1 новый ответ на этот вопрос». Давайте подождем некоторого не встроенного ответа ... / В основном решение Mathematica часто <первое слово в заголовке>
user202729
Самый короткий встроенный не чистый First@Eigensystem@#&
код
7
Я на самом деле согласен с user202729 здесь. Хотя забавно шутить о том, что у Mathematica есть встроенная программа для всего, это очень раздражает как постер-испытатель и ответ, когда я вижу встроенный ответ, эквивалентный тому, что вы пытались сделать относительно трудно. Гольф (ИМО) - это попытка найти кратчайший алгоритм и реализацию указанного алгоритма, но встроенный ответ уводит его от «спорта».
Кэрд coinheringaahing
2
@cairdcoinheringaahing Мы должны начать применять предложение xnor на практике .
Мартин Эндер
1

R , 22 байта

function(m)eigen(m)$va

Попробуйте онлайн!

Берет mв качестве матрицы. К сожалению, eigenфункция в R возвращает объект класса eigen, который имеет два поля: valuesсобственные значения и vectorsсобственные векторы.

Однако более досадно, что необязательный аргумент only.valuesвозвращает a listс двумя полями:values содержащими собственные значения, и vectors, установленными в NULL, но, поскольку eigen(m,,T)он также составляет 22 байта, это промывка.

Giuseppe
источник
1

Юля , 12 байт

n->eig(n)[1]

Попробуйте онлайн!

К сожалению, eigвозвращает как собственные значения, так и собственные векторы в виде кортежа, поэтому мы тратим еще 9 байтов, чтобы преобразовать его и получить первый элемент.

Уриэль
источник
0

Python + NumPy, 33 байта

from numpy.linalg import*
eigvals
Уриэль
источник