Ejemplo n.º 1
0
    def testSparseMonomialQuadrature(self):
        chaos = make_legendre()
        dim = 2
        level_max = 3  # legendre and hermite: level,maxsumbound: 1,3/2,7/3,11/4,17/5,31/6,78
        sum_bound = 11  # open weakly nested order is 2 ** (level+1) - 1 (for level=3 this is 15)
        quad = SparseQuadrature(level_max,
                                nst.get_nesting_for_name(chaos.name),
                                dim * [chaos.nodes_and_weights])
        for multi_index in multi_index_bounded_sum(dim, sum_bound):

            def func(xs):
                return mul_prod(x**index for x, index in zip(xs, multi_index))

            result = quad.apply(func)
            if chaos.name == "Legendre":
                wanted = (0 if any(index % 2 == 1
                                   for index in multi_index) else mul_prod(
                                       1. / (index + 1)
                                       for index in multi_index))
            elif chaos.name == "Hermite":

                def uneven_factorial(number):
                    fac = 1
                    while number > 1:
                        fac *= number - 1
                        number -= 2
                    return fac

                wanted = (0 if any(index % 2 == 1
                                   for index in multi_index) else mul_prod(
                                       uneven_factorial(index)
                                       for index in multi_index))
            # print(result, wanted, "for multi index", multi_index)
            self.assertAlmostEqual(result, wanted)
Ejemplo n.º 2
0
    def __init__(self, nodes_and_weights_funcs, poly_names, sum_bound):
        nodes_list, weights_list = [], []
        length = sum_bound + 1
        nodes_weights_pairs = [nodes_and_weights_func(length) for nodes_and_weights_func in nodes_and_weights_funcs]
        # for every multi index we add one nodes tuple to the list, so we will later have the same
        # amount of nodes/weights as we have basis polynomials with the same sum_bound
        indices = multi_index_bounded_sum(len(nodes_and_weights_funcs), sum_bound)

        for multi_index in indices:
            current_nodes, current_weights = [], []
            for (nodes, weights), index, poly_name in zip(nodes_weights_pairs, multi_index, poly_names):
                # here it is important that we have enough nodes to use the multi_index's index!
                if poly_name in ["Hermite", "Legendre"]:
                    index = centralize_index(index, length)  # important as nodes are symmetric around the center
                elif poly_name == "Jacobi":
                    index = length - index - 1
                elif poly_name == "Laguerre":
                    pass  # do not change index
                else:
                    raise ValueError("Not supported polynomials:", poly_name)
                current_nodes.append(nodes[index])
                current_weights.append(weights[index])
            nodes_list.append(current_nodes)
            weights_list.append(mul_prod(current_weights))
        self.nodes = np.array(nodes_list)
        self.weights = np.array(weights_list)
Ejemplo n.º 3
0
 def func_in_ys(*ys):
     transformed_ys = [
         rvar(value) for rvar, value in zip(self.rvars, ys)
     ]
     return (function(x_coords, t, transformed_ys) * mul_prod(
         distr.weight(y)
         for y, distr in zip(ys, self.variable_distributions)))
Ejemplo n.º 4
0
def sparse_grid(dim_num: int, level_min2: int, level_max: int, point_num: int,
                nodes_and_weights_funcs, calculate_grid_base2,
                calculate_offset, calculate_index_level):
    grid_weight = np.zeros(point_num)
    grid_point = np.zeros((dim_num, point_num))

    point_num2 = 0
    level_min = max(0, level_max + 1 - dim_num)
    last_point3 = -1
    for level in range(level_min2, level_max + 1):
        for level_1d in compositions(level, dim_num):
            order_1d = level_to_order_open(level_1d)
            grid_base2 = calculate_grid_base2(order_1d)
            order_nd = mul_prod(order_1d)
            grid_weights2 = product_weights(dim_num, order_1d, order_nd,
                                            nodes_and_weights_funcs)
            coeff = ((-1)**((level_max - level) % 2)) * comb(
                dim_num - 1, level_max - level, exact=True)
            offset = calculate_offset(order_1d)
            grid_index2 = multigrid_index(dim_num, order_1d, order_nd, offset)

            # level is used to find out if the point is new or already existed as it sets the lowest level
            # of appearance of each point. If grid_level is None then every point is new
            grid_level = calculate_index_level(level, level_max, dim_num,
                                               order_nd, grid_index2,
                                               grid_base2)
            for point in range(order_nd):
                if grid_level is None or grid_level[point] == level:
                    # new point!
                    point_num2 += 1
                    assert point_num2 <= point_num
                    grid_point[:, point_num2 - 1] = multigrid_point(
                        dim_num, grid_index2[:, point], order_1d, offset,
                        nodes_and_weights_funcs)
                    if level_min <= level:
                        grid_weight[point_num2 -
                                    1] = coeff * grid_weights2[point]
                elif level_min <= level:
                    # already existing point!
                    grid_point_temp = multigrid_point(dim_num,
                                                      grid_index2[:, point],
                                                      order_1d, offset,
                                                      nodes_and_weights_funcs)
                    # find the index
                    point3 = -1
                    # it is very common that the point is the last_point3+1, so instead of using
                    # bruteforce search range(point_num2) we make the order smarter
                    # this SIGNIFICANTLY improves speed, as np.allclose is in the innermost loop and quite costly
                    for point2 in chain([last_point3 + 1],
                                        range(last_point3 + 1),
                                        range(last_point3 + 2, point_num2)):
                        if np.allclose(grid_point[:, point2], grid_point_temp):
                            point3 = point2
                            last_point3 = point3
                            break
                    assert point3 != -1  # we know it has to be somewhere as grid_level[point] != level
                    grid_weight[point3] += coeff * grid_weights2[point]
    assert point_num2 == point_num
    return np.rollaxis(grid_point, 1), grid_weight
Ejemplo n.º 5
0
def calculate_point_num(dim_num: int, level_max: int):
    if level_max == 0:
        return 1
    # the amount of new nodes appearing per level, so 1 new for level=0, 2 new for level=1, afterwards 2^(level-1) new
    new_1d = np.array([1, 2] + [2**i for i in range(1, level_max)])
    point_num = 0
    for level in range(level_max + 1):
        for level_1d in compositions(level, dim_num):
            point_num += mul_prod(new_1d[level_1d])
    return point_num
Ejemplo n.º 6
0
 def __init__(self, orders_1d, nodes_and_weights_funcs):
     assert len(orders_1d) == len(nodes_and_weights_funcs)
     # contains [([n11,n12,n13],[w11,w12,w13]), ([n21,n22],[w21,w22])]
     nodes_weights_pairs = [nodes_and_weights(order) for order, nodes_and_weights in zip(orders_1d,
                                                                                         nodes_and_weights_funcs)]
     nodes_list = [nodes for nodes, _ in nodes_weights_pairs]
     weights_list = [weights for _, weights in nodes_weights_pairs]
     # use full tensor product of all dimensions by using 'product'
     self.nodes = np.array([grid_nodes for grid_nodes in product(*nodes_list)])
     self.weights = np.array([mul_prod(grid_weights) for grid_weights in product(*weights_list)])
Ejemplo n.º 7
0
def calculate_point_num(dim_num: int,
                        level_min: int,
                        level_max: int,
                        init_point_num: int,
                        repetition_handler=None):
    if level_max == 0:
        return 1
    point_num = init_point_num
    for level in range(level_min, level_max + 1):
        for level_1d in compositions(level, dim_num):
            order_1d = level_to_order_open(level_1d)
            if repetition_handler is not None:
                order_1d = repetition_handler(order_1d)
            point_num += mul_prod(
                order_1d
            )  # the number of points is the full product of all 1d points
    return point_num
Ejemplo n.º 8
0
def levels_index(dim_num: int, level_max: int, point_num: int):
    grid_index = np.zeros((dim_num, point_num), dtype=int)
    grid_base = np.zeros((dim_num, point_num), dtype=int)

    point_num2 = 0
    for level in range(level_max + 1):
        for level_1d in compositions(level, dim_num):
            order_1d = level_to_order_closed(level_1d)
            order_nd = mul_prod(order_1d)
            grid_index2 = multigrid_index(dim_num, order_1d, order_nd)
            prev_shape = grid_index2.shape
            grid_index2 = multigrid_scale_closed(dim_num, level_max, level_1d,
                                                 grid_index2)
            grid_level = abscissa_level_closed_nd(level_max, dim_num, order_nd,
                                                  grid_index2)
            for point in range(order_nd):
                if grid_level[point] == level:
                    point_num2 += 1
                    assert point_num2 <= point_num
                    grid_base[:, point_num2 - 1] = order_1d
                    grid_index[:, point_num2 - 1] = grid_index2[:, point]
    assert point_num2 == point_num
    return grid_index, grid_base
Ejemplo n.º 9
0
    def __init__(self, nodes_and_weights_funcs, sum_bound, even):
        nodes_list, weights_list = [], []
        length = sum_bound + 1  # ignore lengths and use sum_bound+1 for every dimension to ensure we can index!
        nodes_weights_pairs = [nodes_and_weights_func(length) for nodes_and_weights_func in nodes_and_weights_funcs]
        # for every multi index we add one nodes tuple to the list, so we will later have the same
        # amount of nodes/weights as we have basis polynomials.
        if even:
            indices = list(multi_index_bounded_sum(len(nodes_and_weights_funcs),
                                                   sum_bound + 1 if sum_bound % 2 == 1 else sum_bound))
        else:
            indices = multi_index_bounded_sum(len(nodes_and_weights_funcs), sum_bound)

        for multi_index in indices:
            current_nodes, current_weights = [], []
            for (nodes, weights), index in zip(nodes_weights_pairs, multi_index):
                # here it is important that we have enough nodes to use the multi_index's index!
                centralized = centralize_index(index, length)  # important as nodes are symmetric around the center
                current_nodes.append(nodes[centralized])
                current_weights.append(weights[centralized])
            nodes_list.append(current_nodes)
            weights_list.append(mul_prod(current_weights))
        self.nodes = np.array(nodes_list)
        self.weights = np.array(weights_list)
Ejemplo n.º 10
0
def sparse_grid_weights(dim_num: int, level_max: int, point_num: int,
                        grid_index, nodes_and_weights_funcs):

    grid_weight = np.zeros(point_num)
    level_min = max(0, level_max + 1 - dim_num)
    for level in range(level_min, level_max + 1):
        for level_1d in compositions(level, dim_num):
            order_1d = level_to_order_closed(level_1d)
            order_nd = mul_prod(order_1d)
            grid_index2 = multigrid_index(dim_num, order_1d, order_nd)
            grid_weight2 = product_weights(dim_num, order_1d, order_nd,
                                           nodes_and_weights_funcs)
            grid_index2 = multigrid_scale_closed(dim_num, level_max, level_1d,
                                                 grid_index2)

            coeff = ((-1)**((level_max - level) % 2)) * comb(
                dim_num - 1, level_max - level, exact=True)
            for point2 in range(order_nd):
                for point in range(point_num):

                    if np.all(grid_index2[:, point2] == grid_index[:, point]):
                        grid_weight[point] += coeff * grid_weight2[point2]
                        break
    return grid_weight
Ejemplo n.º 11
0
 def func(xs):
     return mul_prod(x**index for x, index in zip(xs, multi_index))
Ejemplo n.º 12
0
    def testGlenshawCurtisQuadrature(self):
        import util.quadrature.glenshaw_curtis as gc
        nodes_and_weights = gc.nodes_and_weights
        from util.quadrature.closed_fully_nested import ClosedFullNesting
        nesting = ClosedFullNesting()

        # 1d polynomial exactness
        count = 10  # exact if polynomials are degree < count
        quad = FullTensorQuadrature([count], [nodes_and_weights])
        for n in range(count):
            result = quad.apply(lambda xs: xs[0]**n)
            wanted = 2. / (n + 1) if n % 2 == 0 else 0.
            self.assertAlmostEqual(
                result,
                wanted,
                places=10,
                msg="GC quad with count = {}, n={} polynomial exactness".
                format(count, n))

        # 2d test
        count = 8  # exact if univariate polynomials of degree < count
        for n, m in product(range(count), repeat=2):
            quad = FullTensorQuadrature([count, count],
                                        [nodes_and_weights] * 2)
            result = quad.apply(lambda xs: xs[0]**n * xs[1]**m)
            if n % 2 == 1 or m % 2 == 1:
                wanted = 0.
            else:
                wanted = 2. / (n + 1) * 2. / (m + 1)
            self.assertAlmostEqual(
                result,
                wanted,
                places=10,
                msg="GC quad with count = {}, 2d poly exactness, n={}, m={}".
                format(count, n, m))

        # sparse test 1d
        for level in range(4):
            quad = SparseQuadrature(level, nesting, [nodes_and_weights])
            count = quad.get_nodes_count()
            for n in range(count):
                result = quad.apply(lambda xs: xs[0]**n)
                wanted = 2. / (n + 1) if n % 2 == 0 else 0.
                self.assertAlmostEqual(
                    result,
                    wanted,
                    places=10,
                    msg=
                    "GC sparse quad on level={} with count = {}, n={} polynomial exactness"
                    .format(level, count, n))

        # sparse test nd
        from util.quadrature.helpers import multi_index_bounded_sum
        from util.analysis import mul_prod
        for level in range(5):
            for dim in range(1, 4):
                quad = SparseQuadrature(level, nesting,
                                        [nodes_and_weights] * dim)
                for ind in multi_index_bounded_sum(dim, level + 1):
                    result = quad.apply(
                        lambda xs: mul_prod(x**i for x, i in zip(xs, ind)))
                    if any(i % 2 == 1 for i in ind):
                        wanted = 0.
                    else:
                        wanted = mul_prod(2. / (i + 1) for i in ind)
                    self.assertAlmostEqual(
                        result,
                        wanted,
                        places=10,
                        msg="CG sparse {}d on level={}, ind={}, quadpoints={}".
                        format(dim, level, ind, quad.get_nodes_count()))
Ejemplo n.º 13
0
 def multi_poly(ys):
     return mul_prod(
         basis.polys(index)(y)
         for y, index, basis in zip(ys, multi_index, basis_list))
Ejemplo n.º 14
0
 def beta_expectancy_func_simple(*ys, i, k, x):
     res3 = mul_prod(
         distr.weight(y) for y, distr in zip(ys, chaos.get_distributions()))
     return trial.beta(
         [x],
         trial.transform_values(ys)) * basis[i](ys) * basis[k](ys) * res3
Ejemplo n.º 15
0
 def integrate_func_simple(*ys, i):
     res3 = mul_prod(
         distr.weight(y) for y, distr in zip(ys, chaos.get_distributions()))
     return function(
         project_trial.transform_values(ys)) * basis[i](ys) * res3
Ejemplo n.º 16
0
 def weight(xs):
     return mul_prod(
         distr.weight(x) for x, distr in zip(xs, distributions))
Ejemplo n.º 17
0
 def function_transformed(*ys):
     return (function(ys) * mul_prod(
         distr.weight(y)
         for y, distr in zip(ys, self.variable_distributions)))
Ejemplo n.º 18
0
 def alpha_expectancy_func_simple(*ys, i, k):
     res1 = trial.alpha(trial.transform_values(ys))
     res2 = basis[i](ys) * basis[k](ys)
     res3 = mul_prod(
         distr.weight(y) for y, distr in zip(ys, chaos.get_distributions()))
     return res1 * res2 * res3