This repository has been archived by the owner on Dec 31, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathjacobi_eig.m
111 lines (104 loc) · 2.99 KB
/
jacobi_eig.m
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
function A = jacobi_eig(A, method, tol)
% JACOBI_EIG Solve symmetric eigenvalue problem using Jacobi method
%
% Here, the function computes eigenvalues and corresponding eigenvectors using
% Jacobi method. For experimentation, three method ('classic', 'cyclic',
% 'threshold') can be chosen.
%
% argin:
% A: The input matrix (must be real-symmetric)
% method (optional): One of 'classic', 'cyclic' and 'threshold' (default:
% 'threshold')
% tol (optional): Stopping criteria
%
% usage:
% lambda = JACOBI_EIG(A)
% Only gets eigenvalues: lambda = [l1, l2, ..., ln]
% [lambda, V] = JACOBI_EIG(A)
% Computes eigenvalues and corresponding eigenvectors, here A =
% V'*diag(lambda)*V
%
% -------------------------------------------------
% Experiments on Matrix Computations -- Spring 2018
% Author: Zilong Liang
% Date: 2018-05-31
% -------------------------------------------------
% Check inputs
if nargin < 2
method = 'threshold';
end
if nargin < 3
if strcmp(method, 'threshold')
tol = 1e-14;
else
tol = 1e-7;
end
end
% Initialize
n = length(A);
if nargout == 2
V = eye(n);
end
if strcmp(method, 'classic')
omega = norm(A, 'fro');
eta = tol * omega;
omega = sqrt(omega^2 - sum(diag(A).^2));
while omega > eta
[a, p] = max(abs(A - diag(diag(A))));
[~, q] = max(a);
p = p(q);
if p > q
temp = p;
p = q;
q = temp;
end
apq = A(p, q);
G = jacobi(A(p, p), apq, A(q, q));
A(:, [p, q]) = A(:, [p, q]) * G;
A([p, q], :) = G' * A([p, q], :);
if nargout == 2
V(:, [p, q]) = V(:, [p, q]) * G;
end
omega = sqrt(omega^2 - 2 * apq^2);
end
elseif strcmp(method, 'cyclic')
omega = norm(A, 'fro');
eta = tol * omega;
omega = sqrt(omega^2 - sum(diag(A).^2));
while omega > eta
for p = 1:n-1
for q = p+1:n
G = jacobi(A(p, p), A(p, q), A(q, q));
A(:, [p, q]) = A(:, [p, q]) * G;
A([p, q], :) = G' * A([p, q], :);
if nargout == 2
V(:, [p, q]) = V(:, [p, q]) * G;
end
end
end
omega = sqrt(norm(A, 'fro')^2 - sum(diag(A).^2));
end
elseif strcmp(method, 'threshold')
rots = 1;
while rots >= 1
rots = 0;
for p = 1:n-1
for q = p+1:n
apq = A(p, q);
app = A(p, p);
aqq = A(q, q);
if abs(apq) >= tol * sqrt(app * aqq)
rots = rots + 1;
G = jacobi(app, apq, aqq);
A(:, [p, q]) = A(:, [p, q]) * G;
A([p, q], :) = G' * A([p, q], :);
if nargout == 2
V(:, [p, q]) = V(:, [p, q]) * G;
end
end
end
end
end
else
error('Choose method among ''classic'', ''cyclic'' and ''threshold''');
end