| Type: | Package |
| Title: | Tile-Based Sparse Cholesky Factorization and Selected Inverse |
| Version: | 2026.9.4 |
| Description: | Interface to the 'sTiles' framework for tile-based sparse Cholesky factorization: log-determinants, selected inverse (marginal variances) and triangular solves, with symbolic reuse so that repeated factorization of matrices sharing one sparsity pattern pays the ordering cost only once, as in a hyperparameter sweep. The compiled glue in this package resolves its symbols at run time against the 'sTiles' solver library ('libstiles'), which is a separate component distributed under its own terms and is not part of this package. Install it once with 'sTiles_install_library()', or point the package at a copy you already have with the 'STILES_LIB' environment variable. |
| License: | MIT + file LICENSE |
| URL: | https://esmail-abdulfattah.github.io/sTiles/ |
| BugReports: | https://github.com/esmail-abdulfattah/sTiles/issues |
| Imports: | methods, Matrix, tools, utils |
| Suggests: | testthat (≥ 3.0.0) |
| Config/testthat/edition: | 3 |
| NeedsCompilation: | yes |
| SystemRequirements: | the 'sTiles' solver library (libstiles.so on Linux, libstiles.dylib on macOS, libstiles.dll on Windows), obtained with sTiles_install_library() or supplied by the user |
| Encoding: | UTF-8 |
| Config/roxygen2/version: | 8.0.0 |
| Packaged: | 2026-09-06 15:22:22 UTC; abdulfe |
| Author: | Esmail Abdul Fattah [aut, cre, cph] |
| Maintainer: | Esmail Abdul Fattah <esmail.abdulfattah@gmail.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-09-15 10:50:02 UTC |
Tile-Based Sparse Cholesky Factorization and Selected Inverse
Description
An interface to the sTiles framework: sparse Cholesky factorization, log-determinants, selected inverse (marginal variances) and triangular solves, organised so that the symbolic work is paid once per sparsity pattern and reused across every set of values sharing it.
Start at [sTiles()] for a one-shot factorization, or at [sTiles_analyze()] plus [sTiles_factorize()] when many matrices share one pattern.
The solver library
The numerical work happens in libstiles, a separate component under its own license terms that this package loads at run time (see the NOTICE file). [sTiles_available()] reports whether a copy is present, [sTiles_install_library()] fetches one, and 'STILES_LIB' points the package at a copy you already have.
Print a sTiles factorization object
Description
Print a sTiles factorization object
Usage
## S3 method for class 'sTiles'
print(x, ...)
Arguments
x |
An "sTiles" object. |
... |
Ignored, present for consistency with [print()]. |
Value
'x', invisibly.
Examples
if (sTiles_available()) {
Q <- Matrix::bandSparse(50, k = c(0, 1),
diagonals = list(rep(4, 50), rep(-1, 49)),
symmetric = TRUE)
print(sTiles(Q))
}
Print a sTiles summary
Description
Print a sTiles summary
Usage
## S3 method for class 'sTiles_summary'
print(x, ...)
Arguments
x |
An object of class "sTiles_summary" from [sTiles_summary()]. |
... |
Ignored, present for consistency with [print()]. |
Value
'x', invisibly.
Examples
if (sTiles_available()) {
Q <- Matrix::bandSparse(50, k = c(0, 1),
diagonals = list(rep(4, 50), rep(-1, 49)),
symmetric = TRUE)
print(sTiles_summary(sTiles(Q)))
}
Factorize a symmetric positive-definite matrix
Description
One shot: runs the preprocessing ([sTiles_analyze()]) and then the numeric factorization ([sTiles_factorize()]). To time the two phases apart, or to reuse one preprocessing across many sets of values, call those two yourself.
Usage
sTiles(
Q,
cores = 1L,
mode = "auto",
tile_size = 40L,
inverse = FALSE,
log_level = -1L
)
Arguments
Q |
A symmetric positive-definite matrix, either a 'Matrix::sparseMatrix' or a base matrix. Only the lower triangle is read. |
cores |
Worker threads (default 1). |
mode |
Tile regime: "auto" (default), "dense", "semisparse" or "sparse". |
tile_size |
Tile size, or -1 to let the solver choose (default 40). |
inverse |
Reserve selected-inverse storage, required by [sTiles_selinv()] and the 'sTiles_selinv_*()' queries (default 'FALSE'). |
log_level |
Solver verbosity: -1 silent (default), 0 timing, 1 info, 2 debug, 3 trace. |
Value
An object of class "sTiles" wrapping a live factorization.
See Also
[sTiles_logdet()], [sTiles_solve()], [sTiles_selinv()], [sTiles_summary()], [sTiles_close()]
Examples
if (sTiles_available()) {
Q <- Matrix::bandSparse(50, k = c(0, 1),
diagonals = list(rep(4, 50), rep(-1, 49)),
symmetric = TRUE)
s <- sTiles(Q)
sTiles_logdet(s)
sTiles_solve(s, rep(1, 50))
sTiles_close(s)
}
Preprocess a matrix: ordering bake-off and tile layout only
Description
The symbolic phase. It depends only on the sparsity pattern, not on the numeric values, and performs no Cholesky. Follow it with [sTiles_factorize()] for the numeric factorization. Timing the two apart separates the preprocessing cost, paid once per pattern, from the numeric cost, paid once per set of values.
Usage
sTiles_analyze(
Q,
cores = 1L,
mode = "auto",
tile_size = 40L,
inverse = FALSE,
log_level = -1L
)
Arguments
Q |
A symmetric positive-definite matrix, either a 'Matrix::sparseMatrix' or a base matrix. Only the lower triangle is read. |
cores |
Worker threads (default 1). |
mode |
Tile regime: "auto" (default), "dense", "semisparse" or "sparse". |
tile_size |
Tile size, or -1 to let the solver choose (default 40). |
inverse |
Reserve selected-inverse storage, required by [sTiles_selinv()] and the 'sTiles_selinv_*()' queries (default 'FALSE'). |
log_level |
Solver verbosity: -1 silent (default), 0 timing, 1 info, 2 debug, 3 trace. |
Value
An object of class "sTiles", analyzed but not yet factorized.
See Also
[sTiles_factorize()], [sTiles_update()], [sTiles()]
Examples
if (sTiles_available()) {
Q <- Matrix::bandSparse(50, k = c(0, 1),
diagonals = list(rep(4, 50), rep(-1, 49)),
symmetric = TRUE)
s <- sTiles_analyze(Q)
sTiles_factorize(s)
sTiles_logdet(s)
sTiles_close(s)
}
Is the sTiles solver library available?
Description
Reports whether a solver library can be found on this machine, checking the 'STILES_LIB', 'STILES_LIB_DIR' and 'STILES_BINARIES_DIR' environment variables, a copy bundled in the installed package, a development checkout, and the cache filled by [sTiles_install_library()]. It looks at the file system only: it never contacts the network and never loads anything, which makes it the right guard for examples and tests that have to be skipped where no solver is installed.
Usage
sTiles_available()
Value
'TRUE' when a solver library was found, 'FALSE' otherwise.
See Also
[sTiles_install_library()]
Examples
sTiles_available()
Delete every cached sTiles solver library
Description
Removes the solver copies that [sTiles_install_library()] placed in the package cache. The blunt instrument for a cache believed to be broken or stale, and the way to make room before installing a different release: call [sTiles_install_library()] afterwards to fetch a fresh one. Takes effect immediately unless this session has already built a matrix with the old solver, in which case the files go but a replacement can only load after restarting R (a loaded solver with live handles cannot be swapped underneath them).
Usage
sTiles_clean_cache()
Value
The number of cached solvers removed, invisibly.
See Also
[sTiles_install_library()], [sTiles_available()]
Examples
## Not run:
sTiles_clean_cache()
## End(Not run)
Free a factorization now
Description
Releases the solver's memory immediately. Optional: an object that goes out of scope is freed at the next garbage collection anyway. Worth calling in a loop over large matrices, where waiting for the collector means holding several factorizations at once.
Usage
sTiles_close(x)
Arguments
x |
An "sTiles" object. |
Value
'NULL', invisibly.
See Also
[sTiles()]
Examples
if (sTiles_available()) {
Q <- Matrix::bandSparse(50, k = c(0, 1),
diagonals = list(rep(4, 50), rep(-1, 49)),
symmetric = TRUE)
s <- sTiles(Q)
sTiles_close(s)
}
Numeric Cholesky factorization, reusing the preprocessing
Description
Runs the numeric phase on an object that [sTiles_analyze()] has already prepared, so the ordering and tile layout are not recomputed.
Usage
sTiles_factorize(x, Q = NULL)
Arguments
x |
An "sTiles" object from [sTiles_analyze()] or [sTiles()]. |
Q |
Optional: a matrix with the SAME sparsity pattern, whose values to factor. When omitted, the values captured at analyze time are used. |
Value
The "sTiles" object, now factorized, invisibly.
See Also
[sTiles_analyze()], [sTiles_update()]
Examples
if (sTiles_available()) {
Q <- Matrix::bandSparse(50, k = c(0, 1),
diagonals = list(rep(4, 50), rep(-1, 49)),
symmetric = TRUE)
s <- sTiles_analyze(Q)
sTiles_factorize(s)
sTiles_logdet(s)
sTiles_close(s)
}
Install the sTiles solver library
Description
Downloads the prebuilt solver library that matches this platform from the sTiles project's releases and stores it in the package cache, under 'tools::R_user_dir("sTiles", "cache")'. Run it once: every later session finds the cached copy without touching the network.
Usage
sTiles_install_library(tag = NULL, variant = NULL, force = FALSE)
Arguments
tag |
Release tag to install, for example "v2026.8.27". Defaults to the latest release. |
variant |
Build variant to prefer, for example "armv82-armpl" or "v3-mkl", or "none" for the portable default. Defaults to the best fit for this CPU, falling back to the portable build when the release does not carry the preferred one. |
force |
Re-download even when a matching solver is already cached. |
Details
The solver is a separate component under its own license terms (see the NOTICE file in this package) and is deliberately not bundled. Nothing is downloaded unless you call this function or accept the prompt an interactive session shows the first time a solver is needed. To skip the download altogether, point 'STILES_LIB' at a shared object you already have, or 'STILES_LIB_DIR' at the directory holding it. Setting 'STILES_NO_DOWNLOAD' disables the download path entirely.
Value
The path of the installed shared library, invisibly.
Search order
Before anything is downloaded, and on every later call, the package takes the first solver it finds among:
'STILES_LIB', a shared object named outright;
'STILES_LIB_DIR', a directory holding one;
'STILES_BINARIES_DIR', a CI-artifact tree;
a 'binaries/' tree above the installed package or the working directory;
a copy bundled in the installed package, under 'solver/';
'lib/' in a development checkout above the package;
the download cache, newest release first.
See Also
[sTiles_available()], [sTiles_clean_cache()]
Examples
## Not run:
sTiles_install_library()
sTiles_install_library(tag = "v2026.8.27", variant = "none")
## End(Not run)
Path of the loaded sTiles solver library
Description
Loads the solver if this session has not loaded it yet, then reports which file answered. Useful when several builds are installed and you need to know which one is in use.
Usage
sTiles_library_path()
Value
The absolute path of the loaded shared library, as a string.
See Also
[sTiles_available()], [sTiles_install_library()]
Examples
if (sTiles_available()) {
sTiles_library_path()
}
Log-determinant of the factorized matrix
Description
Returns 'log(det(Q))', computed from the factor as '2 * sum(log(diag(L)))'.
Usage
sTiles_logdet(x)
Arguments
x |
A factorized "sTiles" object. |
Value
The log-determinant, a single number.
See Also
[sTiles()], [sTiles_summary()]
Examples
if (sTiles_available()) {
Q <- Matrix::bandSparse(50, k = c(0, 1),
diagonals = list(rep(4, 50), rep(-1, 49)),
symmetric = TRUE)
s <- sTiles(Q)
sTiles_logdet(s)
sTiles_close(s)
}
Compute the selected inverse, reusing the current factorization
Description
Computes Z, the inverse of Q restricted to the pattern of the Cholesky factor, 'pattern(L + L^T)'. The object must have been built with 'inverse = TRUE'. The call is idempotent, and the computation otherwise happens lazily on the first 'sTiles_selinv_*()' query. Call it explicitly to time the selected inverse on its own, and call it again after each [sTiles_factorize()] to refresh Z for the new values.
Usage
sTiles_selinv(x)
Arguments
x |
A factorized "sTiles" object built with 'inverse = TRUE'. |
Value
The "sTiles" object, invisibly.
See Also
[sTiles_selinv_diag()], [sTiles_selinv_elm()], [sTiles_selinv_row()]
Examples
if (sTiles_available()) {
Q <- Matrix::bandSparse(50, k = c(0, 1),
diagonals = list(rep(4, 50), rep(-1, 49)),
symmetric = TRUE)
s <- sTiles(Q, inverse = TRUE)
sTiles_selinv(s)
head(sTiles_selinv_diag(s))
sTiles_close(s)
}
Diagonal of the selected inverse: the marginal variances
Description
Returns 'diag(solve(Q))', in the original ordering. Triggers the selected-inverse computation on first use.
Usage
sTiles_selinv_diag(x)
Arguments
x |
A factorized "sTiles" object built with 'inverse = TRUE'. |
Value
A numeric vector of length 'n', the diagonal of the inverse.
See Also
[sTiles_selinv()], [sTiles_selinv_elm()]
Examples
if (sTiles_available()) {
Q <- Matrix::bandSparse(50, k = c(0, 1),
diagonals = list(rep(4, 50), rep(-1, 49)),
symmetric = TRUE)
s <- sTiles(Q, inverse = TRUE)
head(sTiles_selinv_diag(s))
sTiles_close(s)
}
One entry of the selected inverse
Description
Returns the selected inverse at position '(i, j)' when that position lies in the factor pattern, 'pattern(L + L^T)', and exactly 0 outside it. Both triangles are accepted, since Z is symmetric. Triggers the selected-inverse computation on first use.
Usage
sTiles_selinv_elm(x, i, j)
Arguments
x |
A factorized "sTiles" object built with 'inverse = TRUE'. |
i, j |
Row and column, 1-based, in the original ordering. |
Value
The entry as a single number, 0 outside the factor pattern.
See Also
[sTiles_selinv()], [sTiles_selinv_row()]
Examples
if (sTiles_available()) {
Q <- Matrix::bandSparse(50, k = c(0, 1),
diagonals = list(rep(4, 50), rep(-1, 49)),
symmetric = TRUE)
s <- sTiles(Q, inverse = TRUE)
sTiles_selinv_elm(s, 1, 2)
sTiles_close(s)
}
Several entries from one row of the selected inverse
Description
Returns the selected inverse at '(node, k)' for each 'k' in 'neighbors', the access pattern a graph model wants. Entries outside the factor pattern come back as 0.
Usage
sTiles_selinv_row(x, node, neighbors)
Arguments
x |
A factorized "sTiles" object built with 'inverse = TRUE'. |
node |
Row index, 1-based, in the original ordering. |
neighbors |
Integer vector of column indices, 1-based. |
Value
A numeric vector, one value per entry of 'neighbors'.
See Also
[sTiles_selinv()], [sTiles_selinv_elm()]
Examples
if (sTiles_available()) {
Q <- Matrix::bandSparse(50, k = c(0, 1),
diagonals = list(rep(4, 50), rep(-1, 49)),
symmetric = TRUE)
s <- sTiles(Q, inverse = TRUE)
sTiles_selinv_row(s, 5, c(4, 5, 6))
sTiles_close(s)
}
Solve a linear system with the factorization
Description
Solve a linear system with the factorization
Usage
sTiles_solve(x, b, system = c("A", "L", "Lt"))
Arguments
x |
A factorized "sTiles" object. |
b |
Right-hand side: a length-'n' vector, or an 'n' by 'nrhs' matrix. |
system |
Which system to solve: "A" for 'Q x = b' (default), "L" for the forward solve 'L y = b', "Lt" for the backward solve 't(L) x = b'. |
Value
The solution, with the same shape as 'b'.
See Also
[sTiles()], [sTiles_logdet()]
Examples
if (sTiles_available()) {
Q <- Matrix::bandSparse(50, k = c(0, 1),
diagonals = list(rep(4, 50), rep(-1, 49)),
symmetric = TRUE)
s <- sTiles(Q)
x <- sTiles_solve(s, rep(1, 50))
max(abs(as.vector(Q %*% x) - 1))
sTiles_close(s)
}
Structured summary of a factorization
Description
Collects the dimensions, the fill, the tile mode, the phase the object is in, and the timings the solver measured. The result is an ordinary list, so single numbers are easy to pull out ('sTiles_summary(s)$chol_time'), and it prints as a short report.
Usage
sTiles_summary(x)
Arguments
x |
An "sTiles" object. |
Value
An object of class "sTiles_summary": a list with elements 'n', 'nnz', 'nnz_factor', 'mode', 'cores', 'inverse', 'factored', 'analyze_time', 'chol_time', 'selinv_time', 'version' and 'library'.
See Also
[sTiles()], [sTiles_version()]
Examples
if (sTiles_available()) {
Q <- Matrix::bandSparse(50, k = c(0, 1),
diagonals = list(rep(4, 50), rep(-1, 49)),
symmetric = TRUE)
s <- sTiles(Q)
sTiles_summary(s)$nnz_factor
sTiles_close(s)
}
New values, same sparsity pattern: refactorize without reanalyzing
Description
The ordering and tile layout depend only on WHERE the non-zeros are, so an object built by [sTiles_analyze()] can absorb any number of value updates and pay only the numeric cost each time. This is the loop an iterative method wants.
Usage
sTiles_update(x, Q)
Arguments
x |
An "sTiles" object from [sTiles_analyze()]. |
Q |
A matrix with the SAME sparsity pattern, whose values to factor. |
Value
The "sTiles" object, factorized with the new values, invisibly.
See Also
[sTiles_analyze()], [sTiles_factorize()]
Examples
if (sTiles_available()) {
Q <- Matrix::bandSparse(50, k = c(0, 1),
diagonals = list(rep(4, 50), rep(-1, 49)),
symmetric = TRUE)
s <- sTiles_analyze(Q)
sTiles_factorize(s)
d1 <- sTiles_logdet(s)
## same pattern, different values: no new ordering
sTiles_update(s, Q * 2)
d2 <- sTiles_logdet(s)
c(d1, d2)
sTiles_close(s)
}
Version of the sTiles solver library
Description
Version of the sTiles solver library
Usage
sTiles_version()
Value
The solver's version string.
See Also
[sTiles_summary()]
Examples
if (sTiles_available()) {
sTiles_version()
}