Commit 9dfa99bb authored by Coriander Violet Pines's avatar Coriander Violet Pines 🦐
Browse files

Added uniform product distribution

parent e13058e6
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -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
+4 −0
Original line number Diff line number Diff line
@@ -81,6 +81,10 @@ Continuous distributions
    :members:
    :inherited-members:

.. autoclass:: UniformProduct
    :members:
    :inherited-members:

.. autoclass:: LogNormal
    :members:
    :inherited-members:
+2 −0
Original line number Diff line number Diff line
@@ -91,6 +91,8 @@ Continuous distributions

.. automethod:: RepeatableRandomSequence.triangular

.. automethod:: RepeatableRandomSequence.uniformproduct

.. automethod:: RepeatableRandomSequence.gauss

.. automethod:: RepeatableRandomSequence.gausspair
+54 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ __all__ = [
    'ZipfMandelbrot',
    'Gamma',
    'Triangular',
    'UniformProduct',
    'LogNormal',
    'Exponential',
    'VonMises',
@@ -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`.
+26 −0
Original line number Diff line number Diff line
@@ -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