numerics 0.1.0
Loading...
Searching...
No Matches
Linear Algebra Examples

Direct solvers, Krylov iterations, eigenvalue routines, SVD, and matrix functions use explicit numerical routine names. Operator arguments enter where only the action (y = Ax) is required.

Dense Direct Solve

#include <numerics.hpp>
num::Matrix A(3, 3, 0.0);
A(0, 0) = 4.0; A(0, 1) = 1.0; A(0, 2) = 0.0;
A(1, 0) = 1.0; A(1, 1) = 3.0; A(1, 2) = 1.0;
A(2, 0) = 0.0; A(2, 1) = 1.0; A(2, 2) = 2.0;
num::Vector b{1.0, 2.0, 0.0};
auto F = num::lu(A);
num::lu_solve(F, b, x);
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
Umbrella include for the numerics library.

Use lu_solve(F, B, X) for multiple right-hand sides after one factorization.

For \(A=A^T>0\):

auto Aspd = num::linalg::make_spd(A);
auto C = num::cholesky(Aspd);
num::Vector x_spd(A.rows(), 0.0);
num::cholesky_solve(C, b, x_spd);
SPDMatrix< Matrix > make_spd(Matrix A, real tol=1e-12)
CholeskyResult cholesky(const linalg::SPDMatrix< Matrix > &A)
Definition cholesky.cpp:7
void cholesky_solve(const CholeskyResult &f, const Vector &b, Vector &x)
Definition cholesky.cpp:40

Use num::linalg::assume_spd(A) when the construction of \(A\) already guarantees symmetry and positive definiteness.

Least Squares

num::Matrix A(4, 2, 0.0);
A(0, 0) = 1.0; A(0, 1) = 0.0;
A(1, 0) = 1.0; A(1, 1) = 1.0;
A(2, 0) = 1.0; A(2, 1) = 2.0;
A(3, 0) = 1.0; A(3, 1) = 3.0;
num::Vector b{1.0, 2.0, 2.0, 4.0};
auto Q = num::qr(A);
num::qr_solve(Q, b, coeff);
void qr_solve(const QRResult &f, const Vector &b, Vector &x)
Solve .
Definition qr.cpp:19
QRResult qr(const Matrix &A, Backend backend=lapack_backend)
Factor as .
Definition qr.cpp:10

This computes the minimizer of (|Ax-b|_2).

Tridiagonal and Banded Systems

const num::idx n = 128;
num::Vector a(n - 1, -1.0);
num::Vector d(n, 2.0);
num::Vector c(n - 1, -1.0);
num::Vector rhs(n, 1.0);
num::thomas(a, d, c, rhs, x);
std::size_t idx
Definition types.hpp:11
void thomas(const Vector &a, const Vector &b, const Vector &c, const Vector &d, Vector &x, Backend backend=lapack_backend)
Definition thomas.cpp:12

For general banded storage:

num::BandedMatrix A(n, 1, 1);
for (num::idx i = 0; i < n; ++i) {
A(i, i) = 2.0;
if (i > 0) A(i, i - 1) = -1.0;
if (i + 1 < n) A(i, i + 1) = -1.0;
}
auto info = num::banded_solve(A, rhs, xb);
LAPACK-style band storage.
Definition banded.hpp:16
BandedSolverResult banded_solve(const BandedMatrix &A, const Vector &b, Vector &x)
Factor and solve .
Definition banded.cpp:281

Sparse Krylov Solve

std::vector<num::idx> rows, cols;
std::vector<num::real> vals;
auto push = [&](num::idx i, num::idx j, num::real v) {
rows.push_back(i);
cols.push_back(j);
vals.push_back(v);
};
for (num::idx i = 0; i < n; ++i) {
push(i, i, 2.0);
if (i > 0) push(i, i - 1, -1.0);
if (i + 1 < n) push(i, i + 1, -1.0);
}
num::Vector x(n, 0.0);
num::cg(num::operators::assume_spd(Aop), rhs, x, 1e-10, 1000);
Sparse matrix in Compressed Sparse Row (CSR) format.
Definition sparse.hpp:17
static SparseMatrix from_triplets(idx n_rows, idx n_cols, const std::vector< idx > &rows, const std::vector< idx > &cols, const std::vector< real > &vals)
Build from coordinate (COO / triplet) lists.
Definition sparse.cpp:25
SPDOp< Op > assume_spd(Op op)
double real
Definition types.hpp:10
SolverResult cg(const Matrix &A, const Vector &b, Vector &x, real tol=1e-10, idx max_iter=1000, Backend backend=default_backend)
Definition cg.cpp:8
Adapt a SparseMatrix to the operator protocol.
Definition sparse_op.hpp:15

Use gmres(Aop, b, x, tol, max_iter, restart) for nonsymmetric systems.

The unified solve(problem, algorithm) form keeps the method choice explicit:

auto Aspd = num::operators::assume_spd(Aop);
num::solve(num::LinearProblem{Aspd, rhs}, num::CG{.tol = 1e-10, .max_iter = 1000});
num::solve(num::LinearProblem{Aop, rhs}, num::GMRES{.tol = 1e-8, .restart = 40});
ODEResult solve(const P &prob, const RK45 &alg, ObserverFn obs=nullptr)
Definition solve.hpp:32
constexpr real e
Definition math.hpp:44
Linear system A x = b. A is any matrix or LinearOperator; b the RHS. Non-owning view over A and b (bi...
Definition problems.hpp:30
Result of a linear solve: the solution vector plus convergence stats.
Definition solve.hpp:24

r.u is the solution vector; r.iterations, r.residual, and r.converged report progress.

Use PCG when a preconditioner is available:

num::pcg(num::operators::assume_spd(Aop), M, rhs, x, 1e-10, 1000);
JacobiPreconditioner jacobi_preconditioner(const Matrix &A)
SolverResult pcg(const Op &A, const M &M_op, const Vector &b, Vector &x, real tol=1e-10, idx max_iter=1000, Backend backend=default_backend)
Definition pcg.hpp:17

Use MINRES for symmetric indefinite operators:

num::SolverResult m = num::minres(Sop, rhs, x, 1e-10, 1000);
SymmetricOp< Op > assume_symmetric(Op op)
SolverResult minres(const Op &A, const Vector &b, Vector &x, real tol=1e-10, idx max_iter=1000, Backend backend=default_backend)
Definition minres.hpp:48

Eigenvalues and SVD

auto E = num::eig_sym(A_dense);
auto dominant = num::power_iteration(A_dense);
auto Aop = num::operators::DenseOp(A_dense);
auto S = num::svd(A_dense);
auto Sk = num::svd_truncated(A_dense, 8);
SVDResult svd_truncated(const Matrix &A, idx k, Backend backend=default_backend, idx oversampling=10, Rng *rng=nullptr)
Definition svd.cpp:20
LanczosResult lanczos(const Op &A, idx k, real tol=1e-10, idx max_steps=0, Backend backend=Backend::seq)
Operator Lanczos for a declared symmetric adapter.
Definition lanczos.hpp:156
SVDResult svd(const Matrix &A, Backend backend=lapack_backend, real tol=1e-12, idx max_sweeps=100)
Definition svd.cpp:11
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
EigenResult eig_sym(const Matrix &A, real tol=1e-12, idx max_sweeps=100, Backend backend=lapack_backend)
Definition eig.cpp:11
Adapt a dense Matrix to the operator protocol.
Definition dense.hpp:12

eig_sym returns a dense symmetric eigendecomposition. lanczos returns a small set of Ritz pairs from a dense, sparse, or matrix-free symmetric operator.

Matrix Exponential Action

auto Aop = num::operators::DenseOp(A_dense);
num::Vector y = num::expv(0.01, Aop, v, 30, 1e-8);
Vector expv(real t, const Op &A, const Vector &v, int m_max=30, real tol=1e-8)
Compute for any adapter.
Definition expv.hpp:29

This forms \(\exp(tA)v\) by Arnoldi projection without forming \(\exp(A)\).