1515
1616from openevolve .config import DatabaseConfig
1717from openevolve .utils .code_utils import calculate_edit_distance
18+ from openevolve .utils .metrics_utils import safe_numeric_average
1819
1920logger = logging .getLogger (__name__ )
2021
@@ -227,10 +228,10 @@ def get_best_program(self, metric: Optional[str] = None) -> Optional[Program]:
227228 if sorted_programs :
228229 logger .debug (f"Found best program by combined_score: { sorted_programs [0 ].id } " )
229230 else :
230- # Sort by average of all metrics as fallback
231+ # Sort by average of all numeric metrics as fallback
231232 sorted_programs = sorted (
232233 self .programs .values (),
233- key = lambda p : sum (p .metrics . values ()) / max ( 1 , len ( p . metrics ) ),
234+ key = lambda p : safe_numeric_average (p .metrics ),
234235 reverse = True ,
235236 )
236237 if sorted_programs :
@@ -281,10 +282,10 @@ def get_top_programs(self, n: int = 10, metric: Optional[str] = None) -> List[Pr
281282 reverse = True ,
282283 )
283284 else :
284- # Sort by average of all metrics
285+ # Sort by average of all numeric metrics
285286 sorted_programs = sorted (
286287 self .programs .values (),
287- key = lambda p : sum (p .metrics . values ()) / max ( 1 , len ( p . metrics ) ),
288+ key = lambda p : safe_numeric_average (p .metrics ),
288289 reverse = True ,
289290 )
290291
@@ -436,7 +437,7 @@ def _calculate_feature_coords(self, program: Program) -> List[int]:
436437 if not program .metrics :
437438 bin_idx = 0
438439 else :
439- avg_score = sum ( program . metrics . values ()) / len (program .metrics )
440+ avg_score = safe_numeric_average (program .metrics )
440441 bin_idx = min (int (avg_score * self .feature_bins ), self .feature_bins - 1 )
441442 coords .append (bin_idx )
442443 elif dim in program .metrics :
@@ -487,9 +488,9 @@ def _is_better(self, program1: Program, program2: Program) -> bool:
487488 if "combined_score" in program1 .metrics and "combined_score" in program2 .metrics :
488489 return program1 .metrics ["combined_score" ] > program2 .metrics ["combined_score" ]
489490
490- # Fallback to average of all metrics
491- avg1 = sum ( program1 . metrics . values ()) / len (program1 .metrics )
492- avg2 = sum ( program2 . metrics . values ()) / len (program2 .metrics )
491+ # Fallback to average of all numeric metrics
492+ avg1 = safe_numeric_average (program1 .metrics )
493+ avg2 = safe_numeric_average (program2 .metrics )
493494
494495 return avg1 > avg2
495496
@@ -507,9 +508,7 @@ def _update_archive(self, program: Program) -> None:
507508
508509 # Otherwise, find worst program in archive
509510 archive_programs = [self .programs [pid ] for pid in self .archive ]
510- worst_program = min (
511- archive_programs , key = lambda p : sum (p .metrics .values ()) / max (1 , len (p .metrics ))
512- )
511+ worst_program = min (archive_programs , key = lambda p : safe_numeric_average (p .metrics ))
513512
514513 # Replace if new program is better
515514 if self ._is_better (program , worst_program ):
@@ -716,7 +715,7 @@ def _enforce_population_limit(self) -> None:
716715 # Sort by average metric (worst first)
717716 sorted_programs = sorted (
718717 all_programs ,
719- key = lambda p : sum (p .metrics . values ()) / max ( 1 , len ( p . metrics )) if p . metrics else 0.0 ,
718+ key = lambda p : safe_numeric_average (p .metrics ) ,
720719 )
721720
722721 # Remove worst programs, but never remove the best program
@@ -811,9 +810,7 @@ def migrate_programs(self) -> None:
811810
812811 # Sort by fitness (using combined_score or average metrics)
813812 island_programs .sort (
814- key = lambda p : p .metrics .get (
815- "combined_score" , sum (p .metrics .values ()) / max (1 , len (p .metrics ))
816- ),
813+ key = lambda p : p .metrics .get ("combined_score" , safe_numeric_average (p .metrics )),
817814 reverse = True ,
818815 )
819816
@@ -858,9 +855,7 @@ def get_island_stats(self) -> List[dict]:
858855
859856 if island_programs :
860857 scores = [
861- p .metrics .get (
862- "combined_score" , sum (p .metrics .values ()) / max (1 , len (p .metrics ))
863- )
858+ p .metrics .get ("combined_score" , safe_numeric_average (p .metrics ))
864859 for p in island_programs
865860 ]
866861
0 commit comments