Source code for SALib.test_functions.Sobol_G

import numpy as np


# Non-monotonic Sobol G Function (8 parameters)
# First-order indices:
# x1: 0.7165
# x2: 0.1791
# x3: 0.0237
# x4: 0.0072
# x5-x8: 0.0001
[docs] def evaluate(values, a=None, delta=None, alpha=None): """Modified Sobol G-function. Reverts to original Sobol G-function if delta and alpha are not given. .. [1] Saltelli, A., Annoni, P., Azzini, I., Campolongo, F., Ratto, M., Tarantola, S., 2010. Variance based sensitivity analysis of model output. Design and estimator for the total sensitivity index. Computer Physics Communications 181, 259–270. https://doi.org/10.1016/j.cpc.2009.09.018 Parameters ---------- values : numpy.ndarray input variables a : numpy.ndarray parameter values delta : numpy.ndarray shift parameters alpha : numpy.ndarray curvature parameters Returns ------- Y : Result of G-function """ if type(values) != np.ndarray: raise TypeError("The argument `values` must be a numpy ndarray") if a is None: a = np.array([0, 1, 4.5, 9, 99, 99, 99, 99]) if delta is None: delta = np.zeros_like(a) else: if not isinstance(delta, np.ndarray): raise TypeError("The argument `delta` must be given as a numpy ndarray") delta_inbetween = delta[(delta < 0) | (delta > 1)] if delta_inbetween.any(): raise ValueError( "Sobol G function called with delta values less than zero or" " greater than one" ) if alpha is None: alpha = np.ones_like(a) else: if not isinstance(alpha, np.ndarray): raise TypeError("The argument `alpha` must be given as a numpy ndarray") alpha_gto = alpha <= 0.0 if alpha_gto.any(): raise ValueError( "Sobol G function called with alpha values less than or equal to zero" ) ltz = values < 0 gto = values > 1 if ltz.any(): raise ValueError("Sobol G function called with values less than zero") elif gto.any(): raise ValueError("Sobol G function called with values greater than one") Y = np.ones([values.shape[0]]) for i, row in enumerate(values): shift_of_x = row + delta integral = np.modf(shift_of_x)[1] mod_x = shift_of_x - integral temp_y = np.abs(2 * mod_x - 1) ** alpha y_elements = ((1 + alpha) * temp_y + a) / (1 + a) Y[i] = np.prod(y_elements) return Y
def _partial_first_order_variance(a=None, alpha=None): if a is None: a = [0, 1, 4.5, 9, 99, 99, 99, 99] if alpha is None: alpha = np.ones_like(a) a = np.array(a) return np.divide((alpha**2), np.multiply((1 + 2 * alpha), np.square(1 + a))) def _total_variance(a=None, alpha=None): if a is None: a = [0, 1, 4.5, 9, 99, 99, 99, 99] if alpha is None: alpha = np.ones_like(a) a = np.array(a) return np.add(-1, np.product(1 + _partial_first_order_variance(a, alpha), axis=0))
[docs] def sensitivity_index(a, alpha=None): a = np.array(a) return np.divide(_partial_first_order_variance(a, alpha), _total_variance(a, alpha))
[docs] def total_sensitivity_index(a, alpha=None): a = np.array(a) pv = _partial_first_order_variance(a, alpha) tv = _total_variance(a, alpha) product_pv = np.product(1 + pv, axis=0) return np.divide(pv * np.divide(product_pv, 1 + pv.T), tv)