Coverage for moptipy / algorithms / modules / selections / random_without_repl.py: 100%
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"""
2Select `n` records at random without replacement.
4This selection scheme is the standard mating selection scheme in an
5Evolutionary Algorithm.
6"""
8from typing import Any, Callable, Final
10from numpy.random import Generator
12from moptipy.algorithms.modules.selection import FitnessRecord, Selection
15# start book
16class RandomWithoutReplacement(Selection):
17 """Select random elements without replacement."""
19 def select(self, source: list[FitnessRecord],
20 dest: Callable[[FitnessRecord], Any],
21 n: int, random: Generator) -> None:
22 """
23 Select `n` random elements from `source` without replacement.
25 :param source: the list with the records to select from
26 :param dest: the destination collector to invoke for each selected
27 record
28 :param n: the number of records to select
29 :param random: the random number generator
30 """
31 m: Final[int] = len(source)
32 if n == 1: # handle n=1 exactly as in (mu+lambda) EA
33 dest(source[random.integers(m)]) # pick 1 solution randomly
34 elif n == 2: # handle n=2 exactly as in (mu+lambda) EA
35 ri = random.integers # fast call
36 a = b = ri(m) # get first random index
37 while a == b: # find a second, different random index
38 b = ri(m)
39 dest(source[a]) # send first solution to dest
40 dest(source[b]) # send second solution to dest
41 else: # handle other cases: n ints from 0..m-1 w/o replacement
42 for i in random.choice(m, n, False): # get the ints
43 dest(source[i]) # send randomly chosen records to dest
44# end book
46 def __str__(self):
47 """
48 Get the name of the random choice without replacement selection.
50 :return: the name of the random choice without replacement selection
51 algorithm
52 """
53 return "rndNoRep"