Compute real eigen values and eigen vectors of a symmetric matrix using QR decomposition method.
More...
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "qr_decompose.h"
|
#define | LIMS 9 |
| limit of range of matrix values
|
|
#define | EPSILON 1e-10 |
| accuracy tolerance limit
|
|
|
void | create_matrix (double **A, int N) |
| create a square matrix of given size with random elements More...
|
|
double ** | mat_mul (double **A, double **B, double **OUT, int R1, int C1, int R2, int C2) |
| Perform multiplication of two matrices. More...
|
|
double | eigen_values (double **A, double *eigen_vals, int mat_size, char debug_print) |
| Compute eigen values using iterative shifted QR decomposition algorithm as follows: More...
|
|
void | test1 () |
| test function to compute eigen values of a 2x2 matrix More...
|
|
void | test2 () |
| test function to compute eigen values of a 2x2 matrix More...
|
|
int | main (int argc, char **argv) |
| main function
|
|
Compute real eigen values and eigen vectors of a symmetric matrix using QR decomposition method.
- Author
- Krishna Vedala
◆ create_matrix()
void create_matrix |
( |
double ** |
A, |
|
|
int |
N |
|
) |
| |
create a square matrix of given size with random elements
- Parameters
-
[out] | A | matrix to create (must be pre-allocated in memory) |
[in] | N | matrix size |
29 int i, j, tmp, lim2 =
LIMS >> 1;
34 for (i = 0; i < N; i++)
36 A[i][i] = (rand() %
LIMS) - lim2;
37 for (j = i + 1; j < N; j++)
39 tmp = (rand() %
LIMS) - lim2;
◆ eigen_values()
double eigen_values |
( |
double ** |
A, |
|
|
double * |
eigen_vals, |
|
|
int |
mat_size, |
|
|
char |
debug_print |
|
) |
| |
Compute eigen values using iterative shifted QR decomposition algorithm as follows:
- Use last diagonal element of A as eigen value approximation \(c\)
- Shift diagonals of matrix \(A' = A - cI\)
- Decompose matrix \(A'=QR\)
- Compute next approximation \(A'_1 = RQ \)
- Shift diagonals back \(A_1 = A'_1 + cI\)
- Termination condition check: last element below diagonal is almost 0
- If not 0, go back to step 1 with the new approximation \(A_1\)
- If 0, continue to step 7
- Save last known \(c\) as the eigen value.
- Are all eigen values found?
- If not, remove last row and column of \(A_1\) and go back to step 1.
- If yes, stop.
- Note
- The matrix \(A\) gets modified
- Parameters
-
[in,out] | A | matrix to compute eigen values for |
[out] | eigen_vals | resultant vector containing computed eigen values |
[in] | mat_size | matrix size |
[in] | debug_print | 1 to print intermediate Q & R matrices, 0 for not to |
- Returns
- time for computation in seconds
111 perror(
"Output eigen value vector cannot be NULL!");
114 double **R = (
double **)malloc(
sizeof(
double *) * mat_size);
115 double **Q = (
double **)malloc(
sizeof(
double *) * mat_size);
118 perror(
"Unable to allocate memory for Q & R!");
131 for (
int i = 0; i < mat_size; i++)
133 R[i] = (
double *)malloc(
sizeof(
double) * mat_size);
134 Q[i] = (
double *)malloc(
sizeof(
double) * mat_size);
137 perror(
"Unable to allocate memory for Q & R.");
154 int rows = mat_size, columns = mat_size;
155 int counter = 0, num_eigs = rows - 1;
158 clock_t t1 = clock();
162 while (fabs(A[num_eigs][num_eigs - 1]) >
EPSILON)
164 last_eig = A[num_eigs][num_eigs];
165 for (
int i = 0; i < rows; i++) A[i][i] -= last_eig;
173 printf(
"-------------------- %d ---------------------\n",
177 mat_mul(R, Q, A, columns, columns, rows, columns);
178 for (
int i = 0; i < rows; i++) A[i][i] += last_eig;
182 eigen_vals[num_eigs] = last_eig;
186 printf(
"========================\n");
187 printf(
"Eigen value: % g,\n", last_eig);
188 printf(
"========================\n");
195 eigen_vals[0] = A[0][0];
196 double dtime = (double)(clock() - t1) / CLOCKS_PER_SEC;
205 for (
int i = 0; i < mat_size; i++)
◆ mat_mul()
double** mat_mul |
( |
double ** |
A, |
|
|
double ** |
B, |
|
|
double ** |
OUT, |
|
|
int |
R1, |
|
|
int |
C1, |
|
|
int |
R2, |
|
|
int |
C2 |
|
) |
| |
Perform multiplication of two matrices.
- R2 must be equal to C1
- Resultant matrix size should be R1xC2
- Parameters
-
[in] | A | first matrix to multiply |
[in] | B | second matrix to multiply |
[out] | OUT | output matrix (must be pre-allocated) |
[in] | R1 | number of rows of first matrix |
[in] | C1 | number of columns of first matrix |
[in] | R2 | number of rows of second matrix |
[in] | C2 | number of columns of second matrix |
- Returns
- pointer to resultant matrix
64 perror(
"Matrix dimensions mismatch!");
72 for (i = 0; i < R1; i++)
74 for (
int j = 0; j < C2; j++)
77 for (
int k = 0; k < C1; k++) OUT[i][j] += A[i][k] * B[k][j];
◆ test1()
test function to compute eigen values of a 2x2 matrix
\[\begin{bmatrix} 5 & 7\\ 7 & 11 \end{bmatrix}\]
which are approximately, {15.56158, 0.384227}
227 double X[][2] = {{5, 7}, {7, 11}};
228 double y[] = {15.56158, 0.384227};
229 double eig_vals[2] = {0, 0};
232 double **A = (
double **)malloc(mat_size *
sizeof(
double *));
233 for (
int i = 0; i < mat_size; i++) A[i] = X[i];
235 printf(
"------- Test 1 -------\n");
239 for (
int i = 0; i < mat_size; i++)
241 printf(
"%d/5 Checking for %.3g --> ", i + 1, y[i]);
243 for (
int j = 0; j < mat_size && !result; j++)
245 if (fabs(y[i] - eig_vals[j]) < 0.1)
248 printf(
"(%.3g) ", eig_vals[j]);
256 printf(
"Test 1 Passed in %.3g sec\n\n", dtime);
◆ test2()
test function to compute eigen values of a 2x2 matrix
\[\begin{bmatrix} -4& 4& 2& 0& -3\\ 4& -4& 4& -3& -1\\ 2& 4& 4& 3& -3\\ 0& -3& 3& -1&-1\\ -3& -1& -3& -3& 0 \end{bmatrix}\]
which are approximately, {9.27648, -9.26948, 2.0181, -1.03516, -5.98994}
274 double X[][5] = {{-4, 4, 2, 0, -3},
278 {-3, -1, -3, -3, 0}};
279 double y[] = {9.27648, -9.26948, 2.0181, -1.03516,
284 double **A = (
double **)malloc(mat_size *
sizeof(
double *));
285 for (
int i = 0; i < mat_size; i++) A[i] = X[i];
287 printf(
"------- Test 2 -------\n");
291 for (
int i = 0; i < mat_size; i++)
293 printf(
"%d/5 Checking for %.3g --> ", i + 1, y[i]);
295 for (
int j = 0; j < mat_size && !result; j++)
297 if (fabs(y[i] - eig_vals[j]) < 0.1)
300 printf(
"(%.3g) ", eig_vals[j]);
308 printf(
"Test 2 Passed in %.3g sec\n\n", dtime);