Skip to content

Commit d7e47b2

Browse files
committed
add
1 parent 69703e4 commit d7e47b2

File tree

5 files changed

+103
-2
lines changed

5 files changed

+103
-2
lines changed

configs/default_config.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ random_seed: 42 # Random seed for reproducibility (null =
1313
diff_based_evolution: true # Use diff-based evolution (true) or full rewrites (false)
1414
max_code_length: 10000 # Maximum allowed code length in characters
1515

16+
# Early stopping settings
17+
early_stopping_patience: null # Stop after N iterations without improvement (null = disabled)
18+
convergence_threshold: 0.001 # Minimum improvement required to reset patience counter
19+
early_stopping_metric: "combined_score" # Metric to track for early stopping
20+
1621
# LLM configuration
1722
llm:
1823
# Models for evolution
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# OpenEvolve Configuration with Early Stopping Example
2+
# This configuration demonstrates how to use the early stopping feature
3+
4+
# Basic settings
5+
max_iterations: 1000
6+
checkpoint_interval: 50
7+
log_level: "INFO"
8+
9+
# Early stopping configuration - stops evolution if no improvement for 30 iterations
10+
early_stopping_patience: 30 # Stop after 30 iterations without improvement
11+
convergence_threshold: 0.01 # Minimum improvement of 0.01 required to reset patience
12+
early_stopping_metric: "combined_score" # Track the combined_score metric
13+
14+
# LLM configuration
15+
llm:
16+
models:
17+
- name: "gpt-4o-mini"
18+
weight: 1.0
19+
20+
api_base: "https://api.openai.com/v1"
21+
temperature: 0.7
22+
max_tokens: 4096
23+
24+
# Database configuration
25+
database:
26+
population_size: 50
27+
num_islands: 3
28+
migration_interval: 20
29+
30+
# Evaluation settings
31+
evaluator:
32+
timeout: 60
33+
max_retries: 2
34+
parallel_evaluations: 2
35+
36+
# Evolution settings
37+
diff_based_evolution: true
38+
max_code_length: 8000

examples/attention_optimization/configs/failing_config.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,16 @@ checkpoints:
3535
keep_best: true
3636
save_all_programs: false
3737

38+
# Early stopping settings (moved to top level)
39+
early_stopping_patience: 50 # Stop after 50 iterations without improvement
40+
convergence_threshold: 0.001 # Minimum improvement required
41+
early_stopping_metric: "speedup" # Track speedup metric
42+
3843
# Optimization targets
3944
optimization:
4045
target_metric: "speedup"
4146
target_value: 1.32 # 32% speedup like AlphaEvolve paper
4247
minimize: false
43-
convergence_threshold: 0.001
44-
early_stopping_patience: 50
4548

4649
# Logging
4750
logging:

openevolve/config.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,11 @@ class Config:
271271
# Evolution settings
272272
diff_based_evolution: bool = True
273273
max_code_length: int = 10000
274+
275+
# Early stopping settings
276+
early_stopping_patience: Optional[int] = None
277+
convergence_threshold: float = 0.001
278+
early_stopping_metric: str = "combined_score"
274279

275280
@classmethod
276281
def from_yaml(cls, path: Union[str, Path]) -> "Config":
@@ -381,6 +386,10 @@ def to_dict(self) -> Dict[str, Any]:
381386
# Evolution settings
382387
"diff_based_evolution": self.diff_based_evolution,
383388
"max_code_length": self.max_code_length,
389+
# Early stopping settings
390+
"early_stopping_patience": self.early_stopping_patience,
391+
"convergence_threshold": self.convergence_threshold,
392+
"early_stopping_metric": self.early_stopping_metric,
384393
}
385394

386395
def to_yaml(self, path: Union[str, Path]) -> None:

openevolve/process_parallel.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,17 @@ async def run_evolution(
425425
# Island management
426426
programs_per_island = max(1, max_iterations // (self.config.database.num_islands * 10))
427427
current_island_counter = 0
428+
429+
# Early stopping tracking
430+
early_stopping_enabled = self.config.early_stopping_patience is not None
431+
if early_stopping_enabled:
432+
best_score = float('-inf')
433+
iterations_without_improvement = 0
434+
logger.info(f"Early stopping enabled: patience={self.config.early_stopping_patience}, "
435+
f"threshold={self.config.convergence_threshold}, "
436+
f"metric={self.config.early_stopping_metric}")
437+
else:
438+
logger.info("Early stopping disabled")
428439

429440
# Process results as they complete
430441
while (
@@ -563,6 +574,41 @@ async def run_evolution(
563574
)
564575
break
565576

577+
# Check early stopping
578+
if early_stopping_enabled and child_program.metrics:
579+
# Get the metric to track for early stopping
580+
current_score = None
581+
if self.config.early_stopping_metric in child_program.metrics:
582+
current_score = child_program.metrics[self.config.early_stopping_metric]
583+
else:
584+
# Fall back to average of numeric metrics if specified metric doesn't exist
585+
numeric_metrics = [
586+
v for v in child_program.metrics.values()
587+
if isinstance(v, (int, float)) and not isinstance(v, bool)
588+
]
589+
if numeric_metrics:
590+
current_score = sum(numeric_metrics) / len(numeric_metrics)
591+
592+
if current_score is not None and isinstance(current_score, (int, float)):
593+
# Check for improvement
594+
improvement = current_score - best_score
595+
if improvement >= self.config.convergence_threshold:
596+
best_score = current_score
597+
iterations_without_improvement = 0
598+
logger.debug(f"New best score: {best_score:.4f} (improvement: {improvement:+.4f})")
599+
else:
600+
iterations_without_improvement += 1
601+
logger.debug(f"No improvement: {iterations_without_improvement}/{self.config.early_stopping_patience}")
602+
603+
# Check if we should stop
604+
if iterations_without_improvement >= self.config.early_stopping_patience:
605+
logger.info(
606+
f"Early stopping triggered at iteration {completed_iteration}: "
607+
f"No improvement for {iterations_without_improvement} iterations "
608+
f"(best score: {best_score:.4f})"
609+
)
610+
break
611+
566612
except Exception as e:
567613
logger.error(f"Error processing result from iteration {completed_iteration}: {e}")
568614

0 commit comments

Comments
 (0)