IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Mathématiques Discussion :

Calcul des valeurs propres et vecteurs propres d'une matrice carrée


Sujet :

Mathématiques

  1. #1
    Membre régulier
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Avril 2011
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2011
    Messages : 108
    Points : 97
    Points
    97
    Par défaut Calcul des valeurs propres et vecteurs propres d'une matrice carrée
    Bonjour,

    Je viens de commencer un programme de calcul des valeurs et vecteurs propres d'une matrice carrée

    J'utilise pour cela la fonction dgeev_() de la librairie LAPACK dans un programme C++ sous Linux

    J'ai tout d'abord commencé par l'exemple basique trouvé à l'adresse https://scicomp.stackexchange.com/qu...ng-lapack-in-c
    (il permet de charger une matrice stockée dans un fichier mais ne renvoie que les valeurs propres, pas les vecteurs propres)

    J'ai ensuite utilisé un autre exemple, que je trouve déjà bien moins basique, trouvé à l'adresse https://www.intel.com/content/www/us...example-c.html
    (il renvoie bien quand à lui les valeurs propres **ET** les vecteurs propres mais est par contre limité à une matrice 5x5 stockée en dur dans le code, cf. ne permet pas de charger une matrice carrée stockée dans un fichier)

    => j'ai donc combinées ces 2 sources afin d'avoir un programme me permettant d'obtenir les valeurs propres ainsi que les vecteurs propres à partir d'une matrice carrée stockée dans un fichier
    (s'il n'y a pas de fichier contenant la matrice à traiter donné en paramêtre, il utilise une matrice par défaut stockée en dur dans le code)

    Mon problème est que je ne comprend pas très bien ce qui distingue un "vecteur gauche", d'un "vecteurs droit"
    + il semble qu'il fasse les lire en colonne mais je ne comprend pas le rapport avec l'ordre des valeurs propres avec leurs vecteurs propres gauches/droits associés
    (les vecteurs semblent normalisés à 1 quand on les lit en colonne mais je ne comprend pas l'ordre des valeurs/vecteurs propres ainsi que la différence entre les vecteurs gauche et les vecteurs droits)


    Par exemple, à l'adresse https://igm.univ-mlv.fr/~vnozick/tea...genProblem.pdf , la matrice suivante

    1 2 0
    0 3 0
    2 −4 2

    renvoie 3 valeurs propres et vecteurs propres associés

    λ1 = 3 avec le vecteur propre (-1 -1 2)

    λ2 = 2 avec le vecteur propre (0 0 1)

    λ3 = 1 avec le vecteur propre (-1 0 2)

    Alors que mon programme renvoie ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    yannoo@cyclone ~/Dev/Vpropre $ ./test_lapack3 matrix321.txt
     DGEEV Example Program Results
     
    Matrix 3x3 loaded 
    1.00 2.00 0.00 
    0.00 3.00 0.00 
    2.00 -4.00 2.00 
     
     
     Eigenvalues
       3.00   1.00   2.00
     
     Left eigenvectors
       0.41   0.45   0.00
       0.41   0.00   0.00
      -0.82  -0.89   1.00
     
     Right eigenvectors
       0.00   0.71   0.89
       1.00  -0.71   0.00
       0.00   0.00   0.45
    => et où ne comprend pas trop bien quel vecteur (droit ou gauche ?) est à associer à quelle valeur propre

    Ci-dessous, le code que j'utilise et qui est un mix de celui des 2 codes trouvées aux adresses données au début :
    (ça se compile tout simplement via un g++ -o test_lapack3 test_lapack3.cpp -llapack )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
     
    /*******************************************************************************
    *  Copyright (C) 2009-2015 Intel Corporation. All Rights Reserved.
    *  The information and material ("Material") provided below is owned by Intel
    *  Corporation or its suppliers or licensors, and title to such Material remains
    *  with Intel Corporation or its suppliers or licensors. The Material contains
    *  proprietary information of Intel or its suppliers and licensors. The Material
    *  is protected by worldwide copyright laws and treaty provisions. No part of
    *  the Material may be copied, reproduced, published, uploaded, posted,
    *  transmitted, or distributed in any way without Intel's prior express written
    *  permission. No license under any patent, copyright or other intellectual
    *  property rights in the Material is granted to or conferred upon you, either
    *  expressly, by implication, inducement, estoppel or otherwise. Any license
    *  under such intellectual property rights must be express and approved by Intel
    *  in writing.
    *
    ********************************************************************************
    */
    /*
       DGEEV Example.
       ==============
     
       Program computes the eigenvalues and left and right eigenvectors of a general
       rectangular matrix A:
     
        -1.01   0.86  -4.60   3.31  -4.81
         3.98   0.53  -7.04   5.29   3.55
         3.30   8.26  -3.89   8.20  -1.51
         4.43   4.96  -7.66  -7.33   6.18
         7.31  -6.43  -6.16   2.47   5.58
     
       Description.
       ============
     
       The routine computes for an n-by-n real nonsymmetric matrix A, the
       eigenvalues and, optionally, the left and/or right eigenvectors. The right
       eigenvector v(j) of A satisfies
     
       A*v(j)= lambda(j)*v(j)
     
       where lambda(j) is its eigenvalue. The left eigenvector u(j) of A satisfies
     
       u(j)H*A = lambda(j)*u(j)H
     
       where u(j)H denotes the conjugate transpose of u(j). The computed
       eigenvectors are normalized to have Euclidean norm equal to 1 and
       largest component real.
     
       Example Program Results.
       ========================
     
     DGEEV Example Program Results
     
     Eigenvalues
     (  2.86, 10.76) (  2.86,-10.76) ( -0.69,  4.70) ( -0.69, -4.70) -10.46
     
     Left eigenvectors
     (  0.04,  0.29) (  0.04, -0.29) ( -0.13, -0.33) ( -0.13,  0.33)   0.04
     (  0.62,  0.00) (  0.62,  0.00) (  0.69,  0.00) (  0.69,  0.00)   0.56
     ( -0.04, -0.58) ( -0.04,  0.58) ( -0.39, -0.07) ( -0.39,  0.07)  -0.13
     (  0.28,  0.01) (  0.28, -0.01) ( -0.02, -0.19) ( -0.02,  0.19)  -0.80
     ( -0.04,  0.34) ( -0.04, -0.34) ( -0.40,  0.22) ( -0.40, -0.22)   0.18
     
     Right eigenvectors
     (  0.11,  0.17) (  0.11, -0.17) (  0.73,  0.00) (  0.73,  0.00)   0.46
     (  0.41, -0.26) (  0.41,  0.26) ( -0.03, -0.02) ( -0.03,  0.02)   0.34
     (  0.10, -0.51) (  0.10,  0.51) (  0.19, -0.29) (  0.19,  0.29)   0.31
     (  0.40, -0.09) (  0.40,  0.09) ( -0.08, -0.08) ( -0.08,  0.08)  -0.74
     (  0.54,  0.00) (  0.54,  0.00) ( -0.29, -0.49) ( -0.29,  0.49)   0.16
    */
    // #include <stdlib.h>
    // #include <stdio.h>
     
    #include <iostream>
    #include <fstream>
    // #include <iomanip>
    using namespace std;
     
     
     
    /* DGEEV prototype */
    /* 
    extern void dgeev_( char* jobvl, char* jobvr, int* n, double* a,
                    int* lda, double* wr, double* wi, double* vl, int* ldvl,
                    double* vr, int* ldvr, double* work, int* lwork, int* info ); 
    */
     
    // dgeev_ is a symbol in the LAPACK library files
    extern "C" 
    {
        extern int dgeev_(char*,char*,int*,double*,int*,double*, double*, double*, int*, double*, int*, double*, int*, int*);
    }
     
     
    /* Auxiliary routines prototypes */
    extern void print_eigenvalues( char* desc, int n, double* wr, double* wi );
    extern void print_eigenvectors( char* desc, int n, double* wi, double* v, int ldv );
     
    /* Parameters */
    #define N 5
    #define LDA N
    #define LDVL N
    #define LDVR N
     
    double * ReadMatrix( char *filename, int *numRows, int *numColums)
    {
          int n,m;
          double *data;
     
          // read in a text file that contains a real matrix stored in column major format
          // but read it into row major format
          ifstream fin(filename);
     
          if (!fin.is_open()){
            cout << "Failed to open " << filename << endl;
            return NULL;
          }
     
          fin >> n >> m;  // n is the number of rows, m the number of columns
          data = new double[n*m];
          *numRows = n;
          *numColums = m;
     
          for (int i=0;i<n;i++)
          {
            for (int j=0;j<m;j++)
    	{
              // fin >> data[j*n+i];		// column order ? 
    	  fin >> data[i*n+j];		// row order ? 
            }
          }
     
          if (fin.fail() || fin.eof()){
            cout << "Error while reading " << filename << endl;
            cout << "n=" << n << " m=" << m; 
            return NULL;
          }
          fin.close();
     
          // check that matrix is square
          if (n != m){
            cout << "Matrix is not square" <<endl;
            return NULL;
          }
     
          return data;
    }
     
    void PrintMatrix( double *data, int n, int m)
    {
    	printf("Matrix %dx%d loaded \n", n, m);
    	for ( int i = 0 ; i < n ; i++ )
    	{
    		for ( int j = 0 ; j < m ; j++ )
    		{
    			// printf("%f ", data[j*n+i]);
    			printf("%.2f ", data[i*n+j]);
    		}
     
    		printf("\n");
    	}
    	printf("\n");
    }
     
     
    /* Main program */
    int main( int argc, char **argv ) 
    {
            /* Locals */
            int n = N, lda = LDA, ldvl = LDVL, ldvr = LDVR;
     
            int  info, lwork;
            double wkopt;
            double* work;
            /* Local arrays */
            double wr[N], wi[N], vl[LDVL*N], vr[LDVR*N];
     
    	char Nchar = 'N';
    	char Vchar = 'V';
     
            double a0[LDA*N] = {
               -1.01,  3.98,  3.30,  4.43,  7.31,
                0.86,  0.53,  8.26,  4.96, -6.43,
               -4.60, -7.04, -3.89, -7.66, -6.16,
                3.31,  5.29,  8.20, -7.33,  2.47,
               -4.81,  3.55, -1.51,  6.18,  5.58
            };
     
    	double *a;
    	int nRows, nColums;
     
    	/* Executable statements */
            printf( " DGEEV Example Program Results\n\n" );
     
    	if ( argc > 1 )
    	{
    		a = ReadMatrix( argv[1], &nRows, &nColums);
    		n = nRows;
    		lda = n;
    		ldvl = n;
     		ldvr = n;
    	}
    	else
    	{
    		a = a0;
    		nRows = nColums = n = N;
    		lda = LDA;
    		ldvl = LDVL;
    		ldvr = LDVR;
    	}
     
    	PrintMatrix(a, nRows, nColums);
     
     
            /* Query and allocate the optimal workspace */
            lwork = -1;
            dgeev_( "Vectors", "Vectors", &n, a, &lda, wr, wi, vl, &ldvl, vr, &ldvr, &wkopt, &lwork, &info );
            lwork = (int)wkopt;
            work = (double*)malloc( lwork*sizeof(double) );
     
            /* Solve eigenproblem */
            dgeev_( "Vectors", "Vectors", &n, a, &lda, wr, wi, vl, &ldvl, vr, &ldvr, work, &lwork, &info );
     
            /* Check for convergence */
            if( info > 0 ) {
                    printf( "The algorithm failed to compute eigenvalues.\n" );
                    exit( 1 );
            }
            /* Print eigenvalues */
            print_eigenvalues( "Eigenvalues", n, wr, wi );
            /* Print left eigenvectors */
            print_eigenvectors( "Left eigenvectors", n, wi, vl, ldvl );
            /* Print right eigenvectors */
            print_eigenvectors( "Right eigenvectors", n, wi, vr, ldvr );
            /* Free workspace */
            free( (void*)work );
            exit( 0 );
    } /* End of DGEEV Example */
     
    /* Auxiliary routine: printing eigenvalues */
    void print_eigenvalues( char* desc, int n, double* wr, double* wi ) {
            int j;
            printf( "\n %s\n", desc );
       for( j = 0; j < n; j++ ) {
          if( wi[j] == (double)0.0 ) {
             printf( " %6.2f", wr[j] );
          } else {
             printf( " (%6.2f,%6.2f)", wr[j], wi[j] );
          }
       }
       printf( "\n" );
    }
     
    /* Auxiliary routine: printing eigenvectors */
    void print_eigenvectors( char* desc, int n, double* wi, double* v, int ldv ) 
    {
            int i, j;
            printf( "\n %s\n", desc );
       for( i = 0; i < n; i++ ) {
          j = 0;
          while( j < n ) {
             if( wi[j] == (double)0.0 ) {
                printf( " %6.2f", v[i+j*ldv] );
                j++;
             } else {
                printf( " (%6.2f,%6.2f)", v[i+j*ldv], v[i+(j+1)*ldv] );
                printf( " (%6.2f,%6.2f)", v[i+j*ldv], -v[i+(j+1)*ldv] );
                j += 2;
             }g++ -o test_lapack3 test_lapack3.cpp -llapack
          }
          printf( "\n" );
       }
    }
    Le format du fichier contenant la matrice sous format texte est relativement simple avec le nombre de lignes et de colonnes indiqués à la première ligne, suivies de n Lignes de m colonnes
    => par exemple, la matrice 3x3 suivante donnée en exemple

    1 2 0
    0 3 0
    2 −4 2

    Est très simplement stockée dans le fichier matrix321.txt suivant
    (cf. le nombre de ligne et de colonnes dans la première ligne, suivie de la matrice stockée par la suite)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    3 3
    1 2 0
    0 3 0
    2 -4 2

  2. #2
    Membre régulier
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Avril 2011
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2011
    Messages : 108
    Points : 97
    Points
    97
    Par défaut
    A noter que je viens d'essayer des calculs de valeurs/vecteurs propres sur des matrices laplaciennes, cf. sur des matrices de connectivité, et que j'ai l'impression que la première valeur propre indique le nombre de sommets réellement utilisés
    (mais je n'en suis absolument pas sûr du tout, c'est juste une impression sur les 2 premier laplaciens que j'y ai testé)
    [+ les vecteurs ne semblent plus normalisés en colonne => je pensais y avoir pigé un truc ... mais en fait non )

    => quelqu'un pourrait me confirmer que la première valeur propre trouvé est le nombre de sommets utilisés et/ou m'expliquer le sens des valeurs propres suivantes ?
    (j'ai l'impression que la seconde valeur propre est toujours à 0 et n'ai strictement aucune idée du sens à donner aux valeurs propres suivantes .. et encore moins du sens que l'on pourrait donner aux vecteurs associés )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    annoo@cyclone ~/Dev/Vpropre $ ./test_lapack3 triangle.txt
     DGEEV Example Program Results
     
    Matrix 3x3 loaded 
    2.00 -1.00 -1.00 
    -1.00 2.00 -1.00 
    -1.00 -1.00 2.00 
     
     
     Eigenvalues
       3.00  -0.00   3.00
     
     Left eigenvectors
       0.76  -0.58   0.00
      -0.64  -0.58  -0.71
      -0.13  -0.58   0.71
     
     Right eigenvectors
       0.82  -0.58   0.29
      -0.41  -0.58  -0.81
      -0.41  -0.58   0.51
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    yannoo@cyclone ~/Dev/Vpropre $ ./test_lapack3 quad.txt
     DGEEV Example Program Results
     
    Matrix 4x4 loaded 
    2.00 -1.00 -1.00 0.00 
    -1.00 2.00 0.00 -1.00 
    -1.00 0.00 2.00 -1.00 
    0.00 -1.00 -1.00 2.00 
     
     
     Eigenvalues
       4.00  -0.00   2.00   2.00
     
     Left eigenvectors
      -0.50   0.50   0.58   0.00
       0.50   0.50   0.41  -0.71
       0.50   0.50  -0.41   0.71
      -0.50   0.50  -0.58   0.00
     
     Right eigenvectors
      -0.50   0.50   0.71   0.41
       0.50   0.50   0.00  -0.58
       0.50   0.50  -0.00   0.58
      -0.50   0.50  -0.71  -0.41

  3. #3
    Membre régulier
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Avril 2011
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2011
    Messages : 108
    Points : 97
    Points
    97
    Par défaut
    Je crois que je viens enfin de comprendre ce qui différencie un "vecteur gauche" d'un "vecteur droit"
    => ça dépend tout simplement si l'on veut mettre le vecteur propre X avant ou après la matrice dans l'égalité, cf. "mu * X = A * X" vs "mu * X = X * A"
    (avec mu la valeur propre, A la matrice testée et X le vecteur propre)

    J'ai de plus lu qu'il fallait ordonner les valeurs propres de la plus petite à la plus grande, cf. modifier l'ordre d'arrivée de valeurs propres afin que mu0 <= mu1 <= mu2 <= ...
    (ainsi que l'ordre des vecteurs propres associés avec bien sûr)

    Par exemple, pour la matrice laplacienne ultra-basique d'un triangle, où la diagonale est composée de 2 car chaque sommet est relié à 2 autres et où les autres valeurs sont à -1 car chaque sommet d'un triangle est rélié aux 2 autres sommets restants du triangle

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    2.00 -1.00 -1.00 
    -1.00 2.00 -1.00 
    -1.00 -1.00 2.00
    => le spectre de cette matrice est { -0.00 , 3.00 } dont la première valeur propre est -0.00 avec une multiplicité de 1 , l'autre valeur propre étant de 3.00 avec une multiplicité de 2

    Par contre, toujours pas compris comment on peut en extraire le nombre de composantes convexes qui devrait ici être de 1 car un seul triangle qui ne peut être que convexe dans cette exemple

    => c'est pourquoi j'ai testé avec un combo triangle + carré comprenant donc 2 composantes convexes (un carré + 1 triangle distincts = 2 composantes convexes)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    2.00 -1.00 -1.00 0.00 0.00 0.00 0.00 
    -1.00 2.00 0.00 -1.00 0.00 0.00 0.00 
    -1.00 0.00 2.00 -1.00 0.00 0.00 0.00 
    0.00 -1.00 -1.00 2.00 0.00 0.00 0.00 
    0.00 0.00 0.00 0.00 2.00 -1.00 -1.00 
    0.00 0.00 0.00 0.00 -1.00 2.00 -1.00 
    0.00 0.00 0.00 0.00 -1.00 -1.00 2.00
    => ses valeurs propres triées sont mu0=0.0 de multiplicité 3, mu1=2.0 de multiplicité 2, mu2=3.0 de multplicité 1 et mu3=4.0 de multiplicité 1
    ==> le nombre de composantes convexes est-il bien la première valeur propre <> 0 et/ou la multiplicité de la première valeur propre <> 0 ?
    (vu que l'on s'attend à un nombre entier, j'aurais tendance à penser que c'est la multiplicité de la première valeur propre <> 0 mais dans le doute + ça ne marche pas avec le cas du simple triangle ...)

Discussions similaires

  1. Réponses: 1
    Dernier message: 18/10/2014, 17h27
  2. Code des valeurs propres d'une matrice carrée
    Par janot92 dans le forum Fortran
    Réponses: 3
    Dernier message: 07/05/2013, 15h55
  3. Réponses: 42
    Dernier message: 28/05/2012, 16h52
  4. Réponses: 3
    Dernier message: 14/06/2009, 23h17
  5. Calcul rapide des valeurs propres d'une matrice creuse
    Par gsagnol dans le forum Mathématiques
    Réponses: 3
    Dernier message: 21/12/2007, 23h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo