示例#1
0
    def test_tensor_product_lagrange_interpolation(self):
        nvars = 5
        level = 10
        x = gauss_hermite_pts_wts_1D(level + 1)[0]
        # active_vars = np.arange(nvars)
        active_vars = np.hstack([np.arange(2), np.arange(3, nvars)])
        nactive_vars = active_vars.shape[0]
        abscissa_1d = [x] * nactive_vars

        power = x.shape[0] - 2

        def fun(samples):
            return np.sum(samples[active_vars, :]**power, axis=0)[:, None]

        nsamples = 1000
        validation_samples = np.random.normal(0, 1, (nvars, nsamples))

        zz = abscissa_1d.copy()
        zz.insert(2, np.zeros(1))
        train_samples = cartesian_product(zz)
        values = fun(train_samples)
        approx_values = tensor_product_lagrange_interpolation(
            validation_samples, abscissa_1d, active_vars, values)

        barycentric_weights_1d = [
            compute_barycentric_weights_1d(x) for x in abscissa_1d
        ]
        poly_vals = multivariate_barycentric_lagrange_interpolation(
            validation_samples, abscissa_1d, barycentric_weights_1d, values,
            active_vars)

        assert np.allclose(approx_values, fun(validation_samples))
        assert np.allclose(poly_vals, fun(validation_samples))
示例#2
0
def evaluate_sparse_grid_subspace(samples, subspace_index, subspace_values,
                                  samples_1d, config_variables_idx, output):
    if config_variables_idx is None:
        config_variables_idx = samples.shape[0]
    
    active_sample_vars = np.where(subspace_index[:config_variables_idx]>0)[0]
    num_active_sample_vars = active_sample_vars.shape[0]
    
    abscissa_1d = []
    barycentric_weights_1d = []
    for dd in range(num_active_sample_vars):
        active_idx = active_sample_vars[dd]
        abscissa_1d.append(samples_1d[active_idx][subspace_index[active_idx]])
        interval_length = 2
        if abscissa_1d[dd].shape[0] > 1:
            interval_length = abscissa_1d[dd].max()-abscissa_1d[dd].min()
        barycentric_weights_1d.append(
            compute_barycentric_weights_1d(
                abscissa_1d[dd], interval_length=interval_length))

    if num_active_sample_vars==0:
        return np.tile(subspace_values,(samples.shape[1],1))
    poly_vals = multivariate_barycentric_lagrange_interpolation( 
        samples, abscissa_1d, barycentric_weights_1d, subspace_values,
        active_sample_vars)
    return poly_vals
示例#3
0
def convert_univariate_lagrange_basis_to_orthonormal_polynomials(
        samples_1d, get_recursion_coefficients):
    """
    Returns
    -------
    coeffs_1d : list [np.ndarray(num_terms_i,num_terms_i)]
        The coefficients of the orthonormal polynomial representation of
        each Lagrange basis. The columns are the coefficients of each 
        lagrange basis. The rows are the coefficient of the degree i 
        orthonormalbasis
    """
    # Get the maximum number of terms in the orthonormal polynomial that
    # are need to interpolate all the interpolation nodes in samples_1d
    max_num_terms = samples_1d[-1].shape[0]
    num_quad_points = max_num_terms + 1
    # Get the recursion coefficients of the orthonormal basis
    recursion_coeffs = get_recursion_coefficients(num_quad_points)
    # compute the points and weights of the correct quadrature rule
    x_quad, w_quad = gauss_quadrature(recursion_coeffs, num_quad_points)
    # evaluate the orthonormal basis at the quadrature points. This can
    # be computed once for all degrees up to the maximum degree
    ortho_basis_matrix = evaluate_orthonormal_polynomial_1d(
        x_quad, max_num_terms, recursion_coeffs)

    # compute coefficients of orthonormal basis using pseudo spectral projection
    coeffs_1d = []
    w_quad = w_quad[:, np.newaxis]
    for ll in range(len(samples_1d)):
        num_terms = samples_1d[ll].shape[0]
        # evaluate the lagrange basis at the quadrature points
        barycentric_weights_1d = [
            compute_barycentric_weights_1d(samples_1d[ll])
        ]
        values = np.eye((num_terms), dtype=float)
        # Sometimes the following function will cause the erro
        # interpolation abscissa are not unique. This can be due to x_quad
        # not abscissa. E.g. x_quad may have points far enough outside
        # range of abscissa, e.g. abscissa are clenshaw curtis points and
        # x_quad points are Gauss-Hermite quadrature points
        lagrange_basis_vals = multivariate_barycentric_lagrange_interpolation(
            x_quad[np.newaxis, :], samples_1d[ll][np.newaxis, :],
            barycentric_weights_1d, values, np.zeros(1, dtype=int))
        # compute fourier like coefficients
        basis_coeffs = []
        for ii in range(num_terms):
            basis_coeffs.append(
                np.dot(w_quad.T, lagrange_basis_vals *
                       ortho_basis_matrix[:, ii:ii + 1])[0, :])
        coeffs_1d.append(np.asarray(basis_coeffs))
    return coeffs_1d
示例#4
0
 def interpolate(self, mesh_values, eval_samples):
     if eval_samples.ndim == 1:
         eval_samples = eval_samples[None, :]
     if mesh_values.ndim == 1:
         mesh_values = mesh_values[:, None]
     assert mesh_values.ndim == 2
     num_dims = eval_samples.shape[0]
     abscissa_1d = [self.mesh_pts_1d]*num_dims
     weights_1d = [compute_barycentric_weights_1d(xx) for xx in abscissa_1d]
     interp_vals = multivariate_barycentric_lagrange_interpolation(
         eval_samples,
         abscissa_1d,
         weights_1d,
         mesh_values,
         np.arange(num_dims))
     return interp_vals
示例#5
0
    def test_interpolation_gaussian_leja_sequence(self):
        def f(x):
            return np.exp(-np.sum(x**2, axis=0))

        level = 30
        # abscissa_leja, __ = gaussian_leja_quadrature_rule(
        #    level, return_weights_for_all_levels=False)
        # abscissa = abscissa_leja
        abscissa_gauss = gauss_hermite_pts_wts_1D(level + 1)[0]
        abscissa = abscissa_gauss
        # print(abscissa_leja.shape,abscissa_gauss.shape)

        abscissa_1d = [abscissa]
        barycentric_weights_1d = [
            compute_barycentric_weights_1d(abscissa_1d[0])
        ]
        # print(barycentric_weights_1d[0])
        barycentric_weights_1d[0] /= barycentric_weights_1d[0].max()
        # print(barycentric_weights_1d[0])
        fn_vals = f(np.array(abscissa).reshape(1,
                                               abscissa.shape[0]))[:,
                                                                   np.newaxis]
        # print(fn_vals.shape)

        samples = np.random.normal(0, 1, (1, 1000))
        poly_vals = multivariate_barycentric_lagrange_interpolation(
            samples, abscissa_1d, barycentric_weights_1d, fn_vals,
            np.array([0]))[:, 0]
        l2_error = np.linalg.norm(poly_vals-f(samples)) / \
            np.sqrt(samples.shape[1])
        # print('l2_error',l2_error)

        # pts = np.linspace(abscissa.min(),abscissa.max(),101).reshape(1,101)
        # poly_vals = multivariate_barycentric_lagrange_interpolation(
        #     pts,abscissa_1d,barycentric_weights_1d,fn_vals,np.array([0]))
        # import matplotlib.pyplot as plt
        # plt.plot(pts[0,:],poly_vals.squeeze())
        # plt.plot(abscissa_1d[0],fn_vals.squeeze(),'r*')
        # plt.plot(abscissa_leja,abscissa_leja*0,'ro')
        # plt.plot(abscissa_gauss,abscissa_gauss*0,'ks',ms=3)
        # plt.ylim(-1,2)
        # plt.show()

        assert l2_error < 1e-2
    def f(samples): return multivariate_barycentric_lagrange_interpolation(
        samples, abscissa_1d, barycentric_weights_1d, fn_vals,
        np.array([0, 1]))

    plot_limits = [-1, 1, -1, 1]
示例#7
0
    def test_multivariate_barycentric_lagrange_interpolation(self):
        def f(x):
            return np.sum(x**2, axis=0)

        eps = 1e-14

        # test 1d barycentric lagrange interpolation
        level = 5
        # abscissa, __ = clenshaw_curtis_pts_wts_1D( level )
        # barycentric_weights_1d = [clenshaw_curtis_barycentric_weights(level)]
        abscissa, __ = clenshaw_curtis_in_polynomial_order(level, False)
        abscissa_1d = [abscissa]
        barycentric_weights_1d = [
            compute_barycentric_weights_1d(abscissa_1d[0])
        ]
        fn_vals = f(np.array(abscissa).reshape(1,
                                               abscissa.shape[0]))[:,
                                                                   np.newaxis]
        pts = np.linspace(-1., 1., 3).reshape(1, 3)
        poly_vals = multivariate_barycentric_lagrange_interpolation(
            pts, abscissa_1d, barycentric_weights_1d, fn_vals, np.array([0]))

        # import pylab
        # print poly_vals.squeeze().shape
        # pylab.plot(pts[0,:],poly_vals.squeeze())
        # pylab.plot(abscissa_1d[0],fn_vals.squeeze(),'ro')
        # print np.linalg.norm( poly_vals - f( pts ) )
        # pylab.show()
        assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps)

        # test 2d barycentric lagrange interpolation
        # with the same abscissa in each dimension
        a = -3.0
        b = 3.0
        x = np.linspace(a, b, 21)
        [X, Y] = np.meshgrid(x, x)
        pts = np.vstack((X.reshape((1, X.shape[0] * X.shape[1])),
                         Y.reshape((1, Y.shape[0] * Y.shape[1]))))

        num_abscissa = [10, 10]
        abscissa_1d = [
            np.linspace(a, b, num_abscissa[0]),
            np.linspace(a, b, num_abscissa[1])
        ]

        abscissa = cartesian_product(abscissa_1d, 1)
        fn_vals = f(abscissa)
        barycentric_weights_1d = [
            compute_barycentric_weights_1d(abscissa_1d[0]),
            compute_barycentric_weights_1d(abscissa_1d[1])
        ]

        poly_vals = multivariate_barycentric_lagrange_interpolation(
            pts, abscissa_1d, barycentric_weights_1d, fn_vals[:, np.newaxis],
            np.array([0, 1]))

        assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps)

        # test 2d barycentric lagrange interpolation
        # with different abscissa in each dimension
        a = -1.0
        b = 1.0
        x = np.linspace(a, b, 21)
        [X, Y] = np.meshgrid(x, x)
        pts = np.vstack((X.reshape((1, X.shape[0] * X.shape[1])),
                         Y.reshape((1, Y.shape[0] * Y.shape[1]))))

        level = [1, 2]
        nodes_0, tmp = clenshaw_curtis_pts_wts_1D(level[0])
        nodes_1, tmp = clenshaw_curtis_pts_wts_1D(level[1])
        abscissa_1d = [nodes_0, nodes_1]
        barycentric_weights_1d = [
            clenshaw_curtis_barycentric_weights(level[0]),
            clenshaw_curtis_barycentric_weights(level[1])
        ]
        abscissa = cartesian_product(abscissa_1d, 1)
        fn_vals = f(abscissa)

        poly_vals = multivariate_barycentric_lagrange_interpolation(
            pts, abscissa_1d, barycentric_weights_1d, fn_vals[:, np.newaxis],
            np.array([0, 1]))

        assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps)

        # test 3d barycentric lagrange interpolation
        # with different abscissa in each dimension
        num_dims = 3
        a = -1.0
        b = 1.0
        pts = np.random.uniform(-1., 1., (num_dims, 10))

        level = [1, 1, 1]
        nodes_0, tmp = clenshaw_curtis_pts_wts_1D(level[0])
        nodes_1, tmp = clenshaw_curtis_pts_wts_1D(level[1])
        nodes_2, tmp = clenshaw_curtis_pts_wts_1D(level[2])
        abscissa_1d = [nodes_0, nodes_1, nodes_2]
        barycentric_weights_1d = [
            clenshaw_curtis_barycentric_weights(level[0]),
            clenshaw_curtis_barycentric_weights(level[1]),
            clenshaw_curtis_barycentric_weights(level[2])
        ]
        abscissa = cartesian_product(abscissa_1d, 1)
        fn_vals = f(abscissa)

        poly_vals = multivariate_barycentric_lagrange_interpolation(
            pts, abscissa_1d, barycentric_weights_1d, fn_vals[:, np.newaxis],
            np.array([0, 1, 2]))
        assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps)

        # test 3d barycentric lagrange interpolation
        # with different abscissa in each dimension
        # and only two active dimensions (0 and 2)
        num_dims = 3
        a = -1.0
        b = 1.0
        pts = np.random.uniform(-1., 1., (num_dims, 5))

        level = [2, 0, 1]
        # to get fn_vals we must specify abscissa for all three dimensions
        # but only the abscissa of the active dimensions should get passed
        # to the interpolation function
        nodes_0, tmp = clenshaw_curtis_pts_wts_1D(level[0])
        nodes_1, tmp = clenshaw_curtis_pts_wts_1D(level[1])
        nodes_2, tmp = clenshaw_curtis_pts_wts_1D(level[2])
        abscissa_1d = [nodes_0, nodes_1, nodes_2]
        abscissa = cartesian_product(abscissa_1d, 1)
        abscissa_1d = [nodes_0, nodes_2]
        barycentric_weights_1d = [
            clenshaw_curtis_barycentric_weights(level[0]),
            clenshaw_curtis_barycentric_weights(level[2])
        ]
        fn_vals = f(abscissa)

        poly_vals = multivariate_barycentric_lagrange_interpolation(
            pts, abscissa_1d, barycentric_weights_1d, fn_vals[:, np.newaxis],
            np.array([0, 2]))
        pts[1, :] = 0.
        assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps)

        # test 3d barycentric lagrange interpolation
        # with different abscissa in each dimension
        # and only two active dimensions (0 and 1)
        num_dims = 3
        a = -1.0
        b = 1.0
        pts = np.random.uniform(-1., 1., (num_dims, 5))

        level = [2, 3, 0]
        # to get fn_vals we must specify abscissa for all three dimensions
        # but only the abscissa of the active dimensions should get passed
        # to the interpolation function
        nodes_0, tmp = clenshaw_curtis_pts_wts_1D(level[0])
        nodes_1, tmp = clenshaw_curtis_pts_wts_1D(level[1])
        nodes_2, tmp = clenshaw_curtis_pts_wts_1D(level[2])
        abscissa_1d = [nodes_0, nodes_1, nodes_2]
        abscissa = cartesian_product(abscissa_1d, 1)
        abscissa_1d = [nodes_0, nodes_1]
        barycentric_weights_1d = [
            clenshaw_curtis_barycentric_weights(level[0]),
            clenshaw_curtis_barycentric_weights(level[1])
        ]
        fn_vals = f(abscissa)

        poly_vals = multivariate_barycentric_lagrange_interpolation(
            pts, abscissa_1d, barycentric_weights_1d, fn_vals[:, np.newaxis],
            np.array([0, 1]))
        # The interpolant will only be correct on the plane involving
        # the active dimensions so we must set the coordinate of the inactive
        # dimension to the abscissa coordinate of the inactive dimension.
        # The interpoolation algorithm is efficient in the sense that it
        # ignores all dimensions involving only one point because the
        # interpolant will be a constant in that direction
        pts[2, :] = 0.
        assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps)

        # test 3d barycentric lagrange interpolation
        # with different abscissa in each dimension
        # and only two active dimensions (1 and 2)
        num_dims = 3
        a = -1.0
        b = 1.0
        pts = np.random.uniform(-1., 1., (num_dims, 5))

        level = [0, 2, 4]
        # to get fn_vals we must specify abscissa for all three dimensions
        # but only the abscissa of the active dimensions should get passed
        # to the interpolation function
        nodes_0, tmp = clenshaw_curtis_pts_wts_1D(level[0])
        nodes_1, tmp = clenshaw_curtis_pts_wts_1D(level[1])
        nodes_2, tmp = clenshaw_curtis_pts_wts_1D(level[2])
        abscissa_1d = [nodes_0, nodes_1, nodes_2]
        abscissa = cartesian_product(abscissa_1d, 1)
        abscissa_1d = [nodes_1, nodes_2]
        barycentric_weights_1d = [
            clenshaw_curtis_barycentric_weights(level[1]),
            clenshaw_curtis_barycentric_weights(level[2])
        ]
        fn_vals = f(abscissa)

        poly_vals = multivariate_barycentric_lagrange_interpolation(
            pts, abscissa_1d, barycentric_weights_1d, fn_vals[:, np.newaxis],
            np.array([1, 2]))
        pts[0, :] = 0.
        assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps)

        # test 2d barycentric lagrange interpolation
        # with different abscissa in each dimension and only some of
        # the coefficients of the basis terms being non-zero. This situation
        # arises in hierarchical interpolation. In these cases we need
        # to construct the basis functions on all abscissa but we only
        # need to add the basis functions that are one at the hierachical
        # nodes
        a = -1.0
        b = 1.0
        # x = np.linspace( a, b, 21 )
        x = np.linspace(a, b, 5)
        [X, Y] = np.meshgrid(x, x)
        pts = np.vstack((X.reshape((1, X.shape[0] * X.shape[1])),
                         Y.reshape((1, Y.shape[0] * Y.shape[1]))))

        poly_vals = np.ones((pts.shape[1], 1), np.double) * \
            f(np.array([[0.0, 0.0]]).T)[:, np.newaxis]

        level = [1]
        nodes_0, tmp = clenshaw_curtis_pts_wts_1D(level[0])
        abscissa_1d = [nodes_0]
        barycentric_weights_1d = [
            compute_barycentric_weights_1d(abscissa_1d[0])
        ]
        sets = copy.copy(abscissa_1d)
        sets.append(np.array([0.0]))
        abscissa = cartesian_product(sets, 1)
        hier_indices = np.array([[0, 2]], np.int32)
        abscissa = abscissa[:, hier_indices[0]]
        fn_vals = f(abscissa)
        poly_vals_increment = \
            multivariate_hierarchical_barycentric_lagrange_interpolation(
                pts, abscissa_1d, barycentric_weights_1d,
                (fn_vals - np.ones((abscissa.shape[1]), np.double) * f(
                    np.array([0.0, 0.0])))[:, np.newaxis],
                np.array([0]), hier_indices)
        poly_vals += poly_vals_increment

        level = [1]
        nodes_0, tmp = clenshaw_curtis_pts_wts_1D(level[0])
        abscissa_1d = [nodes_0]
        # barycentric_weights_1d = [barycentric_weights( np.array( [0.0] ) ),
        #                          barycentric_weights( abscissa_1d[0] )]
        barycentric_weights_1d = [
            compute_barycentric_weights_1d(abscissa_1d[0])
        ]

        sets = [np.array([0.0])]
        sets.append(nodes_0)
        abscissa = cartesian_product(sets, 1)
        hier_indices = np.array([[0, 2]], np.int32)
        abscissa = abscissa[:, hier_indices[0]]
        fn_vals = f(abscissa)
        poly_vals += \
            multivariate_hierarchical_barycentric_lagrange_interpolation(
                pts, abscissa_1d, barycentric_weights_1d,
                (fn_vals - np.ones((abscissa.shape[1]), np.double) * f(
                    np.array([[0.0, 0.0]]).T))[:, np.newaxis],
                np.array([1]), hier_indices)

        assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps)