def test_evaluate_multivariate_orthonormal_polynomial(self): num_vars = 2 alpha = 0. beta = 0. degree = 2 deriv_order = 1 probability_measure = True ab = jacobi_recurrence(degree + 1, alpha=alpha, beta=beta, probability=probability_measure) x, w = np.polynomial.legendre.leggauss(degree) samples = cartesian_product([x] * num_vars, 1) weights = outer_product([w] * num_vars) indices = compute_hyperbolic_indices(num_vars, degree, 1.0) # sort lexographically to make testing easier I = np.lexsort((indices[0, :], indices[1, :], indices.sum(axis=0))) indices = indices[:, I] basis_matrix = evaluate_multivariate_orthonormal_polynomial( samples, indices, ab, deriv_order) exact_basis_vals_1d = [] exact_basis_derivs_1d = [] for dd in range(num_vars): x = samples[dd, :] exact_basis_vals_1d.append( np.asarray([1 + 0. * x, x, 0.5 * (3. * x**2 - 1)]).T) exact_basis_derivs_1d.append( np.asarray([0. * x, 1.0 + 0. * x, 3. * x]).T) exact_basis_vals_1d[-1] /= np.sqrt(1. / (2 * np.arange(degree + 1) + 1)) exact_basis_derivs_1d[-1] /= np.sqrt( 1. / (2 * np.arange(degree + 1) + 1)) exact_basis_matrix = np.asarray([ exact_basis_vals_1d[0][:, 0], exact_basis_vals_1d[0][:, 1], exact_basis_vals_1d[1][:, 1], exact_basis_vals_1d[0][:, 2], exact_basis_vals_1d[0][:, 1] * exact_basis_vals_1d[1][:, 1], exact_basis_vals_1d[1][:, 2] ]).T # x1 derivative exact_basis_matrix = np.vstack( (exact_basis_matrix, np.asarray([ 0. * x, exact_basis_derivs_1d[0][:, 1], 0. * x, exact_basis_derivs_1d[0][:, 2], exact_basis_derivs_1d[0][:, 1] * exact_basis_vals_1d[1][:, 1], 0. * x ]).T)) # x2 derivative exact_basis_matrix = np.vstack( (exact_basis_matrix, np.asarray([ 0. * x, 0. * x, exact_basis_derivs_1d[1][:, 1], 0. * x, exact_basis_vals_1d[0][:, 1] * exact_basis_derivs_1d[1][:, 1], exact_basis_derivs_1d[1][:, 2] ]).T)) def func(x): return evaluate_multivariate_orthonormal_polynomial( x, indices, ab, 0) basis_matrix_derivs = basis_matrix[samples.shape[1]:] basis_matrix_derivs_fd = np.empty_like(basis_matrix_derivs) for ii in range(samples.shape[1]): basis_matrix_derivs_fd[ii::samples.shape[1], :] = approx_fprime( samples[:, ii:ii + 1], func, 1e-7) assert np.allclose(exact_basis_matrix[samples.shape[1]:], basis_matrix_derivs_fd) assert np.allclose(exact_basis_matrix, basis_matrix)
def test_evaluate_multivariate_mixed_basis_pce(self): degree = 2 deriv_order = 1 probability_measure = True gauss_mean, gauss_var = -1, 4 univariate_variables = [ uniform(-1, 2), norm(gauss_mean, np.sqrt(gauss_var)), uniform(0, 3) ] variable = IndependentMultivariateRandomVariable(univariate_variables) var_trans = AffineRandomVariableTransformation(variable) num_vars = len(univariate_variables) poly = PolynomialChaosExpansion() poly_opts = define_poly_options_from_variable_transformation(var_trans) poly.configure(poly_opts) univariate_quadrature_rules = [ partial(gauss_jacobi_pts_wts_1D, alpha_poly=0, beta_poly=0), gauss_hermite_pts_wts_1D, partial(gauss_jacobi_pts_wts_1D, alpha_poly=0, beta_poly=0) ] samples, weights = get_tensor_product_quadrature_rule( degree + 1, num_vars, univariate_quadrature_rules, var_trans.map_from_canonical_space) indices = compute_hyperbolic_indices(num_vars, degree, 1.0) # sort lexographically to make testing easier indices = sort_indices_lexiographically(indices) poly.set_indices(indices) basis_matrix = poly.basis_matrix(samples, {'deriv_order': 1}) vals_basis_matrix = basis_matrix[:samples.shape[1], :] inner_products = (vals_basis_matrix.T * weights).dot(vals_basis_matrix) assert np.allclose(inner_products, np.eye(basis_matrix.shape[1])) exact_basis_vals_1d = [] exact_basis_derivs_1d = [] for dd in range(num_vars): x = samples[dd, :].copy() if dd == 0 or dd == 2: if dd == 2: # y = x/3 # z = 2*y-1=2*x/3-1=2/3*x-3/2*2/3=2/3*(x-3/2)=(x-3/2)/(3/2) loc, scale = 3 / 2, 3 / 2 x = (x - loc) / scale exact_basis_vals_1d.append( np.asarray([1 + 0. * x, x, 0.5 * (3. * x**2 - 1)]).T) exact_basis_derivs_1d.append( np.asarray([0. * x, 1.0 + 0. * x, 3. * x]).T) exact_basis_vals_1d[-1] /= np.sqrt( 1. / (2 * np.arange(degree + 1) + 1)) exact_basis_derivs_1d[-1] /= np.sqrt( 1. / (2 * np.arange(degree + 1) + 1)) # account for affine transformation in derivs if dd == 2: exact_basis_derivs_1d[-1] /= scale if dd == 1: loc, scale = gauss_mean, np.sqrt(gauss_var) x = (x - loc) / scale exact_basis_vals_1d.append( np.asarray([1 + 0. * x, x, x**2 - 1]).T) exact_basis_derivs_1d.append( np.asarray([0. * x, 1.0 + 0. * x, 2. * x]).T) exact_basis_vals_1d[-1] /= np.sqrt( sp.factorial(np.arange(degree + 1))) exact_basis_derivs_1d[-1] /= np.sqrt( sp.factorial(np.arange(degree + 1))) # account for affine transformation in derivs exact_basis_derivs_1d[-1] /= scale exact_basis_matrix = np.asarray([ exact_basis_vals_1d[0][:, 0], exact_basis_vals_1d[0][:, 1], exact_basis_vals_1d[1][:, 1], exact_basis_vals_1d[2][:, 1], exact_basis_vals_1d[0][:, 2], exact_basis_vals_1d[0][:, 1] * exact_basis_vals_1d[1][:, 1], exact_basis_vals_1d[1][:, 2], exact_basis_vals_1d[0][:, 1] * exact_basis_vals_1d[2][:, 1], exact_basis_vals_1d[1][:, 1] * exact_basis_vals_1d[2][:, 1], exact_basis_vals_1d[2][:, 2] ]).T # x1 derivative exact_basis_matrix = np.vstack( (exact_basis_matrix, np.asarray([ 0. * x, exact_basis_derivs_1d[0][:, 1], 0. * x, 0 * x, exact_basis_derivs_1d[0][:, 2], exact_basis_derivs_1d[0][:, 1] * exact_basis_vals_1d[1][:, 1], 0. * x, exact_basis_derivs_1d[0][:, 1] * exact_basis_vals_1d[2][:, 1], 0. * x, 0. * x ]).T)) # x2 derivative exact_basis_matrix = np.vstack( (exact_basis_matrix, np.asarray([ 0. * x, 0. * x, exact_basis_derivs_1d[1][:, 1], 0. * x, 0 * x, exact_basis_derivs_1d[1][:, 1] * exact_basis_vals_1d[0][:, 1], exact_basis_derivs_1d[1][:, 2], 0. * x, exact_basis_derivs_1d[1][:, 1] * exact_basis_vals_1d[2][:, 1], 0. * x ]).T)) # x3 derivative exact_basis_matrix = np.vstack( (exact_basis_matrix, np.asarray([ 0. * x, 0. * x, 0. * x, exact_basis_derivs_1d[2][:, 1], 0 * x, 0 * x, 0 * x, exact_basis_derivs_1d[2][:, 1] * exact_basis_vals_1d[0][:, 1], exact_basis_derivs_1d[2][:, 1] * exact_basis_vals_1d[1][:, 1], exact_basis_derivs_1d[2][:, 2] ]).T)) func = poly.basis_matrix exact_basis_matrix_derivs = exact_basis_matrix[samples.shape[1]:] basis_matrix_derivs_fd = np.empty_like(exact_basis_matrix_derivs) for ii in range(samples.shape[1]): basis_matrix_derivs_fd[ii::samples.shape[1], :] = approx_fprime( samples[:, ii:ii + 1], func) # print(np.linalg.norm( # exact_basis_matrix_derivs-basis_matrix_derivs_fd, # ord=np.inf)) assert np.allclose(exact_basis_matrix_derivs, basis_matrix_derivs_fd, atol=1e-7, rtol=1e-7) assert np.allclose(exact_basis_matrix, basis_matrix)