def norm(order, dist, orth=None): dim = len(dist) try: if dim > 1: norms = numpy.array([norm(order + 1, D) for D in dist]) Is = numpoly.bindex(order + 1, dimensions=dim) out = numpy.ones(len(Is)) for i in range(len(Is)): index = Is[i] for j in range(dim): if index[j]: out[i] *= norms[j, index[j]] return out K = range(1, order + 1) ttr = [1.] + [dist.ttr(k)[1] for k in K] return numpy.cumprod(ttr) except NotImplementedError: if orth is None: orth = orth_chol(order, dist) return chaospy.descriptives.E(orth**2, dist)
def _construct_collection( orders, dist, x_lookup, w_lookup, ): """Create a collection of {abscissa: weight} key-value pairs.""" order = numpy.min(orders) skew = orders-order # Indices and coefficients used in the calculations indices = numpoly.bindex(order-len(dist)+1, order+1, dimensions=len(dist)) coeffs = numpy.sum(indices, -1) coeffs = (2*((order-coeffs+1) % 2)-1)*comb(len(dist)-1, order-coeffs) collection = defaultdict(float) for bidx, coeff in zip(indices+skew, coeffs.tolist()): abscissas = [value[idx] for idx, value in zip(bidx, x_lookup)] weights = [value[idx] for idx, value in zip(bidx, w_lookup)] for abscissa, weight in zip(product(*abscissas), product(*weights)): collection[abscissa] += numpy.prod(weight)*coeff return collection
def lagrange_polynomial(abscissas, sort="G"): """ Create Lagrange polynomials. Args: abscissas (numpy.ndarray): Sample points where the Lagrange polynomials shall be defined. Example: >>> chaospy.lagrange_polynomial([-10, 10]).round(4) polynomial([0.5-0.05*q0, 0.5+0.05*q0]) >>> chaospy.lagrange_polynomial([-1, 0, 1]).round(4) polynomial([-0.5*q0+0.5*q0**2, 1.0-q0**2, 0.5*q0+0.5*q0**2]) >>> poly = chaospy.lagrange_polynomial([[1, 0, 1], [0, 1, 2]]) >>> poly.round(4) polynomial([0.5-0.5*q1+0.5*q0, 1.0-q0, -0.5+0.5*q1+0.5*q0]) >>> poly([1, 0, 1], [0, 1, 2]).round(4) 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 chaospy.bertran.terms(order, dim) < size: order += 1 indices = numpoly.bindex(0, order + 1, dimensions=dim, ordering=sort)[: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 = chaospy.poly.basis(0, order, dim, sort)[:size] coeffs = numpy.zeros((size, size)) if size == 1: out = chaospy.poly.basis(0, 0, dim, sort) * abscissas.item() elif size == 2: coeffs = numpy.linalg.inv(matrix) out = chaospy.poly.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 = chaospy.poly.sum(vec * (coeffs.T), 1) return out
def orth_ttr(order, dist, normed=False, sort="G", retall=False, cross_truncation=1., **kws): """ Create orthogonal polynomial expansion from three terms recursion formula. Args: order (int): Order of polynomial expansion. dist (Dist): Distribution space where polynomials are orthogonal If dist.ttr exists, it will be used. Must be stochastically independent. normed (bool): If True orthonormal polynomials will be used. sort (str): Polynomial sorting. Same as in basis. 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. only include terms where the exponents ``K`` satisfied the equation ``order >= sum(K**(1/cross_truncation))**cross_truncation``. Returns: (chaospy.poly.ndpoly, numpy.ndarray): Orthogonal polynomial expansion and norms of the orthogonal expansion on the form ``E(orth**2, dist)``. Calculated using recurrence coefficients for stability. Examples: >>> Z = chaospy.Normal() >>> chaospy.orth_ttr(4, Z).round(4) polynomial([1.0, q0, -1.0+q0**2, -3.0*q0+q0**3, 3.0-6.0*q0**2+q0**4]) """ try: _, polynomials, norms, = chaospy.quadrature.recurrence.analytical_stieljes( numpy.max(order), dist, normed=normed) except NotImplementedError: abscissas, weights = chaospy.quadrature.generate_quadrature( int(10000**(1 / len(dist))), dist, rule="fejer") _, polynomials, norms, = chaospy.quadrature.recurrence.discretized_stieltjes( numpy.max(order), abscissas, weights, normed=normed) polynomials = polynomials.reshape((len(dist), numpy.max(order) + 1)) order = numpy.array(order) indices = numpoly.bindex(start=0, stop=order + 1, dimensions=len(dist), ordering=sort, cross_truncation=cross_truncation) if len(dist) > 1: polynomials = chaospy.poly.prod( chaospy.polynomial( [poly[idx] for poly, idx in zip(polynomials, indices.T)]), 0) norms = numpy.prod( [norms_[idx] for norms_, idx in zip(norms, indices.T)], 0) else: polynomials = polynomials.flatten() if retall: return polynomials, norms return polynomials
def test_numpoly_bindex(): assert not numpoly.bindex(0).size assert numpy.all(numpoly.bindex(1) == [[0]]) assert numpy.all(numpoly.bindex(5) == [[0], [1], [2], [3], [4]]) assert numpy.all( numpoly.bindex(2, dimensions=2) == [[0, 0], [0, 1], [1, 0]]) assert numpy.all( numpoly.bindex(start=2, stop=3, dimensions=2) == [[0, 2], [1, 1], [2, 0]]) assert numpy.all( numpoly.bindex(start=2, stop=[3, 4], dimensions=2) == [[0, 2], [1, 1], [2, 0], [0, 3]]) assert numpy.all( numpoly.bindex(start=[2, 5], stop=[3, 6], dimensions=2) == [[1, 1], [2, 0], [1, 2], [0, 5]]) assert numpy.all( numpoly.bindex(start=2, stop=3, dimensions=2, ordering="I") == [[2, 0], [1, 1], [0, 2]]) assert numpy.all( numpoly.bindex(start=2, stop=4, dimensions=2, cross_truncation=0) == [[0, 2], [2, 0], [0, 3], [3, 0]]) assert numpy.all( numpoly.bindex(start=2, stop=4, dimensions=2, cross_truncation=1) == [[0, 2], [1, 1], [2, 0], [0, 3], [1, 2], [2, 1], [3, 0]]) assert numpy.all( numpoly.bindex(start=2, stop=4, dimensions=2, cross_truncation=2) == [[0, 2], [1, 1], [2, 0], [0, 3], [1, 2], [2, 1], [3, 0], [2, 2]]) assert numpy.all( numpoly.bindex(start=0, stop=2, dimensions=3) == [[0, 0, 0], [0, 0, 1], [0, 1, 0], [1, 0, 0]])