TheAlgorithms/C++
1.0.0
All the algorithms implemented in C++
Toggle main menu visibility
Loading...
Searching...
No Matches
qr_eigen_values.cpp
Go to the documentation of this file.
1
8
#include <cassert>
9
#include <cmath>
10
#include <cstdlib>
11
#include <ctime>
12
#include <iostream>
13
#ifdef _OPENMP
14
#include <omp.h>
15
#endif
16
17
#include "
./qr_decompose.h
"
18
using
qr_algorithm::operator<<;
19
20
#define LIMS 9
21
28
void
create_matrix
(std::valarray<std::valarray<double>> *A) {
29
int
i, j, tmp, lim2 =
LIMS
>> 1;
30
int
N = A->size();
31
32
#ifdef _OPENMP
33
#pragma omp for
34
#endif
35
for
(i = 0; i < N; i++) {
36
A[0][i][i] = (std::rand() %
LIMS
) - lim2;
37
for
(j = i + 1; j < N; j++) {
38
tmp = (std::rand() %
LIMS
) - lim2;
39
A[0][i][j] = tmp;
// summetrically distribute random values
40
A[0][j][i] = tmp;
41
}
42
}
43
}
44
54
void
mat_mul
(
const
std::valarray<std::valarray<double>> &A,
55
const
std::valarray<std::valarray<double>> &B,
56
std::valarray<std::valarray<double>> *OUT) {
57
int
R1 = A.size();
58
int
C1 = A[0].size();
59
int
R2 = B.size();
60
int
C2 = B[0].size();
61
if
(C1 != R2) {
62
perror(
"Matrix dimensions mismatch!"
);
63
return
;
64
}
65
66
for
(
int
i = 0; i < R1; i++) {
67
for
(
int
j = 0; j < C2; j++) {
68
OUT[0][i][j] = 0.f;
69
for
(
int
k = 0; k < C1; k++) {
70
OUT[0][i][j] += A[i][k] * B[k][j];
71
}
72
}
73
}
74
}
75
76
namespace
qr_algorithm
{
98
std::valarray<double>
eigen_values
(std::valarray<std::valarray<double>> *A,
99
bool
print_intermediates =
false
) {
100
int
rows = A->size();
101
int
columns = rows;
102
int
counter = 0, num_eigs = rows - 1;
103
double
last_eig = 0;
104
105
std::valarray<std::valarray<double>> Q(rows);
106
std::valarray<std::valarray<double>> R(columns);
107
108
/* number of eigen values = matrix size */
109
std::valarray<double> eigen_vals(rows);
110
for
(
int
i = 0; i < rows; i++) {
111
Q[i] = std::valarray<double>(columns);
112
R[i] = std::valarray<double>(columns);
113
}
114
115
/* continue till all eigen values are found */
116
while
(num_eigs > 0) {
117
/* iterate with QR decomposition */
118
while
(std::abs(A[0][num_eigs][num_eigs - 1]) >
119
std::numeric_limits<double>::epsilon()) {
120
// initial approximation = last diagonal element
121
last_eig = A[0][num_eigs][num_eigs];
122
for
(
int
i = 0; i < rows; i++) {
123
A[0][i][i] -= last_eig;
/* A - cI */
124
}
125
126
qr_decompose
(*A, &Q, &R);
127
128
if
(print_intermediates) {
129
std::cout << *A <<
"\n"
;
130
std::cout << Q <<
"\n"
;
131
std::cout << R <<
"\n"
;
132
printf(
"-------------------- %d ---------------------\n"
,
133
++counter);
134
}
135
136
// new approximation A' = R * Q
137
mat_mul
(R, Q, A);
138
139
for
(
int
i = 0; i < rows; i++) {
140
A[0][i][i] += last_eig;
/* A + cI */
141
}
142
}
143
144
/* store the converged eigen value */
145
eigen_vals[num_eigs] = last_eig;
146
// A[0][num_eigs][num_eigs];
147
if
(print_intermediates) {
148
std::cout <<
"========================\n"
;
149
std::cout <<
"Eigen value: "
<< last_eig <<
",\n"
;
150
std::cout <<
"========================\n"
;
151
}
152
153
num_eigs--;
154
rows--;
155
columns--;
156
}
157
eigen_vals[0] = A[0][0][0];
158
159
if
(print_intermediates) {
160
std::cout << Q <<
"\n"
;
161
std::cout << R <<
"\n"
;
162
}
163
164
return
eigen_vals;
165
}
166
167
}
// namespace qr_algorithm
168
177
void
test1
() {
178
std::valarray<std::valarray<double>> X = {{5, 7}, {7, 11}};
179
double
y[] = {15.56158, 0.384227};
// corresponding y-values
180
181
std::cout <<
"------- Test 1 -------"
<< std::endl;
182
std::valarray<double> eig_vals =
qr_algorithm::eigen_values
(&X);
183
184
for
(
int
i = 0; i < 2; i++) {
185
std::cout << i + 1 <<
"/2 Checking for "
<< y[i] <<
" --> "
;
186
bool
result =
false
;
187
for
(
int
j = 0; j < 2 && !result; j++) {
188
if
(std::abs(y[i] - eig_vals[j]) < 0.1) {
189
result =
true
;
190
std::cout <<
"("
<< eig_vals[j] <<
") "
;
191
}
192
}
193
assert(result);
// ensure that i^th expected eigen value was computed
194
std::cout <<
"found\n"
;
195
}
196
std::cout <<
"Test 1 Passed\n\n"
;
197
}
198
210
void
test2
() {
211
std::valarray<std::valarray<double>> X = {{-4, 4, 2, 0, -3},
212
{4, -4, 4, -3, -1},
213
{2, 4, 4, 3, -3},
214
{0, -3, 3, -1, -3},
215
{-3, -1, -3, -3, 0}};
216
double
y[] = {9.27648, -9.26948, 2.0181, -1.03516,
217
-5.98994};
// corresponding y-values
218
219
std::cout <<
"------- Test 2 -------"
<< std::endl;
220
std::valarray<double> eig_vals =
qr_algorithm::eigen_values
(&X);
221
222
std::cout << X <<
"\n"
223
<<
"Eigen values: "
<< eig_vals <<
"\n"
;
224
225
for
(
int
i = 0; i < 5; i++) {
226
std::cout << i + 1 <<
"/5 Checking for "
<< y[i] <<
" --> "
;
227
bool
result =
false
;
228
for
(
int
j = 0; j < 5 && !result; j++) {
229
if
(std::abs(y[i] - eig_vals[j]) < 0.1) {
230
result =
true
;
231
std::cout <<
"("
<< eig_vals[j] <<
") "
;
232
}
233
}
234
assert(result);
// ensure that i^th expected eigen value was computed
235
std::cout <<
"found\n"
;
236
}
237
std::cout <<
"Test 2 Passed\n\n"
;
238
}
239
243
int
main
(
int
argc,
char
**argv) {
244
int
mat_size
= 5;
245
if
(argc == 2) {
246
mat_size
= atoi(argv[1]);
247
}
else
{
// if invalid input argument is given run tests
248
test1
();
249
test2
();
250
std::cout <<
"Usage: ./qr_eigen_values [mat_size]\n"
;
251
return
0;
252
}
253
254
if
(
mat_size
< 2) {
255
fprintf(stderr,
"Matrix size should be > 2\n"
);
256
return
-1;
257
}
258
259
// initialize random number generator
260
std::srand(std::time(
nullptr
));
261
262
int
i, rows =
mat_size
, columns =
mat_size
;
263
264
std::valarray<std::valarray<double>> A(rows);
265
266
for
(
int
i = 0; i < rows; i++) {
267
A[i] = std::valarray<double>(columns);
268
}
269
270
/* create a random matrix */
271
create_matrix
(&A);
272
273
std::cout << A <<
"\n"
;
274
275
clock_t t1 = clock();
276
std::valarray<double> eigen_vals =
qr_algorithm::eigen_values
(&A);
277
double
dtime =
static_cast<
double
>
(clock() - t1) / CLOCKS_PER_SEC;
278
279
std::cout <<
"Eigen vals: "
;
280
for
(i = 0; i <
mat_size
; i++) std::cout << eigen_vals[i] <<
"\t"
;
281
std::cout <<
"\nTime taken to compute: "
<< dtime <<
" sec\n"
;
282
283
return
0;
284
}
main
int main()
Main function.
Definition
generate_parentheses.cpp:110
test2
void test2(const std::string &text)
Self test 2 - using 8x8 randomly generated key.
Definition
hill_cipher.cpp:505
test1
void test1(const std::string &text)
Self test 1 - using 3x3 randomly generated key.
Definition
hill_cipher.cpp:470
mat_size
ll mat_size
Definition
matrix_exponentiation.cpp:45
qr_algorithm
Functions to compute QR decomposition of any rectangular matrix.
qr_algorithm::eigen_values
std::valarray< double > eigen_values(std::valarray< std::valarray< double > > *A, bool print_intermediates=false)
Definition
qr_eigen_values.cpp:98
qr_algorithm::qr_decompose
void qr_decompose(const std::valarray< std::valarray< T > > &A, std::valarray< std::valarray< T > > *Q, std::valarray< std::valarray< T > > *R)
Definition
qr_decompose.h:146
qr_decompose.h
Library functions to compute QR decomposition of a given matrix.
create_matrix
void create_matrix(std::valarray< std::valarray< double > > *A)
Definition
qr_eigen_values.cpp:28
mat_mul
void mat_mul(const std::valarray< std::valarray< double > > &A, const std::valarray< std::valarray< double > > &B, std::valarray< std::valarray< double > > *OUT)
Definition
qr_eigen_values.cpp:54
LIMS
#define LIMS
Definition
qr_eigen_values.cpp:20
numerical_methods
qr_eigen_values.cpp
Generated by
1.18.0