Reproducible perturbation-kernel estimators with SIMD and GPU backends
Project description
perturbation-kernel
Reproducible perturbation-kernel estimators with SIMD and GPU backends.
A perturbation kernel answers one question: how much does a result move when you nudge the thing that produced it? You supply a base state, a family of random perturbations, a forward map to what you actually observe, and a scalar functional of the resulting ensemble. You get back that scalar and a non-asymptotic error bound.
The estimator is a pure function of (family, n, seed). Same three
inputs, same bits, on any machine, any thread count, any CPU vector
width.
Python bindings over the Rust reference implementation of SCHEMA.md v1.0.0.
Install
pip install perturbation-kernel
Wheels ship for Linux, macOS and Windows on CPython 3.8+ (stable ABI, so one wheel per platform covers every version).
Use
import perturbation_kernel as pk
cfg = pk.Config(n=100_000, seed=20260610, invariance_lambda=1.0)
report = pk.Markov(k=5, theta_max=0.3).run(cfg)
print(report.value) # 0.880235
print(report.functional) # tail_survival
print(report.execution) # {'backend': 'auto', 'simd_path': 'neon', ...}
Three families ship built in:
| Family | Perturbation | Invariance | Range |
|---|---|---|---|
Gaussian(base, sigma_max) |
s + sigma * N(0, I) |
negative dispersion | <= 0 |
Bistable(x0, dt, theta_max) |
one Langevin step in a double well | polarisation | [-1, 1] |
Markov(k, theta_max, start, base_label) |
mix to uniform w.p. theta |
tail survival | [0, 1] |
Error bounds
Declare the Lipschitz constants and an accuracy target, and the report
carries the Theorem 7.3 bound. Claiming an accuracy that n cannot
support is an error, not a footnote:
cfg = pk.Config(
n=1_000_000, seed=1,
invariance_lambda=1.0, forward_l=1.0,
epsilon=0.05, eta=0.05, observation_diameter=1.0, obs_dim=1,
)
r = pk.Markov(k=5, theta_max=0.3).run(cfg)
print(r.error_bound) # {'epsilon': 0.0158..., 'eta': 0.05, ...}
pk.Markov(k=5, theta_max=0.3).run(pk.Config(
n=100, seed=1, invariance_lambda=1.0,
epsilon=0.05, eta=0.05, observation_diameter=1.0, obs_dim=1))
# ValueError: sample-complexity floor: requested (0.05,0.05) needs N >= 262144, got 100
Backends
pk.available_backends() # ['auto', 'scalar', 'simd', 'gpu']
pk.simd_path() # 'neon'
pk.gpu_device() # 'Apple M4 Max (Metal, IntegratedGpu)'
auto, scalar and simd are bit-identical to each other. They differ
only in how long they take.
gpu is a different numerical path. The device carries the ensemble in
single precision and draws normals by Box-Muller rather than the
ziggurat, so it agrees with the host statistically rather than bit for
bit. It draws from the same ChaCha20 substreams, which keeps the
agreement tight in practice (~1e-4 at n=200k). report.execution
always records which path ran, so a device result can never be mistaken
for a host one.
host = pk.Markov(k=5, theta_max=0.3).run(pk.Config(n=200_000, seed=1))
dev = pk.Markov(k=5, theta_max=0.3).run(
pk.Config(n=200_000, seed=1, backend="gpu")
)
abs(host.value - dev.value) # 3e-4
Reproducibility
a = pk.Config(n=50_000, seed=7)
b = pk.Config(n=50_000, seed=7, backend="scalar")
pk.Markov(k=5, theta_max=0.3).run(a).value \
== pk.Markov(k=5, theta_max=0.3).run(b).value # True, exactly
Randomness flows through a ChaCha20 stream keyed by seed and forked
per draw index, so draw i never depends on how many other draws ran or
in what order. report.to_json(v1=True) gives the strict SCHEMA v1.0.0
payload if you need to hand it to another implementation.
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file perturbation_kernel-2.0.0.tar.gz.
File metadata
- Download URL: perturbation_kernel-2.0.0.tar.gz
- Upload date:
- Size: 112.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
353d3e8228ab8dc5f0b736bd3c61dc0308b8ca2170085f3af555d7e04796178f
|
|
| MD5 |
149aef7a4a609827cf85a01d4cf128a1
|
|
| BLAKE2b-256 |
7737d35c7371cea270a20887c77ca8d5b8be7ebb20c04e340e2a71fd50d29ac9
|
File details
Details for the file perturbation_kernel-2.0.0-cp38-abi3-win_amd64.whl.
File metadata
- Download URL: perturbation_kernel-2.0.0-cp38-abi3-win_amd64.whl
- Upload date:
- Size: 2.8 MB
- Tags: CPython 3.8+, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8bdf4b681999f2277ce5dc9eb5056661f24c9bdd7cae73156b7728387a6077b3
|
|
| MD5 |
4c405e7a803fd82090aa76f6e7c704f4
|
|
| BLAKE2b-256 |
64a04152cb405addbcf19eb537076954735ceeb0792686ec1a36b4c37f4035ee
|
File details
Details for the file perturbation_kernel-2.0.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: perturbation_kernel-2.0.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 2.4 MB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
92b88e951db5f355004ff4247223ccfa2c0409ba0f5c9f707fde633a6aacce52
|
|
| MD5 |
9149e584c371bf9c754cc1442bdc5a75
|
|
| BLAKE2b-256 |
03423512597dfad3b4264d1308b28d69fd1e20f3149383169a70d6e301436cf3
|
File details
Details for the file perturbation_kernel-2.0.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: perturbation_kernel-2.0.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 2.3 MB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30b66bd269a408c423749623fc440d9e8cadd0e7ad59c7444b0743201af1a200
|
|
| MD5 |
ea43a373f86787db6e4041f4338ed4d7
|
|
| BLAKE2b-256 |
9d19a11085a132fee8a55c6dba1bab3a7cb8d2d9e60255d72ff9cf8e1e783410
|
File details
Details for the file perturbation_kernel-2.0.0-cp38-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: perturbation_kernel-2.0.0-cp38-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.9 MB
- Tags: CPython 3.8+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d08124cfeba4b82d1f947fe0b61136c3c9b523193827fee1e0979276f8a17df4
|
|
| MD5 |
4570051cd0d4ff422094580b1fef88b9
|
|
| BLAKE2b-256 |
5fb2ac888c8e0a4a068863e71f00013e8427d27b443382fc136b03c8c48da528
|
File details
Details for the file perturbation_kernel-2.0.0-cp38-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: perturbation_kernel-2.0.0-cp38-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 2.0 MB
- Tags: CPython 3.8+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d28420c57a0160d1b2e87adaaa3a80f4ced3a19f9a080331427a71dc99c30323
|
|
| MD5 |
dac79bf06d692ffd141f4d18b9b3b0b2
|
|
| BLAKE2b-256 |
273f3b77837d1719e874cfb426be646457f9b43c0f515bf716d4465037ff2b0b
|