Exemplo n.º 1
0
def prange(N=1, dim=1):
    """
    Constructor to create a range of polynomials where the exponent vary.

    Args:
        N (int):
            Number of polynomials in the array.
        dim (int):
            The dimension the polynomial should span.

    Returns:
        (numpoly.ndpoly):
            A polynomial array of length N containing simple polynomials with
            increasing exponent.

    Examples:
        >>> chaospy.prange(4)
        polynomial([1, q0, q0**2, q0**3])
        >>> chaospy.prange(4, dim=3)
        polynomial([1, q2, q2**2, q2**3])
    """
    logger = logging.getLogger(__name__)
    logger.warning(
        "chaospy.prange is deprecated; use chaospy.monomial instead")
    return numpoly.monomial(N, names=["q%d" % (dim - 1)])
Exemplo n.º 2
0
def basis(start, stop=None, dim=1, sort="G", cross_truncation=1.):
    """
    Create an N-dimensional unit polynomial basis.

    Args:
        start (int, numpy.ndarray):
            the minimum polynomial to include. If int is provided, set as
            lowest total order.  If array of int, set as lower order along each
            axis.
        stop (int, numpy.ndarray):
            the maximum shape included. If omitted:
            ``stop <- start; start <- 0`` If int is provided, set as largest
            total order. If array of int, set as largest order along each axis.
        dim (int):
            dim of the basis. Ignored if array is provided in either start or
            stop.
        sort (str):
            The polynomial ordering where the letters ``G``, ``I`` and ``R``
            can be used to set grade, inverse and reverse to the ordering.  For
            ``basis(start=0, stop=2, dim=2, order=order)`` we get:
            ======  ==================
            order   output
            ======  ==================
            ""      [1 y y^2 x xy x^2]
            "G"     [1 y x y^2 xy x^2]
            "I"     [x^2 xy x y^2 y 1]
            "R"     [1 x x^2 y xy y^2]
            "GIR"   [y^2 xy x^2 y x 1]
            ======  ==================
        cross_truncation (float):
            Use hyperbolic cross truncation scheme to reduce the number of
            terms in expansion.

    Returns:
        (chaospy.poly.ndpoly) : Polynomial array.

    Examples:
        >>> chaospy.basis(2, dim=2, sort="GR")
        polynomial([1, q0, q1, q0**2, q0*q1, q1**2])
        >>> chaospy.basis(2, dim=4, sort="GR", cross_truncation=0)
        polynomial([1, q0, q1, q2, q3, q0**2, q1**2, q2**2, q3**2])
        >>> chaospy.basis(2, 2, dim=2, sort="GR", cross_truncation=numpy.inf)
        polynomial([q0**2, q1**2, q0**2*q1, q0*q1**2, q0**2*q1**2])
    """
    if stop is None:
        start, stop = 0, start
    dim = max(numpy.asarray(start).size, numpy.asarray(stop).size, dim)
    return numpoly.monomial(
        start=start,
        stop=numpy.array(stop)+1,
        ordering=sort,
        cross_truncation=cross_truncation,
        names=numpoly.symbols("q:%d" % dim, asarray=True),
    )
Exemplo n.º 3
0
def basis(start, stop=None, dim=1, cross_truncation=1., sort="G"):
    """
    Create an N-dimensional unit polynomial basis.

    Args:
        start (int, numpy.ndarray):
            the minimum polynomial to include. If int is provided, set as
            lowest total order.  If array of int, set as lower order along each
            axis.
        stop (int, numpy.ndarray):
            the maximum shape included. If omitted:
            ``stop <- start; start <- 0`` If int is provided, set as largest
            total order. If array of int, set as largest order along each axis.
        dim (int):
            dim of the basis. Ignored if array is provided in either start or
            stop.
        cross_truncation (float):
            Use hyperbolic cross truncation scheme to reduce the number of
            terms in expansion.

    Returns:
        (numpoly.ndpoly) : Polynomial array.

    Examples:
        >>> chaospy.basis(2, dim=2)
        polynomial([1, q1, q0, q1**2, q0*q1, q0**2])
        >>> chaospy.basis(2, dim=4, cross_truncation=0)
        polynomial([1, q3, q2, q1, q0, q3**2, q2**2, q1**2, q0**2])
        >>> chaospy.basis(2, 2, dim=2, cross_truncation=numpy.inf)
        polynomial([q1**2, q0**2, q0*q1**2, q0**2*q1, q0**2*q1**2])

    """
    logger = logging.getLogger(__name__)
    logger.warning("chaospy.basis is deprecated; use chaospy.monomial instead")

    if stop is None:
        start, stop = 0, start
    dim = max(numpy.asarray(start).size, numpy.asarray(stop).size, dim)
    out = numpoly.monomial(
        start=start,
        stop=numpy.array(stop)+1,
        reverse="R" not in sort.upper(),
        graded="G" in sort.upper(),
        cross_truncation=cross_truncation,
        names=numpoly.symbols("q:%d" % dim, asarray=True),
    )
    if "I" in sort.upper():
        out = out[::-1]
    return out
Exemplo n.º 4
0
def test_diagonal(interface):
    """Tests for numpoly.diagonal."""
    # TODO: return view instead of copy
    poly = polynomial([[1, 2, X], [4, Y, 6], [7, 8, X + Y]])
    assert_equal(interface.diagonal(poly), [1, Y, X + Y])
    assert_equal(interface.diagonal(poly, offset=1), [2, 6])
    assert_equal(interface.diagonal(poly, offset=-1), [4, 8])

    poly = numpoly.monomial(27).reshape(3, 3, 3)
    assert_equal(interface.diagonal(poly, axis1=0, axis2=1),
                 [[1, X**12, X**24], [X, X**13, X**25], [X**2, X**14, X**26]])
    assert_equal(
        interface.diagonal(poly, axis1=0, axis2=2),
        [[1, X**10, X**20], [X**3, X**13, X**23], [X**6, X**16, X**26]])
    assert_equal(
        interface.diagonal(poly, axis1=1, axis2=2),
        [[1, X**4, X**8], [X**9, X**13, X**17], [X**18, X**22, X**26]])
Exemplo n.º 5
0
def prange(N=1, dim=1):
    """
    Constructor to create a range of polynomials where the exponent vary.

    Args:
        N (int):
            Number of polynomials in the array.
        dim (int):
            The dimension the polynomial should span.

    Returns:
        (chaospy.poly.ndpoly):
            A polynomial array of length N containing simple polynomials with
            increasing exponent.

    Examples:
        >>> chaospy.prange(4)
        polynomial([1, q0, q0**2, q0**3])
        >>> chaospy.prange(4, dim=3)
        polynomial([1, q2, q2**2, q2**3])
    """
    return numpoly.monomial(N, names=["q%d" % (dim-1)])
Exemplo n.º 6
0
def orth_chol(order,
              dist,
              normed=False,
              graded=True,
              reverse=True,
              cross_truncation=1.,
              retall=False,
              **kws):
    """
    Create orthogonal polynomial expansion from Cholesky decomposition.

    Args:
        order (int):
            Order of polynomial expansion
        dist (Dist):
            Distribution space where polynomials are orthogonal
        normed (bool):
            If True orthonormal polynomials will be used instead of monic.
        graded (bool):
            Graded sorting, meaning the indices are always sorted by the index
            sum. E.g. ``q0**2*q1**2*q2**2`` has an exponent sum of 6, and will
            therefore be consider larger than both ``q0**2*q1*q2``,
            ``q0*q1**2*q2`` and ``q0*q1*q2**2``, which all have exponent sum of
            5.
        reverse (bool):
            Reverse lexicographical sorting meaning that ``q0*q1**3`` is
            considered bigger than ``q0**3*q1``, instead of the opposite.
        cross_truncation (float):
            Use hyperbolic cross truncation scheme to reduce the number of
            terms in expansion.
        retall (bool):
            If true return numerical stabilized norms as well. Roughly the same
            as ``cp.E(orth**2, dist)``.

    Examples:
        >>> distribution = chaospy.Normal()
        >>> expansion, norms = chaospy.orth_chol(3, distribution, retall=True)
        >>> expansion.round(4)
        polynomial([1.0, q0, q0**2-1.0, q0**3-3.0*q0])
        >>> norms
        array([1., 1., 2., 6.])

    """
    dim = len(dist)
    basis = numpoly.monomial(
        start=1,
        stop=order + 1,
        names=numpoly.variable(dim).names,
        graded=graded,
        reverse=reverse,
        cross_truncation=cross_truncation,
    )
    length = len(basis)

    covariance = chaospy.descriptives.Cov(basis, dist)
    cholmat = chaospy.chol.gill_king(covariance)
    cholmat_inv = numpy.linalg.inv(cholmat.T).T
    if not normed:
        diag_mesh = numpy.repeat(numpy.diag(cholmat_inv), len(cholmat_inv))
        cholmat_inv /= diag_mesh.reshape(cholmat_inv.shape)
        norms = numpy.hstack([1, numpy.diag(cholmat)**2])
    else:
        norms = numpy.ones(length + 1, dtype=float)

    coefs = numpy.empty((length + 1, length + 1))

    coefs[1:, 1:] = cholmat_inv
    coefs[0, 0] = 1
    coefs[0, 1:] = 0

    expected = -numpy.sum(
        cholmat_inv * chaospy.descriptives.E(basis, dist, **kws), -1)
    coefs[1:, 0] = expected

    coefs = coefs.T

    out = {}
    out[(0, ) * dim] = coefs[0]
    for idx, key in enumerate(basis.exponents):
        out[tuple(key)] = coefs[idx + 1]

    names = numpoly.symbols("q:%d" % dim)
    polynomials = numpoly.polynomial(out, names=names)

    if retall:
        return polynomials, norms
    return polynomials
Exemplo n.º 7
0
def lagrange_polynomial(abscissas, graded=True, reverse=True, sort=None):
    """
    Create Lagrange polynomials.

    Args:
        abscissas (numpy.ndarray):
            Sample points where the Lagrange polynomials shall be defined.
        graded (bool):
            Graded sorting, meaning the indices are always sorted by the index
            sum. E.g. ``q0**2*q1**2*q2**2`` has an exponent sum of 6, and will
            therefore be consider larger than both ``q0**2*q1*q2``,
            ``q0*q1**2*q2`` and ``q0*q1*q2**2``, which all have exponent sum of
            5.
        reverse (bool):
            Reverse lexicographical sorting meaning that ``q0*q1**3`` is
            considered bigger than ``q0**3*q1``, instead of the opposite.

    Example:
        >>> chaospy.lagrange_polynomial([4]).round(4)
        polynomial([4.0])
        >>> chaospy.lagrange_polynomial([-10, 10]).round(4)
        polynomial([-0.05*q0+0.5, 0.05*q0+0.5])
        >>> chaospy.lagrange_polynomial([-1, 0, 1]).round(4)
        polynomial([0.5*q0**2-0.5*q0, -q0**2+1.0, 0.5*q0**2+0.5*q0])
        >>> poly = chaospy.lagrange_polynomial([[1, 0, 1], [0, 1, 2]])
        >>> poly.round(4)
        polynomial([-0.5*q1+0.5*q0+0.5, -q0+1.0, 0.5*q1+0.5*q0-0.5])
        >>> poly([1, 0, 1], [0, 1, 2]).round(14)
        array([[1., 0., 0.],
               [0., 1., 0.],
               [0., 0., 1.]])
        >>> nodes = numpy.array([[ 0.17,  0.15,  0.17,  0.19],
        ...                      [14.94, 16.69, 16.69, 16.69]])
        >>> poly = chaospy.lagrange_polynomial(nodes)  # doctest: +IGNORE_EXCEPTION_DETAIL
        Traceback (most recent call last):
            ...
        LinAlgError: Lagrange abscissas resulted in invertible matrix
    """
    abscissas = numpy.asfarray(abscissas)
    if len(abscissas.shape) == 1:
        abscissas = abscissas.reshape(1, abscissas.size)
    dim, size = abscissas.shape

    order = 1
    while comb(order + dim, dim) < size:
        order += 1

    indices = numpoly.glexindex(0,
                                order + 1,
                                dimensions=dim,
                                graded=graded,
                                reverse=reverse)[:size]
    idx, idy = numpy.mgrid[:size, :size]

    matrix = numpy.prod(abscissas.T[idx]**indices[idy], -1)
    det = numpy.linalg.det(matrix)
    if det == 0:
        raise numpy.linalg.LinAlgError(
            "Lagrange abscissas resulted in invertible matrix")

    vec = numpoly.monomial(0,
                           order + 1,
                           dimensions=dim,
                           graded=graded,
                           reverse=reverse)[:size]

    coeffs = numpy.zeros((size, size))

    if size == 1:
        out = numpoly.monomial(
            0, 1, dimensions=dim, graded=graded,
            reverse=reverse) * abscissas.item()

    elif size == 2:
        coeffs = numpy.linalg.inv(matrix)
        out = numpoly.sum(vec * (coeffs.T), 1)

    else:
        for i in range(size):
            if i % 2 != 0:
                k = 1
            else:
                k = 0
            for j in range(size):
                if k % 2 == 0:
                    coeffs[i, j] += numpy.linalg.det(matrix[1:, 1:])
                else:
                    if size % 2 == 0:
                        coeffs[i, j] += -numpy.linalg.det(matrix[1:, 1:])
                    else:
                        coeffs[i, j] += numpy.linalg.det(matrix[1:, 1:])
                matrix = numpy.roll(matrix, -1, axis=0)
                k += 1
            matrix = numpy.roll(matrix, -1, axis=1)
        coeffs /= det
        out = numpoly.sum(vec * (coeffs.T), 1)

    return out
Exemplo n.º 8
0
def orth_gs(order,
            dist,
            normed=False,
            graded=True,
            reverse=True,
            retall=False,
            cross_truncation=1.,
            **kws):
    """
    Gram-Schmidt process for generating orthogonal polynomials.

    Args:
        order (int, numpoly.ndpoly):
            The upper polynomial order. Alternative a custom polynomial basis
            can be used.
        dist (Dist):
            Weighting distribution(s) defining orthogonality.
        normed (bool):
            If True orthonormal polynomials will be used instead of monic.
        graded (bool):
            Graded sorting, meaning the indices are always sorted by the index
            sum. E.g. ``q0**2*q1**2*q2**2`` has an exponent sum of 6, and will
            therefore be consider larger than both ``q0**2*q1*q2``,
            ``q0*q1**2*q2`` and ``q0*q1*q2**2``, which all have exponent sum of
            5.
        reverse (bool):
            Reverse lexicographical sorting meaning that ``q0*q1**3`` is
            considered bigger than ``q0**3*q1``, instead of the opposite.
        retall (bool):
            If true return numerical stabilized norms as well. Roughly the same
            as ``cp.E(orth**2, dist)``.
        cross_truncation (float):
            Use hyperbolic cross truncation scheme to reduce the number of
            terms in expansion.

    Returns:
        (chapspy.poly.ndpoly):
            The orthogonal polynomial expansion.

    Examples:
        >>> distribution = chaospy.J(chaospy.Normal(), chaospy.Normal())
        >>> polynomials, norms = chaospy.orth_gs(2, distribution, retall=True)
        >>> polynomials.round(10)
        polynomial([1.0, q1, q0, q1**2-1.0, q0*q1, q0**2-1.0])
        >>> norms.round(10)
        array([1., 1., 1., 2., 1., 2.])
        >>> polynomials = chaospy.orth_gs(2, distribution, normed=True)
        >>> polynomials.round(3)
        polynomial([1.0, q1, q0, 0.707*q1**2-0.707, q0*q1, 0.707*q0**2-0.707])

    """
    logger = logging.getLogger(__name__)
    dim = len(dist)

    if isinstance(order, int):
        if order == 0:
            return numpoly.polynomial(1)
        basis = numpoly.monomial(
            0,
            order + 1,
            names=numpoly.variable(2).names,
            graded=graded,
            reverse=reverse,
            cross_truncation=cross_truncation,
        )
    else:
        basis = order

    basis = list(basis)

    polynomials = [basis[0]]

    norms = [1.]
    for idx in range(1, len(basis)):

        # orthogonalize polynomial:
        for idy in range(idx):
            orth = chaospy.E(basis[idx] * polynomials[idy], dist, **kws)
            basis[idx] = basis[idx] - polynomials[idy] * orth / norms[idy]

        norms_ = chaospy.E(basis[idx]**2, dist, **kws)
        if norms_ <= 0:
            logger.warning("Warning: Polynomial cutoff at term %d", idx)
            break

        norms.append(1. if normed else norms_)
        basis[idx] = basis[idx] / numpy.sqrt(norms_) if normed else basis[idx]
        polynomials.append(basis[idx])

    polynomials = chaospy.polynomial(polynomials).flatten()
    if retall:
        norms = numpy.array(norms)
        return polynomials, norms
    return polynomials
Exemplo n.º 9
0
def test_display_order(display_config):
    """Ensure string output changes with various display options."""
    expected_output = display_config.pop("expected_output")
    polynomial = numpy.sum(numpoly.monomial(3, dimensions=("q0", "q1")))
    with numpoly.global_options(**display_config):
        assert str(polynomial) == expected_output
Exemplo n.º 10
0
def test_monomial():
    assert not numpoly.monomial(0).size
    assert numpoly.monomial(1) == 1
    assert numpy.all(numpoly.monomial(2, dimensions="q0") == [1, X])
    assert numpoly.monomial(1, 2, dimensions="q0") == X
    assert numpoly.monomial(1, 2, dimensions=None) == X
Exemplo n.º 11
0
def basis(start,
          stop=None,
          dim=1,
          graded=True,
          reverse=True,
          cross_truncation=1.,
          sort=None):
    """
    Create an N-dimensional unit polynomial basis.

    Args:
        start (int, numpy.ndarray):
            the minimum polynomial to include. If int is provided, set as
            lowest total order.  If array of int, set as lower order along each
            axis.
        stop (int, numpy.ndarray):
            the maximum shape included. If omitted:
            ``stop <- start; start <- 0`` If int is provided, set as largest
            total order. If array of int, set as largest order along each axis.
        dim (int):
            dim of the basis. Ignored if array is provided in either start or
            stop.
        graded (bool):
            Graded sorting, meaning the indices are always sorted by the index
            sum. E.g. ``q0**2*q1**2*q2**2`` has an exponent sum of 6, and will
            therefore be consider larger than both ``q0**2*q1*q2``,
            ``q0*q1**2*q2`` and ``q0*q1*q2**2``, which all have exponent sum of
            5.
        reverse (bool):
            Reverse lexicographical sorting meaning that ``q0*q1**3`` is
            considered bigger than ``q0**3*q1``, instead of the opposite.
        cross_truncation (float):
            Use hyperbolic cross truncation scheme to reduce the number of
            terms in expansion.

    Returns:
        (chaospy.poly.ndpoly) : Polynomial array.

    Examples:
        >>> chaospy.basis(2, dim=2)
        polynomial([1, q1, q0, q1**2, q0*q1, q0**2])
        >>> chaospy.basis(2, dim=4, cross_truncation=0)
        polynomial([1, q3, q2, q1, q0, q3**2, q2**2, q1**2, q0**2])
        >>> chaospy.basis(2, 2, dim=2, cross_truncation=numpy.inf)
        polynomial([q1**2, q0**2, q0*q1**2, q0**2*q1, q0**2*q1**2])

    """
    logger = logging.getLogger(__name__)
    if sort is not None:
        logger.warning("deprecation warning: 'sort' argument is deprecated; "
                       "use 'graded' and/or 'reverse' instead")
        graded = "G" in sort.upper()
        reverse = "R" not in sort.upper()
        inverse = "I" in sort.upper()
        out = basis(start, stop, dim, graded, reverse, cross_truncation)
        if inverse:
            out = out[::-1]
        return out

    if stop is None:
        start, stop = 0, start
    dim = max(numpy.asarray(start).size, numpy.asarray(stop).size, dim)
    return numpoly.monomial(
        start=start,
        stop=numpy.array(stop) + 1,
        reverse=reverse,
        graded=graded,
        cross_truncation=cross_truncation,
        names=numpoly.symbols("q:%d" % dim, asarray=True),
    )
Exemplo n.º 12
0
def test_numpoly_monomial():
    assert not numpoly.monomial(0).size
    assert numpoly.monomial(1) == 1
    assert numpy.all(numpoly.monomial(2, names="X") == [1, X])