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))
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
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
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
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]
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)