The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
A matrix too large to fully diagonalize still has a handful of eigenvalues or singular values you actually need — the top few directions of variance, the leading modes of a graph, the dominant singular triplets behind a low-rank approximation. eigencore computes exactly that partial answer, and every result carries a certificate: residuals, a backward-error bound, and a pass/fail verdict, so you don’t have to recompute the check yourself to trust it.
Build a symmetric matrix and ask for its five largest eigenvalues:
set.seed(1)
n <- 200
A <- crossprod(matrix(rnorm(n * n), n, n)) / n + diag(n)
fit <- eig_partial(A, k = 5, target = largest())
fit
#> Partial eigen decomposition
#> requested: 5
#> converged: 5
#> method: native scalar thick-restart Hermitian Lanczos
#> target: largest
#> restart:thick_restart(in_native_loop)
#> locked: 5
#> max residual: 1.67046e-07
#> max backward error: 4.546939e-09
#> max orthogonality loss: 2.220446e-15
#> norm bound: frobenius_exact+identity_exact
#> scale estimated: FALSE
#> certificate: passedThe certificate is not a side note —
fit$certificate$passed is the answer to “can I trust these
five numbers?”
The five largest eigenvalues (blue) located within the full spectrum of A (grey). eigencore computes only the requested slice, then certifies it.
With n = 200 this computed 5 of 200 pairs. In a
production problem with n = 1e6, storing all eigenvectors
and computing the full spectrum is usually impractical; a certified
partial result is often the useful result you can afford.
A v = lambda B v)Pass a metric B to eig_partial() when the
problem is A v = lambda B v rather than the standard
A v = lambda v.
B <- diag(seq(1, 5, length.out = n))
fit_gen <- eig_partial(A, k = 5, target = largest(), B = B,
method = lobpcg(maxit = 200))
fit_gen
#> Partial eigen decomposition
#> requested: 5
#> converged: 5
#> method: native generalized SPD LOBPCG (B-orthogonal, residual certified)
#> target: largest
#> restart: lobpcg
#> locked: 5
#> max residual: 2.030435e-08
#> max backward error: 1.501444e-10
#> max orthogonality loss: 1.332268e-15
#> norm bound: frobenius_exact+frobenius_exact
#> scale estimated: FALSE
#> certificate: passedThe absolute residual is ||A v - lambda B v||. The
certificate divides that quantity by ||A|| + |lambda| ||B||
(and the vector norm, when needed) to form the backward error used for
convergence. Orthogonality is measured in the B-inner
product where appropriate. See
vignette("generalized-eigenproblems") for dense pencils,
singular B, and the QZ decomposition.
For rectangular problems use svd_partial():
M <- matrix(rnorm(400 * 50), 400, 50)
svd_fit <- svd_partial(M, rank = 5, target = largest())
svd_fit
#> Partial SVD
#> requested rank: 5
#> converged rank: 5
#> method: native certified Gram SVD special case
#> target: largest
#> max residual: 1.251212e-15
#> max backward error: 8.762535e-18
#> max orthogonality loss: 4.657733e-16
#> norm bound: frobenius_exact
#> scale estimated: FALSE
#> certificate: passedThe same mental model applies to singular values: you compute the leading few and leave the tail untouched.
The five leading singular values (blue) computed by eigencore, shown against the full singular-value spectrum of M (grey).
The reported method identifies the path — for very small
or near-square problems eigencore may use a dense LAPACK SVD fallback
rather than running its iterative Golub-Kahan kernel. Either way the
certificate covers both ||A v - sigma u|| and
||A^T u - sigma v||.
If your existing code uses RSpectra::eigs_sym(), you can
call eigencore in the same shape — the return list extends RSpectra’s by
adding certificate and diagnostics:
res <- eigs_sym(A, k = 5, which = "LA")
str(res, max.level = 1)
#> List of 7
#> $ values : num [1:5] 5.01 4.77 4.7 4.57 4.5
#> $ vectors : num [1:200, 1:5] 0.0227 0.0103 0.0923 -0.1479 -0.0414 ...
#> $ nconv : int 5
#> $ niter : int 60
#> $ nops : int 62
#> $ certificate:List of 18
#> ..- attr(*, "class")= chr "eigencore_certificate"
#> $ diagnostics:List of 15res$certificate
#> eigencore certificate
#> passed: TRUE
#> tolerance: 1e-08
#> type: residual_backward_error
#> norm bound: frobenius_exact+identity_exact
#> scale estimated: FALSE
#> max residual: 2.074433e-09
#> max backward error: 5.646539e-11
#> max orthogonality loss: 3.330669e-15
#> orthogonality tolerance: 1.490116e-08
#> orthogonality required: TRUEeigs(), eigs_sym(), and svds()
accept the same which codes as RSpectra —
"LM", "SM", "LA",
"SA", "LR", "SR",
"LI", "SI", and "BE".
eig_partial() and svd_partial() cover the
common case, but every call you’ve made in this vignette runs through
the same four-stage architecture, and you can drop down to it directly
when you want to inspect or reuse a piece of that pipeline.
1. Operators. Any matrix is wrapped in a block-native operator the moment you hand it to a problem constructor. You can do this explicitly:
Aop <- as_operator(A)
Aop
#> <eigencore operator>
#> name: dense_matrix
#> dim: 200 x 200
#> dtype: double
#> structure: hermitianThe operator carries dimensions, structure tags, and a flag
indicating whether the underlying storage has a native kernel (in this
case dense double — yes). vignette("sparse-pca") builds
operators that center and scale a sparse matrix without densifying it —
the same object type, doing more work per call.
2. Problems. eigen_problem() and
svd_problem() describe what to solve: the matrix,
its structure (hermitian(), general(), …), and
the spectral target (largest(), smallest(),
nearest(), …).
3. Plans. plan_solver() reports the
primary method selected from the problem’s current structure, target,
and policy, together with any allowed fallback. It is an inspection
object, not an executable or frozen plan: certification can still
trigger a recorded fallback while solving.
plan <- plan_solver(P, k = 5)
plan
#> eigencore solver plan
#> problem: eigen
#> requested: 5
#> target: largest
#> method: native scalar thick-restart Hermitian Lanczos
#> reasons:
#> - structure: hermitian
#> - target: largest
#> - standard eigenproblem
#> - built-in dense operator has native block apply
#> controls:
#> - block : 1
#> - max_subspace : 35
#> - max_restarts : 100
#> - reorthogonalize : TRUE
#> fallback: dense oracle prototype if unsupported4. Solve. solve() on a problem is what
eig_partial() calls internally. Reuse the problem object
when you want to solve it again. Inspect the returned
method, warnings, and restart diagnostics to see the route
that actually ran.
vignette("sparse-pca") — the flagship workflow:
centering and scaling a sparse matrix without densifying it, and
building matrix-free operators by hand.vignette("certificates") is the deep dive on reading
the numerical evidence — what each field means and what to do when a
check fails.vignette("generalized-eigenproblems") covers dense
pencils, singular B, and the QZ decomposition.help(package = "eigencore") to browse the installed
help index.?certificate documents the certificate fields in
detail.?plan_solver explains how operator structure, target,
and method combine to choose a kernel.These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.