2013-04-28 84 views

risposta

31

si può anche verificare se tutti gli autovalori di matrici sono positivi, in tal caso la matrice è definita positiva:

import numpy as np 

def is_pos_def(x): 
    return np.all(np.linalg.eigvals(x) > 0) 
+1

È possibile utilizzare invece np.linalg.eigvals, che calcola solo gli autovalori. Anche in questo caso, è molto più lento dell'approccio di @ NPE (3x per matrici 10x10, 40x per 1000x1000). – jorgeca

+0

@jorgeca, ho aggiornato la mia risposta per riflettere il tuo suggerimento, grazie. Grazie per le informazioni sull'ora. – Akavall

+8

In generale non è vero che tutti gli autovalori positivi implicano la definitività positiva, a meno che non si sappia che la matrice è simmetrica (caso reale) o Hermitiano (caso complesso). Ad esempio, A = array ([[1, -100], [0, 2]]) non è definito positivo. Alcuni potrebbero includere simmetrico o Hermitiano come parte della * definizione * di "positivo definito", ma ciò non è universale.

33

Si potrebbe provare a calcolare la scomposizione di Cholesky (numpy.linalg.cholesky). Questo aumenterà LinAlgError se la matrice non è definita positiva.

+0

Grazie mille, non variare elegante ma funziona! –

+4

Questo dovrebbe essere sostanzialmente più efficiente della soluzione autovalore. – MRocklin

+0

Solo una nota che nel caso semi-definito positivo, numericamente parlando, si può anche aggiungere una piccola identità alla matrice (spostando così tutti gli autovalori di una piccola quantità per esempio alcune volte la precisione della macchina) quindi utilizzare il metodo Cholesky come al solito. – jawknee

4

Non so il motivo per cui la soluzione di NPE è così sottovalutato. È il modo migliore per farlo. Ho trovato su Wkipedia che la complessità è cubica.

Inoltre, si dice che è più numericamente stabile della decomposizione Lu. E la decomposizione di Lu è più stabile del metodo di trovare tutti gli autovalori.

E, si tratta di una soluzione molto elegante, perché è un dato di fatto:

Una matrice ha una decomposizione di Cholesky se e solo se è simmetrica positiva.

Quindi perché non usare la matematica? Forse alcune persone hanno paura del rilancio dell'eccezione, ma è un dato di fatto, è abbastanza utile programmare con eccezioni.

+1

Dalla stessa pagina di Wikipedia, sembra che la tua affermazione sia errata. La pagina dice " Se la matrice A è Hermitiana e semi-definita positiva, allora ha ancora una scomposizione della forma A = LL * se le voci diagonali di L sono consentite per essere zero. [3]" Così una matrice con una scomposizione di Cholesky non implica che la matrice sia definita positivamente simmetrica poiché potrebbe essere solo semi-definita. Sto interpretando questo torto? Inoltre, sembra che tu abbia appena lanciato un "simmetrico" attraverso l'implicazione. cioè, non dovrebbe essere che ogni matrice Hermitiana positiva-definita abbia una decomposizione di Cholesky unica? – user3731622

0

Per una matrice reale $ A $, abbiamo $ x^TAx = \ frac {1} {2} (x^T (A + A^T) x) $ e $ A + A^T $ è una matrice reale simmetrica. Quindi $ A $ è definito positivo se $ A + A^T $ è positivo definito, se tutti gli autovalori di $ A + A^T $ sono positivi.

import numpy as np 

def is_pos_def(A): 
    M = np.matrix(A) 
    return np.all(np.linalg.eigvals(M+M.transpose()) > 0) 
1

Per illustrare la risposta @ NPE con un po 'di codice pronto per l'uso:

importazione NumPy come np

def is_pd(K): 
    try: 
     np.linalg.cholesky(K) 
     return 1 
    except np.linalg.linalg.LinAlgError as err: 
     if 'Matrix is not positive definite' in err.message: 
      return 0 
     else: 
    raise 
+1

Si potrebbe anche chiedere a @NPE di aggiungere il codice alla propria risposta originale. – Matthias

2

Sembra che ci sia una piccola confusione tutte le risposte di cui sopra (almeno riguardo alla domanda).

Per le matrici reali, i test per autovalori positivi e termini a conduzione positiva in np.linalg.cholesky si applicano solo se la matrice è simmetrica. Quindi, per prima cosa è necessario testare se la matrice è simmetrica e quindi applicare uno di questi metodi (autovalori positivi o scomposizione di Cholesky).

Ad esempio:

import numpy as np 

#A nonsymmetric matrix 
A = np.array([[9,7],[6,14]]) 

#check that all eigenvalues are positive: 
np.all(np.linalg.eigvals(A) > 0) 

#take a 'Cholesky' decomposition: 
chol_A = np.linalg.cholesky(A) 

La matrice A non è simmetrica, ma gli autovalori sono positivi e Numpy restituisce una decomposizione di Cholesky che è sbagliato. È possibile verificare che:

chol_A.dot(chol_A.T) 

è diverso da A.

Si può anche verificare che tutte le funzioni di cui sopra sarebbero pitone test positivo per 'positiva determinatezza'.Questo potrebbe potenzialmente essere un problema grave se si stava tentando di utilizzare la decomposizione di Cholesky per calcolare l'inverso, in quanto:

>np.linalg.inv(A) 
array([[ 0.16666667, -0.08333333], 
    [-0.07142857, 0.10714286]]) 

>np.linalg.inv(chol_A.T).dot(np.linalg.inv(chol_A)) 
array([[ 0.15555556, -0.06666667], 
    [-0.06666667, 0.1  ]]) 

sono diversi.

In sintesi, vorrei suggerire l'aggiunta di una linea ad una qualsiasi delle funzioni di cui sopra per verificare se la matrice è simmetrica, per esempio:

def is_pos_def(A): 
    if np.array_equal(A, A.T): 
     try: 
      np.linalg.cholesky(A) 
      return True 
     except LinAlgError: 
      return False 
    else: 
     return False 

Si consiglia di sostituire np.array_equal (A, AT) nella funzione sopra per np.allclose (A, AT) per evitare differenze dovute a errori in virgola mobile.

Problemi correlati