Code Duplication    Length = 28-28 lines in 2 locations

src/gradient_free_optimizers/_stopping_conditions.py 2 locations

@@ 97-124 (lines=28) @@
94
        }
95
96
97
class ScoreExceededCondition(StoppingCondition):
98
    """Stops when target score is reached or exceeded."""
99
100
    def __init__(self, max_score: Optional[float]):
101
        super().__init__("ScoreExceeded")
102
        self.max_score = max_score
103
104
    def should_stop(self, context: StoppingContext) -> bool:
105
        if self.max_score is None:
106
            return False
107
108
        if context.score_best >= self.max_score:
109
            self.triggered = True
110
            self.trigger_reason = f"Target score reached: {context.score_best:.6f} >= {self.max_score:.6f}"
111
            self.logger.info(self.trigger_reason)
112
            return True
113
        return False
114
115
    def get_debug_info(self, context: StoppingContext) -> Dict[str, Any]:
116
        return {
117
            "condition": self.name,
118
            "max_score": self.max_score,
119
            "current_best_score": context.score_best,
120
            "score_gap": (
121
                self.max_score - context.score_best if self.max_score else None
122
            ),
123
            "triggered": self.triggered,
124
            "reason": self.trigger_reason,
125
        }
126
127
@@ 66-93 (lines=28) @@
63
        self.trigger_reason = ""
64
65
66
class TimeExceededCondition(StoppingCondition):
67
    """Stops when maximum time limit is exceeded."""
68
69
    def __init__(self, max_time: Optional[float]):
70
        super().__init__("TimeExceeded")
71
        self.max_time = max_time
72
73
    def should_stop(self, context: StoppingContext) -> bool:
74
        if self.max_time is None:
75
            return False
76
77
        if context.elapsed_time > self.max_time:
78
            self.triggered = True
79
            self.trigger_reason = f"Time limit exceeded: {context.elapsed_time:.2f}s > {self.max_time:.2f}s"
80
            self.logger.info(self.trigger_reason)
81
            return True
82
        return False
83
84
    def get_debug_info(self, context: StoppingContext) -> Dict[str, Any]:
85
        return {
86
            "condition": self.name,
87
            "max_time": self.max_time,
88
            "elapsed_time": context.elapsed_time,
89
            "time_remaining": (
90
                self.max_time - context.elapsed_time if self.max_time else None
91
            ),
92
            "triggered": self.triggered,
93
            "reason": self.trigger_reason,
94
        }
95
96