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

1""" 

2Select `n` records at random without replacement. 

3 

4This selection scheme is the standard mating selection scheme in an 

5Evolutionary Algorithm. 

6""" 

7 

8from typing import Any, Callable, Final 

9 

10from numpy.random import Generator 

11 

12from moptipy.algorithms.modules.selection import FitnessRecord, Selection 

13 

14 

15# start book 

16class RandomWithoutReplacement(Selection): 

17 """Select random elements without replacement.""" 

18 

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. 

24 

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 

45 

46 def __str__(self): 

47 """ 

48 Get the name of the random choice without replacement selection. 

49 

50 :return: the name of the random choice without replacement selection 

51 algorithm 

52 """ 

53 return "rndNoRep"