derivkit.forecasting.expansions module#
Utilities for evaluating Fisher and DALI likelihood expansions.
This module provides functional helpers to evaluate approximate likelihoods (or posterior) surfaces from forecast tensors.
Conventions#
This module uses a single convention throughout:
delta_chi2is defined from the displacementd = theta - theta0.The log posterior is returned (up to an additive constant) as:
log p(theta) = logprior(theta) - 0.5 * delta_chi2(theta)
With the forecast tensors returned by derivkit.forecasting.get_forecast_tensors()
(using the introduced-at-order convention):
dali[1] == (F,)dali[2] == (D1, D2)dali[3] == (T1, T2, T3)
the DALI delta_chi2 is:
order 1 (Fisher):
d.T @ F @ dorder 2 (doublet): add
(1/3) D1[d,d,d] + (1/12) D2[d,d,d,d]order 3 (triplet): add
(1/3) T1[d^4] + (1/6) T2[d^5] + (1/36) T3[d^6]
GetDist convention#
GetDist expects loglikes to be the negative log posterior, up to a constant.
Since this module defines:
log p = logprior - 0.5 * delta_chi2 + const
a compatible choice for GetDist is:
loglikes = -logprior + 0.5 * delta_chi2
(optionally shifted by an additive constant for numerical stability).
- derivkit.forecasting.expansions.build_delta_chi2_dali(theta: ndarray[tuple[Any, ...], dtype[floating]], theta0: ndarray[tuple[Any, ...], dtype[floating]], dali: Any, *, forecast_order: int | None = 2) float#
Compute
delta_chi2under the DALI approximation.This evaluates a scalar
delta_chi2from the displacementd = theta - theta0using forecast tensors returned byderivkit.forecasting.get_forecast_tensors().The input must be the dict form using the introduced-at-order convention:
dali[1] == (F,)withFof shape(p, p)dali[2] == (D1, D2)with shapes(p, p, p)and(p, p, p, p)dali[3] == (T1, T2, T3)with shapes(p,)*4,(p,)*5,(p,)*6
The evaluated quantity is:
order 2:
d.T @ F @ d + (1/3) D1[d^3] + (1/12) D2[d^4]order 3: order 2 plus
(1/3) T1[d^4] + (1/6) T2[d^5] + (1/36) T3[d^6].
- Parameters:
theta – Evaluation point in parameter space.
theta0 – Expansion point (fiducial parameters).
dali – Forecast tensors as a dict.
forecast_order – Maximum order to include. If
None, uses the highest key indaliand requires it to be at least 2.
- Returns:
Scalar
delta_chi2.- Raises:
TypeError – If
daliis not a dict.ValueError – If required tensor orders are missing or have incompatible shapes.
- derivkit.forecasting.expansions.build_delta_chi2_fisher(theta: ndarray[tuple[Any, ...], dtype[floating]], theta0: ndarray[tuple[Any, ...], dtype[floating]], fisher: ndarray[tuple[Any, ...], dtype[floating]]) float#
Computes a displacement chi-squared under the Fisher approximation.
- Parameters:
theta – Evaluation point in parameter space. This is the trial parameter vector at which the Fisher expansion is evaluated.
theta0 – Expansion point (reference parameter vector). The Fisher matrix is assumed to have been computed at this point, and the expansion is taken in the displacement
theta - theta0.fisher – Fisher matrix with shape
(p, p)withpthe number of parameters.
- Returns:
The scalar delta chi-squared value between
thetaandtheta_0.
- derivkit.forecasting.expansions.build_logposterior_dali(theta: ndarray[tuple[Any, ...], dtype[floating]], theta0: ndarray[tuple[Any, ...], dtype[floating]], dali: Any, *, forecast_order: int | None = 2, prior_terms: Sequence[tuple[str, dict[str, Any]] | dict[str, Any]] | None = None, prior_bounds: Sequence[tuple[float | None, float | None]] | None = None, logprior: Callable[[ndarray[tuple[Any, ...], dtype[floating]]], float] | None = None) float#
Compute the log posterior under the DALI approximation.
The posterior is evaluated as:
log p(theta) = logprior(theta) - 0.5 * delta_chi2(theta)
where
delta_chi2is computed from the dict-form forecast tensorsdaliusingbuild_delta_chi2_dali().- Parameters:
theta – Evaluation point in parameter space.
theta0 – Expansion point (fiducial parameters).
dali – Forecast tensors as a dict in the introduced-at-order convention.
forecast_order – Maximum order to include in
delta_chi2. IfNone, uses the highest key indali.prior_terms – Prior term specification passed to
build_prior().prior_bounds – Global hard bounds passed to
build_prior().logprior – Optional custom log-prior callable.
- Returns:
Scalar log posterior value (up to an additive constant). If the prior evaluates to a non-finite value, returns
-np.inf.
- derivkit.forecasting.expansions.build_logposterior_fisher(theta: ndarray[tuple[Any, ...], dtype[floating]], theta0: ndarray[tuple[Any, ...], dtype[floating]], fisher: ndarray[tuple[Any, ...], dtype[floating]], *, prior_terms: Sequence[tuple[str, dict[str, Any]] | dict[str, Any]] | None = None, prior_bounds: Sequence[tuple[float | None, float | None]] | None = None, logprior: Callable[[ndarray[tuple[Any, ...], dtype[floating]]], float] | None = None) float#
Computes the log posterior under the Fisher approximation.
The returned value is defined up to an additive constant in log space. This corresponds to an overall multiplicative normalization of the posterior density in probability space.
If no prior is provided, this returns the Fisher log-likelihoods expansion with a flat prior and no hard cutoffs.
The Fisher approximation corresponds to a purely quadratic
delta_chi2surface:delta_chi2 = d.T @ F @ d
so the log posterior is:
log p = -0.5 * delta_chi2
This normalization is equivalent to the
convention="delta_chi2"used for DALI. In this interpretation, fixeddelta_chi2values correspond to fixed probability content (e.g. 68%, 95%) in parameter space, as for a Gaussian likelihoods. Seederivkit.forecasting.expansions.delta_chi2_dali()for the corresponding DALI definition ofdelta_chi2and its supported conventions.Unlike the DALI case, there is no alternative normalization for the Fisher approximation: the likelihoods is strictly Gaussian and fully described by the quadratic form.
- Parameters:
theta – Evaluation point in parameter space. This is the trial parameter vector at which the Fisher/DALI expansion is evaluated.
theta0 – Expansion point (reference parameter vector). The Fisher matrix and any DALI tensors are assumed to have been computed at this point, and the expansion is taken in the displacement
theta - theta0.fisher – Fisher matrix with shape
(p, p)withpthe number of parameters.prior_terms – prior term specification passed to
derivkit.forecasting.priors.core.build_prior().prior_bounds – Global hard bounds passed to
derivkit.forecasting.priors.core.build_prior().logprior – Optional custom log-prior callable. If it returns a non-finite value, the posterior is treated as zero at that point and the function returns
-np.inf.
- Returns:
Scalar log posterior value, defined up to an additive constant.
- derivkit.forecasting.expansions.build_subspace(idx: Sequence[int], *, theta0: ndarray[tuple[Any, ...], dtype[floating]], fisher: ndarray[tuple[Any, ...], dtype[floating]] | None = None, dali: dict[int, tuple[ndarray[tuple[Any, ...], dtype[floating]], ...]] | None = None) dict[str, Any]#
Extracts a parameter subspace for Fisher or DALI expansions.
This returns a slice through parameter space: parameters not in
idxare held fixed at their expansion values. This is not a marginalization.Provide exactly one of
fisherordali:Fisher:
fisherhas shape(p, p)and the return dict contains{"theta0": theta0_sub, "fisher": fisher_sub}.DALI:
daliis the dict form returned byderivkit.forecasting.get_forecast_tensors()using the introduced-at-order convention, and the return dict contains{"theta0": theta0_sub, "dali": dali_sub}.
- Parameters:
idx – Parameter indices to extract.
theta0 – Expansion point of shape
(p,).fisher – Fisher matrix of shape
(p, p).dali – Forecast tensors as a dict mapping
order -> multiplet.
- Returns:
A dict containing the sliced objects. Always includes
"theta0". Includes"fisher"iffisherwas provided, or"dali"ifdaliwas provided.- Raises:
ValueError – If not exactly one of
fisherordaliis provided.TypeError – If
idxcontains non-integers, or ifdaliis not a dict.IndexError – If any index in
idxis out of bounds.ValueError – If the provided arrays have incompatible shapes.