def test_least_interpolant( self ): num_dims = 2 func_domain = TensorProductDomain( num_dims, [[-1,1]] ) x = -numpy.cos( numpy.linspace( 0., 1., 10 ) * numpy.pi ); [X,Y] = numpy.meshgrid( x, x ) build_points = numpy.vstack( ( X.reshape(( 1,X.shape[0]*X.shape[1])), Y.reshape(( 1, Y.shape[0]*Y.shape[1])))) build_values = matlab_peaks( build_points ) poly_1d = [ LegendrePolynomial1D() ] basis = TensorProductBasis( num_dims, poly_1d ) linear_solver = LeastInterpolation() predictor = PCE( build_points.shape[0], basis = basis, linear_solver = linear_solver ) predictor.function_domain( func_domain ) predictor.build( build_points, build_values ) result = predictor.evaluate_set( build_points ) if ( result.ndim > 1 ): result = result.reshape( result.shape[0] ) error = result - build_values l2_error = numpy.sqrt( numpy.dot( error.T, error ) / \ build_points.shape[1] ) print 'error at nodes: %1.15e' %l2_error assert l2_error < self.eps poly_1d = [ JacobiPolynomial1D( 0.5, 0.5 ) ] basis = TensorProductBasis( num_dims, poly_1d ) linear_solver = LeastInterpolation() predictor = PCE( build_points.shape[0], basis = basis, linear_solver = linear_solver ) predictor.function_domain( func_domain ) predictor.build( build_points, build_values ) result = predictor.evaluate_set( build_points ) if ( result.ndim > 1 ): result = result.reshape( result.shape[0] )
def interpolation_1d_test_I( f ): seed = 2 rng = numpy.random#.RandomState( seed ) # 1D example with least interpolation order = 3 num_dims = 1 func_domain = TensorProductDomain( num_dims, [[-1.,1.]] ) poly_1d = [ LegendrePolynomial1D() ] basis = TensorProductBasis( num_dims, poly_1d ) linear_solver = LeastInterpolation() predictor = PCE( num_dims, basis, order = order, linear_solver = linear_solver ) predictor.function_domain( func_domain ) x = -numpy.cos( numpy.linspace( 0., 1., order + 1 ) * numpy.pi ); build_points = x.reshape( 1, x.shape[0] ) build_values = f( build_points[0,:] ) p = predictor.build( build_points, build_values ) print 'c', predictor.coeff
def test_polynomial_chaos_expansion( self ): # test 1D bounded domain num_dims = 1 func_domain = TensorProductDomain( num_dims ) poly_1d = [ JacobiPolynomial1D( 0., 0. ) ] basis = TensorProductBasis( num_dims, poly_1d ) predictor = PCE( num_dims, basis, order = 2 ) predictor.set_coefficients( numpy.ones( predictor.coeff.shape ) ) predictor.function_domain( func_domain ) num_test_points = 20 test_points = \ numpy.linspace( 0., 1., num_test_points ).reshape(1,num_test_points) pred_vals = predictor.evaluate_set( test_points ) x = 2. * test_points - 1. test_vals = numpy.ones( num_test_points ) + x[0,:] + \ 0.5 * ( 3.*x[0,:]**2 - 1. ) assert numpy.allclose( test_vals, pred_vals ) test_mean = 1. test_variance = 1./3. + 1./5. assert numpy.allclose( predictor.mean(), test_mean ) assert numpy.allclose( predictor.variance(), test_variance ) # test 2D bounded domain num_dims = 2 func_domain = TensorProductDomain( num_dims ) poly_1d = [ JacobiPolynomial1D( 0., 0. ) ] basis = TensorProductBasis( num_dims, poly_1d ) predictor = PCE( num_dims, basis, order = 2 ) predictor.set_coefficients( numpy.ones( predictor.coeff.shape ) ) predictor.function_domain( func_domain ) num_test_points = 20 test_points = numpy.random.uniform( 0., 1., ( num_dims, num_test_points)) pred_vals = predictor.evaluate_set( test_points ) x = 2. * test_points - 1. test_vals = numpy.ones( num_test_points ) + x[0,:] + x[1,:] + \ 0.5 * ( 3.*x[0,:]**2 - 1. ) + 0.5 * ( 3.*x[1,:]**2 - 1. ) + \ x[0,:] * x[1,:] assert numpy.allclose( test_vals, pred_vals ) test_mean = 1. test_variance = 2. * 1./3. + 1./9. + 2. * 1./5. assert numpy.allclose( predictor.mean(), test_mean ) assert numpy.allclose( predictor.variance(), test_variance ) # test when domain is unbounded in one dimension num_dims = 2 func_domain = TensorProductDomain( num_dims, ranges = [[0.,1.], [-numpy.inf, numpy.inf]] ) poly_1d = [ JacobiPolynomial1D( 0., 0. ), HermitePolynomial1D() ] basis = TensorProductBasis( num_dims, poly_1d ) predictor = PCE( num_dims, basis, order = 2 ) predictor.set_coefficients( numpy.ones( predictor.coeff.shape ) ) predictor.function_domain( func_domain ) num_test_points = 20 x_1 = numpy.random.uniform( 0., 1., ( 1, 20 ) ) x_2 = numpy.random.normal( 0., 1., ( 1, 20 ) ) test_points = numpy.vstack( ( x_1, x_2 ) ) pred_vals = predictor.evaluate_set( test_points ) x = test_points x[0,:] = 2. * x[0,:] - 1. test_vals = numpy.ones( num_test_points ) + x[0,:] + x[1,:] + \ 0.5 * ( 3.*x[0,:]**2 - 1. ) + ( x[1,:]**2 - 1. ) + \ x[0,:] * x[1,:] assert numpy.allclose( test_vals, pred_vals ) test_mean = 1. test_variance = 2. * 1./3. + 1./5. + 2. + 1. assert numpy.allclose( predictor.mean(), test_mean ) assert numpy.allclose( predictor.variance(), test_variance )
class GridPointAdaptedSparseGrid(object): def __init__( self, num_dims, max_level, quadrature_rule, refinement_manager, sparse_grid_data, target_function ): self.num_dims = num_dims self.max_level = max_level self.quadrature_rule = quadrature_rule self.refinement_manager = refinement_manager self.target_function = target_function # for least interpolant poly_1d = [ LegendrePolynomial1D() ] basis = TensorProductBasis( num_dims, poly_1d ) linear_solver = LeastInterpolation() self.pce = PCE( self.num_dims, basis = basis, linear_solver = linear_solver ) self.pce.function_domain( self.quadrature_rule.domain ) # grid points used in the sparse grid self.grid_point_indices = set() # number of grid points in the grid. This is not equal to # len( self.grid_point_indices ). The later contains all grid points # including candidates and those actually in the grid self.num_grid_points = 0 # grid points that are candidates for addition to the sparse grid # but have not been initialized and so can not be prioritized self.uninit_grid_point_indices = set() # grid points that are candidates for addition to the sparse grid self.candidate_grid_point_indices_queue = [] # Python note: heap[0] has the smallest value ( inverse of priority ), # i.e the highest prioirity # grid points that are candidates for addition to the sparse grid # This object will contain the same grid point indices as # self.candidate_grid_point_indices_queue but is used to ensure a # point is only added to the self.candidate_grid_point_indices_queue #once self.candidate_grid_point_indices_hash = set() # keep track of the number of grid points generated # ( self.num_grid_points + self.num_candidate_grid_points + # self.num_uninit_grid_points ) self.num_grid_point_indices_generated = 0 self.data = sparse_grid_data def build_root( self ): """ Initialize the grid by creating the root subspace """ root_grid_point_index = GridPointIndex( None ) self.insert_uninit_grid_point( root_grid_point_index ) def insert_remaining_candidate_points( self ): if ( self.refinement_manager.candidate_point_needs_func_eval() ): while ( len( self.candidate_grid_point_indices_queue ) > 0 ): inv_priority, grid_point_index = \ heapq.heappop( self.candidate_grid_point_indices_queue ) self.candidate_grid_point_indices_hash.remove( grid_point_index ) self.insert_grid_point( grid_point_index ) def insert_next_grid_point( self ): """ Insert a subspace into the list of subspaces in the grid """ # if two indices have the same priority the indices themselves will be # compared inv_priority, grid_point_index = \ heapq.heappop( self.candidate_grid_point_indices_queue ) self.candidate_grid_point_indices_hash.remove( grid_point_index ) if ( grid_point_index not in self.grid_point_indices ): if ( not self.refinement_manager.candidate_point_needs_func_eval() ): self.evaluate_target_function( grid_point_index ) self.insert_grid_point( grid_point_index ) else: # point was originally a missing parent pass return grid_point_index def insert_uninit_grid_point( self, grid_point_index ): if ( grid_point_index not in self.uninit_grid_point_indices and grid_point_index not in self.candidate_grid_point_indices_hash and grid_point_index not in self.grid_point_indices and self.refinement_manager.grid_point_admissible( grid_point_index ) ): self.uninit_grid_point_indices.add( grid_point_index ) grid_point_index.array_index = self.num_grid_point_indices_generated self.num_grid_point_indices_generated += 1 def insert_candidate_grid_point( self, grid_point_index ): # I think this can be removed if check is made when point is added to # unitialized set, check for existance must be made for uninit # candidate and sparse grid points if ( grid_point_index not in self.candidate_grid_point_indices_hash ): heapq.heappush( self.candidate_grid_point_indices_queue, ( 1. / grid_point_index.priority, grid_point_index )) self.candidate_grid_point_indices_hash.add( grid_point_index ) else: msg = 'grid point already exists' raise Exception, msg def insert_grid_point( self, grid_point_index ): self.grid_point_indices.add( grid_point_index ) self.num_grid_points += 1 def refine( self ): """ Perform point-wise adaptive refinement. Extract the grid points with the highest priority. """ grid_point_index = self.insert_next_grid_point() if self.refinement_manager.grid_point_warrants_refinement( grid_point_index ): for dim in xrange( self.quadrature_rule.num_dims ): # todo would be better not to assume that a left and right child # are both available or more are not as well child_index = self.quadrature_rule.child_index( grid_point_index, dim, 'left' ) if child_index is not None: self.insert_uninit_grid_point( child_index ) child_index = self.quadrature_rule.child_index( grid_point_index, dim, 'right' ) if child_index is not None: self.insert_uninit_grid_point( child_index ) def compute_hierarical_surpluses( self, fn_val, coord, grid_point_index ): self.insert_missing_parent_grid_points( grid_point_index ) subspace_index = grid_point_index.subspace_index() return fn_val - self.evaluate_set( coord.reshape( self.num_dims,1), subspace_index ) # evaluate all points belonging to subspaces that have indices <= # current_subspace_index def evaluate_set( self, pts, current_subspace_index = None ): result = numpy.zeros( ( pts.shape[1] ), numpy.double ) for grid_point_index in self.grid_point_indices: evaluate_grid_point = True # this is very expensive. at least in python #grid_point_subspace_index = grid_point_index.subspace_index() #if ( current_subspace_index is None ): # evaluate_grid_point = True #elif ( grid_point_subspace_index <= current_subspace_index ): # evaluate_grid_point = True #else: # evaluate_grid_point = False if ( evaluate_grid_point ): if ( grid_point_index.data is not None ): #evaluate basis result += \ self.data.hier_surplus[grid_point_index.array_index] * \ self.quadrature_rule.basis.value( pts, grid_point_index, self.quadrature_rule.domain ) else: result += \ self.data.hier_surplus[grid_point_index.array_index] * \ numpy.ones( ( result.shape[0] ), numpy.double ) return result def evaluate_set1( self, pts, current_subspace_index = None ): if ( len( self.grid_point_indices ) == 0 ): return numpy.zeros( ( pts.shape[1] ), numpy.double ) poly_indices = \ get_polynomial_indices_of_subspace_indices( self.refinement_manager.subspace_indices, self.quadrature_rule ) coords = numpy.empty( ( self.num_dims, len( self.grid_point_indices ) ), numpy.double ) values = numpy.empty( ( len( self.grid_point_indices ), 1 ), numpy.double ) for i, grid_point_index in enumerate( self.grid_point_indices ): coords[:,i] = \ self.quadrature_rule.coordinate( grid_point_index ) values[i,0] = self.data.fn_vals[grid_point_index.array_index] self.pce.build( coords, values ) return self.pce.evaluate_set( pts ) def grid_point_coordinates( self ): coords = numpy.empty( ( self.num_dims, len( self.grid_point_indices ) ), numpy.double ) for i, grid_point_index in enumerate( self.grid_point_indices ): coords[:,i] = \ self.quadrature_rule.coordinate( grid_point_index ) return coords def insert_parent_grid_point( self, grid_point_index ): # If the parent is missing from self.sparse_grid_indices # always promote it to self.sparse grid_indices. # If the parent is in self.candidate_grid_point_indices # keep it there so it will be refined. Doing this means that # in insert_next_grid_point we must include a check that does not # allow points that are already in self.sparse_grid_indices to # be added again. We must also evaluate # the target function if it has not been evaluated already. # If the parent is in self.uninit_grid_point_indices # then promote it to the candidate set. We must always calculate # the priority and evaluate the function if not done so already. self.insert_missing_parent_grid_points( grid_point_index ) # Check if grid_point_index is in a candidate point array_index = None grid_point_index_ref=find( self.candidate_grid_point_indices_hash, grid_point_index ) if ( grid_point_index_ref is not None ): # grid_point_index is not a candidate point. # grid_point_index_ref contains is the original index # contained in self.candidate_grid_point_indices_hash. # grid_point_index will not have priority or aray_index set. # only evaluate function if not done so already if ( not self.refinement_manager.candidate_point_needs_func_eval() ): self.evaluate_target_function( grid_point_index_ref ) # promote point to the sparse grid self.insert_grid_point( grid_point_index_ref ) else: # grid_point_index is not a candidate point so check if it is # an uninit point grid_point_index_ref = \ find( self.uninit_grid_point_indices, grid_point_index ) if ( grid_point_index_ref is not None ): # grid_point_index is an uninit point # grid_point_index_ref contains is the original index # contained in self.uninit_grid_point_indices. self.uninit_grid_point_indices.remove(grid_point_index_ref) self.insert_candidate_grid_point( grid_point_index_ref ) else: # grid_point_index is not an uninit point or candidate # point grid_point_index_ref = grid_point_index grid_point_index_ref.array_index = \ self.num_grid_point_indices_generated self.num_grid_point_indices_generated += 1 self.evaluate_target_function( grid_point_index_ref ) self.refinement_manager.prioritize_grid_point( grid_point_index_ref ) self.insert_candidate_grid_point( grid_point_index_ref ) self.insert_grid_point( grid_point_index ) def insert_missing_parent_grid_points( self, grid_point_index ): for d in xrange( grid_point_index.num_effect_dims() ): dim = grid_point_index.dimension_from_array_index ( d ) parent_index = self.quadrature_rule.parent_index( grid_point_index, dim ) if ( parent_index not in self.grid_point_indices ): self.insert_parent_grid_point( parent_index ) def evaluate_target_function( self, grid_point_index ): coord = self.quadrature_rule.coordinate( grid_point_index ) coord = coord.reshape( coord.shape[0], 1 ) array_index = grid_point_index.array_index self.data.set_fn_vals( self.target_function( coord ), array_index ) hier_surplus = \ self.compute_hierarical_surpluses( self.data.fn_vals[array_index], coord, grid_point_index ) self.data.set_hier_surplus( hier_surplus, array_index ) self.refinement_manager.num_model_runs +=1 def prioritize( self ): for grid_point_index in self.uninit_grid_point_indices: if ( self.refinement_manager.candidate_point_needs_func_eval() ): self.evaluate_target_function( grid_point_index ) self.refinement_manager.prioritize_grid_point( grid_point_index ) self.insert_candidate_grid_point( grid_point_index ) self.uninit_grid_point_indices = set()