| """Tests for the abstract Optimizer base class and dataclasses.""" |
|
|
| from __future__ import annotations |
|
|
| import time |
|
|
| import numpy as np |
| import pytest |
|
|
| from ahdcma.algorithms.base import ( |
| History, |
| OptimizationResult, |
| Optimizer, |
| SearchSpace, |
| ) |
|
|
|
|
| def test_search_space_unit_cube() -> None: |
| sp = SearchSpace.unit_cube(4) |
| assert sp.dim == 4 |
| assert np.all(sp.lower == 0.0) |
| assert np.all(sp.upper == 1.0) |
|
|
|
|
| def test_search_space_validation() -> None: |
| with pytest.raises(ValueError): |
| SearchSpace(dim=3, lower=np.zeros(2), upper=np.ones(3)) |
| with pytest.raises(ValueError): |
| SearchSpace(dim=2, lower=np.array([0.0, 1.0]), upper=np.array([1.0, 0.5])) |
|
|
|
|
| def test_search_space_clip() -> None: |
| sp = SearchSpace.unit_cube(3) |
| x = np.array([-0.5, 0.3, 1.7]) |
| np.testing.assert_array_equal(sp.clip(x), np.array([0.0, 0.3, 1.0])) |
|
|
|
|
| def test_history_append_and_len() -> None: |
| h = History() |
| assert len(h) == 0 |
| h.append(0, np.zeros((4, 2)), np.array([1.0, 0.5, 2.0, 1.5]), mode="explore", entropy=2.3) |
| assert len(h) == 1 |
| assert h.best_fitness[0] == 0.5 |
| assert h.mode_per_gen[0] == "explore" |
| assert h.entropy_per_gen[0] == pytest.approx(2.3) |
|
|
|
|
| def test_optimizer_subclass_minimal() -> None: |
| class _Const(Optimizer): |
| def optimize(self) -> OptimizationResult: |
| x = np.full(self.search_space.dim, 0.5) |
| f = float(self.fitness_fn(x)) |
| self._history.append(0, x[None, :], np.array([f]), mode="hybrid") |
| return OptimizationResult( |
| best_x=x, |
| best_f=f, |
| history=self._history, |
| config_snapshot=self.config, |
| run_id=self.run_id, |
| wall_time=0.0, |
| ) |
|
|
| sp = SearchSpace.unit_cube(3) |
| opt = _Const(config={"foo": 1}, fitness_fn=lambda x: float(np.sum(x**2)), search_space=sp) |
| t0 = time.time() |
| result = opt.optimize() |
| assert result.best_f == pytest.approx(0.75) |
| assert result.run_id == "anonymous" |
| assert len(opt.get_history()) == 1 |
| assert time.time() - t0 < 1.0 |
|
|