Skip to main content

Stateful adaptive quadrature with exact node reuse.

Project description

Stateful Quadrature

stateful_quadrature is a focused adaptive quadrature package for repeated finite-domain integrals of the form

I(lambda) = integral Psi(x, K(x), lambda) dx

where K(x) is expensive, independent of lambda, and worth caching exactly.

The package is intentionally small. Its public surface centers on stateful_quadrature.StatefulIntegrator, which keeps a live adaptive leaf mesh and reuses cached kernel payloads exactly across repeated calls. It can also prepare mutable per-node payload objects once and reuse them across later integrations.

The package is inspired by SciPy's cubature function.

What It Does

  • adaptive finite-domain quadrature on rectangular regions,
  • exact per-leaf kernel reuse across repeated integrations,
  • optional one-time prepared payload building for mutable node-local state,
  • scalar, vector, matrix, complex, and fixed-shape tensor outputs,
  • built-in gk21 for 1D integrals,
  • built-in genz_malik for ndim >= 2.

Each active leaf stores only its bounds, cached payloads at that leaf's rule nodes, and its current estimate and error. Cached payloads can be raw numeric kernel arrays or prepared per-node objects. When the parameters change, the mesh is reused as-is: cached payloads stay valid, the cheap evaluator is recomputed on the current leaves, and refinement only continues if the new parameter still fails tolerance.

Current Limits

  • finite rectangular domains only,
  • no SciPy compatibility wrapper,
  • no infinite limits,
  • no breakpoint seeding,
  • no disk-backed caches or serialization,
  • no public custom-rule API.

Installation

Install from PyPI:

python -m pip install stateful-quadrature

For local development in a clone, prefer Pixi:

pixi run test
pixi run example

If you want an editable Python install in the same clone:

python -m pip install -e .

Minimal Example

import numpy as np

from stateful_quadrature import StatefulIntegrator


def kernel(points):
    x = points[:, 0]
    return np.stack([np.sin(x), np.cos(x)], axis=-1)


def evaluator(points, payload, params):
    alpha = params["alpha"]
    return payload[:, 0] + alpha * payload[:, 1]


integrator = StatefulIntegrator(
    a=[-1.0],
    b=[1.0],
    kernel=kernel,
    evaluator=evaluator,
    rule="gk21",
)

result = integrator.integrate(alpha=1.5, atol=1e-10, rtol=1e-10)
print(result.status, result.estimate, result.error)

The example above integrates sin(x) + 1.5 cos(x) over [-1, 1]. The returned IntegrationResult also includes n_kernel_evals, n_evaluator_evals, n_leaves, n_leaf_nodes, and subdivisions.

An executable copy of this example lives in examples/basic_usage.py and can be run from a clone with pixi run example.

Prepared Payloads

If raw numeric kernel data should be turned into mutable node-local state once, pass a payload_builder:

import numpy as np

from stateful_quadrature import StatefulIntegrator


def kernel(points):
    return points[:, 0]


def payload_builder(points, raw_payloads):
    return [{"value": float(value), "history": []} for value in raw_payloads]


def evaluator(points, payloads, scale):
    return np.array([scale * payload["value"] for payload in payloads])


integrator = StatefulIntegrator(
    a=[0.0],
    b=[1.0],
    kernel=kernel,
    evaluator=evaluator,
    payload_builder=payload_builder,
)

kernel still returns numeric arrays. payload_builder(points, raw_payloads) runs only when new rule nodes are created and must return one prepared payload object per input point. The evaluator then receives a Python list of prepared payloads aligned with points.

Repeated integrate(...) calls reuse the same prepared payload objects on the live mesh, and replace_evaluator(...) shallow-shares those objects into the cloned integrator.

Reusing The Live Mesh

If a second integral uses the same kernel but a different evaluator, clone the live mesh with:

other = integrator.replace_evaluator(other_evaluator)

The new integrator shares the current leaf payload cache but can refine independently from that point onward. This applies to both numeric payload arrays and prepared payload objects.

integrate(...) accepts either a single params object or keyword arguments. Keyword arguments are bundled into a dictionary and passed to the evaluator as the third argument.

Output Shapes

The evaluator can return any fixed trailing shape. Typical forms are:

  • scalar output: (npoints,),
  • vector output: (npoints, m),
  • matrix output: (npoints, m, n),
  • higher-rank tensor output: (npoints, *shape).

The trailing shape must stay fixed for a given integrator instance.

Development

This repository is Pixi-centric. The default Pixi environment provides the supported local development workflow.

Run the test suite:

pixi run test

Run the executable example:

pixi run example

Run the optional SciPy benchmark comparison:

pixi run -e test benchmark-quick

The benchmark script is for local comparison work and is not part of the package runtime dependency set.

Maintainers

Maintainer workflow notes live in RELEASING.md.

For design background on the leaf-only reuse model, see DESIGN.md.

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

stateful_quadrature-0.2.1.tar.gz (15.0 kB view details)

Uploaded Source

Built Distribution

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

stateful_quadrature-0.2.1-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

File details

Details for the file stateful_quadrature-0.2.1.tar.gz.

File metadata

  • Download URL: stateful_quadrature-0.2.1.tar.gz
  • Upload date:
  • Size: 15.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for stateful_quadrature-0.2.1.tar.gz
Algorithm Hash digest
SHA256 931f86b3947146d20b0d335ae871288650877bed052c9c15f5e0c46da3d5f26d
MD5 93f050005d5fdbdf6ebcd5166f6f92e1
BLAKE2b-256 f2b86c1f8c77d9d50dbbeacf4ed8359424e21a674a2e151bf582c31992c4b4ea

See more details on using hashes here.

Provenance

The following attestation bundles were made for stateful_quadrature-0.2.1.tar.gz:

Publisher: publish.yml on Kostusas/stateful_quadrature

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file stateful_quadrature-0.2.1-py3-none-any.whl.

File metadata

File hashes

Hashes for stateful_quadrature-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f88dc0e9d780df20f824020542b73357411db21440ddf9d81a9512df7b5cb868
MD5 efed38c6d780446d74e1a4b82779aae6
BLAKE2b-256 a08c0f661a4d9c796e5e06dd80812641729ebce9e83012f6412bf60b2741e815

See more details on using hashes here.

Provenance

The following attestation bundles were made for stateful_quadrature-0.2.1-py3-none-any.whl:

Publisher: publish.yml on Kostusas/stateful_quadrature

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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