GitHub

romtools.workflows.parameters

  1import abc
  2import numpy as np
  3from scipy.stats import qmc
  4from scipy.stats import norm
  5from scipy.stats import triang
  6from scipy.stats import rv_continuous
  7
  8class Parameter(abc.ABC):
  9    '''Abstract implementation'''
 10
 11    @abc.abstractmethod
 12    def get_name(self) -> str:
 13        '''
 14        Returns parameter name
 15        '''
 16
 17    @abc.abstractmethod
 18    def get_dimensionality(self) -> int:
 19        '''
 20        Returns dimensionality of parameter for vector quantities.
 21        Returns 1 for scalar parameters
 22        '''
 23
 24    @abc.abstractmethod
 25    def scale_samples(self, uniform_dist_samples) -> np.array:
 26        '''
 27        Generates samples from the desired distribution given a set of samples
 28        from a uniform distribution on (0,1)
 29
 30        uniform_dist_samples should be of shape
 31        (number_of_samples, self.get_dimensionality())
 32
 33        Returns np.array of the same shape
 34        '''
 35
 36##########################################
 37# Concrete Parameter Classes
 38##########################################
 39
 40
 41class UniformParameter(Parameter):
 42    '''
 43    Uniformly distributed floating point
 44    '''
 45    def __init__(self, parameter_name: str,
 46                 lower_bound: float = 0,
 47                 upper_bound: float = 1):
 48        self._parameter_name = parameter_name
 49
 50        try:
 51            assert len(lower_bound) == len(upper_bound)
 52            self._dimension = len(lower_bound)
 53        except TypeError:
 54            self._dimension = 1
 55        self._lower_bound = lower_bound
 56        self._upper_bound = upper_bound
 57
 58    def get_name(self) -> str:
 59        return self._parameter_name
 60
 61    def get_dimensionality(self) -> int:
 62        return self._dimension
 63
 64    def scale_samples(self, uniform_dist_samples: np.array) -> np.array:
 65        assert uniform_dist_samples.shape[1] == self.get_dimensionality()
 66        return qmc.scale(uniform_dist_samples,
 67                         self._lower_bound,
 68                         self._upper_bound)
 69
 70
 71class StringParameter(Parameter):
 72    '''
 73    Constant string-valued parameter
 74    '''
 75    def __init__(self, parameter_name: str, value):
 76        self._parameter_name = parameter_name
 77        self._parameter_value = value
 78
 79    def get_name(self) -> str:
 80        return self._parameter_name
 81
 82    def get_dimensionality(self) -> int:
 83        return 1
 84
 85    def scale_samples(self, uniform_dist_samples: np.array) -> np.array:
 86        assert uniform_dist_samples.shape[1] == self.get_dimensionality()
 87        number_of_samples = uniform_dist_samples.shape[0]
 88        return np.array([[self._parameter_value]] * number_of_samples)
 89
 90
 91class GaussianParameter(Parameter):
 92    '''
 93    Normally distributed parameter
 94    '''
 95    def __init__(self, parameter_name: str,
 96                 mean: float = 0,
 97                 std: float = 1):
 98        self._parameter_name = parameter_name
 99        try:
100            assert len(mean) == len(std)
101            self._dimension = len(mean)
102        except TypeError:
103            self._dimension = 1
104        self._mean = mean
105        self._std = std
106
107    def get_name(self) -> str:
108        return self._parameter_name
109
110    def get_dimensionality(self) -> int:
111        return self._dimension
112
113    def scale_samples(self, uniform_dist_samples: np.array) -> np.array:
114        assert uniform_dist_samples.shape[1] == self.get_dimensionality()
115        return norm.ppf(uniform_dist_samples, loc=self._mean, scale=self._std)
116
117
118class TriangularParameter(Parameter):
119    '''
120    Random parameter with a triangular distribution
121    '''
122    def __init__(self, parameter_name: str,
123                 lower_bound: float = -1,
124                 peak: float = 0,
125                 upper_bound: float = 1):
126        self._parameter_name = parameter_name
127        try:
128            assert len(lower_bound) == len(peak)
129            assert len(lower_bound) == len(upper_bound)
130            self._dimension = len(lower_bound)
131        except TypeError:
132            self._dimension = 1
133        self._loc = lower_bound
134        self._scale = np.array(upper_bound) - np.array(lower_bound)
135        self._c = (np.array(peak) - np.array(lower_bound))/(self._scale)
136
137    def get_name(self) -> str:
138        return self._parameter_name
139
140    def get_dimensionality(self) -> int:
141        return self._dimension
142
143    def scale_samples(self, uniform_dist_samples: np.array) -> np.array:
144        assert uniform_dist_samples.shape[1] == self.get_dimensionality()
145        return triang.ppf(uniform_dist_samples, loc=self._loc, scale=self._scale, c=self._c)
146
147
148class ScipyDistributionParameter(Parameter):
149    '''
150    Random parameter with distribution described by a scipy.stats.rv_continuous object
151    '''
152
153    def __init__(self, parameter_name: str, distribution: rv_continuous, **kwargs):
154        self._parameter_name = parameter_name
155        self._dist_obj = distribution
156        self._kwargs = kwargs
157
158        try:
159            self._dimension = len(kwargs['loc'])
160        except TypeError:
161            self._dimension = 1
162
163    def get_name(self) -> str:
164        return self._parameter_name
165
166    def get_dimensionality(self) -> int:
167        return self._dimension
168
169    def scale_samples(self, uniform_dist_samples: np.array) -> np.array:
170        assert uniform_dist_samples.shape[1] == self.get_dimensionality()
171        return self._dist_obj.ppf(uniform_dist_samples, **self._kwargs)
class Parameter(abc.ABC):
 9class Parameter(abc.ABC):
10    '''Abstract implementation'''
11
12    @abc.abstractmethod
13    def get_name(self) -> str:
14        '''
15        Returns parameter name
16        '''
17
18    @abc.abstractmethod
19    def get_dimensionality(self) -> int:
20        '''
21        Returns dimensionality of parameter for vector quantities.
22        Returns 1 for scalar parameters
23        '''
24
25    @abc.abstractmethod
26    def scale_samples(self, uniform_dist_samples) -> np.array:
27        '''
28        Generates samples from the desired distribution given a set of samples
29        from a uniform distribution on (0,1)
30
31        uniform_dist_samples should be of shape
32        (number_of_samples, self.get_dimensionality())
33
34        Returns np.array of the same shape
35        '''

Abstract implementation

@abc.abstractmethod
def get_name(self) -> str:
12    @abc.abstractmethod
13    def get_name(self) -> str:
14        '''
15        Returns parameter name
16        '''

Returns parameter name

@abc.abstractmethod
def get_dimensionality(self) -> int:
18    @abc.abstractmethod
19    def get_dimensionality(self) -> int:
20        '''
21        Returns dimensionality of parameter for vector quantities.
22        Returns 1 for scalar parameters
23        '''

Returns dimensionality of parameter for vector quantities. Returns 1 for scalar parameters

@abc.abstractmethod
def scale_samples(self, uniform_dist_samples) -> <built-in function array>:
25    @abc.abstractmethod
26    def scale_samples(self, uniform_dist_samples) -> np.array:
27        '''
28        Generates samples from the desired distribution given a set of samples
29        from a uniform distribution on (0,1)
30
31        uniform_dist_samples should be of shape
32        (number_of_samples, self.get_dimensionality())
33
34        Returns np.array of the same shape
35        '''

Generates samples from the desired distribution given a set of samples from a uniform distribution on (0,1)

uniform_dist_samples should be of shape (number_of_samples, self.get_dimensionality())

Returns np.array of the same shape

class UniformParameter(Parameter):
42class UniformParameter(Parameter):
43    '''
44    Uniformly distributed floating point
45    '''
46    def __init__(self, parameter_name: str,
47                 lower_bound: float = 0,
48                 upper_bound: float = 1):
49        self._parameter_name = parameter_name
50
51        try:
52            assert len(lower_bound) == len(upper_bound)
53            self._dimension = len(lower_bound)
54        except TypeError:
55            self._dimension = 1
56        self._lower_bound = lower_bound
57        self._upper_bound = upper_bound
58
59    def get_name(self) -> str:
60        return self._parameter_name
61
62    def get_dimensionality(self) -> int:
63        return self._dimension
64
65    def scale_samples(self, uniform_dist_samples: np.array) -> np.array:
66        assert uniform_dist_samples.shape[1] == self.get_dimensionality()
67        return qmc.scale(uniform_dist_samples,
68                         self._lower_bound,
69                         self._upper_bound)

Uniformly distributed floating point

UniformParameter(parameter_name: str, lower_bound: float = 0, upper_bound: float = 1)
46    def __init__(self, parameter_name: str,
47                 lower_bound: float = 0,
48                 upper_bound: float = 1):
49        self._parameter_name = parameter_name
50
51        try:
52            assert len(lower_bound) == len(upper_bound)
53            self._dimension = len(lower_bound)
54        except TypeError:
55            self._dimension = 1
56        self._lower_bound = lower_bound
57        self._upper_bound = upper_bound
def get_name(self) -> str:
59    def get_name(self) -> str:
60        return self._parameter_name

Returns parameter name

def get_dimensionality(self) -> int:
62    def get_dimensionality(self) -> int:
63        return self._dimension

Returns dimensionality of parameter for vector quantities. Returns 1 for scalar parameters

def scale_samples( self, uniform_dist_samples: <built-in function array>) -> <built-in function array>:
65    def scale_samples(self, uniform_dist_samples: np.array) -> np.array:
66        assert uniform_dist_samples.shape[1] == self.get_dimensionality()
67        return qmc.scale(uniform_dist_samples,
68                         self._lower_bound,
69                         self._upper_bound)

Generates samples from the desired distribution given a set of samples from a uniform distribution on (0,1)

uniform_dist_samples should be of shape (number_of_samples, self.get_dimensionality())

Returns np.array of the same shape

class StringParameter(Parameter):
72class StringParameter(Parameter):
73    '''
74    Constant string-valued parameter
75    '''
76    def __init__(self, parameter_name: str, value):
77        self._parameter_name = parameter_name
78        self._parameter_value = value
79
80    def get_name(self) -> str:
81        return self._parameter_name
82
83    def get_dimensionality(self) -> int:
84        return 1
85
86    def scale_samples(self, uniform_dist_samples: np.array) -> np.array:
87        assert uniform_dist_samples.shape[1] == self.get_dimensionality()
88        number_of_samples = uniform_dist_samples.shape[0]
89        return np.array([[self._parameter_value]] * number_of_samples)

Constant string-valued parameter

StringParameter(parameter_name: str, value)
76    def __init__(self, parameter_name: str, value):
77        self._parameter_name = parameter_name
78        self._parameter_value = value
def get_name(self) -> str:
80    def get_name(self) -> str:
81        return self._parameter_name

Returns parameter name

def get_dimensionality(self) -> int:
83    def get_dimensionality(self) -> int:
84        return 1

Returns dimensionality of parameter for vector quantities. Returns 1 for scalar parameters

def scale_samples( self, uniform_dist_samples: <built-in function array>) -> <built-in function array>:
86    def scale_samples(self, uniform_dist_samples: np.array) -> np.array:
87        assert uniform_dist_samples.shape[1] == self.get_dimensionality()
88        number_of_samples = uniform_dist_samples.shape[0]
89        return np.array([[self._parameter_value]] * number_of_samples)

Generates samples from the desired distribution given a set of samples from a uniform distribution on (0,1)

uniform_dist_samples should be of shape (number_of_samples, self.get_dimensionality())

Returns np.array of the same shape

class GaussianParameter(Parameter):
 92class GaussianParameter(Parameter):
 93    '''
 94    Normally distributed parameter
 95    '''
 96    def __init__(self, parameter_name: str,
 97                 mean: float = 0,
 98                 std: float = 1):
 99        self._parameter_name = parameter_name
100        try:
101            assert len(mean) == len(std)
102            self._dimension = len(mean)
103        except TypeError:
104            self._dimension = 1
105        self._mean = mean
106        self._std = std
107
108    def get_name(self) -> str:
109        return self._parameter_name
110
111    def get_dimensionality(self) -> int:
112        return self._dimension
113
114    def scale_samples(self, uniform_dist_samples: np.array) -> np.array:
115        assert uniform_dist_samples.shape[1] == self.get_dimensionality()
116        return norm.ppf(uniform_dist_samples, loc=self._mean, scale=self._std)

Normally distributed parameter

GaussianParameter(parameter_name: str, mean: float = 0, std: float = 1)
 96    def __init__(self, parameter_name: str,
 97                 mean: float = 0,
 98                 std: float = 1):
 99        self._parameter_name = parameter_name
100        try:
101            assert len(mean) == len(std)
102            self._dimension = len(mean)
103        except TypeError:
104            self._dimension = 1
105        self._mean = mean
106        self._std = std
def get_name(self) -> str:
108    def get_name(self) -> str:
109        return self._parameter_name

Returns parameter name

def get_dimensionality(self) -> int:
111    def get_dimensionality(self) -> int:
112        return self._dimension

Returns dimensionality of parameter for vector quantities. Returns 1 for scalar parameters

def scale_samples( self, uniform_dist_samples: <built-in function array>) -> <built-in function array>:
114    def scale_samples(self, uniform_dist_samples: np.array) -> np.array:
115        assert uniform_dist_samples.shape[1] == self.get_dimensionality()
116        return norm.ppf(uniform_dist_samples, loc=self._mean, scale=self._std)

Generates samples from the desired distribution given a set of samples from a uniform distribution on (0,1)

uniform_dist_samples should be of shape (number_of_samples, self.get_dimensionality())

Returns np.array of the same shape

class TriangularParameter(Parameter):
119class TriangularParameter(Parameter):
120    '''
121    Random parameter with a triangular distribution
122    '''
123    def __init__(self, parameter_name: str,
124                 lower_bound: float = -1,
125                 peak: float = 0,
126                 upper_bound: float = 1):
127        self._parameter_name = parameter_name
128        try:
129            assert len(lower_bound) == len(peak)
130            assert len(lower_bound) == len(upper_bound)
131            self._dimension = len(lower_bound)
132        except TypeError:
133            self._dimension = 1
134        self._loc = lower_bound
135        self._scale = np.array(upper_bound) - np.array(lower_bound)
136        self._c = (np.array(peak) - np.array(lower_bound))/(self._scale)
137
138    def get_name(self) -> str:
139        return self._parameter_name
140
141    def get_dimensionality(self) -> int:
142        return self._dimension
143
144    def scale_samples(self, uniform_dist_samples: np.array) -> np.array:
145        assert uniform_dist_samples.shape[1] == self.get_dimensionality()
146        return triang.ppf(uniform_dist_samples, loc=self._loc, scale=self._scale, c=self._c)

Random parameter with a triangular distribution

TriangularParameter( parameter_name: str, lower_bound: float = -1, peak: float = 0, upper_bound: float = 1)
123    def __init__(self, parameter_name: str,
124                 lower_bound: float = -1,
125                 peak: float = 0,
126                 upper_bound: float = 1):
127        self._parameter_name = parameter_name
128        try:
129            assert len(lower_bound) == len(peak)
130            assert len(lower_bound) == len(upper_bound)
131            self._dimension = len(lower_bound)
132        except TypeError:
133            self._dimension = 1
134        self._loc = lower_bound
135        self._scale = np.array(upper_bound) - np.array(lower_bound)
136        self._c = (np.array(peak) - np.array(lower_bound))/(self._scale)
def get_name(self) -> str:
138    def get_name(self) -> str:
139        return self._parameter_name

Returns parameter name

def get_dimensionality(self) -> int:
141    def get_dimensionality(self) -> int:
142        return self._dimension

Returns dimensionality of parameter for vector quantities. Returns 1 for scalar parameters

def scale_samples( self, uniform_dist_samples: <built-in function array>) -> <built-in function array>:
144    def scale_samples(self, uniform_dist_samples: np.array) -> np.array:
145        assert uniform_dist_samples.shape[1] == self.get_dimensionality()
146        return triang.ppf(uniform_dist_samples, loc=self._loc, scale=self._scale, c=self._c)

Generates samples from the desired distribution given a set of samples from a uniform distribution on (0,1)

uniform_dist_samples should be of shape (number_of_samples, self.get_dimensionality())

Returns np.array of the same shape

class ScipyDistributionParameter(Parameter):
149class ScipyDistributionParameter(Parameter):
150    '''
151    Random parameter with distribution described by a scipy.stats.rv_continuous object
152    '''
153
154    def __init__(self, parameter_name: str, distribution: rv_continuous, **kwargs):
155        self._parameter_name = parameter_name
156        self._dist_obj = distribution
157        self._kwargs = kwargs
158
159        try:
160            self._dimension = len(kwargs['loc'])
161        except TypeError:
162            self._dimension = 1
163
164    def get_name(self) -> str:
165        return self._parameter_name
166
167    def get_dimensionality(self) -> int:
168        return self._dimension
169
170    def scale_samples(self, uniform_dist_samples: np.array) -> np.array:
171        assert uniform_dist_samples.shape[1] == self.get_dimensionality()
172        return self._dist_obj.ppf(uniform_dist_samples, **self._kwargs)

Random parameter with distribution described by a scipy.stats.rv_continuous object

ScipyDistributionParameter( parameter_name: str, distribution: scipy.stats._distn_infrastructure.rv_continuous, **kwargs)
154    def __init__(self, parameter_name: str, distribution: rv_continuous, **kwargs):
155        self._parameter_name = parameter_name
156        self._dist_obj = distribution
157        self._kwargs = kwargs
158
159        try:
160            self._dimension = len(kwargs['loc'])
161        except TypeError:
162            self._dimension = 1
def get_name(self) -> str:
164    def get_name(self) -> str:
165        return self._parameter_name

Returns parameter name

def get_dimensionality(self) -> int:
167    def get_dimensionality(self) -> int:
168        return self._dimension

Returns dimensionality of parameter for vector quantities. Returns 1 for scalar parameters

def scale_samples( self, uniform_dist_samples: <built-in function array>) -> <built-in function array>:
170    def scale_samples(self, uniform_dist_samples: np.array) -> np.array:
171        assert uniform_dist_samples.shape[1] == self.get_dimensionality()
172        return self._dist_obj.ppf(uniform_dist_samples, **self._kwargs)

Generates samples from the desired distribution given a set of samples from a uniform distribution on (0,1)

uniform_dist_samples should be of shape (number_of_samples, self.get_dimensionality())

Returns np.array of the same shape