Пример #1
0
def calculate_gradients_cfd(samples, data, normalize=True):
    """
    Approximate gradient vectors at ``num_centers, centers.shape[0]`` points
    in the parameter space for each QoI map.  THIS METHOD IS DEPENDENT
    ON USING :meth:~bet.sensitivity.pick_cfd_points TO CHOOSE SAMPLES FOR THE 
    CFD STENCIL AROUND EACH CENTER.  THE ORDERING MATTERS.

    :param samples: Samples for which the model has been solved.
    :type samples: :class:`np.ndarray` of shape
        (2*Lambda_dim*num_centers, Lambda_dim)
    :param data: QoI values corresponding to each sample.
    :type data: :class:`np.ndarray` of shape (num_samples, Data_dim)

    :rtype: :class:`np.ndarray` of shape (num_samples, Data_dim, Lambda_dim)
    :returns: Tensor representation of the gradient vectors of each
        QoI map at each point in centers

    """
    num_model_samples = samples.shape[0]
    Lambda_dim = samples.shape[1]
    num_centers = num_model_samples / (2*Lambda_dim + 1)

    # Find rvec from the first cluster of samples
    rvec = samples[num_centers:num_centers + Lambda_dim, :] - samples[0, :]
    rvec = util.fix_dimensions_vector_2darray(rvec.diagonal())

    # Clean the data
    data = util.fix_dimensions_vector_2darray(util.clean_data(
        data[num_centers:]))
    num_qois = data.shape[1]
    gradient_tensor = np.zeros([num_centers, num_qois, Lambda_dim])

    rvec = np.tile(np.repeat(rvec, num_qois, axis=1), [num_centers, 1])

    # Construct indices for CFD gradient approxiation
    inds = np.repeat(range(0, 2 * Lambda_dim * num_centers, 2 * Lambda_dim),
        Lambda_dim) + np.tile(range(0, Lambda_dim), num_centers)
    inds = np.array([inds, inds+Lambda_dim]).transpose()

    gradient_mat = (data[inds[:, 0]] - data[inds[:, 1]]) * (0.5 / rvec)

    # Reshape and organize
    gradient_tensor = np.reshape(gradient_mat.transpose(), [num_qois,
        Lambda_dim, num_centers], order='F').transpose(2, 0, 1)

    if normalize:
        # Compute the norm of each vector
        norm_gradient_tensor = np.linalg.norm(gradient_tensor, axis=2)

        # If it is a zero vector (has 0 norm), set norm=1, avoid divide by zero
        norm_gradient_tensor[norm_gradient_tensor == 0] = 1.0

        # Normalize each gradient vector
        gradient_tensor = gradient_tensor/np.tile(norm_gradient_tensor,
            (Lambda_dim, 1, 1)).transpose(1, 2, 0)

    return gradient_tensor
Пример #2
0
def calculate_gradients_cfd(samples, data, normalize=True):
    """
    Approximate gradient vectors at ``num_centers, centers.shape[0]`` points
    in the parameter space for each QoI map.  THIS METHOD IS DEPENDENT
    ON USING :meth:~bet.sensitivity.pick_cfd_points TO CHOOSE SAMPLES FOR THE 
    CFD STENCIL AROUND EACH CENTER.  THE ORDERING MATTERS.
    :param samples: Samples for which the model has been solved.
    :type samples: :class:`np.ndarray` of shape
        (2*Lambda_dim*num_centers, Lambda_dim)
    :param data: QoI values corresponding to each sample.
    :type data: :class:`np.ndarray` of shape (num_samples, Data_dim)
    :param boolean normalize:  If normalize is True, normalize each gradient
        vector
    :rtype: :class:`np.ndarray` of shape (num_samples, Data_dim, Lambda_dim)
    :returns: Tensor representation of the gradient vectors of each
        QoI map at each point in centers
    """
    num_model_samples = samples.shape[0]
    Lambda_dim = samples.shape[1]
    num_centers = num_model_samples / (2*Lambda_dim + 1)

    # Find rvec from the first cluster of samples
    rvec = samples[num_centers:num_centers + Lambda_dim, :] - samples[0, :]
    rvec = util.fix_dimensions_vector_2darray(rvec.diagonal())

    # Clean the data
    data = util.fix_dimensions_vector_2darray(util.clean_data(
        data[num_centers:]))
    num_qois = data.shape[1]
    gradient_tensor = np.zeros([num_centers, num_qois, Lambda_dim])

    rvec = np.tile(np.repeat(rvec, num_qois, axis=1), [num_centers, 1])

    # Construct indices for CFD gradient approxiation
    inds = np.repeat(range(0, 2 * Lambda_dim * num_centers, 2 * Lambda_dim),
        Lambda_dim) + np.tile(range(0, Lambda_dim), num_centers)
    inds = np.array([inds, inds+Lambda_dim]).transpose()

    gradient_mat = (data[inds[:, 0]] - data[inds[:, 1]]) * (0.5 / rvec)

    # Reshape and organize
    gradient_tensor = np.reshape(gradient_mat.transpose(), [num_qois,
        Lambda_dim, num_centers], order='F').transpose(2, 0, 1)

    if normalize:
        # Compute the norm of each vector
        norm_gradient_tensor = np.linalg.norm(gradient_tensor, ord=1, axis=2)

        # If it is a zero vector (has 0 norm), set norm=1, avoid divide by zero
        norm_gradient_tensor[norm_gradient_tensor == 0] = 1.0

        # Normalize each gradient vector
        gradient_tensor = gradient_tensor/np.tile(norm_gradient_tensor,
            (Lambda_dim, 1, 1)).transpose(1, 2, 0)

    return gradient_tensor
Пример #3
0
 def test_hypersphere(self):
     """
     Test :meth:`bet.calculateP.indicatorFunctions.hypersphere`
     """
     indicator = ifun.hypersphere(self.center, self.radius)
     assert np.all(indicator(util.fix_dimensions_vector_2darray(self.center)))
     assert False == np.all(indicator(self.outcoords_sphere))
Пример #4
0
 def test_hyperrectangle_size(self):
     """
     Test :meth:`bet.calculateP.indicatorFunctions.hyperrectangle_size`
     """
     indicator = ifun.hyperrectangle_size(self.center, self.width)
     assert np.all(indicator(util.fix_dimensions_vector_2darray(self.center)))
     assert False == np.all(indicator(self.outcoords_rect))
Пример #5
0
 def test_hypersphere(self):
     """
     Test :meth:`bet.calculateP.indicatorFunctions.hypersphere`
     """
     indicator = ifun.hypersphere(self.center, self.radius)
     assert np.all(
         indicator(util.fix_dimensions_vector_2darray(self.center)))
     assert False == np.all(indicator(self.outcoords_sphere))
Пример #6
0
 def test_hyperrectangle(self):
     """
     Test :meth:`bet.calculateP.indicatorFunctions.hyperrectangle`
     """
     indicator = ifun.hyperrectangle(self.left, self.right)
     assert np.all(
         indicator(util.fix_dimensions_vector_2darray(self.center)))
     assert False == np.all(indicator(self.outcoords_rect))
Пример #7
0
def test_fix_dimensions_vector_2darray():
    """
    Tests :meth:`bet.util.fix_dimensions_vector_2darray`
    """
    values = [1, [1], np.empty((1, 1)), range(5), np.array(range(5)), np.empty((5, 1))]
    shapes = [(1, 1), (1, 1), (1, 1), (5, 1), (5, 1), (5, 1)]
    for value, shape in zip(values, shapes):
        vector = util.fix_dimensions_vector_2darray(value)
        assert vector.shape == shape
Пример #8
0
 def test_boundary_hyperrectangle(self):
     """
     Test :meth:`bet.calculateP.indicatorFunctions.boundary_hyperrectangle`
     """
     indicator = ifun.boundary_hyperrectangle(self.left, self.right,
             self.boundary_width)
     assert False == np.all(indicator(util.fix_dimensions_vector_2darray(self.center)))
     assert False == np.all(indicator(self.outcoords_rect))
     assert np.all(indicator(self.oncoords_rect))
Пример #9
0
 def test_boundary_hyperrectangle_size_ratio(self):
     """
     Test
     :meth:`bet.calculateP.indicatorFunctions.boundary_hyperrectangle_size_ratio`
     """
     indicator = ifun.boundary_hyperrectangle_size_ratio(self.center,
                                                         self.width, self.boundary_ratio)
     assert False == np.all(
         indicator(util.fix_dimensions_vector_2darray(self.center)))
     assert False == np.all(indicator(self.outcoords_rect))
     assert np.all(indicator(self.oncoords_rect))
Пример #10
0
def test_fix_dimensions_vector_2darray():
    """
    Tests :meth:`bet.util.fix_dimensions_vector_2darray`
    """
    values = [
        1, [1],
        np.empty((1, 1)),
        range(5),
        np.array(range(5)),
        np.empty((5, 1))
    ]
    shapes = [(1, 1), (1, 1), (1, 1), (5, 1), (5, 1), (5, 1)]
    for value, shape in zip(values, shapes):
        vector = util.fix_dimensions_vector_2darray(value)
        assert vector.shape == shape
Пример #11
0
def find_good_sets(grad_tensor, good_sets_prev, unique_indices,
        num_optsets_return, cond_tol, volume):
    r"""
    #TODO:  Use the idea we only know vectors are with 10% accuracy to guide
        inner_prod tol and condnum_tol.
    Given gradient vectors at each center in the parameter space and given
    good sets of size n - 1, return good sets of size n.  That is, return
    sets of size n that have average condition number less than some tolerance.
    :param grad_tensor: Gradient vectors at each centers in the parameter
        space :math:'\Lambda' for each QoI map.
    :type grad_tensor: :class:`np.ndarray` of shape (num_centers,num_qois,Ldim)
        where num_centers is the number of points in :math:'\Lambda' we have
        approximated the gradient vectors, num_qois is the total number of
        possible QoIs to choose from, Ldim is the dimension of :math:`\Lambda`.
    :param good_sets_prev: Good sets of QoIs of size n - 1.
    :type good_sets_prev: :class:`np.ndarray` of size (num_good_sets_prev, n - 1)
    :param unique_indices: Unique QoIs to consider.
    :type unique_indices: :class:'np.ndarray' of size (num_unique_qois, 1)
    :param int num_optsets_return: Number of best sets to return
    :param float cond_tol: Throw out all sets of QoIs with average condition
        number greater than this.
    :param boolean volume: If volume is True, use ``calculate_avg_volume``
        to determine optimal QoIs
    :rtype: tuple
    :returns: (good_sets, best_sets, optsingvals_tensor) where good sets has
        size (num_good_sets, n), best sets has size (num_optsets_return,
        n + 1) and optsingvals_tensor has size (num_centers, n, Lambda_dim)
    """
    num_centers = grad_tensor.shape[0]
    Lambda_dim = grad_tensor.shape[2]
    num_qois_return = good_sets_prev.shape[1] + 1
    comm.Barrier()

    # Initialize best sets and set all condition numbers large
    best_sets = np.zeros([num_optsets_return, num_qois_return + 1])
    best_sets[:, 0] = 1E99
    good_sets = np.zeros([1, num_qois_return])
    count_qois = 0
    optsingvals_tensor = np.zeros([num_centers, num_qois_return,
        num_optsets_return])

    # For each good set of size n - 1, find the possible sets of size n and
    # compute the average condition number of each
    count_qois = 0
    for i in range(good_sets_prev.shape[0]):
        min_ind = np.max(good_sets_prev[i, :])
        # Find all possible combinations of QoIs that include this set of n - 1
        if comm.rank == 0:
            inds_notin_set = util.fix_dimensions_vector_2darray(list(set(\
                unique_indices) - set(good_sets_prev[i, :])))

            # Choose only the QoI indices > min_ind so we do not repeat sets
            inds_notin_set = util.fix_dimensions_vector_2darray(inds_notin_set[\
                inds_notin_set > min_ind])
            qoi_combs = util.fix_dimensions_vector_2darray(np.append(np.tile(\
                good_sets_prev[i, :], [inds_notin_set.shape[0], 1]),
                inds_notin_set, axis=1))
            qoi_combs = np.array_split(qoi_combs, comm.size)
        else:
            qoi_combs = None

        # Scatter them throughout the processors
        qoi_combs = comm.scatter(qoi_combs, root=0)

        # For each combination, compute the average condition number and add the
        # set to good_sets if it is less than cond_tol
        for qoi_set in range(len(qoi_combs)):
            count_qois += 1
            curr_set = util.fix_dimensions_vector_2darray(qoi_combs[qoi_set])\
                .transpose()
            if volume == False:
                (current_condnum, singvals) = calculate_avg_condnum(grad_tensor,
                    qoi_combs[qoi_set])
            else:
                (current_condnum, singvals) = calculate_avg_volume(grad_tensor,
                    qoi_combs[qoi_set])

            # If its a good set, add it to good_sets
            if current_condnum < cond_tol:
                good_sets = np.append(good_sets, curr_set, axis=0)

                # If the average condition number is less than the max condition
                # number in our best_sets, add it to best_sets
                if current_condnum < best_sets[-1, 0]:
                    best_sets[-1, :] = np.append(np.array([current_condnum]),
                        qoi_combs[qoi_set])
                    order = best_sets[:, 0].argsort()
                    best_sets = best_sets[order]

                    # Store the corresponding singular values
                    optsingvals_tensor[:, :, -1] = singvals
                    optsingvals_tensor = optsingvals_tensor[:, :, order]

    # Wait for all processes to get to this point
    comm.Barrier()

    # Gather the best sets and condition numbers from each processor
    good_sets = comm.gather(good_sets, root=0)
    best_sets = np.array(comm.gather(best_sets, root=0))
    count_qois = np.array(comm.gather(count_qois, root=0))

    # Find the num_optsets_return smallest condition numbers from all processors
    if comm.rank == 0:

        # Organize the best sets
        best_sets = best_sets.reshape(num_optsets_return * \
            comm.size, num_qois_return + 1)
        [temp, uniq_inds_best] = np.unique(best_sets[:, 0], return_index=True)
        best_sets = best_sets[uniq_inds_best, :]
        best_sets = best_sets[best_sets[:, 0].argsort()]
        best_sets = best_sets[:num_optsets_return, :]

        # Organize the good sets
        good_sets_new = np.zeros([1, num_qois_return])
        for each in good_sets:
            good_sets_new = np.append(good_sets_new, each[1:], axis=0)
        good_sets = good_sets_new

        print 'Possible sets of QoIs of size %i : '%good_sets.shape[1],\
            np.sum(count_qois)
        print 'Good sets of QoIs of size %i : '%good_sets.shape[1],\
            good_sets.shape[0] - 1

    comm.Barrier()
    best_sets = comm.bcast(best_sets, root=0)
    good_sets = comm.bcast(good_sets, root=0)

    return (good_sets[1:].astype(int), best_sets, optsingvals_tensor)
Пример #12
0
def find_good_sets(input_set, good_sets_prev, unique_indices,
                   num_optsets_return, measskew_tol, measure):
    r"""

    .. todo::  Use the idea we only know vectors are with 10% accuracy to guide
        inner_prod tol and skewness_tol.

    Given gradient vectors at each center in the parameter space and given
    good sets of size (n - 1), return good sets of size n.  That is, return
    sets of size n that have average measure(skewness) less than some tolerance.

    :param input_set: The input sample set.  Make sure the attribute _jacobians
        is not None.
    :type input_set: :class:`~bet.sample.sample_set`
    :param good_sets_prev: Good sets of QoIs of size n - 1.
    :type good_sets_prev: :class:`np.ndarray` of size (num_good_sets_prev, n -
        1) 
    :param unique_indices: Unique QoIs to consider.
    :type unique_indices: :class:`np.ndarray` of size (num_unique_qois, 1)
    :param int num_optsets_return: Number of best sets to return
    :param float measskew_tol: Throw out all sets of QoIs with average
        measure(skewness) number greater than this.
    :param boolean measure: If measure is True, use ``calculate_avg_measure``
        to determine optimal QoIs, else use ``calculate_avg_skewness``

    :rtype: tuple
    :returns: (good_sets, best_sets, optsingvals_tensor) where good sets has
        size (num_good_sets, n), best sets has size (num_optsets_return,
        n + 1) and optsingvals_tensor has size (num_centers, n, input_dim)

    """

    if input_set._jacobians is None:
        raise ValueError("You must have jacobians to use this method.")

    num_centers = input_set._jacobians.shape[0]
    num_qois_return = good_sets_prev.shape[1] + 1
    comm.Barrier()

    # Initialize best sets and set all skewness values large
    best_sets = np.zeros([num_optsets_return, num_qois_return + 1])
    best_sets[:, 0] = np.inf
    good_sets = np.zeros([1, num_qois_return])
    count_qois = 0
    optsingvals_tensor = np.zeros([num_centers, num_qois_return,
                                   num_optsets_return])

    # For each good set of size (n - 1), find the possible sets of size n and
    # compute the average skewness of each
    count_qois = 0
    for i in range(good_sets_prev.shape[0]):
        min_ind = np.max(good_sets_prev[i, :])
        # Find all possible combinations of QoIs that include this set of
        # (n - 1)
        if comm.rank == 0:
            inds_notin_set = util.fix_dimensions_vector_2darray(list(set(
                unique_indices) - set(good_sets_prev[i, :])))

            # Choose only the QoI indices > min_ind so we do not repeat sets
            inds_notin_set = util.fix_dimensions_vector_2darray(inds_notin_set[
                inds_notin_set > min_ind])
            qoi_combs = util.fix_dimensions_vector_2darray(np.append(np.tile(
                good_sets_prev[i, :], [inds_notin_set.shape[0], 1]),
                inds_notin_set, axis=1))
            qoi_combs = np.array_split(qoi_combs, comm.size)
        else:
            qoi_combs = None

        # Scatter them throughout the processors
        qoi_combs = comm.scatter(qoi_combs, root=0)

        # For each combination, compute the average measure(skewness) and add
        # the set to good_sets if it is less than measskew_tol
        for qoi_set in range(len(qoi_combs)):
            count_qois += 1
            curr_set = util.fix_dimensions_vector_2darray(qoi_combs[qoi_set])\
                .transpose()
            if measure is False:
                (current_measskew, singvals) = calculate_avg_skewness(input_set,
                                                                      qoi_combs[qoi_set])
            else:
                (current_measskew, singvals) = calculate_avg_measure(input_set,
                                                                     qoi_combs[qoi_set])

            # If its a good set, add it to good_sets
            if current_measskew < measskew_tol:
                good_sets = np.append(good_sets, curr_set, axis=0)

                # If the average skewness is less than the maxskewness
                # in our best_sets, add it to best_sets
                if current_measskew < best_sets[-1, 0]:
                    best_sets[-1, :] = np.append(np.array([current_measskew]),
                                                 qoi_combs[qoi_set])
                    order = best_sets[:, 0].argsort()
                    best_sets = best_sets[order]

                    # Store the corresponding singular values
                    optsingvals_tensor[:, :, -1] = singvals
                    optsingvals_tensor = optsingvals_tensor[:, :, order]

    # Wait for all processes to get to this point
    comm.Barrier()

    # Gather the best sets and skewness values from each processor
    good_sets = comm.gather(good_sets, root=0)
    best_sets = np.array(comm.gather(best_sets, root=0))
    count_qois = np.array(comm.gather(count_qois, root=0))

    # Find the num_optsets_return smallest skewness from all processors
    if comm.rank == 0:

        # Organize the best sets
        best_sets = best_sets.reshape(num_optsets_return *
                                      comm.size, num_qois_return + 1)
        [_, uniq_inds_best] = np.unique(best_sets[:, 0], return_index=True)
        best_sets = best_sets[uniq_inds_best, :]
        best_sets = best_sets[best_sets[:, 0].argsort()]
        best_sets = best_sets[:num_optsets_return, :]

        # Organize the good sets
        good_sets_new = np.zeros([1, num_qois_return])
        for each in good_sets:
            good_sets_new = np.append(good_sets_new, each[1:], axis=0)
        good_sets = good_sets_new

        logging.info('Possible sets of QoIs of size {} : {}'.format(
            good_sets.shape[1], np.sum(count_qois)))
        logging.info('Good sets of QoIs of size {} : {}'.format(
            good_sets.shape[1], good_sets.shape[0] - 1))

    comm.Barrier()
    best_sets = comm.bcast(best_sets, root=0)
    good_sets = comm.bcast(good_sets, root=0)

    return (good_sets[1:].astype(int), best_sets, optsingvals_tensor)
Пример #13
0
def chooseOptQoIs_large_verbose(input_set, qoiIndices=None,
                                max_qois_return=None, num_optsets_return=None, inner_prod_tol=None,
                                measskew_tol=None, measure=False, remove_zeros=True):
    r"""
    Given gradient vectors at some points (centers) in the parameter space, a
    large set of QoIs to choose from, and the number of desired QoIs to return,
    this method return the set of optimal QoIs of size 1, 2, ... max_qois_return
    to use in the inverse problem by choosing the set with smallext average
    skewness.  Also a tensor that represents the singular values of the
    matrices formed by the gradient vectors of the optimal QoIs at each center
    is returned.

    :param input_set: The input sample set.  Make sure the attribute _jacobians
        is not None.
    :type input_set: :class:`~bet.sample.sample_set`
    :param qoiIndices: Set of QoIs to consider from G.  Default is
        xrange(0, G.shape[1]).
    :type qoiIndices: :class:`np.ndarray` of size (1, num QoIs to consider)
    :param int max_qois_return: Maximum number of desired QoIs to use in the
        inverse problem.  Default is input_dim.
    :param int num_optsets_return: Number of best sets to return.  Default is
        10.  
    :param float inner_prod_tol: Throw out one vectors from each pair of
        QoIs that has average inner product greater than this.  Default is 0.9.
    :param float measskew_tol: Throw out all sets of QoIs with average
        measure(skewness) number greater than this.  Default is max_float.
    :param boolean measure: If measure is True, use ``calculate_avg_measure``
        to determine optimal QoIs, else use ``calculate_avg_skewness``
    :param boolean remove_zeros: If True, ``find_unique_vecs`` will remove any
        QoIs that have a zero gradient vector at atleast one point in
        :math:`\Lambda`.

    :rtype: tuple
    :returns: (measure_skewness_indices_mat, optsingvals) where
        measure_skewness_indices_mat has shape (num_optsets_return,
        num_qois_return+1) and optsingvals is a list where each element has
        shape (num_centers, num_qois_return, num_optsets_return).
        num_qois_return will change for each element of the list.

    """
    input_dim = input_set._dim
    if input_set._jacobians is None:
        raise ValueError("You must have jacobians to use this method.")
    if qoiIndices is None:
        qoiIndices = range(0, input_set._jacobians.shape[1])
    if max_qois_return is None:
        max_qois_return = input_dim
    if num_optsets_return is None:
        num_optsets_return = 10
    if inner_prod_tol is None:
        inner_prod_tol = 1.0
    if measskew_tol is None:
        measskew_tol = np.inf

    # Find the unique QoIs to consider
    unique_indices = find_unique_vecs(input_set, inner_prod_tol, qoiIndices,
                                      remove_zeros)
    if comm.rank == 0:
        logging.info('Unique Indices are : {}'.format(unique_indices))

    good_sets_curr = util.fix_dimensions_vector_2darray(unique_indices)
    best_sets = []
    optsingvals_list = []

    # Given good sets of QoIs of size (n - 1), find the good sets of size n
    for qois_return in range(2, max_qois_return + 1):
        (good_sets_curr, best_sets_curr, optsingvals_tensor_curr) = \
            find_good_sets(input_set, good_sets_curr, unique_indices,
                           num_optsets_return, measskew_tol, measure)
        best_sets.append(best_sets_curr)
        optsingvals_list.append(optsingvals_tensor_curr)
        if comm.rank == 0:
            logging.info(best_sets_curr)

    return (best_sets, optsingvals_list)
Пример #14
0
def chooseOptQoIs_large_verbose(grad_tensor,
                                qoiIndices=None,
                                max_qois_return=None,
                                num_optsets_return=None,
                                inner_prod_tol=None,
                                cond_tol=None,
                                volume=False,
                                remove_zeros=True):
    r"""
    Given gradient vectors at some points (centers) in the parameter space, a
    large set of QoIs to choose from, and the number of desired QoIs to return,
    this method return the set of optimal QoIs of size 1, 2, ... max_qois_return
    to use in the inverse problem by choosing the set with smallext average
    condition number.  Also a tensor that represents the singular values of the
    matrices formed by the gradient vectors of the optimal QoIs at each center
    is returned.
    :param grad_tensor: Gradient vectors at each point of interest in the
        parameter space :math:`\Lambda` for each QoI map.
    :type grad_tensor: :class:`np.ndarray` of shape (num_centers, num_qois,
        Lambda_dim) where num_centers is the number of points in :math:`\Lambda`
        we have approximated the gradient vectors and num_qois is the total
        number of possible QoIs to choose from.
    :param qoiIndices: Set of QoIs to consider from grad_tensor.  Default is
        range(0, grad_tensor.shape[1]).
    :type qoiIndices: :class:`np.ndarray` of size (1, num QoIs to consider)
    :param int max_qois_return: Maximum number of desired QoIs to use in the
        inverse problem.  Default is Lambda_dim.
    :param int num_optsets_return: Number of best sets to return.  Default is 10.
    :param float inner_prod_tol: Throw out one vectors from each pair of QoIs
        that has average inner product greater than this.  Default is 0.9.
    :param float cond_tol: Throw out all sets of QoIs with average condition
        number greater than this.  Default is max_float.
    :param boolean volume: If volume is True, use ``calculate_avg_volume``
        to determine optimal QoIs
    :param boolean remove_zeros: If True, ``find_unique_vecs`` will remove any
        QoIs that have a zero gradient vector at atleast one point in
        :math:`\Lambda`.
    :rtype: tuple
    :returns: (condnum_indices_mat, optsingvals) where condnum_indices_mat has
        shape (num_optsets_return, num_qois_return+1) and optsingvals is a list
        where each element has shape (num_centers, num_qois_return,
        num_optsets_return).  num_qois_return will change for each element of
        the list.
    """
    num_centers = grad_tensor.shape[0]
    Lambda_dim = grad_tensor.shape[2]
    if qoiIndices is None:
        qoiIndices = range(0, grad_tensor.shape[1])
    if max_qois_return is None:
        max_qois_return = Lambda_dim
    if num_optsets_return is None:
        num_optsets_return = 10
    if inner_prod_tol is None:
        inner_prod_tol = 1.0
    if cond_tol is None:
        cond_tol = np.inf

    # Find the unique QoIs to consider
    unique_indices = find_unique_vecs(grad_tensor, inner_prod_tol, qoiIndices,
                                      remove_zeros)
    if comm.rank == 0:
        print 'Unique Indices are : ', unique_indices

    good_sets_curr = util.fix_dimensions_vector_2darray(unique_indices)
    best_sets = []
    optsingvals_list = []

    # Given good sets of QoIs of size n - 1, find the good sets of size n
    for qois_return in range(2, max_qois_return + 1):
        (good_sets_curr, best_sets_curr, optsingvals_tensor_curr) = \
            find_good_sets(grad_tensor, good_sets_curr, unique_indices,
            num_optsets_return, cond_tol, volume)
        best_sets.append(best_sets_curr)
        optsingvals_list.append(optsingvals_tensor_curr)
        if comm.rank == 0:
            print best_sets_curr

    return (best_sets, optsingvals_list)
Пример #15
0
def find_good_sets(grad_tensor, good_sets_prev, unique_indices,
                   num_optsets_return, cond_tol, volume):
    r"""
    #TODO:  Use the idea we only know vectors are with 10% accuracy to guide
        inner_prod tol and condnum_tol.
    Given gradient vectors at each center in the parameter space and given
    good sets of size n - 1, return good sets of size n.  That is, return
    sets of size n that have average condition number less than some tolerance.
    :param grad_tensor: Gradient vectors at each centers in the parameter
        space :math:'\Lambda' for each QoI map.
    :type grad_tensor: :class:`np.ndarray` of shape (num_centers,num_qois,Ldim)
        where num_centers is the number of points in :math:'\Lambda' we have
        approximated the gradient vectors, num_qois is the total number of
        possible QoIs to choose from, Ldim is the dimension of :math:`\Lambda`.
    :param good_sets_prev: Good sets of QoIs of size n - 1.
    :type good_sets_prev: :class:`np.ndarray` of size (num_good_sets_prev, n - 1)
    :param unique_indices: Unique QoIs to consider.
    :type unique_indices: :class:'np.ndarray' of size (num_unique_qois, 1)
    :param int num_optsets_return: Number of best sets to return
    :param float cond_tol: Throw out all sets of QoIs with average condition
        number greater than this.
    :param boolean volume: If volume is True, use ``calculate_avg_volume``
        to determine optimal QoIs
    :rtype: tuple
    :returns: (good_sets, best_sets, optsingvals_tensor) where good sets has
        size (num_good_sets, n), best sets has size (num_optsets_return,
        n + 1) and optsingvals_tensor has size (num_centers, n, Lambda_dim)
    """
    num_centers = grad_tensor.shape[0]
    Lambda_dim = grad_tensor.shape[2]
    num_qois_return = good_sets_prev.shape[1] + 1
    comm.Barrier()

    # Initialize best sets and set all condition numbers large
    best_sets = np.zeros([num_optsets_return, num_qois_return + 1])
    best_sets[:, 0] = np.inf
    good_sets = np.zeros([1, num_qois_return])
    count_qois = 0
    optsingvals_tensor = np.zeros(
        [num_centers, num_qois_return, num_optsets_return])

    # For each good set of size n - 1, find the possible sets of size n and
    # compute the average condition number of each
    count_qois = 0
    for i in range(good_sets_prev.shape[0]):
        min_ind = np.max(good_sets_prev[i, :])
        # Find all possible combinations of QoIs that include this set of n - 1
        if comm.rank == 0:
            inds_notin_set = util.fix_dimensions_vector_2darray(list(set(\
                unique_indices) - set(good_sets_prev[i, :])))

            # Choose only the QoI indices > min_ind so we do not repeat sets
            inds_notin_set = util.fix_dimensions_vector_2darray(inds_notin_set[\
                inds_notin_set > min_ind])
            qoi_combs = util.fix_dimensions_vector_2darray(np.append(np.tile(\
                good_sets_prev[i, :], [inds_notin_set.shape[0], 1]),
                inds_notin_set, axis=1))
            qoi_combs = np.array_split(qoi_combs, comm.size)
        else:
            qoi_combs = None

        # Scatter them throughout the processors
        qoi_combs = comm.scatter(qoi_combs, root=0)

        # For each combination, compute the average condition number and add the
        # set to good_sets if it is less than cond_tol
        for qoi_set in range(len(qoi_combs)):
            count_qois += 1
            curr_set = util.fix_dimensions_vector_2darray(qoi_combs[qoi_set])\
                .transpose()
            if volume == False:
                (current_condnum,
                 singvals) = calculate_avg_condnum(grad_tensor,
                                                   qoi_combs[qoi_set])
            else:
                (current_condnum,
                 singvals) = calculate_avg_volume(grad_tensor,
                                                  qoi_combs[qoi_set])

            # If its a good set, add it to good_sets
            if current_condnum < cond_tol:
                good_sets = np.append(good_sets, curr_set, axis=0)

                # If the average condition number is less than the max condition
                # number in our best_sets, add it to best_sets
                if current_condnum < best_sets[-1, 0]:
                    best_sets[-1, :] = np.append(np.array([current_condnum]),
                                                 qoi_combs[qoi_set])
                    order = best_sets[:, 0].argsort()
                    best_sets = best_sets[order]

                    # Store the corresponding singular values
                    optsingvals_tensor[:, :, -1] = singvals
                    optsingvals_tensor = optsingvals_tensor[:, :, order]

    # Wait for all processes to get to this point
    comm.Barrier()

    # Gather the best sets and condition numbers from each processor
    good_sets = comm.gather(good_sets, root=0)
    best_sets = np.array(comm.gather(best_sets, root=0))
    count_qois = np.array(comm.gather(count_qois, root=0))

    # Find the num_optsets_return smallest condition numbers from all processors
    if comm.rank == 0:

        # Organize the best sets
        best_sets = best_sets.reshape(num_optsets_return * \
            comm.size, num_qois_return + 1)
        [temp, uniq_inds_best] = np.unique(best_sets[:, 0], return_index=True)
        best_sets = best_sets[uniq_inds_best, :]
        best_sets = best_sets[best_sets[:, 0].argsort()]
        best_sets = best_sets[:num_optsets_return, :]

        # Organize the good sets
        good_sets_new = np.zeros([1, num_qois_return])
        for each in good_sets:
            good_sets_new = np.append(good_sets_new, each[1:], axis=0)
        good_sets = good_sets_new

        print 'Possible sets of QoIs of size %i : '%good_sets.shape[1],\
            np.sum(count_qois)
        print 'Good sets of QoIs of size %i : '%good_sets.shape[1],\
            good_sets.shape[0] - 1

    comm.Barrier()
    best_sets = comm.bcast(best_sets, root=0)
    good_sets = comm.bcast(good_sets, root=0)

    return (good_sets[1:].astype(int), best_sets, optsingvals_tensor)
Пример #16
0
def chooseOptQoIs_large_verbose(input_set,
                                qoiIndices=None,
                                max_qois_return=None,
                                num_optsets_return=None,
                                inner_prod_tol=None,
                                measskew_tol=None,
                                measure=False,
                                remove_zeros=True):
    r"""
    Given gradient vectors at some points (centers) in the parameter space, a
    large set of QoIs to choose from, and the number of desired QoIs to return,
    this method return the set of optimal QoIs of size 1, 2, ... max_qois_return
    to use in the inverse problem by choosing the set with smallext average
    skewness.  Also a tensor that represents the singular values of the
    matrices formed by the gradient vectors of the optimal QoIs at each center
    is returned.
    
    :param input_set: The input sample set.  Make sure the attribute _jacobians
        is not None.
    :type input_set: :class:`~bet.sample.sample_set`
    :param qoiIndices: Set of QoIs to consider from G.  Default is
        xrange(0, G.shape[1]).
    :type qoiIndices: :class:`np.ndarray` of size (1, num QoIs to consider)
    :param int max_qois_return: Maximum number of desired QoIs to use in the
        inverse problem.  Default is input_dim.
    :param int num_optsets_return: Number of best sets to return.  Default is
        10.  
    :param float inner_prod_tol: Throw out one vectors from each pair of
        QoIs that has average inner product greater than this.  Default is 0.9.
    :param float measskew_tol: Throw out all sets of QoIs with average
        measure(skewness) number greater than this.  Default is max_float.
    :param boolean measure: If measure is True, use ``calculate_avg_measure``
        to determine optimal QoIs, else use ``calculate_avg_skewness``
    :param boolean remove_zeros: If True, ``find_unique_vecs`` will remove any
        QoIs that have a zero gradient vector at atleast one point in
        :math:`\Lambda`.
    
    :rtype: tuple
    :returns: (measure_skewness_indices_mat, optsingvals) where
        measure_skewness_indices_mat has shape (num_optsets_return,
        num_qois_return+1) and optsingvals is a list where each element has
        shape (num_centers, num_qois_return, num_optsets_return).
        num_qois_return will change for each element of the list.
    
    """
    input_dim = input_set._dim
    if input_set._jacobians is None:
        raise ValueError("You must have jacobians to use this method.")
    if qoiIndices is None:
        qoiIndices = xrange(0, input_set._jacobians.shape[1])
    if max_qois_return is None:
        max_qois_return = input_dim
    if num_optsets_return is None:
        num_optsets_return = 10
    if inner_prod_tol is None:
        inner_prod_tol = 1.0
    if measskew_tol is None:
        measskew_tol = np.inf

    # Find the unique QoIs to consider
    unique_indices = find_unique_vecs(input_set, inner_prod_tol, qoiIndices,
                                      remove_zeros)
    if comm.rank == 0:
        logging.info('Unique Indices are : {}'.format(unique_indices))

    good_sets_curr = util.fix_dimensions_vector_2darray(unique_indices)
    best_sets = []
    optsingvals_list = []

    # Given good sets of QoIs of size (n - 1), find the good sets of size n
    for qois_return in xrange(2, max_qois_return + 1):
        (good_sets_curr, best_sets_curr, optsingvals_tensor_curr) = \
            find_good_sets(input_set, good_sets_curr, unique_indices,
            num_optsets_return, measskew_tol, measure)
        best_sets.append(best_sets_curr)
        optsingvals_list.append(optsingvals_tensor_curr)
        if comm.rank == 0:
            logging.info(best_sets_curr)

    return (best_sets, optsingvals_list)
Пример #17
0
def find_good_sets(input_set, good_sets_prev, unique_indices,
                   num_optsets_return, measskew_tol, measure):
    r"""

    .. todo::  Use the idea we only know vectors are with 10% accuracy to guide
        inner_prod tol and skewness_tol.
    
    Given gradient vectors at each center in the parameter space and given
    good sets of size (n - 1), return good sets of size n.  That is, return
    sets of size n that have average measure(skewness) less than some tolerance.
    
    :param input_set: The input sample set.  Make sure the attribute _jacobians
        is not None.
    :type input_set: :class:`~bet.sample.sample_set`
    :param good_sets_prev: Good sets of QoIs of size n - 1.
    :type good_sets_prev: :class:`np.ndarray` of size (num_good_sets_prev, n -
        1) 
    :param unique_indices: Unique QoIs to consider.
    :type unique_indices: :class:`np.ndarray` of size (num_unique_qois, 1)
    :param int num_optsets_return: Number of best sets to return
    :param float measskew_tol: Throw out all sets of QoIs with average
        measure(skewness) number greater than this.
    :param boolean measure: If measure is True, use ``calculate_avg_measure``
        to determine optimal QoIs, else use ``calculate_avg_skewness``
    
    :rtype: tuple
    :returns: (good_sets, best_sets, optsingvals_tensor) where good sets has
        size (num_good_sets, n), best sets has size (num_optsets_return,
        n + 1) and optsingvals_tensor has size (num_centers, n, input_dim)
    
    """

    if input_set._jacobians is None:
        raise ValueError("You must have jacobians to use this method.")

    num_centers = input_set._jacobians.shape[0]
    num_qois_return = good_sets_prev.shape[1] + 1
    comm.Barrier()

    # Initialize best sets and set all skewness values large
    best_sets = np.zeros([num_optsets_return, num_qois_return + 1])
    best_sets[:, 0] = np.inf
    good_sets = np.zeros([1, num_qois_return])
    count_qois = 0
    optsingvals_tensor = np.zeros(
        [num_centers, num_qois_return, num_optsets_return])

    # For each good set of size (n - 1), find the possible sets of size n and
    # compute the average skewness of each
    count_qois = 0
    for i in xrange(good_sets_prev.shape[0]):
        min_ind = np.max(good_sets_prev[i, :])
        # Find all possible combinations of QoIs that include this set of
        # (n - 1)
        if comm.rank == 0:
            inds_notin_set = util.fix_dimensions_vector_2darray(list(set(\
                unique_indices) - set(good_sets_prev[i, :])))

            # Choose only the QoI indices > min_ind so we do not repeat sets
            inds_notin_set = util.fix_dimensions_vector_2darray(inds_notin_set[\
                inds_notin_set > min_ind])
            qoi_combs = util.fix_dimensions_vector_2darray(np.append(np.tile(\
                good_sets_prev[i, :], [inds_notin_set.shape[0], 1]),
                inds_notin_set, axis=1))
            qoi_combs = np.array_split(qoi_combs, comm.size)
        else:
            qoi_combs = None

        # Scatter them throughout the processors
        qoi_combs = comm.scatter(qoi_combs, root=0)

        # For each combination, compute the average measure(skewness) and add
        # the set to good_sets if it is less than measskew_tol
        for qoi_set in xrange(len(qoi_combs)):
            count_qois += 1
            curr_set = util.fix_dimensions_vector_2darray(qoi_combs[qoi_set])\
                .transpose()
            if measure is False:
                (current_measskew,
                 singvals) = calculate_avg_skewness(input_set,
                                                    qoi_combs[qoi_set])
            else:
                (current_measskew,
                 singvals) = calculate_avg_measure(input_set,
                                                   qoi_combs[qoi_set])

            # If its a good set, add it to good_sets
            if current_measskew < measskew_tol:
                good_sets = np.append(good_sets, curr_set, axis=0)

                # If the average skewness is less than the maxskewness
                # in our best_sets, add it to best_sets
                if current_measskew < best_sets[-1, 0]:
                    best_sets[-1, :] = np.append(np.array([current_measskew]),
                                                 qoi_combs[qoi_set])
                    order = best_sets[:, 0].argsort()
                    best_sets = best_sets[order]

                    # Store the corresponding singular values
                    optsingvals_tensor[:, :, -1] = singvals
                    optsingvals_tensor = optsingvals_tensor[:, :, order]

    # Wait for all processes to get to this point
    comm.Barrier()

    # Gather the best sets and skewness values from each processor
    good_sets = comm.gather(good_sets, root=0)
    best_sets = np.array(comm.gather(best_sets, root=0))
    count_qois = np.array(comm.gather(count_qois, root=0))

    # Find the num_optsets_return smallest skewness from all processors
    if comm.rank == 0:

        # Organize the best sets
        best_sets = best_sets.reshape(num_optsets_return * \
            comm.size, num_qois_return + 1)
        [_, uniq_inds_best] = np.unique(best_sets[:, 0], return_index=True)
        best_sets = best_sets[uniq_inds_best, :]
        best_sets = best_sets[best_sets[:, 0].argsort()]
        best_sets = best_sets[:num_optsets_return, :]

        # Organize the good sets
        good_sets_new = np.zeros([1, num_qois_return])
        for each in good_sets:
            good_sets_new = np.append(good_sets_new, each[1:], axis=0)
        good_sets = good_sets_new

        logging.info('Possible sets of QoIs of size {} : {}'.format(\
                good_sets.shape[1], np.sum(count_qois)))
        logging.info('Good sets of QoIs of size {} : {}'.format(\
                good_sets.shape[1], good_sets.shape[0] - 1))

    comm.Barrier()
    best_sets = comm.bcast(best_sets, root=0)
    good_sets = comm.bcast(good_sets, root=0)

    return (good_sets[1:].astype(int), best_sets, optsingvals_tensor)
Пример #18
0
def calculate_gradients_cfd(cluster_discretization, normalize=True):
    """
    Approximate gradient vectors at ``num_centers, centers.shape[0]`` points
    in the parameter space for each QoI map.  THIS METHOD IS DEPENDENT
    ON USING :meth:~bet.sensitivity.pick_cfd_points TO CHOOSE SAMPLES FOR THE 
    CFD STENCIL AROUND EACH CENTER.  THE ORDERING MATTERS.
    
    :param cluster_discretization: Must contain input and output values for the
        sample clusters.
    :type cluster_discretization: :class:`~bet.sample.discretization`
    :param boolean normalize:  If normalize is True, normalize each gradient
        vector
    
    :rtype: :class:`~bet.sample.discretization`
    :returns: A new :class:`~bet.sample.discretization` that contains only the
        centers of the clusters and their associated ``_jacobians`` which are
        tensor representation of the gradient vectors of each QoI map at each
        point in centers :class:`numpy.ndarray` of shape (num_samples,
        output_dim, input_dim)
    
    """
    if cluster_discretization._input_sample_set.get_values() is None \
            or cluster_discretization._output_sample_set.get_values() is None:
        raise ValueError("You must have values to use this method.")
    samples = cluster_discretization._input_sample_set.get_values()
    data = cluster_discretization._output_sample_set.get_values()

    input_dim = cluster_discretization._input_sample_set.get_dim()
    num_model_samples = cluster_discretization.check_nums()
    output_dim = cluster_discretization._output_sample_set.get_dim()

    num_model_samples = cluster_discretization.check_nums()
    input_dim = cluster_discretization._input_sample_set.get_dim()

    num_centers = num_model_samples / (2 * input_dim + 1)

    # Find radii_vec from the first cluster of samples
    radii_vec = samples[num_centers:num_centers + input_dim, :] - samples[0, :]
    radii_vec = util.fix_dimensions_vector_2darray(radii_vec.diagonal())

    # Clean the data
    data = util.clean_data(data[num_centers:])
    gradient_tensor = np.zeros([num_centers, output_dim, input_dim])

    radii_vec = np.tile(np.repeat(radii_vec, output_dim, axis=1),
                        [num_centers, 1])

    # Construct indices for CFD gradient approxiation
    inds = np.repeat(range(0, 2 * input_dim * num_centers, 2 * input_dim),
                     input_dim) + np.tile(range(0, input_dim), num_centers)
    inds = np.array([inds, inds + input_dim]).transpose()

    gradient_mat = (data[inds[:, 0]] - data[inds[:, 1]]) * (0.5 / radii_vec)

    # Reshape and organize
    gradient_tensor = np.reshape(gradient_mat.transpose(),
                                 [output_dim, input_dim, num_centers],
                                 order='F').transpose(2, 0, 1)

    if normalize:
        # Compute the norm of each vector
        norm_gradient_tensor = np.linalg.norm(gradient_tensor, ord=1, axis=2)

        # If it is a zero vector (has 0 norm), set norm=1, avoid divide by zero
        norm_gradient_tensor[norm_gradient_tensor == 0] = 1.0

        # Normalize each gradient vector
        gradient_tensor = gradient_tensor / np.tile(
            norm_gradient_tensor, (input_dim, 1, 1)).transpose(1, 2, 0)

    center_input_sample_set = sample.sample_set(input_dim)
    center_input_sample_set.set_values(samples[:num_centers, :])
    if cluster_discretization._input_sample_set.get_domain() is not None:
        center_input_sample_set.set_domain(cluster_discretization.\
                _input_sample_set.get_domain())
    center_input_sample_set.set_jacobians(gradient_tensor)
    center_output_sample_set = sample.sample_set(output_dim)
    center_output_sample_set.set_values(data[:num_centers, :])
    if cluster_discretization._output_sample_set.get_domain() is not None:
        center_output_sample_set.set_domain(cluster_discretization.\
                _output_sample_set.get_domain())
    #center_output_sample_set.set_jacobians(gradient_tensor.transpose())
    center_discretization = sample.discretization(center_input_sample_set,
                                                  center_output_sample_set)
    return center_discretization
Пример #19
0
def calculate_gradients_rbf(samples, data, centers=None, num_neighbors=None,
        RBF=None, ep=None, normalize=True):
    r"""
    Approximate gradient vectors at ``num_centers, centers.shape[0]`` points
    in the parameter space for each QoI map using a radial basis function
    interpolation method.
    :param samples: Samples for which the model has been solved.
    :type samples: :class:`np.ndarray` of shape (num_samples, Lambda_dim)
    :param data: QoI values corresponding to each sample.
    :type data: :class:`np.ndarray` of shape (num_samples, Data_dim)
    :param centers: Points in :math:`\Lambda` at which to approximate gradient
        information.
    :type centers: :class:`np.ndarray` of shape (num_exval, Lambda_dim)
    :param int num_neighbors: Number of nearest neighbors to use in gradient
        approximation. Default value is Lambda_dim + 2.
    :param string RBF: Choice of radial basis function. Default is Gaussian
    :param float ep: Choice of shape parameter for radial basis function.
        Default value is 1.0
    :param boolean normalize:  If normailze is True, normalize each gradient
        vector
    :rtype: :class:`np.ndarray` of shape (num_samples, Data_dim, Lambda_dim)
    :returns: Tensor representation of the gradient vectors of each
        QoI map at each point in centers
    """
    data = util.fix_dimensions_vector_2darray(util.clean_data(data))
    Lambda_dim = samples.shape[1]
    num_model_samples = samples.shape[0]
    Data_dim = data.shape[1]

    if num_neighbors is None:
        num_neighbors = Lambda_dim + 2
    if ep is None:
        ep = 1.0
    if RBF is None:
        RBF = 'Gaussian'

    # If centers is None we assume the user chose clusters of size
    # Lambda_dim + 2
    if centers is None:
        num_centers = num_model_samples / (Lambda_dim + 2)
        centers = samples[:num_centers]
    else:
        num_centers = centers.shape[0]

    rbf_tensor = np.zeros([num_centers, num_model_samples, Lambda_dim])
    gradient_tensor = np.zeros([num_centers, Data_dim, Lambda_dim])
    tree = spatial.KDTree(samples)

    # For each centers, interpolate the data using the rbf chosen and
    # then evaluate the partial derivative of that rbf at the desired point.
    for c in range(num_centers):
        # Find the k nearest neighbors and their distances to centers[c,:]
        [r, nearest] = tree.query(centers[c, :], k=num_neighbors)
        r = np.tile(r, (Lambda_dim, 1))

        # Compute the linf distances to each of the nearest neighbors
        diffVec = (centers[c, :] - samples[nearest, :]).transpose()

        # Compute the l2 distances between pairs of nearest neighbors
        distMat = spatial.distance_matrix(
            samples[nearest, :], samples[nearest, :])

        # Solve for the rbf weights using interpolation conditions and
        # evaluate the partial derivatives
        rbf_mat_values = \
            np.linalg.solve(radial_basis_function(distMat, RBF),
            radial_basis_function_dxi(r, diffVec, RBF, ep) \
            .transpose()).transpose()

        # Construct the finite difference matrices
        rbf_tensor[c, nearest, :] = rbf_mat_values.transpose()

    gradient_tensor = rbf_tensor.transpose(2, 0, 1).dot(data).transpose(1, 2, 0)

    if normalize:
        # Compute the norm of each vector
        norm_gradient_tensor = np.linalg.norm(gradient_tensor, ord=1, axis=2)

        # If it is a zero vector (has 0 norm), set norm=1, avoid divide by zero
        norm_gradient_tensor[norm_gradient_tensor == 0] = 1.0

        # Normalize each gradient vector
        gradient_tensor = gradient_tensor/np.tile(norm_gradient_tensor,
            (Lambda_dim, 1, 1)).transpose(1, 2, 0)

    return gradient_tensor
Пример #20
0
def calculate_gradients_cfd(cluster_discretization, normalize=True):
    """
    Approximate gradient vectors at ``num_centers, centers.shape[0]`` points
    in the parameter space for each QoI map.  THIS METHOD IS DEPENDENT
    ON USING :meth:~bet.sensitivity.pick_cfd_points TO CHOOSE SAMPLES FOR THE 
    CFD STENCIL AROUND EACH CENTER.  THE ORDERING MATTERS.
    
    :param cluster_discretization: Must contain input and output values for the
        sample clusters.
    :type cluster_discretization: :class:`~bet.sample.discretization`
    :param boolean normalize:  If normalize is True, normalize each gradient
        vector
    
    :rtype: :class:`~bet.sample.discretization`
    :returns: A new :class:`~bet.sample.discretization` that contains only the
        centers of the clusters and their associated ``_jacobians`` which are
        tensor representation of the gradient vectors of each QoI map at each
        point in centers :class:`numpy.ndarray` of shape (num_samples,
        output_dim, input_dim)
    
    """
    if cluster_discretization._input_sample_set.get_values() is None \
            or cluster_discretization._output_sample_set.get_values() is None:
        raise ValueError("You must have values to use this method.")
    samples = cluster_discretization._input_sample_set.get_values()
    data = cluster_discretization._output_sample_set.get_values()

    input_dim = cluster_discretization._input_sample_set.get_dim()
    num_model_samples = cluster_discretization.check_nums()
    output_dim = cluster_discretization._output_sample_set.get_dim()

    num_model_samples = cluster_discretization.check_nums()
    input_dim = cluster_discretization._input_sample_set.get_dim()

    num_centers = num_model_samples / (2*input_dim + 1)

    # Find radii_vec from the first cluster of samples
    radii_vec = samples[num_centers:num_centers + input_dim, :] - samples[0, :]
    radii_vec = util.fix_dimensions_vector_2darray(radii_vec.diagonal())

    # Clean the data
    data = util.clean_data(data[num_centers:])
    gradient_tensor = np.zeros([num_centers, output_dim, input_dim])

    radii_vec = np.tile(np.repeat(radii_vec, output_dim, axis=1), [num_centers,
        1])

    # Construct indices for CFD gradient approxiation
    inds = np.repeat(range(0, 2 * input_dim * num_centers, 2 * input_dim),
        input_dim) + np.tile(range(0, input_dim), num_centers)
    inds = np.array([inds, inds+input_dim]).transpose()

    gradient_mat = (data[inds[:, 0]] - data[inds[:, 1]]) * (0.5 / radii_vec)

    # Reshape and organize
    gradient_tensor = np.reshape(gradient_mat.transpose(), [output_dim,
        input_dim, num_centers], order='F').transpose(2, 0, 1)

    if normalize:
        # Compute the norm of each vector
        norm_gradient_tensor = np.linalg.norm(gradient_tensor, ord=1, axis=2)

        # If it is a zero vector (has 0 norm), set norm=1, avoid divide by zero
        norm_gradient_tensor[norm_gradient_tensor == 0] = 1.0

        # Normalize each gradient vector
        gradient_tensor = gradient_tensor/np.tile(norm_gradient_tensor,
            (input_dim, 1, 1)).transpose(1, 2, 0)

    center_input_sample_set = sample.sample_set(input_dim)
    center_input_sample_set.set_values(samples[:num_centers, :])
    if cluster_discretization._input_sample_set.get_domain() is not None:
        center_input_sample_set.set_domain(cluster_discretization.\
                _input_sample_set.get_domain())
    center_input_sample_set.set_jacobians(gradient_tensor)
    center_output_sample_set = sample.sample_set(output_dim)
    center_output_sample_set.set_values(data[:num_centers, :])
    if cluster_discretization._output_sample_set.get_domain() is not None:
        center_output_sample_set.set_domain(cluster_discretization.\
                _output_sample_set.get_domain())
    #center_output_sample_set.set_jacobians(gradient_tensor.transpose())
    center_discretization = sample.discretization(center_input_sample_set,
            center_output_sample_set)
    return center_discretization
Пример #21
0
def chooseOptQoIs_large_verbose(grad_tensor, qoiIndices=None,
        max_qois_return=None, num_optsets_return=None, inner_prod_tol=None,
        cond_tol=None, volume=False, remove_zeros=True):
    r"""
    Given gradient vectors at some points (centers) in the parameter space, a
    large set of QoIs to choose from, and the number of desired QoIs to return,
    this method return the set of optimal QoIs of size 1, 2, ... max_qois_return
    to use in the inverse problem by choosing the set with smallext average
    condition number.  Also a tensor that represents the singular values of the
    matrices formed by the gradient vectors of the optimal QoIs at each center
    is returned.
    :param grad_tensor: Gradient vectors at each point of interest in the
        parameter space :math:`\Lambda` for each QoI map.
    :type grad_tensor: :class:`np.ndarray` of shape (num_centers, num_qois,
        Lambda_dim) where num_centers is the number of points in :math:`\Lambda`
        we have approximated the gradient vectors and num_qois is the total
        number of possible QoIs to choose from.
    :param qoiIndices: Set of QoIs to consider from grad_tensor.  Default is
        range(0, grad_tensor.shape[1]).
    :type qoiIndices: :class:`np.ndarray` of size (1, num QoIs to consider)
    :param int max_qois_return: Maximum number of desired QoIs to use in the
        inverse problem.  Default is Lambda_dim.
    :param int num_optsets_return: Number of best sets to return.  Default is 10.
    :param float inner_prod_tol: Throw out one vectors from each pair of QoIs
        that has average inner product greater than this.  Default is 0.9.
    :param float cond_tol: Throw out all sets of QoIs with average condition
        number greater than this.  Default is max_float.
    :param boolean volume: If volume is True, use ``calculate_avg_volume``
        to determine optimal QoIs
    :param boolean remove_zeros: If True, ``find_unique_vecs`` will remove any
        QoIs that have a zero gradient vector at atleast one point in
        :math:`\Lambda`.
    :rtype: tuple
    :returns: (condnum_indices_mat, optsingvals) where condnum_indices_mat has
        shape (num_optsets_return, num_qois_return+1) and optsingvals is a list
        where each element has shape (num_centers, num_qois_return,
        num_optsets_return).  num_qois_return will change for each element of
        the list.
    """
    num_centers = grad_tensor.shape[0]
    Lambda_dim = grad_tensor.shape[2]
    if qoiIndices is None:
        qoiIndices = range(0, grad_tensor.shape[1])
    if max_qois_return is None:
        max_qois_return = Lambda_dim
    if num_optsets_return is None:
        num_optsets_return = 10
    if inner_prod_tol is None:
        inner_prod_tol = 0.9
    if cond_tol is None:
        cond_tol = sys.float_info[0]

    # Find the unique QoIs to consider
    unique_indices = find_unique_vecs(grad_tensor, inner_prod_tol, qoiIndices,
        remove_zeros)
    if comm.rank == 0:
        print 'Unique Indices are : ', unique_indices

    good_sets_curr = util.fix_dimensions_vector_2darray(unique_indices)
    best_sets = []
    optsingvals_list = []

    # Given good sets of QoIs of size n - 1, find the good sets of size n
    for qois_return in range(2, max_qois_return + 1):
        (good_sets_curr, best_sets_curr, optsingvals_tensor_curr) = \
            find_good_sets(grad_tensor, good_sets_curr, unique_indices,
            num_optsets_return, cond_tol, volume)
        best_sets.append(best_sets_curr)
        optsingvals_list.append(optsingvals_tensor_curr)
        if comm.rank == 0:
            print best_sets_curr

    return (best_sets, optsingvals_list)
Пример #22
0
def calculate_gradients_rbf(samples, data, centers=None, num_neighbors=None,
        RBF=None, ep=None, normalize=True):
    r"""
    Approximate gradient vectors at ``num_centers, centers.shape[0]`` points
    in the parameter space for each QoI map using a radial basis function
    interpolation method.
    :param samples: Samples for which the model has been solved.
    :type samples: :class:`np.ndarray` of shape (num_samples, Lambda_dim)
    :param data: QoI values corresponding to each sample.
    :type data: :class:`np.ndarray` of shape (num_samples, Data_dim)
    :param centers: Points in :math:`\Lambda` at which to approximate gradient
        information.
    :type centers: :class:`np.ndarray` of shape (num_exval, Lambda_dim)
    :param int num_neighbors: Number of nearest neighbors to use in gradient
        approximation. Default value is Lambda_dim + 2.
    :param string RBF: Choice of radial basis function. Default is Gaussian
    :param float ep: Choice of shape parameter for radial basis function.
        Default value is 1.0
    :param boolean normalize:  If normalize is True, normalize each gradient
        vector
    :rtype: :class:`np.ndarray` of shape (num_samples, Data_dim, Lambda_dim)
    :returns: Tensor representation of the gradient vectors of each
        QoI map at each point in centers
    """
    data = util.fix_dimensions_vector_2darray(util.clean_data(data))
    Lambda_dim = samples.shape[1]
    num_model_samples = samples.shape[0]
    Data_dim = data.shape[1]

    if num_neighbors is None:
        num_neighbors = Lambda_dim + 2
    if ep is None:
        ep = 1.0
    if RBF is None:
        RBF = 'Gaussian'

    # If centers is None we assume the user chose clusters of size
    # Lambda_dim + 2
    if centers is None:
        num_centers = num_model_samples / (Lambda_dim + 2)
        centers = samples[:num_centers]
    else:
        num_centers = centers.shape[0]

    rbf_tensor = np.zeros([num_centers, num_model_samples, Lambda_dim])
    gradient_tensor = np.zeros([num_centers, Data_dim, Lambda_dim])
    tree = spatial.KDTree(samples)

    # For each centers, interpolate the data using the rbf chosen and
    # then evaluate the partial derivative of that rbf at the desired point.
    for c in range(num_centers):
        # Find the k nearest neighbors and their distances to centers[c,:]
        [r, nearest] = tree.query(centers[c, :], k=num_neighbors)
        r = np.tile(r, (Lambda_dim, 1))

        # Compute the linf distances to each of the nearest neighbors
        diffVec = (centers[c, :] - samples[nearest, :]).transpose()

        # Compute the l2 distances between pairs of nearest neighbors
        distMat = spatial.distance_matrix(
            samples[nearest, :], samples[nearest, :])

        # Solve for the rbf weights using interpolation conditions and
        # evaluate the partial derivatives
        rbf_mat_values = \
            np.linalg.solve(radial_basis_function(distMat, RBF),
            radial_basis_function_dxi(r, diffVec, RBF, ep) \
            .transpose()).transpose()

        # Construct the finite difference matrices
        rbf_tensor[c, nearest, :] = rbf_mat_values.transpose()

    gradient_tensor = rbf_tensor.transpose(2, 0, 1).dot(data).transpose(1, 2, 0)

    if normalize:
        # Compute the norm of each vector
        norm_gradient_tensor = np.linalg.norm(gradient_tensor, ord=1, axis=2)

        # If it is a zero vector (has 0 norm), set norm=1, avoid divide by zero
        norm_gradient_tensor[norm_gradient_tensor == 0] = 1.0

        # Normalize each gradient vector
        gradient_tensor = gradient_tensor/np.tile(norm_gradient_tensor,
            (Lambda_dim, 1, 1)).transpose(1, 2, 0)

    return gradient_tensor