Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions openevolve/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
ProgramState,
)
from openevolve.utils.code_utils import calculate_edit_distance
from openevolve.utils.metrics_utils import safe_numeric_average, get_fitness_score
from openevolve.utils.metrics_utils import get_fitness_score, safe_numeric_average

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -186,6 +186,9 @@ def __init__(
# Track the last iteration number (for resuming)
self.last_iteration: int = 0

# Initialize before loading so restored MAP-Elites scales are retained.
self.feature_stats: Dict[str, Dict[str, Union[float, float, List[float]]]] = {}

# Load database from disk if path is provided
if config.db_path and os.path.exists(config.db_path):
self.load(config.db_path)
Expand All @@ -211,7 +214,6 @@ def __init__(
self.diversity_reference_size: int = getattr(config, "diversity_reference_size", 20)

# Feature scaling infrastructure
self.feature_stats: Dict[str, Dict[str, Union[float, float, List[float]]]] = {}
self.feature_scaling_method: str = "minmax" # Options: minmax, zscore, percentile

# Per-dimension bins support
Expand Down Expand Up @@ -1136,6 +1138,7 @@ def _llm_judge_novelty(self, program: Program, similar_program: Program) -> bool
Use LLM to judge if a program is novel compared to a similar existing program
"""
import asyncio

from openevolve.novelty_judge import NOVELTY_SYSTEM_MSG, NOVELTY_USER_MSG

user_msg = NOVELTY_USER_MSG.format(
Expand Down
45 changes: 45 additions & 0 deletions tests/test_constructor_feature_stats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""Loading through db_path must retain the checkpoint's MAP-Elites scale."""

import tempfile
import unittest

from openevolve.config import DatabaseConfig
from openevolve.database import Program, ProgramDatabase


class TestConstructorFeatureStats(unittest.TestCase):
def setUp(self):
self.tempdir = tempfile.TemporaryDirectory()
self.addCleanup(self.tempdir.cleanup)
self.config = DatabaseConfig(
in_memory=True,
num_islands=1,
feature_dimensions=["custom"],
feature_bins=10,
archive_size=1,
)
self.db = ProgramDatabase(self.config)
self.db._update_feature_stats("custom", 0.0)
self.db._update_feature_stats("custom", 100.0)
self.program = Program(
id="candidate", code="pass", metrics={"combined_score": 0.5, "custom": 25.0}
)
self.db.add(self.program)
self.db.save(self.tempdir.name)
self.config.db_path = self.tempdir.name

def test_constructor_preserves_loaded_feature_ranges(self):
restored = ProgramDatabase(self.config)
self.assertEqual(restored.feature_stats, self.db.feature_stats)

def test_constructor_preserves_feature_placement_without_second_load(self):
expected = self.db._calculate_feature_coords(self.program)
restored = ProgramDatabase(self.config)
self.assertEqual(expected, [2])
self.assertEqual(
restored._calculate_feature_coords(restored.programs[self.program.id]), expected
)


if __name__ == "__main__":
unittest.main()
Loading