derivkit.utils.numerics module#

Numerical utilities.

derivkit.utils.numerics.apply_hard_bounds(term: Callable[[ndarray[tuple[Any, ...], dtype[floating]]], floating], *, bounds: Sequence[tuple[floating | None, floating | None]] | None = None) Callable[[ndarray[tuple[Any, ...], dtype[floating]]], floating]#

Returns a bounded version of a log-density contribution.

A term is a callable that returns a scalar log-density contribution and support refers to the region where the density is non-zero.

This helper enforces a top-hat support region defined by bounds. If theta lies outside the allowed region, the result is -np.inf to denote zero probability. If theta lies inside the region, the provided term is evaluated and any non-finite output is treated as -np.inf.

Parameters:
  • term – Callable returning a log-density contribution.

  • bounds – Optional sequence of (lower, upper) pairs defining the allowed support region.

Returns:

A callable with the same signature as term that enforces the given bounds, or term itself if no bounds are provided.

derivkit.utils.numerics.central_difference_error_estimate(step_size: float, order: int = 1) float#

Computes a general heuristic size of the first omitted term in central-difference stencils.

Uses the general pattern h^2 / ((order + 1) * (order + 2)) as a rule-of-thumb O(h^2) truncation-error scale.

Parameters:
  • step_size – Grid spacing.

  • order – Derivative order (positive integer).

Returns:

Estimated truncation error scale.

Raises:

ValueError – If order is not a positive integer.

derivkit.utils.numerics.evaluate_logprior(theta: ArrayLike, logprior: Callable[[ndarray[tuple[Any, ...], dtype[floating]]], floating] | None) floating#

Evaluates a user-supplied log-prior callable at theta.

If logprior is None, a flat prior is assumed and this returns 0.0. If a callable is provided, its output is interpreted as a log-density defined up to an additive constant. Any non-finite output (e.g., -np.inf or np.nan) is treated as zero probability and mapped to -np.inf.

Parameters:
  • theta – Parameter vector at which to evaluate the prior.

  • logprior – Callable returning the log-prior density, or None to indicate a flat prior.

Returns:

Log-prior value at theta (finite or -np.inf).

derivkit.utils.numerics.get_index_value(theta: ArrayLike, index: int, *, name: str = 'theta') float#

Extracts a single parameter value from a 1D parameter vector.

This helper enforces that theta is one-dimensional and raises a clear, user-facing error if the requested index is out of bounds. It is intended for simple prior or likelihoods components that act on a single parameter.

Parameters:
  • theta – 1D parameter vector.

  • index – Index to extract.

  • name – Name used in error messages.

Returns:

Value at the given index as float.

Raises:
  • ValueError – If theta is not 1D.

  • IndexError – If index is out of bounds.

derivkit.utils.numerics.is_in_bounds(theta: ndarray[tuple[Any, ...], dtype[floating]], bounds: Sequence[tuple[floating | None, floating | None]] | None) bool#

Checks whether a parameter vector lies within specified bounds.

If bounds is None, this returns True by convention so callers can write if is_in_bounds(theta, bounds): ... without special-casing the absence of bounds.

Bounds are interpreted component-wise. For each parameter, either side may be unbounded by setting that limit to None.

Parameters:
  • theta – Parameter vector to test.

  • bounds – Optional sequence of (lower, upper) pairs, one per parameter. Use None for an unconstrained lower or upper limit.

Returns:

A boolean indicating whether all parameters satisfy their bounds (or True if bounds is None).

Raises:

ValueError – If bounds is provided and its length does not match theta.

derivkit.utils.numerics.logsumexp_1d(x: ArrayLike) float#

Computes log(sum(exp(x))) for a 1D array using the max-shift identity.

This implements the common max-shift trick used to reduce overflow/underflow.

Parameters:

x – 1D array-like values.

Returns:

Value of log(sum(exp(x))) as a float.

Raises:

ValueError – If x is not 1D.

derivkit.utils.numerics.relative_error(a: ndarray, b: ndarray) float#

Computes the relative error metric between a and b.

This metric is defined as the maximum over all components of a and b of the absolute difference divided by the maximum of 1.0 and the absolute values of a and b.

Parameters:
  • a – First array-like input.

  • b – Second array-like input.

Returns:

The relative error metric as a float.

derivkit.utils.numerics.sum_terms(*terms: Callable[[ndarray[tuple[Any, ...], dtype[floating]]], floating]) Callable[[ndarray[tuple[Any, ...], dtype[floating]]], floating]#

Constructs a composite log term by summing multiple contributions.

The returned callable evaluates each provided term at the same parameter vector and adds the results. If any term is non-finite, the composite term evaluates to -np.inf, corresponding to zero probability under the combined density.

A term is a callable that returns a scalar log-density contribution and support refers to the region where the density is non-zero.

Parameters:

*terms – One or more callables, each returning a log-density contribution.

Returns:

A callable that returns the sum of the provided log terms at theta.

Raises:

ValueError – If no terms are provided.