Source code for pyvbmc.priors.prior

from abc import ABC, abstractmethod

import numpy as np


[docs] class Prior(ABC): """Abstract base class for PyVBMC prior distributions."""
[docs] def log_pdf(self, x, keepdims=True): """Compute the log-pdf of the distribution. Parameters ---------- x : np.ndarray The array of input point(s), of dimension `(D,)` or `(n, D)`, where `d` is the distribution dimension. keepdims : bool Whether to keep the input dimensions and return an array of shape `(1, D)`, or discard them and return an array of shape `(D,)`. Returns ------- log_pdf : np.ndarray The log-density of the prior at the input point(s), of dimension `(n, 1)` or `(n,)` (depending on ``keepdims``). """ x_orig_shape = x.shape x = np.atleast_2d(x) n, D = x.shape if self.D == 1 and n == 1: x = x.T elif D != self.D: raise ValueError( f"x should have shape ({self.D},) or (n, {self.D}) but has shape {x_orig_shape}." ) log_pdf = self._log_pdf(x) if keepdims: return log_pdf else: return log_pdf.ravel()
[docs] def pdf(self, x, keepdims=True): """Compute the pdf of the distribution. Parameters ---------- x : np.ndarray The array of input point(s), of dimension `(D,)` or `(n, D)`, where `D` is the distribution dimension. keepdims : bool Whether to keep the input dimensions and return an array of shape `(1, D)`, or discard them and return an array of shape `(D,)`. returns ------- pdf : np.ndarray The density of the prior at the input point(s), of dimension `(n, 1)` or `(n,)` (depending on ``keepdims``). """ return np.exp(self.log_pdf(x, keepdims=keepdims))
[docs] def support(self): r"""Returns the support of the distribution. Used to test that the distribution integrates to one, so it is also acceptable to return a box which bounds the support of the distribution. Returns ------- lb, ub : tuple(np.ndarray, np.ndarray) A tuple of lower and upper bounds of the support, such that [``lb[i]``, ``ub[i]``] bounds the support of the ``i``\ th marginal. """ if hasattr(self, "_support"): return self._support() else: return np.full(self.D, -np.inf), np.full(self.D, np.inf)
@abstractmethod def __init__(self): """Initialize the distribution.""" self.D = 1 @abstractmethod def _log_pdf(self, x): """Compute the log-pdf of the distribution. This private method is wrapped by ``self.log_pdf()``, which handles input validation and output shape. Parameters ---------- x : np.ndarray The array of input point(s), of dimension `(D,)` or `(n, D)`, where `d` is the distribution dimension. Returns ------- log_pdf : np.ndarray The log-density of the prior at the input point(s), of dimension `(n, 1)`. """ pass
[docs] @abstractmethod def sample(self, n): """Sample random variables from the distribution. Parameters ---------- n : int The number of points to sample. Returns ------- rvs : np.ndarray The samples points, of shape `(n, D)`, where `D` is the dimension. """ pass
@classmethod @abstractmethod def _generic(cls, D=1): """Return a generic instance of the class (used for tests).""" return cls(D=D)