Loading CHANGELOG.md +4 −2 Original line number Diff line number Diff line Loading @@ -14,7 +14,9 @@ v1.0.2 * Fixed documentation typo * Improved PyPI info XXXXXX v1.0.3 ------ * Markdown cleanup * Minor code cleanup * Updated dependency versions * Added uniform product distribution docs/source/distributions.rst +4 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,10 @@ Continuous distributions :members: :inherited-members: .. autoclass:: UniformProduct :members: :inherited-members: .. autoclass:: LogNormal :members: :inherited-members: Loading docs/source/repeatablerandom.rst +2 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,8 @@ Continuous distributions .. automethod:: RepeatableRandomSequence.triangular .. automethod:: RepeatableRandomSequence.uniformproduct .. automethod:: RepeatableRandomSequence.gauss .. automethod:: RepeatableRandomSequence.gausspair Loading samplespace/distributions.py +54 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ __all__ = [ 'ZipfMandelbrot', 'Gamma', 'Triangular', 'UniformProduct', 'LogNormal', 'Exponential', 'VonMises', Loading Loading @@ -484,6 +485,59 @@ class Triangular(Distribution): return result class UniformProduct(Distribution): r"""Represents a distribution whose values are the product of N uniformly distributed variables. This distribution has the following PDF .. math:: \text{P}(x) = \begin{cases} \frac{(-1)^{n-1} log^{n-1}(x)}{(n - 1)!} & \text{for } x \in [0, 1) \\ 0 & \text{otherwise} \end{cases} """ def __init__(self, n: int): super().__init__() if n < 1: raise ValueError('n must be at least 1.') self._n: int = n @property def n(self) -> int: """Read-only property for the number of uniformly distributed variables to multiply.""" return self._n def sample(self, rand) -> float: func = getattr(rand, 'uniformproduct', lambda n: self._impl(rand, n)) return func(self._n) def as_list(self) -> List: return [self.__class__.__name__.casefold(), self._n] def as_dict(self) -> Dict: return { 'distribution': self.__class__.__name__.casefold(), 'n': self._n } @staticmethod def _impl(rand, n: int) -> float: result: float = 1.0 for _ in range(n): result *= rand.random() return result class LogNormal(Distribution): r"""Represents a log-normal distribution with parameters `mu` and `sigma`. Loading samplespace/repeatablerandom.py +26 −0 Original line number Diff line number Diff line Loading @@ -723,6 +723,32 @@ class RepeatableRandomSequence(object): low, high = high, low return low + (high - low) * sqrt(u * c) def uniformproduct(self, n: int) -> float: r"""Sample from a distribution whose values are the product of N uniformly distributed variables. This distribution has the following PDF .. math:: \text{P}(x) = \begin{cases} \frac{(-1)^{n-1} log^{n-1}(x)}{(n - 1)!} & \text{for } x \in [0, 1) \\ 0 & \text{otherwise} \end{cases} Raises: ValueError: if `n` is not at least 1. """ if n < 1: raise ValueError('n must be at least 1.') result: float = 1.0 with self.cascade(): for _ in range(n): result *= self.random() return result def chance(self, p: float) -> bool: """Returns ``True`` with probability `p`, else ``False``. Loading Loading
CHANGELOG.md +4 −2 Original line number Diff line number Diff line Loading @@ -14,7 +14,9 @@ v1.0.2 * Fixed documentation typo * Improved PyPI info XXXXXX v1.0.3 ------ * Markdown cleanup * Minor code cleanup * Updated dependency versions * Added uniform product distribution
docs/source/distributions.rst +4 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,10 @@ Continuous distributions :members: :inherited-members: .. autoclass:: UniformProduct :members: :inherited-members: .. autoclass:: LogNormal :members: :inherited-members: Loading
docs/source/repeatablerandom.rst +2 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,8 @@ Continuous distributions .. automethod:: RepeatableRandomSequence.triangular .. automethod:: RepeatableRandomSequence.uniformproduct .. automethod:: RepeatableRandomSequence.gauss .. automethod:: RepeatableRandomSequence.gausspair Loading
samplespace/distributions.py +54 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ __all__ = [ 'ZipfMandelbrot', 'Gamma', 'Triangular', 'UniformProduct', 'LogNormal', 'Exponential', 'VonMises', Loading Loading @@ -484,6 +485,59 @@ class Triangular(Distribution): return result class UniformProduct(Distribution): r"""Represents a distribution whose values are the product of N uniformly distributed variables. This distribution has the following PDF .. math:: \text{P}(x) = \begin{cases} \frac{(-1)^{n-1} log^{n-1}(x)}{(n - 1)!} & \text{for } x \in [0, 1) \\ 0 & \text{otherwise} \end{cases} """ def __init__(self, n: int): super().__init__() if n < 1: raise ValueError('n must be at least 1.') self._n: int = n @property def n(self) -> int: """Read-only property for the number of uniformly distributed variables to multiply.""" return self._n def sample(self, rand) -> float: func = getattr(rand, 'uniformproduct', lambda n: self._impl(rand, n)) return func(self._n) def as_list(self) -> List: return [self.__class__.__name__.casefold(), self._n] def as_dict(self) -> Dict: return { 'distribution': self.__class__.__name__.casefold(), 'n': self._n } @staticmethod def _impl(rand, n: int) -> float: result: float = 1.0 for _ in range(n): result *= rand.random() return result class LogNormal(Distribution): r"""Represents a log-normal distribution with parameters `mu` and `sigma`. Loading
samplespace/repeatablerandom.py +26 −0 Original line number Diff line number Diff line Loading @@ -723,6 +723,32 @@ class RepeatableRandomSequence(object): low, high = high, low return low + (high - low) * sqrt(u * c) def uniformproduct(self, n: int) -> float: r"""Sample from a distribution whose values are the product of N uniformly distributed variables. This distribution has the following PDF .. math:: \text{P}(x) = \begin{cases} \frac{(-1)^{n-1} log^{n-1}(x)}{(n - 1)!} & \text{for } x \in [0, 1) \\ 0 & \text{otherwise} \end{cases} Raises: ValueError: if `n` is not at least 1. """ if n < 1: raise ValueError('n must be at least 1.') result: float = 1.0 with self.cascade(): for _ in range(n): result *= self.random() return result def chance(self, p: float) -> bool: """Returns ``True`` with probability `p`, else ``False``. Loading