Власні значення матриці


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]



Відповіді:


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].

Безумовно

Я знову вбудовуються функції 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
1717

6

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

@eig

Спробуйте в Інтернеті!

Тільки на два байти більше, ніж еквівалент мови для гольфу MATL!

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

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

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

3

MATL , 2 байти

Yv

Спробуйте в Інтернеті!

Пояснення

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

До речі, це коротше. ¯ \ _ (ツ) _ / ¯


Це ставить питання, як довго це було б без Yv?
Санчіз

@Sanchises Я не впевнений. Я б, мабуть, пішов про це, знайшовши коріння ( ZQ) характерного многочлена. Але явно обчислити коефіцієнти многочлена може бути багато роботи
Луїс Мендо

2

Математика, 11 байт

Eigenvalues

Спробуйте в Інтернеті!


Так, я очікував вбудованої відповіді, перш ніж натиснути "1 нова відповідь на це питання". Будемо чекати деяких невбудованих відповідей ... / В основному рішення Mathematica часто <перше слово в заголовку>
user202729

Найкоротший First@Eigensystem@#&
нечистий

7
Я фактично згоден з user202729 тут. Хоча весело жартувати про те, що Mathematica має вбудований для всього, це дуже дратує і як плакат виклику, і відповідь, щоб побачити вбудований відповідь, еквівалентну тому, що ви намагалися відносно важко зробити. Гольфінг (ІМО) - це спроба знайти найкоротший алгоритм та реалізацію зазначеного алгоритму, але вбудована відповідь відводить це від «спорту».
caird 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 байти, це промивання.




Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.