diff --git a/.readthedocs.yml b/.readthedocs.yml index eee11fd..361d49f 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -10,4 +10,4 @@ sphinx: python: version: 3.8 install: - - requirements: requirements.txt \ No newline at end of file + - requirements: docs/requirements.txt \ No newline at end of file diff --git a/modcma/parameters.py b/modcma/parameters.py index 6fa53e3..2fc47f1 100644 --- a/modcma/parameters.py +++ b/modcma/parameters.py @@ -386,19 +386,23 @@ def init_adaptation_parameters(self) -> None: Examples are recombination weights and learning rates for the covariance matrix adapation. + TODO: clean the initlialization of these weights, this can be wrong in some cases + when mu != .5 """ + if self.weights_option == "equal": ws = np.ones(self.lambda_) / self.lambda_ - self.weights = np.append(ws, ws[::-1] * -1) + self.weights = np.append(ws[:self.mu], ws[self.mu::-1] * -1) + if self.lambda_ % 2 != 0: - self.weights = np.append([1 / self.lambda_], self.weights) + self.weights = np.append([1 / self.lambda_], self.weights[:-1]) elif self.weights_option == "1/2^lambda": ws = 1 / 2 ** np.arange(1, self.lambda_ + 1) + ( (1 / (2 ** self.lambda_)) / self.lambda_ ) - self.weights = np.append(ws, ws[::-1] * -1) + self.weights = np.append(ws[:self.mu], ws[self.mu::-1] * -1) if self.lambda_ % 2 != 0: - self.weights = np.append([1 / self.lambda_ ** 2], self.weights) + self.weights = np.append([1 / self.lambda_ ** 2], self.weights[:-1]) else: self.weights = np.log((self.lambda_ + 1) / 2) - np.log( np.arange(1, self.lambda_ + 1) @@ -831,7 +835,7 @@ def adapt(self, used_budget: int) -> None: self.lambda_large *= 2 else: self.budget_small -= used_previous_iteration - + self.lambda_small = np.floor( self.lambda_init * (0.5 * self.lambda_large / self.lambda_init) ** (np.random.uniform() ** 2) diff --git a/tests/test_modularcmaes.py b/tests/test_modularcmaes.py index b5d6a3f..d4dea89 100644 --- a/tests/test_modularcmaes.py +++ b/tests/test_modularcmaes.py @@ -96,6 +96,12 @@ def test_local_restart(self): class TestModularCMAESSingle(unittest.TestCase): """Test case for ModularCMAES Object, holds custom tests.""" + def test_tpa_threshold_cov_sequential(self): + c = modularcmaes.ModularCMAES(sum, 2, + threshold_convergence=True, sequential=True, + step_size_adaptation='tpa', budget=10).run() + self.assertLess(c.parameters.fopt, 0.) + def test_str_repr(self): """Test the output of repr and str.""" c = modularcmaes.ModularCMAES(sum, 5) @@ -188,7 +194,7 @@ def test_evaluate_bbob(self, mock_std): self.assertTrue(os.path.isdir(data_folder)) modularcmaes.evaluate_bbob(1, 1, 1, logging=True, data_folder=data_folder) shutil.rmtree(data_folder) - modularcmaes.evaluate_bbob(1, 1, 1) + modularcmaes.evaluate_bbob(1, 1, 2) diff --git a/tests/test_parameters.py b/tests/test_parameters.py index 32d9219..7be8995 100644 --- a/tests/test_parameters.py +++ b/tests/test_parameters.py @@ -7,7 +7,7 @@ import numpy as np -from modcma.parameters import Parameters +from modcma.parameters import Parameters, BIPOPParameters from modcma.utils import AnyOf from modcma.population import Population @@ -177,6 +177,23 @@ def test_save_load(self): self.p.load(tmpfile) os.remove(tmpfile) + def test_fix_lambda_even(self): + self.p.lambda_ = 11 + self.p.mirrored = 'mirrored pairwise' + self.assertEqual(self.p.lambda_, 11) + self.p.init_selection_parameters() + self.assertEqual(self.p.lambda_, 12) + + for weights_option in ("equal", "1/2^lambda"): + self.p.weights_option = weights_option + self.p.lambda_ = 11 + self.p.mu = 5 + self.p.init_adaptation_parameters() + self.assertEqual(len(self.p.weights), 11) + + b = BIPOPParameters(7, 20, .5) + b.adapt(11) + self.assertEqual(b.lambda_small, 8) if __name__ == "__main__": unittest.main() diff --git a/tests/test_population.py b/tests/test_population.py index 44a0d32..407f1b0 100644 --- a/tests/test_population.py +++ b/tests/test_population.py @@ -106,6 +106,7 @@ def test_d(self): def test_repr(self): """Test representation.""" self.assertEqual(type(repr(self.pop)), str) + self.assertEqual(type(str(self.pop)), str) if __name__ == "__main__": diff --git a/tests/test_sampling.py b/tests/test_sampling.py index d6d9075..3c6049d 100644 --- a/tests/test_sampling.py +++ b/tests/test_sampling.py @@ -43,6 +43,7 @@ def test_halton(self): """Test halton sampling.""" sampler = sampling.halton_sampling(self._dim) self.is_sampler(sampler) + self.assertEqual(sampling.Halton.vectorized_next(10, 2), .3125) def test_orthogonal(self): """Test orthogonal sampling."""