Source code for moptipy.tests.on_permutations

"""Test stuff on permutations with repetitions."""

from typing import Any, Callable, Iterable, cast

import numpy as np
from numpy.random import Generator, default_rng
from pycommons.types import type_error

from moptipy.api.operators import Op0, Op1, Op1WithStepSize, Op2
from moptipy.spaces.permutations import Permutations
from moptipy.tests.op0 import validate_op0
from moptipy.tests.op1 import validate_op1
from moptipy.tests.op1_with_step_size import validate_op1_with_step_size
from moptipy.tests.op2 import validate_op2


[docs] def permutations_for_tests( perm_filter: Callable[[Permutations], bool] | None = None) \ -> Iterable[Permutations]: """ Get a sequence of permutations for tests. :param perm_filter: an optional filter to sort out permutations we cannot use for testing :returns: the sequence of Permutations """ r = default_rng() pwrs: list[Permutations] = [ Permutations.standard(2), Permutations.standard(3), Permutations.standard(4), Permutations.standard(5), Permutations.standard(6), Permutations.standard(12), Permutations.standard(23), Permutations.with_repetitions(2, 2), Permutations.with_repetitions(2, 3), Permutations.with_repetitions(3, 2), Permutations.with_repetitions(3, 3), Permutations.with_repetitions(5, 5), Permutations.with_repetitions(int(r.integers(6, 10)), int(r.integers(2, 7))), Permutations.with_repetitions(int(r.integers(2, 5)), int(r.integers(6, 10))), Permutations.with_repetitions(int(r.integers(130, 500)), int(r.integers(2, 200))), Permutations([1, 1, 1, 1, 1, 5, 5, 3]), Permutations([0, 1, 1, 1, 1, 1])] if perm_filter is not None: if not callable(perm_filter): raise type_error(perm_filter, "perm_filter", None, call=True) pwrs = [p for p in pwrs if perm_filter(p)] r.shuffle(cast(list, pwrs)) return pwrs
[docs] def make_permutation_valid(pwr: Permutations) -> \ Callable[[Generator, np.ndarray], np.ndarray]: """ Create a function that can make permutations with repetitions valid. :param pwr: the permutations :returns: the function """ def __make_valid(prnd: Generator, x: np.ndarray, ppp=pwr) -> np.ndarray: np.copyto(x, ppp.blueprint) prnd.shuffle(x) return x return __make_valid
[docs] def validate_op0_on_1_permutations( op0: Op0 | Callable[[Permutations], Op0], search_space: Permutations, number_of_samples: int | None = None, min_unique_samples: int | Callable[[ int, Permutations], int] | None = None) -> None: """ Validate the nullary operator on one `Permutations` instance. :param op0: the operator or operator factory :param search_space: the search space :param number_of_samples: the optional number of samples :param min_unique_samples: the optional unique samples """ args: dict[str, Any] = { "op0": op0(search_space) if callable(op0) else op0, "search_space": search_space, "make_search_space_element_valid": make_permutation_valid(search_space), } if number_of_samples is not None: args["number_of_samples"] = number_of_samples if min_unique_samples is not None: args["min_unique_samples"] = min_unique_samples validate_op0(**args)
[docs] def validate_op0_on_permutations( op0: Op0 | Callable[[Permutations], Op0], number_of_samples: int | None = None, min_unique_samples: int | Callable[[ int, Permutations], int] | None = None, perm_filter: Callable[[Permutations], bool] | None = None) -> None: """ Validate the nullary operator on several `Permutations` instances. :param op0: the operator or operator factory :param number_of_samples: the optional number of samples :param min_unique_samples: the optional unique samples :param perm_filter: an optional filter to sort out permutations we cannot use for testing """ for pwr in permutations_for_tests(perm_filter): validate_op0_on_1_permutations(op0, pwr, number_of_samples, min_unique_samples)
[docs] def validate_op1_on_1_permutations( op1: Op1 | Callable[[Permutations], Op1], search_space: Permutations, number_of_samples: int | None = None, min_unique_samples: int | Callable[[ int, Permutations], int] | None = None) -> None: """ Validate the unary operator on one `Permutations` instance. :param op1: the operator or operator factory :param search_space: the search space :param number_of_samples: the optional number of samples :param min_unique_samples: the optional unique samples """ args: dict[str, Any] = { "op1": op1(search_space) if callable(op1) else op1, "search_space": search_space, "make_search_space_element_valid": make_permutation_valid(search_space), } if number_of_samples is not None: args["number_of_samples"] = number_of_samples if min_unique_samples is not None: args["min_unique_samples"] = min_unique_samples validate_op1(**args)
[docs] def validate_op1_on_permutations( op1: Op1 | Callable[[Permutations], Op1], number_of_samples: int | None = None, min_unique_samples: int | Callable[[ int, Permutations], int] | None = None, perm_filter: Callable[[Permutations], bool] | None = None) -> None: """ Validate the unary operator on several `Permutations` instances. :param op1: the operator or operator factory :param number_of_samples: the optional number of samples :param min_unique_samples: the optional unique samples :param perm_filter: an optional filter to sort out permutations we cannot use for testing """ for pwr in permutations_for_tests(perm_filter): validate_op1_on_1_permutations(op1, pwr, number_of_samples, min_unique_samples)
[docs] def validate_op1_with_step_size_on_1_permutations( op1: Op1WithStepSize | Callable[[Permutations], Op1WithStepSize], search_space: Permutations, number_of_samples: int | None = None, min_unique_samples: int | Callable[[ int, Permutations], int] | None = None, step_sizes: Iterable[float] | Callable[ [Permutations], Iterable[float]] = (), get_step_size: Callable[[ Permutations, np.ndarray, np.ndarray, ], float | None] | None = None) -> None: """ Validate the step-sized unary operator on one `Permutations` instance. :param op1: the operator or operator factory :param search_space: the search space :param number_of_samples: the optional number of samples :param min_unique_samples: the optional unique samples :param step_sizes: the step sizes to test :param get_step_size: try to get the step size from two space elements """ args: dict[str, Any] = { "op1": op1(search_space) if callable(op1) else op1, "search_space": search_space, "make_search_space_element_valid": make_permutation_valid(search_space), "step_sizes": step_sizes(search_space) if callable(step_sizes) else step_sizes, "get_step_size": get_step_size, } if number_of_samples is not None: args["number_of_samples"] = number_of_samples if min_unique_samples is not None: args["min_unique_samples"] = min_unique_samples validate_op1_with_step_size(**args)
[docs] def validate_op1_with_step_size_on_permutations( op1: Op1WithStepSize | Callable[[Permutations], Op1WithStepSize], number_of_samples: int | None = None, min_unique_samples: int | Callable[[ int, Permutations], int] | None = None, step_sizes: Iterable[float] | Callable[ [Permutations], Iterable[float]] = (), get_step_size: Callable[[ Permutations, np.ndarray, np.ndarray, ], float | None] | None = None, perm_filter: Callable[[Permutations], bool] | None = None) -> None: """ Validate the unary operator on several `Permutations` instances. :param op1: the operator or operator factory :param number_of_samples: the optional number of samples :param min_unique_samples: the optional unique samples :param step_sizes: the step sizes to test :param get_step_size: try to get the step size from two space elements :param perm_filter: an optional filter to sort out permutations we cannot use for testing """ for pwr in permutations_for_tests(perm_filter): validate_op1_with_step_size_on_1_permutations( op1, pwr, number_of_samples, min_unique_samples, step_sizes, get_step_size)
[docs] def validate_op2_on_1_permutations( op2: Op2 | Callable[[Permutations], Op2], search_space: Permutations, number_of_samples: int | None = None, min_unique_samples: int | Callable[[ int, Permutations], int] | None = None) -> None: """ Validate the binary operator on one `Permutations` instance. :param op2: the operator or operator factory :param search_space: the search space :param number_of_samples: the optional number of samples :param min_unique_samples: the optional unique samples """ args: dict[str, Any] = { "op2": op2(search_space) if callable(op2) else op2, "search_space": search_space, "make_search_space_element_valid": make_permutation_valid(search_space), } if number_of_samples is not None: args["number_of_samples"] = number_of_samples if min_unique_samples is not None: args["min_unique_samples"] = min_unique_samples validate_op2(**args)
[docs] def validate_op2_on_permutations( op2: Op2 | Callable[[Permutations], Op2], number_of_samples: int | None = None, min_unique_samples: int | Callable[[ int, Permutations], int] | None = None, perm_filter: Callable[[Permutations], bool] | None = None) -> None: """ Validate the binary operator on several `Permutations` instances. :param op2: the operator or operator factory :param number_of_samples: the optional number of samples :param min_unique_samples: the optional unique samples :param perm_filter: an optional filter to sort out permutations we cannot use for testing """ for pwr in permutations_for_tests(perm_filter): validate_op2_on_1_permutations(op2, pwr, number_of_samples, min_unique_samples)