Esempio n. 1
0
def simplex_grid(length, subdivisions, using=None, inplace=False):
    """Returns a generator over distributions, determined by a grid.

    The grid is "triangular" in Euclidean space.

    The total number of points on the grid is::

        (subdivisions + length - 1)! / (subdivisions)! / (length-1)!

    and is equivalent to the total number of ways ``n`` indistinguishable items
    can be placed into ``k`` distinguishable slots, where n=`subdivisions` and
    k=`length`.

    Parameters
    ----------
    length : int
        The number of elements in each distribution. The dimensionality
        of the simplex is length-1.
    subdivisions : int
        The number of subdivisions for the interval [0, 1]. Each component
        will take on values at the boundaries of the subdivisions. For example,
        one subdivision means each component can take the values 0 or 1 only.
        Two subdivisions corresponds to :math:`[[0, 1/2], [1/2, 1]]` and thus,
        each component can take the values 0, 1/2, or 1. A common use case is
        to exponentially increase the number of subdivisions at each level.
        That is, subdivisions would be: 2**0, 2**1, 2**2, 2**3, ...
    using : None, callable, or distribution
        If None, then scalar distributions on integers are yielded. If `using`
        is a distribution, then each yielded distribution is a copy of `using`
        with its pmf set appropriately. For other callables, a tuple of the
        pmf is passed to the callable and then yielded.
    inplace : bool
        If `True`, then each yielded distribution is the same Python object,
        but with a new probability mass function. If `False`, then each yielded
        distribution is a unique Python object and can be safely stored for
        other calculations after the generator has finished. This keyword has
        an effect only when `using` is None or some distribution.

    Examples
    --------
    >>> list(dit.simplex_grid(2, 2, using=tuple))
    [(0.0, 1.0), (0.25, 0.75), (0.5, 0.5), (0.75, 0.25), (1.0, 0.0)]

    """
    from dit.math.combinatorics import slots

    if subdivisions < 1:
        raise ditException('`subdivisions` must be greater than or equal to 1')
    elif length < 1:
        raise ditException('`length` must be greater than or equal to 1')

    gen = slots(int(subdivisions), int(length), normalized=True)

    if using is None:
        using = random_scalar_distribution(length)

    if using is tuple:
        for pmf in gen:
            yield pmf
    elif not isinstance(using, BaseDistribution):
        for pmf in gen:
            yield using(pmf)
    else:
        if length != len(using.pmf):
            raise Exception('`length` must match the length of pmf')

        if inplace:
            d = using
            for pmf in gen:
                d.pmf[:] = pmf
                yield d
        else:
            for pmf in gen:
                d = using.copy()
                d.pmf[:] = pmf
                yield d
Esempio n. 2
0
def test_slots1():
    x = list(slots(3, 2))
    x_ = [(0, 3), (1, 2), (2, 1), (3, 0)]
    assert x == x_
Esempio n. 3
0
def test_slots2():
    x = np.asarray(list(slots(3, 2, normalized=True)))
    x_ = np.asarray([(0, 1), (1 / 3, 2 / 3), (2 / 3, 1 / 3), (1, 0)])
    assert np.allclose(x, x_)
Esempio n. 4
0
def test_slots2():
    x = np.asarray(list(slots(3, 2, normalized=True)))
    x_ = np.asarray([(0, 1), (1/3, 2/3), (2/3, 1/3), (1, 0)])
    assert np.allclose(x, x_)
Esempio n. 5
0
def test_slots1():
    x = list(slots(3, 2))
    x_ = [(0, 3), (1, 2), (2, 1), (3, 0)]
    assert x == x_
Esempio n. 6
0
def test_slots1():
    x = list(slots(3, 2))
    x_ = [(0, 3), (1, 2), (2, 1), (3, 0)]
    assert_equal(x, x_)
Esempio n. 7
0
def simplex_grid(length, subdivisions, using=None, inplace=False):
    """Returns a generator over distributions, determined by a grid.

    The grid is "triangular" in Euclidean space.

    The total number of points on the grid is::

        (subdivisions + length - 1)! / (subdivisions)! / (length-1)!

    and is equivalent to the total number of ways ``n`` indistinguishable items
    can be placed into ``k`` distinguishable slots, where n=`subdivisions` and
    k=`length`.

    Parameters
    ----------
    length : int
        The number of elements in each distribution. The dimensionality
        of the simplex is length-1.
    subdivisions : int
        The number of subdivisions for the interval [0, 1]. Each component
        will take on values at the boundaries of the subdivisions. For example,
        one subdivision means each component can take the values 0 or 1 only.
        Two subdivisions corresponds to :math:`[[0, 1/2], [1/2, 1]]` and thus,
        each component can take the values 0, 1/2, or 1. A common use case is
        to exponentially increase the number of subdivisions at each level.
        That is, subdivisions would be: 2**0, 2**1, 2**2, 2**3, ...
    using : None, callable, or distribution
        If None, then scalar distributions on integers are yielded. If `using`
        is a distribution, then each yielded distribution is a copy of `using`
        with its pmf set appropriately. For other callables, a tuple of the
        pmf is passed to the callable and then yielded.
    inplace : bool
        If `True`, then each yielded distribution is the same Python object,
        but with a new probability mass function. If `False`, then each yielded
        distribution is a unique Python object and can be safely stored for
        other calculations after the generator has finished. This keyword has
        an effect only when `using` is None or some distribution.

    Examples
    --------
    >>> list(dit.simplex_grid(2, 2, using=tuple))
    [(0.0, 1.0), (0.25, 0.75), (0.5, 0.5), (0.75, 0.25), (1.0, 0.0)]

    """
    from dit.math.combinatorics import slots

    if subdivisions < 1:
        raise ditException('`subdivisions` must be greater than or equal to 1')
    elif length < 1:
        raise ditException('`length` must be greater than or equal to 1')

    gen = slots(int(subdivisions), int(length), normalized=True)

    if using is None:
        using = random_scalar_distribution(length)

    if using is tuple:
        for pmf in gen:
            yield pmf
    elif not isinstance(using, BaseDistribution):
        for pmf in gen:
            yield using(pmf)
    else:
        if length != len(using.pmf):
            raise Exception('`length` must match the length of pmf')

        if inplace:
            d = using
            for pmf in gen:
                d.pmf[:] = pmf
                yield d
        else:
            for pmf in gen:
                d = using.copy()
                d.pmf[:] = pmf
                yield d
Esempio n. 8
0
def test_slots1():
    x = list(slots(3, 2))
    x_ = [(0, 3), (1, 2), (2, 1), (3, 0)]
    assert_equal(x, x_)