Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Binary-aware likelihood

San Diego State University

The binary-aware likelihood

The single-star likelihood

Lnaive(α)  =  i=1Nξ(Msys,iα)\mathcal{L}_{\mathrm{naive}}(\alpha) \;=\; \prod_{i=1}^{N} \xi(M_{\mathrm{sys},i} \mid \alpha)

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:

p(Mα)  =  (1fˉb)ξ(Mα)single  +  fˉbqmin1ξ ⁣(M1+qα)1+qg ⁣(qM1+q)dqbinaryp(M \mid \alpha) \;=\; \underbrace{(1 - \bar f_b)\,\xi(M \mid \alpha)}_{\text{single}} \;+\; \underbrace{\bar f_b \int_{q_{\min}}^{1} \frac{\xi\!\bigl(\tfrac{M}{1+q} \mid \alpha\bigr)}{1+q}\, g\!\bigl(q \mid \tfrac{M}{1+q}\bigr)\,\mathrm{d}q}_{\text{binary}}

Each term has direct physical meaning. The single-star contribution is the probability that the observed mass MM is just one star, with that star drawn from the IMF at mass MM. The binary contribution integrates over every possible mass-ratio qq for which the observed MM could be a binary: the primary had mass M/(1+q)M / (1+q), the secondary had qM/(1+q)q \cdot M / (1+q), and the IMF and mass-ratio distribution combine to give the joint probability density. The Jacobian 1/(1+q)1/(1+q) comes from the change of variables msys=m1(1+q)m_{\mathrm{sys}} = m_1 (1+q).

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:

  1. The IMF ξ\xi — closed form for Maschberger (2013), piecewise for Kroupa (2001).

  2. The mass-ratio distribution g(qm1)g(q \mid m_1)(1) from Mass-ratio distributions, piecewise in m1m_1 via the Moe & Di Stefano (2017) mass-bin lookup.

  3. The Jacobian 1/(1+q)1/(1+q) — trivial.

The piecewise mass-bin lookup in g(qm1)g(q \mid m_1) 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 m1=M/(1+q)m_1 = M/(1+q), which depends on the integration variable qq. progenax evaluates the integral numerically.

The Gauss-Legendre quadrature

For a smooth integrand on [a,b][a, b], KK-point Gauss-Legendre quadrature gives roughly 14 digits of accuracy at K=128K = 128. The integrand of (2) is smooth on the interior (qmin,1)(q_{\min}, 1) with weak edge behaviour at q1q \to 1 (where the Jacobian 1/(1+q)1/21/(1+q) \to 1/2 and the twin Gaussian peaks). Gauss-Legendre with K=128K = 128 nodes is the right tool:

qmin1h(q)dq    1qmin2k=1Kwkh ⁣((1qmin)xk+(1+qmin)2)\int_{q_{\min}}^{1} h(q)\,\mathrm{d}q \;\approx\; \frac{1 - q_{\min}}{2}\,\sum_{k=1}^{K} w_k\,h\!\biggl(\frac{(1 - q_{\min})\,x_k + (1 + q_{\min})}{2}\biggr)

where {xk,wk}\{x_k, w_k\} are the standard Gauss-Legendre nodes and weights on [1,1][-1, 1]. progenax precomputes {xk,wk}\{x_k, w_k\} 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 1010\le 10^{-10} relative error across the full α[0.5,4.0]\alpha \in [0.5, 4.0] range and M[mmin,mmax]M \in [m_{\min}, m_{\max}]. Smaller KK shows degradation near qminq_{\min} where the integrand can be steep.

Vectorisation: the N×KN \times K tile

For NN observed systems and KK 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 NN:

  1. Log-space evaluation. log_xi + log_g - log(1+q) is computed in log-space, then jnp.exp is applied before the quadrature sum. The intermediate log values can be large negative (for unlikely mass-ratio combinations), but never produce overflow.

  2. logsumexp for the final mixture. The single-star and binary contributions can differ by orders of magnitude at the tails of the mass distribution. progenax uses jax.scipy.special.logsumexp for the final log[(1fb)ξ+fbI]\log[(1-f_b)\xi + f_b\,I] to avoid catastrophic cancellation.

  3. qminq_{\min} floor. The integral lower limit is qmin=0.1q_{\min} = 0.1 matching Moe & Di Stefano (2017)’s observational completeness. progenax does not extrapolate below this; setting qmin=0q_{\min} = 0 would make the integral diverge for some IMF parameter values.

Computational cost

For NN observed systems and K=128K = 128 quadrature nodes, each likelihood evaluation requires N×KN \times K IMF + mass-ratio evaluations:

NN

N×KN \times K ops

CPU time

GPU time (A100)

100

1.3 ⁣× ⁣1041.3\!\times\!10^4

1\sim 1 ms

0.05\sim 0.05 ms

1{,}000

1.3 ⁣× ⁣1051.3\!\times\!10^5

5\sim 5 ms

0.1\sim 0.1 ms

10{,}000

1.3 ⁣× ⁣1061.3\!\times\!10^6

50\sim 50 ms

0.5\sim 0.5 ms

30{,}000

3.8 ⁣× ⁣1063.8\!\times\!10^6

150\sim 150 ms

1\sim 1 ms

Per chain (NUTS, 1500 steps) at N=30,000N = 30{,}000:

The N×KN \times K tile is embarrassingly parallel via jax.vmap, which is what makes the GPU advantage so dramatic.

Differentiability

Every step in (2) is JAX-differentiable:

jax.grad(log_likelihood)(alpha, M_sys) returns logL/α\partial \log \mathcal{L}/\partial \alpha 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 R^<1.01\hat R < 1.01 on α\alpha at N=30,000N = 30{,}000.

What if the binary statistics are wrong?

The likelihood above assumes known fb(m1)f_b(m_1) and g(qm1)g(q \mid m_1). In real applications, the Moe & Di Stefano (2017) calibration carries its own uncertainties: ±0.04\pm 0.04 for solar-type binary fractions, growing to ±0.10\pm 0.10 for O-stars. Misspecification of these statistics reintroduces bias on α\alpha at large NN.

The architectural extension is a hierarchical likelihood: jointly infer α\alpha alongside hyper-parameters of the binary statistics (an overall fbf_b multiplicative factor, a γ\gamma 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

References
  1. 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
  2. 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
  3. 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