From 0bf632990157133b6139c38f199e4f27e3df6279 Mon Sep 17 00:00:00 2001 From: c-bata Date: Sun, 11 Apr 2021 01:48:01 +0900 Subject: [PATCH] Fuzzing for sep-CMA-ES --- cmaes/_sepcma.py | 13 +++++++++++-- tests/test_fuzzing.py | 30 +++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/cmaes/_sepcma.py b/cmaes/_sepcma.py index df56536..118104d 100644 --- a/cmaes/_sepcma.py +++ b/cmaes/_sepcma.py @@ -9,6 +9,7 @@ _EPS = 1e-8 +_MEAN_MAX = 1e32 _SIGMA_MAX = 1e32 @@ -73,6 +74,10 @@ def __init__( ): assert sigma > 0, "sigma must be non-zero positive value" + assert np.all( + np.abs(mean) < _MEAN_MAX + ), f"Abs of all elements of mean vector must be less than {_MEAN_MAX}" + n_dim = len(mean) assert n_dim > 1, "The dimension of mean must be larger than 1" @@ -233,8 +238,12 @@ def _repair_infeasible_params(self, param: np.ndarray) -> np.ndarray: def tell(self, solutions: List[Tuple[np.ndarray, float]]) -> None: """Tell evaluation values""" - if len(solutions) != self._popsize: - raise ValueError("Must tell popsize-length solutions.") + + assert len(solutions) == self._popsize, "Must tell popsize-length solutions." + for s in solutions: + assert np.all( + np.abs(s[0]) < _MEAN_MAX + ), f"Abs of all param values must be less than {_MEAN_MAX} to avoid overflow errors" self._g += 1 solutions.sort(key=lambda s: s[1]) diff --git a/tests/test_fuzzing.py b/tests/test_fuzzing.py index df11c91..a567607 100644 --- a/tests/test_fuzzing.py +++ b/tests/test_fuzzing.py @@ -2,7 +2,7 @@ import unittest from hypothesis import given, strategies as st -from cmaes import CMA +from cmaes import CMA, SepCMA class TestFuzzing(unittest.TestCase): @@ -33,3 +33,31 @@ def test_cma_tell(self, data): except AssertionError: return optimizer.ask() + + @given( + data=st.data(), + ) + def test_sepcma_tell(self, data): + dim = data.draw(st.integers(min_value=2, max_value=100)) + mean = data.draw(npst.arrays(dtype=float, shape=dim)) + sigma = data.draw(st.floats(min_value=1e-16)) + n_iterations = data.draw(st.integers(min_value=1)) + try: + optimizer = SepCMA(mean, sigma) + except AssertionError: + return + popsize = optimizer.population_size + for _ in range(n_iterations): + tell_solutions = data.draw( + st.lists( + st.tuples(npst.arrays(dtype=float, shape=dim), st.floats()), + min_size=popsize, + max_size=popsize, + ) + ) + optimizer.ask() + try: + optimizer.tell(tell_solutions) + except AssertionError: + return + optimizer.ask()