Example #1
0
def test_set_dimensions():
    """Tests for numpoly.set_dimensions."""
    assert numpoly.set_dimensions(POLY1).names == ("q0", "q1", "q2")
    assert numpoly.set_dimensions(POLY1, 1).names == ("q0", )
    assert numpoly.set_dimensions(POLY1, 2).names == ("q0", "q1")
    assert numpoly.set_dimensions(POLY1, 3).names == ("q0", "q1", "q2")
    assert numpoly.set_dimensions(POLY1, 4).names == ("q0", "q1", "q2", "q3")
Example #2
0
def Sens_m2(poly, dist, **kws):
    """
    Variance-based decomposition/Sobol' indices.

    Second order sensitivity indices.

    Args:
        poly (numpoly.ndpoly):
            Polynomial to find second order Sobol indices on.
        dist (Dist):
            The distributions of the input used in ``poly``.

    Returns:
        (numpy.ndarray):
            First order sensitivity indices for each parameters in ``poly``,
            with shape ``(len(dist), len(dist)) + poly.shape``.

    Examples:
        >>> q0, q1 = chaospy.variable(2)
        >>> poly = chaospy.polynomial([1, q0*q1, q0**3*q1, q0*q1**3])
        >>> dist = chaospy.Iid(chaospy.Uniform(0, 1), 2)
        >>> chaospy.Sens_m2(poly, dist).round(4)
        array([[[0.    , 0.    , 0.    , 0.    ],
                [0.    , 0.1429, 0.2093, 0.2093]],
        <BLANKLINE>
               [[0.    , 0.1429, 0.2093, 0.2093],
                [0.    , 0.    , 0.    , 0.    ]]])

    """
    dim = len(dist)
    poly = numpoly.set_dimensions(poly, len(dist))

    out = numpy.zeros((dim, dim) + poly.shape)
    variance = Var(poly, dist)

    valids = variance != 0
    if not numpy.all(valids):
        out[:, :, valids] = Sens_m2(poly[valids], dist, **kws)
        return out

    conditional_v = numpy.zeros((dim, ) + poly.shape)
    for idx, unit_vec in enumerate(numpy.eye(dim, dtype=int)):
        conditional_e = E_cond(poly, unit_vec, dist, **kws)
        conditional_v[idx] = Var(conditional_e, dist, **kws)

    for idx, unit_vec1 in enumerate(numpy.eye(dim, dtype=int)):
        for idy, unit_vec2 in enumerate(
                numpy.eye(dim, dtype=int)[idx + 1:], idx + 1):

            conditional_e = E_cond(poly, unit_vec1 + unit_vec2, dist, **kws)
            out[idx, idy] = Var(conditional_e, dist, **kws)
            out[idx, idy] -= conditional_v[idx]
            out[idx, idy] -= conditional_v[idy]
            out[idx, idy] /= variance

    # copy upper matrix triangle down to lower triangle
    indices = numpy.tril_indices(dim, -1)
    out[indices] = numpy.swapaxes(out, 0, 1)[indices]

    return out
Example #3
0
def Var(poly, dist=None, **kws):
    """
    Element by element 2nd order statistics.

    Args:
        poly (numpoly.ndpoly, Distribution):
            Input to take variance on.
        dist (Distribution):
            Defines the space the variance is taken on. It is ignored if
            ``poly`` is a distribution.

    Returns:
        (numpy.ndarray):
            Element for element variance along ``poly``, where
            ``variation.shape == poly.shape``.

    Examples:
        >>> dist = chaospy.J(chaospy.Gamma(1, 1), chaospy.Normal(0, 2))
        >>> chaospy.Var(dist)
        array([1., 4.])
        >>> q0, q1 = chaospy.variable(2)
        >>> poly = chaospy.polynomial([1, q0, q1, 10*q0*q1])
        >>> chaospy.Var(poly, dist)
        array([  0.,   1.,   4., 800.])
    """
    if dist is None:
        dist, poly = poly, numpoly.variable(len(poly))
    poly = numpoly.set_dimensions(poly, len(dist))
    if not poly.isconstant:

        return poly.tonumpy()**2
    poly = poly-E(poly, dist, **kws)
    poly = numpoly.square(poly)
    return E(poly, dist, **kws)
Example #4
0
 def _mom(self, kloc, dist, scale, shift, parameters):
     del parameters
     poly = numpoly.variable(len(self))
     poly = numpoly.sum(scale*poly, axis=-1)+shift
     poly = numpoly.set_dimensions(numpoly.prod(poly**kloc), len(self))
     out = sum(dist._get_mom(key)*coeff
               for key, coeff in zip(poly.exponents, poly.coefficients))
     return out
Example #5
0
    def _mom(self, kloc, mean, sigma, cache):
        poly = numpoly.variable(len(self))
        cholesky = numpy.linalg.cholesky(self._covariance)
        poly = numpoly.sum(cholesky * poly, axis=-1) + mean

        poly = numpoly.set_dimensions(numpoly.prod(poly**kloc), len(self))
        out = sum(
            self._dist.mom(key) * coeff
            for key, coeff in zip(poly.exponents, poly.coefficients))
        return out
Example #6
0
def Kurt(poly, dist=None, fisher=True, **kws):
    """
    The forth order statistical moment Kurtosis.

    Element by element 4rd order statistics of a distribution or polynomial.

    Args:
        poly (numpoly.ndpoly, Distribution):
            Input to take kurtosis on.
        dist (Distribution):
            Defines the space the skewness is taken on. It is ignored if
            ``poly`` is a distribution.
        fisher (bool):
            If True, Fisher's definition is used (Normal -> 0.0). If False,
            Pearson's definition is used (normal -> 3.0)

    Returns:
        (numpy.ndarray):
            Element for element variance along ``poly``, where
            ``skewness.shape==poly.shape``.

    Examples:
        >>> dist = chaospy.J(chaospy.Gamma(1, 1), chaospy.Normal(0, 2))
        >>> chaospy.Kurt(dist).round(4)
        array([6., 0.])
        >>> chaospy.Kurt(dist, fisher=False).round(4)
        array([9., 3.])
        >>> q0, q1 = chaospy.variable(2)
        >>> poly = chaospy.polynomial([1, q0, q1, 10*q0*q1-1])
        >>> chaospy.Kurt(poly, dist).round(4)
        array([nan,  6.,  0., 15.])
        >>> chaospy.Kurt(4., dist)
        array(nan)

    """
    adjust = 3 if fisher else 0

    if dist is None:
        dist, poly = poly, numpoly.variable(len(poly))
    poly = numpoly.set_dimensions(poly, len(dist))
    if poly.isconstant():
        return numpy.full(poly.shape, numpy.nan)

    poly = poly - E(poly, dist, **kws)
    poly = numpoly.true_divide(poly, Std(poly, dist, **kws))
    return E(poly**4, dist, **kws) - adjust
Example #7
0
def E(poly, dist=None, **kws):
    """
    The expected value of a distribution or polynomial.

    1st order statistics of a probability distribution or polynomial on a given
    probability space.

    Args:
        poly (numpoly.ndpoly, Distribution):
            Input to take expected value on.
        dist (Distribution):
            Defines the space the expected value is taken on. It is ignored if
            ``poly`` is a distribution.

    Returns:
        (numpy.ndarray):
            The expected value of the polynomial or distribution, where
            ``expected.shape == poly.shape``.

    Examples:
        >>> dist = chaospy.J(chaospy.Gamma(1, 1), chaospy.Normal(0, 2))
        >>> chaospy.E(dist)
        array([1., 0.])
        >>> q0, q1 = chaospy.variable(2)
        >>> poly = chaospy.polynomial([1, q0, q1, 10*q0*q1-1])
        >>> chaospy.E(poly, dist)
        array([ 1.,  1.,  0., -1.])

    """
    if dist is None:
        dist, poly = poly, numpoly.variable(len(poly))

    poly = numpoly.set_dimensions(poly, len(dist))
    if poly.isconstant():
        return poly.tonumpy()

    moments = dist.mom(poly.exponents.T, **kws)
    if len(dist) == 1:
        moments = moments[0]

    out = numpy.zeros(poly.shape)
    for idx, key in enumerate(poly.keys):
        out += poly[key] * moments[idx]
    return out
Example #8
0
def Sens_t(poly, dist, **kws):
    """
    Variance-based decomposition
    AKA Sobol' indices

    Total effect sensitivity index

    Args:
        poly (numpoly.ndpoly):
            Polynomial to find first order Sobol indices on.
        dist (Dist):
            The distributions of the input used in ``poly``.

    Returns:
        (numpy.ndarray) :
            First order sensitivity indices for each parameters in ``poly``,
            with shape ``(len(dist),) + poly.shape``.

    Examples:
        >>> q0, q1 = chaospy.variable(2)
        >>> poly = chaospy.polynomial([1, q0, q1, 10*q0*q1-1])
        >>> dist = chaospy.Iid(chaospy.Uniform(0, 1), 2)
        >>> chaospy.Sens_t(poly, dist)
        array([[0.        , 1.        , 0.        , 0.57142857],
               [0.        , 0.        , 1.        , 0.57142857]])
    """
    dim = len(dist)
    poly = numpoly.set_dimensions(poly, dim)

    out = numpy.zeros((dim, ) + poly.shape, dtype=float)
    variance = Var(poly, dist, **kws)

    valids = variance != 0
    if not numpy.all(valids):
        out[:, valids] = Sens_t(poly[valids], dist, **kws)
        return out

    out[:] = variance
    for idx, unit_vec in enumerate(numpy.eye(dim, dtype=int)):
        conditional = E_cond(poly, 1 - unit_vec, dist, **kws)
        out[idx] -= Var(conditional, dist, **kws)
        out[idx] /= variance

    return out
Example #9
0
def Cov(poly, dist=None, **kws):
    """
    Variance/Covariance matrix of a distribution or polynomial array.

    Args:
        poly (numpoly.ndpoly, Distribution) :
            Input to take covariance on. Must have `len(poly)>=2`.
        dist (Distribution) :
            Defines the space the covariance is taken on.  It is ignored if
            `poly` is a distribution.

    Returns:
        (numpy.ndarray):
            Covariance matrix with shape ``poly.shape+poly.shape``.

    Examples:
        >>> dist = chaospy.MvNormal([0, 0], [[2, .5], [.5, 1]])
        >>> chaospy.Cov(dist)
        array([[2. , 0.5],
               [0.5, 1. ]])
        >>> q0, q1 = chaospy.variable(2)
        >>> poly = chaospy.polynomial([1, q0, q1, 10*q0*q1-1])
        >>> chaospy.Cov(poly, dist)
        array([[  0. ,   0. ,   0. ,   0. ],
               [  0. ,   2. ,   0.5,   0. ],
               [  0. ,   0.5,   1. ,   0. ],
               [  0. ,   0. ,   0. , 225. ]])
        >>> chaospy.Cov([1, 2, 3], dist)
        array([[0., 0., 0.],
               [0., 0., 0.],
               [0., 0., 0.]])

    """
    if dist is None:
        dist, poly = poly, numpoly.variable(len(poly))
    poly = numpoly.set_dimensions(poly, len(dist))
    if poly.isconstant():
        return numpy.zeros((len(poly), len(poly)))
    poly = poly-E(poly, dist)
    poly = numpoly.outer(poly, poly)
    return E(poly, dist)
Example #10
0
def Skew(poly, dist=None, **kws):
    """
    The third order statistical moment Kurtosis.

    Element by element 3rd order statistics of a distribution or polynomial.

    Args:
        poly (numpoly.ndpoly, Distribution):
            Input to take skewness on.
        dist (Distribution):
            Defines the space the skewness is taken on. It is ignored if
            ``poly`` is a distribution.

    Returns:
        (numpy.ndarray):
            Element for element variance along ``poly``, where
            ``skewness.shape == poly.shape``.

    Examples:
        >>> dist = chaospy.J(chaospy.Gamma(1, 1), chaospy.Normal(0, 2))
        >>> chaospy.Skew(dist)
        array([2., 0.])
        >>> q0, q1 = chaospy.variable(2)
        >>> poly = chaospy.polynomial([1, q0, q1, 10*q0*q1-1])
        >>> chaospy.Skew(poly, dist)
        array([nan,  2.,  0.,  0.])
        >>> chaospy.Skew(2., dist)
        array(nan)

    """
    if dist is None:
        dist, poly = poly, numpoly.variable(len(poly))
    poly = numpoly.set_dimensions(poly, len(dist))
    if poly.isconstant():
        return numpy.full(poly.shape, numpy.nan)

    poly = poly - E(poly, dist, **kws)
    poly = numpoly.true_divide(poly, Std(poly, dist, **kws))
    return E(poly**3, dist, **kws)
Example #11
0
def Sens_m(poly, dist, **kws):
    """
    Variance-based decomposition/Sobol' indices.

    First order sensitivity indices.

    Args:
        poly (numpoly.ndpoly):
            Polynomial to find first order Sobol indices on.
        dist (Dist):
            The distributions of the input used in ``poly``.

    Returns:
        (numpy.ndarray):
            First order sensitivity indices for each parameters in ``poly``,
            with shape ``(len(dist),) + poly.shape``.

    Examples:
        >>> q0, q1 = chaospy.variable(2)
        >>> poly = chaospy.polynomial([1, q0, q1, 10*q0*q1-1])
        >>> distribution = chaospy.Iid(chaospy.Uniform(0, 1), 2)
        >>> chaospy.Sens_m(poly, distribution)
        array([[0.        , 1.        , 0.        , 0.42857143],
               [0.        , 0.        , 1.        , 0.42857143]])
    """
    dim = len(dist)
    poly = numpoly.set_dimensions(poly, dim)

    out = numpy.zeros((dim, ) + poly.shape)
    variance = Var(poly, dist, **kws)
    valids = variance != 0

    for idx, unit_vec in enumerate(numpy.eye(dim, dtype=int)):

        conditional = E_cond(poly[valids], unit_vec, dist, **kws)
        out[idx, valids] = Var(conditional, dist, **kws)
        out[idx, valids] /= variance[valids]

    return out
Example #12
0
def E_cond(poly, freeze, dist, **kws):
    """
    Conditional expected value of a distribution or polynomial.

    1st order statistics of a polynomial on a given probability space
    conditioned on some of the variables.

    Args:
        poly (numpoly.ndpoly):
            Polynomial to find conditional expected value on.
        freeze (numpy.ndpoly):
            Boolean values defining the conditional variables. True values
            implies that the value is conditioned on, e.g. frozen during the
            expected value calculation.
        dist (Distribution) :
            The distributions of the input used in ``poly``.

    Returns:
        (numpoly.ndpoly) :
            Same as ``poly``, but with the variables not tagged in ``frozen``
            integrated away.

    Examples:
        >>> q0, q1 = chaospy.variable(2)
        >>> poly = chaospy.polynomial([1, q0, q1, 10*q0*q1-1])
        >>> poly
        polynomial([1, q0, q1, 10*q0*q1-1])
        >>> dist = chaospy.J(chaospy.Gamma(1, 1), chaospy.Normal(0, 2))
        >>> chaospy.E_cond(poly, q0, dist)
        polynomial([1.0, q0, 0.0, -1.0])
        >>> chaospy.E_cond(poly, q1, dist)
        polynomial([1.0, 1.0, q1, 10.0*q1-1.0])
        >>> chaospy.E_cond(poly, [q0, q1], dist)
        polynomial([1, q0, q1, 10*q0*q1-1])
        >>> chaospy.E_cond(poly, [], dist)
        polynomial([1.0, 1.0, 0.0, -1.0])
        >>> chaospy.E_cond(4, [], dist)
        array(4)

    """
    poly = numpoly.set_dimensions(poly, len(dist))
    if poly.isconstant():
        return poly.tonumpy()
    assert not dist.stochastic_dependent, dist

    freeze = numpoly.aspolynomial(freeze)
    if not freeze.size:
        return numpoly.polynomial(chaospy.E(poly, dist))
    if not freeze.isconstant():
        freeze = [
            name in freeze.names
            for name in sorted(poly.names, key=lambda x: int(x[1:]))
        ]

    else:
        freeze = freeze.tonumpy()
    freeze = numpy.asarray(freeze, dtype=bool)

    # decompose into frozen and unfrozen part
    poly = numpoly.decompose(poly)
    unfrozen = poly(**{("q%d" % idx): 1
                       for idx, keep in enumerate(freeze) if keep})
    frozen = poly(**{("q%d" % idx): 1
                     for idx, keep in enumerate(freeze) if not keep})

    # if no unfrozen, poly will return numpy.ndarray instead of numpoly.ndpoly
    if not isinstance(unfrozen, numpoly.ndpoly):
        return numpoly.sum(frozen, 0)

    # Remove frozen coefficients, such that poly == sum(frozen*unfrozen) holds
    for key in unfrozen.keys:
        unfrozen.values[key] = unfrozen.values[key] != 0
    return numpoly.sum(frozen * expected.E(unfrozen, dist), 0)