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 test_pce_build( self ): f = lambda x: numpy.sum( x**5, axis = 0 ) num_dims = 2 func_domain = TensorProductDomain( num_dims, ranges = [[-1.,1.]] ) poly_1d = [ LegendrePolynomial1D() ] basis = TensorProductBasis( num_dims, poly_1d ) predictor = PCE( num_dims, basis, order = 5, func_domain = func_domain, index_norm_order = 0.5 ) rng = numpy.random.RandomState( 0 ) build_pts = rng.uniform( -1., 1., ( num_dims , 21 ) ) build_vals = f( build_pts ) predictor.build( build_pts, build_vals ) true_mean = mean_anisotropic_sum_of_monomials_2d( 5, 5 ) true_var = variance_anisotropic_sum_of_monomials_2d( 5, 5 ) assert numpy.allclose( predictor.mean(), true_mean ) assert numpy.allclose( predictor.variance(), true_var )
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
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()