Coverage for moptipy / operators / op0_forward.py: 95%
21 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-24 08:49 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-24 08:49 +0000
1"""
2A nullary operator forwarding to another function.
4This is a nullary operator (an instance of
5:class:`~moptipy.api.operators.Op0`) whose method
6:meth:`~moptipy.api.operators.Op0.op0` forwards to another `Callable`.
7This other `Callable` can then return a solution that is created in some
8special way, or maybe even the current best solution of a search process.
10This operator has been designed to be used in conjunction with
11:func:`~moptipy.api.subprocesses.from_starting_point`, which is an
12optimization :class:`~moptipy.api.process.Process` where a starting point
13has been defined, i.e., where the methods
14:meth:`~moptipy.api.process.Process.get_copy_of_best_x` and
15:meth:`~moptipy.api.process.Process.get_best_f` return pre-defined values.
16By setting :meth:`~moptipy.operators.op0_forward.Op0Forward.forward_to` to
17:meth:`~moptipy.api.process.Process.get_copy_of_best_x`, this nullary operator
18will return the current-best solution of the optimization process, which, in
19this case, will be the pre-defined starting point.
20Any optimization algorithm (e.g., an instance of
21:class:`~moptipy.api.algorithm.Algorithm0`) using this nullary operator to get
22its initial solution will then begin the search at this pre-defined starting
23point. This allows using one algorithm as a sub-algorithm of another one.
24Wrapping :func:`~moptipy.api.subprocesses.from_starting_point` around the
25result of a call to :func:`~moptipy.api.subprocesses.for_fes` would allow to
26limit the number of objective function evaluations consumed by the
27sub-algorithm.
28"""
29from typing import Any, Callable
31import numpy as np
32from numpy.random import Generator
33from pycommons.types import type_error
35from moptipy.api.operators import Op0
38class Op0Forward(Op0):
39 """A nullary operator that forwards all calls to `op0` to a `Callable`."""
41 def __init__(self):
42 """Initialize this operator."""
43 #: the internal blueprint for filling permutations
44 self.__call: Callable[[Any], None] | None = None
46 def op0(self, random: Generator, dest: np.ndarray) -> None:
47 """
48 Forward the call.
50 :param random: ignored
51 :param dest: the destination data structure to be filled with the data
52 of the point in the search space by the internal `Callable` set by
53 :meth:`forward_to`.
54 """
55 self.__call(dest)
57 def forward_to(self, call: Callable[[Any], None]) -> None:
58 """
59 Set the `Callable` to forward all calls from :meth:`op0` to.
61 :param call: the `Callable` to which all calls to :meth:`op0` should
62 be delegated to.
63 """
64 if not callable(call):
65 raise type_error(call, "call", call=True)
66 self.__call = call
68 def stop_forwarding(self) -> None:
69 """Stop forwarding the call."""
70 self.__call = None
72 def __str__(self) -> str:
73 """
74 Get the name of this operator.
76 :return: "forward"
77 """
78 return "forward"
80 def initialize(self) -> None:
81 """Initialize this operator by stopping to forward."""
82 super().initialize()
83 self.stop_forwarding()