Threshold-Elites Island-based Program Selection #407
Closed
+145
−8
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Net effect (what changes for users)
You can now choose between map-elites and threshold-elites archive insertion using DatabaseConfig.variant.
In threshold-elites, programs are:
filtered by novelty,
grouped into islands (with parent island inheritance),
and locally compared by embedding distance with a winner-takes-all rule inside a threshold radius.
The attention optimization evaluator becomes more portable (pathing) and its output schema shifts toward a combined_score field.
openevolve/database.py
This is the main functional change: introduces a “threshold-elites” variant alongside map-elites, and refactors add() accordingly.
Variant-based dispatch in add(...)
Database.add(...) now checks config.variant:
"map-elites" → add_map_elites_program(...)
"threshold-elites" → add_threshold_elites_program(...)
otherwise raises NotImplementedError.
New add_threshold_elites_program(...) behavior
When adding a program:
Stores program + iteration bookkeeping
Computes embedding + an elite score
Calls _calculate_feature_coords(program) and stores in program.embedding.
Computes a fitness-based score = get_fitness_score(...).
Stores program.metrics["elite_score"] = score.
Determines island placement
If target_island is not given and the program has a parent, it inherits the parent’s island from parent.metadata["island"] to keep island isolation.
Else falls back to self.current_island.
Novelty gating happens before insertion
Threshold-elites competition (within an island)
For existing programs in the island, computes Euclidean distance between embeddings.
If distance < elite_threshold, it keeps the higher elite_score and demotes the other by setting its elite_score to -inf (effectively marking it as dominated).
Finalization
Exploration parent sampling now preserves embeddings
In two places inside _sample_exploration_parent(...), when cloning the best program, it now does:
This prevents the clone from sharing the same embedding object reference.
Misc
openevolve/config.py
Extends DatabaseConfig with parameters to support a new archive strategy:
variant: str = "threshold-elites" (strategy selector)
elite_threshold: int = 3 (distance threshold used by the new strategy)
examples/attention_optimization/evaluator.py
Makes MLIR path resolution robust:
Previously: Path("mlir/self_attn_with_consts_linalg_dialect.mlir") (relative to current working directory).
Now: builds an absolute path relative to the evaluator file’s directory using file. This prevents failures when running from a different working directory.
Renames/standardizes a scoring field:
In estimate_performance_from_ir(...), the returned dict changes from using optimization_score to combined_score.
In evaluate(...), result packaging similarly switches from optimization_score → combined_score.