numerics 0.1.0
Loading...
Searching...
No Matches
power.cpp
Go to the documentation of this file.
1/// @file eigen/power.cpp
2/// @brief Power iteration, inverse iteration, Rayleigh quotient iteration
3
5#include <cmath>
6#include <stdexcept>
7
8namespace num {
9
10PowerResult power_iteration(const Matrix& A, real tol, idx max_iter, Backend backend) {
11 constexpr real tiny = 1e-300;
12 const idx n = A.rows();
13 if (A.cols() != n)
14 throw std::invalid_argument("power_iteration: matrix must be square");
15
16 Vector v(n, 0.0);
17 v[0] = 1.0;
18
19 real lambda = 0.0;
20 PowerResult result{0.0, v, 0, false};
21
22 for (idx iter = 0; iter < max_iter; ++iter) {
23 result.iterations = iter + 1;
24
25 Vector w(n);
26 matvec(A, v, w, backend);
27
28 real new_lambda = dot(v, w, backend);
30
31 real delta = std::abs(new_lambda - lambda);
32 lambda = new_lambda;
33 v = w;
34
35 if (delta < tol * (std::abs(lambda) + tiny)) {
36 result.converged = true;
37 break;
38 }
39 }
40
41 result.eigenvalue = lambda;
42 result.eigenvector = v;
43 return result;
44}
45
47 real sigma,
48 real tol,
49 idx max_iter,
50 Backend backend) {
51 constexpr real tiny = 1e-300;
52 const idx n = A.rows();
53 if (A.cols() != n)
54 throw std::invalid_argument("inverse_iteration: matrix must be square");
55
56 // Factorize (A - sigma*I) once
57 Matrix M = A;
58 for (idx i = 0; i < n; ++i)
59 M(i, i) -= sigma;
60 LUResult f = lu(M);
61
62 Vector v(n, 0.0);
63 v[0] = 1.0;
64
65 real lambda = 0.0;
66 PowerResult result{0.0, v, 0, false};
67
68 for (idx iter = 0; iter < max_iter; ++iter) {
69 result.iterations = iter + 1;
70
71 Vector w(n);
72 lu_solve(f, v, w);
74
75 // Rayleigh quotient as eigenvalue estimate
76 Vector Av(n);
77 matvec(A, w, Av, backend);
78 real new_lambda = dot(w, Av, backend);
79
80 real delta = std::abs(new_lambda - lambda);
81 lambda = new_lambda;
82 v = w;
83
84 if (delta < tol * (std::abs(lambda) + tiny)) {
85 result.converged = true;
86 break;
87 }
88 }
89
90 result.eigenvalue = lambda;
91 result.eigenvector = v;
92 return result;
93}
94
96 const Vector& x0,
97 real tol,
98 idx max_iter,
99 Backend backend) {
100 const idx n = A.rows();
101 if (A.cols() != n)
102 throw std::invalid_argument("rayleigh_iteration: matrix must be square");
103 if (x0.size() != n)
104 throw std::invalid_argument("rayleigh_iteration: x0 size mismatch");
105
106 Vector v = x0;
108
109 // Initial Rayleigh quotient
110 Vector Av(n);
111 matvec(A, v, Av, backend);
112 real sigma = dot(v, Av, backend);
113
114 PowerResult result{sigma, v, 0, false};
115
116 for (idx iter = 0; iter < max_iter; ++iter) {
117 result.iterations = iter + 1;
118
119 // Factorize (A - sigma*I); fresh each iteration (cubic convergence)
120 Matrix M = A;
121 for (idx i = 0; i < n; ++i)
122 M(i, i) -= sigma;
123 LUResult f = lu(M);
124
125 if (f.singular)
126 break;
127
128 Vector w(n);
129 lu_solve(f, v, w);
131
132 matvec(A, w, Av, backend);
133 real new_sigma = dot(w, Av, backend);
134
135 // Residual: ||A*v - sigma*v||
136 real res = 0;
137 for (idx i = 0; i < n; ++i) {
138 real d = Av[i] - new_sigma * w[i];
139 res += d * d;
140 }
141 res = std::sqrt(res);
142
143 sigma = new_sigma;
144 v = w;
145
146 if (res < tol) {
147 result.converged = true;
148 break;
149 }
150 }
151
152 result.eigenvalue = sigma;
153 result.eigenvector = v;
154 return result;
155}
156
157} // namespace num
constexpr idx rows() const noexcept
Definition matrix.hpp:87
constexpr idx cols() const noexcept
Definition matrix.hpp:88
constexpr idx size() const noexcept
Definition vector.hpp:83
real normalise(Vector &v)
Normalise v in-place; returns the old norm.
Definition power.hpp:34
double real
Definition types.hpp:10
Backend
Definition policy.hpp:7
std::size_t idx
Definition types.hpp:11
void matvec(const Matrix &A, const Vector &x, Vector &y, Backend b=default_backend)
y = A * x
Definition matrix.cpp:45
PowerResult inverse_iteration(const Matrix &A, real sigma, real tol=1e-10, idx max_iter=1000, Backend backend=default_backend)
Inverse iteration – finds the eigenvalue closest to a shift sigma.
Definition power.cpp:46
real dot(const Vector &x, const Vector &y, Backend b=default_backend)
Compute .
Definition vector.cpp:65
PowerResult power_iteration(const Matrix &A, real tol=1e-10, idx max_iter=1000, Backend backend=default_backend)
Power iteration – finds the eigenvalue largest in absolute value.
Definition power.cpp:10
constexpr real e
Definition math.hpp:44
void lu_solve(const LUResult &f, const Vector &b, Vector &x)
Solve from a precomputed factorization.
Definition lu.cpp:19
LUResult lu(const Matrix &A, Backend backend=lapack_backend)
Definition lu.cpp:10
PowerResult rayleigh_iteration(const Matrix &A, const Vector &x0, real tol=1e-10, idx max_iter=50, Backend backend=default_backend)
Rayleigh quotient iteration – cubically convergent.
Definition power.cpp:95
Power iteration, inverse iteration, Rayleigh quotient iteration.
Packed factorization .
Definition lu.hpp:12
bool singular
Definition lu.hpp:15
Result of a single-eigenvalue iteration.
Definition power.hpp:25