From b69683f747de007436af1279a4aa17de10cc53f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20P=C3=A4tzel?= Date: Wed, 11 Dec 2024 15:50:27 +0100 Subject: [PATCH] Improve performance of early stop check in ES --- suprb/optimizer/rule/es/es.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/suprb/optimizer/rule/es/es.py b/suprb/optimizer/rule/es/es.py index dfc82a41..2736313a 100644 --- a/suprb/optimizer/rule/es/es.py +++ b/suprb/optimizer/rule/es/es.py @@ -87,13 +87,13 @@ def __init__(self, def _optimize(self, X: np.ndarray, y: np.ndarray, initial_rule: Rule, random_state: RandomState) -> Optional[Rule]: + elitist_last = None elitist = initial_rule - elitists = deque(maxlen=self.delay) + n_iter_since_improvement = 0 # Main iteration for iteration in range(self.n_iter): - elitists.append(elitist) # Generate, fit and evaluate lambda children children = [self.constraint(self.mutation(elitist, random_state=random_state)) @@ -116,9 +116,18 @@ def _optimize(self, X: np.ndarray, y: np.ndarray, initial_rule: Rule, random_sta elitist = self.selection(children, random_state=random_state)[0] elif self.operator in (',', '&'): elitist = self.selection(children, random_state=random_state)[0] + + if elitist_last == None or elitist.fitness_ >= elitist_last.fitness_: + # @heidmic I don't think we have to `clone(…)` here because + # `mutation` already does but I'm not 100% sure. + elitist_last = elitist + n_iter_since_improvement = 0 + else: + n_iter_since_improvement += 1 + if self.operator == '&': - if len(elitists) == self.delay and all([e.fitness_ <= elitists[0].fitness_ for e in elitists]): - elitist = elitists[0] + if n_iter_since_improvement >= self.delay: + elitist = elitist_last break return elitist