import random from multi_swarm.ga.loop import GAConfig, next_generation from multi_swarm.genome.hypothesis import HypothesisAgentGenome, ModelTier def make(idx: int) -> HypothesisAgentGenome: return HypothesisAgentGenome( system_prompt=f"p-{idx}", feature_access=["close"], temperature=0.9, top_p=0.95, model_tier=ModelTier.C, lookback_window=100, cognitive_style="x", ) def test_next_generation_size_preserved() -> None: population = [make(i) for i in range(20)] fitnesses = {g.id: float(i) for i, g in enumerate(population)} cfg = GAConfig(population_size=20, elite_k=2, tournament_k=3, p_crossover=0.5) new_pop = next_generation(population, fitnesses, cfg, rng=random.Random(0)) assert len(new_pop) == 20 def test_next_generation_includes_elites() -> None: population = [make(i) for i in range(20)] fitnesses = {g.id: float(i) for i, g in enumerate(population)} cfg = GAConfig(population_size=20, elite_k=2, tournament_k=3, p_crossover=0.5) new_pop = next_generation(population, fitnesses, cfg, rng=random.Random(0)) elite_ids = { g.id for g in sorted(population, key=lambda g: fitnesses[g.id], reverse=True)[:2] } new_ids = {g.id for g in new_pop} assert elite_ids.issubset(new_ids) def test_next_generation_increments_generation_for_offspring() -> None: population = [make(i) for i in range(20)] fitnesses = {g.id: float(i) for i, g in enumerate(population)} cfg = GAConfig(population_size=20, elite_k=2, tournament_k=3, p_crossover=0.5) new_pop = next_generation(population, fitnesses, cfg, rng=random.Random(0)) new_offspring = [g for g in new_pop if g.id not in {p.id for p in population}] assert all(g.generation > 0 for g in new_offspring)