def pick_ffd_points(centers, rvec): r""" Pick Lambda_dim points, for each centers, for a forward finite difference gradient approximation. The points are returned in the order: centers, followed by the cluster around the first center, then the cluster around the second center and so on. :param centers: Points in :math:`\Lambda` the place stencil around :type centers: :class:`np.ndarray` of shape (num_centers, Lambda_dim) :param rvec: The radius of the stencil, along each axis :type rvec: :class:`np.ndarray` of shape (Lambda_dim,) :rtype: :class:`np.ndarray` of shape ((Lambda_dim+1)*num_centers, Lambda_dim) :returns: Samples for centered finite difference stencil for each point in centers. """ Lambda_dim = centers.shape[1] num_centers = centers.shape[0] samples = np.repeat(centers, Lambda_dim, axis=0) rvec = util.fix_dimensions_vector(rvec) # Construct a [num_centers*(Lambda_dim+1), Lambda_dim] matrix that # translates the centers to the FFD points. translate = np.tile(np.eye(Lambda_dim) * rvec, (num_centers, 1)) samples = samples + translate return np.concatenate([centers, samples])
def pick_cfd_points(centers, rvec): r""" Pick 2*Lambda_dim points, for each center, for centered finite difference gradient approximation. The center are not needed for the CFD gradient approximation, they are returned for consistency with the other methods and because of the common need to have not just the gradient but also the QoI value at the centers in adaptive sampling algorithms.The points are returned in the order: centers, followed by the cluster around the first center, then the cluster around the second center and so on. :param centers: Points in :math:`\Lambda` to cluster points around :type centers: :class:`np.ndarray` of shape (num_centers, Lambda_dim) :param rvec: The radius of the stencil, along each axis :type rvec: :class:`np.ndarray` of shape (Lambda_dim,) :rtype: :class:`np.ndarray` of shape ((2*Lambda_dim+1)*num_centers, Lambda_dim) :returns: Samples for centered finite difference stencil for each point in centers. """ Lambda_dim = centers.shape[1] num_centers = centers.shape[0] samples = np.repeat(centers, 2 * Lambda_dim, axis=0) rvec = util.fix_dimensions_vector(rvec) # Contstruct a [num_centers*2*Lambda_dim, Lambda_dim] matrix that # translates the centers to the CFD points ident = np.eye(Lambda_dim) * rvec translate = np.tile(np.append(ident, -ident, axis=0), (num_centers, 1)) samples = samples + translate return np.concatenate([centers, samples])
def test_fix_dimensions_vector(): """ Tests :meth:`bet.util.fix_dimensions_vector` """ values = [1, [1], range(5), np.array(range(5)), np.ones((5, 1)), np.ones((5, 5))] shapes = [(1,), (1,), (5,), (5,), (5,), (25,)] for value, shape in zip(values, shapes): vector = util.fix_dimensions_vector(value) assert vector.shape == shape
def test_fix_dimensions_vector(): """ Tests :meth:`bet.util.fix_dimensions_vector` """ values = [ 1, [1], range(5), np.array(range(5)), np.ones((5, 1)), np.ones((5, 5)) ] shapes = [(1, ), (1, ), (5, ), (5, ), (5, ), (25, )] for value, shape in zip(values, shapes): vector = util.fix_dimensions_vector(value) assert vector.shape == shape
def pick_cfd_points(input_set, radii_vec): r""" Pick 2*input_dim points, for each center, for centered finite difference gradient approximation. The center are not needed for the CFD gradient approximation, they are returned for consistency with the other methods and because of the common need to have not just the gradient but also the QoI value at the centers in adaptive sampling algorithms.The points are returned in the order: centers, followed by the cluster around the first center, then the cluster around the second center and so on. :param input_set: The input sample set. Make sure the attribute _values is not None :type input_set: :class:`~bet.sample.sample_set` :param radii_vec: The radius of the stencil, along each axis :type radii_vec: :class:`numpy.ndarray` of shape (input_dim,) :rtype: :class:`~bet.sample.sample_set` :returns: Centers and clusters of samples near each center (values are :class:`numpy.ndarray` of shape ((``num_close+1``)*``num_centers``, ``input_dim``)) """ if input_set._values is None: raise ValueError("You must have values to use this method.") input_dim = input_set.get_dim() centers = input_set.get_values() num_centers = centers.shape[0] samples = np.repeat(centers, 2 * input_dim, axis=0) radii_vec = util.fix_dimensions_vector(radii_vec) # Contstruct a [num_centers*2*input_dim, input_dim] array that # translates the centers to the CFD points ident = np.eye(input_dim) * radii_vec translate = np.tile(np.append(ident, -ident, axis=0), (num_centers, 1)) samples = samples + translate cluster_set = sample.sample_set(input_dim) if input_set.get_domain() is not None: cluster_set.set_domain(input_set.get_domain()) cluster_set.set_values(centers) cluster_set.append_values(samples) return cluster_set
def sample_linf_ball(centers, num_close, rvec, lam_domain=None): r""" Pick num_close points in a the l-infinity ball of length 2*rvec around a point in :math:`\Lambda`, do this for each point in centers. If this box extends outside of :math:`\Lambda`, we sample the intersection. :param centers: Points in :math:`\Lambda` to cluster points around :type centers: :class:`np.ndarray` of shape (num_centers, Lambda_dim) :param int num_close: Number of points in each cluster :param rvec: Each side of the box will have length 2*rvec[i] :type rvec: :class:`np.ndarray` of shape (Lambda_dim,) :param lam_domain: The domain of the parameter space :type lam_domain: :class:`np.ndarray` of shape (Lambda_dim, 2) :rtype: :class:`np.ndarray` of shape ((num_close+1)*num_centers, Lambda_dim) :returns: Centers and clusters of samples near each center """ Lambda_dim = centers.shape[1] num_centers = centers.shape[0] rvec = util.fix_dimensions_vector(rvec) #If no lam_domain, set domain large if lam_domain is None: lam_domain = np.zeros([Lambda_dim, 2]) lam_domain[:, 0] = -sys.float_info[0] lam_domain[:, 1] = sys.float_info[0] # Define bounds for each box left = np.maximum( centers - rvec, np.ones([num_centers, Lambda_dim]) * lam_domain[:, 0]) right = np.minimum( centers + rvec, np.ones([num_centers, Lambda_dim]) * lam_domain[:, 1]) # Samples each box uniformly samples = np.repeat(right - left, num_close, axis=0) * np.random.random( [num_centers * num_close, Lambda_dim]) + np.repeat(left, num_close, \ axis=0) return np.concatenate([centers, samples])
def pick_ffd_points(input_set, radii_vec): r""" Pick input_dim points, for each centers, for a forward finite difference gradient approximation. The points are returned in the order: centers, followed by the cluster around the first center, then the cluster around the second center and so on. :param input_set: The input sample set. Make sure the attribute _values is not None :type input_set: :class:`~bet.sample.sample_set` :param radii_vec: The radius of the stencil, along each axis :type radii_vec: :class:`numpy.ndarray` of shape (input_dim,) :rtype: :class:`~bet.sample.sample_set` :returns: Centers and clusters of samples near each center (values are :class:`numpy.ndarray` of shape ((``num_close+1``)*``num_centers``, ``input_dim``)) """ if input_set._values is None: raise ValueError("You must have values to use this method.") input_dim = input_set.get_dim() centers = input_set.get_values() num_centers = centers.shape[0] samples = np.repeat(centers, input_dim, axis=0) radii_vec = util.fix_dimensions_vector(radii_vec) # Construct a [num_centers*(input_dim+1), input_dim] matrix that # translates the centers to the FFD points. translate = np.tile(np.eye(input_dim) * radii_vec, (num_centers, 1)) samples = samples + translate cluster_set = sample.sample_set(input_dim) if input_set.get_domain() is not None: cluster_set.set_domain(input_set.get_domain()) cluster_set.set_values(centers) cluster_set.append_values(samples) return cluster_set
def sample_l1_ball(centers, num_close, rvec): r""" Uniformly sample the l1-ball (defined by 2^dim simplices). Then scale each dimension according to rvec and translate the center to centers. Do this for each point in centers. *This method currently allows samples to be placed outside of lam_domain. Please place your centers accordingly.* :param centers: Points in :math:`\Lambda` to cluster samples around :type centers: :class:`np.ndarray` of shape (num_centers, Ldim) :param int num_close: Number of samples in each l1 ball :param rvec: The radius of the l1 ball, along each axis :type rvec: :class:`np.ndarray` of shape (Lambda_dim) :rtype: :class:`np.ndarray` of shape ((num_close+1)*num_centers, Lambda_dim) :returns: Uniform random samples from an l1 ball around each center """ Lambda_dim = centers.shape[1] rvec = util.fix_dimensions_vector(rvec) samples = np.zeros([(num_close + 1) * centers.shape[0], centers.shape[1]]) samples[0:centers.shape[0], :] = centers # We choose weighted random distance from the center for each new sample random_dist = np.random.random([num_close, 1]) weight_vec = random_dist**(1. / Lambda_dim) # For each center, randomly sample the l1_ball for cen in range(centers.shape[0]): # Begin by uniformly sampling the unit simplex in the first quadrant # Choose Lambda_dim-1 reals uniformly between 0 and weight_vec for each # new sample random_mat = np.random.random([num_close, Lambda_dim - 1]) * \ np.tile(weight_vec, (1, Lambda_dim - 1)) # Sort the random_mat random_mat = np.sort(random_mat, 1) # Contrust weight_mat so that the first column is zeros, the next # Lambda_dim-1 columns are the sorted reals between 0 and weight_vec, # and the last column is weight_vec. weight_mat = np.zeros([num_close, Lambda_dim + 1]) weight_mat[:, 1:Lambda_dim] = random_mat weight_mat[:, Lambda_dim] = np.array(weight_vec).transpose() # The differences between the Lambda_dim+1 columns will give us # random points in the unit simplex of dimension Lambda_dim. samples_cen = np.zeros([num_close, Lambda_dim]) for Ldim in range(Lambda_dim): samples_cen[:, Ldim] = weight_mat[:, Ldim + 1] - weight_mat[:, Ldim] # Assign a random sign to each element of each new sample # This give us samples in the l1_ball, not just the unit simplex in # the first quadrant rand_sign = 2 * np.round(np.random.random([num_close, Lambda_dim])) - 1 samples_cen = samples_cen * rand_sign # Scale each dimension according to rvec and translate to center samples_cen = samples_cen * rvec + centers[cen, :] # Append newsamples to samples samples[centers.shape[0] + cen * num_close:centers.shape[0] + \ (cen + 1) * num_close, :] = samples_cen return samples