Summary
select_next_parent.py builds a child_counts dictionary tracking the number of
descendants each candidate parent has spawned, then immediately discards it and
selects a parent uniformly at random via random.choice. The computation is dead
code, and the selection is not actually novelty-weighted --- both contradict what
a reader of the function would reasonably expect from a method named
select_next_parent in an open-ended exploration framework.
Reproduction
select_next_parent.py:50-57 (current main):
# Build child counts from metadata
child_counts = {genid: 0 for genid in candidates}
for genid in archive:
parent = get_parent_genid(output_dir, genid)
if parent in child_counts:
child_counts[parent] += 1
# Select parent randomly, keeping the search space open
return random.choice(list(candidates.keys()))
child_counts is constructed but never read. The selection ignores it entirely.
Expected behavior
Either:
-
Option A (preferred): the function uses child_counts to implement
novelty-weighted selection (probability inversely proportional to
1 + child_counts[genid]), so under-explored candidates are preferentially
picked. This is the standard mechanism used by FunSearch, MAP-Elites, and
AlphaEvolve to prevent mode collapse during open-ended search, and it appears
to be what the existing code structure is reaching for.
-
Option B: if uniform random is genuinely the intended behavior, the
child_counts computation should be deleted and the docstring/comment updated
to reflect that the function does not prefer under-explored branches.
Actual behavior
Selection is uniform random. The child_counts table is computed every call and
thrown away. Downstream evolutionary loops that rely on this function for diverse
parent selection silently get unweighted sampling instead.
Impact
In the use case I encountered (a custom domain that ran 10 generations on a
single-incumbent loop), uniform random parent selection contributed to mode
collapse: only 4 distinct child variants emerged across 10 generations. While
that was partly attributable to the calling code, the framework documentation
implies a smarter selection strategy than is actually implemented.
Proposed fix
I have a PR ready that implements Option A (novelty-weighted sampling), with
backward-compatible API and a deterministic unit test. Happy to open it
immediately if maintainers agree on the direction.
Environment
- HyperAgents commit:
main HEAD as of 2026-05-03
- File:
select_next_parent.py lines 50-57
Summary
select_next_parent.pybuilds achild_countsdictionary tracking the number ofdescendants each candidate parent has spawned, then immediately discards it and
selects a parent uniformly at random via
random.choice. The computation is deadcode, and the selection is not actually novelty-weighted --- both contradict what
a reader of the function would reasonably expect from a method named
select_next_parentin an open-ended exploration framework.Reproduction
select_next_parent.py:50-57(currentmain):child_countsis constructed but never read. The selection ignores it entirely.Expected behavior
Either:
Option A (preferred): the function uses
child_countsto implementnovelty-weighted selection (probability inversely proportional to
1 + child_counts[genid]), so under-explored candidates are preferentiallypicked. This is the standard mechanism used by FunSearch, MAP-Elites, and
AlphaEvolve to prevent mode collapse during open-ended search, and it appears
to be what the existing code structure is reaching for.
Option B: if uniform random is genuinely the intended behavior, the
child_countscomputation should be deleted and the docstring/comment updatedto reflect that the function does not prefer under-explored branches.
Actual behavior
Selection is uniform random. The
child_countstable is computed every call andthrown away. Downstream evolutionary loops that rely on this function for diverse
parent selection silently get unweighted sampling instead.
Impact
In the use case I encountered (a custom domain that ran 10 generations on a
single-incumbent loop), uniform random parent selection contributed to mode
collapse: only 4 distinct child variants emerged across 10 generations. While
that was partly attributable to the calling code, the framework documentation
implies a smarter selection strategy than is actually implemented.
Proposed fix
I have a PR ready that implements Option A (novelty-weighted sampling), with
backward-compatible API and a deterministic unit test. Happy to open it
immediately if maintainers agree on the direction.
Environment
mainHEAD as of 2026-05-03select_next_parent.pylines 50-57