nmoo.noises.gaussian
Random noises to apply to objective functions.
1""" 2Random noises to apply to objective functions. 3""" 4__docformat__ = "google" 5 6from typing import Any, Dict, Optional, Tuple, Union 7 8import numpy as np 9from loguru import logger as logging 10from pymoo.core.problem import Problem 11 12from nmoo.wrapped_problem import WrappedProblem 13 14 15class GaussianNoise(WrappedProblem): 16 """ 17 A wrapper that adds a (multivariate) gaussian noise to a problem. 18 19 Assume that the output of the wrapped problem as an `F` numerical component 20 (as they almost always do). The following creates a new problem by adding a 21 `N(0, .2)` noise on all components of `F` (without any covariance): 22 23 mean_F = np.array([0., 0.]) 24 cov_F = .2 * np.eye(2) 25 noisy_problem = nmoo.GaussianNoise(problem, mean_F, cov_F) 26 27 Assume that in addition, the problem has a `G` numerical component to which 28 we would also like to add noise. The following a 0-mean 1-dimensional 29 gaussian noise along the plane antidiagonal (line with -pi/4 orientation) 30 to `G`, and the same noise as above to `F`: 31 32 mean_F = np.array([0., 0.]) 33 cov_F = .2 * np.eye(2) 34 mean_G = np.array([0., 0.]) 35 cov_G = np.array([[1., -1.], [-1., 1.]]) 36 noisy_problem = nmoo.GaussianNoise( 37 problem, { 38 "F": (mean_F, cov_F), 39 "G": (mean_G, cov_G), 40 }, 41 ) 42 43 """ 44 45 _generator: np.random.Generator 46 """Random number generator.""" 47 48 _parameters: Dict[str, Tuple[np.ndarray, np.ndarray]] 49 """ 50 Noise parameters. Each entry is a tuple containing the noise's mean vector 51 and covariance matrix. 52 """ 53 54 def __init__( 55 self, 56 problem: Problem, 57 mean: Optional[np.ndarray] = None, 58 covariance: Optional[Union[float, int, np.ndarray]] = None, 59 parameters: Optional[Dict[str, Tuple[np.ndarray, np.ndarray]]] = None, 60 seed: Any = None, 61 *, 62 name: str = "gaussian_noise", 63 **kwargs, 64 ): 65 """ 66 Args: 67 name (str): An optional name for this problem. This will be used 68 when creating history dump files. Defaults to `gaussian_noise`. 69 problem (pymoo `Problem`): A non-noisy pymoo problem (or 70 `nmoo.wrapped_problem.WrappedProblem`). 71 mean (optional `np.ndarray`): The mean vector of the gaussian 72 distribution. If specified, the `covariance` argument must also 73 be specified, and `parameters` must be left to its default 74 `None`. 75 covariance (optional `np.ndarray` or number): The covariance 76 matrix of the gaussian distribution. If specified, the `mean` 77 argument must also be specified, and `parameters` must be left 78 to its default `None`. For convenience, a number `v` can be 79 passed instead of a matrix, in which case the covariance matrix 80 is set to be `v * I_n`, where `n` is the dimension of the 81 `mean` vector. Note that `v` is then the variance of every 82 component of the distribution, **not the standard deviation**! 83 parameters (optional dict): Gaussian noise parameters, in the form 84 of a dict mapping the name of an objective to a numpy array 85 pair (mean, covariance matrix). The set of keys should be a 86 subset of the final `out` dictionary keys in the wrapped 87 problem's `_evaluate` method. If specified, the `mean` and 88 `covariance` arguments must be left to their default `None`. 89 seed: Seed for 90 [`numpy.random.default_rng`](https://numpy.org/doc/stable/reference/random/generator.html#numpy.random.default_rng) 91 """ 92 super().__init__(problem, name=name, **kwargs) 93 if mean is not None and covariance is not None and parameters is None: 94 if not isinstance(covariance, np.ndarray): 95 covariance = covariance * np.eye(mean.shape[0]) 96 self._parameters = {"F": (mean, covariance)} 97 elif mean is None and covariance is None and parameters is not None: 98 self._parameters = parameters 99 else: 100 raise ValueError( 101 "Invalid noise specification. Either mean and covariance are " 102 "both set, or a parameters dict is set." 103 ) 104 self.reseed(seed) 105 106 def _evaluate(self, x, out, *args, **kwargs): 107 """ 108 Calls the wrapped problems's `_evaluate` method and adds a Gaussian 109 noise. Adds the input (`x`), the noisy output, and the noise values to 110 history. 111 112 Example: 113 114 If the wrapped problem's output dict looks like: 115 116 { 117 "A": (n, m) np.ndarray, 118 "B": not an np.ndarray 119 } 120 121 then the history will look like this: 122 123 { 124 "A": an np.ndarray (with the noise added), 125 "A_noise": an np.ndarray of the same dimension 126 } 127 128 """ 129 self._problem._evaluate(x, out, *args, **kwargs) 130 noises: Dict[str, np.ndarray] = {} 131 for k in self._parameters.keys(): 132 try: 133 mean, cov = self._parameters[k] 134 noises[k] = self._generator.multivariate_normal( 135 mean, 136 cov, 137 out[k].shape[0], 138 ) 139 out[k] += noises[k] 140 except KeyError: 141 logging.error( 142 "Noise parameter key {} is not present in objective " 143 "function output keys. No noise will be applied. " 144 "Objective function keys: {}. ", 145 k, 146 str(list(out.keys())), 147 ) 148 self.add_to_history_x_out( 149 x, out, **{k + "_noise": v for k, v in noises.items()} 150 ) 151 152 def reseed(self, seed: Any) -> None: 153 self._generator = np.random.default_rng(seed) 154 if isinstance(self._problem, WrappedProblem): 155 self._problem.reseed(seed)
16class GaussianNoise(WrappedProblem): 17 """ 18 A wrapper that adds a (multivariate) gaussian noise to a problem. 19 20 Assume that the output of the wrapped problem as an `F` numerical component 21 (as they almost always do). The following creates a new problem by adding a 22 `N(0, .2)` noise on all components of `F` (without any covariance): 23 24 mean_F = np.array([0., 0.]) 25 cov_F = .2 * np.eye(2) 26 noisy_problem = nmoo.GaussianNoise(problem, mean_F, cov_F) 27 28 Assume that in addition, the problem has a `G` numerical component to which 29 we would also like to add noise. The following a 0-mean 1-dimensional 30 gaussian noise along the plane antidiagonal (line with -pi/4 orientation) 31 to `G`, and the same noise as above to `F`: 32 33 mean_F = np.array([0., 0.]) 34 cov_F = .2 * np.eye(2) 35 mean_G = np.array([0., 0.]) 36 cov_G = np.array([[1., -1.], [-1., 1.]]) 37 noisy_problem = nmoo.GaussianNoise( 38 problem, { 39 "F": (mean_F, cov_F), 40 "G": (mean_G, cov_G), 41 }, 42 ) 43 44 """ 45 46 _generator: np.random.Generator 47 """Random number generator.""" 48 49 _parameters: Dict[str, Tuple[np.ndarray, np.ndarray]] 50 """ 51 Noise parameters. Each entry is a tuple containing the noise's mean vector 52 and covariance matrix. 53 """ 54 55 def __init__( 56 self, 57 problem: Problem, 58 mean: Optional[np.ndarray] = None, 59 covariance: Optional[Union[float, int, np.ndarray]] = None, 60 parameters: Optional[Dict[str, Tuple[np.ndarray, np.ndarray]]] = None, 61 seed: Any = None, 62 *, 63 name: str = "gaussian_noise", 64 **kwargs, 65 ): 66 """ 67 Args: 68 name (str): An optional name for this problem. This will be used 69 when creating history dump files. Defaults to `gaussian_noise`. 70 problem (pymoo `Problem`): A non-noisy pymoo problem (or 71 `nmoo.wrapped_problem.WrappedProblem`). 72 mean (optional `np.ndarray`): The mean vector of the gaussian 73 distribution. If specified, the `covariance` argument must also 74 be specified, and `parameters` must be left to its default 75 `None`. 76 covariance (optional `np.ndarray` or number): The covariance 77 matrix of the gaussian distribution. If specified, the `mean` 78 argument must also be specified, and `parameters` must be left 79 to its default `None`. For convenience, a number `v` can be 80 passed instead of a matrix, in which case the covariance matrix 81 is set to be `v * I_n`, where `n` is the dimension of the 82 `mean` vector. Note that `v` is then the variance of every 83 component of the distribution, **not the standard deviation**! 84 parameters (optional dict): Gaussian noise parameters, in the form 85 of a dict mapping the name of an objective to a numpy array 86 pair (mean, covariance matrix). The set of keys should be a 87 subset of the final `out` dictionary keys in the wrapped 88 problem's `_evaluate` method. If specified, the `mean` and 89 `covariance` arguments must be left to their default `None`. 90 seed: Seed for 91 [`numpy.random.default_rng`](https://numpy.org/doc/stable/reference/random/generator.html#numpy.random.default_rng) 92 """ 93 super().__init__(problem, name=name, **kwargs) 94 if mean is not None and covariance is not None and parameters is None: 95 if not isinstance(covariance, np.ndarray): 96 covariance = covariance * np.eye(mean.shape[0]) 97 self._parameters = {"F": (mean, covariance)} 98 elif mean is None and covariance is None and parameters is not None: 99 self._parameters = parameters 100 else: 101 raise ValueError( 102 "Invalid noise specification. Either mean and covariance are " 103 "both set, or a parameters dict is set." 104 ) 105 self.reseed(seed) 106 107 def _evaluate(self, x, out, *args, **kwargs): 108 """ 109 Calls the wrapped problems's `_evaluate` method and adds a Gaussian 110 noise. Adds the input (`x`), the noisy output, and the noise values to 111 history. 112 113 Example: 114 115 If the wrapped problem's output dict looks like: 116 117 { 118 "A": (n, m) np.ndarray, 119 "B": not an np.ndarray 120 } 121 122 then the history will look like this: 123 124 { 125 "A": an np.ndarray (with the noise added), 126 "A_noise": an np.ndarray of the same dimension 127 } 128 129 """ 130 self._problem._evaluate(x, out, *args, **kwargs) 131 noises: Dict[str, np.ndarray] = {} 132 for k in self._parameters.keys(): 133 try: 134 mean, cov = self._parameters[k] 135 noises[k] = self._generator.multivariate_normal( 136 mean, 137 cov, 138 out[k].shape[0], 139 ) 140 out[k] += noises[k] 141 except KeyError: 142 logging.error( 143 "Noise parameter key {} is not present in objective " 144 "function output keys. No noise will be applied. " 145 "Objective function keys: {}. ", 146 k, 147 str(list(out.keys())), 148 ) 149 self.add_to_history_x_out( 150 x, out, **{k + "_noise": v for k, v in noises.items()} 151 ) 152 153 def reseed(self, seed: Any) -> None: 154 self._generator = np.random.default_rng(seed) 155 if isinstance(self._problem, WrappedProblem): 156 self._problem.reseed(seed)
A wrapper that adds a (multivariate) gaussian noise to a problem.
Assume that the output of the wrapped problem as an F
numerical component
(as they almost always do). The following creates a new problem by adding a
N(0, .2)
noise on all components of F
(without any covariance):
mean_F = np.array([0., 0.])
cov_F = .2 * np.eye(2)
noisy_problem = nmoo.GaussianNoise(problem, mean_F, cov_F)
Assume that in addition, the problem has a G
numerical component to which
we would also like to add noise. The following a 0-mean 1-dimensional
gaussian noise along the plane antidiagonal (line with -pi/4 orientation)
to G
, and the same noise as above to F
:
mean_F = np.array([0., 0.])
cov_F = .2 * np.eye(2)
mean_G = np.array([0., 0.])
cov_G = np.array([[1., -1.], [-1., 1.]])
noisy_problem = nmoo.GaussianNoise(
problem, {
"F": (mean_F, cov_F),
"G": (mean_G, cov_G),
},
)
GaussianNoise( problem: pymoo.core.problem.Problem, mean: Union[numpy.ndarray, NoneType] = None, covariance: Union[float, int, numpy.ndarray, NoneType] = None, parameters: Union[Dict[str, Tuple[numpy.ndarray, numpy.ndarray]], NoneType] = None, seed: Any = None, *, name: str = 'gaussian_noise', **kwargs)
55 def __init__( 56 self, 57 problem: Problem, 58 mean: Optional[np.ndarray] = None, 59 covariance: Optional[Union[float, int, np.ndarray]] = None, 60 parameters: Optional[Dict[str, Tuple[np.ndarray, np.ndarray]]] = None, 61 seed: Any = None, 62 *, 63 name: str = "gaussian_noise", 64 **kwargs, 65 ): 66 """ 67 Args: 68 name (str): An optional name for this problem. This will be used 69 when creating history dump files. Defaults to `gaussian_noise`. 70 problem (pymoo `Problem`): A non-noisy pymoo problem (or 71 `nmoo.wrapped_problem.WrappedProblem`). 72 mean (optional `np.ndarray`): The mean vector of the gaussian 73 distribution. If specified, the `covariance` argument must also 74 be specified, and `parameters` must be left to its default 75 `None`. 76 covariance (optional `np.ndarray` or number): The covariance 77 matrix of the gaussian distribution. If specified, the `mean` 78 argument must also be specified, and `parameters` must be left 79 to its default `None`. For convenience, a number `v` can be 80 passed instead of a matrix, in which case the covariance matrix 81 is set to be `v * I_n`, where `n` is the dimension of the 82 `mean` vector. Note that `v` is then the variance of every 83 component of the distribution, **not the standard deviation**! 84 parameters (optional dict): Gaussian noise parameters, in the form 85 of a dict mapping the name of an objective to a numpy array 86 pair (mean, covariance matrix). The set of keys should be a 87 subset of the final `out` dictionary keys in the wrapped 88 problem's `_evaluate` method. If specified, the `mean` and 89 `covariance` arguments must be left to their default `None`. 90 seed: Seed for 91 [`numpy.random.default_rng`](https://numpy.org/doc/stable/reference/random/generator.html#numpy.random.default_rng) 92 """ 93 super().__init__(problem, name=name, **kwargs) 94 if mean is not None and covariance is not None and parameters is None: 95 if not isinstance(covariance, np.ndarray): 96 covariance = covariance * np.eye(mean.shape[0]) 97 self._parameters = {"F": (mean, covariance)} 98 elif mean is None and covariance is None and parameters is not None: 99 self._parameters = parameters 100 else: 101 raise ValueError( 102 "Invalid noise specification. Either mean and covariance are " 103 "both set, or a parameters dict is set." 104 ) 105 self.reseed(seed)
Arguments:
- name (str): An optional name for this problem. This will be used
when creating history dump files. Defaults to
gaussian_noise
. - problem (pymoo
Problem
): A non-noisy pymoo problem (ornmoo.wrapped_problem.WrappedProblem
). - mean (optional
np.ndarray
): The mean vector of the gaussian distribution. If specified, thecovariance
argument must also be specified, andparameters
must be left to its defaultNone
. - covariance (optional
np.ndarray
or number): The covariance matrix of the gaussian distribution. If specified, themean
argument must also be specified, andparameters
must be left to its defaultNone
. For convenience, a numberv
can be passed instead of a matrix, in which case the covariance matrix is set to bev * I_n
, wheren
is the dimension of themean
vector. Note thatv
is then the variance of every component of the distribution, not the standard deviation! - parameters (optional dict): Gaussian noise parameters, in the form
of a dict mapping the name of an objective to a numpy array
pair (mean, covariance matrix). The set of keys should be a
subset of the final
out
dictionary keys in the wrapped problem's_evaluate
method. If specified, themean
andcovariance
arguments must be left to their defaultNone
. - seed: Seed for
numpy.random.default_rng
def
reseed(self, seed: Any) -> None:
153 def reseed(self, seed: Any) -> None: 154 self._generator = np.random.default_rng(seed) 155 if isinstance(self._problem, WrappedProblem): 156 self._problem.reseed(seed)
Recursively resets the internal random state of the problem. See the numpy documentation for details about acceptable seeds.
Inherited Members
- nmoo.wrapped_problem.WrappedProblem
- add_to_history
- add_to_history_x_out
- all_layers
- depth
- dump_all_histories
- dump_history
- ground_problem
- innermost_wrapper
- start_new_run
- pymoo.core.problem.Problem
- evaluate
- do
- nadir_point
- ideal_point
- pareto_front
- pareto_set
- has_bounds
- has_constraints
- bounds
- name
- calc_constraint_violation