Source code for UQpy.surrogates.polynomial_chaos.polynomials.baseclass.Polynomials

from abc import abstractmethod
from typing import Union, Callable

import numpy as np
import scipy.integrate as integrate
from beartype import beartype
from scipy import stats as stats
from UQpy.distributions.baseclass import Distribution
import warnings

from UQpy.distributions.collection import Uniform, Normal

warnings.filterwarnings('ignore')


[docs]class Polynomials: @beartype def __init__(self, distributions: Union[Distribution, list[Distribution]], degree: int): """ Class for polynomials used for the polynomial_chaos method. :param distributions: Object from a distribution class. :param degree: Maximum degree of the polynomials. """ self.distributions = distributions self.degree = degree + 1
[docs] @staticmethod def standardize_sample(x, joint_distribution): """ Static method: Standardize data based on the joint probability distribution. :param x: Input data generated from a joint probability distribution. :param joint_distribution: joint probability distribution from :py:mod:`UQpy` distribution object :return: Standardized data. """ s = np.zeros(x.shape) inputs_number = len(x[0, :]) if inputs_number == 1: marginals = [joint_distribution] else: marginals = joint_distribution.marginals for i in range(inputs_number): if type(marginals[i]) == Normal: s[:, i] = Polynomials.standardize_normal(x[:, i], mean=marginals[i].parameters['loc'], std=marginals[i].parameters['scale']) elif type(marginals[i]) == Uniform: s[:, i] = Polynomials.standardize_uniform(x[:, i], marginals[i]) else: raise TypeError("standarize_sample is defined only for Uniform and Gaussian marginal distributions") return s
[docs] @staticmethod def standardize_pdf(x, joint_distribution): """ Static method: PDF of standardized distributions associated to Hermite or Legendre polynomials. :param x: Input data generated from a joint probability distribution :param joint_distribution: joint probability distribution from :py:mod:`UQpy` distribution object :return: Value of standardized PDF calculated for x """ inputs_number = len(x[0, :]) pdf_val = 1 s = Polynomials.standardize_sample(x, joint_distribution) if inputs_number == 1: marginals = [joint_distribution] else: marginals = joint_distribution.marginals for i in range(inputs_number): if type(marginals[i]) == Normal: pdf_val *= (stats.norm.pdf(s[:, i])) elif type(marginals[i]) == Uniform: pdf_val *= (stats.uniform.pdf(s[:, i], loc=-1, scale=2)) else: raise TypeError("standardize_pdf is defined only for Uniform and Gaussian marginal distributions") return pdf_val
[docs] @staticmethod def standardize_normal(tensor: np.ndarray, mean: float, std: float): """ Static method: Standardize data based on the standard normal distribution :math:`\mathcal{N}(0,1)`. :param tensor: Input data generated from a normal distribution. :param mean: Mean value of the original normal distribution. :param std: Standard deviation of the original normal distribution. :return: Standardized data. """ return (tensor - mean) / std
@staticmethod def standardize_uniform(x, uniform): loc = uniform.get_parameters()['loc'] # loc = lower bound of uniform distribution scale = uniform.get_parameters()['scale'] upper = loc + scale # upper bound = loc + scale return (2 * x - loc - upper) / (upper - loc)
[docs] @staticmethod def normalized(degree: int, samples: np.ndarray, a: float, b: float, pdf_st: Callable, p: list): """ Calculates design matrix and normalized polynomials. :param degree: polynomial degree :param samples: Input samples. :param a: Left bound of the support the distribution. :param b: Right bound of the support of the distribution. :param pdf_st: Pdf function generated from :py:mod:`UQpy` distribution object. :param p: List containing the orthogonal polynomials generated with scipy. :return: Design matrix,normalized polynomials """ pol_normed = [] m = np.zeros((degree, degree)) for i in range(degree): for j in range(degree): int_res = integrate.quad( lambda k: p[i](k) * p[j](k) * pdf_st(k), a, b, epsabs=1e-15, epsrel=1e-15, ) m[i, j] = int_res[0] pol_normed.append(p[i] / np.sqrt(m[i, i])) a = np.zeros((samples.shape[0], degree)) for i in range(samples.shape[0]): for j in range(degree): a[i, j] = pol_normed[j](samples[i]) return a, pol_normed
[docs] def get_mean(self): """ Returns a :any:`float` with the mean of the :py:mod:`UQpy` distribution object. """ m = self.distributions.moments(moments2return="m") return m
[docs] def get_std(self): """ Returns a :any:`float` with the variance of the :py:mod:`UQpy` distribution object. """ s = np.sqrt(self.distributions.moments(moments2return="v")) return s
[docs] def location(self): """ Returns a :any:`float` with the location of the :py:mod:`UQpy` distribution object. """ m = self.distributions.__dict__["parameters"]["location"] return m
[docs] def scale(self): """ Returns a :any:`float` with the scale of the :py:mod:`UQpy` distribution object. """ s = self.distributions.__dict__["parameters"]["scale"] return s
@abstractmethod def evaluate(self, x: np.ndarray): pass distribution_to_polynomial = {}