Coverage for moptipy / tests / on_permutations.py: 91%
65 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"""Test stuff on permutations with repetitions."""
3from typing import Any, Callable, Iterable, cast
5import numpy as np
6from numpy.random import Generator, default_rng
7from pycommons.types import type_error
9from moptipy.api.operators import Op0, Op1, Op1WithStepSize, Op2
10from moptipy.spaces.permutations import Permutations
11from moptipy.tests.op0 import validate_op0
12from moptipy.tests.op1 import validate_op1
13from moptipy.tests.op1_with_step_size import validate_op1_with_step_size
14from moptipy.tests.op2 import validate_op2
17def permutations_for_tests(
18 perm_filter: Callable[[Permutations], bool] | None = None) \
19 -> Iterable[Permutations]:
20 """
21 Get a sequence of permutations for tests.
23 :param perm_filter: an optional filter to sort out permutations we cannot
24 use for testing
25 :returns: the sequence of Permutations
26 """
27 r = default_rng()
28 pwrs: list[Permutations] = [
29 Permutations.standard(2),
30 Permutations.standard(3),
31 Permutations.standard(4),
32 Permutations.standard(5),
33 Permutations.standard(6),
34 Permutations.standard(12),
35 Permutations.standard(23),
36 Permutations.with_repetitions(2, 2),
37 Permutations.with_repetitions(2, 3),
38 Permutations.with_repetitions(3, 2),
39 Permutations.with_repetitions(3, 3),
40 Permutations.with_repetitions(5, 5),
41 Permutations.with_repetitions(int(r.integers(6, 10)),
42 int(r.integers(2, 7))),
43 Permutations.with_repetitions(int(r.integers(2, 5)),
44 int(r.integers(6, 10))),
45 Permutations.with_repetitions(int(r.integers(130, 500)),
46 int(r.integers(2, 200))),
47 Permutations([1, 1, 1, 1, 1, 5, 5, 3]),
48 Permutations([0, 1, 1, 1, 1, 1])]
49 if perm_filter is not None:
50 if not callable(perm_filter):
51 raise type_error(perm_filter, "perm_filter", None, call=True)
52 pwrs = [p for p in pwrs if perm_filter(p)]
53 r.shuffle(cast("list", pwrs))
54 return pwrs
57def make_permutation_valid(pwr: Permutations) -> \
58 Callable[[Generator, np.ndarray], np.ndarray]:
59 """
60 Create a function that can make permutations with repetitions valid.
62 :param pwr: the permutations
63 :returns: the function
64 """
65 def __make_valid(prnd: Generator, x: np.ndarray, ppp=pwr) -> np.ndarray:
66 np.copyto(x, ppp.blueprint)
67 prnd.shuffle(x)
68 return x
69 return __make_valid
72def validate_op0_on_1_permutations(
73 op0: Op0 | Callable[[Permutations], Op0],
74 search_space: Permutations,
75 number_of_samples: int | None = None,
76 min_unique_samples: int | Callable[[
77 int, Permutations], int] | None = None) -> None:
78 """
79 Validate the nullary operator on one `Permutations` instance.
81 :param op0: the operator or operator factory
82 :param search_space: the search space
83 :param number_of_samples: the optional number of samples
84 :param min_unique_samples: the optional unique samples
85 """
86 args: dict[str, Any] = {
87 "op0": op0(search_space) if callable(op0) else op0,
88 "search_space": search_space,
89 "make_search_space_element_valid":
90 make_permutation_valid(search_space),
91 }
92 if number_of_samples is not None:
93 args["number_of_samples"] = number_of_samples
94 if min_unique_samples is not None:
95 args["min_unique_samples"] = min_unique_samples
96 validate_op0(**args)
99def validate_op0_on_permutations(
100 op0: Op0 | Callable[[Permutations], Op0],
101 number_of_samples: int | None = None,
102 min_unique_samples: int | Callable[[
103 int, Permutations], int] | None = None,
104 perm_filter: Callable[[Permutations], bool] | None = None) -> None:
105 """
106 Validate the nullary operator on several `Permutations` instances.
108 :param op0: the operator or operator factory
109 :param number_of_samples: the optional number of samples
110 :param min_unique_samples: the optional unique samples
111 :param perm_filter: an optional filter to sort out permutations we cannot
112 use for testing
113 """
114 for pwr in permutations_for_tests(perm_filter):
115 validate_op0_on_1_permutations(op0, pwr, number_of_samples,
116 min_unique_samples)
119def validate_op1_on_1_permutations(
120 op1: Op1 | Callable[[Permutations], Op1],
121 search_space: Permutations,
122 number_of_samples: int | None = None,
123 min_unique_samples: int | Callable[[
124 int, Permutations], int] | None = None) -> None:
125 """
126 Validate the unary operator on one `Permutations` instance.
128 :param op1: the operator or operator factory
129 :param search_space: the search space
130 :param number_of_samples: the optional number of samples
131 :param min_unique_samples: the optional unique samples
132 """
133 args: dict[str, Any] = {
134 "op1": op1(search_space) if callable(op1) else op1,
135 "search_space": search_space,
136 "make_search_space_element_valid":
137 make_permutation_valid(search_space),
138 }
139 if number_of_samples is not None:
140 args["number_of_samples"] = number_of_samples
141 if min_unique_samples is not None:
142 args["min_unique_samples"] = min_unique_samples
143 validate_op1(**args)
146def validate_op1_on_permutations(
147 op1: Op1 | Callable[[Permutations], Op1],
148 number_of_samples: int | None = None,
149 min_unique_samples: int | Callable[[
150 int, Permutations], int] | None = None,
151 perm_filter: Callable[[Permutations], bool] | None = None) -> None:
152 """
153 Validate the unary operator on several `Permutations` instances.
155 :param op1: the operator or operator factory
156 :param number_of_samples: the optional number of samples
157 :param min_unique_samples: the optional unique samples
158 :param perm_filter: an optional filter to sort out permutations we cannot
159 use for testing
160 """
161 for pwr in permutations_for_tests(perm_filter):
162 validate_op1_on_1_permutations(op1, pwr, number_of_samples,
163 min_unique_samples)
166def validate_op1_with_step_size_on_1_permutations(
167 op1: Op1WithStepSize | Callable[[Permutations], Op1WithStepSize],
168 search_space: Permutations,
169 number_of_samples: int | None = None,
170 min_unique_samples: int | Callable[[
171 int, Permutations], int] | None = None,
172 step_sizes: Iterable[float] | Callable[
173 [Permutations], Iterable[float]] = (),
174 get_step_size: Callable[[
175 Permutations, np.ndarray, np.ndarray,
176 ], float | None] | None = None) -> None:
177 """
178 Validate the step-sized unary operator on one `Permutations` instance.
180 :param op1: the operator or operator factory
181 :param search_space: the search space
182 :param number_of_samples: the optional number of samples
183 :param min_unique_samples: the optional unique samples
184 :param step_sizes: the step sizes to test
185 :param get_step_size: try to get the step size from two space elements
186 """
187 args: dict[str, Any] = {
188 "op1": op1(search_space) if callable(op1) else op1,
189 "search_space": search_space,
190 "make_search_space_element_valid":
191 make_permutation_valid(search_space),
192 "step_sizes": step_sizes(search_space) if callable(step_sizes)
193 else step_sizes,
194 "get_step_size": get_step_size,
195 }
196 if number_of_samples is not None:
197 args["number_of_samples"] = number_of_samples
198 if min_unique_samples is not None:
199 args["min_unique_samples"] = min_unique_samples
200 validate_op1_with_step_size(**args)
203def validate_op1_with_step_size_on_permutations(
204 op1: Op1WithStepSize | Callable[[Permutations], Op1WithStepSize],
205 number_of_samples: int | None = None,
206 min_unique_samples: int | Callable[[
207 int, Permutations], int] | None = None,
208 step_sizes: Iterable[float] | Callable[
209 [Permutations], Iterable[float]] = (),
210 get_step_size: Callable[[
211 Permutations, np.ndarray, np.ndarray,
212 ], float | None] | None = None,
213 perm_filter: Callable[[Permutations], bool] | None = None) -> None:
214 """
215 Validate the unary operator on several `Permutations` instances.
217 :param op1: the operator or operator factory
218 :param number_of_samples: the optional number of samples
219 :param min_unique_samples: the optional unique samples
220 :param step_sizes: the step sizes to test
221 :param get_step_size: try to get the step size from two space elements
222 :param perm_filter: an optional filter to sort out permutations we cannot
223 use for testing
224 """
225 for pwr in permutations_for_tests(perm_filter):
226 validate_op1_with_step_size_on_1_permutations(
227 op1, pwr, number_of_samples, min_unique_samples, step_sizes,
228 get_step_size)
231def validate_op2_on_1_permutations(
232 op2: Op2 | Callable[[Permutations], Op2],
233 search_space: Permutations,
234 number_of_samples: int | None = None,
235 min_unique_samples: int | Callable[[
236 int, Permutations], int] | None = None) -> None:
237 """
238 Validate the binary operator on one `Permutations` instance.
240 :param op2: the operator or operator factory
241 :param search_space: the search space
242 :param number_of_samples: the optional number of samples
243 :param min_unique_samples: the optional unique samples
244 """
245 args: dict[str, Any] = {
246 "op2": op2(search_space) if callable(op2) else op2,
247 "search_space": search_space,
248 "make_search_space_element_valid":
249 make_permutation_valid(search_space),
250 }
251 if number_of_samples is not None:
252 args["number_of_samples"] = number_of_samples
253 if min_unique_samples is not None:
254 args["min_unique_samples"] = min_unique_samples
255 validate_op2(**args)
258def validate_op2_on_permutations(
259 op2: Op2 | Callable[[Permutations], Op2],
260 number_of_samples: int | None = None,
261 min_unique_samples: int | Callable[[
262 int, Permutations], int] | None = None,
263 perm_filter: Callable[[Permutations], bool] | None = None) -> None:
264 """
265 Validate the binary operator on several `Permutations` instances.
267 :param op2: the operator or operator factory
268 :param number_of_samples: the optional number of samples
269 :param min_unique_samples: the optional unique samples
270 :param perm_filter: an optional filter to sort out permutations we cannot
271 use for testing
272 """
273 for pwr in permutations_for_tests(perm_filter):
274 validate_op2_on_1_permutations(op2, pwr, number_of_samples,
275 min_unique_samples)