Documentation
¶
Overview ¶
Package ga is a small, dependency-free genetic algorithm for maximizing a caller-supplied fitness function over fixed-length vectors of float64.
It combines elitism, tournament selection, per-gene crossover, and Gaussian mutation, and resists premature convergence with two diversity mechanisms: a floor of fresh random immigrants injected every generation, and a mutation rate that widens while the best fitness is stagnating and relaxes once it improves again. All randomness derives from Config.Seed, so a run is fully reproducible and independent of the order in which genomes are evaluated.
Most callers use Run (or an Optimizer for step-by-step control). Callers that need to evaluate a generation concurrently can drive Reproduce, the pure generational operator, from their own loop.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RandomGenome ¶
RandomGenome returns n independent standard-normal genes drawn from rng.
func Reproduce ¶
Reproduce returns the next generation from the current genomes and their fitness (in the same order). gen is the generation index, which seeds the immigrant stream; stalled is the number of generations since the best fitness last improved, which drives adaptive mutation. It is pure and deterministic given Config.Seed, gen, stalled, and the inputs, so a caller that evaluates fitness concurrently still gets reproducible evolution.
Types ¶
type Config ¶
type Config struct {
// PopulationSize is the number of genomes carried each generation. It is used
// by [Run] and [NewOptimizer]; [Reproduce] takes the size from its input.
PopulationSize int
// EliteFraction is the share of the fittest genomes copied unchanged into the
// next generation. At least one elite is always kept.
EliteFraction float64
// MutationRate is the per-gene probability of a Gaussian perturbation.
MutationRate float64
// MutationStd is the standard deviation of that perturbation.
MutationStd float64
// TournamentSize is the number of genomes sampled per selection (default 3).
TournamentSize int
// ImmigrantFraction is the share of each generation reseeded with fresh random
// genomes, keeping a permanent floor of diversity (default 0.15).
ImmigrantFraction float64
// StagnationWindow is the number of generations without an improvement in the
// best fitness that trigger widened mutation (default 4; 0 disables it).
StagnationWindow int
// HyperMutation scales MutationRate and MutationStd while the best fitness is
// stagnating (default 6).
HyperMutation float64
// Seed makes the whole run reproducible.
Seed int64
}
Config parameters the genetic algorithm. Zero values for TournamentSize and the diversity fields are replaced with sensible defaults, so the minimum useful configuration is a PopulationSize, the two mutation settings, and a Seed.
type Optimizer ¶
type Optimizer struct {
// contains filtered or unexported fields
}
Optimizer maximizes a Fitness over fixed-length float genomes, one generation at a time. It tracks the best genome seen and the stagnation used by adaptive mutation. It is deterministic given Config.Seed.
func NewOptimizer ¶
NewOptimizer builds an optimizer with a random initial population of the given genome length. Any seed genomes are placed at the front of the population (truncated to the population size), so a known-good starting point — such as the incumbent solution — is always evaluated and, with elitism, never lost.
func (*Optimizer) Best ¶
Best returns a copy of the fittest genome found so far and its fitness. It returns nil before the first Optimizer.Step.
func (*Optimizer) Generation ¶
Generation returns the number of generations evaluated so far.
type Result ¶
type Result struct {
// Best is the fittest genome found.
Best []float64
// Fitness is Best's fitness.
Fitness float64
// Generations is the number of generations evaluated.
Generations int
}
Result is the outcome of Run.
func Run ¶
Run evolves a population for the given number of generations and returns the best genome found. Seed genomes are carried into the initial population (see NewOptimizer); passing the incumbent solution guarantees the result never scores worse than it, provided generations is at least one.