Source code for smac.random_design.modulus_design

from __future__ import annotations

from typing import Any

import numpy as np

from smac.random_design.abstract_random_design import AbstractRandomDesign
from smac.utils.logging import get_logger

__copyright__ = "Copyright 2022, automl.org"
__license__ = "3-clause BSD"

logger = get_logger(__name__)


[docs] class ModulusRandomDesign(AbstractRandomDesign): """Interleave a random configuration after a constant number of configurations found by Bayesian optimization. Parameters ---------- modulus : float Every modulus-th configuration will be at random. seed : int Integer used to initialize random state. This class does not use the seed. """ def __init__(self, modulus: float = 2.0, seed: int = 0): super().__init__(seed) assert modulus > 0 if modulus <= 1.0: logger.warning("Using SMAC with random configurations only. ROAR is the better choice for this.") self._modulus = modulus @property def meta(self) -> dict[str, Any]: # noqa: D102 meta = super().meta meta.update({"modulus": self._modulus}) return meta
[docs] def check(self, iteration: int) -> bool: # noqa: D102 assert iteration >= 0 return iteration % self._modulus < 1
[docs] class DynamicModulusRandomDesign(AbstractRandomDesign): """Interleave a random configuration, decreasing the fraction of random configurations over time. Parameters ---------- start_modulus : float, defaults to 2.0 Initially, every modulus-th configuration will be at random. modulus_increment : float, defaults to 0.3 Increase modulus by this amount in every iteration. end_modulus : float, defaults to np.inf The maximum modulus ever used. If the value is reached before the optimization is over, it is not further increased. If it is not reached before the optimization is over, there will be no adjustment to make sure that the `end_modulus` is reached. seed : int, defaults to 0 Integer used to initialize the random state. This class does not use the seed. """ def __init__( self, start_modulus: float = 2.0, modulus_increment: float = 0.3, end_modulus: float = np.inf, seed: int = 0 ): super().__init__(seed) assert start_modulus > 0 assert modulus_increment > 0 assert end_modulus > 0 assert end_modulus > start_modulus if start_modulus <= 1.0 and modulus_increment <= 0.0: logger.warning("Using SMAC with random configurations only. ROAR is the better choice for this.") self._modulus = start_modulus self._start_modulus = start_modulus self._modulus_increment = modulus_increment self._end_modulus = end_modulus @property def meta(self) -> dict[str, Any]: # noqa: D102 meta = super().meta meta.update( { "start_modulus": self._start_modulus, "end_modulus": self._end_modulus, "modulus_increment": self._modulus_increment, } ) return meta
[docs] def next_iteration(self) -> None: # noqa: D102 self._modulus += self._modulus_increment self._modulus = min(self._modulus, self._end_modulus)
[docs] def check(self, iteration: int) -> bool: # noqa: D102 assert iteration >= 0 if iteration % self._modulus < 1: return True else: return False