ga

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2026 License: MIT Imports: 2 Imported by: 0

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

func RandomGenome(n int, rng *rand.Rand) []float64

RandomGenome returns n independent standard-normal genes drawn from rng.

func Reproduce

func Reproduce(cfg Config, genomes [][]float64, fitness []float64, gen, stalled int) [][]float64

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 Fitness

type Fitness func(genome []float64) float64

Fitness scores a genome; larger is better.

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

func NewOptimizer(cfg Config, genomeLen int, seed ...[]float64) *Optimizer

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

func (o *Optimizer) Best() (genome []float64, fitness float64)

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

func (o *Optimizer) Generation() int

Generation returns the number of generations evaluated so far.

func (*Optimizer) Step

func (o *Optimizer) Step(f Fitness)

Step evaluates the current population with f, updates the best genome and stagnation counter, then replaces the population with the next generation.

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

func Run(cfg Config, genomeLen, generations int, f Fitness, seed ...[]float64) Result

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL