nmoo.noises.uniform

Wrapper that generates a uniform noise.

  1"""
  2Wrapper that generates a uniform noise.
  3"""
  4__docformat__ = "google"
  5
  6from typing import Any, Dict, List, 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 UniformNoise(WrappedProblem):
 16    """
 17    A wrapper that adds a uniform 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) of dimension 2. The following creates a new
 21    problem by adding a `U(-1, 1)` noise on all components of `F` (without any
 22    covariance):
 23
 24        noisy_problem = nmoo.UniformNoise(problem, 1)
 25
 26    The following adds a `U(-1, 1)` noise on the first component of `F` but a
 27    `U(-2, 2)` noise on the second:
 28
 29        noisy_problem = nmoo.UniformNoise(problem, [1, 2])
 30
 31    For biased noises (i.e. with nonzero mean), the min and max values of every
 32    distribution must be specified. For example the following adds a `U(-.1,
 33    1)` noise on the first component of `F` but a `U(-.2, 2)` noise on the
 34    second:
 35
 36        noisy_problem = nmoo.UniformNoise(problem, [[-.1, 1], [-.2, 2]])
 37
 38    Note that mixed bound specifications such as
 39
 40        noisy_problem = nmoo.UniformNoise(problem, [[-.1, 1], 2])
 41        # instead of [[-.1, 1], [-2, 2]]
 42
 43    is not possible.
 44
 45    If you want to add noise to more outputs of the wrapped problem, a
 46    parameter specification like `nmoo.noises.GaussianNoise` is also possible.
 47    For example, assume that the problem has a `G` numerical component. To
 48    apply a `U(-3, 3)` to all components of `G`, together with the noise above
 49    for `F`,
 50
 51        noisy_problem = nmoo.UniformNoise(
 52            problem,
 53            {
 54                "F": [[-.1, 1], [-.2, 2]],
 55                "G": 3,
 56            }
 57        )
 58
 59    """
 60
 61    _generator: np.random.Generator
 62    """Random number generator."""
 63
 64    _parameters: Dict[str, List[Tuple[float, float]]] = {}
 65    """Noise parameters."""
 66
 67    def __init__(
 68        self,
 69        problem: Problem,
 70        parameters: Union[
 71            float,
 72            Tuple[float, float],
 73            List[Tuple[float, float]],
 74            Dict[
 75                str,
 76                Union[
 77                    float,
 78                    Tuple[float, float],
 79                    List[Tuple[float, float]],
 80                ],
 81            ],
 82        ],
 83        seed: Any = None,
 84        *,
 85        name: str = "uniform_noise",
 86        **kwargs,
 87    ):
 88        """
 89        Args:
 90            name (str): An optional name for this problem. This will be used
 91                when creating history dump files. Defaults to `gaussian_noise`.
 92            problem (pymoo `Problem`): A non-noisy pymoo problem (or
 93                `nmoo.wrapped_problem.WrappedProblem`).
 94            parameters: See the examples above.
 95            seed: Seed for
 96                [`numpy.random.default_rng`](https://numpy.org/doc/stable/reference/random/generator.html#numpy.random.default_rng)
 97        """
 98        super().__init__(problem, name=name, **kwargs)
 99        if not isinstance(parameters, dict):
100            parameters = {"F": parameters}
101        try:
102            for k, v in parameters.items():
103                if isinstance(v, (float, int)):
104                    assert v >= 0
105                    self._parameters[k] = [(-v, v)]
106                elif isinstance(v, (list, tuple)) and isinstance(v[0], list):
107                    # v expected to be a list of min-max tuples
108                    for w in v:
109                        assert isinstance(w, (list, tuple))
110                        assert len(w) == 2
111                        assert w[0] <= w[1]
112                    self._parameters[k] = parameters[k]
113                else:
114                    # v is expected to be a list of numbers
115                    self._parameters[k] = []
116                    for a in v:
117                        assert isinstance(a, (float, int))
118                        assert a >= 0
119                        self._parameters[k].append((-a, a))
120        except AssertionError as e:
121            raise ValueError("Invalid noise parameters") from e
122        self.reseed(seed)
123
124    # pylint: disable=duplicate-code
125    def _evaluate(self, x, out, *args, **kwargs):
126        """
127        Calls the wrapped problems's `_evaluate` method and adds a uniform
128        noise. The history scheme is the same as in
129        `nmoo.noises.GaussianNoise._evaluate`.
130        """
131        self._problem._evaluate(x, out, *args, **kwargs)
132        noises: Dict[str, np.ndarray] = {}
133        for k, v in self._parameters.items():
134            try:
135                noises[k] = np.stack(
136                    [
137                        self._generator.uniform(*b, size=out[k].shape[0])
138                        for b in v
139                    ],
140                    axis=-1,
141                )
142                out[k] += noises[k]
143            except KeyError:
144                logging.error(
145                    "Noise parameter key {} is not present in objective "
146                    "function output keys. No noise will be applied. "
147                    "Objective function keys: {}.",
148                    k,
149                    str(list(out.keys())),
150                )
151        self.add_to_history_x_out(
152            x, out, **{k + "_noise": v for k, v in noises.items()}
153        )
154
155    def reseed(self, seed: Any) -> None:
156        self._generator = np.random.default_rng(seed)
157        if isinstance(self._problem, WrappedProblem):
158            self._problem.reseed(seed)
class UniformNoise(nmoo.wrapped_problem.WrappedProblem):
 16class UniformNoise(WrappedProblem):
 17    """
 18    A wrapper that adds a uniform 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) of dimension 2. The following creates a new
 22    problem by adding a `U(-1, 1)` noise on all components of `F` (without any
 23    covariance):
 24
 25        noisy_problem = nmoo.UniformNoise(problem, 1)
 26
 27    The following adds a `U(-1, 1)` noise on the first component of `F` but a
 28    `U(-2, 2)` noise on the second:
 29
 30        noisy_problem = nmoo.UniformNoise(problem, [1, 2])
 31
 32    For biased noises (i.e. with nonzero mean), the min and max values of every
 33    distribution must be specified. For example the following adds a `U(-.1,
 34    1)` noise on the first component of `F` but a `U(-.2, 2)` noise on the
 35    second:
 36
 37        noisy_problem = nmoo.UniformNoise(problem, [[-.1, 1], [-.2, 2]])
 38
 39    Note that mixed bound specifications such as
 40
 41        noisy_problem = nmoo.UniformNoise(problem, [[-.1, 1], 2])
 42        # instead of [[-.1, 1], [-2, 2]]
 43
 44    is not possible.
 45
 46    If you want to add noise to more outputs of the wrapped problem, a
 47    parameter specification like `nmoo.noises.GaussianNoise` is also possible.
 48    For example, assume that the problem has a `G` numerical component. To
 49    apply a `U(-3, 3)` to all components of `G`, together with the noise above
 50    for `F`,
 51
 52        noisy_problem = nmoo.UniformNoise(
 53            problem,
 54            {
 55                "F": [[-.1, 1], [-.2, 2]],
 56                "G": 3,
 57            }
 58        )
 59
 60    """
 61
 62    _generator: np.random.Generator
 63    """Random number generator."""
 64
 65    _parameters: Dict[str, List[Tuple[float, float]]] = {}
 66    """Noise parameters."""
 67
 68    def __init__(
 69        self,
 70        problem: Problem,
 71        parameters: Union[
 72            float,
 73            Tuple[float, float],
 74            List[Tuple[float, float]],
 75            Dict[
 76                str,
 77                Union[
 78                    float,
 79                    Tuple[float, float],
 80                    List[Tuple[float, float]],
 81                ],
 82            ],
 83        ],
 84        seed: Any = None,
 85        *,
 86        name: str = "uniform_noise",
 87        **kwargs,
 88    ):
 89        """
 90        Args:
 91            name (str): An optional name for this problem. This will be used
 92                when creating history dump files. Defaults to `gaussian_noise`.
 93            problem (pymoo `Problem`): A non-noisy pymoo problem (or
 94                `nmoo.wrapped_problem.WrappedProblem`).
 95            parameters: See the examples above.
 96            seed: Seed for
 97                [`numpy.random.default_rng`](https://numpy.org/doc/stable/reference/random/generator.html#numpy.random.default_rng)
 98        """
 99        super().__init__(problem, name=name, **kwargs)
100        if not isinstance(parameters, dict):
101            parameters = {"F": parameters}
102        try:
103            for k, v in parameters.items():
104                if isinstance(v, (float, int)):
105                    assert v >= 0
106                    self._parameters[k] = [(-v, v)]
107                elif isinstance(v, (list, tuple)) and isinstance(v[0], list):
108                    # v expected to be a list of min-max tuples
109                    for w in v:
110                        assert isinstance(w, (list, tuple))
111                        assert len(w) == 2
112                        assert w[0] <= w[1]
113                    self._parameters[k] = parameters[k]
114                else:
115                    # v is expected to be a list of numbers
116                    self._parameters[k] = []
117                    for a in v:
118                        assert isinstance(a, (float, int))
119                        assert a >= 0
120                        self._parameters[k].append((-a, a))
121        except AssertionError as e:
122            raise ValueError("Invalid noise parameters") from e
123        self.reseed(seed)
124
125    # pylint: disable=duplicate-code
126    def _evaluate(self, x, out, *args, **kwargs):
127        """
128        Calls the wrapped problems's `_evaluate` method and adds a uniform
129        noise. The history scheme is the same as in
130        `nmoo.noises.GaussianNoise._evaluate`.
131        """
132        self._problem._evaluate(x, out, *args, **kwargs)
133        noises: Dict[str, np.ndarray] = {}
134        for k, v in self._parameters.items():
135            try:
136                noises[k] = np.stack(
137                    [
138                        self._generator.uniform(*b, size=out[k].shape[0])
139                        for b in v
140                    ],
141                    axis=-1,
142                )
143                out[k] += noises[k]
144            except KeyError:
145                logging.error(
146                    "Noise parameter key {} is not present in objective "
147                    "function output keys. No noise will be applied. "
148                    "Objective function keys: {}.",
149                    k,
150                    str(list(out.keys())),
151                )
152        self.add_to_history_x_out(
153            x, out, **{k + "_noise": v for k, v in noises.items()}
154        )
155
156    def reseed(self, seed: Any) -> None:
157        self._generator = np.random.default_rng(seed)
158        if isinstance(self._problem, WrappedProblem):
159            self._problem.reseed(seed)

A wrapper that adds a uniform noise to a problem.

Assume that the output of the wrapped problem as an F numerical component (as they almost always do) of dimension 2. The following creates a new problem by adding a U(-1, 1) noise on all components of F (without any covariance):

noisy_problem = nmoo.UniformNoise(problem, 1)

The following adds a U(-1, 1) noise on the first component of F but a U(-2, 2) noise on the second:

noisy_problem = nmoo.UniformNoise(problem, [1, 2])

For biased noises (i.e. with nonzero mean), the min and max values of every distribution must be specified. For example the following adds a U(-.1, 1) noise on the first component of F but a U(-.2, 2) noise on the second:

noisy_problem = nmoo.UniformNoise(problem, [[-.1, 1], [-.2, 2]])

Note that mixed bound specifications such as

noisy_problem = nmoo.UniformNoise(problem, [[-.1, 1], 2])
# instead of [[-.1, 1], [-2, 2]]

is not possible.

If you want to add noise to more outputs of the wrapped problem, a parameter specification like nmoo.noises.GaussianNoise is also possible. For example, assume that the problem has a G numerical component. To apply a U(-3, 3) to all components of G, together with the noise above for F,

noisy_problem = nmoo.UniformNoise(
    problem,
    {
        "F": [[-.1, 1], [-.2, 2]],
        "G": 3,
    }
)
UniformNoise( problem: pymoo.core.problem.Problem, parameters: Union[float, Tuple[float, float], List[Tuple[float, float]], Dict[str, Union[float, Tuple[float, float], List[Tuple[float, float]]]]], seed: Any = None, *, name: str = 'uniform_noise', **kwargs)
 68    def __init__(
 69        self,
 70        problem: Problem,
 71        parameters: Union[
 72            float,
 73            Tuple[float, float],
 74            List[Tuple[float, float]],
 75            Dict[
 76                str,
 77                Union[
 78                    float,
 79                    Tuple[float, float],
 80                    List[Tuple[float, float]],
 81                ],
 82            ],
 83        ],
 84        seed: Any = None,
 85        *,
 86        name: str = "uniform_noise",
 87        **kwargs,
 88    ):
 89        """
 90        Args:
 91            name (str): An optional name for this problem. This will be used
 92                when creating history dump files. Defaults to `gaussian_noise`.
 93            problem (pymoo `Problem`): A non-noisy pymoo problem (or
 94                `nmoo.wrapped_problem.WrappedProblem`).
 95            parameters: See the examples above.
 96            seed: Seed for
 97                [`numpy.random.default_rng`](https://numpy.org/doc/stable/reference/random/generator.html#numpy.random.default_rng)
 98        """
 99        super().__init__(problem, name=name, **kwargs)
100        if not isinstance(parameters, dict):
101            parameters = {"F": parameters}
102        try:
103            for k, v in parameters.items():
104                if isinstance(v, (float, int)):
105                    assert v >= 0
106                    self._parameters[k] = [(-v, v)]
107                elif isinstance(v, (list, tuple)) and isinstance(v[0], list):
108                    # v expected to be a list of min-max tuples
109                    for w in v:
110                        assert isinstance(w, (list, tuple))
111                        assert len(w) == 2
112                        assert w[0] <= w[1]
113                    self._parameters[k] = parameters[k]
114                else:
115                    # v is expected to be a list of numbers
116                    self._parameters[k] = []
117                    for a in v:
118                        assert isinstance(a, (float, int))
119                        assert a >= 0
120                        self._parameters[k].append((-a, a))
121        except AssertionError as e:
122            raise ValueError("Invalid noise parameters") from e
123        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 (or nmoo.wrapped_problem.WrappedProblem).
  • parameters: See the examples above.
  • seed: Seed for numpy.random.default_rng
def reseed(self, seed: Any) -> None:
156    def reseed(self, seed: Any) -> None:
157        self._generator = np.random.default_rng(seed)
158        if isinstance(self._problem, WrappedProblem):
159            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