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
11 real tol,
12 idx max_iter,
13 Backend backend) {
14 constexpr real tiny = 1e-300;
15 const idx n = A.rows();
16 if (A.cols() != n)
17 throw std::invalid_argument("power_iteration: matrix must be square");
18
19 Vector v(n, 0.0);
20 v[0] = 1.0;
21
22 real lambda = 0.0;
23 PowerResult result{0.0, v, 0, false};
24
25 for (idx iter = 0; iter < max_iter; ++iter) {
26 result.iterations = iter + 1;
27
28 Vector w(n);
29 matvec(A, v, w, backend);
30
31 real new_lambda = dot(v, w, backend);
33
34 real delta = std::abs(new_lambda - lambda);
35 lambda = new_lambda;
36 v = w;
37
38 if (delta < tol * (std::abs(lambda) + tiny)) {
39 result.converged = true;
40 break;
41 }
42 }
43
44 result.eigenvalue = lambda;
45 result.eigenvector = v;
46 return result;
47}
48
50 real sigma,
51 real tol,
52 idx max_iter,
53 Backend backend) {
54 constexpr real tiny = 1e-300;
55 const idx n = A.rows();
56 if (A.cols() != n)
57 throw std::invalid_argument("inverse_iteration: matrix must be square");
58
59 // Factorize (A - sigma*I) once
60 Matrix M = A;
61 for (idx i = 0; i < n; ++i)
62 M(i, i) -= sigma;
63 LUResult f = lu(M);
64
65 Vector v(n, 0.0);
66 v[0] = 1.0;
67
68 real lambda = 0.0;
69 PowerResult result{0.0, v, 0, false};
70
71 for (idx iter = 0; iter < max_iter; ++iter) {
72 result.iterations = iter + 1;
73
74 Vector w(n);
75 lu_solve(f, v, w);
77
78 // Rayleigh quotient as eigenvalue estimate
79 Vector Av(n);
80 matvec(A, w, Av, backend);
81 real new_lambda = dot(w, Av, backend);
82
83 real delta = std::abs(new_lambda - lambda);
84 lambda = new_lambda;
85 v = w;
86
87 if (delta < tol * (std::abs(lambda) + tiny)) {
88 result.converged = true;
89 break;
90 }
91 }
92
93 result.eigenvalue = lambda;
94 result.eigenvector = v;
95 return result;
96}
97
99 const Vector& x0,
100 real tol,
101 idx max_iter,
102 Backend backend) {
103 const idx n = A.rows();
104 if (A.cols() != n)
105 throw std::invalid_argument(
106 "rayleigh_iteration: matrix must be square");
107 if (x0.size() != n)
108 throw std::invalid_argument("rayleigh_iteration: x0 size mismatch");
109
110 Vector v = x0;
112
113 // Initial Rayleigh quotient
114 Vector Av(n);
115 matvec(A, v, Av, backend);
116 real sigma = dot(v, Av, backend);
117
118 PowerResult result{sigma, v, 0, false};
119
120 for (idx iter = 0; iter < max_iter; ++iter) {
121 result.iterations = iter + 1;
122
123 // Factorize (A - sigma*I); fresh each iteration (cubic convergence)
124 Matrix M = A;
125 for (idx i = 0; i < n; ++i)
126 M(i, i) -= sigma;
127 LUResult f = lu(M);
128
129 if (f.singular)
130 break;
131
132 Vector w(n);
133 lu_solve(f, v, w);
135
136 matvec(A, w, Av, backend);
137 real new_sigma = dot(w, Av, backend);
138
139 // Residual: ||A*v - sigma*v||
140 real res = 0;
141 for (idx i = 0; i < n; ++i) {
142 real d = Av[i] - new_sigma * w[i];
143 res += d * d;
144 }
145 res = std::sqrt(res);
146
147 sigma = new_sigma;
148 v = w;
149
150 if (res < tol) {
151 result.converged = true;
152 break;
153 }
154 }
155
156 result.eigenvalue = sigma;
157 result.eigenvector = v;
158 return result;
159}
160
161} // namespace num
constexpr idx size() const noexcept
Definition vector.hpp:80
Dense row-major matrix with optional GPU storage.
Definition matrix.hpp:12
constexpr idx rows() const noexcept
Definition matrix.hpp:24
constexpr idx cols() const noexcept
Definition matrix.hpp:25
real normalise(Vector &v)
Normalise v in-place; returns the old norm.
Definition power.hpp:34
double real
Definition types.hpp:10
Backend
Selects which backend handles a linalg operation.
Definition policy.hpp:19
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:120
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:49
real dot(const Vector &x, const Vector &y, Backend b=default_backend)
dot product
Definition vector.cpp:79
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:43
void lu_solve(const LUResult &f, const Vector &b, Vector &x)
Solve A*x = b using a precomputed LU factorization.
Definition lu.cpp:28
LUResult lu(const Matrix &A, Backend backend=lapack_backend)
LU factorization of a square matrix A with partial pivoting.
Definition lu.cpp:17
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:98
Power iteration, inverse iteration, Rayleigh quotient iteration.
Result of an LU factorization with partial pivoting (PA = LU)
Definition lu.hpp:19
bool singular
Definition lu.hpp:22
Result of a single-eigenvalue iteration.
Definition power.hpp:25