def analyze(problem, X, Y, second_order=False, print_to_console=False): """Perform a fractional factorial analysis Returns a dictionary with keys 'ME' (main effect) and 'IE' (interaction effect). The techniques bulks out the number of parameters with dummy parameters to the nearest 2**n. Any results involving dummy parameters could indicate a problem with the model runs. Arguments --------- problem: dict The problem definition X: numpy.matrix The NumPy matrix containing the model inputs Y: numpy.array The NumPy array containing the model outputs second_order: bool, default=False Include interaction effects print_to_console: bool, default=False Print results directly to console Returns ------- Si: dict A dictionary of sensitivity indices, including main effects ``ME``, and interaction effects ``IE`` (if ``second_order`` is True) Examples -------- >>> X = sample(problem) >>> Y = X[:, 0] + (0.1 * X[:, 1]) + ((1.2 * X[:, 2]) * (0.2 + X[:, 0])) >>> analyze(problem, X, Y, second_order=True, print_to_console=True) """ problem = extend_bounds(problem) num_vars = problem['num_vars'] X = generate_contrast(problem) main_effect = (1. / (2 * num_vars)) * np.dot(Y, X) Si = dict((k, [None] * num_vars) for k in ['names', 'ME']) Si['ME'] = main_effect Si['names'] = problem['names'] if print_to_console: print("Parameter ME") for j in range(num_vars): print("%s %f" % (problem['names'][j], Si['ME'][j])) if second_order == True: interaction_names, interaction_effects = interactions(problem, Y, print_to_console) Si['names'].append(interaction_names) Si['IE'] = interaction_effects return Si
def analyze(problem, X, Y, second_order=False, print_to_console=False): problem = extend_bounds(problem) num_vars = problem['num_vars'] X = generate_contrast(problem) main_effect = (1. / (2 * num_vars)) * np.dot(Y, X) Si = dict((k, [None] * num_vars) for k in ['names', 'ME']) Si['ME'] = main_effect Si['names'] = problem['names'] if print_to_console: print("Parameter ME") for j in range(num_vars): print("%s %f" % (problem['names'][j], Si['ME'][j])) if second_order == True: interaction_names, interaction_effects = interactions(problem, Y, print_to_console) Si['names'].append(interaction_names) Si['IE'] = interaction_effects return Si
def test_extend_bounds(): problem = { 'bounds': np.repeat([-1, 1], 12).reshape(2, 12).T, 'num_vars': 12, 'names': ["x" + str(x + 1) for x in range(12)] } actual = extend_bounds(problem) expected = { 'names': [ 'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10', 'x11', 'x12', 'dummy_0', 'dummy_1', 'dummy_2', 'dummy_3' ], 'bounds': [ np.array([-1, 1]), np.array([-1, 1]), np.array([-1, 1]), np.array([-1, 1]), np.array([-1, 1]), np.array([-1, 1]), np.array([-1, 1]), np.array([-1, 1]), np.array([-1, 1]), np.array([-1, 1]), np.array([-1, 1]), np.array([-1, 1]), np.array([0, 1]), np.array([0, 1]), np.array([0, 1]), np.array([0, 1]) ], 'num_vars': 16 } assert_equal(actual, expected)
def analyze(problem, X, Y, second_order=False, print_to_console=False, seed=None): """Perform a fractional factorial analysis Returns a dictionary with keys 'ME' (main effect) and 'IE' (interaction effect). The techniques bulks out the number of parameters with dummy parameters to the nearest 2**n. Any results involving dummy parameters could indicate a problem with the model runs. Compatible with --------------- * `ff` Parameters ---------- problem: dict The problem definition X: numpy.matrix The NumPy matrix containing the model inputs Y: numpy.array The NumPy array containing the model outputs second_order: bool, default=False Include interaction effects print_to_console: bool, default=False Print results directly to console Returns ------- Si: dict A dictionary of sensitivity indices, including main effects ``ME``, and interaction effects ``IE`` (if ``second_order`` is True) References ---------- .. [1] Saltelli, A., Ratto, M., Andres, T., Campolongo, F., Cariboni, J., Gatelli, D., Saisana, M., Tarantola, S., 2008. Global Sensitivity Analysis: The Primer. Wiley, West Sussex, U.K. https://dx.doi.org/10.1002/9780470725184 Examples -------- >>> X = sample(problem) >>> Y = X[:, 0] + (0.1 * X[:, 1]) + ((1.2 * X[:, 2]) * (0.2 + X[:, 0])) >>> analyze(problem, X, Y, second_order=True, print_to_console=True) """ if seed: np.random.seed(seed) problem = extend_bounds(problem) num_vars = problem['num_vars'] X = generate_contrast(problem) main_effect = (1. / (2 * num_vars)) * np.dot(Y, X) Si = ResultDict((k, [None] * num_vars) for k in ['names', 'ME']) Si['ME'] = main_effect Si['names'] = problem['names'] if second_order: interaction_names, interaction_effects = interactions(problem, Y) Si['interaction_names'] = interaction_names Si['IE'] = interaction_effects Si.to_df = MethodType(to_df, Si) if print_to_console: for S in Si.to_df(): print(S) return Si