Coverage for moptipy / algorithms / modules / selection.py: 88%
16 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"""
2Selection algorithms are common modules that choose `n` out of `N` objects.
4Selection algorithms are modules of the fully-configurable Evolutionary
5Algorithm :class:`~moptipy.algorithms.so.general_ea.GeneralEA`. They can
6utilize fitness values computed by the fitness assignment processes
7(:class:`~moptipy.algorithms.so.fitness.Fitness`). Of course, they can
8also be applied in different contexts and are not bound to single-objective
9optimization.
11:class:`~moptipy.algorithms.modules.selection.Selection` is especially
12important in Evolutionary Algorithms
13(`~moptipy.algorithms.so.general_ea.GeneralEA`), where it is used in two
14places: As *survival selection*, it chooses which points will be allowed to
15remain in the population and, hence, survive into the mating pool for the next
16generation. As *mating selection* methods, they choose the inputs of the
17search operations from the mating pool.
19:class:`~moptipy.algorithms.modules.selection.Selection` algorithms must
20*only* use the
21:attr:`~moptipy.algorithms.modules.selection.FitnessRecord.fitness` of a
22solution record (and random numbers) to make their decisions. These fitness
23values are subject to minimization. They can equal to the objective values in
24optimization or stem from a :class:`~moptipy.algorithms.so.fitness.Fitness`
25Assignment Process.
27The following selection algorithms have currently been implemented:
29- :class:`~moptipy.algorithms.modules.selections.best.Best` selection
30 selects the best `n` solutions without replacement. This is a common
31 strategy for survival selection, especially in (mu+lambda) EAs
32 (compatible to :class:`~moptipy.algorithms.so.ea.EA`).
33- :class:`~moptipy.algorithms.modules.selections.random_without_repl\
34.RandomWithoutReplacement` selects random solutions without replacement. It is
35 a common strategy for mating selection.
36- :class:`~moptipy.algorithms.modules.selections.fitness_proportionate_sus\
37.FitnessProportionateSUS` performs fitness proportionate selection for
38 minimization using stochastic uniform sampling and, optionally, a minimum
39 selection probability threshold. It is the classic survival selection
40 algorithm in Genetic Algorithm.
41- :class:`~moptipy.algorithms.modules.selections.tournament_with_repl.\
42TournamentWithReplacement`
43 performs tournament selection with a specified tournament size with
44 replacement.
45- :class:`~moptipy.algorithms.modules.selections.tournament_without_repl.\
46TournamentWithoutReplacement`
47 performs tournament selection with a specified tournament size without
48 replacement.
49"""
50from typing import Any, Callable, Protocol
52from numpy.random import Generator
53from pycommons.types import type_error
55from moptipy.api.component import Component
58# start book
59class FitnessRecord(Protocol):
60 """A fitness record stores data together with a fitness."""
62# end book
63 #: the fitness value, which can either be an integer or a float and
64 #: is the only criterion to be used by a selection
65 #: algorithm (besides random numbers)
66 fitness: float
68 def __lt__(self, other) -> bool:
69 """
70 Compare the fitness of this record with the fitness of another one.
72 :param other: the other fitness record
73 """
74 return self.fitness < other.fitness
75# start book
78class Selection(Component):
79 """The base class for selections algorithms."""
81 def select(self, source: list[FitnessRecord],
82 dest: Callable[[FitnessRecord], Any],
83 n: int, random: Generator) -> None: # pylint: disable=W0613
84 """
85 Select `n` records from `source` and pass them to `dest`.
87 When choosing the `n` records from `source` to be passed to
88 `dest`, only the :attr:`~FitnessRecord.fitness` attribute of
89 the records and the random numbers from `random` must be used
90 as decision criteria.
92 :param source: the list with the records to select from
93 :param dest: the destination collector Callable to invoke for
94 each selected record, can be :class:`list`.`append`.
95 :param n: the number of records to select
96 :param random: the random number generator
97 """
98# end book
101def check_selection(selection: Selection) -> Selection:
102 """
103 Check whether an object is a valid instance of :class:`Selection`.
105 :param selection: the Selection object
106 :return: the object
107 :raises TypeError: if `selections` is not an instance of
108 :class:`Selection` or if it is an instance of the abstract base
109 class
110 """
111 if not isinstance(selection, Selection):
112 raise type_error(selection, "selections", Selection)
113 if selection.__class__ is Selection:
114 raise TypeError("cannot use abstract class 'Selection' directly")
115 return selection