|
| 1 | +""" |
| 2 | +Simple Inverse-Transform Sampling Strategy |
| 3 | +========================================== |
| 4 | +
|
| 5 | +This module provides a basic univariate sampler based on inverse transform |
| 6 | +sampling (also known as the quantile/PPF method). It is used as a fallback |
| 7 | +when advanced sampling methods (e.g. UNU.RAN) are not available. |
| 8 | +""" |
| 9 | + |
| 10 | +from __future__ import annotations |
| 11 | + |
| 12 | +__author__ = "Leonid Elkin, Mikhail Mikhailov" |
| 13 | +__copyright__ = "Copyright (c) 2025 PySATL project" |
| 14 | +__license__ = "SPDX-License-Identifier: MIT" |
| 15 | + |
| 16 | +from typing import TYPE_CHECKING, Any, cast |
| 17 | + |
| 18 | +import numpy as np |
| 19 | + |
| 20 | +from pysatl_core.distributions.strategies import SamplingStrategy |
| 21 | +from pysatl_core.types import CharacteristicName, NumericArray |
| 22 | + |
| 23 | +if TYPE_CHECKING: |
| 24 | + from pysatl_core.distributions.distribution import Distribution |
| 25 | + |
| 26 | + |
| 27 | +class DefaultSamplingUnivariateStrategy(SamplingStrategy): |
| 28 | + """ |
| 29 | + Default univariate sampler based on inverse transform sampling. |
| 30 | +
|
| 31 | + This strategy generates samples by applying the PPF (inverse CDF) |
| 32 | + to uniformly distributed random variables. |
| 33 | +
|
| 34 | + Notes |
| 35 | + ----- |
| 36 | + - Requires the distribution to provide a PPF computation method. |
| 37 | + - Assumes that the PPF follows NumPy semantics (vectorized evaluation). |
| 38 | + - Graph-derived PPFs (scalar-only) are currently not supported. |
| 39 | + - Returns a NumPy array containing the generated samples. |
| 40 | + """ |
| 41 | + |
| 42 | + def sample(self, n: int, distr: Distribution, **options: Any) -> NumericArray: |
| 43 | + """ |
| 44 | + Generate samples from the distribution. |
| 45 | +
|
| 46 | + Parameters |
| 47 | + ---------- |
| 48 | + n : int |
| 49 | + Number of samples to generate. |
| 50 | + distr : Distribution |
| 51 | + Distribution to sample from. |
| 52 | + **options : Any |
| 53 | + Additional options forwarded to the PPF computation. |
| 54 | +
|
| 55 | + Returns |
| 56 | + ------- |
| 57 | + NumericArray |
| 58 | + NumPy array containing ``n`` generated samples. |
| 59 | + The exact array shape depends on the distribution and sampling strategy. |
| 60 | + """ |
| 61 | + ppf = distr.query_method(CharacteristicName.PPF, **options) |
| 62 | + rng = np.random.default_rng() |
| 63 | + U = rng.random(n) |
| 64 | + # TODO: Now it will be based on the fact that the characteristic |
| 65 | + # has NumPy semantics (It is much more faster), that is, |
| 66 | + # it will not work with the graph computed characteristics currently. |
| 67 | + samples = ppf(U) |
| 68 | + return cast(NumericArray, samples) |
0 commit comments