feat(ga): initial population generator with cognitive style coverage
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
from ..genome.hypothesis import HypothesisAgentGenome, ModelTier
|
||||||
|
from ..genome.mutation import COGNITIVE_STYLES
|
||||||
|
|
||||||
|
STYLE_PROMPTS: dict[str, str] = {
|
||||||
|
"physicist": (
|
||||||
|
"Cerca leggi conservative, simmetrie, regimi di scala. "
|
||||||
|
"Pensa in termini di flussi e potenziali."
|
||||||
|
),
|
||||||
|
"biologist": (
|
||||||
|
"Cerca pattern adattivi, nicchie ecologiche, "
|
||||||
|
"predator-prey dynamics tra partecipanti del mercato."
|
||||||
|
),
|
||||||
|
"historian": (
|
||||||
|
"Cerca pattern ricorrenti su scale temporali multiple, "
|
||||||
|
"analogie con regimi storici, mean reversion strutturali."
|
||||||
|
),
|
||||||
|
"meteorologist": (
|
||||||
|
"Cerca regimi di volatilità che si autoalimentano, "
|
||||||
|
"transizioni di stato come fronti, persistenza locale."
|
||||||
|
),
|
||||||
|
"ecologist": (
|
||||||
|
"Cerca interazioni multi-asset, correlazioni cluster, "
|
||||||
|
"segnali di stress sistemico nelle dinamiche di flusso."
|
||||||
|
),
|
||||||
|
"engineer": (
|
||||||
|
"Cerca segnali con rapporto S/N favorevole, filtri causali, "
|
||||||
|
"robustezza a perturbazioni di calibrazione."
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def build_initial_population(
|
||||||
|
k: int,
|
||||||
|
model_tier: ModelTier,
|
||||||
|
rng: random.Random,
|
||||||
|
feature_pool: tuple[str, ...] = ("close", "high", "low", "volume"),
|
||||||
|
) -> list[HypothesisAgentGenome]:
|
||||||
|
"""Costruisce una popolazione iniziale K varia per stile cognitivo + parametri."""
|
||||||
|
population: list[HypothesisAgentGenome] = []
|
||||||
|
for i in range(k):
|
||||||
|
style = COGNITIVE_STYLES[i % len(COGNITIVE_STYLES)]
|
||||||
|
n_features = rng.randint(1, len(feature_pool))
|
||||||
|
feats = sorted(rng.sample(feature_pool, k=n_features))
|
||||||
|
g = HypothesisAgentGenome(
|
||||||
|
system_prompt=STYLE_PROMPTS[style],
|
||||||
|
feature_access=feats,
|
||||||
|
temperature=round(rng.uniform(0.7, 1.2), 2),
|
||||||
|
top_p=0.95,
|
||||||
|
model_tier=model_tier,
|
||||||
|
lookback_window=rng.choice([100, 150, 200, 300]),
|
||||||
|
cognitive_style=style,
|
||||||
|
)
|
||||||
|
# Seed per garantire id univoco se duplicato (raro ma possibile)
|
||||||
|
while any(g.id == p.id for p in population):
|
||||||
|
g = HypothesisAgentGenome(
|
||||||
|
system_prompt=g.system_prompt + f" [seed-{i}-{rng.randint(0, 1_000_000)}]",
|
||||||
|
feature_access=g.feature_access,
|
||||||
|
temperature=g.temperature,
|
||||||
|
top_p=g.top_p,
|
||||||
|
model_tier=g.model_tier,
|
||||||
|
lookback_window=g.lookback_window,
|
||||||
|
cognitive_style=g.cognitive_style,
|
||||||
|
)
|
||||||
|
population.append(g)
|
||||||
|
return population
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import random
|
||||||
|
|
||||||
|
from multi_swarm.ga.initial import build_initial_population
|
||||||
|
from multi_swarm.genome.hypothesis import ModelTier
|
||||||
|
|
||||||
|
|
||||||
|
def test_initial_population_size():
|
||||||
|
pop = build_initial_population(k=20, model_tier=ModelTier.C, rng=random.Random(0))
|
||||||
|
assert len(pop) == 20
|
||||||
|
|
||||||
|
|
||||||
|
def test_initial_population_unique_ids():
|
||||||
|
pop = build_initial_population(k=20, model_tier=ModelTier.C, rng=random.Random(0))
|
||||||
|
ids = {g.id for g in pop}
|
||||||
|
assert len(ids) == 20
|
||||||
|
|
||||||
|
|
||||||
|
def test_initial_population_covers_all_styles():
|
||||||
|
pop = build_initial_population(k=12, model_tier=ModelTier.C, rng=random.Random(0))
|
||||||
|
styles = {g.cognitive_style for g in pop}
|
||||||
|
assert len(styles) == 6
|
||||||
|
|
||||||
|
|
||||||
|
def test_initial_population_generation_zero():
|
||||||
|
pop = build_initial_population(k=20, model_tier=ModelTier.C, rng=random.Random(0))
|
||||||
|
assert all(g.generation == 0 for g in pop)
|
||||||
|
assert all(g.parent_ids == [] for g in pop)
|
||||||
Reference in New Issue
Block a user