def test_scalarQoI(self):
        systemsize = 3
        mu = np.random.rand(systemsize)
        std_dev = np.diag(np.random.rand(systemsize))
        jdist = cp.MvNormal(mu, std_dev)
        # Create QoI Object
        QoI = Paraboloid3D(systemsize)

        # Create the Monte Carlo object
        QoI_dict = {
            'paraboloid': {
                'QoI_func': QoI.eval_QoI,
                'output_dimensions': 1,
            }
        }
        nsample = 1000000
        mc_obj = MonteCarlo(nsample, jdist, QoI_dict)
        mc_obj.getSamples(jdist)
        # Get the mean and variance using Monte Carlo
        mu_js = mc_obj.mean(jdist, of=['paraboloid'])
        var_js = mc_obj.variance(jdist, of=['paraboloid'])

        # Analytical mean
        mu_j_analytical = QoI.eval_QoI_analyticalmean(mu, cp.Cov(jdist))
        err = abs((mu_js['paraboloid'] - mu_j_analytical) / mu_j_analytical)
        self.assertTrue(err < 1e-3)
        # Analytical variance
        var_j_analytical = QoI.eval_QoI_analyticalvariance(mu, cp.Cov(jdist))
        err = abs((var_js['paraboloid'] - var_j_analytical) / var_j_analytical)
        # print('var_js paraboloid = ', var_js['paraboloid'], '\n')
        self.assertTrue(err < 1e-2)
示例#2
0
    def test_hadamard_accuracy(self):
        systemsize = 4
        eigen_decayrate = 2.0

        # Create Hadmard Quadratic object
        QoI = examples.HadamardQuadratic(systemsize, eigen_decayrate)

        mu = np.zeros(systemsize)
        std_dev = np.eye(systemsize)
        jdist = cp.MvNormal(mu, std_dev)

        active_subspace = ActiveSubspace(QoI, n_dominant_dimensions=4,
                                             n_monte_carlo_samples=10000,
                                             use_svd=True, read_rv_samples=False,
                                             write_rv_samples=False)
        active_subspace.getDominantDirections(QoI, jdist)

        mu_j_analytical = QoI.eval_analytical_QoI_mean(mu, cp.Cov(jdist))
        var_j_analytical = QoI.eval_analytical_QoI_variance(mu, cp.Cov(jdist))

        # Create reduced collocation object
        QoI_dict = {'Hadamard' : {'QoI_func' : QoI.eval_QoI,
                                  'output_dimensions' : 1,
                                  },
                    }
        sc_obj_active = StochasticCollocation2(jdist, 4, 'MvNormal', QoI_dict,
                                        include_derivs=False,
                                        reduced_collocation=True,
                                        dominant_dir=active_subspace.dominant_dir)
        sc_obj_active.evaluateQoIs(jdist)

        mu_j_active = sc_obj_active.mean(of=['Hadamard'])
        var_j_active = sc_obj_active.variance(of=['Hadamard'])
    def calcMarginals(self, jdist):
        """
        Compute the marginal density object for the dominant space. The current
        implementation is only for Gaussian distribution.
        """

        marginal_size = len(self.dominant_indices)
        orig_mean = cp.E(jdist)
        orig_covariance = cp.Cov(jdist)

        # Step 1: Rotate the mean & covariance matrix of the the original joint
        # distribution along the eigenve
        dominant_vecs = self.iso_eigenvecs[:, self.dominant_indices]
        marginal_mean = np.dot(dominant_vecs.T, orig_mean)
        marginal_covariance = np.matmul(
            dominant_vecs.T, np.matmul(orig_covariance, dominant_vecs))

        # Step 2: Create the new marginal distribution
        if marginal_size == 1:  # Univariate distributions have to be treated separately
            marginal_std_dev = np.sqrt(np.asscalar(marginal_covariance))
            self.marginal_distribution = cp.Normal(np.asscalar(marginal_mean),
                                                   marginal_std_dev)
        else:
            self.marginal_distribution = cp.MvNormal(marginal_mean,
                                                     marginal_covariance)
    def reduced_dVariance(self, QoI_func, jdist, dominant_space, mu_j,
                          dQoI_func, dmu_j):
        """
        same as dVariance but in the reduced stochastic space.
        """
        x = cp.E(jdist)
        rv_covariance = cp.Cov(jdist)
        n_quadrature_loops = len(dominant_space.dominant_indices)
        dominant_dir = dominant_space.iso_eigenvecs[:, dominant_space.
                                                    dominant_indices]
        ref_collocation_pts = self.q
        ref_collocation_w = self.w
        idx = 0
        colloc_xi_arr = np.zeros(n_quadrature_loops)
        colloc_w_arr = np.zeros(n_quadrature_loops)
        dvariance_j = np.zeros([self.QoI_dimensions, self.QoI_dimensions])

        idx = self.doReduced_dVariance(x, rv_covariance, dominant_dir, mu_j,
                                       dmu_j, dvariance_j, ref_collocation_pts,
                                       ref_collocation_w, QoI_func, dQoI_func,
                                       colloc_xi_arr, colloc_w_arr, idx)

        assert idx == -1
        dvariance_j[:] = dvariance_j[:] / (np.sqrt(np.pi)**n_quadrature_loops)

        # TODO: figure out a better way of handling arrays and matrices for this routine
        return dvariance_j.diagonal()
    def dVariance(self, QoI_func, jdist, mu_j, dQoI_func, dmu_j):
        """
        Computes the partial derivative of the variance
        This implementation is CURRENTLY ONLY for QoI's that return scalar values.
        """
        x = cp.E(jdist)
        rv_covariance = cp.Cov(jdist)
        systemsize = x.size
        ref_collocation_pts = self.q
        ref_collocation_w = self.w
        idx = 0
        colloc_xi_arr = np.zeros(systemsize)
        colloc_w_arr = np.zeros(systemsize)
        dvariance_j = np.zeros([self.QoI_dimensions, self.QoI_dimensions])
        # dvariance_j = np.zeros(self.QoI_dimensions)

        idx = self.do_dVariance(x, rv_covariance, mu_j, dmu_j, dvariance_j,
                                ref_collocation_pts, ref_collocation_w,
                                QoI_func, dQoI_func, colloc_xi_arr,
                                colloc_w_arr, idx)
        assert idx == -1
        dvariance_j[:] = dvariance_j[:] / (np.sqrt(np.pi)**systemsize)

        # TODO: figure out a better way of handling arrays and matrices for this routine
        return dvariance_j.diagonal()
    def test_multipleQoI(self):

        # This tests for multiple QoIs. We only compute the mean in this test,
        # because it is only checking if it can do multiple loops

        systemsize = 2
        theta = 0
        mu = mean_2dim  # np.random.randn(systemsize)
        std_dev = std_dev_2dim  # np.diag(np.random.rand(systemsize))
        jdist = cp.MvNormal(mu, std_dev)
        QoI1 = examples.Paraboloid2D(systemsize, (theta, ))
        QoI2 = examples.PolyRVDV()
        QoI_dict = {
            'paraboloid2': {
                'QoI_func': QoI1.eval_QoI,
                'output_dimensions': 1,
            },
            'PolyRVDV': {
                'QoI_func': QoI2.eval_QoI,
                'output_dimensions': 1,
            }
        }
        sc_obj = StochasticCollocation2(jdist, 3, 'MvNormal', QoI_dict)
        sc_obj.evaluateQoIs(jdist)
        mu_js = sc_obj.mean(of=['paraboloid2', 'PolyRVDV'])

        # Compare against known values
        # 1. Paraboloid2D, we use nested loops
        mu_j1_analytical = QoI1.eval_QoI_analyticalmean(mu, cp.Cov(jdist))
        err = abs(
            (mu_js['paraboloid2'][0] - mu_j1_analytical) / mu_j1_analytical)
        self.assertTrue(err < 1.e-15)
示例#7
0
    def __init__(self, uq_systemsize):

        mean_v = 248.136  # Mean value of input random variable
        mean_alpha = 5  #
        mean_Ma = 0.84
        mean_re = 1.e6
        mean_rho = 0.38
        mean_cg = np.zeros((3))

        std_dev = np.diag([0.2, 0.01])  # np.diag([1.0, 0.2, 0.01, 1.e2, 0.01])
        rv_dict = {  # 'v' : mean_v,
            'alpha': mean_alpha,
            'Mach_number': mean_Ma,
            # 're' : mean_re,
            # 'rho' : mean_rho,
        }
        self.QoI = examples.OASAerodynamicWrapper(uq_systemsize, rv_dict)
        self.jdist = cp.Normal(self.QoI.rv_array, std_dev)
        self.dominant_space = DimensionReduction(
            n_arnoldi_sample=uq_systemsize + 1, exact_Hessian=False)
        self.dominant_space.getDominantDirections(self.QoI,
                                                  self.jdist,
                                                  max_eigenmodes=1)

        # print 'iso_eigenvals = ', self.dominant_space.iso_eigenvals
        # print 'iso_eigenvecs = ', '\n', self.dominant_space.iso_eigenvecs
        # print 'dominant_indices = ', self.dominant_space.dominant_indices
        # print 'ratio = ', abs(self.dominant_space.iso_eigenvals[0] / self.dominant_space.iso_eigenvals[1])
        print 'std_dev = ', cp.Std(self.jdist), '\n'
        print 'cov = ', cp.Cov(self.jdist), '\n'
    def getDominantDirections(self, QoI, jdist):
        systemsize = QoI.systemsize

        if self.read_file == True:
            rv_arr = np.loadtxt('rv_arr.txt')
            np.testing.assert_equal(self.n_monte_carlo_samples,
                                    rv_arr.shape[1])
        else:
            if self.use_truncated_samples:
                rv_arr = self.get_truncated_samples(jdist)
            else:
                rv_arr = jdist.sample(
                    self.n_monte_carlo_samples
                )  # points for computing the uncentered covariance matrix
        if self.write_file == True:
            np.savetxt('rv_arr.txt', rv_arr)

        pert = np.zeros(systemsize)

        if self.use_truncated_samples:
            new_samples = self.check_3sigma_violation(rv_arr, jdist)

        if self.use_svd == False:
            # Get C_tilde using Monte Carlo
            grad = np.zeros(systemsize)
            self.C_tilde = np.zeros([systemsize, systemsize])
            for i in range(0, self.n_monte_carlo_samples):
                grad[:] = QoI.eval_QoIGradient(rv_arr[:, i], pert)
                self.C_tilde[:, :] += np.outer(grad, grad)
            self.C_tilde[:, :] = self.C_tilde[:, :] / self.n_monte_carlo_samples

            # Factorize C_tilde that
            self.iso_eigenvals, self.iso_eigenvecs = np.linalg.eig(
                self.C_tilde)
        else:
            # Grad matrix
            grad = np.zeros([systemsize, self.n_monte_carlo_samples])
            for i in range(0, self.n_monte_carlo_samples):
                grad[:, i] = QoI.eval_QoIGradient(rv_arr[:, i], pert)
            grad[:, :] = grad / np.sqrt(self.n_monte_carlo_samples)
            # Perform SVD
            W, s, _ = np.linalg.svd(grad)

            if self.use_iso_transformation:
                # Do the isoprobabilistic transformation
                covariance = cp.Cov(jdist)
                sqrt_Sigma = np.sqrt(covariance)
                iso_grad = np.dot(grad.T, sqrt_Sigma).T
                # Perform SVD
                W, s, _ = np.linalg.svd(iso_grad)

            self.iso_eigenvals = s**2
            self.iso_eigenvecs = W

        # get the indices of dominant eigenvalues in descending order
        sort_ind = self.iso_eigenvals.argsort()[::-1]
        self.iso_eigenvecs[:, :] = self.iso_eigenvecs[:, sort_ind]
        self.iso_eigenvals[:] = self.iso_eigenvals[sort_ind]
        self.dominant_indices = np.arange(0, self.n_dominant_dimensions)
        self.dominant_dir = self.iso_eigenvecs[:, self.dominant_indices]
    def reduced_mean(self, QoI_func, jdist, dominant_space):

        x = cp.E(jdist)
        covariance = cp.Cov(jdist)
        n_quadrature_loops = len(dominant_space.dominant_indices)
        dominant_dir = dominant_space.iso_eigen_vectors[:, dominant_space.
                                                        dominant_indices]
        ref_collocation_pts = self.q
        ref_collocation_w = self.w
        idx = 0
        colloc_xi_arr = np.zeros(n_quadrature_loops)
        colloc_w_arr = np.zeros(n_quadrature_loops)
        mu_j = np.zeros(self.QoI_dimensions)

        idx = self.doReducedUniformMean(x, covariance, dominant_dir, mu_j,
                                        ref_collocation_pts, ref_collocation_w,
                                        QoI_func, colloc_xi_arr, colloc_w_arr,
                                        idx)

        assert idx == -1
        # TODO: The following scaling doesnt look right, INVESTIGATE
        mu_j[:] = mu_j[:] * (0.5**n_quadrature_loops)

        if len(mu_j) == 1:
            return mu_j[0]
        else:
            return mu_j
    def test_reduced_normalStochasticCollocation3D(self):

        # This is not a very good test because we are comparing the reduced collocation
        # against the analytical expected value. The only hting it tells us is that
        # the solution is within the ball park of actual value. We still need to
        # come up with a better test.

        systemsize = 3
        mu = mean_3dim  # np.random.randn(systemsize)
        std_dev = std_dev_3dim  # abs(np.diag(np.random.randn(systemsize)))
        jdist = cp.MvNormal(mu, std_dev)
        # Create QoI Object
        QoI = examples.Paraboloid3D(systemsize)
        dominant_dir = np.array([[1.0, 0.0], [0.0, 1.0], [0.0, 0.0]],
                                dtype=np.float)
        # Create the Stochastic Collocation object
        deriv_dict = {
            'xi': {
                'dQoI_func': QoI.eval_QoIGradient,
                'output_dimensions': systemsize
            }
        }
        QoI_dict = {
            'paraboloid': {
                'QoI_func': QoI.eval_QoI,
                'output_dimensions': 1,
                'deriv_dict': deriv_dict
            }
        }
        sc_obj = StochasticCollocation2(jdist,
                                        3,
                                        'MvNormal',
                                        QoI_dict,
                                        reduced_collocation=True,
                                        dominant_dir=dominant_dir)
        sc_obj.evaluateQoIs(jdist)
        mu_js = sc_obj.mean(of=['paraboloid'])
        var_js = sc_obj.variance(of=['paraboloid'])
        # Analytical mean
        mu_j_analytical = QoI.eval_QoI_analyticalmean(mu, cp.Cov(jdist))
        err = abs((mu_js['paraboloid'][0] - mu_j_analytical) / mu_j_analytical)
        self.assertTrue(err < 1e-1)
        # Analytical variance
        var_j_analytical = QoI.eval_QoI_analyticalvariance(mu, cp.Cov(jdist))
        err = abs(
            (var_js['paraboloid'][0, 0] - var_j_analytical) / var_j_analytical)
        self.assertTrue(err < 0.01)
def run_hadamard(systemsize, eigen_decayrate, std_dev, n_eigenmodes):
    n_collocation_pts = 2

    # Create Hadmard Quadratic object
    QoI = examples.HadamardQuadratic(systemsize, eigen_decayrate)

    # # Create stochastic collocation object
    # collocation = StochasticCollocation(n_collocation_pts, "Normal")

    # Initialize chaospy distribution
    x = np.random.rand(QoI.systemsize)
    jdist = cp.MvNormal(x, np.diag(std_dev))

    threshold_factor = 0.5
    dominant_space = DimensionReduction(threshold_factor=threshold_factor,
                                        exact_Hessian=False,
                                        n_arnoldi_sample=71,
                                        min_eigen_accuracy=1.e-2)
    dominant_space.getDominantDirections(QoI,
                                         jdist,
                                         max_eigenmodes=n_eigenmodes)

    # if systemsize == 64:
    # print('x = \n', repr(x))
    # print('std_dev = \n', repr(std_dev))
    # print('iso_eigenvals = ', dominant_space.iso_eigenvals)
    # print("dominant_indices = ", dominant_space.dominant_indices)

    # Collocate
    # collocation = StochasticCollocation(n_collocation_pts, "Normal")
    # mu_j = collocation.normal.reduced_mean(QoI.eval_QoI, jdist, dominant_space)
    # print "mu_j = ", mu_j

    QoI_dict = {
        'Hadamard': {
            'QoI_func': QoI.eval_QoI,
            'output_dimensions': 1,
        },
    }
    sc_obj = StochasticCollocation2(jdist,
                                    n_collocation_pts,
                                    'MvNormal',
                                    QoI_dict,
                                    include_derivs=False,
                                    reduced_collocation=True,
                                    dominant_dir=dominant_space.dominant_dir)
    sc_obj.evaluateQoIs(jdist)
    mu_j_dict = sc_obj.mean(of=['Hadamard'])
    mu_j = mu_j_dict['Hadamard']

    # Evaluate the analytical value of the Hadamard Quadratic
    covariance = cp.Cov(jdist)
    mu_analytic = QoI.eval_analytical_QoI_mean(x, covariance)
    # print "mu_analytic = ", mu_analytic

    relative_error = np.linalg.norm((mu_j - mu_analytic) / mu_analytic)
    # print "relative_error = ", relative_error

    return relative_error
示例#12
0
def test_orth_ttr():
    dist = cp.Normal(0, 1)
    orth = cp.orth_ttr(5, dist)
    outer = cp.outer(orth, orth)
    Cov1 = cp.E(outer, dist)
    Diatoric = Cov1 - np.diag(np.diag(Cov1))
    assert np.allclose(Diatoric, 0)

    Cov2 = cp.Cov(orth[1:], dist)
    assert np.allclose(Cov1[1:,1:], Cov2)
    def test_normalStochasticCollocation3D(self):
        systemsize = 3
        mu = mean_3dim  # np.random.randn(systemsize)
        std_dev = std_dev_3dim  # np.diag(np.random.rand(systemsize))
        jdist = cp.MvNormal(mu, std_dev)
        # Create QoI Object
        QoI = examples.Paraboloid3D(systemsize)

        # Create the Stochastic Collocation object
        deriv_dict = {
            'xi': {
                'dQoI_func': QoI.eval_QoIGradient,
                'output_dimensions': systemsize
            }
        }
        QoI_dict = {
            'paraboloid': {
                'quadrature_degree': 3,
                'reduced_collocation': False,
                'QoI_func': QoI.eval_QoI,
                'output_dimensions': 1,
                'include_derivs': False,
                'deriv_dict': deriv_dict
            }
        }
        sc_obj = StochasticCollocation3(jdist, 'MvNormal', QoI_dict)
        sc_obj.evaluateQoIs(jdist)
        mu_js = sc_obj.mean(of=['paraboloid'])
        var_js = sc_obj.variance(of=['paraboloid'])

        # Analytical mean
        mu_j_analytical = QoI.eval_QoI_analyticalmean(mu, cp.Cov(jdist))
        err = abs((mu_js['paraboloid'][0] - mu_j_analytical) / mu_j_analytical)
        self.assertTrue(err < 1.e-15)

        # Analytical variance
        var_j_analytical = QoI.eval_QoI_analyticalvariance(mu, cp.Cov(jdist))
        err = abs(
            (var_js['paraboloid'][0, 0] - var_j_analytical) / var_j_analytical)
        self.assertTrue(err < 1.e-15)
    def reduced_variance(self, QoI_func, jdist, dominant_space, mu_j):
        """
        Public member that is used to perform stochastic collocation only along
        certain directions to compute the variance of a QoI.

        **Inputs**

        * `QoI_func` : Quantity of Interest function to be evaluated
        * `jdist` : joint distribution object of the random variables
        * `dominant_space` : Array of vectors along which the stochastic
                             collocation is performed.

        **Outputs**

        * `mu_j` : Mean value of the Quantity of Interest for a given mean value
                   of random variabes
        """
        x = cp.E(jdist)
        rv_covariance = cp.Cov(jdist)
        n_quadrature_loops = len(dominant_space.dominant_indices)
        dominant_dir = dominant_space.iso_eigenvecs[:, dominant_space.
                                                    dominant_indices]
        ref_collocation_pts = self.q
        ref_collocation_w = self.w
        idx = 0
        colloc_xi_arr = np.zeros(n_quadrature_loops)
        colloc_w_arr = np.zeros(n_quadrature_loops)
        variance_j = np.zeros([self.QoI_dimensions, self.QoI_dimensions])

        idx = self.doReducedNormalVariance(x, rv_covariance, dominant_dir,
                                           mu_j, variance_j,
                                           ref_collocation_pts,
                                           ref_collocation_w, QoI_func,
                                           colloc_xi_arr, colloc_w_arr, idx)

        assert idx == -1
        variance_j[:] = variance_j[:] / (np.sqrt(np.pi)**n_quadrature_loops)

        if len(variance_j) == 1:
            return variance_j[0]
        else:
            return variance_j
示例#15
0
def Corr(poly, dist=None, **kws):
    """
    Correlation matrix of a distribution or polynomial.

    Args:
        poly (numpoly.ndpoly, Distribution):
            Input to take correlation on. Must have ``len(poly)>=2``.
        dist (Distribution):
            Defines the space the correlation is taken on.  It is ignored if
            ``poly`` is a distribution.

    Returns:
        (numpy.ndarray):
            Correlation matrix with
            ``correlation.shape == poly.shape+poly.shape``.

    Examples:
        >>> distribution = chaospy.MvNormal(
        ...     [3, 4], [[2, .5], [.5, 1]])
        >>> chaospy.Corr(distribution).round(4)
        array([[1.    , 0.3536],
               [0.3536, 1.    ]])
        >>> q0 = chaospy.variable()
        >>> poly = chaospy.polynomial([q0, q0**2])
        >>> distribution = chaospy.Normal()
        >>> chaospy.Corr(poly, distribution).round(4)
        array([[1., 0.],
               [0., 1.]])

    """
    if isinstance(poly, chaospy.Distribution):
        poly, dist = numpoly.variable(len(poly)), poly
    else:
        poly = numpoly.polynomial(poly)

    if not poly.shape:
        return numpy.ones((1, 1))

    cov = chaospy.Cov(poly, dist, **kws)
    var = numpy.diag(cov)
    vvar = numpy.sqrt(numpy.outer(var, var))
    return numpy.where(vvar > 0, cov / vvar, 0)
示例#16
0
def get_iso_gradients(dv_dict):
    """
    Computes the gradient of the scaneagle problem in the isoprobabilistic space
    w.r.t the random variables.
    """
    UQObj.QoI.p['oas_scaneagle.wing.twist_cp'] = dv_dict['twist_cp']
    UQObj.QoI.p['oas_scaneagle.wing.thickness_cp'] = dv_dict['thickness_cp']
    UQObj.QoI.p['oas_scaneagle.wing.sweep'] = dv_dict['sweep']
    UQObj.QoI.p['oas_scaneagle.alpha'] = dv_dict['alpha']

    mu_val = cp.E(UQObj.jdist)
    covariance = cp.Cov(UQObj.jdist)
    sqrt_Sigma = np.sqrt(covariance)  # !!!! ONLY FOR INDEPENDENT RVs !!!!
    print('mu_val = ', mu_val)
    print('covariance = ', covariance)
    # print('sqrt_Sigma = \n', sqrt_Sigma)
    grad = UQObj.QoI.eval_QoIGradient(mu_val, np.zeros(len(mu_val)))
    iso_grad = np.dot(grad, sqrt_Sigma)

    return iso_grad, grad
    def mean(self, QoI_func, jdist):
        x = cp.E(jdist)
        covariance = cp.Cov(jdist)

        systemsize = x.size
        ref_collocation_pts = self.q
        ref_collocation_w = self.w
        idx = 0
        colloc_xi_arr = np.zeros(systemsize)
        colloc_w_arr = np.zeros(systemsize)
        mu_j = np.zeros(self.QoI_dimensions)
        idx = self.doUniformMean(x, covariance, mu_j, ref_collocation_pts,
                                 ref_collocation_w, QoI_func, colloc_xi_arr,
                                 colloc_w_arr, idx)
        assert idx == -1
        mu_j[:] = mu_j[:] * (0.5**systemsize)

        if len(mu_j) == 1:
            return mu_j[0]
        else:
            return mu_j
示例#18
0
    def __init__(self, nsamples, jdist, QoI_dict, include_derivs=False,
                 reduced_collocation=False, dominant_dir=None, data_type=np.float):
        assert nsamples > 0, "Number of MonteCarlo samples must be greater than 0"
        self.num_samples = nsamples
        self.data_type = data_type # To enable complex variables
        self.QoI_dict = utils.copy_qoi_dict(QoI_dict)

        if reduced_collocation == False:
            self.samples = jdist.sample(self.num_samples)
        else:
            # !!! This implementation is only for normal distribution !!!
            # Get the number of dominant directions
            ndims = dominant_dir.shape[1]
            mu = cp.E(jdist)
            covariance = cp.Cov(jdist)
            sqrt_Sigma = np.sqrt(covariance) # This assumes the random variables are independent
            if ndims > 1:
                self.iso_jdist = cp.MvNormal(np.zeros(ndims), np.eye(ndims))
                self.iso_samples = self.iso_jdist.sample(self.num_samples)
                int_mat = np.matmul(sqrt_Sigma, dominant_dir)
                self.samples = np.add(np.einsum('ij,jk', int_mat, self.iso_samples).T, mu).T
            else:
                self.iso_jdist = cp.Normal()
                self.iso_samples = self.iso_jdist.sample(self.num_samples)
                int_mat = np.matmul(sqrt_Sigma, dominant_dir)
                # print(np.outer(int_mat, self.iso_samples))
                self.samples = np.add(np.outer(int_mat, self.iso_samples).T, mu).T


        for i in self.QoI_dict:
            self.QoI_dict[i]['fvals'] = np.zeros([self.num_samples,
                                        self.QoI_dict[i]['output_dimensions']],
                                        dtype=self.data_type)
        if include_derivs == True:
            for i in self.QoI_dict:
                for j in self.QoI_dict[i]['deriv_dict']:
                    self.QoI_dict[i]['deriv_dict'][j]['fvals'] =  np.zeros([self.num_samples,
                                                self.QoI_dict[i]['output_dimensions'],
                                                self.QoI_dict[i]['deriv_dict'][j]['output_dimensions']],
                                                dtype=self.data_type)
    def variance(self, QoI_func, jdist, mu_j):
        """
        Public member that is used to perform stochastic collocation only along
        certain directions to compute the variance of a QoI.

        **Inputs**

        * `QoI` : Quantity of Interest Object
        * `jdist` : joint distribution object of the random variables
        * `mu_j` : Mean value of the quantity of interest

        **Outputs**

        * `variance_j` : variance of the Quantity of Interest for a given mean
                         value of random variabes
        """

        # np.testing.assert_equal(len(mu_j), self.QoI_dimensions) # sanity check
        x = cp.E(jdist)
        rv_covariance = cp.Cov(jdist)
        systemsize = x.size
        ref_collocation_pts = self.q
        ref_collocation_w = self.w
        idx = 0
        colloc_xi_arr = np.zeros(systemsize)
        colloc_w_arr = np.zeros(systemsize)
        variance_j = np.zeros([self.QoI_dimensions, self.QoI_dimensions])

        idx = self.doVariance(x, rv_covariance, mu_j, variance_j,
                              ref_collocation_pts, ref_collocation_w, QoI_func,
                              colloc_xi_arr, colloc_w_arr, idx)

        assert idx == -1
        variance_j[:] = variance_j[:] / (np.sqrt(np.pi)**systemsize)

        if len(variance_j) == 0:
            return variance_j[0]
        else:
            return variance_j
    def variance(self, QoI_func, jdist, mu_j):
        x = cp.E(jdist)
        rv_covariance = cp.Cov(jdist)
        systemsize = x.size
        ref_collocation_pts = self.q
        ref_collocation_w = self.w
        idx = 0
        colloc_xi_arr = np.zeros(systemsize)
        colloc_w_arr = np.zeros(systemsize)
        variance_j = np.zeros(1)

        idx = self.doVariance(x, rv_covariance, mu_j, variance_j,
                              ref_collocation_pts, ref_collocation_w, QoI_func,
                              colloc_xi_arr, colloc_w_arr, idx)

        assert idx == -1
        variance_j[:] = variance_j[:] * (0.5**systemsize)

        if len(variance_j) == 1:
            return variance_j[0]
        else:
            return variance_j
    def test_reducedCollocation(self):

        systemsize = 4
        eigen_decayrate = 2.0

        # Create Hadmard Quadratic object
        QoI = examples.HadamardQuadratic(systemsize, eigen_decayrate)

        # Create stochastic collocation object
        collocation = StochasticCollocation(3, "Normal")

        # Create dimension reduction object
        threshold_factor = 0.9
        dominant_space = DimensionReduction(threshold_factor=threshold_factor,
                                            exact_Hessian=True)

        # Initialize chaospy distribution
        std_dev = 0.2 * np.ones(QoI.systemsize)
        x = np.ones(QoI.systemsize)
        jdist = cp.MvNormal(x, np.diag(std_dev))

        # Get the eigenmodes of the Hessian product and the dominant indices
        dominant_space.getDominantDirections(QoI, jdist)

        QoI_func = QoI.eval_QoI
        # Check the mean
        mu_j = collocation.normal.reduced_mean(QoI_func, jdist, dominant_space)
        true_value_mu_j = 4.05
        err = abs(mu_j - true_value_mu_j)
        self.assertTrue(err < 1.e-13)

        # Check the variance
        red_var_j = collocation.normal.reduced_variance(
            QoI_func, jdist, dominant_space, mu_j)
        # var_j = collocation.normal.variance(QoI_func, jdist, mu_j)
        analytical_var_j = QoI.eval_analytical_QoI_variance(x, cp.Cov(jdist))
        err = abs(analytical_var_j - red_var_j)
        self.assertTrue(err < 1.e-4)
 def getQuadratureInfo(self, jdist, quadrature_degree, ref_collocation_pts,
                       ref_collocation_w):
     """
     Generates the integration points at which the deterministic QoI needs
     to be evaluated, and also the corresponding quadrature weights.
     """
     self.n_quadrature_loops = self.n_rv
     self.n_points = quadrature_degree**self.n_quadrature_loops
     covariance = cp.Cov(jdist)
     idx = 0
     ctr = 0
     colloc_xi_arr = np.zeros(self.n_rv)
     colloc_w_arr = np.zeros(self.n_rv)
     self.points = np.zeros([self.n_points, self.n_rv],
                            dtype=self.data_type)
     self.quadrature_weights = np.zeros(self.n_points, dtype=self.data_type)
     sqrt_Sigma = np.sqrt(covariance)
     idx, ctr = self.__compute_quad(sqrt_Sigma, ref_collocation_pts,
                                    ref_collocation_w, colloc_xi_arr,
                                    colloc_w_arr, self.points,
                                    self.quadrature_weights, idx, ctr)
     assert idx == -1
     self.points += cp.E(jdist)
示例#23
0
    def getReducedQuadratureInfo(self, jdist, dominant_dir, quadrature_degree,
                                 ref_collocation_pts, ref_collocation_w):
        """
        Generates the integration points at which the deterministic QoI needs
        to be evaluated for the reduced stochastic space, and also the
        corresponding quadrature weights.
        """
        n_quadrature_loops = dominant_dir.shape[1]
        n_points = quadrature_degree**n_quadrature_loops
        covariance = cp.Cov(jdist)
        idx = 0
        ctr = 0
        colloc_xi_arr = np.zeros(n_quadrature_loops)
        colloc_w_arr = np.zeros(n_quadrature_loops)
        points = np.zeros([n_points, self.n_rv], dtype=self.data_type)
        quadrature_weights = np.zeros(n_points, dtype=self.data_type)
        sqrt_Sigma = np.sqrt(covariance)
        idx, ctr = self.__compute_reduced_quad(
            sqrt_Sigma, dominant_dir, ref_collocation_pts, ref_collocation_w,
            colloc_xi_arr, colloc_w_arr, points, quadrature_weights, idx, ctr)
        assert idx == -1
        points += cp.E(jdist)

        return points, quadrature_weights
示例#24
0
def test_descriptives():
    dist = cp.Iid(cp.Normal(), dim)
    orth = cp.orth_ttr(order, dist)
    cp.E(orth, dist)
    cp.Var(orth, dist)
    cp.Cov(orth, dist)
示例#25
0
from dimension_reduction import DimensionReduction
from stochastic_arnoldi.arnoldi_sample import ArnoldiSampling
import examples

# V_orig = np.array([[-np.sqrt(3)/2, -0.5],[-0.5, np.sqrt(3)/2]])
# V2 = np.array([-0.5, np.sqrt(3)/2])

mu = np.zeros(2)
theta = np.pi / 3
tuple = (theta, )
QoI = examples.Paraboloid2D(2, tuple)

sigma = np.ones(2)
jdist = cp.MvNormal(mu, np.diag(sigma))
Hessian = QoI.eval_QoIHessian(mu, np.zeros(2))
covariance = cp.Cov(jdist)
sqrt_Sigma = np.sqrt(covariance)
Hessian_Product = np.matmul(sqrt_Sigma, np.matmul(Hessian, sqrt_Sigma))
eigenvalues, V_orig = np.linalg.eig(Hessian_Product)
sort_ind = eigenvalues.argsort()
eigenvalues[:] = eigenvalues[sort_ind]
V_orig[:, :] = V_orig[:, sort_ind]
V2 = V_orig[:, 1]
theta_bar = np.arctan(V2[1] / V2[0])

# contour plot
n_xi = 100
xi_min = [-3.0, -3.0]
xi_max = [3.0, 3.0]
xi_1 = np.linspace(xi_min[0], xi_max[0], n_xi)
xi_2 = np.linspace(xi_min[1], xi_max[1], n_xi)
示例#26
0
from oas_aerodynamic_group import OASAerodynamic


p = Problem()
dvs = p.model.add_subsystem('des_vars', IndepVarComp(), promotes_outputs=['*'])

N_RANDOM = 2
DEGREE = 3
N_SAMPLES = DEGREE**N_RANDOM
SCLOC_Q, SCLOC_W = np.polynomial.hermite.hermgauss(DEGREE)

x_init = np.zeros(N_RANDOM)
dvs.add_output('mu', val=x_init)

J_dist = cp.MvNormal(x_init, np.eye(N_RANDOM))
co_mat = cp.Cov(J_dist)

class Rosenbrock_OMDAO(ExplicitComponent):
    """
    Base class that computes the deterministic Rosenbrock function.
    """

    def initialize(self):
        self.options.declare('size', types=int)

    def setup(self):
        self.add_input('rv', val = np.zeros(N_RANDOM)) # rv = random variable
        self.add_output('fval', val=0.0)
        self.declare_partials('fval', 'rv')

    def compute(self, inputs, outputs):
    def getDominantDirections(self, QoI, jdist, **kwargs):
        """
        Given a Quantity of Interest and a jpint distribution of the random
        variables, this function computes the directions along which the
        function is most nonlinear. We call these nonlinear directions as
        dominant directions.

        **Arguments**

        * `QoI` : QuantityOfInterest object
        * `jdist` : Joint distribution object

        """

        mu = cp.E(jdist)
        covariance = cp.Cov(jdist)
        # Check if variance covariance matrix is diagonal
        if np.count_nonzero(covariance -
                            np.diag(np.diagonal(covariance))) == 0:
            sqrt_Sigma = np.sqrt(covariance)
        else:
            raise NotImplementedError
        # TODO: Break the long if blocks into functions
        if self.use_exact_Hessian == True:

            # Get the Hessian of the QoI
            xi = np.zeros(QoI.systemsize)
            Hessian = QoI.eval_QoIHessian(mu, xi)

            # Compute the eigen modes of the Hessian of the Hadamard Quadratic
            Hessian_Product = np.matmul(sqrt_Sigma,
                                        np.matmul(Hessian, sqrt_Sigma))
            self.iso_eigenvals, self.iso_eigenvecs = np.linalg.eig(
                Hessian_Product)

            self.num_sample = QoI.systemsize

            # Next,
            # Get the system energy of Hessian_Product
            system_energy = np.sum(self.iso_eigenvals)
            ind = []

            # get the indices of dominant eigenvalues in descending order
            sort_ind = self.iso_eigenvals.argsort()[::-1]

            # Check the threshold
            for i in range(0, self.num_sample):
                dominant_eigen_val_ind = sort_ind[0:i + 1]
                reduced_energy = np.sum(
                    self.iso_eigenvals[dominant_eigen_val_ind])
                if reduced_energy <= self.threshold_factor * system_energy:
                    ind.append(dominant_eigen_val_ind[i])
                else:
                    break

            if len(ind) == 0:
                ind.append(np.argmax(self.iso_eigenvals))

            self.dominant_indices = ind

        else:
            # approximate the hessian of the QoI in the isoprobabilistic space
            # 1. Initialize ArnoldiSampling object
            # Check if the system size is smaller than the number of arnoldi sample - 1
            if QoI.systemsize < self.num_sample - 1:
                self.num_sample = QoI.systemsize + 1

            arnoldi = ArnoldiSampling(self.sample_radius, self.num_sample)

            # 2. Declare arrays
            # 2.1 iso-eigenmodes
            self.iso_eigenvals = np.zeros(self.num_sample - 1)
            self.iso_eigenvecs = np.zeros(
                [QoI.systemsize, self.num_sample - 1])
            # 2.2 solution and function history array
            mu_iso = np.zeros(QoI.systemsize)
            gdata0 = np.zeros([QoI.systemsize, self.num_sample])

            # 3. Approximate eigenvalues using ArnoldiSampling
            # 3.1 Convert x into a standard normal distribution
            mu_iso[:] = 0.0
            gdata0[:, 0] = np.dot(
                QoI.eval_QoIGradient(mu, np.zeros(QoI.systemsize)), sqrt_Sigma)
            dim, error_estimate = arnoldi.arnoldiSample(
                QoI, jdist, mu_iso, gdata0, self.iso_eigenvals,
                self.iso_eigenvecs)

            # Check how many eigen pairs are good. We will exploit the fact that
            # the eigen pairs are already sorted in a descending order. We will
            # only use "good" eigen pairs to estimate the dominant directions.
            ctr = 0
            for i in range(0, dim):
                if error_estimate[i] < self.min_eigen_accuracy:
                    ctr += 1
                else:
                    break
            # print('error_estimate = ', error_estimate)
            # Compute the accumulated energy
            # acc_energy = np.sum(np.square(self.iso_eigenvals[0:ctr]))

            # Compute the magnitude of the eigenvalues w.r.t the largest eigenvalues
            relative_ratio = self.iso_eigenvals[0:ctr] / self.iso_eigenvals[0]

            # We will only use eigenpairs which whose relative size > discard_ratio
            # Since we are considering the size we consider the absolute magnitude
            usable_pairs = np.where(
                np.abs(relative_ratio) > self.discard_ratio)

            if 'max_eigenmodes' in kwargs:
                max_eigenmodes = kwargs['max_eigenmodes']
                if usable_pairs[0].size < max_eigenmodes:
                    self.dominant_indices = usable_pairs[0]
                else:
                    self.dominant_indices = usable_pairs[0][0:max_eigenmodes]
            else:
                self.dominant_indices = usable_pairs[0]

        # For either of the two cases of Exact hessian or inexact Hessian, we
        # specify the dominant indices
        self.dominant_dir = self.iso_eigenvecs[:, self.dominant_indices]
def run_hadamard(systemsize, eigen_decayrate, std_dev, n_eigenmodes):
    n_collocation_pts = 3

    # Create Hadmard Quadratic object
    QoI = examples.HadamardQuadratic(systemsize, eigen_decayrate)

    # Initialize chaospy distribution
    x = np.random.rand(QoI.systemsize)
    jdist = cp.MvNormal(x, np.diag(std_dev))

    threshold_factor = 1.0
    use_exact_Hessian = False
    if use_exact_Hessian:
        dominant_space = DimensionReduction(threshold_factor=threshold_factor,
                                            exact_Hessian=True)
        dominant_space.getDominantDirections(QoI, jdist)
        dominant_dir = dominant_space.iso_eigenvecs[:, 0:n_eigenmodes]
    else:
        dominant_space = DimensionReduction(threshold_factor=threshold_factor,
                                            exact_Hessian=False,
                                            n_arnoldi_sample=71,
                                            min_eigen_accuracy=1.e-2)
        dominant_space.getDominantDirections(QoI,
                                             jdist,
                                             max_eigenmodes=n_eigenmodes)
        dominant_dir = dominant_space.dominant_dir
    # print "dominant_indices = ", dominant_space.dominant_indices

    # Create stochastic collocation object
    # collocation = StochasticCollocation(n_collocation_pts, "Normal")
    QoI_dict = {
        'Hadamard': {
            'QoI_func': QoI.eval_QoI,
            'output_dimensions': 1,
        },
    }
    sc_obj = StochasticCollocation2(jdist,
                                    n_collocation_pts,
                                    'MvNormal',
                                    QoI_dict,
                                    include_derivs=False,
                                    reduced_collocation=True,
                                    dominant_dir=dominant_dir)
    sc_obj.evaluateQoIs(jdist)

    # Collocate
    # mu_j = collocation.normal.reduced_mean(QoI, jdist, dominant_space)
    mu_j = sc_obj.mean(of=['Hadamard'])
    var_j = sc_obj.variance(of=['Hadamard'])
    std_dev_j = np.sqrt(var_j['Hadamard'])
    # print "mu_j = ", mu_j

    # Evaluate the analytical value of the Hadamard Quadratic
    covariance = cp.Cov(jdist)
    mu_analytic = QoI.eval_analytical_QoI_mean(x, covariance)
    var_analytic = QoI.eval_analytical_QoI_variance(x, covariance)
    std_dev_analytic = np.sqrt(var_analytic)
    # print "mu_analytic = ", mu_analytic

    relative_error_mu = np.linalg.norm(
        (mu_j['Hadamard'] - mu_analytic) / mu_analytic)
    relative_err_var = np.linalg.norm(
        (var_j['Hadamard'] - var_analytic) / var_analytic)
    relative_err_std_dev = np.linalg.norm(
        (std_dev_j - std_dev_analytic) / std_dev_analytic)
    # print "relative_error = ", relative_error

    return relative_error_mu, relative_err_var, relative_err_std_dev
示例#29
0
    mu, std_dev = utils.get_scaneagle_input_rv_statistics(rv_dict)
    jdist = cp.MvNormal(mu, std_dev)

    # Step 1: Instantiate all objects needed for test
    QoI.p['oas_scaneagle.wing.thickness_cp'] = optimal_dv_dict[dv_dict_key]['thickness_cp']
    QoI.p['oas_scaneagle.wing.twist_cp'] = optimal_dv_dict[dv_dict_key]['twist_cp']
    QoI.p['oas_scaneagle.wing.sweep'] = optimal_dv_dict[dv_dict_key]['sweep']
    QoI.p['oas_scaneagle.alpha'] = optimal_dv_dict[dv_dict_key]['alpha']
    QoI.p.final_setup()

    # Get the direction number
    dir_no = int(sys.argv[3])
    npts = 11
    rdo_range = 9.0 # 3.0
    sqrt_Sigma = np.sqrt(cp.Cov(jdist))
    v_samples = np.linspace(-rdo_range, rdo_range, num=npts)
    # Create vector for plucking out points in the isoprobabilistic space
    e_i = np.zeros(uq_systemsize)
    e_i[dir_no] = 1.0
    fval_arr = np.zeros(npts)
    for pts in range(0, npts):
        rvs = mu + np.dot(sqrt_Sigma, np.dot(iso_eigenvecs, v_samples[pts] * e_i))
        # Update the random variables
        QoI.update_rv(rvs)
        QoI.p.run_model()
        fval_arr[pts] = QoI.p['oas_scaneagle.AS_point_0.fuelburn']

    # Write to file
    combined_arr = np.array([v_samples, fval_arr])
    fname = './V' + str(dir_no) + '/fburn_vs_V' + str(dir_no) + '_' + dv_dict_key + '.txt'
示例#30
0
def test_descriptives():
    dist = cp.Iid(cp.Normal(), dim)
    orth = cp.expansion.stieltjes(order, dist)
    cp.E(orth, dist)
    cp.Var(orth, dist)
    cp.Cov(orth, dist)