Source code for parepy_toolbox.distributions

"""Probability distributions"""
import numpy as np
import scipy as sc


[docs] def convert_params_to_scipy(dist: str, parameters: dict) -> dict: """ Convert user-provided distribution parameters to the format required by "scipy.stats". :param parameters: Original distribution parameters. (a) 'uniform': keys 'min' and 'max', (b) 'normal': keys 'mean' and 'std', (c) 'lognormal': keys 'mean' and 'std', (d) 'gumbel max': keys 'mean' and 'std', (e) 'gumbel min': keys 'mean' and 'std', (f) 'triangular': keys 'min', 'mode' and 'max', or (g) 'gamma': keys 'mean' and 'std'. :return: Distribution parameters according scipy.stats documentation. """ if dist.lower() == 'uniform': parameters_scipy = {'loc': parameters['min'], 'scale': parameters['max'] - parameters['min']} elif dist.lower() == 'normal': parameters_scipy = {'loc': parameters['mean'], 'scale': parameters['std']} elif dist.lower() == 'lognormal': epsilon = np.sqrt(np.log(1 + (parameters['std'] / parameters['mean']) ** 2)) lambda_ = np.log(parameters['mean']) - 0.5 * epsilon ** 2 parameters_scipy = {'s': epsilon, 'loc': 0.0, 'scale': np.exp(lambda_)} elif dist.lower() == 'gumbel max': gamma = 0.5772156649015329 alpha = parameters['std'] * np.sqrt(6) / np.pi beta = parameters['mean'] - alpha * gamma parameters_scipy = {'loc': beta, 'scale': alpha} elif dist.lower() == 'gumbel min': gamma = 0.5772156649015329 alpha = parameters['std'] * np.sqrt(6) / np.pi beta = parameters['mean'] + alpha * gamma parameters_scipy = {'loc': beta, 'scale': alpha} elif dist.lower() == 'triangular': parameters_scipy = {'c': (parameters['mode'] - parameters['min']) / (parameters['max'] - parameters['min']), 'loc': parameters['min'], 'scale': parameters['max'] - parameters['min']} elif dist.lower() == 'gamma': a = (parameters['mean'] / parameters['std']) ** 2 scale = parameters['std'] ** 2 / parameters['mean'] parameters_scipy = {'a': a, 'loc': 0.0, 'scale': scale} elif dist.lower() == 'weibull min': def weibull_params_from_mean_std(mean, std): def equation(c): gamma1 = np.exp(sc.special.loggamma(1 + 1 / c)) gamma2 = np.exp(sc.special.loggamma(1 + 2 / c)) cv_squared = (std / mean) ** 2 return (gamma2 / (gamma1 ** 2)) - 1 - cv_squared c = sc.optimize.root(equation, x0=1.0).x[0] scale = mean / np.exp(sc.special.loggamma(1 + 1 / c)) return c, scale c, scale = weibull_params_from_mean_std(parameters['mean'], parameters['std']) parameters_scipy = {'c': c, 'loc': 0.0, 'scale': scale} return parameters_scipy
[docs] def normal_tail_approximation(dist: str, parameters_scipy: dict, x: float) -> tuple[float, float]: """ Converts non-normal distributions to normal approximations while preserving their statistical properties in x point. :param dist: Type of distribution. Supported values: 'uniform', 'normal', 'lognormal', 'gumbel max', 'gumbel min', 'triangular', or 'gamma'. :param parameters_scipy: Distribution parameters according scipy.stats documentation. :param x: Project point. return: output[0] = Mean of the normal approximation at point x, output[1] = Standard deviation of the normal approximation at point x. """ if dist.lower() == 'uniform': z_aux = sc.stats.uniform.cdf(x, loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) z = sc.stats.norm.ppf(z_aux, loc=0, scale=1) num = sc.stats.norm.pdf(z, loc=0, scale=1) den = sc.stats.uniform.pdf(x, loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) std_eq = num / den mean_eq = x - std_eq * z elif dist.lower() == 'normal': mean_eq = parameters_scipy['loc'] std_eq = parameters_scipy['scale'] elif dist.lower() == 'lognormal': z_aux = sc.stats.lognorm.cdf(x, s=parameters_scipy['s'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) z = sc.stats.norm.ppf(z_aux, loc=0, scale=1) num = sc.stats.norm.pdf(z, loc=0, scale=1) den = sc.stats.lognorm.pdf(x, s=parameters_scipy['s'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) std_eq = num / den mean_eq = x - std_eq * z elif dist.lower() == 'gumbel max': z_aux = sc.stats.gumbel_r.cdf(x, loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) z = sc.stats.norm.ppf(z_aux, loc=0, scale=1) num = sc.stats.norm.pdf(z, loc=0, scale=1) den = sc.stats.gumbel_r.pdf(x, loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) std_eq = num / den mean_eq = x - std_eq * z elif dist.lower() == 'gumbel min': z_aux = sc.stats.gumbel_l.cdf(x, loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) z = sc.stats.norm.ppf(z_aux, loc=0, scale=1) num = sc.stats.norm.pdf(z, loc=0, scale=1) den = sc.stats.gumbel_l.pdf(x, loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) std_eq = num / den mean_eq = x - std_eq * z elif dist.lower() == 'triangular': z_aux = sc.stats.triang.cdf(x, c=parameters_scipy['c'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) z = sc.stats.norm.ppf(z_aux, loc=0, scale=1) num = sc.stats.norm.pdf(z, loc=0, scale=1) den = sc.stats.triang.pdf(x, c=parameters_scipy['c'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) std_eq = num / den mean_eq = x - std_eq * z elif dist.lower() == 'gamma': z_aux = sc.stats.gamma.cdf(x, a=parameters_scipy['a'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) z = sc.stats.norm.ppf(z_aux, loc=0, scale=1) num = sc.stats.norm.pdf(z, loc=0, scale=1) den = sc.stats.gamma.pdf(x, a=parameters_scipy['a'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) std_eq = num / den mean_eq = x - std_eq * z elif dist.lower() == 'weibull min': z_aux = sc.stats.weibull_min.cdf(x, c=parameters_scipy['c'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) z = sc.stats.norm.ppf(z_aux, loc=0, scale=1) num = sc.stats.norm.pdf(z, loc=0, scale=1) den = sc.stats.weibull_min.pdf(x, c=parameters_scipy['c'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) std_eq = num / den mean_eq = x - std_eq * z return mean_eq, std_eq
[docs] def random_sampling(dist: str, parameters: dict, method: str, n_samples: int) -> list: """ Generates random samples from a specified distribution. :param dist: Type of distribution. Supported values: 'uniform', 'normal', 'lognormal', 'gumbel max', 'gumbel min', 'triangular', or 'gamma'. :param parameters: Original distribution parameters. (a) 'uniform': keys 'min' and 'max', (b) 'normal': keys 'mean' and 'std', (c) 'lognormal': keys 'mean' and 'std', (d) 'gumbel max': keys 'mean' and 'std', (e) 'gumbel min': keys 'mean' and 'std', (f) 'triangular': keys 'min', 'mode' and 'max', or (g) 'gamma': keys 'mean' and 'std'. :param method: Sampling method. Supported values: 'lhs' (Latin Hypercube Sampling), 'mcs' (Crude Monte Carlo Sampling) or 'sobol' (Sobol Sampling). :param n_samples: Number of samples. For Sobol sequences, this variable represents the exponent "m" (n = 2^m). :return: Random samples. Example ============== >>> # pip install -U parepy-toolbox >>> from parepy_toolbox import random_sampling >>> parameters = {'mean': 10, 'std': 2} >>> samples = random_sampling(dist='normal', parameters=parameters,method='lhs', n_samples=100) >>> print(samples[:10]) """ # Convert user parameters to scipy.stats format parameters_scipy = convert_params_to_scipy(dist, parameters) # Generate random samples based on the specified distribution and method if dist.lower() == 'uniform': if method.lower() == 'mcs': rv = sc.stats.uniform(loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) x = list(rv.rvs(size=n_samples)) elif method.lower() == 'lhs': sampler = sc.stats.qmc.LatinHypercube(d=1) samples = sampler.random(n=n_samples) x = [sc.stats.uniform.ppf(i, loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] elif method.lower() == 'sobol': sampler = sc.stats.qmc.Sobol(d=1) samples = sampler.random_base2(m=n_samples) x = [sc.stats.uniform.ppf(i, loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] elif dist.lower() == 'normal': if method.lower() == 'mcs': rv = sc.stats.norm(loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) x = list(rv.rvs(size=n_samples)) elif method.lower() == 'lhs': sampler = sc.stats.qmc.LatinHypercube(d=1) samples = sampler.random(n=n_samples) x = [sc.stats.norm.ppf(i, loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] elif method.lower() == 'sobol': sampler = sc.stats.qmc.Sobol(d=1) samples = sampler.random_base2(m=n_samples) x = [sc.stats.norm.ppf(i, loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] elif dist.lower() == 'lognormal': if method.lower() == 'mcs': rv = sc.stats.lognorm(s=parameters_scipy['s'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) x = list(rv.rvs(size=n_samples)) elif method.lower() == 'lhs': sampler = sc.stats.qmc.LatinHypercube(d=1) samples = sampler.random(n=n_samples) x = [sc.stats.lognorm.ppf(i, s=parameters_scipy['s'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] elif method.lower() == 'sobol': sampler = sc.stats.qmc.Sobol(d=1) samples = sampler.random_base2(m=n_samples) x = [sc.stats.lognorm.ppf(i, s=parameters_scipy['s'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] elif dist.lower() == 'gumbel max': if method.lower() == 'mcs': rv = sc.stats.gumbel_r(loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) x = list(rv.rvs(size=n_samples)) elif method.lower() == 'lhs': sampler = sc.stats.qmc.LatinHypercube(d=1) samples = sampler.random(n=n_samples) x = [sc.stats.gumbel_r.ppf(i, loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] elif method.lower() == 'sobol': sampler = sc.stats.qmc.Sobol(d=1) samples = sampler.random_base2(m=n_samples) x = [sc.stats.gumbel_r.ppf(i, loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] elif dist.lower() == 'gumbel min': if method.lower() == 'mcs': rv = sc.stats.gumbel_l(loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) x = list(rv.rvs(size=n_samples)) elif method.lower() == 'lhs': sampler = sc.stats.qmc.LatinHypercube(d=1) samples = sampler.random(n=n_samples) x = [sc.stats.gumbel_l.ppf(i, loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] elif method.lower() == 'sobol': sampler = sc.stats.qmc.Sobol(d=1) samples = sampler.random_base2(m=n_samples) x = [sc.stats.gumbel_l.ppf(i, loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] elif dist.lower() == 'triangular': if method.lower() == 'mcs': rv = sc.stats.triang(c=parameters_scipy['c'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) x = list(rv.rvs(size=n_samples)) elif method.lower() == 'lhs': sampler = sc.stats.qmc.LatinHypercube(d=1) samples = sampler.random(n=n_samples) x = [sc.stats.triang.ppf(i, c=parameters_scipy['c'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] elif method.lower() == 'sobol': sampler = sc.stats.qmc.Sobol(d=1) samples = sampler.random_base2(m=n_samples) x = [sc.stats.triang.ppf(i, c=parameters_scipy['c'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] elif dist.lower() == 'gamma': if method.lower() == 'mcs': rv = sc.stats.gamma(a=parameters_scipy['a'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) x = list(rv.rvs(size=n_samples)) elif method.lower() == 'lhs': sampler = sc.stats.qmc.LatinHypercube(d=1) samples = sampler.random(n=n_samples) x = [sc.stats.gamma.ppf(i, a=parameters_scipy['a'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] elif method.lower() == 'sobol': sampler = sc.stats.qmc.Sobol(d=1) samples = sampler.random_base2(m=n_samples) x = [sc.stats.gamma.ppf(i, a=parameters_scipy['a'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] elif dist.lower() == 'weibull min': if method.lower() == 'mcs': rv = sc.stats.weibull_min(c=parameters_scipy['c'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) x = list(rv.rvs(size=n_samples)) elif method.lower() == 'lhs': sampler = sc.stats.qmc.LatinHypercube(d=1) samples = sampler.random(n=n_samples) x = [sc.stats.weibull_min.ppf(i, c=parameters_scipy['c'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] elif method.lower() == 'sobol': sampler = sc.stats.qmc.Sobol(d=1) samples = sampler.random_base2(m=n_samples) x = [sc.stats.weibull_min.ppf(i, c=parameters_scipy['c'], loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) for i in samples.flatten()] return x
[docs] def random_sampling_statistcs(dist: str, parameters: dict, values: list): """ """ # Convert user parameters to scipy.stats format parameters_scipy = convert_params_to_scipy(dist, parameters) if dist.lower() == 'uniform': rv = sc.stats.uniform(loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) pdf = rv.pdf(values) # cdf = rv.cdf(value) # icdf = rv.ppf(value) elif dist.lower() == 'normal': rv = sc.stats.norm(loc=parameters_scipy['loc'], scale=parameters_scipy['scale']) pdf = rv.pdf(values) # cdf = rv.cdf(value) # icdf = rv.ppf(value) return pdf.tolist() # if #, cdf, icdf
# def crude_sampling_zero_one(n_samples: int, seed: Optional[int] = None) -> list: # """ # Generates a uniform sampling between 0 and 1. # :param n_samples: Number of samples. # :param seed: Seed for reproducible random number generation. If None (default), the results are non-repeatable. # :return: Random samples. # """ # rng = np.random.default_rng(seed=seed) # return rng.random(n_samples).tolist() # def lhs_sampling_zero_one(n_samples: int, dimension: int, seed: Optional[int] = None) -> np.ndarray: # """ # Generates a uniform sampling between 0 and 1 using the Latin Hypercube Sampling algorithm. # :param n_samples: Number of samples. # :param dimension: Number of dimensions. # :param seed: Seed for reproducible random number generation. If None (default), the results are non-repeatable. # :return: Random samples. # # Theory: # Latin hypercube sampling is a stratified sampling technique that produces random numbers in terms of the marginal CDF of a random input variable. # ### PDF # $$ # f(x) = \begin{cases} # \frac{1}{b-a} & \text{se } a \leq x \leq b \\ # 0 & \text{caso contrário} # \end{cases} # $$ # ### CDF # $$ # F(x) = \begin{cases} # 0 & \text{se } x < a \\ # \frac{x-a}{b-a} & \text{se } a \leq x \leq b \\ # 1 & \text{se } x > b # \end{cases} # $$ # """ # r = np.zeros((n_samples, dimension)) # p = np.zeros((n_samples, dimension)) # original_ids = [i for i in range(1, n_samples+1)] # if seed is not None: # x = crude_sampling_zero_one(n_samples * dimension, seed) # else: # x = crude_sampling_zero_one(n_samples * dimension) # for i in range(dimension): # perms = original_ids.copy() # r[:, i] = x[:n_samples] # del x[:n_samples] # rng = np.random.default_rng(seed=seed) # rng.shuffle(perms) # p[:, i] = perms.copy() # u = (p - r) * (1 / n_samples) # return u # def uniform_sampling(parameters: dict, method: str, n_samples: int, seed: Optional[int] = None) -> list: # """ # Generates a uniform sampling between a minimum (a) and maximum (b) value. # :param parameters: Distribution parameters. (a) key 'min': Minimum value. (b) key 'max': Maximum value. # :param method: Sampling method. Supported values: 'lhs' (Latin Hypercube Sampling) or 'mcs' (Crude Monte Carlo Sampling). # :param n_samples: Number of samples. # :param seed: Seed for reproducible random number generation. If None (default), the results are non-repeatable. # :return: Random samples. # """ # # Random uniform sampling between 0 and 1 # if method.lower() == 'mcs': # if seed is not None: # u_aux = crude_sampling_zero_one(n_samples, seed) # elif seed is None: # u_aux = crude_sampling_zero_one(n_samples) # elif method.lower() == 'lhs': # if seed is not None: # u_aux = lhs_sampling_zero_one(n_samples, 1, seed).flatten() # elif seed is None: # u_aux = lhs_sampling_zero_one(n_samples, 1).flatten() # # PDF parameters and generation of samples # a = parameters['min'] # b = parameters['max'] # u = [float(a + (b - a) * i) for i in u_aux] # return u # def normal_sampling(parameters: dict, method: str, n_samples: int, seed: int=None) -> list: # """ # Generates a normal (Gaussian) sampling with specified mean (mu) and standard deviation (sigma). # :param parameters: Dictionary of parameters, including: # - 'mu': Mean of the normal distribution. # - 'sigma': Standard deviation of the normal distribution. # :param method: Sampling method. Supported values: 'lhs' (Latin Hypercube Sampling) or 'mcs' (Crude Monte Carlo Sampling). # :param n_samples: Number of samples. # :param seed: Seed for random number generation. Default is None for a random seed. # :return: List of random samples. # """ # # Random uniform sampling between 0 and 1 # if method.lower() == 'mcs': # if seed is not None: # u_aux1 = crude_sampling_zero_one(n_samples, seed) # u_aux2 = crude_sampling_zero_one(n_samples, seed+1) # elif seed is None: # u_aux1 = crude_sampling_zero_one(n_samples) # u_aux2 = crude_sampling_zero_one(n_samples) # elif method.lower() == 'lhs': # if seed is not None: # u_aux1 = lhs_sampling_zero_one(n_samples, 2, seed) # elif seed is None: # u_aux1 = lhs_sampling_zero_one(n_samples, 2) # # PDF parameters and generation of samples # mean = parameters['mean'] # std = parameters['sigma'] # u = [] # for i in range(n_samples): # if method.lower() == 'lhs': # z = float(np.sqrt(-2 * np.log(u_aux1[i, 0])) * np.cos(2 * np.pi * u_aux1[i, 1])) # elif method.lower() == 'mcs': # z = float(np.sqrt(-2 * np.log(u_aux1[i])) * np.cos(2 * np.pi * u_aux2[i])) # u.append(mean + std * z) # return u # def corr_normal_sampling(parameters_b: dict, parameters_g: dict, pho_gb: float, method: str, n_samples: int, seed: int=None) -> list: # """ # Generates a normal (Gaussian) sampling with specified mean (mu) and standard deviation (sigma). # Variable g has a correlation `rho_gb` with b. # :param parameters: Dictionary of parameters, including: # - 'mu': Mean of the normal distribution. # - 'sigma': Standard deviation of the normal distribution. # :param method: Sampling method. Supported values: 'lhs' (Latin Hypercube Sampling) or 'mcs' (Crude Monte Carlo Sampling). # :param n_samples: Number of samples. # :param seed: Seed for random number generation. Use None for a random seed. # :return: List of random samples. # """ # # Random uniform sampling between 0 and 1 # if method.lower() == 'mcs': # if seed is not None: # u_aux1 = crude_sampling_zero_one(n_samples, seed) # u_aux2 = crude_sampling_zero_one(n_samples, seed+1) # elif seed is None: # u_aux1 = crude_sampling_zero_one(n_samples) # u_aux2 = crude_sampling_zero_one(n_samples) # elif method.lower() == 'lhs': # if seed is not None: # u_aux1 = lhs_sampling_zero_one(n_samples, 2, seed) # elif seed is None: # u_aux1 = lhs_sampling_zero_one(n_samples, 2) # # PDF parameters and generation of samples # mean_b = parameters_b['mean'] # std_b = parameters_b['sigma'] # mean_g = parameters_g['mean'] # std_g = parameters_g['sigma'] # b = [] # g = [] # for i in range(n_samples): # if method.lower() == 'lhs': # z_1 = float(np.sqrt(-2 * np.log(u_aux1[i, 0])) * np.cos(2 * np.pi * u_aux1[i, 1])) # z_2 = float(np.sqrt(-2 * np.log(u_aux1[i, 0])) * np.sin(2 * np.pi * u_aux1[i, 1])) # elif method.lower() == 'mcs': # z_1 = float(np.sqrt(-2 * np.log(u_aux1[i])) * np.cos(2 * np.pi * u_aux2[i])) # z_2 = float(np.sqrt(-2 * np.log(u_aux1[i])) * np.sin(2 * np.pi * u_aux2[i])) # b.append(mean_b + std_b * z_1) # g.append(mean_g + std_g * (pho_gb * z_1 + z_2 * np.sqrt(1 - pho_gb ** 2))) # return b, g # def lognormal_sampling(parameters: dict, method: str, n_samples: int, seed: int=None) -> list: # """ # Generates a log-normal sampling with specified mean and standard deviation. # :param parameters: Dictionary of parameters, including: # - 'mu': Mean of the underlying normal distribution. # - 'sigma': Standard deviation of the underlying normal distribution. # :param method: Sampling method. Supported values: 'lhs' (Latin Hypercube Sampling) or 'mcs' (Crude Monte Carlo Sampling). # :param n_samples: Number of samples. # :param seed: Seed for random number generation. # :return: List of random samples. # """ # # Random uniform sampling between 0 and 1 # if method.lower() == 'mcs': # if seed is not None: # u_aux1 = crude_sampling_zero_one(n_samples, seed) # u_aux2 = crude_sampling_zero_one(n_samples, seed+1) # elif seed is None: # u_aux1 = crude_sampling_zero_one(n_samples) # u_aux2 = crude_sampling_zero_one(n_samples) # elif method.lower() == 'lhs': # if seed is not None: # u_aux1 = lhs_sampling_zero_one(n_samples, 2, seed) # elif seed is None: # u_aux1 = lhs_sampling_zero_one(n_samples, 2) # # PDF parameters and generation of samples # mean = parameters['mean'] # std = parameters['sigma'] # epsilon = np.sqrt(np.log(1 + (std/mean)**2)) # lambdaa = np.log(mean) - 0.5 * epsilon**2 # u = [] # for i in range(n_samples): # if method.lower() == 'lhs': # z = float(np.sqrt(-2 * np.log(u_aux1[i, 0])) * np.cos(2 * np.pi * u_aux1[i, 1])) # elif method.lower() == 'mcs': # z = float(np.sqrt(-2 * np.log(u_aux1[i])) * np.cos(2 * np.pi * u_aux2[i])) # u.append(np.exp(lambdaa + epsilon * z)) # return u # def gumbel_max_sampling(parameters: dict, method: str, n_samples: int, seed: int=None) -> list: # """ # Generates a Gumbel maximum distribution with specified mean and standard deviation. # :param parameters: Dictionary of parameters, including: # - 'mu': Mean of the Gumbel distribution. # - 'sigma': Standard deviation of the Gumbel distribution. # :param method: Sampling method. Supported values: 'lhs' (Latin Hypercube Sampling) or 'mcs' (Crude Monte Carlo Sampling). # :param n_samples: Number of samples. # :param seed: Seed for random number generation. # :return: List of random samples. # """ # # Random uniform sampling between 0 and 1 # if method.lower() == 'mcs': # if seed is not None: # u_aux = crude_sampling_zero_one(n_samples, seed) # elif seed is None: # u_aux = crude_sampling_zero_one(n_samples) # elif method.lower() == 'lhs': # if seed is not None: # u_aux = lhs_sampling_zero_one(n_samples, 1, seed).flatten() # elif seed is None: # u_aux = lhs_sampling_zero_one(n_samples, 1).flatten() # # PDF parameters and generation of samples # mean = parameters['mean'] # std = parameters['sigma'] # gamma = 0.577215665 # beta = np.pi / (np.sqrt(6) * std) # alpha = mean - gamma / beta # u = [] # for i in range(n_samples): # u.append(alpha - (1 / beta) * np.log(-np.log(u_aux[i]))) # return u # def gumbel_min_sampling(parameters: dict, method: str, n_samples: int, seed: int=None) -> list: # """ # Generates a Gumbel minimum distribution with specified mean and standard deviation. # :param parameters: Dictionary of parameters, including: # - 'mu': Mean of the Gumbel distribution. # - 'sigma': Standard deviation of the Gumbel distribution. # :param method: Sampling method. Supported values: 'lhs' (Latin Hypercube Sampling) or 'mcs' (Crude Monte Carlo Sampling). # :param n_samples: Number of samples. # :param seed: Seed for random number generation. # :return: List of random samples. # """ # # Random uniform sampling between 0 and 1 # if method.lower() == 'mcs': # if seed is not None: # u_aux = crude_sampling_zero_one(n_samples, seed) # elif seed is None: # u_aux = crude_sampling_zero_one(n_samples) # elif method.lower() == 'lhs': # if seed is not None: # u_aux = lhs_sampling_zero_one(n_samples, 1, seed).flatten() # elif seed is None: # u_aux = lhs_sampling_zero_one(n_samples, 1).flatten() # # PDF parameters and generation of samples # mean = parameters['mean'] # std = parameters['sigma'] # gamma = 0.577215665 # beta = np.pi / (np.sqrt(6) * std) # alpha = mean + gamma / beta # u = [] # for i in range(n_samples): # u.append(alpha + (1 / beta) * np.log(-np.log(1 - u_aux[i]))) # return u # def triangular_sampling(parameters: dict, method: str, n_samples: int, seed: int=None) -> list: # """ # Generates a triangular sampling with minimum a, mode c, and maximum b. # :param parameters: Dictionary of parameters, including: # - 'a': Minimum value of the distribution. # - 'c': Mode (most likely value) of the distribution. # - 'b': Maximum value of the distribution. # :param method: Sampling method. Supported values: 'lhs' (Latin Hypercube Sampling) or 'mcs' (Crude Monte Carlo Sampling). # :param n_samples: Number of samples. # :param seed: Seed for random number generation. # :return: List of random samples. # """ # # Random uniform sampling between 0 and 1 # if method.lower() == 'mcs': # if seed is not None: # u_aux = crude_sampling_zero_one(n_samples, seed) # elif seed is None: # u_aux = crude_sampling_zero_one(n_samples) # elif method.lower() == 'lhs': # if seed is not None: # u_aux = lhs_sampling_zero_one(n_samples, 1, seed).flatten() # elif seed is None: # u_aux = lhs_sampling_zero_one(n_samples, 1).flatten() # # PDF parameters and generation of samples # a = parameters['min'] # c = parameters['mode'] # b = parameters['max'] # u = [] # for i in range(n_samples): # criteria = (c - a) / (b - a) # if u_aux[i] < criteria: # u.append(a + np.sqrt(u_aux[i] * (b - a) * (c - a))) # else: # u.append(b - np.sqrt((1 - u_aux[i]) * (b - a) * (b - c))) # return u # def cdf_gumbel_max(x: float, u: float, beta: float) -> float: # """ # Calculates the cumulative distribution function (CDF) of the Maximum Gumbel distribution. # :param x: Input value for which the CDF will be calculated. # :param u: Location parameter (mode) of the Maximum Gumbel distribution. # :param beta: Scale parameter of the Maximum Gumbel distribution. # :return: Value of the CDF at point x. # """ # fx = np.exp(-np.exp((- beta * (x - u)))) # return fx # def pdf_gumbel_max(x: float, u: float, beta: float) -> float: # """ # Calculates the probability density function (PDF) of the Maximum Gumbel distribution. # :param x: Input value for which the PDF will be calculated. # :param u: Location parameter (mode) of the Maximum Gumbel distribution. # :param beta: Scale parameter of the Maximum Gumbel distribution. # :return: Value of the PDF at point x. # """ # fx = beta * np.exp((- beta * (x - u))) - np.exp((- beta * (x - u))) # return fx # def cdf_gumbel_min(x: float, u: float, beta: float) -> float: # """ # Calculates the cumulative distribution function (CDF) of the Minimum Gumbel distribution. # :param x: Input value for which the CDF will be calculated. # :param u: Location parameter (mode) of the Minimum Gumbel distribution. # :param beta: Scale parameter of the Minimum Gumbel distribution. # :return: Value of the CDF at point x. # """ # fx = 1 - np.exp(- np.exp((beta * (x - u)))) # return fx # def pdf_gumbel_min(x: float, u: float, beta: float) -> float: # """ # Calculates the probability density function (PDF) of the Minimum Gumbel distribution. # :param x: Input value for which the PDF will be calculated. # :param u: Location parameter (mode) of the Minimum Gumbel distribution. # :param beta: Scale parameter of the Minimum Gumbel distribution. # :return: Value of the PDF at point x. # """ # fx = beta * np.exp((beta * (x - u))) - np.exp(beta * (x - u)) # return fx # def cdf_normal(x: float, u: float, sigma: float) -> float: # """ # Calculates the cumulative distribution function (CDF) of the Normal distribution. # :param x: Input value for which the CDF will be calculated. # :param u: Mean (location) of the Normal distribution. # :param sigma: Standard deviation (scale) of the Normal distribution. # :return: Value of the CDF at point x. # """ # fx = norm.cdf(x, loc=u, scale=sigma) # return fx # def pdf_normal(x: float, u: float, sigma: float) -> float: # """ # Calculates the probability density function (PDF) of the Normal distribution. # :param x: Input value for which the PDF will be calculated. # :param u: Mean (location) of the Normal distribution. # :param sigma: Standard deviation (scale) of the Normal distribution. # :return: Value of the PDF at point x. # """ # fx = norm.pdf(x, loc=u, scale=sigma) # return fx # def log_normal(x: float, lambdaa: float, epsilon: float) -> tuple[float, float]: # """ # Calculates the location (u) and scale (sigma) parameters for a Log-Normal distribution. # :param x: Input value. # :param lambdaa: Shape parameter of the Log-Normal distribution. # :param epsilon: Scale parameter of the Log-Normal distribution. # :return: Tuple containing: # - u: Location parameter. # - sigma: Scale parameter. # """ # loc = x * (1 - np.log(x) + lambdaa) # sigma = x * epsilon # return loc, sigma # def non_normal_approach_normal(x, dist, params): # """ # Converts a non-normal distribution to an equivalent normal distribution. # :param x: Random variable. # :param dist: Type of distribution. Supported values: 'gumbel max', 'gumbel min', 'lognormal'. # :param params: Dictionary of distribution parameters, depending on the selected distribution type. # - For 'gumbel max' or 'gumbel min': {'mu': location, 'sigma': scale} # - For 'lognormal': {'lambda': shape, 'epsilon': scale} # :return: Tuple containing: # - mu_t: Mean of the equivalent normal distribution. # - sigma_t: Standard deviation of the equivalent normal distribution. # """ # if dist == 'gumbel max': # u = params.get('u') # beta = params.get('beta') # cdf_x = cdf_gumbel_max(x, u, beta) # pdf_temp = pdf_gumbel_max(x, u, beta) # elif dist == 'gumbel min': # u = params.get('u') # beta = params.get('beta') # cdf_x = cdf_gumbel_min(x, u, beta) # pdf_temp = pdf_gumbel_min(x, u, beta) # if dist == 'lognormal': # epsilon = params.get('epsilon') # lambdaa = params.get('lambda') # loc_eq, sigma_eq = log_normal(x, lambdaa, epsilon) # else: # icdf = norm.ppf(cdf_x, loc=0, scale=1) # sigma_eq = norm.pdf(icdf, loc=0, scale=1) / pdf_temp # loc_eq = x - sigma_eq * icdf # return float(loc_eq), float(sigma_eq)