The binary-aware likelihood¶
The single-star likelihood
assumes every observed system mass is a single star. The binary-aware likelihood corrects this by marginalising over the latent binary status and mass ratio of each observation:
Each term has direct physical meaning. The single-star contribution is the probability that the observed mass is just one star, with that star drawn from the IMF at mass . The binary contribution integrates over every possible mass-ratio for which the observed could be a binary: the primary had mass , the secondary had , and the IMF and mass-ratio distribution combine to give the joint probability density. The Jacobian comes from the change of variables .
This page derives the integrand, walks through the 128-point Gauss-Legendre quadrature progenax uses, and quantifies the cost.
Why no closed form¶
The integrand of (2) involves three pieces that all have closed-form expressions individually, but no closed form for their product:
The IMF — closed form for Maschberger (2013), piecewise for Kroupa (2001).
The mass-ratio distribution — (1) from Mass-ratio distributions, piecewise in via the Moe & Di Stefano (2017) mass-bin lookup.
The Jacobian — trivial.
The piecewise mass-bin lookup in is what kills any hope of a closed form. The integrand is a sum of products of analytic pieces, but the boundaries of each piece depend on the candidate primary mass , which depends on the integration variable . progenax evaluates the integral numerically.
The Gauss-Legendre quadrature¶
For a smooth integrand on , -point Gauss-Legendre quadrature gives roughly 14 digits of accuracy at . The integrand of (2) is smooth on the interior with weak edge behaviour at (where the Jacobian and the twin Gaussian peaks). Gauss-Legendre with nodes is the right tool:
where are the standard Gauss-Legendre nodes and weights on . progenax precomputes at module-import time and passes them as a fixed array to the JIT-compiled likelihood.
The 128-point choice is calibrated against analytic test cases (where the integrand reduces to closed-form sub-cases) to give relative error across the full range and . Smaller shows degradation near where the integrand can be steep.
Vectorisation: the tile¶
For observed systems and quadrature points, the likelihood evaluation is a tensor contraction:
@jax.jit
def log_likelihood(alpha, M_sys):
# q_nodes, w_nodes: shape (K,) — fixed
q = q_nodes_scaled # (K,)
# Candidate primary masses for each (M_sys, q) pair
m1 = M_sys[:, None] / (1.0 + q[None, :]) # (N, K)
# IMF + mass-ratio distribution at each (m1, q)
log_xi = imf.logpdf(m1, alpha=alpha) # (N, K)
log_g = mass_ratio_log_prob(q[None, :], m1) # (N, K)
# Integrand and quadrature
log_integrand = log_xi + log_g - jnp.log(1.0 + q[None, :])
binary_integral = jnp.sum(w_nodes * jnp.exp(log_integrand), axis=1)
# Combine single + binary contributions
f_b = binary_fraction(M_sys) # (N,)
p = (1 - f_b) * jnp.exp(imf.logpdf(M_sys, alpha)) + f_b * binary_integral
return jnp.sum(jnp.log(p))The whole pipeline is one JIT trace and one device call — no Python loops, no rejection sampling, no per-particle branching. Gradients flow analytically through every line.
Numerical-stability notes¶
Three details that matter at large :
Log-space evaluation.
log_xi + log_g - log(1+q)is computed in log-space, thenjnp.expis applied before the quadrature sum. The intermediate log values can be large negative (for unlikely mass-ratio combinations), but never produce overflow.logsumexpfor the final mixture. The single-star and binary contributions can differ by orders of magnitude at the tails of the mass distribution. progenax usesjax.scipy.special.logsumexpfor the final to avoid catastrophic cancellation.floor. The integral lower limit is matching Moe & Di Stefano (2017)’s observational completeness. progenax does not extrapolate below this; setting would make the integral diverge for some IMF parameter values.
Computational cost¶
For observed systems and quadrature nodes, each likelihood evaluation requires IMF + mass-ratio evaluations:
ops | CPU time | GPU time (A100) | |
|---|---|---|---|
100 | ms | ms | |
1{,}000 | ms | ms | |
10{,}000 | ms | ms | |
30{,}000 | ms | ms |
Per chain (NUTS, 1500 steps) at :
CPU: minutes per chain.
GPU (A100): seconds per chain — a speedup.
The tile is embarrassingly parallel via jax.vmap, which
is what makes the GPU advantage so dramatic.
Differentiability¶
Every step in (2) is JAX-differentiable:
— analytic in for Maschberger (2013), piecewise-analytic for Kroupa (2001).
— power-law and Gaussian both analytic; the mass-bin lookup uses
jnp.where(smooth fallback for boundary derivatives optional via sigmoid-blend).—
jnp.interpon the Moe & Di Stefano (2017) Table 13 values, differentiable via piecewise-linear gradients.The Gauss-Legendre quadrature is a fixed weighted sum.
jax.grad(log_likelihood)(alpha, M_sys) returns in one backward pass; jax.hessian
returns the Fisher-information matrix needed for Laplace-approximation
posteriors. Both work without any rewriting.
Connection to NUTS / NumPyro¶
progenax exposes the binary-aware likelihood through a NumPyro
numpyro.factor statement:
import numpyro
import numpyro.distributions as dist
def model(M_sys):
alpha = numpyro.sample("alpha", dist.Uniform(0.5, 4.0))
numpyro.factor("ll", log_likelihood(alpha, M_sys))
# Run NUTS
from numpyro.infer import MCMC, NUTS
mcmc = MCMC(NUTS(model), num_warmup=500, num_samples=1000, num_chains=4)
mcmc.run(jax.random.PRNGKey(0), M_sys=observed_masses)NUTS adaptively chooses step sizes and trajectory lengths; the binary-aware likelihood’s smooth gradients keep step-size adaptation stable across the full prior range. Production runs (the validation suite at Binary-aware IMF validation) use 4 chains × 1500 post-warmup samples, which is sufficient for on at .
What if the binary statistics are wrong?¶
The likelihood above assumes known and . In real applications, the Moe & Di Stefano (2017) calibration carries its own uncertainties: for solar-type binary fractions, growing to for O-stars. Misspecification of these statistics reintroduces bias on at large .
The architectural extension is a hierarchical likelihood: jointly
infer alongside hyper-parameters of the binary statistics
(an overall multiplicative factor, a offset). The
extra parameters cost 2–3 NUTS steps in convergence rate but produce
posteriors that account for the calibration uncertainty. progenax does
not currently export a BinaryIMF.with_inferred_binary_stats() helper;
this is a planned likelihood-layer extension rather than a live API.
Implementation, validation & references¶
In code: the binary-aware forward model lives in
src/progenax/imf/binary/imf.py(BinaryIMF); thelog_likelihoodblock on this page is schematic pseudocode (the publicBinaryIMFexposes sampling helpers, not this exactlog_prob). See the IMF API.Validated in: binary-aware recovery — 4 chains × 1500 post-warmup samples demonstrate unbiased recovery () at .
Primary sources: the likelihood structure and “confidently wrong” framing are original to progenax; the binary-statistics calibration is Moe & Di Stefano (2017), sampled with NUTS via NumPyro. Full notes in the bibliography; the scientific context is at Binary-aware IMF recovery.
- Maschberger, T. (2013). On the function describing the stellar initial mass function. Monthly Notices of the Royal Astronomical Society, 429, 1725–1733. 10.1093/mnras/sts479
- Kroupa, P. (2001). On the variation of the initial mass function. Monthly Notices of the Royal Astronomical Society, 322, 231–246. 10.1046/j.1365-8711.2001.04022.x
- Moe, M., & Di Stefano, R. (2017). Mind your Ps and Qs: The interrelation between period (P) and mass-ratio (Q) distributions of binary stars. The Astrophysical Journal Supplement Series, 230, 15. 10.3847/1538-4365/aa6fb6