def test_symbols(): assert numpoly.symbols() == X assert numpoly.symbols().shape == () assert numpoly.symbols("q0") == X assert numpoly.symbols("q0").shape == () assert numpoly.symbols("q0,") == X assert numpoly.symbols("q0,").shape == (1, ) assert numpoly.symbols("q0", asarray=True) == X assert numpoly.symbols("q0", asarray=True).shape == (1, ) assert numpoly.symbols("q:1").names == ("q0", ) assert numpoly.symbols("q1").names == ("q1", )
def setdim(poly, dim=None): """ Adjust the dimensions of a polynomial. Output the results into ndpoly object Args: poly (chaospy.poly.ndpoly): Input polynomial dim (int): The dimensions of the output polynomial. If omitted, increase polynomial with one dimension. If the new dim is smaller then `poly`'s dimensions, variables with cut components are all cut. Examples: >>> q0, q1 = chaospy.variable(2) >>> poly = q0*q1-q0**2 >>> chaospy.setdim(poly, 1) polynomial(-q0**2) >>> chaospy.setdim(poly, 3) polynomial(q0*q1-q0**2) >>> chaospy.setdim(poly).names ('q0', 'q1', 'q2') """ poly = numpoly.polynomial(poly) indices = [int(name[1:]) for name in poly.names] dim = max(indices) + 2 if dim is None else dim poly = poly(**{("q%d" % index): 0 for index in indices if index >= dim}) _, poly = numpoly.align_indeterminants(numpoly.symbols("q:%d" % dim), poly) return poly
def orth_chol(order, dist, normed=True, sort="G", cross_truncation=1., **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. sort (str): Ordering argument passed to poly.basis. If custom basis is used, argument is ignored. cross_truncation (float): Use hyperbolic cross truncation scheme to reduce the number of terms in expansion. Examples: >>> Z = chaospy.Normal() >>> chaospy.orth_chol(3, Z).round(4) polynomial([1.0, q0, -0.7071+0.7071*q0**2, -1.2247*q0+0.4082*q0**3]) """ dim = len(dist) basis = chaospy.poly.basis( start=1, stop=order, dim=dim, sort=sort, cross_truncation=cross_truncation, ) length = len(basis) cholmat = chaospy.chol.gill_king(chaospy.descriptives.Cov(basis, dist)) 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) 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 = chaospy.poly.polynomial(out, names=names) return polynomials
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), )
def test_aspolynomial(): poly = 2*X-Y+1 assert poly == numpoly.aspolynomial(poly) assert poly == numpoly.aspolynomial(poly, names=XY) assert poly == numpoly.aspolynomial(poly.todict(), names=XY) assert poly == numpoly.aspolynomial(poly, names=("X", "Y")) assert numpy.all(numpoly.symbols("Z:2") == numpoly.aspolynomial(XY, names="Z")) assert poly == numpoly.aspolynomial(poly.todict(), names=("X", "Y")) assert poly != numpoly.aspolynomial(poly.todict(), names=("Y", "X")) assert X == numpoly.aspolynomial(Y, names="X") assert poly != numpoly.aspolynomial(poly.todict(), names="X") assert isinstance(numpoly.aspolynomial([1, 2, 3]), numpoly.ndpoly) assert numpy.all(numpoly.aspolynomial([1, 2, 3]) == [1, 2, 3])
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
def test_aspolynomial(): poly = 2 * X - Y + 1 assert poly == numpoly.aspolynomial(poly) assert poly == numpoly.aspolynomial(poly, names=XY) assert poly == numpoly.aspolynomial(poly.todict(), names=XY) assert poly == numpoly.aspolynomial(poly, names=("q0", "q1")) with numpoly.global_options(varname_filter=r"\w+", force_number_suffix=False): assert numpy.all( numpoly.symbols("Z:2") == numpoly.aspolynomial(XY, names="Z")) assert poly == numpoly.aspolynomial(poly.todict(), names=("q0", "q1")) assert poly != numpoly.aspolynomial(poly.todict(), names=("q1", "q0")) assert X == numpoly.aspolynomial(Y, names="q0") assert poly != numpoly.aspolynomial(poly.todict(), names="q0") assert isinstance(numpoly.aspolynomial([1, 2, 3]), numpoly.ndpoly) assert numpy.all(numpoly.aspolynomial([1, 2, 3]) == [1, 2, 3])
def test_numpoly_ndpoly(): poly = numpoly.ndpoly(exponents=[(1, )], shape=(), names="X") poly["<"] = 1 assert poly == X poly = numpoly.ndpoly(exponents=[(1, )], shape=(), names=X) poly["<"] = 1 assert poly == X poly = numpoly.ndpoly(exponents=[(1, 0), (0, 1)], shape=(), names=("X", "Y")) poly["<;"] = 2 poly[";<"] = 3 assert poly == 2 * X + 3 * Y poly = numpoly.ndpoly(exponents=[(1, 0), (0, 1)], shape=(2, ), names="Q") poly["<;"] = [1, 0] poly[";<"] = [0, 1] assert numpy.all(poly == numpoly.symbols("Q0 Q1"))
def variable(dims=1): """ Simple constructor to create single variables to create polynomials. Args: dims (int): Number of dimensions in the array. Returns: (chaospy.poly.polynomial): Polynomial array with unit components in each dimension. Examples: >>> chaospy.variable() polynomial(q0) >>> chaospy.variable(3) polynomial([q0, q1, q2]) """ return numpoly.symbols("q:%d" % dims)
def test_ndpoly(): poly = numpoly.ndpoly(exponents=[(1, )], shape=(), names="q0") poly["<"] = 1 assert poly == X poly = numpoly.ndpoly(exponents=[(1, )], shape=(), names=X) poly["<"] = 1 assert poly == X poly = numpoly.ndpoly(exponents=[(1, 0), (0, 1)], shape=(), names=("q0", "q1")) poly["<;"] = 2 poly[";<"] = 3 assert poly == 2 * X + 3 * Y with numpoly.global_options(varname_filter=r"Q\d+"): poly = numpoly.ndpoly(exponents=[(1, 0), (0, 1)], shape=(2, ), names="Q:2") poly["<;"] = [1, 0] poly[";<"] = [0, 1] assert numpy.all(poly == numpoly.symbols("Q0 Q1"))
def test_numpoly_polynomial(): assert numpoly.polynomial() == 0 assert numpoly.polynomial({(0, ): 4}) == 4 assert numpoly.polynomial({(1, ): 5}, names="X") == 5 * X assert numpoly.polynomial({ (0, 1): 2, (1, 0): 3 }, names=("X", "Y")) == 3 * X + 2 * Y assert numpy.all( numpoly.polynomial({ (0, 1): [0, 1], (1, 0): [1, 0] }, names="Q") == numpoly.symbols("Q0 Q1")) assert numpoly.polynomial(X) == X assert numpoly.polynomial(numpy.array((3, ), dtype=[(";", int)])) == 3 assert numpoly.polynomial(5.5) == 5.5 assert numpoly.polynomial(sympy.symbols("X")) == X assert numpy.all(numpoly.polynomial([1, 2, 3]) == [1, 2, 3]) assert numpy.all(numpoly.polynomial([[1, 2], [3, 4]]) == [[1, 2], [3, 4]]) assert numpy.all( numpoly.polynomial(numpy.array([[1, 2], [3, 4]])) == [[1, 2], [3, 4]])
def variable( dimensions: int = 1, asarray: bool = False, dtype: numpy.typing.DTypeLike = "i8", allocation: Optional[int] = None, ) -> ndpoly: """ Construct variables that can be used to construct polynomials. Args: dimensions: Number of dimensions in the array. asarray: Enforce output as array even in the case where there is only one variable. dtype: The data type of the polynomial coefficients. allocation: The maximum number of polynomial exponents. If omitted, use length of exponents for allocation. Returns: Polynomial array with unit components in each dimension. Examples: >>> numpoly.variable() polynomial(q0) >>> q0, q1, q2 = numpoly.variable(3) >>> q1+1 polynomial(q1+1) >>> numpoly.polynomial([q2**3, q1+q2, 1]) polynomial([q2**3, q2+q1, 1]) """ return numpoly.symbols( names=f"{numpoly.get_options()['default_varname']}:{dimensions:d}", asarray=asarray, dtype=dtype, allocation=allocation, )
def test_polynomial(): assert numpoly.polynomial() == 0 assert numpoly.polynomial({(0, ): 4}) == 4 assert numpoly.polynomial({(1, ): 5}, names="q0") == 5 * X assert numpoly.polynomial({ (0, 1): 2, (1, 0): 3 }, names=("q0", "q1")) == 3 * X + 2 * Y with numpoly.global_options(varname_filter=r"\w+"): assert numpy.all( numpoly.polynomial({ (0, 1): [0, 1], (1, 0): [1, 0] }, names="Q") == numpoly.symbols("Q0 Q1")) assert numpoly.polynomial(X) == X assert numpoly.polynomial(numpy.array((3, ), dtype=[(";", int)])) == 3 assert numpoly.polynomial(5.5) == 5.5 assert numpoly.polynomial(sympy.symbols("q0")) == X assert numpy.all(numpoly.polynomial([1, 2, 3]) == [1, 2, 3]) assert numpy.all(numpoly.polynomial([[1, 2], [3, 4]]) == [[1, 2], [3, 4]]) assert numpy.all( numpoly.polynomial(numpy.array([[1, 2], [3, 4]])) == [[1, 2], [3, 4]])
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
"""Test ndpoly baseclass functionality.""" import numpy from pytest import raises import numpoly XY = numpoly.variable(2) X, Y = numpoly.symbols("q0"), numpoly.symbols("q1") EMPTY = numpoly.polynomial([]) def test_scalars(): """Test scalar objects to catch edgecases.""" assert XY.shape == (2, ) assert XY.size == 2 assert X.shape == () assert X.size == 1 assert EMPTY.shape in [(), (0, )] # different behavior in py2/3 assert EMPTY.size == 0 assert numpy.all(numpy.array(XY.coefficients) == [[1, 0], [0, 1]]) assert X.coefficients == [1] assert EMPTY.coefficients == [] assert numpy.all(XY.exponents == [[1, 0], [0, 1]]) assert XY.exponents.shape == (2, 2) assert X.exponents == 1 assert X.exponents.shape == (1, 1) assert numpy.all(EMPTY.exponents == 0) assert EMPTY.exponents.shape == (1, 1) assert numpy.all(XY.indeterminants == XY)
def __new__( cls, exponents: numpy.typing.ArrayLike = ((0,),), shape: Tuple[int, ...] = (), names: Union[None, str, Tuple[str, ...], "ndpoly"] = None, dtype: Optional[numpy.typing.DTypeLike] = None, allocation: Optional[int] = None, **kwargs: Any ) -> "ndpoly": """ Class constructor. Args: exponents: The exponents in an integer array with shape ``(N, D)``, where ``N`` is the number of terms in the polynomial sum and ``D`` is the number of dimensions. shape: Shape of created array. names: The name of the indeterminant variables in the polynomial. If polynomial, inherent from it. Else, pass argument to `numpoly.symbols` to create the indeterminants names. If only one name is provided, but more than one is required, indeterminants will be extended with an integer index. If omitted, use ``numpoly.get_options()["default_varname"]``. dtype: Any object that can be interpreted as a numpy data type. allocation: The maximum number of polynomial exponents. If omitted, use length of exponents for allocation. kwargs: Extra arguments passed to `numpy.ndarray` constructor. """ exponents = numpy.array(exponents, dtype=numpy.uint32) if numpy.prod(exponents.shape): keys = (exponents+cls.KEY_OFFSET).flatten() keys = keys.view(f"U{exponents.shape[-1]}") keys = numpy.array(keys, dtype=f"U{exponents.shape[-1]}") else: keys = numpy.full((1,), cls.KEY_OFFSET, dtype="uint32").view("U1") assert len(keys.shape) == 1 dtype = int if dtype is None else dtype dtype_ = numpy.dtype([(key, dtype) for key in keys]) obj = super(ndpoly, cls).__new__( cls, shape=shape, dtype=dtype_, **kwargs) if allocation is None: allocation = 2*len(keys) assert isinstance(allocation, int) and allocation >= len(keys), ( "Not enough memory allocated; increase 'allocation'") if allocation > len(keys): allocation_ = numpy.arange(allocation-len(keys), len(keys)) allocation_ = [str(s) for s in allocation_] keys = numpy.concatenate([keys, allocation_]) obj.allocation = allocation if names is None: names = numpoly.get_options()["default_varname"] obj.names = numpoly.symbols( f"{names}:{exponents.shape[-1]}").names elif isinstance(names, str): obj.names = numpoly.symbols(names).names elif isinstance(names, ndpoly): obj.names = names.names else: obj.names = tuple(str(name) for name in names) for name in obj.names: assert re.search(numpoly.get_options()["varname_filter"], name), ( "invalid polynomial name; " f"expected format: {numpoly.get_options()['varname_filter']}") obj._dtype = numpy.dtype(dtype) # pylint: disable=protected-access obj.keys = keys return obj
"""Testing functions used for numpy compatible.""" from pytest import raises import numpy from numpoly import polynomial import numpoly X, Y = numpoly.symbols("X Y") def test_numpy_absolute(interface): assert abs(-X) == abs(X) == X assert numpy.all( interface.abs(polynomial([X - Y, Y - 4])) == [X + Y, Y + 4]) def test_numpy_add(interface): assert interface.add(X, 3) == 3 + X assert numpy.all( interface.add(polynomial([1, X, Y]), 4) == [5, 4 + X, 4 + Y]) assert numpy.all( interface.add(polynomial([0, X]), polynomial([Y, 0])) == [Y, X]) assert numpy.all( interface.add(polynomial([[1, X], [Y, X * Y]]), [2, X]) == [[3, 2 * X], [2 + Y, X + X * Y]]) def test_numpy_any(interface): poly = polynomial([[0, Y], [0, 0]]) assert interface.any(poly) assert numpy.all(interface.any(poly, axis=0) == [False, True]) assert numpy.all(
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), )
def test_numpoly(): import numpoly x = numpoly.symbols("x") p = x**2 + 3 * x + 1 assert numpoly.diff(p, x) == 2 * x + 3
def orth_chol(order, dist, normed=False, sort="G", 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. sort (str): Ordering argument passed to poly.basis. If custom basis is used, argument is ignored. 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, -1.0+q0**2, -3.0*q0+q0**3]) >>> norms array([1., 1., 2., 6.]) """ dim = len(dist) basis = chaospy.poly.basis( start=1, stop=order, dim=dim, sort=sort, 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 = chaospy.poly.polynomial(out, names=names) if retall: return polynomials, norms return polynomials