from .basestopper import BaseStopper
from ..core.optimizerlogger import BaseLogger
from ..optimizers.baseoptimizer import BaseOptimizer
from ...plams.core.settings import Settings
__all__ = ("OptimizerType",)
[docs]class OptimizerType(BaseStopper):
"""Stops an optimizer based on its class.
Intended for use with other stoppers to allow for specific stopping conditions based on the type of optimizer.
:Parameters:
opt_to_stop
:class:`.BaseOptimizer` class which is targeted.
:Returns:
bool
``True`` if the tested optimizer is an instance of ``opt_to_stop``.
:Examples:
>>> OptimizerType(CMAOptimizer) & StopperA() | OptimizerType(Nevergrad) & StopperB()
In this case ``StopperA`` will only stop :class:`.CMAOptimizer`\\s and ``StopperB`` will only stop
:class:`scm.glompo.optimizers.nevergrad.Nevergrad` optimizers. This is useful in cases where exploratory optimizers
should be stopped quickly but late stage optimizers encouraged to converge and iterate for longer periods.
"""
def __init__(self, opt_to_stop: BaseOptimizer):
super().__init__()
if issubclass(opt_to_stop, BaseOptimizer):
self.opt_to_stop = opt_to_stop.__name__
else:
raise TypeError("Optimizer not recognized, must be a subclass of BaseOptimizer")
def __call__(self, log: BaseLogger, best_opt_id: int, tested_opt_id: int) -> bool:
self.last_result = self.opt_to_stop == log.get_metadata(tested_opt_id, "opt_type")
return self.last_result
def __amssettings__(self, s: Settings) -> Settings:
from scm.params.core.input_parser import OPTIMIZER_DICT
opt_dict = {v.__name__: k for k, v in OPTIMIZER_DICT.items()}
s.input.ams.Stopper.Type = "OptimizerType"
s.input.ams.Stopper.OptimizerType = opt_dict[self.opt_to_stop]
return s