Skip to main content

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

perturbation_kernel-2.0.0.tar.gz (112.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

perturbation_kernel-2.0.0-cp38-abi3-win_amd64.whl (2.8 MB view details)

Uploaded CPython 3.8+Windows x86-64

perturbation_kernel-2.0.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.4 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ x86-64

perturbation_kernel-2.0.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.3 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARM64

perturbation_kernel-2.0.0-cp38-abi3-macosx_11_0_arm64.whl (1.9 MB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

perturbation_kernel-2.0.0-cp38-abi3-macosx_10_12_x86_64.whl (2.0 MB view details)

Uploaded CPython 3.8+macOS 10.12+ x86-64

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

Hashes for perturbation_kernel-2.0.0.tar.gz
Algorithm Hash digest
SHA256 353d3e8228ab8dc5f0b736bd3c61dc0308b8ca2170085f3af555d7e04796178f
MD5 149aef7a4a609827cf85a01d4cf128a1
BLAKE2b-256 7737d35c7371cea270a20887c77ca8d5b8be7ebb20c04e340e2a71fd50d29ac9

See more details on using hashes here.

File details

Details for the file perturbation_kernel-2.0.0-cp38-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for perturbation_kernel-2.0.0-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 8bdf4b681999f2277ce5dc9eb5056661f24c9bdd7cae73156b7728387a6077b3
MD5 4c405e7a803fd82090aa76f6e7c704f4
BLAKE2b-256 64a04152cb405addbcf19eb537076954735ceeb0792686ec1a36b4c37f4035ee

See more details on using hashes here.

File details

Details for the file perturbation_kernel-2.0.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for perturbation_kernel-2.0.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 92b88e951db5f355004ff4247223ccfa2c0409ba0f5c9f707fde633a6aacce52
MD5 9149e584c371bf9c754cc1442bdc5a75
BLAKE2b-256 03423512597dfad3b4264d1308b28d69fd1e20f3149383169a70d6e301436cf3

See more details on using hashes here.

File details

Details for the file perturbation_kernel-2.0.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for perturbation_kernel-2.0.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 30b66bd269a408c423749623fc440d9e8cadd0e7ad59c7444b0743201af1a200
MD5 ea43a373f86787db6e4041f4338ed4d7
BLAKE2b-256 9d19a11085a132fee8a55c6dba1bab3a7cb8d2d9e60255d72ff9cf8e1e783410

See more details on using hashes here.

File details

Details for the file perturbation_kernel-2.0.0-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for perturbation_kernel-2.0.0-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d08124cfeba4b82d1f947fe0b61136c3c9b523193827fee1e0979276f8a17df4
MD5 4570051cd0d4ff422094580b1fef88b9
BLAKE2b-256 5fb2ac888c8e0a4a068863e71f00013e8427d27b443382fc136b03c8c48da528

See more details on using hashes here.

File details

Details for the file perturbation_kernel-2.0.0-cp38-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for perturbation_kernel-2.0.0-cp38-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 d28420c57a0160d1b2e87adaaa3a80f4ced3a19f9a080331427a71dc99c30323
MD5 dac79bf06d692ffd141f4d18b9b3b0b2
BLAKE2b-256 273f3b77837d1719e874cfb426be646457f9b43c0f515bf716d4465037ff2b0b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page