2016-04-19 31 views
7

Sto usando le funzioni gsl_eigen_nonsymm e/o gsl_eigen_symm dalla libreria GSL per trovare gli autovalori di una L x L matrice M[i][j] che è anche in funzione del tempo t = 1,....,N quindi devo M[i][j][t] per ottenere gli autovalori per ogni TI allocare una matrice L x L E[i][j] = M[i][j][t] e diagonalize per ogni t.GSL autovalori ordinare

Il problema è che il programma assegna gli autovalori in ordine diverso dopo una determinata iterazione. Per esempio (L = 3) se in t = 0 ottengo eigen[t = 0] = {l1,l2,l3}(0) a t = 1 i può ottenere eigen[t = 1] = {l3,l2,l1}(1) mentre ho bisogno di avere sempre {l1,l2,l3}(t) Per essere più concreti: considerare la matrice M (t)) = {{0,t,t},{t,0,2t},{t,t,0}} autovalori saranno sempre (approximatevly) l1 = -1.3 t , l2 = -t , l3 = 2.3 t Quando ho cercato diagonalizzare (con il codice sotto) ho ottenuto più volte uno scambio nel risultato degli autovalori. C'è un modo per prevenirlo? Non posso solo ordinarli in base alla grandezza, ho bisogno che siano sempre nello stesso ordine (qualunque cosa sia) a priori. (il codice qui sotto è solo un esempio per chiarire il mio problema)

EDIT: Non posso solo ordinarli perché a priori non conosco il loro valore e se hanno in modo affidabile una struttura come l1<l2<l3 in ogni momento a causa di fluttuazioni statistiche, ecco perché volevo sapere se c'è un modo per far si che l'algoritmo si comporti sempre nello stesso modo in modo che l'ordine degli autovalori sia sempre lo stesso o se ci sia qualche trucco per farlo accadere.

Giusto per essere più chiaro proverò a descrivere nuovamente il problema del giocattolo che ho presentato qui. Abbiamo una matrice che dipende dal tempo, io, forse ingenuamente, mi aspetto semplicemente di ottenere lambda_1(t).....lambda_N(t), invece quello che vedo è che l'algoritmo spesso scambia gli autovalori in momenti diversi, quindi se a t = 1 I've got (lambda_1,lambda_2,lambda_3)(1) at time t = 2 (lambda_2,lambda_1,lambda_3)(2) così se ad esempio volessi vedere come lambda_1 si evolve nel tempo non posso perché l'algoritmo mescola gli autovalori in momenti diversi. Il seguente programma è solo un esempio analitico del mio problema: gli autovalori della matrice sottostante sono l1 = -1.3 t , l2 = -t , l3 = 2.3 t ma il programma potrebbe darmi come output (-1.3,-1,2.3)(1), (-2,-2.6,4.6)(2), etc Come precedentemente affermato, mi chiedevo se esiste un modo per rendere l'ordine del programma gli autovalori sempre nello stesso modo, nonostante il loro valore numerico effettivo, in modo da ottenere sempre la combinazione (l1, l2, l3). Spero che ora sia più chiaro, per favore dimmi se non lo è.

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include <gsl/gsl_linalg.h> 
#include <gsl/gsl_eigen.h> 
#include <gsl/gsl_sort_vector.h> 

main() { 
    int L = 3, i, j, t; 
    int N = 10; 
    double M[L][L][N]; 
    gsl_matrix *E = gsl_matrix_alloc(L, L); 
    gsl_vector_complex *eigen = gsl_vector_complex_alloc(L); 
    gsl_eigen_nonsymm_workspace * w = gsl_eigen_nonsymm_alloc(L); 

    for(t = 1; t <= N; t++) { 
     M[0][0][t-1] = 0; 
     M[0][1][t-1] = t; 
     M[0][2][t-1] = t; 
     M[1][0][t-1] = t; 
     M[1][1][t-1] = 0; 
     M[1][2][t-1] = 2.0 * t; 
     M[2][1][t-1] = t; 
     M[2][0][t-1] = t; 
     M[2][2][t-1] = 0; 

     for(i = 0; i < L; i++) { 
      for(j = 0; j < L; j++) { 
       gsl_matrix_set(E, i, j, M[i][j][t - 1]); 
      } 
     } 

     gsl_eigen_nonsymm(E, eigen, w); /*diagonalize E which is M at t fixed*/ 
     printf("#%d\n\n", t); 

     for(i = 0; i < L; i++) { 
      printf("%d\t%lf\n", i, GSL_REAL(gsl_vector_complex_get(eigen, i))) 
     } 
     printf("\n"); 
    } 
} 
+1

Mi rendo conto che non si desidera ordinarli, ma gsl ha anche funzioni per l'ordinamento. Immagino che tu lo sappia già, ma nel caso ... gsl_eigen_nonsymmv_sort –

+0

Non esiste un "ordine a priori" per gli autovalori. Si prega di elaborare ciò che ti impedisce di ordinarli. – Phillip

+0

Ho modificato la domanda, ma fondamentalmente non posso semplicemente ordinarli tramite i metodi usuali a causa delle fluttuazioni statistiche che rendono gli autovalori cambiare "casualmente" il loro comportamento di volta in volta. – Fra

risposta

1

Non penso che tu possa fare quello che vuoi. Come t cambia l'output cambia.

La mia risposta originale ha menzionato l'ordine sui puntatori, ma guardando la struttura dei dati non sarà di aiuto. Quando gli autovalori sono stati calcolati, i valori sono memorizzati in E. Puoi vederli come segue.

gsl_eigen_nonsymm(E, eigen, w); 
double *mdata = (double*)E->data; 
printf("mdata[%i] \t%lf\n", 0, mdata[0]); 
printf("mdata[%i] \t%lf\n", 4, mdata[4]); 
printf("mdata[%i] \t%lf\n", 8, mdata[8]); 

Il seguente codice è come i dati nella autovettore è spiegate ...

double *data = (double*)eigen->data; 
for(i = 0; i < L; i++) { 
    printf("%d n \t%zu\n", i, eigen->size); 
    printf("%d \t%lf\n", i, GSL_REAL(gsl_vector_complex_get(eigen, i))); 
    printf("%d r \t%lf\n", i, data[0]); 
    printf("%d i \t%lf\n", i, data[1]); 
    printf("%d r \t%lf\n", i, data[2]); 
    printf("%d i \t%lf\n", i, data[3]); 
    printf("%d r \t%lf\n", i, data[4]); 
    printf("%d i \t%lf\n", i, data[5]); 
} 

Se, e si può controllare questo quando si vede il cambio d'ordine, l'ordine dei dati in mdata modifiche E l'ordine in data cambia quindi l'algoritmo non ha un ordine fisso cioè non puoi fare quello che stai chiedendo di fare. Se l'ordine non cambia in mdata e cambia in data allora hai una soluzione ma dubito davvero che sarà il caso.

+0

Mi dispiace, potresti per favore elaborare un po 'di più? grazie – Fra

+0

Per favore, metti un po 'di impegno nella risposta o semplicemente non rispondi. Avresti potuto postare questo come commento. Oppure inserisci dettagli e maggiori informazioni nella risposta. Si prega di modificare la risposta o semplicemente eliminarlo. È inutile in questa condizione. –

+0

@AshishAhuja ツ Mi sforzo ancora di più. – Harry

1

La tua domanda non ha senso. Gli autovalori non hanno alcun ordine intrinseco per loro. Mi sembra che tu voglia definire autovalori di M_t qualcosa di simile a L_1 (M_t), ..., L_n (M_t) e quindi tracciare come cambiano nel tempo. Supponendo che il tuo processo di guida di M_t sia continuo, allora anche i tuoi autovalori saranno.In altre parole, non cambieranno in modo significativo quando si apportano piccole modifiche a M_t. Quindi se si definisce un ordinamento applicando L_1 < L_2 ... < L_n, allora questo ordine non cambierà per piccole modifiche in t. Quando si superano due autovalori, è necessario prendere una decisione su come assegnare le modifiche. Se hai "fluttuazioni casuali" che sono più grandi della distanza tipica tra i tuoi autovalori, allora diventa essenzialmente impossibile.

Ecco un altro modo di tracciare gli autovettori, che potrebbe rivelarsi migliore. Per fare ciò, supponiamo che i tuoi autovettori siano v_i, con componenti v_ij. Quello che fai è innanzitutto "normalizzare" i tuoi autovettori in modo tale che v_i1 sia non negativo, cioè basta capovolgere il segno di ciascun autovettore in modo appropriato. Questo definirà un ordine sugli autovalori attraverso un ordinamento su v_i1, il primo componente di ciascun autovettore. In questo modo puoi ancora tenere traccia degli autovalori che si incrociano l'un l'altro. Tuttavia se i tuoi autovettori si incrociano sul primo componente, sei nei guai.

0

Secondo la documentazione, tali funzioni restituiscono non ordinato:

https://www.gnu.org/software/gsl/manual/html_node/Real-Symmetric-Matrices.html

Questa funzione calcola gli autovalori della matrice reale simmetrica A. Ulteriori lavoro di dimensioni adeguate devono essere forniti in w. La parte triangolare e inferiore triangolare di A viene distrutta durante il calcolo, ma la rigida parte triangolare superiore non viene referenziata. Gli autovalori sono memorizzati nella valutazione vettoriale e sono non ordinati.

Anche le funzioni che restituiscono ordinate risultati, fanno per semplice ascendente/ampiezza decrescente:

https://www.gnu.org/software/gsl/manual/html_node/Sorting-Eigenvalues-and-Eigenvectors.html

Questa funzione ordina simultaneamente gli autovalori memorizzati nel eval vettore ei corrispondenti autovettori reali memorizzato nelle colonne della matrice evec in ordine ascendente o discendente in base al valore del parametro sort_type come mostrato sopra.

Se stai cercando l'evoluzione temporale degli autovalori, basta fare come voi avete fatto e risolvere per le rappresentazioni dipendenti dal tempo, ad esempio:

lambda_1(t).....lambda_N(t) 

Per la vostra semplice time-come esempio -scalar,

l1 = -1.3 t , l2 = -t , l3 = 2.3 t 

È letteralmente hanno una parametrizzazione di tutte le possibili soluzioni e perché hai assegnato loro identificatori ln non si esegue la questione della degenerazione. Anche se qualsiasi M[i][j] è una funzione non lineare di t, non dovrebbe avere importanza perché il sistema stesso è lineare e le soluzioni sono calcolate esclusivamente dall'equazione caratteristica (che manterrà t costante mentre risolve per lambda).