Skip to content

Add TruncatedNormal#91

Open
gvcallen wants to merge 1 commit into
lockwo:mainfrom
gvcallen:trunc_normal
Open

Add TruncatedNormal#91
gvcallen wants to merge 1 commit into
lockwo:mainfrom
gvcallen:trunc_normal

Conversation

@gvcallen

@gvcallen gvcallen commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Truncated Normal distribution with loc, scale, low, and high parameters. Every closed-form formula (sample, log_prob, cdf, icdf, survival function, entropy, mean, variance, mode, median) is cross-checked numerically against scipy.stats.truncnorm. KL divergence between arbitrary truncated normals isn't analytically tractable and raises NotImplementedError.

Truncated Normal distribution with loc, scale, low, and high parameters.
Every closed-form formula (sample, log_prob, cdf, icdf, survival
function, entropy, mean, variance, mode, median) is cross-checked
numerically against scipy.stats.truncnorm. KL divergence between
arbitrary truncated normals isn't analytically tractable and raises
NotImplementedError.
low: Array
high: Array

def __init__(self, loc: Array, scale: Array, low: Array, high: Array):

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can type better/more specific? + fields


def __init__(self, loc: Array, scale: Array, low: Array, high: Array):
"""Initializes a Truncated Normal distribution.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for docstrings with fields you can set the init.docs (I did this with uniform e.g.

return self._standardize(self.high)

def _log_normalizer(self) -> Array:
"""Calculates the log of the normalization constant Z."""

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should include math in the description to define Z (of the class)

"""Calculates the log of the normalization constant Z."""
cdf_high = jax.scipy.special.ndtr(self._std_high)
cdf_low = jax.scipy.special.ndtr(self._std_low)
return jnp.log(cdf_high - cdf_low)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also should this just be a property or member variable?

"""Calculates the log of the normalization constant Z."""
cdf_high = jax.scipy.special.ndtr(self._std_high)
cdf_low = jax.scipy.special.ndtr(self._std_low)
return jnp.log(cdf_high - cdf_low)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we probably want to do this in log space? like with jax.scipy.special.log_ndtr right, since large distributions e.g. TruncatedNormal(0, 1, 8, 9).icdf(0.5) is inf but is stable with scipy.

Z = jax.scipy.special.ndtr(beta) - jax.scipy.special.ndtr(alpha)

pdf_alpha = self._pdf(alpha)
pdf_beta = self._pdf(beta)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want to support single bounded distributions, e.g. [10, inf) truncation? this might hit a NaN here if so

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants