Source code for bayesflow.simulators.benchmark_simulators.slcp

import numpy as np

from .benchmark_simulator import BenchmarkSimulator


[docs] class SLCP(BenchmarkSimulator): def __init__( self, lower_bound: float = -3.0, upper_bound: float = 3.0, n_obs: int = 4, flatten: bool = True, rng: np.random.Generator = None, ): """SLCP simulated benchmark See https://arxiv.org/pdf/2101.04653.pdf, Task T.3 Parameters ---------- lower_bound: float, optional, default: -3.0 The lower bound of the uniform prior. upper_bound: float, optional, default: 3.0 The upper bound of the uniform prior. n_obs: int, optional, default: 4 The number of observations to generate from the slcp likelihood. flatten: bool, optional, default: True A flag to indicate whather a 1D (`flatten=True`) or a 2D (`flatten=False`) representation of the simulated data is returned. rng: np.random.Generator or None, optional, default: None An optional random number generator to use. """ self.lower_bound = lower_bound self.upper_bound = upper_bound self.n_obs = n_obs self.flatten = flatten self.rng = rng if self.rng is None: self.rng = np.random.default_rng()
[docs] def prior(self): """Generates a random draw from a 5-dimensional uniform prior bounded between `lower_bound` and `upper_bound` which represents the 5 parameters of the SLCP simulator. Returns ------- params : np.ndarray of shape (5, ) A single draw from the 5-dimensional uniform prior. """ return self.rng.uniform(low=self.lower_bound, high=self.upper_bound, size=5)
[docs] def observation_model(self, params: np.ndarray): """Generates data from the SLCP model designed as a benchmark for a simple likelihood and a complex posterior due to a non-linear pushforward params -> x. Parameters ---------- params : np.ndarray of shape (params, D) The location parameters of the Gaussian likelihood. Returns ------- x : np.ndarray of shape (n_obs*2, ) or (n_obs, 2), as indictated by the `flatten` boolean flag. The sample of simulated data from the SLCP model. """ # Specify 2D location loc = np.array([params[0], params[1]]) # Specify 2D covariance matrix s1 = params[2] ** 2 s2 = params[3] ** 2 rho = np.tanh(params[4]) cov = rho * s1 * s2 S_param = np.array([[s1**2, cov], [cov, s2**2]]) # Obtain given number of draws from the MVN likelihood x = self.rng.multivariate_normal(loc, S_param, size=self.n_obs) if self.flatten: return x.flatten() return x