def test_group_sample_fails_with_wrong_G_matrix(): N = 6 num_levels = 4 grid_jump = 2 problem = {'bounds': [[0., 1.], [0., 1.], [0., 1.], [0., 1.]], 'num_vars': 4, 'groups': (list([1, 2, 3, 4]), None)} with raises(TypeError): sample(problem, N, num_levels, grid_jump)
def test_optimal_trajectories_lt_samples(setup_param_file): parameter_file = setup_param_file problem = read_param_file(parameter_file) samples = 10 num_levels = 4 with raises(ValueError): sample(problem, samples, num_levels, optimal_trajectories=samples)
def test_group_sample_fails_with_wrong_G_matrix(): N = 6 num_levels = 4 problem = {'bounds': [[0., 1.], [0., 1.], [0., 1.], [0., 1.]], 'num_vars': 4, 'groups': list([1, 2, 3])} with raises(ValueError) as err: sample(problem, N, num_levels) assert "Groups do not match to number of variables" in str(err)
def test_even_num_levels_no_warning(setup_param_file_with_groups): parameter_file = setup_param_file_with_groups problem = read_param_file(parameter_file) with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("always") # Trigger a warning. sample(problem, 10, num_levels=4) # Verify some things assert len(w) == 0
def test_optimal_trajectories_lt_samples(): parameter_file = setup_param_file() problem = read_param_file(parameter_file) samples = 10 num_levels = 4 grid_jump = 2 sample(problem, samples, num_levels, grid_jump, \ optimal_trajectories=samples)
def test_group_sample_fails_with_wrong_G_matrix(): N = 6 num_levels = 4 problem = {'bounds': [[0., 1.], [0., 1.], [0., 1.], [0., 1.]], 'num_vars': 4, 'groups': list([1, 2, 3])} with raises(ValueError) as err: sample(problem, N, num_levels) assert "Groups do not match to number of variables" in str(err.value)
def test_optimal_trajectories_lt_10(setup_param_file): parameter_file = setup_param_file problem = read_param_file(parameter_file) samples = 10 num_levels = 4 grid_jump = 2 optimal_trajectories = 11 with raises(ValueError): sample(problem, samples, num_levels, grid_jump, optimal_trajectories=optimal_trajectories)
def test_odd_num_levels_raises_warning(setup_param_file_with_groups): parameter_file = setup_param_file_with_groups problem = read_param_file(parameter_file) with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("always") # Trigger a warning. sample(problem, 10, num_levels=3) # Verify some things assert len(w) == 1 assert issubclass(w[-1].category, UserWarning) assert "num_levels should be an even number, sample may be biased" in str(w[-1].message)
def test_group_sample_fails_with_wrong_G_matrix(): N = 6 num_levels = 4 problem = { 'bounds': [[0., 1.], [0., 1.], [0., 1.], [0., 1.]], 'num_vars': 4, 'groups': list([1, 2, 3]) } expected_err = ".*Groups do not match to number of variables.*" with raises(ValueError, match=expected_err): sample(problem, N, num_levels)
def __init__(self, param, N=12, num_levels=4): """ :param dict param: Uncertain parameters for the sensitivity analysis {"parameter name": [lower bound, upper bound]} :param int N: The number of trajectories to generate (recommended 10-20) :param int num_levels: The number of grid levels (default 4) """ self.idf = None self.num_levels = num_levels self.problem = {'num_vars': len(param), 'names': [], 'bounds': []} self.problem['bounds'] = param['bounds'] self.problem['num_vars'] = param['num_vars'] self.objects = param['obj_id'] for obj in self.objects: # TODO find longest string match in list instead of using obj[0] self.problem['names'].append(obj[0]) ''' for k, v in param.items(): self.problem['names'].append(k) range = v['range'] self.problem['bounds'].append(range) ''' self.X = sample(self.problem, N, num_levels) self.y = None self.si = None
def main(config): processed_data_path = config['paths']['data'] results_path = config['paths']['output'] # Set up problem for sensitivity analysis problem = { 'num_vars': 2, 'names': ['cost_uncertainty_parameter', 'damage_uncertainty_parameter'], 'bounds': [[0.0, 1.0], [0.0, 1.0]] } # And create parameter values param_values = morris.sample(problem, 10, num_levels=4, optimal_trajectories=8, local_optimization=False) param_values = list(set([(p[0], p[1]) for p in param_values])) with open("parameter_combinations.txt", "w+") as f: # f.write("parameter_set cost_uncertainty_parameter damage_uncertainty_parameter\n") for p in range(len(param_values)): f.write(f"{p},{param_values[p][0]},{param_values[p][1]}\n") f.close() num_blocks = len(param_values) """Next we call the failure analysis script and loop through the falure scenarios """ args = [ "parallel", "-j", str(num_blocks), "--colsep", ",", "-a", "parameter_combinations.txt", "python", "direct_damage_calculations_parallel.py", "{}" ] print(args) subprocess.run(args)
def test_regression_morris_groups_brute_optim(self, set_seed): set_seed param_file = 'src/SALib/test_functions/params/Ishigami_groups.txt' problem = read_param_file(param_file) param_values = sample(problem=problem, N=50, num_levels=4, optimal_trajectories=6, local_optimization=False) Y = Ishigami.evaluate(param_values) Si = morris.analyze(problem, param_values, Y, conf_level=0.95, print_to_console=False, num_levels=4) assert_allclose(Si['mu'], [9.786986, np.NaN], atol=0, rtol=1e-5) assert_allclose(Si['sigma'], [6.453729, np.NaN], atol=0, rtol=1e-5) assert_allclose(Si['mu_star'], [9.786986, 7.875], atol=0, rtol=1e-5)
def test_morris_to_df(): params = ['x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8'] problem = { 'num_vars': 8, 'names': params, 'groups': None, 'bounds': [[0.0, 1.0], [0.0, 1.0], [0.0, 1.0], [0.0, 1.0], [0.0, 1.0], [0.0, 1.0], [0.0, 1.0], [0.0, 1.0]] } param_values = morris_sample.sample(problem, N=1000, num_levels=4, optimal_trajectories=None) Y = Sobol_G.evaluate(param_values) Si = morris.analyze(problem, param_values, Y) Si_df = Si.to_df() assert isinstance(Si_df, pd.DataFrame), \ "Morris Si: Expected DataFrame, got {}".format(type(Si_df)) expected_index = set(params) assert set(Si_df.index) == expected_index, "Incorrect index in DataFrame" col_names = ['mu', 'mu_star', 'sigma', 'mu_star_conf'] assert set(Si_df.columns) == set(col_names), \ "Unexpected column names in DataFrame. Expected {}, got {}".format( col_names, Si_df.columns)
def test_regression_morris_optimal(self, set_seed): ''' Tests the use of optimal trajectories with Morris. Uses brute force approach Note that the relative tolerance is set to a very high value (default is 1e-05) due to the coarse nature of the num_levels. ''' set_seed param_file = 'src/SALib/test_functions/params/Ishigami.txt' problem = read_param_file(param_file) param_values = sample(problem=problem, N=20, num_levels=4, optimal_trajectories=9, local_optimization=True) Y = Ishigami.evaluate(param_values) Si = morris.analyze(problem, param_values, Y, conf_level=0.95, print_to_console=False, num_levels=4) assert_allclose(Si['mu_star'], [9.786986e+00, 7.875000e+00, 1.388621], atol=0, rtol=1e-5)
def sample(self): kwargs = { 'num_levels': 4, } kwargs.update(self.kwargs) problem = self.gen_problem_from_data(self.data, self.feature_names) return morris_sampler.sample(problem, N=self.N, **kwargs)
def sample(self): from SALib.sample import morris as morris_sampler kwargs = {"num_levels": 4} kwargs.update(self.kwargs) problem = self.gen_problem_from_data(self.data, self.feature_names) return morris_sampler.sample(problem, N=self.N, **kwargs)
def generate_parameter_set(parameters, scenarios, parameter_range_file='param_range_SA.txt', sample_file='morris_input.txt', num_trajectories=10, num_levels=10, grid_jump=5, optimal_trajectories=None, nboots=5): """ Generate the file with samples for the analysis of Morris. Parameters ---------- parameters: OrderedDict([('name', [min, max])]) Names and variation range of quantitative parameters scenarios: list[tuple(year, variety)] Years and varieties of wheat on which SA is repeated """ # Reset parameter range file open(parameter_range_file, 'w').close() generate_parameter_range_file(parameters=parameters, filename=parameter_range_file) # Generate samples problem = read_param_file(parameter_range_file) for boot in range(nboots): param_values = sample(problem, N=num_trajectories, num_levels=num_levels, grid_jump=grid_jump, optimal_trajectories=optimal_trajectories) # For Method of Morris, save the parameter values in a file (they are needed in the analysis) s_file = sample_file[:-4] + '_boot' + str(boot) + sample_file[-4:] np.savetxt(s_file, param_values, delimiter=' ') # Repeat samples for scenario full_params = [] for scen in scenarios: for i_set, param_set in enumerate(param_values): full_params += [np.insert(param_set, 0, scen).tolist()] # Add boot number full_params = [ np.insert(param_set, 0, boot).tolist() for i_sample, param_set in enumerate(full_params) ] # Add indices of sample full_params = [ np.insert(param_set, 0, i_sample).tolist() for i_sample, param_set in enumerate(full_params) ] # Save full parameter values np.savetxt(s_file[:-4] + '_full' + s_file[-4:], full_params, delimiter=' ')
def fit(self, X, y): """ Fits the regressor to the data `(X, y)` and performs a sensitivity analysis on the result of the regression. :param X: Training data :param y: Target values :return: `self` """ from numpy import argpartition N = len(X[0]) if (self.domain is None) or (self.probs is None): self._avg_fucn(X, y) if self.regressor is None: from sklearn.svm import SVR self.regressor = SVR() self.regressor.fit(self.domain, self.probs) bounds = [[ min(self.domain[:, idx]) - self.margin, max(self.domain[:, idx]) + self.margin ] for idx in range(N)] problem = dict(num_vars=N, names=['x%d' % idx for idx in range(N)], bounds=bounds) res = [] if self.method == 'sobol': from SALib.sample import saltelli from SALib.analyze import sobol param_values = saltelli.sample(problem, self.num_smpl) y_ = self.regressor.predict(param_values) res = sobol.analyze(problem, y_)['ST'] self.weights_ = res elif self.method == 'morris': from SALib.sample import morris as mrs from SALib.analyze import morris param_values = mrs.sample(problem, self.num_smpl, num_levels=self.num_levels) y_ = self.regressor.predict(param_values) res = morris.analyze(problem, param_values, y_, num_levels=self.num_levels)['mu_star'] self.weights_ = res elif self.method == 'delta-mmnt': from SALib.sample import latin from SALib.analyze import delta param_values = latin.sample(problem, self.num_smpl) y_ = self.regressor.predict(param_values) res = delta.analyze(problem, param_values, y_, num_resamples=self.num_resmpl)['delta'] self.weights_ = res self.top_features_ = argpartition( res, -self.n_features_to_select)[-self.n_features_to_select:] return self
def generate_parameter_set(parameters, scenarios, parameter_range_file='param_range_SA.txt', sample_file='morris_input.txt', num_trajectories=10, num_levels=10, grid_jump=5, optimal_trajectories=None, nboots=5): """ Generate the file with samples for the analysis of Morris. Parameters ---------- parameters: OrderedDict([('name', [min, max])]) Names and variation range of quantitative parameters scenarios: list[tuple(year, variety)] Years and varieties of wheat on which SA is repeated """ # Reset parameter range file open(parameter_range_file, 'w').close() generate_parameter_range_file(parameters=parameters, filename=parameter_range_file) # Generate samples problem = read_param_file(parameter_range_file) for boot in range(nboots): param_values = sample(problem, N=num_trajectories, num_levels=num_levels, grid_jump=grid_jump, optimal_trajectories=optimal_trajectories) # For Method of Morris, save the parameter values in a file (they are needed in the analysis) s_file = sample_file[:-4] + '_boot' + str(boot) + sample_file[-4:] np.savetxt(s_file, param_values, delimiter=' ') # Repeat samples for scenario full_params = [] for scen in scenarios: for i_set, param_set in enumerate(param_values): full_params += [np.insert(param_set, 0, scen).tolist()] # Add boot number full_params = [np.insert(param_set, 0, boot).tolist() for i_sample, param_set in enumerate(full_params)] # Add indices of sample full_params = [np.insert(param_set, 0, i_sample).tolist() for i_sample, param_set in enumerate(full_params)] # Save full parameter values np.savetxt(s_file[:-4] + '_full' + s_file[-4:], full_params, delimiter=' ')
def morris(): from SALib.analyze import morris from SALib.sample.morris import sample problem = { 'num_vars': 5, 'names': ['HEME', 'K1', 'MPY', 'MPYgu', 'QCC'], 'groups': None, 'bounds': [[.4, .5], [10., 30.], [30., 40.], [15., 25.], [10., 15.]] } parameter_values = sample(problem, N=10, num_levels=4, grid_jump=2, optimal_trajectories=None) parameters = assign_parameters() schedule = get_default_schedule() y_index = np.argmax(o["Curine"]) ys = [] for inputs in parameter_values: for i in range(len(problem["names"])): setattr(parameters, problem["names"][i], inputs[i]) _, __, ___, output = pbpk(parameters, schedule) ys.append(output["Curine"][y_index]) sis = morris.analyze(problem, parameter_values, np.array(ys), conf_level=0.95, print_to_console=True, num_levels=4, grid_jump=2, num_resamples=100) import matplotlib.pyplot as plt from SALib.plotting.morris import horizontal_bar_plot, covariance_plot, sample_histograms fig, (ax1, ax2) = plt.subplots(1, 2) horizontal_bar_plot(ax1, sis, {}, sortby='mu_star', unit=r"mg/g") covariance_plot(ax2, sis, {}, unit=r"mg/g") fig2 = plt.figure() sample_histograms(fig2, parameter_values, problem, {'color': 'y'}) plt.show()
def _sample(*args, **kwargs): self = args[0] N = self.N num_levels = kwargs.get('num_levels', 4) grid_jump = kwargs.get('grid_jump', 2) optimal_trajectories = kwargs.get('optimal_trajectories', None) local_optimization = kwargs.get('local_optimization', False) X = morris_sampler.sample(self.problem, N, num_levels, grid_jump, optimal_trajectories=optimal_trajectories, local_optimization=local_optimization) self.storeKwargs(num_levels=num_levels, grid_jump=grid_jump) return X
def test_regression_morris_vanilla(): param_file = 'SALib/test_functions/params/Ishigami.txt' problem = read_param_file(param_file) param_values = sample(problem=problem, N=5000, \ num_levels=10, grid_jump=5, \ optimal_trajectories=None) Y = Ishigami.evaluate(param_values) Si = morris.analyze(problem, param_values, Y, conf_level=0.95, print_to_console=False, num_levels=10, grid_jump=5) assert_allclose(Si['mu_star'], [8.1, 2.2, 5.4], atol=0, rtol=5e-1)
def _gen_muestrea(símismo, n, ops): if símismo.método == 'sobol': return saltelli.sample(problem=símismo.problema, N=n, **ops) elif símismo.método == 'fast': return fast_sampler.sample(problem=símismo.problema, N=n, **ops) elif símismo.método == 'morris': return morris_muestra.sample(problem=símismo.problema, N=n, **ops) elif símismo.método == 'dmim': return latin.sample(problem=símismo.problema, N=n) elif símismo.método == 'dgsm': return saltelli.sample(problem=símismo.problema, N=n) elif símismo.método == 'ff': return ff_muestra.sample(problem=símismo.problema) else: raise ValueError('Método de análisis de sensibilidad "{}" no reconocido.'.format(símismo.método))
def run_salib_morris(target_parameters, target_output_name, n_trajectories, num_levels, grid_jump, n_processors=cpu_count() - 1): num_vars = len(target_parameters) parameter_names = list(target_parameters.keys()) groups = None bounds = [target_parameters[name] for name in parameter_names] problem = { 'num_vars': num_vars, 'names': parameter_names, 'groups': groups, 'bounds': bounds } parameter_values = sample(problem, N=n_trajectories, num_levels=num_levels, grid_jump=grid_jump, optimal_trajectories=None) ys = None if n_processors > 1: chunks = np.array_split(parameter_values, n_processors) chunks = [(parameter_names, chunk, target_output_name) for chunk in chunks] pool = Pool(n_processors) results = pool.map(hdmpp.generate_outputs, chunks) ys = np.concatenate(results) else: ys = hdmpp.generate_outputs( (parameter_names, parameter_values, target_output_name)) sis = morris.analyze(problem, parameter_values, np.array(ys), conf_level=0.95, print_to_console=False, num_levels=num_levels, grid_jump=grid_jump, num_resamples=100) return problem, parameter_values, sis
def gsa(self, nb_impacts, A_indices, B_indices, number_of_trajectories, progressBar=True, cpus=None, chunk_size=None): ''' Samples the A and B element using Morris method and return the computed impact for the aggregated score and then for each category of impact. ''' self.A_indices = A_indices self.B_indices = B_indices cpus = cpus or multiprocessing.cpu_count() # TODO propose an automatic number_of_trajectories self.samples = ms.sample(self.morris_problem, number_of_trajectories, num_levels=4) if chunk_size: self.chunk_size = chunk_size else: self.chunk_size = max(cpus, number_of_trajectories // 100) pool = multiprocessing.Pool(processes=cpus) if progressBar: bar = pyprind.ProgBar( max(1, math.ceil(len(self.samples) / self.chunk_size))) chunks = [] scores = [[] for i in range(1 + nb_impacts)] # store in 'stores' all the mid-point impact for sample in self.samples: chunks.append(sample) if len(chunks) == self.chunk_size: for i, result_by_impact in enumerate( map(list, zip(*pool.map(self.single_worker, chunks)))): scores[i] += result_by_impact if progressBar: bar.update() chunks = [] if len(chunks): for i, result_by_impact in enumerate( map(list, zip(*pool.map(self.single_worker, chunks)))): scores[i] += result_by_impact if progressBar: bar.update() chunks = [] self.scores = scores return scores
def test_regression_morris_groups(self, set_seed): set_seed param_file = 'src/SALib/test_functions/params/Ishigami_groups.txt' problem = read_param_file(param_file) param_values = sample(problem=problem, N=10000, num_levels=4, optimal_trajectories=None) Y = Ishigami.evaluate(param_values) Si = morris.analyze(problem, param_values, Y, conf_level=0.95, print_to_console=False, num_levels=4) assert_allclose(Si['mu_star'], [7.610322, 10.197014], atol=0, rtol=1e-5)
def generate_samples(model, inputs, kind, N, seed=None, **kwargs): ''' Generate samples for sensitivity analysis using ``SALib``. Parameters ---------- model : :class:`biosteam.Model` Uncertainty model with defined paramters and metrics. inputs : dict A dict generated by :func:`~.sensitivity.define_inputs` to be used for ``SALib``, keys should include "num_vars", "names", and "bounds". kind : str Can be "Morris" (for Morris analysis) or "Saltelli" (for Sobol analysis). N : int The number of trajectories (Morris) or samples. seed : int Seed to generate a random number. Returns ------- samples: array Samples to be used for the indicated sensitivies analyses. See Also -------- `SALib.sample.morris <https://salib.readthedocs.io/en/latest/api.html?highlight=morris#method-of-morris>`_ `SALib.sample.saltelli <https://salib.readthedocs.io/en/latest/api/SALib.sample.html?highlight=saltelli#module-SALib.sample.saltelli>`_ ''' params = model.get_parameters() D = len(params) if kind.capitalize() == 'Morris': sample = morris_sampling.sample(inputs, N=N, seed=seed, **kwargs) for i in range(D): lower = params[i].distribution.lower[0] scale = params[i].distribution.upper[0] - lower sample[:, i] = lower + sample[:, i] * scale return sample elif kind.capitalize() == 'Saltelli': sample = saltelli.sample(inputs, N=N, seed=seed, **kwargs) for i in range(D): sample[:, i] = params[i].distribution.inv(sample[:, i]) return sample else: raise ValueError('kind can only be "Morris" or "Saltelli", ' \ f'not "{kind}".')
def test_regression_morris_vanilla(self, set_seed): """Note that this is a poor estimate of the Ishigami function. """ set_seed param_file = 'src/SALib/test_functions/params/Ishigami.txt' problem = read_param_file(param_file) param_values = sample(problem, 10000, 4, optimal_trajectories=None) Y = Ishigami.evaluate(param_values) Si = morris.analyze(problem, param_values, Y, conf_level=0.95, print_to_console=False, num_levels=4) assert_allclose(Si['mu_star'], [7.536586, 7.875, 6.308785], atol=0, rtol=1e-5)
def test_regression_morris_groups_local_optim(self, set_seed): set_seed param_file = 'src/SALib/test_functions/params/Ishigami_groups.txt' problem = read_param_file(param_file) param_values = sample(problem=problem, N=500, num_levels=4, optimal_trajectories=20, local_optimization=True) Y = Ishigami.evaluate(param_values) Si = morris.analyze(problem, param_values, Y, conf_level=0.95, print_to_console=False, num_levels=4) assert_allclose(Si['mu_star'], [13.95285, 7.875], rtol=1e-5)
def test_regression_morris_optimal(): ''' Tests the use of optimal trajectories with Morris. Note that the relative tolerance is set to a very high value (default is 1e-05) due to the coarse nature of the num_levels and grid_jump. ''' param_file = 'SALib/test_functions/params/Ishigami.txt' problem = read_param_file(param_file) param_values = sample(problem=problem, N=20, \ num_levels=4, grid_jump=2, \ optimal_trajectories=9) Y = Ishigami.evaluate(param_values) Si = morris.analyze(problem, param_values, Y, conf_level=0.95, print_to_console=False, num_levels=4, grid_jump=2) assert_allclose(Si['mu_star'], [8.1, 2.2, 5.4], rtol=10)
def sampleMORRIS(num,num_levels,grid_jump,cz): #read the variable table, "variable" data_set_temp = np.genfromtxt('./variable.csv', skip_header=1, dtype=str, delimiter=',') #generate the data set under cz climate = ['1A','2A','2B','3A','3B','3C','4A','4B','4C','5A','5B','6A','6B','7A','8A'] ind = climate.index(cz) data_set = [] k = 1 for row in data_set_temp: temp = [str(k)] temp.append(row[0])#the measure's name temp.append(row[1])#the argument's name temp.append(float(row[ind+2]))#the minimum value temp.append(float(row[ind+19]))#the maximum value data_set.append(temp) k += 1 names = [] bounds = [] for row in data_set: names.append(row[0]) temp = [] temp.append(row[3]) temp.append(row[4]) bounds.append(temp) #set the variables and ranges of variables problem = { 'num_vars': len(data_set), 'names': names, 'bounds': bounds } #select the samples param_values = morris.sample(problem, num, num_levels, grid_jump) return data_set,problem,param_values
def test_regression_morris_vanilla(self, set_seed): set_seed param_file = 'SALib/test_functions/params/Ishigami.txt' problem = read_param_file(param_file) param_values = sample(problem=problem, N=10000, num_levels=4, grid_jump=2, optimal_trajectories=None) Y = Ishigami.evaluate(param_values) Si = morris.analyze(problem, param_values, Y, conf_level=0.95, print_to_console=False, num_levels=4, grid_jump=2) assert_allclose(Si['mu_star'], [7.701555, 7.875, 6.288788], atol=0, rtol=1e-5)
def sample(self): kwargs = {"num_levels": 4} kwargs.update(self.kwargs) problem = self.gen_problem_from_data(self.data, self.feature_names) return morris_sampler.sample(problem, N=self.N, **kwargs)
problem = read_param_file('../../SALib/test_functions/params/Sobol_G.txt') # or define manually without a parameter file: # problem = { # 'num_vars': 3, # 'names': ['x1', 'x2', 'x3'], # 'groups': None, # 'bounds': [[-3.14159265359, 3.14159265359], # [-3.14159265359, 3.14159265359], # [-3.14159265359, 3.14159265359]] # } # Files with a 4th column for "group name" will be detected automatically, e.g. # param_file = '../../SALib/test_functions/params/Ishigami_groups.txt' # Generate samples param_values = sample(problem, N=1000, num_levels=4, optimal_trajectories=None) # To use optimized trajectories (brute force method), # give an integer value for optimal_trajectories # Run the "model" -- this will happen offline for external models Y = Sobol_G.evaluate(param_values) # Perform the sensitivity analysis using the model output # Specify which column of the output file to analyze (zero-indexed) Si = morris.analyze(problem, param_values, Y, conf_level=0.95, print_to_console=True, num_levels=4, num_resamples=100) # Returns a dictionary with keys 'mu', 'mu_star', 'sigma', and 'mu_star_conf' # e.g. Si['mu_star'] contains the mu* value for each parameter, in the # same order as the parameter file
[0.87,0.97], # inverter efficienct (%) [0.5, 24] # dispatch time - hours of the day in which the energy is dispatched ], # I don't want to group any of these variables together 'groups': None } # ### Generate a Sample # # We then generate a sample using the `morris.sample()` procedure from the SALib package. # In[5]: number_of_trajectories = 1000 sample = ms.sample(morris_problem, number_of_trajectories, num_levels=4, grid_jump=2) print("The sample array is ",sample.shape) print("Here are the first 10 rows:") for j in range(10): print(' '.join(['{:10.3f}'.format(i) for i in sample[j]])) # Now we're going to save the parameters to a file, so we can run the jobs separately not in this notebook. # Because the parameters in the sensitivity analysis problem may not be (in fact *are not*!) in the same order as those expected by the function (this took me a while to notice) we save the column orders into the parameters file as a header. # In[6]: header = ' '.join(morris_problem['names']) np.savetxt("parameter_values.txt", sample, header=header)
problem = read_param_file('../../SALib/test_functions/params/Sobol_G.txt') # or define manually without a parameter file: # problem = { # 'num_vars': 3, # 'names': ['x1', 'x2', 'x3'], # 'groups': None, # 'bounds': [[-3.14159265359, 3.14159265359], # [-3.14159265359, 3.14159265359], # [-3.14159265359, 3.14159265359]] # } # Files with a 4th column for "group name" will be detected automatically, e.g.: # param_file = '../../SALib/test_functions/params/Ishigami_groups.txt' # Generate samples param_values = sample(problem, N=1000, num_levels=4, grid_jump=2, \ optimal_trajectories=None) # To use optimized trajectories (brute force method), give an integer value for optimal_trajectories # Run the "model" -- this will happen offline for external models Y = Sobol_G.evaluate(param_values) # Perform the sensitivity analysis using the model output # Specify which column of the output file to analyze (zero-indexed) Si = morris.analyze(problem, param_values, Y, conf_level=0.95, print_to_console=True, num_levels=4, grid_jump=2, num_resamples=100) # Returns a dictionary with keys 'mu', 'mu_star', 'sigma', and 'mu_star_conf' # e.g. Si['mu_star'] contains the mu* value for each parameter, in the # same order as the parameter file
def sample(self, problem, size): return morris.sample(problem, size, self.num_levels, self.optimal_trajectories, self.local_optimization)
def sa(model, response, policy={}, method="sobol", nsamples=1000, **kwargs): if len(model.uncertainties) == 0: raise ValueError("no uncertainties defined in model") problem = { 'num_vars' : len(model.uncertainties), 'names' : model.uncertainties.keys(), 'bounds' : [[0.0, 1.0] for u in model.uncertainties], 'groups' : kwargs.get("groups", None) } # estimate the argument N passed to the sampler that produces the requested # number of samples N = _predict_N(method, nsamples, problem["num_vars"], kwargs) # generate the samples if method == "sobol": samples = saltelli.sample(problem, N, **_cleanup_kwargs(saltelli.sample, kwargs)) elif method == "morris": samples = morris_sampler.sample(problem, N, **_cleanup_kwargs(morris_sampler.sample, kwargs)) elif method == "fast": samples = fast_sampler.sample(problem, N, **_cleanup_kwargs(fast_sampler.sample, kwargs)) elif method == "ff": samples = ff_sampler.sample(problem, **_cleanup_kwargs(ff_sampler.sample, kwargs)) elif method == "dgsm": samples = finite_diff.sample(problem, N, **_cleanup_kwargs(finite_diff.sample, kwargs)) elif method == "delta": if "samples" in kwargs: samples = kwargs["samples"] else: samples = latin.sample(problem, N, **_cleanup_kwargs(latin.sample, kwargs)) # convert from samples in [0, 1] to uncertainty domain for i, u in enumerate(model.uncertainties): samples[:,i] = u.ppf(samples[:,i]) # run the model and collect the responses responses = np.empty(samples.shape[0]) for i in range(samples.shape[0]): sample = {k : v for k, v in zip(model.uncertainties.keys(), samples[i])} responses[i] = evaluate(model, overwrite(sample, policy))[response] # run the sensitivity analysis method if method == "sobol": result = sobol.analyze(problem, responses, **_cleanup_kwargs(sobol.analyze, kwargs)) elif method == "morris": result = morris_analyzer.analyze(problem, samples, responses, **_cleanup_kwargs(morris_analyzer.analyze, kwargs)) elif method == "fast": result = fast.analyze(problem, responses, **_cleanup_kwargs(fast.analyze, kwargs)) elif method == "ff": result = ff_analyzer.analyze(problem, samples, responses, **_cleanup_kwargs(ff_analyzer.analyze, kwargs)) elif method == "dgsm": result = dgsm.analyze(problem, samples, responses, **_cleanup_kwargs(dgsm.analyze, kwargs)) elif method == "delta": result = delta.analyze(problem, samples, responses, **_cleanup_kwargs(delta.analyze, kwargs)) # convert the SALib results into a form allowing pretty printing and # lookups using the parameter name pretty_result = SAResult(result["names"] if "names" in result else problem["names"]) if "S1" in result: pretty_result["S1"] = {k : float(v) for k, v in zip(problem["names"], result["S1"])} if "S1_conf" in result: pretty_result["S1_conf"] = {k : float(v) for k, v in zip(problem["names"], result["S1_conf"])} if "ST" in result: pretty_result["ST"] = {k : float(v) for k, v in zip(problem["names"], result["ST"])} if "ST_conf" in result: pretty_result["ST_conf"] = {k : float(v) for k, v in zip(problem["names"], result["ST_conf"])} if "S2" in result: pretty_result["S2"] = _S2_to_dict(result["S2"], problem) if "S2_conf" in result: pretty_result["S2_conf"] = _S2_to_dict(result["S2_conf"], problem) if "delta" in result: pretty_result["delta"] = {k : float(v) for k, v in zip(problem["names"], result["delta"])} if "delta_conf" in result: pretty_result["delta_conf"] = {k : float(v) for k, v in zip(problem["names"], result["delta_conf"])} if "vi" in result: pretty_result["vi"] = {k : float(v) for k, v in zip(problem["names"], result["vi"])} if "vi_std" in result: pretty_result["vi_std"] = {k : float(v) for k, v in zip(problem["names"], result["vi_std"])} if "dgsm" in result: pretty_result["dgsm"] = {k : float(v) for k, v in zip(problem["names"], result["dgsm"])} if "dgsm_conf" in result: pretty_result["dgsm_conf"] = {k : float(v) for k, v in zip(problem["names"], result["dgsm_conf"])} if "mu" in result: pretty_result["mu"] = {k : float(v) for k, v in zip(result["names"], result["mu"])} if "mu_star" in result: pretty_result["mu_star"] = {k : float(v) for k, v in zip(result["names"], result["mu_star"])} if "mu_star_conf" in result: pretty_result["mu_star_conf"] = {k : float(v) for k, v in zip(result["names"], result["mu_star_conf"])} if "sigma" in result: pretty_result["sigma"] = {k : float(v) for k, v in zip(result["names"], result["sigma"])} return pretty_result