romtools.workflows.parameter_spaces
Model reduction is often focused on parameterized PDEs, where $\boldsymbol \mu$ is the parameter set. The ParameterSpace class encapsulates the notion of the parameter space.
1# 2# ************************************************************************ 3# 4# ROM Tools and Workflows 5# Copyright 2019 National Technology & Engineering Solutions of Sandia,LLC 6# (NTESS) 7# 8# Under the terms of Contract DE-NA0003525 with NTESS, the 9# U.S. Government retains certain rights in this software. 10# 11# ROM Tools and Workflows is licensed under BSD-3-Clause terms of use: 12# 13# Redistribution and use in source and binary forms, with or without 14# modification, are permitted provided that the following conditions 15# are met: 16# 17# 1. Redistributions of source code must retain the above copyright 18# notice, this list of conditions and the following disclaimer. 19# 20# 2. Redistributions in binary form must reproduce the above copyright 21# notice, this list of conditions and the following disclaimer in the 22# documentation and/or other materials provided with the distribution. 23# 24# 3. Neither the name of the copyright holder nor the names of its 25# contributors may be used to endorse or promote products derived 26# from this software without specific prior written permission. 27# 28# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 31# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 32# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 33# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 35# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 37# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 38# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39# POSSIBILITY OF SUCH DAMAGE. 40# 41# Questions? Contact Eric Parish (ejparis@sandia.gov) 42# 43# ************************************************************************ 44# 45 46''' 47Model reduction is often focused on parameterized PDEs, where 48$\\boldsymbol \\mu$ is the parameter set. 49The ParameterSpace class encapsulates the notion of the parameter space. 50''' 51import abc 52from typing import Iterable 53import numpy as np 54 55from romtools.workflows.sampling_methods import Sampler, MonteCarloSampler 56from romtools.workflows.parameters import Parameter, StringParameter, UniformParameter, GaussianParameter 57 58 59class ParameterSpace(abc.ABC): 60 '''Abstract implementation''' 61 62 @abc.abstractmethod 63 def get_names(self) -> Iterable[str]: 64 ''' 65 Returns a list of parameter names 66 # e.g., ['sigma','beta',...] 67 ''' 68 69 @abc.abstractmethod 70 def get_dimensionality(self) -> int: 71 ''' 72 Returns an integer for the size 73 of the parameter domain 74 ''' 75 76 @abc.abstractmethod 77 def generate_samples(self, number_of_samples: int, seed=None) -> np.array: 78 ''' 79 Generates samples from the parameter space 80 81 Returns np.array of shape 82 (number_of_samples, self.get_dimensionality()) 83 ''' 84 85 86########################################## 87# Concrete ParameterSpace Classes 88########################################## 89 90 91class HeterogeneousParameterSpace(ParameterSpace): 92 ''' 93 Heterogeneous parameter space consisting of a list of arbitrary Parameter 94 objects 95 ''' 96 97 def __init__(self, parameter_objs: Iterable[Parameter], sampler: Sampler = MonteCarloSampler): 98 self._parameters = parameter_objs 99 self._sampler = sampler 100 101 def _get_parameter_list(self) -> Iterable[Parameter]: 102 ''' 103 Returns a list of Parameter objects 104 ''' 105 return self._parameters 106 107 def get_names(self) -> Iterable[str]: 108 return [p.get_name() for p in self._get_parameter_list()] 109 110 def get_dimensionality(self) -> int: 111 return sum(p.get_dimensionality() for p in self._get_parameter_list()) 112 113 def generate_samples(self, number_of_samples: int, seed=None) -> np.array: 114 iid_samples = self._sampler(number_of_samples, self.get_dimensionality(), seed) 115 samples = [] 116 param_idx = 0 117 for param in self._get_parameter_list(): 118 next_param_idx = param_idx + param.get_dimensionality() 119 param_samples = param.scale_samples(iid_samples[:, param_idx:next_param_idx]) 120 samples.append(param_samples) 121 param_idx = next_param_idx 122 return np.concatenate(samples, axis=1) 123 124 125class HomogeneousParameterSpace(HeterogeneousParameterSpace): 126 ''' 127 Homogenous parameter space in which every parameter is of the same type 128 ''' 129 130 def __init__(self, parameter_names: Iterable[str], sampler: Sampler, param_constructor, **kwargs): 131 parameters = [] 132 for param_num, param_name in enumerate(parameter_names): 133 args = {key: val[param_num] for key, val in kwargs.items()} 134 parameters.append(param_constructor(parameter_name=param_name, **args)) 135 super().__init__(parameters, sampler) 136 137 138class EmptyParameterSpace(ParameterSpace): 139 ''' 140 Empty parameter space that is useful for initializations 141 ''' 142 143 def get_names(self) -> list: 144 return [] 145 146 def get_dimensionality(self) -> int: 147 return 0 148 149 def generate_samples(self, number_of_samples: int, seed=None) -> np.ndarray: 150 return np.empty(shape=(number_of_samples, 0)) 151 152 153class UniformParameterSpace(HomogeneousParameterSpace): 154 ''' 155 Homogeneous parameter space in which every parameter is a UniformParameter 156 ''' 157 158 def __init__(self, parameter_names: Iterable[str], lower_bounds, upper_bounds, sampler: Sampler): 159 super().__init__(parameter_names, sampler=sampler, param_constructor=UniformParameter, 160 lower_bound=lower_bounds, upper_bound=upper_bounds) 161 162 163class GaussianParameterSpace(HomogeneousParameterSpace): 164 ''' 165 Homogeneous parameter space in which every parameter is a GaussianParameter 166 ''' 167 168 def __init__(self, parameter_names: Iterable[str], means, stds, sampler: Sampler): 169 super().__init__(parameter_names, sampler=sampler, param_constructor=GaussianParameter, mean=means, std=stds) 170 171 172class ConstParameterSpace(HomogeneousParameterSpace): 173 ''' 174 Homogeneous parameter space in which every parameter is a constant 175 StringParameter. All numeric values are converted to str-type. 176 177 Useful if you need to execute workflows in a non-stochastic setting 178 ''' 179 180 def __init__(self, parameter_names: Iterable[str], parameter_values): 181 super().__init__(parameter_names, MonteCarloSampler, StringParameter, value=parameter_values)
60class ParameterSpace(abc.ABC): 61 '''Abstract implementation''' 62 63 @abc.abstractmethod 64 def get_names(self) -> Iterable[str]: 65 ''' 66 Returns a list of parameter names 67 # e.g., ['sigma','beta',...] 68 ''' 69 70 @abc.abstractmethod 71 def get_dimensionality(self) -> int: 72 ''' 73 Returns an integer for the size 74 of the parameter domain 75 ''' 76 77 @abc.abstractmethod 78 def generate_samples(self, number_of_samples: int, seed=None) -> np.array: 79 ''' 80 Generates samples from the parameter space 81 82 Returns np.array of shape 83 (number_of_samples, self.get_dimensionality()) 84 '''
Abstract implementation
63 @abc.abstractmethod 64 def get_names(self) -> Iterable[str]: 65 ''' 66 Returns a list of parameter names 67 # e.g., ['sigma','beta',...] 68 '''
Returns a list of parameter names
e.g., ['sigma','beta',...]
70 @abc.abstractmethod 71 def get_dimensionality(self) -> int: 72 ''' 73 Returns an integer for the size 74 of the parameter domain 75 '''
Returns an integer for the size of the parameter domain
77 @abc.abstractmethod 78 def generate_samples(self, number_of_samples: int, seed=None) -> np.array: 79 ''' 80 Generates samples from the parameter space 81 82 Returns np.array of shape 83 (number_of_samples, self.get_dimensionality()) 84 '''
Generates samples from the parameter space
Returns np.array of shape (number_of_samples, self.get_dimensionality())
92class HeterogeneousParameterSpace(ParameterSpace): 93 ''' 94 Heterogeneous parameter space consisting of a list of arbitrary Parameter 95 objects 96 ''' 97 98 def __init__(self, parameter_objs: Iterable[Parameter], sampler: Sampler = MonteCarloSampler): 99 self._parameters = parameter_objs 100 self._sampler = sampler 101 102 def _get_parameter_list(self) -> Iterable[Parameter]: 103 ''' 104 Returns a list of Parameter objects 105 ''' 106 return self._parameters 107 108 def get_names(self) -> Iterable[str]: 109 return [p.get_name() for p in self._get_parameter_list()] 110 111 def get_dimensionality(self) -> int: 112 return sum(p.get_dimensionality() for p in self._get_parameter_list()) 113 114 def generate_samples(self, number_of_samples: int, seed=None) -> np.array: 115 iid_samples = self._sampler(number_of_samples, self.get_dimensionality(), seed) 116 samples = [] 117 param_idx = 0 118 for param in self._get_parameter_list(): 119 next_param_idx = param_idx + param.get_dimensionality() 120 param_samples = param.scale_samples(iid_samples[:, param_idx:next_param_idx]) 121 samples.append(param_samples) 122 param_idx = next_param_idx 123 return np.concatenate(samples, axis=1)
Heterogeneous parameter space consisting of a list of arbitrary Parameter objects
108 def get_names(self) -> Iterable[str]: 109 return [p.get_name() for p in self._get_parameter_list()]
Returns a list of parameter names
e.g., ['sigma','beta',...]
111 def get_dimensionality(self) -> int: 112 return sum(p.get_dimensionality() for p in self._get_parameter_list())
Returns an integer for the size of the parameter domain
114 def generate_samples(self, number_of_samples: int, seed=None) -> np.array: 115 iid_samples = self._sampler(number_of_samples, self.get_dimensionality(), seed) 116 samples = [] 117 param_idx = 0 118 for param in self._get_parameter_list(): 119 next_param_idx = param_idx + param.get_dimensionality() 120 param_samples = param.scale_samples(iid_samples[:, param_idx:next_param_idx]) 121 samples.append(param_samples) 122 param_idx = next_param_idx 123 return np.concatenate(samples, axis=1)
Generates samples from the parameter space
Returns np.array of shape (number_of_samples, self.get_dimensionality())
126class HomogeneousParameterSpace(HeterogeneousParameterSpace): 127 ''' 128 Homogenous parameter space in which every parameter is of the same type 129 ''' 130 131 def __init__(self, parameter_names: Iterable[str], sampler: Sampler, param_constructor, **kwargs): 132 parameters = [] 133 for param_num, param_name in enumerate(parameter_names): 134 args = {key: val[param_num] for key, val in kwargs.items()} 135 parameters.append(param_constructor(parameter_name=param_name, **args)) 136 super().__init__(parameters, sampler)
Homogenous parameter space in which every parameter is of the same type
131 def __init__(self, parameter_names: Iterable[str], sampler: Sampler, param_constructor, **kwargs): 132 parameters = [] 133 for param_num, param_name in enumerate(parameter_names): 134 args = {key: val[param_num] for key, val in kwargs.items()} 135 parameters.append(param_constructor(parameter_name=param_name, **args)) 136 super().__init__(parameters, sampler)
Inherited Members
139class EmptyParameterSpace(ParameterSpace): 140 ''' 141 Empty parameter space that is useful for initializations 142 ''' 143 144 def get_names(self) -> list: 145 return [] 146 147 def get_dimensionality(self) -> int: 148 return 0 149 150 def generate_samples(self, number_of_samples: int, seed=None) -> np.ndarray: 151 return np.empty(shape=(number_of_samples, 0))
Empty parameter space that is useful for initializations
150 def generate_samples(self, number_of_samples: int, seed=None) -> np.ndarray: 151 return np.empty(shape=(number_of_samples, 0))
Generates samples from the parameter space
Returns np.array of shape (number_of_samples, self.get_dimensionality())
154class UniformParameterSpace(HomogeneousParameterSpace): 155 ''' 156 Homogeneous parameter space in which every parameter is a UniformParameter 157 ''' 158 159 def __init__(self, parameter_names: Iterable[str], lower_bounds, upper_bounds, sampler: Sampler): 160 super().__init__(parameter_names, sampler=sampler, param_constructor=UniformParameter, 161 lower_bound=lower_bounds, upper_bound=upper_bounds)
Homogeneous parameter space in which every parameter is a UniformParameter
Inherited Members
164class GaussianParameterSpace(HomogeneousParameterSpace): 165 ''' 166 Homogeneous parameter space in which every parameter is a GaussianParameter 167 ''' 168 169 def __init__(self, parameter_names: Iterable[str], means, stds, sampler: Sampler): 170 super().__init__(parameter_names, sampler=sampler, param_constructor=GaussianParameter, mean=means, std=stds)
Homogeneous parameter space in which every parameter is a GaussianParameter
Inherited Members
173class ConstParameterSpace(HomogeneousParameterSpace): 174 ''' 175 Homogeneous parameter space in which every parameter is a constant 176 StringParameter. All numeric values are converted to str-type. 177 178 Useful if you need to execute workflows in a non-stochastic setting 179 ''' 180 181 def __init__(self, parameter_names: Iterable[str], parameter_values): 182 super().__init__(parameter_names, MonteCarloSampler, StringParameter, value=parameter_values)
Homogeneous parameter space in which every parameter is a constant StringParameter. All numeric values are converted to str-type.
Useful if you need to execute workflows in a non-stochastic setting