Autovalori di una matrice


11

Data una matrice quadrata, genera gli autovalori della matrice. Ogni autovalore dovrebbe essere ripetuto un numero di volte uguale alla sua molteplicità algebrica.

Gli autovalori di una matrice Asono valori scalari λtali che, per alcuni vettore colonna v, A*v = λ*v. Sono anche le soluzioni al polinomio caratteristico di A: det(A - λ*I) = 0(dov'è Ila matrice identità con le stesse dimensioni di A).

Gli output devono essere precisi su 3 cifre significative. Tutti gli ingressi e le uscite rientreranno nell'intervallo rappresentabile di valori numerici per la lingua scelta.

I builtin sono accettabili, ma si consiglia di includere soluzioni che non utilizzano i builtin.

Casi test

In questi casi di test, Irappresenta l'unità immaginaria. I numeri complessi sono scritti nel modulo a + b*I. Tutte le uscite hanno 3 cifre significative di precisione.

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



Correlati ? Probabilmente correlato ? (dipende dall'approccio)
user202729

Risposte:


12

Haskell , 576 554 532 507 byte

Nessun built-in!

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)

Provalo online!

Mille grazie a ØrjanJohansen per un totale di -47 byte!

Spiegazione

In primo luogo, questo calcola il polinomio caratteristico con l' algoritmo di Faddeev – LeVerrier che è la funzione f. Quindi la funzione zcalcola tutte le radici di quel polinomio iterando gche implementa il Metodo di Laguerre per trovare una radice, una volta che una radice viene trovata viene rimossa e gviene richiamata fino a quando il polinomio ha grado 1 che è banalmente risolto z[a,b]=[-b/a].

Ungolfed

I ri-inline le funzioni sum, length, magnitude, fromIntegral, zipWithe (&)così come il piccolo aiutante (!). La funzione faddeevLeVerriercorrisponde rispettivamente a f, rootsa ze ga 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
Come unica richiesta che non utilizza i builtin, questa dovrebbe essere la risposta più votata.
Esolanging Fruit il

+1 per il calcolo di qualcosa di correlato a determinante in tempo inferiore a n!!
user202729

Grazie ragazzi! @ user202729: Inizialmente ho supervisionato l'argomento !ed ero davvero confuso: D
ბიმო

6

Ottava , 4 byte

@eig

Provalo online!

Solo due byte in più rispetto all'equivalente linguistico del golf MATL!

Definisce un handle di funzione anonimo per il eigbuilt-in. È interessante notare che la filosofia di progettazione MATLAB va contro molti linguaggi di fascia alta, che amano usare DescripteFunctionNamesTakingArguments(), mentre MATLAB e di conseguenza Octave tendono a ottenere il nome di funzione univoco più breve possibile. Ad esempio, per ottenere un s ubset di autovalori (ad esempio, il più piccolo nin valore assoluto), si utilizza eigs.

Come bonus, ecco una funzione (funziona in MATLAB, e in teoria potrebbe funzionare in Octave ma il loro solvenon è all'altezza del compito) che non usa i built-in, ma risolve simbolicamente il problema degli autovalori det(A-λI)=0e lo converte in forma numerica utilizzandovpa

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

3

MATL , 2 byte

Yv

Provalo online!

Spiegazione

Ho seguito i consueti consigli nell'algebra lineare numerica: invece di scrivere la tua funzione, usa un built-in appositamente progettato per evitare instabilità numeriche.

Per inciso, è più breve. ¯ \ _ (ツ) _ / ¯


Questo pone la domanda, quanto tempo sarebbe senza Yv?
Sanchises,

@Sanchise non ne sono sicuro. Probabilmente lo farei trovando le radici ( ZQ) del caratteristico polinomio. Ma calcolare esplicitamente i coefficienti del polinomio potrebbe richiedere molto lavoro
Luis Mendo,

2

Mathematica, 11 byte

Eigenvalues

Provalo online!


Sì, mi aspettavo una risposta integrata prima di fare clic su "1 nuova risposta a questa domanda". Aspettiamo una risposta non integrata ... / Fondamentalmente la soluzione Mathematica è spesso <prima parola nel titolo>
user202729

Il più breve built-in non puro che ho ricevuto è First@Eigensystem@#&(20 byte)
Mr. Xcoder

7
In realtà sono d'accordo con user202729 qui. Mentre è divertente scherzare sul fatto che Mathematica abbia un built-in per tutto, è molto fastidioso sia come poster di sfida che rispondere per vedere una risposta integrata equivalente a qualcosa che hai provato relativamente difficile da fare. Il golf (IMO) riguarda il tentativo di trovare l'algoritmo e l'implementazione più brevi di detto algoritmo, ma una risposta integrata lo allontana dallo "sport".
caird coinheringaahing il

2
@cairdcoinheringaahing Dovremmo davvero iniziare a mettere in pratica la proposta di xnor .
Martin Ender,

1

R , 22 byte

function(m)eigen(m)$va

Provalo online!

Prende mcome una matrice. Frustrantemente, la eigenfunzione in R restituisce un oggetto di classe eigen, che ha due campi: valuesgli autovalori e vectorsgli autovettori.

Tuttavia, più fastidiosamente, l'argomento facoltativo only.valuesrestituisce a listcon due campi, valuescontenenti gli autovalori e vectors, impostato su NULL, ma poiché eigen(m,,T)è anche 22 byte, è un lavaggio.


1

Julia , 12 byte

n->eig(n)[1]

Provalo online!

Sfortunatamente, eigrestituisce sia gli autovalori che gli autovettori, come una tupla, quindi perdiamo altri 9 byte per lambificarlo e prendere il primo oggetto.


0

Python + numpy, 33 byte

from numpy.linalg import*
eigvals

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.