Skip to content

Jebel-Quant/linalg

Repository files navigation

cvx-linalg

PyPI version Python Downloads License CodeFactor Rhiza Coverage

Linear algebra utilities for portfolio optimization, part of the jebel-quant ecosystem.

Installation

pip install cvx-linalg

The ewm_covariance function requires the optional Polars dependency:

pip install 'cvx-linalg[ewm]'

Usage

The entire public API is re-exported at the top level, so a flat import is all you ever need:

from cvx.linalg import (
    a_norm, cholesky, cholesky_solve, cov_to_corr,
    inv, inv_a_norm, is_positive_definite, lstsq, pca, rand_cov, solve, valid,
    GramOperator, bordered_solve,
)
from cvx.linalg.covariance.ewm_cov import ewm_covariance  # requires the 'ewm' extra (polars)

Internally the package is organized into subpackages (which can also be imported directly, e.g. from cvx.linalg.decomposition import qr):

Subpackage Contents
cvx.linalg.core Type aliases, exceptions/warnings, condition-number helpers, matrix validation
cvx.linalg.covariance Covariance utilities: PCA, random covariance, correlation conversion, EWM covariance
cvx.linalg.decomposition Matrix decompositions: Cholesky, QR, SVD, eigenvalue routines, power iteration
cvx.linalg.kkt Equality-constrained solves: bordered KKT systems, affine projections
cvx.linalg.norm NaN-aware vector and matrix norms, A-norms and their inverses
cvx.linalg.operators Symmetric linear operators (dense, Gram, factor, incremental) for active-set and Krylov solvers
cvx.linalg.solve NaN-aware linear-system solvers: solve, lstsq, inv, det

The one exception to the flat-import rule is ewm_covariance: it lives in cvx.linalg.covariance.ewm_cov and is deliberately not re-exported because it requires the optional polars dependency.

Core (cvx.linalg.core)

Types

  • Matrix — Type alias for a 2-D numpy.ndarray with float64 dtype
  • Vector — Type alias for a 1-D numpy.ndarray with float64 dtype

The package ships a py.typed marker; all public signatures are precisely annotated and verified with ty in CI.

Exceptions & Warnings

All exceptions and warnings live in core/exceptions.py:

  • DimensionMismatchError — Raised when vector length does not match matrix dimension
  • IllConditionedMatrixWarning — Emitted when the condition number exceeds a configurable threshold
  • InvalidComponentsError — Raised when pca is asked for fewer than 1 or more components than the data supports
  • NegativeWarmupError — Raised when a negative warmup period is passed to ewm_covariance
  • NonIntegerWarmupError — Raised when a non-integer warmup is passed to ewm_covariance
  • NonSquareMatrixError — Raised when a square matrix is required but the input is not square
  • NotAMatrixError — Raised when a 2-D matrix is required but the input has different dimensionality
  • SingularMatrixError — Raised when a matrix is numerically singular

Covariance (cvx.linalg.covariance)

Decompositions (cvx.linalg.decomposition)

  • cholesky(cov) — Upper triangular Cholesky factor R such that R.T @ R = cov
  • cholesky_solve(cov, rhs) — Solve cov @ x = rhs via Cholesky decomposition (falls back to LU for non-positive-definite matrices)
  • is_positive_definite(matrix) — Return True if the matrix is symmetric positive-definite
  • eigh(matrix) — Eigenvalues/eigenvectors of the valid symmetric/Hermitian submatrix in ascending eigenvalue order
  • eigvalsh(matrix) — Eigenvalues-only convenience wrapper around eigh
  • eigvals(matrix) — Eigenvalues of a general square matrix (supports complex output for non-symmetric matrices)
  • power_iteration(matrix, n_iter=1000, tol=1e-9, seed=None) — Estimate the dominant (largest-magnitude) eigenpair of a symmetric matrix via power iteration
  • qr(matrix) — Reduced QR decomposition, matching np.linalg.qr(mode='reduced')
  • svd(matrix) — Raw compact singular value decomposition via np.linalg.svd(full_matrices=False)
  • svd_k(matrix, k) — Exact truncated rank-k SVD (the best rank-k approximation; leading triplets of the compact SVD)

Norms (cvx.linalg.norm)

Solvers (cvx.linalg.solve)

Operators (cvx.linalg.operators)

Active-set and Krylov solvers never need a symmetric matrix A as an explicit array — they touch it through a handful of products: a full matrix-vector product, sub-block products, and a direct solve against a principal ("free") sub-block. The SymmetricOperator protocol captures exactly that contract (including rcond_free for detecting rank-deficient free blocks and restricted(free) for a pre-sliced free-block view), and the backends implement it at very different cost:

  • SymmetricOperator — Protocol exposing a symmetric matrix through matvec, block_matvec, solve_free, apply_free, rcond_free, restricted, and diag
  • DenseOperator — Backend wrapping an explicit dense n x n matrix
  • IncrementalDenseOperatorDenseOperator maintaining the free-block inverse across single-index flips for active-set sweeps
  • GramOperator — Matrix-free backend for A = M.T @ M, represented by its factor M; never forms the Gram matrix
  • FactorOperator — Diagonal-plus-low-rank backend A = diag(d) + U @ Delta @ U.T with Woodbury free-block solves
  • SumOperator — Weighted sum of symmetric operators (forward-only; feed apply_free to a Krylov solver)

Constrained solves (cvx.linalg.kkt)

Building blocks for active-set and path-tracing solvers, built on top of the operator protocol:

  • bordered_solve(operator, free, c_free, rhs, d) — Range-space (Schur complement) solve of the bordered KKT system [[H_FF, C.T], [C, 0]] @ [x; nu] = [rhs; d], reaching the Hessian block only through a SymmetricOperator
  • AffineProjection(c, d) — Euclidean projection onto the affine set {x : C x = d}, caching the Gram matrix C C.T for repeated use

Stability policy

This package follows semantic versioning. The public API is everything importable from cvx.linalg (plus cvx.linalg.covariance.ewm_cov):

  • Breaking changes only occur in major releases.
  • Deprecations are announced at least one minor release before removal and emit a DeprecationWarning in the meantime (currently: the two-argument cholesky(cov, rhs) form — use cholesky_solve — slated for removal in 1.0).
  • Supported environments: Python 3.11–3.14, NumPy ≥ 2.0. The optional ewm extra requires Polars ≥ 1.40.

Numerical conventions (NaN handling, condition-number warnings, dtype contract) are documented in Numerical Behavior.

About

Linear algebra utilities for portfolio optimization

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors