import numpy as np
from .basestopper import BaseStopper
from ..core.optimizerlogger import BaseLogger
from ...plams.core.settings import Settings
__all__ = ("MaxSequentialInvalidPoints",)
[docs]class MaxSequentialInvalidPoints(BaseStopper):
"""Checks for non-numerical solutions.
Some pathological functions may have undefined regions within them or combinations of parameters which return
non-finite results.
:Parameters:
n_iters
Number of allowed invalid function evaluations.
:Returns:
bool
Returns ``True`` if the optimizer fails to find a valid function evaluation in the last ``n_iters`` function
evaluations.
"""
def __init__(self, n_iters: int = 1):
super().__init__()
self.n_iters = n_iters
def __call__(self, log: BaseLogger, best_opt_id: int, tested_opt_id: int) -> bool:
fcalls = log.get_history(tested_opt_id, "fx")[-self.n_iters :]
self.last_result = len(fcalls) >= self.n_iters and not np.isfinite(fcalls).any()
return self.last_result
def __amssettings__(self, s: Settings) -> Settings:
s.input.ams.Stopper.Type = "MaxSequentialInvalidPoints"
s.input.ams.Stopper.MaxSequentialInvalidPoints = self.n_iters
return s