ocs-rs — exact, matrix-free optimum contribution selection
Python bindings for the Rust support-first OCS solver.
Optimum contribution selection (OCS) chooses how much each candidate contributes to the next generation: maximise genetic gain bᵀc subject to a quadratic relationship bound, cᵀGc ≤ k, with non-negative contributions summing to one — or, in the sexed form, to one half per sex.
The solver targets the global optimum of the convex OCS program and reports
Solved when its numerical termination checks pass. Scope: continuous
contributions under a single coancestry constraint; it does not do integer mate
allocation. See the repository's manuscript and validation results for the precise
optimality conditions and numerical tolerances.
Matrix-free. It never forms the dense n×n relationship matrix: the kinship
products come straight from the genotype matrix as Gc = εc + Z(Zᵀc)/s. A dense
float64 relationship matrix would occupy about 11.9 GiB at n = 40 000; this is
calculated storage, not an observed allocation failure. Working on a small active
support can reduce factorization costs. Small support is an empirical property of
the reported instances; individual contribution caps can force larger supports.
The matrix-free path costs O(nm) per product. The wrappers accept a dense genotype
matrix: Python converts Z to contiguous float64, copies it to bytes, and the
native layer copies those entries into its matrix layout. It therefore needs
additional O(nm) memory during a solve. Packed 2-bit PLINK solving is currently
available only through Rust's read_packed and solve_sexed_packed APIs.
Install
pip install ocs-rs
Wheels ship for Linux (x86_64, aarch64), macOS (Intel, Apple silicon) and Windows,
abi3 for Python 3.9+. To build from a full repository checkout, install Rust
1.85+ and activate a virtual environment, then run pip install maturin and
maturin develop --release from bindings/python/. The Cargo dependency on the
core crate is relative to that checkout. Current package version: 0.4.0.
Quickstart
import numpy as np
import ocs_rs
rng = np.random.default_rng(11)
n, m = 12, 20
dosages = rng.binomial(2, rng.uniform(0.1, 0.5, m), size=(n, m))
p = dosages.mean(axis=0) / 2
Z = dosages - 2 * p
s = ocs_rs.vanraden_scale(p)
b = rng.standard_normal(n)
male = np.arange(n) % 2 == 0
caps = np.full(n, 0.15)
ridge = 1e-5 # G = Z @ Z.T / s + ridge * I
# A feasible plan contributes half from each sex, uniformly within that sex.
c0 = np.where(male, 0.5 / male.sum(), 0.5 / (~male).sum())
assert np.all(c0 <= caps)
q0 = float(np.sum((Z.T @ c0) ** 2) / s + ridge * (c0 @ c0))
k = q0 + 0.05 # This cap admits c0; it is not a universal breeding threshold.
res = ocs_rs.solve(Z, b, k=k, s=s, ridge=ridge, male=male, caps=caps)
if res.status != "Solved":
raise RuntimeError(f"No solved optimum: {res.status}")
print(res)
print(res.support) # 0-based NumPy indices
print(res.c[res.support])
The same example is executable as python examples/quickstart.py from this
directory. The positive ridge contributes ridge * sum(c**2) to the quadratic relationship
constraint and must also be included when computing a feasible cap.
API
solve(Z, b, k, *, s, ridge=1e-5, male=None, caps=None, max_iter=10_000, tol=1e-9)
| argument | meaning |
|---|---|
Z |
(n, m) centred genotype matrix — G = ZZᵀ/s + ridge·I, never formed |
b |
(n,) breeding values (the selection criterion) |
k |
quadratic relationship bound: cᵀGc ≤ k |
s |
VanRaden scale 2 Σ p(1-p) |
male |
(n,) bool — give it for the sexed form (Σ_males = Σ_females = ½) |
caps |
(n,) per-candidate upper bounds c ≤ caps |
Returns an OcsResult with c, support (0-based indices), gain, quad,
iterations, products and status. Check status == "Solved" before using the
contributions as an optimum; MaxIter has no such guarantee.
The API reports quad = cᵀGc. Here G is an additive relationship matrix;
group coancestry is quad / 2 using K = G / 2. A group-coancestry bound ub
therefore corresponds to k = 2 * ub. This score does not specify realised
offspring inbreeding without a mating allocation and reference population.
The API accepts Z, not a relationship matrix G. Passing an n×n G as Z
would solve with G @ G.T / s + ridge * I. An arbitrary relationship matrix or
one modified by blending, shrinkage or pedigree adjustment needs a separate
adapter/factorization that reproduces the intended operator; the wrappers do not
provide a general G argument.
b, male and caps must have exactly the row order of Z. For a PLINK panel,
align them to panel.ids before solving. These IDs are the .fam IID column
only; family IDs (FID) and .fam sex are not returned. Preserve that metadata
separately, check that your identifiers are unique, and supply the sex mask
yourself. The reader checks file dimensions and encoding consistency; matching
dimensions do not verify that .bed, .bim and .fam describe the same identities
or ordering. Use a trio produced together, not independently reordered files.
Links
- Source, manuscript and reproduction scripts: https://github.com/Adelagric/ocs-rs
- Archived release: https://doi.org/10.5281/zenodo.20746987
MIT licence.
Metadata
Release files for ocs-rs 0.4.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ocs_rs-0.4.2.tar.gz | 1.9 MB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| ocs_rs-0.4.2-cp39-abi3-win_amd64.whl | CPython 3.9 | abi3 | Windows x86-64 | Details |
| ocs_rs-0.4.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| ocs_rs-0.4.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| ocs_rs-0.4.2-cp39-abi3-macosx_11_0_arm64.whl | CPython 3.9 | abi3 | macOS 11.0+ ARM64 | Details |
| ocs_rs-0.4.2-cp39-abi3-macosx_10_12_x86_64.whl | CPython 3.9 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 5.6 MB
Release files / ocs_rs-0.4.2.tar.gz
| Download URL | ocs_rs-0.4.2.tar.gz |
|---|---|
| Size | 1.9 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e9f6113a4422ca9d58f4fb2fd25221d4c9b2b4ac82823357774b6f13f2c1343c
|
|
BLAKE2b-256 checksum How to use checksums |
a3bb33903fd2392c8891ad9527df34b75650f49053a48d75db8a75f49a976f05
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / ocs_rs-0.4.2-cp39-abi3-win_amd64.whl
| Download URL | ocs_rs-0.4.2-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 745.4 kB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
a029e417d56787e44ed4ef5acaf0b54466dd99508673a22b9ad62b31e9e01edc
|
|
BLAKE2b-256 checksum How to use checksums |
7a9f79d814366f95e48e0e9fe4d16e7d3e25e90e2890c7293c15a75808b2ed43
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / ocs_rs-0.4.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | ocs_rs-0.4.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.0 MB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
35ab0d7141d0fa277221b6bc48d4c0e0b9d0cd4debafcb72703c3993543f3046
|
|
BLAKE2b-256 checksum How to use checksums |
11cf0609fa60881c267dc85ab39d06cff215996ede4b423222c77eefdeaa13e6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / ocs_rs-0.4.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | ocs_rs-0.4.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 615.0 kB |
| Tags | CPython 3.9 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
89255394ebd464c630db34bb49ab57df8f785d08915d8cfda8a3aa7e2c40c020
|
|
BLAKE2b-256 checksum How to use checksums |
2cf1dfac923d41dbc198aec615519f428d5518441ecb99653a2c02df12248f18
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / ocs_rs-0.4.2-cp39-abi3-macosx_11_0_arm64.whl
| Download URL | ocs_rs-0.4.2-cp39-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 507.7 kB |
| Tags | CPython 3.9 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
3e7aaa5cf4e63f58620003ee4fba5fdc249c37a7d3d7fd2fbb423652f84cae10
|
|
BLAKE2b-256 checksum How to use checksums |
b6780bfae3bc04d2784c51a614293426816a5103390557d1a48251fd9f77e80a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / ocs_rs-0.4.2-cp39-abi3-macosx_10_12_x86_64.whl
| Download URL | ocs_rs-0.4.2-cp39-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 817.6 kB |
| Tags | CPython 3.9 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
de3cc3f5c7a24ab9f0464894f4f5bc9b21d1f78a0757083d7ecc97607045cb00
|
|
BLAKE2b-256 checksum How to use checksums |
0e9c1d0137966ce3b97dd68089a96df9e3ed314344bb83a66d28882aa1fa0439
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency log