From 3a95327bf1f8b2184fd35ebae96a3aea0c94dc56 Mon Sep 17 00:00:00 2001 From: Henry Liu Date: Wed, 18 Jun 2025 12:04:29 +0800 Subject: [PATCH 1/2] fix: replace glob.glob root_dir with os.walk for checkpoint search --- scripts/visualizer.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/visualizer.py b/scripts/visualizer.py index 081f8efc9..83689c6dd 100644 --- a/scripts/visualizer.py +++ b/scripts/visualizer.py @@ -16,11 +16,17 @@ def find_latest_checkpoint(base_folder): if os.path.basename(base_folder).startswith("checkpoint_"): return base_folder - checkpoint_folders = glob.glob("**/checkpoint_*", root_dir=base_folder, recursive=True) + # checkpoint_folders = glob.glob("**/checkpoint_*", root_dir=base_folder, recursive=True) + # glob.glob 没有 root_dir 参数,需手动递归遍历 + checkpoint_folders = [] + for root, dirs, files in os.walk(base_folder): + for d in dirs: + if d.startswith("checkpoint_"): + checkpoint_folders.append(os.path.join(root, d)) + if not checkpoint_folders: logger.info(f"No checkpoint folders found in {base_folder}") return None - checkpoint_folders = [os.path.join(base_folder, folder) for folder in checkpoint_folders] checkpoint_folders.sort(key=lambda x: os.path.getmtime(x), reverse=True) logger.debug(f"Found checkpoint folder: {checkpoint_folders[0]}") return checkpoint_folders[0] From b717b085be896929e7892ba6f8bbd225e9b6352b Mon Sep 17 00:00:00 2001 From: Henry Liu Date: Wed, 18 Jun 2025 12:20:37 +0800 Subject: [PATCH 2/2] Fix(database): Prevent KeyError during parent sampling The _enforce_population_limit function did not remove culled program IDs from self.archive and self.feature_map. This caused a KeyError when the sampling logic later tried to access a program ID that no longer existed in the main self.programs dictionary. This patch ensures that culled programs are removed from all relevant data structures, making the evolution process more robust. --- openevolve/database.py | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/openevolve/database.py b/openevolve/database.py index 48527c384..29e160842 100644 --- a/openevolve/database.py +++ b/openevolve/database.py @@ -743,30 +743,27 @@ def _enforce_population_limit(self) -> None: additional_removals = remaining_programs[: num_to_remove - len(programs_to_remove)] programs_to_remove.extend(additional_removals) - # Remove the selected programs + # Remove from main dictionary and their respective islands for program in programs_to_remove: program_id = program.id - - # Remove from main programs dict if program_id in self.programs: del self.programs[program_id] - # Remove from feature map - keys_to_remove = [] - for key, pid in self.feature_map.items(): - if pid == program_id: - keys_to_remove.append(key) - for key in keys_to_remove: - del self.feature_map[key] - - # Remove from islands + # Also remove from islands for island in self.islands: island.discard(program_id) - # Remove from archive + # CRITICAL FIX: Also remove from archive and feature_map self.archive.discard(program_id) - logger.debug(f"Removed program {program_id} due to population limit") + # Remove from feature_map if it's the one stored there + keys_to_remove = [ + key for key, value in self.feature_map.items() if value == program_id + ] + for key in keys_to_remove: + del self.feature_map[key] + + logger.info(f"Removed program {program_id} to maintain population size.") logger.info(f"Population size after cleanup: {len(self.programs)}")