Coverage for moptipy / api / mo_process.py: 89%
19 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"""
2Processes offer data to both the user and the optimization algorithm.
4They provide the information about the optimization process and its current
5state as handed to the optimization algorithm and, after the algorithm has
6finished, to the user.
7This is the multi-objective version of the :class:`~moptipy.api.process.\
8Process`-API.
9It supports having multiple objective functions.
10It also provides a single core objective value, which is the scalarized
11result of several objective values.
12"""
13from typing import Any, Callable, Iterable
15import numpy as np
17from moptipy.api.mo_archive import MORecord
18from moptipy.api.mo_problem import MOProblem
19from moptipy.api.process import Process
22class MOProcess(MOProblem, Process):
23 """
24 A multi-objective :class:`~moptipy.api.process.Process` API variant.
26 This class encapsulates an optimization process using multiple objective
27 functions. It inherits all of its methods from the single-objective
28 process :class:`~moptipy.api.process.Process` and extends its API towards
29 multi-objective optimization by providing the functionality of the class
30 :class:`~moptipy.api.mo_problem.MOProblem`.
31 """
33 def register(self, x, f: int | float) -> None:
34 """Unavailable during multi-objective optimization."""
35 raise ValueError(
36 "register is not available during multi-objective optimization.")
38 def get_archive(self) -> list[MORecord]:
39 """
40 Get the archive of non-dominated solutions.
42 :returns: a list containing all non-dominated solutions currently in
43 the archive
44 """
46 def check_in(self, x: Any, fs: np.ndarray,
47 prune_if_necessary: bool = False) -> bool:
48 """
49 Check a solution into the archive.
51 This method is intended for being invoked after the optimization
52 algorithm has finished its work. The algorithm should, by itself,
53 maintain the set of interesting solutions during its course. Once
54 it has completed all of its computations, it should flush these
55 solutions to the process using this method. All the non-dominated
56 solutions preserved in the archive will then become available via
57 :meth:`get_archive` to the code starting the optimization procedure.
59 If you have a sequence of :class:`~moptipy.api.mo_archive.MORecord`
60 instances that you want to flush into the archive, you can use the
61 convenience method :meth:`~check_in_all` for that purpose.
63 :param x: the point in the search space
64 :param fs: the vector of objective values
65 :param prune_if_necessary: should we prune the archive if it becomes
66 too large? `False` means that the archive may grow unbounded
67 :returns: `True` if the solution was non-dominated and has actually
68 entered the archive, `False` if it has not entered the archive
69 """
71 def check_in_all(self, recs: Iterable[MORecord],
72 prune_if_necessary: bool = False) -> None:
73 """
74 Check in all the elements of an `Iterable` of `MORecord` instances.
76 This is a convenience wrapper around :meth:`~check_in`.
78 :param recs: an iterable sequence of solution + quality vector records
79 :param prune_if_necessary: should we prune the archive if it becomes
80 too large? `False` means that the archive may grow unbounded
81 """
82 sci: Callable[[Any, np.ndarray, bool], bool] = self.check_in
83 for r in recs:
84 sci(r.x, r.fs, prune_if_necessary)
86 def get_copy_of_best_fs(self, fs: np.ndarray) -> None:
87 """
88 Get a copy of the objective vector of the current best solution.
90 This always corresponds to the best-so-far solution based on the
91 scalarization of the objective vector. It is the best solution that
92 the process has seen *so far*, the current best solution.
94 You should only call this method if you are either sure that you
95 have invoked :meth:`~moptipy.api.process.Process.evaluate`, have
96 invoked :meth:`~moptipy.api.mo_problem.MOProblem.f_evaluate`, or
97 have called :meth:`~moptipy.api.process.Process.has_best` before
98 and it returned `True`.
100 :param fs: the destination vector to be overwritten
102 See Also
103 - :meth:`~moptipy.api.process.Process.has_best`
104 - :meth:`~moptipy.api.process.Process.get_best_f`
105 - :meth:`~moptipy.api.process.Process.get_copy_of_best_x`
106 - :meth:`~moptipy.api.process.Process.get_copy_of_best_y`
107 - :meth:`~moptipy.api.mo_problem.MOProblem.f_evaluate`
108 """
110 def __str__(self) -> str:
111 """
112 Get the name of this process implementation.
114 :return: "mo_process"
115 """
116 return "mo_process"
118 def __enter__(self) -> "MOProcess":
119 """
120 Begin a `with` statement.
122 :return: this process itself
123 """
124 return self