PDA

View Full Version : [C/C++] Algoritmo per calcolare gli invarianti secondari delle matrici quadrate


mesonepigreco
15-01-2012, 19:25
Ciao a tutti,
Non riesco a trovare un algoritmo per calcolare gli invarianti secondari delle matrici quadrate. È chiaramente banale il problema se si conosce in anticipo l'ordine dell'invariante, ma vorrei scrivere una funzione che prende in input l'ordine dell'inveriante, la matrice e la sua dimensione e restituisce l'invariante di quell'ordine, il prototipo dovrebbe essere qualcosa del genere

double OttieniInvariante(double Matrice[][1000], int dimensione, int ordine);


Per chi non lo sapesse un invariante di ordine k è la somma dei determinanti di tutte le possibili sottomatrici di ordine k costruite sulla diagonale della matrice data.
Lo scopo del programma è quello di usare gli invarianti primari (traccia e determinante) e secondari per costruire il polinomio caratteristico di una matrice, e trovare dunque gli autovalori.

So che è complicato, ma ho già scritto alcune funzioni possono essere utili per questo, ecco i prototipi:

int RiduciAScala(double Matrice[][N_MAX], int n);
// Riduce a scala la matrice con l'algoritmo di Gauss-Jordan

double Determinante(double Matrice[][N_MAX], int n);
// Calcola con lo sviluppo di Laplace il determinante della matrice

double ComplementoAlgebrico(double Matrice[][N_MAX], int n, int riga, int colonna);
// Calcola il complemento algebrico della matrice nella riga e nella colonna data

void stampa(double Matrice[][N_MAX], int n);
//Stampa a schermo la matrice

void CalcolaInversa(double Matrice[][N_MAX], int n, double inversa[][N_MAX]);
// Calcola la matrice inversa salvando il risultato in inversa

void Trasposta(double Matrice[][N_MAX], int n, double trasposta[][N_MAX]);
// Transpone la matrice, salvando il risultato in trasposta

void ProdottoRigheXColonne(double m1[][N_MAX], double m2[][N_MAX], int n, double ris[][N_MAX]);

void CalcolaSottomatrice(double Matrice[][N_MAX], int n, int riga, int colonna, double ridotta[][N_MAX]);
// Calcola la sottomatrice ottenuta togliendo dalla matrice la riga e la colonna data e salvando il risultato in ridotta


Grazie mille in anticipo!

mesonepigreco
16-01-2012, 15:52
Entro un po' nel dettaglio del mio problema.
Allora, ho ragionato un po' sul problema, e penso che si possa risolvere in più passaggi:


Generare un array contenente tutte le possibili combinazioni di numeri da 1 alla dimensione della matrice come nell'esempio:
k = 1 Matrice di dimensione 4x4
{1} {2} {3} {4}
k = 2 Matrice di dimensione 4x4
{1,2} {1,3} {1,4} {2,3} {2,4} {3,4}
k = 3 Matrice di dimensione 4x4
{1,2,3} {1,2,4} {1,3,4} {2,3,4}
k = 4
{1,2,3,4}

A questo punto si crea una sottomatrice per ognuno degli array in cui si sono tolte tutte le righe e le colonne che non appartengono all'array
es:
Matrice 4X4 Array: {1,2,4}
tolgo la terza riga e la terza colonna (non appartengono all'array)
Matrice 4x4 Array {2,3}
tolgo la prima riga e la quarta riga e colonna (1 e 4 non sono nell'array)

Sommo tra di loro i determinanti delle matrici così ottenute e ho il valore dell'invariante.


Il problema rimane come fare il punto primo?
Non riesco a scrivere una funzione che generi questi array, il prototipo dovrebbe essere qualcosa del genere

int GeneraArrays(int Array[][100], int k, int max);
// Genera questi array e li salva in Array, con k elementi generati da max numeri, e ritorna il numero di array generati


Mi è venuto in mente che per farlo, basterebbe generare un gruppo simmetrico e poi salvare la posizione dei primi k numeri, poi cancellare tutti quelli che non sono in ordine crescente:
es.
k = 2; numeri da 1 a 3
{1,2,3} {1,3,2} {2,1,3} {3,2,1} {3,1,2}{2,3,1} // Questo sono in numero 3!
Prendo le posizioni dei primi k numeri:
{1,2} {1,3}{2,1}{3,1}{2,3}{3,1} // Anche questi sono in numero 3!
Elimino quelli non ordinati:
{1,2}{1,3}{2,3} // e ho quello che voglio

Il problema è, come genero questi array? :doh:
k = 2; numeri da 1 a 3
{1,2,3} {1,3,2} {2,1,3} {3,2,1} {3,1,2}{2,3,1}????????

Aiuto!!!! :mc:

mesonepigreco
17-01-2012, 16:48
Non fa niente, ho trovato l'algoritmo dei gruppi simmetrici da solo,
se ci fosse la remota possibilità che qualcunaltro si inbatta in questo problema ecco l'algoritmo:

si parte da k = 1
il gruppo vale 1.

k = 2. Si aggiunge 2 in tutte le posizioni possibili del gruppo precedente:
2 1
1 2

k = 3. Si aggiunge 3 in tutte le posizioni possibili:
3 2 1
3 1 2

2 3 1
1 3 2

2 1 3
1 2 3

k = 4. Si aggiunge 4 in ogni possibile posizioni delle permutazioni di k = 3:
4 3 2 1
4 3 1 2
4 2 3 1
4 1 3 2
4 2 1 3
4 1 2 3

3 4 2 1
3 4 1 2
.....

Adesso devo solo implementare tutto in C, ma non sembra essere troppo impossibile.