Extending
Theories and likelihoods are Equinox modules: plug in any differentiable code or data.
From a function
For toy models and quick fits, wrap functions written with jax.numpy:
import jax.numpy as jnp
from cosmonuts import Model, Uniform
from cosmonuts.external import FunctionLikelihood, FunctionTheory
x = jnp.linspace(0.0, 1.0, 20)
y = 1.0 + 2.0 * x
s = 0.1
line = FunctionTheory(lambda a, b: {"y": lambda x: a + b * x}, provides={"y"})
fit = FunctionLikelihood(
lambda provider: -0.5 * jnp.sum((provider.y(x) - y) ** 2 / s**2),
requires={"y"}, name="points",
)
model = Model(line, [fit], {"a": Uniform(-5, 5), "b": Uniform(-5, 5)})
FunctionTheory takes its parameters from the
function's argument names. FunctionLikelihood
returns \(\log L\) and reads the theory's output through an argument named provider.
NoTheory covers likelihoods that only read parameters.
In a run file, the same lambdas are written as strings (see Run files and CLI).
Subclass
- A
Theorysetsparamsand implements__call__(params), returning a provider with the quantities ofProviderit serves and anokflag. - A
Likelihoodsetsrequiresand implementslog_likelihood(provider, params). GaussianLikelihoodneeds onlydata, a covariance andtheory_vector(provider, params).
Keep the code differentiable and jit-able; return ok=False instead of raising when the
theory fails at a parameter point.
Optional backends
If your theory needs a heavy dependency, import it inside the methods that use it, as
the bundled ClassETheory and EFT4PyTheory do, and expose it as an extra.
To feed a bundled likelihood, return the quantities it requires with their standard signatures. Run-file names resolve to your classes by import path:
theory:
mypackage.mytheory:MyTheory: {option: 1}