def test_scale_samples_upper_eq_lower(): ''' Raise ValueError if upper bound lower equal to lower bound ''' params = np.array([[0, 0], [0.1, 0.1], [0.2, 0.2]]) bounds = [[10, 10], [-10, 10]] scale_samples(params, bounds)
def sample(problem, N, num_levels, grid_jump, optimal_trajectories=None, local_optimization=True, seed=None): """Generate model inputs using the Method of Morris Returns a NumPy matrix containing the model inputs required for Method of Morris. The resulting matrix has :math:`(G+1)*T` rows and :math:`D` columns, where :math:`D` is the number of parameters, :math:`G` is the number of groups (if no groups are selected, the number of parameters). :math:`T` is the number of trajectories :math:`N`, or `optimal_trajectories` if selected. These model inputs are intended to be used with :func:`SALib.analyze.morris.analyze`. Parameters ---------- problem : dict The problem definition N : int The number of trajectories to generate num_levels : int The number of grid levels grid_jump : int The grid jump size optimal_trajectories : int The number of optimal trajectories to sample (between 2 and N) local_optimization : bool, default=True Flag whether to use local optimization according to Ruano et al. (2012) Speeds up the process tremendously for bigger N and num_levels. If set to ``False`` brute force method is used, unless ``gurobipy`` is available Returns ------- sample : numpy.ndarray Returns a numpy.ndarray containing the model inputs required for Method of Morris. The resulting matrix has :math:`(G/D+1)*N/T` rows and :math:`D` columns, where :math:`D` is the number of parameters. """ if seed: np.random.seed(seed) if grid_jump >= num_levels: raise ValueError("grid_jump must be less than num_levels") if problem.get('groups'): sample = _sample_groups(problem, N, num_levels, grid_jump) else: sample = _sample_oat(problem, N, num_levels, grid_jump) if optimal_trajectories: sample = _compute_optimised_trajectories(problem, sample, N, optimal_trajectories, local_optimization) scale_samples(sample, problem['bounds']) return sample
def test_scale_samples_upper_lt_lower(): ''' Raise ValueError if upper bound lower than lower bound ''' params = np.array([[0, 0], [0.1, 0.1], [0.2, 0.2]]) bounds = [[10, 9], [-10, 10]] with raises(ValueError): scale_samples(params, bounds)
def test_scale_samples_upper_eq_lower(): ''' Raise ValueError if upper bound lower equal to lower bound ''' params = np.array([[0, 0], [0.1, 0.1], [0.2, 0.2]]) bounds = [[10, 10], [-10, 10]] with raises(ValueError): scale_samples(params, bounds)
def sample(problem: Dict, N: int, num_levels: int = 4, optimal_trajectories: int = None, local_optimization: bool = True, seed: int = None) -> np.ndarray: """Generate model inputs using the Method of Morris Returns a NumPy matrix containing the model inputs required for Method of Morris. The resulting matrix has :math:`(G+1)*T` rows and :math:`D` columns, where :math:`D` is the number of parameters, :math:`G` is the number of groups (if no groups are selected, the number of parameters). :math:`T` is the number of trajectories :math:`N`, or `optimal_trajectories` if selected. These model inputs are intended to be used with :func:`SALib.analyze.morris.analyze`. Parameters ---------- problem : dict The problem definition N : int The number of trajectories to generate num_levels : int, default=4 The number of grid levels (should be even) optimal_trajectories : int The number of optimal trajectories to sample (between 2 and N) local_optimization : bool, default=True Flag whether to use local optimization according to Ruano et al. (2012) Speeds up the process tremendously for bigger N and num_levels. If set to ``False`` brute force method is used, unless ``gurobipy`` is available seed : int Seed to generate a random number Returns ------- sample_morris : numpy.ndarray Returns a numpy.ndarray containing the model inputs required for Method of Morris. The resulting matrix has :math:`(G/D+1)*N/T` rows and :math:`D` columns, where :math:`D` is the number of parameters. """ if seed: np.random.seed(seed) _check_if_num_levels_is_even(num_levels) problem = _define_problem_with_groups(problem) sample_morris = _sample_morris(problem, N, num_levels) if optimal_trajectories: sample_morris = _compute_optimised_trajectories( problem, sample_morris, N, optimal_trajectories, local_optimization) scale_samples(sample_morris, problem['bounds']) return sample_morris
def sample(problem, N, num_levels, grid_jump, optimal_trajectories=None, local_optimization=True): """Generate model inputs using the Method of Morris Returns a NumPy matrix containing the model inputs required for Method of Morris. The resulting matrix has :math:`(G+1)*T` rows and :math:`D` columns, where :math:`D` is the number of parameters, :math:`G` is the number of groups (if no groups are selected, the number of parameters). :math:`T` is the number of trajectories :math:`N`, or `optimal_trajectories` if selected. These model inputs are intended to be used with :func:`SALib.analyze.morris.analyze`. Parameters ---------- problem : dict The problem definition N : int The number of trajectories to generate num_levels : int The number of grid levels grid_jump : int The grid jump size optimal_trajectories : int The number of optimal trajectories to sample (between 2 and N) local_optimization : bool, default=True Flag whether to use local optimization according to Ruano et al. (2012) Speeds up the process tremendously for bigger N and num_levels. If set to ``False`` brute force method is used, unless ``gurobipy`` is available Returns ------- sample : numpy.ndarray Returns a numpy.ndarray containing the model inputs required for Method of Morris. The resulting matrix has :math:`(G/D+1)*N/T` rows and :math:`D` columns, where :math:`D` is the number of parameters. """ if grid_jump >= num_levels: raise ValueError("grid_jump must be less than num_levels") if problem.get('groups'): sample = _sample_groups(problem, N, num_levels, grid_jump) else: sample = _sample_oat(problem, N, num_levels, grid_jump) if optimal_trajectories: sample = _compute_optimised_trajectories(problem, sample, N, optimal_trajectories, local_optimization) scale_samples(sample, problem['bounds']) return sample
def _generate_lhs(cls, parameter_bounds, n_samples, seed=1): """ Generates a latin hypercube array. """ num_vars = len(parameter_bounds) lhs_array = lhs(n=num_vars, samples=n_samples, criterion="maximin", random_state=seed) # scale to the bounds scale_samples(lhs_array, parameter_bounds) return lhs_array
def test_scale_samples(): ''' Simple test to ensure that samples are correctly scaled ''' params = np.arange(0, 1.1, 0.1).repeat(2).reshape((11, 2)) bounds = [[10, 20], [-10, 10]] desired = np.array( [np.arange(10, 21, 1), np.arange(-10, 12, 2)], dtype=np.float).T scale_samples(params, bounds) assert_allclose(params, desired, atol=1e-03, rtol=1e-03)
def Create_LHS_parameter_set(nsamples): from SALib.sample import latin_hypercube from SALib.util import scale_samples, read_param_file import random as rd # Set random seed (does not affect quasi-random Sobol sampling) seed = 1 np.random.seed(seed) rd.seed(seed) #Define parameters and ranges parameters = ordereddict.OrderedDict() parameters['log10m'] = [np.log10(0.001),np.log10(0.1)] parameters['lnTe'] = [np.log(np.exp(-8.0)/3600.0),np.log(np.exp(8.0)/3600.0)] parameters['log10soil'] = [np.log10(1.0),np.log10(2.00)] parameters['sdmax'] = [0.1,2.0] #dtopmodel #Make directory if os.path.exists('LHS') == False: os.mkdir('LHS') #Prepare file with parameter range fp = open('LHS/parameters.txt','w') vars = [] for var in parameters: vars.append(var) fp.write('%s %f %f\n' % (var,parameters[var][0],parameters[var][1])) fp.close() #Read the parameter range file and generate samples param_file = 'LHS/parameters.txt' pf = read_param_file(param_file) #Generate samples (choose method here) param_values = latin_hypercube.sample(nsamples, pf['num_vars']) #Samples are given in range [0, 1] by default. Rescale them to your parameter bounds. scale_samples(param_values, pf['bounds']) #Save parameters to file np.savetxt('LHS/LHS_sampling.txt', param_values, delimiter=' ',header=" ".join(vars)) return
# Set random seed (does not affect quasi-random Sobol sampling) seed = 1 np.random.seed(seed) rd.seed(seed) # Read the parameter range file and generate samples param_file = './SALib/test_functions/params/Sobol_G.txt' pf = read_param_file(param_file) # Generate samples (choose method here) param_values = saltelli.sample(100, pf['num_vars'], calc_second_order = True) # param_values = morris_oat.sample(100, pf['num_vars'], num_levels = 10, grid_jump = 5) # param_values = fast_sampler.sample(100, pf['num_vars']) # Samples are given in range [0, 1] by default. Rescale them to your parameter bounds. (If using normal distributions, use "scale_samples_normal" instead) scale_samples(param_values, pf['bounds']) # For Method of Morris, save the parameter values in a file (they are needed in the analysis) # FAST and Sobol do not require this step, unless you want to save samples to input into an external model np.savetxt('SGInput.txt', param_values, delimiter=' ') # Run the "model" and save the output in a text file # This will happen offline for external models Y = Sobol_G.evaluate(param_values) np.savetxt("SGOutput.txt", Y, delimiter=' ') # Perform the sensitivity analysis using the model output # Specify which column of the output file to analyze (zero-indexed) sobol.analyze(param_file, 'SGOutput.txt', column = 0, calc_second_order = True) # morris.analyze(param_file, 'SGInput.txt', 'SGOutput.txt', column = 0) # extended_fast.analyze(param_file, 'SGOutput.txt', column = 0)
def sample(problem: Dict, N: int, num_levels: int = 4, optimal_trajectories: int = None, local_optimization: bool = True, seed: int = None) -> np.ndarray: """Generate model inputs using the Method of Morris Returns a NumPy matrix containing the model inputs required for Method of Morris. The resulting matrix has :math:`(G+1)*T` rows and :math:`D` columns, where :math:`D` is the number of parameters, :math:`G` is the number of groups (if no groups are selected, the number of parameters). :math:`T` is the number of trajectories :math:`N`, or `optimal_trajectories` if selected. These model inputs are intended to be used with :func:`SALib.analyze.morris.analyze`. Parameters ---------- problem : dict The problem definition N : int The number of trajectories to generate num_levels : int, default=4 The number of grid levels (should be even) optimal_trajectories : int The number of optimal trajectories to sample (between 2 and N) local_optimization : bool, default=True Flag whether to use local optimization according to Ruano et al. (2012) Speeds up the process tremendously for bigger N and num_levels. If set to ``False`` brute force method is used, unless ``gurobipy`` is available seed : int Seed to generate a random number Returns ------- sample_morris : numpy.ndarray Returns a numpy.ndarray containing the model inputs required for Method of Morris. The resulting matrix has :math:`(G/D+1)*N/T` rows and :math:`D` columns, where :math:`D` is the number of parameters. References ---------- .. [1] Ruano, M.V., Ribes, J., Seco, A., Ferrer, J., 2012. An improved sampling strategy based on trajectory design for application of the Morris method to systems with many input factors. Environmental Modelling & Software 37, 103–109. https://doi.org/10.1016/j.envsoft.2012.03.008 .. [2] Morris, M.D., 1991. Factorial Sampling Plans for Preliminary Computational Experiments. Technometrics 33, 161–174. https://doi.org/10.1080/00401706.1991.10484804 .. [3] Campolongo, F., Cariboni, J., Saltelli, A., 2007. An effective screening design for sensitivity analysis of large models. Environmental Modelling & Software, Modelling, computer-assisted simulations, and mapping of dangerous phenomena for hazard assessment 22, 1509–1518. https://doi.org/10.1016/j.envsoft.2006.10.004 """ if seed: np.random.seed(seed) _check_if_num_levels_is_even(num_levels) problem = _define_problem_with_groups(problem) sample_morris = _sample_morris(problem, N, num_levels) if optimal_trajectories: sample_morris = _compute_optimised_trajectories(problem, sample_morris, N, optimal_trajectories, local_optimization) sample_morris = scale_samples(sample_morris, problem) return sample_morris