- selector: tournament selection for parent sampling from island populations - prompt: assembles evolution prompts from parent code, replay analysis, and meta description - llm: OpenAI-compatible client routing to ZAI proxy with fast (GLM-5-Turbo) and strong (GLM-5) tiers, plus code block extraction from model responses - Tests for prompt assembly, code extraction, and tournament selection Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
55 lines
1.6 KiB
Go
55 lines
1.6 KiB
Go
// Package selector implements parent sampling strategies for the evolution
|
|
// pipeline. The primary strategy is tournament selection, which balances
|
|
// selection pressure (favoring fit individuals) with diversity (random
|
|
// sampling prevents premature convergence).
|
|
package selector
|
|
|
|
import (
|
|
"math/rand"
|
|
|
|
evolverdb "github.com/aicodebattle/acb/cmd/acb-evolver/internal/db"
|
|
)
|
|
|
|
// TournamentSelect picks the highest-fitness program from k randomly sampled
|
|
// candidates drawn without replacement from programs.
|
|
//
|
|
// When k ≥ len(programs) the function returns the globally best program.
|
|
// Returns nil when programs is empty.
|
|
func TournamentSelect(programs []*evolverdb.Program, k int, rng *rand.Rand) *evolverdb.Program {
|
|
if len(programs) == 0 {
|
|
return nil
|
|
}
|
|
|
|
// If k covers the whole population, just return the global best.
|
|
if k >= len(programs) {
|
|
best := programs[0]
|
|
for _, p := range programs[1:] {
|
|
if p.Fitness > best.Fitness {
|
|
best = p
|
|
}
|
|
}
|
|
return best
|
|
}
|
|
|
|
// Sample k distinct indices using a Fisher-Yates partial shuffle.
|
|
indices := rng.Perm(len(programs))[:k]
|
|
|
|
best := programs[indices[0]]
|
|
for _, idx := range indices[1:] {
|
|
if programs[idx].Fitness > best.Fitness {
|
|
best = programs[idx]
|
|
}
|
|
}
|
|
return best
|
|
}
|
|
|
|
// SelectParents draws n parents via tournament selection with tournament size k.
|
|
// The same program may be selected more than once (sampling with replacement
|
|
// across tournaments).
|
|
func SelectParents(programs []*evolverdb.Program, n, k int, rng *rand.Rand) []*evolverdb.Program {
|
|
parents := make([]*evolverdb.Program, n)
|
|
for i := range parents {
|
|
parents[i] = TournamentSelect(programs, k, rng)
|
|
}
|
|
return parents
|
|
}
|