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