nucleotide

package module
v0.13.0 Latest Latest
Warning

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

Go to latest
Published: Jul 24, 2026 License: BSD-3-Clause Imports: 13 Imported by: 0

README

Nucleotide

Nucleotide is a highly modular and type-safe Genetic Algorithm (GA) framework for Go, designed to evolve complex behaviors and parameters for software agents and simulations.

It introduces the concept of Categorical Genomes, where evolution doesn't just tune numbers, but selects specific behaviors (functions) and configurations that can be directly executed in a simulated or real-world environment.

Key Features

  • Generic Environments ([E any]): Pass any type (Database connections, World simulations, API clients) directly to your genes.
  • Typed Loci Architecture:
    • Behavioral: Genes that execute logic via callbacks.
    • Parameter: Genes that provide data values for behavioral genes.
    • Configuration: Internal framework settings that can themselves be evolved.
    • Sequence: Slots that define a permutation range to evolve orderings, routing sequences, or schedules.
  • Multi-Chromosomal Genomes (CompositeGenome): Map multiple distinct chromosomes by name to evolve complex combinations of behavioral categorical genes, configurations, and independent sequences simultaneously.
  • Permutation Optimization (SequenceGenome): Native support for permutation sequence evolution powered by Partially Mapped Crossover (PMX) and Swap Mutation to guarantee duplicate-free evolution.
  • Unified Robust Serialization: Save any winning genome (BitGenome, FloatGenome, SequenceGenome, CategoricalGenome, CompositeGenome) to JSON using stable IDs, and reload them seamlessly in production.
  • Context-Aware Expression: Execute evolved individuals with context.Context for safe cancellation and timeouts.
  • Modern Go: Built with Go 1.22+ and fully leverages Generics.

Core Concepts: Loci vs. Genes

[!NOTE] Loci (pronounced lo-sigh) is the plural form of Locus. Throughout the library and documentation, we use Locus when referring to a single slot, and Loci when referring to multiple slots.

To understand Nucleotide, it's essential to distinguish between a Locus and a Gene:

The Biological Analogy

Imagine the trait for Eye Color.

  • The Locus is the specific position on a chromosome that determines eye color. Every human has this "slot".
  • The Gene (or allele) is the specific version occupying that slot—such as Blue, Brown, or Green.
The Software Analogy

In a software system, imagine a Sorting Strategy:

  • The Locus is the abstract "Sorting" component in your architecture.
  • The Genes are the concrete implementations you can plug in: QuickSort, MergeSort, or HeapSort.

Evolution in Nucleotide works by testing which Gene performs best at each Locus given a specific environment.

Advanced Dynamics

1. Execution Order

Nucleotide allows the evolution of the order in which genes are expressed. In many systems, the sequence of operations is as critical as the operations themselves. For example, in a processing pipeline, executing ValidateData before SaveToDB is mandatory, but the order of optional Enrichment steps might yield different results depending on environmental constraints (like latency or data availability).

2. Parameterization & Adaptation

Parameter Genes allow a specific algorithm (Gene) to operate differently to best suit its environment.

  • Example: In a K-Means Clustering algorithm, the number of clusters (k) is a critical parameter.
  • A locus could define the "Cluster Count", and evolution would find the optimal k for the current dataset, allowing the same K-Means gene to adapt its behavior without changing its core logic.

Advanced Selection & Evolution Operators

Nucleotide provides a highly customizable operator execution model and advanced selection algorithms to prevent premature convergence and control selection pressure.

1. Multi-Operator Slices & Fallback Defaults

Instead of defining a single crossover or mutation strategy, EngineConfig supports multiple strategies in slices:

  • Crossoverers & Mutators: Slices of strategies that run interchangeably. If empty, Nucleotide supplies smart defaults (DefaultCrossoverer and DefaultMutator) that automatically adjust at runtime to the type of genome being processed (BitGenome, FloatGenome, or CategoricalGenome).
  • Pondered Weights: Use CrossovererWeights and MutatorWeights to configure custom probability distributions for each operator. If weights are omitted, the engine defaults to a smooth, alternating Round-Robin sequencing strategy.
2. Individual Lifetime (Age) Tracking

Individuals track their survival generation span using an Age property, initialized to 0 and automatically incremented at the end of each generation loop in the evolutionary engine. This age metric is used to model life expectancy and introduce biological selection penalties.

3. Core Selection Operators

All custom selectors implement the standard Selector interface:

  • RouletteWheelSelector[E, S]: Proportional fitness selection with optional AutoShift capability to handle negative fitness boundaries.
  • StochasticUniversalSamplingSelector[E, S]: Low-variance, zero-bias multi-pointer selection utilizing a single-spin buffer queue to ensure equal-interval selection across sequential calls.
  • RankSelector[E, S]: Maps absolute fitness values to linear ranks ($1$ to $N$) with customizable SelectionPressure values. Prevents super-individuals from dominating early generations.
  • BoltzmannSelector[E, S]: Standard temperature-scaled selection ($e^{f(x) / T}$) allowing exploration/exploitation weighting across epochs.
4. Advanced GenericTournamentSelector[E, S] Features

The built-in tournament selector can be enhanced using several advanced, fully opt-in dynamics:

  • Adaptive Diversity: Sizing adapts dynamically depending on population standard deviation (reducing tournament size when diversity is low to encourage exploration).
  • Age Bias: A custom penalty applied to competitor fitness proportional to their survival age (adjustedFit = adjustedFit - age * AgeBias) to prevent stagnation.
  • Hall of Fame competitor mixing: Integrates historical elite individuals into active tournaments with a specified HallOfFameProbability to encourage competition.
  • Self-Adaptive Sizing: Individuals can adaptively define their preferred tournament sizing (TournamentSize) through parameter genes or custom state interfaces implementing SelfAdaptiveIndividual.
5. Dynamic Population Sizing

Nucleotide supports dynamic resizing of the population during evolution to match computational budgets or adapt to search space needs. By setting AdaptivePopulation: true in EngineConfig, you can provide a PopulationController (implementing AdaptivePopulationController[Env, State]) to compute the target population size for the next generation. Safety bounds (MinPopulationSize and MaxPopulationSize) are applied automatically to prevent unbounded growth or shrinkage. The framework provides several built-in controllers:

  • DiversitySigmoidPopulationController: Computes size using a smooth logistic sigmoid curve based on diversity (larger population size when diversity is low to encourage exploration, smaller size when diversity is high to save resources).
  • DiversityThresholdPopulationController: Resizes step-wise if diversity falls below a low threshold (increases size by a factor) or exceeds a high threshold (decreases size by a factor).
  • StagnationPopulationController: Increases population size if the best fitness has not improved for $N$ generations to help escape local optima, resetting/decaying to baseline when progress is resumed.
  • TemporalSchedulePopulationController: Scales population size following a linear, exponential, or cosine schedule relative to generation progress.
  • CallbackPopulationController: Invokes a custom user-defined function func(e *Engine) int to determine the size.
6. Concurrency-Safe Fitness Memoization Cache

Evaluating fitness is often the most expensive step in genetic algorithms. Nucleotide includes a built-in, thread-safe memoization cache to avoid redundant evaluations of identical genomes.

  • Opt-in Activation: Set EnableFitnessCache: true in EngineConfig to activate caching.
  • Race-Free Coalescing (Singleflight): Under high concurrency, if multiple identical genomes are evaluated simultaneously for the first time, only one execution of FitnessFunc is triggered. The other threads block and automatically receive the computed result once it is done.
  • Determinism: Genomes are uniquely and deterministically serialized to string keys (handles BitGenome, FloatGenome, SequenceGenome, CategoricalGenome, CompositeGenome, and custom types implementing String()).
  • Safety: Fitness arrays ([]float64) are copied when stored and retrieved to prevent references from being mutated by subsequent selection/elitism operations.
7. Pointer-Based Adaptive Mutator Wrapper

For cases where you want to dynamically adjust mutation probabilities from outside the engine (e.g., in a generation hook) without implementing a full controller, Nucleotide provides PointerAdaptiveMutator:

  • Wraps an existing Mutator and updates its Probability dynamically based on a shared float64 pointer before mutating.
  • Supports all built-in mutators (CategoricalMutator, SwapMutator, BitFlipMutator, GaussianMutator, CategoricalCreepMutator, SwapCategoricalMutator, etc.).
8. SwapCategoricalMutator for Categorical Genomes

Designed specifically for CategoricalGenome, SwapCategoricalMutator swaps the gene configurations of two compatible loci within the same individual.

  • Allows migration of strategies between loci while preserving the set of alleles chosen by the individual.
  • Verifies compatibility to ensure that the swapped values fit within the possible gene ranges of the target loci.
9. Adaptive Evaluation Windows / Dynamic Training Subset Selection

To speed up evolution and prevent overfitting (curriculum learning) in data-heavy tasks, Nucleotide allows you to dynamically scale the number of training scenarios/scenarios evaluated each generation. By setting AdaptiveWindow: true in EngineConfig, you can provide a WindowController (implementing AdaptiveWindowController[Env, State]).

  • Safety Boundaries: MinWindowSize and MaxWindowSize clamp the returned size.
  • Environment Integration: If the evolution environment Env implements the WindowAwareEnvironment interface, the engine automatically calls SetWindowSize(size) before each generation's evaluation.
  • Built-in Controllers:
    • LinearDecayWindowController: Linearly interpolates the window size from StartSize to EndSize based on generation progress.
    • DiversityFeedbackWindowController: Dynamically adjusts the window size based on diversity (larger window size when diversity is low to encourage generalization, smaller size when diversity is high to speed up convergence).
    • CallbackWindowController: Invokes a custom user-defined callback func(generation int, diversity float64) int.

Multi-Objective Optimization (NSGA-II)

Nucleotide supports Multi-Objective Optimization using the NSGA-II (Nondominated Sorting Genetic Algorithm II) algorithm. This is suitable when you need to optimize conflicting metrics in tension, such as maximizing performance/throughput while minimizing cost/power consumption.

Key NSGA-II Features:
  • Unified Fitness Signature: Fitness is represented as []float64 to transparently scale from single-objective (length 1) to multi-objective environments.
  • Configurable Directions: Define whether to Maximize or Minimize each objective independently via ObjectiveDirections []ObjectiveDirection.
  • Fast Non-Dominated Sorting: Classifies individuals into sequential Pareto frontiers ($F_1, F_2, \dots$) based on mathematical dominance.
  • Crowding Distance & Density Calculation: Scans boundary points and computes sparsity metrics to favor diverse, well-distributed solutions across the Pareto frontier.
  • Crowded Comparison Operator Selection: The GenericTournamentSelector automatically applies rank-based and crowding-distance-based tournament selection when running in multi-objective mode.
  • Pareto Frontier Access: Retrieve the best non-dominated solutions of a finished run via engine.ParetoFrontier().
Code Example:
config := nucleotide.EngineConfig[MyEnv, MyState]{
    PopulationSize: 100,
    MaxGenerations: 50,
    FitnessFunc: func(g nucleotide.Genome, env MyEnv) []float64 {
        // Return multiple fitness scores
        return []float64{performance, cost}
    },
    Selector: nucleotide.GenericTournamentSelector[MyEnv, MyState]{Size: 3},
    
    // Objective 0: Maximize performance
    // Objective 1: Minimize cost
    ObjectiveDirections: []nucleotide.ObjectiveDirection{
        nucleotide.Maximize,
        nucleotide.Minimize,
    },
}

engine, _ := nucleotide.NewEngine(config)
engine.Run(def)

// Retrieve the optimal trade-offs (Rank 0 non-dominated solutions)
paretoFrontier := engine.ParetoFrontier()

Parallel Island Model GA (MultiIslandEngine)

Nucleotide supports the Parallel Island Model Genetic Algorithm via the MultiIslandEngine struct. Instead of evolving a single global population, the population is divided into isolated sub-populations (islands) that evolve independently in parallel in their own goroutines, periodically exchanging individuals (migration epochs) to maintain diversity and prevent premature convergence.

Key Island Model Features:
  • True Concurrency: Sub-populations evolve concurrently on separate Go routine threads, synchronizing at migration epochs using a synchronization barrier (sync.WaitGroup).
  • Flexible Topologies: Configure migration routing using TopologyRing (cyclic neighbor routing) or TopologyRandom (fully connected randomized target routing).
  • Migration Policies: Support PolicyBestReplaceWorst (exploitation-focused: copies best individuals to replace target worst) or PolicyRandomReplaceRandom (exploration-focused).
  • 3 Environment Configurations (Option A, B, and C):
    • Option A (Shared Static Env): All islands share the same single environment (the default).
    • Option B (Distributed Independent Envs): The EnvFactory instantiates independent environment simulator instances to prevent resource contention.
    • Option C (Heterogeneous Envs): The EnvFactory provides specialized configurations per island (e.g. different weather/difficulties), forcing the co-evolution of generalist solutions.
Code Example:
config := nucleotide.EngineConfig[MyEnv, MyState]{
    PopulationSize: 20,
    MaxGenerations: 40,
    FitnessFunc:    myFitnessFunc,
    Selector:       nucleotide.GenericTournamentSelector[MyEnv, MyState]{Size: 3},
}

// Option C: Evolve across heterogeneous climates (Sunny, Windy, Rainy)
envFactory := func(islandIndex int) MyEnv {
    return climates[islandIndex]
}

miConfig := nucleotide.MultiIslandEngineConfig[MyEnv, MyState]{
    NumIslands:        3,
    MigrationInterval: 5, // migrate every 5 generations
    MigrationRate:     2, // move top 2 individuals
    MigrationTopology: nucleotide.TopologyRing,
    MigrationPolicy:   nucleotide.PolicyBestReplaceWorst,
    EngineConfig:      config,
    EnvFactory:        envFactory,
}

miEngine, _ := nucleotide.NewMultiIslandEngine(miConfig)
bestIndividual, _ := miEngine.Run(def)

Installation

go get github.com/rghashimoto/nucleotide

Usage Levels

1. Basic Usage (Optimization)

Ideal for solving classic optimization problems like OneMax or Knapsack using simple bitstring or float genomes.

  • Example: onemax/main.go
  • Goal: Find the bitstring with the maximum number of true values.
2. Structured Usage (Component Selection)

Use Categorical Genomes to select the best combination of components or traits for an entity.

  • Example: structured/main.go
  • Goal: Evolve an object with the best combination of Color, Size, and Material.
3. Advanced Usage (Behavioral Evolution)

Evolve agents that interact with a dynamic environment. Genes are functions that consume resources or change the state of the world.

  • Example: advanced/main.go
  • Goal: Evolve a survival strategy (Glutton vs. Frugal) in a world with limited food.
4. Multi-Objective Optimization (NSGA-II)

Solve complex problems where multiple conflicting objectives must be optimized simultaneously (e.g. maximizing value while minimizing weight).

  • Example: multiobjective/main.go
  • Goal: Find the non-dominated Pareto Frontier trade-offs for a dual-objective Knapsack problem.
5. Comprehensive Usage (Autonomous Routing & Multi-Chromosomal Evolution)

Co-evolve categorical behaviors, parameters, internal configurations, and sequence delivery routes using name-based multi-chromosomal mapping.

  • Example: comprehensive/main.go
  • Goal: Evolve the optimal drone battery configuration, pre-flight safety actions, sequential execution flow, and customer visitation route order in a unified cargo delivery simulation with round-trip JSON serialization.
6. Parallel Island Model GA (MultiIslandEngine)

Evolve sub-populations in parallel concurrently in separate goroutines, periodically migrating selected individuals to maintain diversity across heterogeneous climates.

  • Example: islands/main.go
  • Goal: Co-evolve a generalist drone dispatcher across three heterogeneous weather climates (Sunny, Windy, and Rainy) using concurrent island routines and ring migration epochs.

Customization & Extensibility

Nucleotide is built to be extended. You can customize almost every aspect of the genetic process by providing your own functions:

Function Type Purpose Usage
FitnessFunc[E] Defines how to score an individual. config.FitnessFunc = myFunc
ElitismFunc[E] Defines which individuals survive to the next generation. config.ElitismFunc = nucleotide.TopNElitism
PopulationFunc[E] Defines how the initial population is created. config.PopulationFunc = myPopFactory
Sequencer[E] Controls the order in which behavioral genes are expressed. Add to "Execution Order" Locus
Gene Callbacks The core logic executed when a gene is expressed. locus.AddGene("ID", myCallback)
AdaptiveMutationController Custom interface for dynamic mutation scaling. config.MutationController = myMutController
AdaptivePopulationController Custom interface for dynamic population sizing. config.PopulationController = myPopController
AdaptiveWindowController Custom interface for dynamic evaluation window sizing. config.WindowController = myWindowController
Example: Custom Sequencer

You can control the execution flow based on the selected genes:

execLocus.AddConfigGene("MyOrder", func(ctx SequencingContext[E]) []int {
    // Return a custom slice of indices to define the execution order
    return []int{1, 0, 2} 
})

From Evolution to Production

Nucleotide is designed to bridge the gap between AI research and production deployment.

  1. Evolve: Run the Genetic Engine to find the best individual.
  2. Save: Export the genome to a portable JSON file.
    best.Save("production_config.json")
    
  3. Deploy: Load the JSON in your production service and execute it.
    loadedGenome, _ := nucleotide.LoadGenome(prodDef, "production_config.json")
    agent := nucleotide.NewIndividual(loadedGenome)
    agent.Express(ctx, liveEnvironment)
    

License

BSD-3-Clause

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EncodeGenome

func EncodeGenome(g Genome) ([]byte, error)

EncodeGenome encodes a Genome's gene IDs into a JSON byte slice.

func SaveGenome

func SaveGenome(g Genome, filename string) error

SaveGenome saves a Genome's gene IDs to a JSON file.

Types

type AdaptiveMutationController

type AdaptiveMutationController[Env any, State any] interface {
	// GetMutationScaler returns a scaling factor for the mutation rate.
	GetMutationScaler(e *Engine[Env, State]) float64
}

AdaptiveMutationController defines the interface for dynamically scaling or adjusting mutation rates.

type AdaptivePopulationController added in v0.11.0

type AdaptivePopulationController[Env any, State any] interface {
	// GetPopulationSize returns the new target population size.
	GetPopulationSize(e *Engine[Env, State]) int
}

AdaptivePopulationController defines the interface for dynamically adjusting population sizes.

type AdaptiveWindowController added in v0.13.0

type AdaptiveWindowController[Env any, State any] interface {
	// GetWindowSize returns the number of active training scenarios/samples to evaluate for the current generation.
	GetWindowSize(generation int, diversity float64) int
}

AdaptiveWindowController defines the interface for dynamically adjusting evaluation window size.

type ArithmeticCrossover

type ArithmeticCrossover struct {
	Alpha float64 // weight factor in [0, 1]
}

ArithmeticCrossover performs arithmetic combination of two FloatGenomes.

func (ArithmeticCrossover) Crossover

func (c ArithmeticCrossover) Crossover(p1, p2 Genome) (Genome, Genome)

type BitFlipMutator

type BitFlipMutator struct {
	Probability float64
}

BitFlipMutator flips a bit with a given probability.

func (BitFlipMutator) Mutate

func (m BitFlipMutator) Mutate(g Genome) Genome

type BitGenome

type BitGenome []bool

BitGenome and FloatGenome are kept for compatibility.

func (BitGenome) Copy

func (g BitGenome) Copy() Genome

func (BitGenome) Size

func (g BitGenome) Size() int

type BoltzmannSelector

type BoltzmannSelector[Env any, State any] struct {
	Temperature float64 // Defaults to 1.0 if <= 0
}

BoltzmannSelector selects individuals using a Boltzmann distribution with temperature.

func (BoltzmannSelector[Env, State]) Select

func (s BoltzmannSelector[Env, State]) Select(pop interface{}) interface{}

func (BoltzmannSelector[Env, State]) SelectTyped

func (s BoltzmannSelector[Env, State]) SelectTyped(pop Population[Env, State]) *Individual[Env, State]

type CallbackPopulationController added in v0.11.0

type CallbackPopulationController[Env any, State any] struct {
	Callback func(e *Engine[Env, State]) int
}

CallbackPopulationController adjusts population size via a user-defined function.

func NewCallbackPopulationController added in v0.11.0

func NewCallbackPopulationController[Env any, State any](cb func(e *Engine[Env, State]) int) *CallbackPopulationController[Env, State]

NewCallbackPopulationController creates a new CallbackPopulationController.

func (*CallbackPopulationController[Env, State]) GetPopulationSize added in v0.11.0

func (c *CallbackPopulationController[Env, State]) GetPopulationSize(e *Engine[Env, State]) int

GetPopulationSize delegates the size computation to the user-supplied callback.

type CallbackWindowController added in v0.13.0

type CallbackWindowController[Env any, State any] struct {
	Callback func(generation int, diversity float64) int
}

CallbackWindowController delegates the window size calculation to a custom user-defined function.

func NewCallbackWindowController added in v0.13.0

func NewCallbackWindowController[Env any, State any](cb func(generation int, diversity float64) int) *CallbackWindowController[Env, State]

NewCallbackWindowController creates a new CallbackWindowController.

func (*CallbackWindowController[Env, State]) GetWindowSize added in v0.13.0

func (c *CallbackWindowController[Env, State]) GetWindowSize(generation int, diversity float64) int

GetWindowSize calls the custom callback.

type CategoricalCreepMutator

type CategoricalCreepMutator struct {
	Probability float64 // mutation probability per locus
}

CategoricalCreepMutator shifts the selected gene index of CategoricalGenomes to an adjacent option.

func (CategoricalCreepMutator) Mutate

type CategoricalGenome

type CategoricalGenome[Env any, State any] struct {
	Definition  *Definition[Env, State]
	GeneIndices []int
}

CategoricalGenome represents a genome where each locus has a specific gene chosen.

func (*CategoricalGenome[Env, State]) Copy

func (g *CategoricalGenome[Env, State]) Copy() Genome

func (*CategoricalGenome[Env, State]) GetDefinition

func (g *CategoricalGenome[Env, State]) GetDefinition() interface{}

func (*CategoricalGenome[Env, State]) GetGenePairs

func (g *CategoricalGenome[Env, State]) GetGenePairs() []LocusGenePair

func (*CategoricalGenome[Env, State]) GetIndices

func (g *CategoricalGenome[Env, State]) GetIndices() []int

func (*CategoricalGenome[Env, State]) GetLocus

func (g *CategoricalGenome[Env, State]) GetLocus(i int) (int, bool, bool)

func (*CategoricalGenome[Env, State]) SetIndices

func (g *CategoricalGenome[Env, State]) SetIndices(indices []int)

func (*CategoricalGenome[Env, State]) Size

func (g *CategoricalGenome[Env, State]) Size() int

type CategoricalMutator

type CategoricalMutator struct {
	Probability float64
}

CategoricalMutator chooses a random gene from the possible genes for a locus.

func (CategoricalMutator) Mutate

func (m CategoricalMutator) Mutate(g Genome) Genome

type CompositeGenome

type CompositeGenome map[string]Genome

CompositeGenome represents a multi-chromosomal genome mapped by name.

func (CompositeGenome) Copy

func (g CompositeGenome) Copy() Genome

func (CompositeGenome) Size

func (g CompositeGenome) Size() int

type Context

type Context[Env any, State any] struct {
	Ctx        context.Context
	Individual *Individual[Env, State]
	Env        Env
}

Context provides access to the individual's state and the environment during expression.

type Crossoverer

type Crossoverer interface {
	Crossover(p1, p2 Genome) (Genome, Genome)
}

Crossoverer defines the interface for combining two parents into offspring.

type CycleCrossover

type CycleCrossover struct{}

CycleCrossover performs Cycle Crossover (CX) on two SequenceGenomes, preserving absolute position mappings.

func (CycleCrossover) Crossover

func (c CycleCrossover) Crossover(p1, p2 Genome) (Genome, Genome)

Crossover implements the Crossoverer interface, delegating composite genomes automatically.

type DefaultCrossoverer

type DefaultCrossoverer struct{}

DefaultCrossoverer performs dynamic fallback crossover based on genome type.

func (DefaultCrossoverer) Crossover

func (c DefaultCrossoverer) Crossover(p1, p2 Genome) (Genome, Genome)

type DefaultMutator

type DefaultMutator struct {
	Probability float64
}

DefaultMutator performs dynamic fallback mutation based on genome type.

func (DefaultMutator) Mutate

func (m DefaultMutator) Mutate(g Genome) Genome

type Definition

type Definition[Env any, State any] struct {
	Loci []*Locus[Env, State]
}

Definition defines the structure of the genome (the set of loci). Note: "Loci" is the plural form of "Locus".

func NewDefinition

func NewDefinition[Env any, State any]() *Definition[Env, State]

NewDefinition creates a new definition with default configuration loci.

func (*Definition[Env, State]) AddLocus

func (d *Definition[Env, State]) AddLocus(id string, lType LocusType) *Locus[Env, State]

AddLocus adds a new locus to the definition.

func (*Definition[Env, State]) AddSequenceGene

func (d *Definition[Env, State]) AddSequenceGene(id string, min, max int)

AddSequenceGene on Definition adds a sequence gene configuration to the last added locus.

type DiversityFeedbackWindowController added in v0.13.0

type DiversityFeedbackWindowController[Env any, State any] struct {
	MinSize         int
	MaxSize         int
	TargetDiversity float64
	Sensitivity     float64
}

DiversityFeedbackWindowController adjusts the window size based on diversity. If diversity is low, it increases the window size to force generalization. If diversity is high, it decreases the window size to speed up convergence.

func NewDiversityFeedbackWindowController added in v0.13.0

func NewDiversityFeedbackWindowController[Env any, State any](min, max int, target float64, sensitivity float64) *DiversityFeedbackWindowController[Env, State]

NewDiversityFeedbackWindowController creates a new DiversityFeedbackWindowController.

func (*DiversityFeedbackWindowController[Env, State]) GetWindowSize added in v0.13.0

func (c *DiversityFeedbackWindowController[Env, State]) GetWindowSize(generation int, diversity float64) int

GetWindowSize calculates the window size using a sigmoid curve.

type DiversitySigmoidPopulationController added in v0.11.0

type DiversitySigmoidPopulationController[Env any, State any] struct {
	TargetDiversity float64 // The desired diversity level (e.g., 0.3)
	Sensitivity     float64 // Controls the steepness of the adjustment curve (e.g., 10.0)
	BaseSize        int     // The baseline population size (around TargetDiversity)
	MinSize         int     // The minimum size this controller will suggest
	MaxSize         int     // The maximum size this controller will suggest
}

DiversitySigmoidPopulationController implements a dynamic population size adjustment based on a sigmoid function of genotypic diversity. If diversity is low, it increases population size to search more space. If diversity is high, it decreases population size to optimize resource usage.

func NewDiversitySigmoidPopulationController added in v0.11.0

func NewDiversitySigmoidPopulationController[Env any, State any](target float64, sensitivity float64, base, min, max int) *DiversitySigmoidPopulationController[Env, State]

NewDiversitySigmoidPopulationController creates a new DiversitySigmoidPopulationController.

func (*DiversitySigmoidPopulationController[Env, State]) GetPopulationSize added in v0.11.0

func (c *DiversitySigmoidPopulationController[Env, State]) GetPopulationSize(e *Engine[Env, State]) int

GetPopulationSize computes target population size based on current genotypic diversity.

type DiversityThresholdPopulationController added in v0.11.0

type DiversityThresholdPopulationController[Env any, State any] struct {
	LowThreshold   float64
	HighThreshold  float64
	IncreaseFactor float64
	DecreaseFactor float64
	BaselineSize   int
}

DiversityThresholdPopulationController adjusts population size based on simple thresholds. If diversity falls below LowThreshold, it increases population size by IncreaseFactor. If diversity goes above HighThreshold, it decreases population size by DecreaseFactor.

func NewDiversityThresholdPopulationController added in v0.11.0

func NewDiversityThresholdPopulationController[Env any, State any](low, high, inc, dec float64, baseline int) *DiversityThresholdPopulationController[Env, State]

NewDiversityThresholdPopulationController creates a new DiversityThresholdPopulationController.

func (*DiversityThresholdPopulationController[Env, State]) GetPopulationSize added in v0.11.0

func (c *DiversityThresholdPopulationController[Env, State]) GetPopulationSize(e *Engine[Env, State]) int

GetPopulationSize adjusts population size step-wise.

type EdgeRecombinationCrossover

type EdgeRecombinationCrossover struct{}

EdgeRecombinationCrossover performs Edge Recombination Crossover (ERX) on two SequenceGenomes, preserving path linkages.

func (EdgeRecombinationCrossover) Crossover

func (c EdgeRecombinationCrossover) Crossover(p1, p2 Genome) (Genome, Genome)

Crossover implements the Crossoverer interface, delegating composite genomes automatically.

type ElitismFunc

type ElitismFunc[Env any, State any] func(pop Population[Env, State], size int) Population[Env, State]

ElitismFunc defines the strategy for carrying over individuals to the next generation.

type Engine

type Engine[Env any, State any] struct {
	Config     EngineConfig[Env, State]
	Population Population[Env, State]
	Generation int

	DiversityHistory    []float64
	SuccessfulMutations int
	TotalMutations      int

	WindowSize int
	// contains filtered or unexported fields
}

Engine orchestrates the genetic algorithm process.

func NewEngine

func NewEngine[Env any, State any](config EngineConfig[Env, State]) (*Engine[Env, State], error)

NewEngine creates a new evolution engine and performs validation.

func (*Engine[Env, State]) EvaluateIndividual added in v0.12.0

func (e *Engine[Env, State]) EvaluateIndividual(ind *Individual[Env, State])

EvaluateIndividual evaluates the fitness of a single individual, using the cache if enabled.

func (*Engine[Env, State]) ParetoFrontier

func (e *Engine[Env, State]) ParetoFrontier() Population[Env, State]

ParetoFrontier returns all non-dominated individuals from the current population (Rank == 0).

func (*Engine[Env, State]) Run

func (e *Engine[Env, State]) Run(def *Definition[Env, State]) (*Individual[Env, State], error)

Run executes the genetic algorithm. It uses the provided definition to initialize the population if not already set.

func (*Engine[Env, State]) Step

func (e *Engine[Env, State]) Step(def *Definition[Env, State]) error

Step executes a single evolutionary generation. It initializes the population if it's not already set.

type EngineConfig

type EngineConfig[Env any, State any] struct {
	PopulationSize      int
	MaxGenerations      int
	FitnessFunc         FitnessFunc[Env, State]
	Selector            Selector
	Crossoverers        []WeightedCrossoverer
	Mutators            []WeightedMutator
	Elitism             int
	ElitismFunc         ElitismFunc[Env, State]
	PopulationFunc      PopulationFunc[Env, State]
	Env                 Env
	ObjectiveDirections []ObjectiveDirection
	Strategy            GenerationStrategy[Env, State]

	// Adaptive Mutation configuration
	AdaptiveMutation   bool
	MaxMutationScaler  float64
	OnMutationAdapted  func(generation int, diversity float64, currentScaler float64)
	MutationController AdaptiveMutationController[Env, State]

	// Age-Biased Mutation configuration
	AgeBiasedMutation    bool
	AgeMutationThreshold int
	AgeMutationScaler    float64

	// Adaptive Population Size configuration
	AdaptivePopulation   bool
	MinPopulationSize    int
	MaxPopulationSize    int
	PopulationController AdaptivePopulationController[Env, State]

	// Concurrency settings
	ConcurrencyLimit            int
	DisableParallelFitness      bool
	DisableParallelReproduction bool

	//Logging and debugging
	Verbose bool
	Silent  bool

	// Cache settings
	EnableFitnessCache bool

	// Adaptive Window settings
	AdaptiveWindow   bool
	MinWindowSize    int
	MaxWindowSize    int
	WindowController AdaptiveWindowController[Env, State]
}

EngineConfig holds the configuration for the evolution engine.

type ExponentialRankSelector

type ExponentialRankSelector[Env any, State any] struct {
	C float64 // Base parameter 'c' in (0.0, 1.0) (defaults to 0.95)
}

ExponentialRankSelector selects individuals based on an exponentially decaying rank.

func (ExponentialRankSelector[Env, State]) Select

func (s ExponentialRankSelector[Env, State]) Select(pop interface{}) interface{}

Select implements the Selector interface.

func (ExponentialRankSelector[Env, State]) SelectTyped

func (s ExponentialRankSelector[Env, State]) SelectTyped(pop Population[Env, State]) *Individual[Env, State]

SelectTyped performs type-safe selection based on exponential rank.

type FitnessCache added in v0.12.0

type FitnessCache struct {
	// contains filtered or unexported fields
}

FitnessCache provides thread-safe caching of fitness scores based on genome serialization.

func NewFitnessCache added in v0.12.0

func NewFitnessCache() *FitnessCache

NewFitnessCache creates a new FitnessCache instance.

func (*FitnessCache) GetOrCreateEntry added in v0.12.0

func (c *FitnessCache) GetOrCreateEntry(key string) (*sync.Mutex, *bool, *[]float64)

GetOrCreateEntry retrieves or creates a cache entry for the given genome key. It returns the entry's mutex, its completion status pointer, and the pointer to its fitness slice.

type FitnessFunc

type FitnessFunc[Env any, State any] func(g Genome, env Env) []float64

FitnessFunc defines how to evaluate an individual's fitness across one or more objectives, with access to the environment.

type FloatGenome

type FloatGenome []float64

func (FloatGenome) Copy

func (g FloatGenome) Copy() Genome

func (FloatGenome) Size

func (g FloatGenome) Size() int

type GPConfig added in v0.10.0

type GPConfig struct {
	Functions []GPFunctionInfo
	Variables []string
	Constants []float64
	MinDepth  int
	MaxDepth  int
}

GPConfig groups all settings, terminals, functions, and limits for tree GP.

type GPCrossover added in v0.10.0

type GPCrossover struct {
	MaxDepth int // Hard limit to combat tree bloat (defaults to 10 if <= 0)
}

GPCrossover performs standard subtree crossover on GPGenomes with max depth protection.

func (GPCrossover) Crossover added in v0.10.0

func (c GPCrossover) Crossover(p1, p2 Genome) (Genome, Genome)

Crossover exchanges subtrees between two GPGenomes.

type GPFunction added in v0.10.0

type GPFunction func(args []float64) float64

GPFunction represents the evaluation signature of a tree function node.

type GPFunctionInfo added in v0.10.0

type GPFunctionInfo struct {
	Name  string
	Arity int
	Eval  GPFunction
}

GPFunctionInfo contains metadata and evaluation callback for a tree function.

func GetAdvancedFunctions added in v0.10.0

func GetAdvancedFunctions() []GPFunctionInfo

GetAdvancedFunctions returns sin, cos, protected exp, and protected log operators.

func GetBasicArithmeticFunctions added in v0.10.0

func GetBasicArithmeticFunctions() []GPFunctionInfo

GetBasicArithmeticFunctions returns standard +, -, *, and protected / operators.

type GPGenome added in v0.10.0

type GPGenome struct {
	Root   *GPNode
	Config *GPConfig
}

GPGenome wraps a GP syntax tree and implements the Genome interface.

func NewRampedHalfAndHalfPopulation added in v0.10.0

func NewRampedHalfAndHalfPopulation(config *GPConfig, size int) []*GPGenome

NewRampedHalfAndHalfPopulation generates a diverse population of GPGenomes using ramped half-and-half.

func (*GPGenome) Copy added in v0.10.0

func (g *GPGenome) Copy() Genome

Copy returns a deep copy of the GPGenome.

func (*GPGenome) Evaluate added in v0.10.0

func (g *GPGenome) Evaluate(vars map[string]float64) float64

Evaluate recursively evaluates the syntax tree value using the provided variable mapping.

func (*GPGenome) Size added in v0.10.0

func (g *GPGenome) Size() int

Size returns the total number of nodes in the syntax tree.

func (*GPGenome) String added in v0.10.0

func (g *GPGenome) String() string

String returns a human-readable mathematical representation of the entire tree.

type GPMutator added in v0.10.0

type GPMutator struct {
	Config      *GPConfig
	SubtreeProb float64 // Probability of subtree mutation vs point mutation
	MaxDepth    int     // Hard limit to combat tree bloat (defaults to 10 if <= 0)
	Probability float64 // Probability of mutation occurring on the genome
}

GPMutator performs point or subtree mutation on GPGenomes.

func (GPMutator) Mutate added in v0.10.0

func (m GPMutator) Mutate(g Genome) Genome

Mutate modifies a GPGenome tree structure.

type GPNode added in v0.10.0

type GPNode struct {
	Op       string
	Children []*GPNode
}

GPNode represents a single function, variable, or constant node in a GP syntax tree.

func (*GPNode) Copy added in v0.10.0

func (n *GPNode) Copy() *GPNode

Copy returns a deep copy of the GPNode syntax tree.

func (*GPNode) Depth added in v0.10.0

func (n *GPNode) Depth() int

Depth returns the maximum depth of the syntax tree under this node (1-indexed).

func (*GPNode) Evaluate added in v0.10.0

func (n *GPNode) Evaluate(vars map[string]float64, config *GPConfig) float64

Evaluate recursively computes the subtree value.

func (*GPNode) Size added in v0.10.0

func (n *GPNode) Size() int

Size returns the number of nodes under this node recursively.

func (*GPNode) String added in v0.10.0

func (n *GPNode) String() string

String returns a human-readable mathematical representation of the node tree.

type GaussianMutator

type GaussianMutator struct {
	Probability float64 // mutation probability per gene
	StdDev      float64 // standard deviation of the Gaussian noise
}

GaussianMutator adds Gaussian distributed noise to FloatGenomes.

func (GaussianMutator) Mutate

func (m GaussianMutator) Mutate(g Genome) Genome

type Gene

type Gene[Env any, State any] struct {
	ID       string
	Callback func(ctx Context[Env, State])
	Value    interface{}
}

Gene represents an allele at a specific locus.

type GenerationEndHook

type GenerationEndHook[Env any, State any] interface {
	OnGenerationEnd(generation int, pop Population[Env, State])
}

GenerationEndHook allows environments to execute custom logic (such as resource regeneration) at the end of each generation.

type GenerationStartHook

type GenerationStartHook[Env any, State any] interface {
	OnGenerationStart(generation int, pop Population[Env, State])
}

GenerationStartHook allows environments to execute custom logic at the start of each generation.

type GenerationStrategy

type GenerationStrategy[Env any, State any] interface {
	Initialize(e *Engine[Env, State]) error
	NextGeneration(e *Engine[Env, State], def *Definition[Env, State], current Population[Env, State]) (Population[Env, State], error)
}

GenerationStrategy defines a modular execution interface for evolutionary generation loops.

type GenericTournamentSelector

type GenericTournamentSelector[Env any, State any] struct {
	Size int

	// Probabilistic Selection
	Probability float64 // If > 0 and < 1.0, active. Best competitor has chance P, next has P*(1-P), etc.

	// Adaptive Selection
	MinSize            int
	MaxSize            int
	GenerationProgress func() float64 // Function returning fraction [0.0, 1.0] representing run progress.

	// Niching / Local Fitness Sharing
	SigmaShare   float64                     // Niching niche radius (active if > 0)
	NichingAlpha float64                     // Sharing power factor (defaults to 1.0 if <= 0)
	DistanceFunc func(g1, g2 Genome) float64 // Optional custom distance metric.

	// Unique Tournament
	Unique bool // If true, selects competitors without replacement.

	// Diversity-based Adaptive Sizing
	AdaptiveDiversity bool

	// Age-biased Selection
	AgeBias float64

	// Hall of Fame Competitor Integration
	HallOfFame            *Population[Env, State]
	HallOfFameProbability float64

	// Self-adaptive Selection
	SelfAdaptive bool
}

GenericTournamentSelector is a type-safe selector for a specific environment Env and state State.

func NewAdaptiveTournamentSelector

func NewAdaptiveTournamentSelector[Env any, State any](minSize, maxSize int, progressFunc func() float64) GenericTournamentSelector[Env, State]

NewAdaptiveTournamentSelector creates a selector that dynamically scales tournament size.

func NewNichingTournamentSelector

func NewNichingTournamentSelector[Env any, State any](size int, sigma float64, distFunc func(g1, g2 Genome) float64) GenericTournamentSelector[Env, State]

NewNichingTournamentSelector creates a selector that applies local fitness sharing within tournaments.

func NewProbabilisticTournamentSelector

func NewProbabilisticTournamentSelector[Env any, State any](size int, probability float64) GenericTournamentSelector[Env, State]

NewProbabilisticTournamentSelector creates a tournament selector with selection probability controls.

func NewUniqueTournamentSelector

func NewUniqueTournamentSelector[Env any, State any](size int) GenericTournamentSelector[Env, State]

NewUniqueTournamentSelector creates a selector that draws tournament competitors without replacement.

func (GenericTournamentSelector[Env, State]) DetermineTournamentSize

func (s GenericTournamentSelector[Env, State]) DetermineTournamentSize(pop Population[Env, State]) int

Determine effective size (Adaptive Tournament & Diversity-based Sizing)

func (GenericTournamentSelector[Env, State]) Select

func (s GenericTournamentSelector[Env, State]) Select(pop interface{}) interface{}

func (GenericTournamentSelector[Env, State]) SelectTyped

func (s GenericTournamentSelector[Env, State]) SelectTyped(pop Population[Env, State]) *Individual[Env, State]

func (GenericTournamentSelector[Env, State]) SelfAdaptiveSelectionSizeOverride

func (s GenericTournamentSelector[Env, State]) SelfAdaptiveSelectionSizeOverride(pop Population[Env, State]) (Population[Env, State], int)

type Genome

type Genome interface {
	Size() int
	Copy() Genome
}

Genome represents the genetic material of an individual.

func DecodeGenome

func DecodeGenome[Env any, State any](def *Definition[Env, State], data []byte) (Genome, error)

DecodeGenome decodes gene IDs from a JSON byte slice and maps them to indices in the provided Definition.

func LoadGenome

func LoadGenome[Env any, State any](def *Definition[Env, State], filename string) (Genome, error)

LoadGenome loads gene IDs from a JSON file and maps them to indices in the provided Definition.

type GenomeData

type GenomeData struct {
	Type      string                    `json:"type,omitempty"`
	Genes     []LocusGenePair           `json:"genes,omitempty"`
	Sequences map[string]SequenceGenome `json:"sequences,omitempty"`
	Bits      BitGenome                 `json:"bits,omitempty"`
	Floats    FloatGenome               `json:"floats,omitempty"`
	Sequence  SequenceGenome            `json:"sequence,omitempty"`
}

GenomeData is the serializable format of any Genome.

type Individual

type Individual[Env any, State any] struct {
	Genome           Genome
	Fitness          []float64
	State            State
	Age              int
	Rank             int
	CrowdingDistance float64
	MutationRate     float64   // Individual-specific mutation rate (self-adaptation)
	ParentFitness    []float64 // Fitness slice of the best parent for tracking success
}

Individual represents a candidate solution in the population.

func NewIndividual

func NewIndividual[Env any, State any](genome Genome) *Individual[Env, State]

NewIndividual creates a new individual with the given genome.

func (*Individual[Env, State]) Express

func (ind *Individual[Env, State]) Express(ctx context.Context, env Env)

Express executes the behavioral genes based on the configuration loci, with access to the environment and a cancellable context.

func (*Individual[Env, State]) GetParameter

func (ind *Individual[Env, State]) GetParameter(locusID string) interface{}

GetParameter returns the value of a parameter gene at a specific locus ID.

func (*Individual[Env, State]) GetSequence

func (ind *Individual[Env, State]) GetSequence(locusID string) SequenceGenome

GetSequence returns the SequenceGenome at a specific locus ID.

func (*Individual[Env, State]) Save

func (ind *Individual[Env, State]) Save(filename string) error

Save saves the individual's genome to a JSON file.

func (*Individual[Env, State]) ToJSON

func (ind *Individual[Env, State]) ToJSON() ([]byte, error)

ToJSON encodes the individual's genome to a JSON byte slice.

type LinearDecayWindowController added in v0.13.0

type LinearDecayWindowController[Env any, State any] struct {
	StartSize      int
	EndSize        int
	MaxGenerations int
}

LinearDecayWindowController decays (or grows) the window size linearly based on the generation progress.

func NewLinearDecayWindowController added in v0.13.0

func NewLinearDecayWindowController[Env any, State any](start, end, maxGens int) *LinearDecayWindowController[Env, State]

NewLinearDecayWindowController creates a new LinearDecayWindowController.

func (*LinearDecayWindowController[Env, State]) GetWindowSize added in v0.13.0

func (c *LinearDecayWindowController[Env, State]) GetWindowSize(generation int, diversity float64) int

GetWindowSize calculates the window size using linear interpolation.

type LinearRankSelector

type LinearRankSelector[Env any, State any] struct {
	SelectionPressure float64 // Selection pressure parameter 's' in [1.0, 2.0] (defaults to 1.5)
}

LinearRankSelector selects individuals based on their sorted rank probability.

func (LinearRankSelector[Env, State]) Select

func (s LinearRankSelector[Env, State]) Select(pop interface{}) interface{}

Select implements the Selector interface.

func (LinearRankSelector[Env, State]) SelectTyped

func (s LinearRankSelector[Env, State]) SelectTyped(pop Population[Env, State]) *Individual[Env, State]

SelectTyped performs type-safe selection based on linear rank.

type Locus

type Locus[Env any, State any] struct {
	ID            string
	Type          LocusType
	Immutable     bool
	PossibleGenes []Gene[Env, State]
	SeqMin        int
	SeqMax        int
}

Locus represents a specific position in the genome. Note: "Loci" (pronounced lo-sigh) is the plural form of "Locus".

func (*Locus[Env, State]) AddConfigGene

func (l *Locus[Env, State]) AddConfigGene(id string, value interface{})

AddConfigGene adds a gene for framework configuration.

func (*Locus[Env, State]) AddGene

func (l *Locus[Env, State]) AddGene(id string, callback func(ctx Context[Env, State]))

AddGene adds a possible gene to the locus.

func (*Locus[Env, State]) AddParameterGene

func (l *Locus[Env, State]) AddParameterGene(id string, value interface{})

AddParameterGene adds a gene that holds a value.

func (*Locus[Env, State]) AddSequenceGene

func (l *Locus[Env, State]) AddSequenceGene(id string, min, max int)

AddSequenceGene configures the sequence range.

type LocusGenePair

type LocusGenePair struct {
	LocusID string `json:"locus_id"`
	GeneID  string `json:"gene_id"`
}

LocusGenePair maps a Locus ID to a selected Gene ID.

type LocusType

type LocusType int

LocusType defines the purpose of a locus.

const (
	LocusBehavioral LocusType = iota
	LocusParameter
	LocusConfig
	LocusSequence
)

type MigrationPolicy

type MigrationPolicy int

MigrationPolicy defines which individuals migrate and who they replace.

const (
	PolicyBestReplaceWorst MigrationPolicy = iota
	PolicyRandomReplaceRandom
)

type MigrationTopology

type MigrationTopology int

MigrationTopology defines how migrants are routed between islands.

const (
	TopologyRing MigrationTopology = iota
	TopologyRandom
	TopologyTorus
	TopologyHypercube
	TopologyStar
)

type MultiIslandEngine

type MultiIslandEngine[Env any, State any] struct {
	Config  MultiIslandEngineConfig[Env, State]
	Islands []*Engine[Env, State]
}

MultiIslandEngine orchestrates a parallel island model genetic algorithm.

func NewMultiIslandEngine

func NewMultiIslandEngine[Env any, State any](config MultiIslandEngineConfig[Env, State]) (*MultiIslandEngine[Env, State], error)

NewMultiIslandEngine instantiates a MultiIslandEngine.

func (*MultiIslandEngine[Env, State]) Run

func (m *MultiIslandEngine[Env, State]) Run(def *Definition[Env, State]) (*Individual[Env, State], error)

Run executes the parallel island evolution.

type MultiIslandEngineConfig

type MultiIslandEngineConfig[Env any, State any] struct {
	NumIslands        int
	MigrationInterval int
	MigrationRate     int
	MigrationTopology MigrationTopology
	MigrationPolicy   MigrationPolicy

	EngineConfig EngineConfig[Env, State]
	EnvFactory   func(islandIndex int) Env
}

MultiIslandEngineConfig holds settings for MultiIslandEngine.

type MutationScheduleType

type MutationScheduleType int

MutationScheduleType defines the supported temporal schedules.

const (
	// ScheduleExponentialDecay continuously decays the mutation rate.
	ScheduleExponentialDecay MutationScheduleType = iota
	// ScheduleCosineAnnealing cycles the mutation rate using cosine curves.
	ScheduleCosineAnnealing
)

type Mutator

type Mutator interface {
	Mutate(g Genome) Genome
}

Mutator defines the interface for introducing random changes to a genome.

type NSGA2Generation

type NSGA2Generation[Env any, State any] struct{}

NSGA2Generation implements the multi-objective Non-dominated Sorting Genetic Algorithm II strategy.

func (*NSGA2Generation[Env, State]) Initialize

func (s *NSGA2Generation[Env, State]) Initialize(e *Engine[Env, State]) error

func (*NSGA2Generation[Env, State]) NextGeneration

func (s *NSGA2Generation[Env, State]) NextGeneration(e *Engine[Env, State], def *Definition[Env, State], current Population[Env, State]) (Population[Env, State], error)

type ObjectiveDirection

type ObjectiveDirection int

ObjectiveDirection represents the optimization direction for a single objective.

const (
	Maximize ObjectiveDirection = iota
	Minimize
)

type OrderCrossover

type OrderCrossover struct{}

OrderCrossover performs Order Crossover (OX) on two SequenceGenomes, preserving duplicate-free permutations.

func (OrderCrossover) Crossover

func (c OrderCrossover) Crossover(p1, p2 Genome) (Genome, Genome)

Crossover implements the Crossoverer interface, delegating composite genomes automatically.

type PMXCrossover

type PMXCrossover struct{}

PMXCrossover performs Partially Mapped Crossover (PMX) on two SequenceGenomes, preserving duplicate-free permutations.

func (PMXCrossover) Crossover

func (c PMXCrossover) Crossover(p1, p2 Genome) (Genome, Genome)

type PointerAdaptiveMutator added in v0.12.0

type PointerAdaptiveMutator struct {
	BaseMutator        Mutator
	ProbabilityPointer *float64
}

PointerAdaptiveMutator wraps an existing Mutator and dynamically updates its probability based on a shared float64 pointer before mutating.

func NewPointerAdaptiveMutator added in v0.12.0

func NewPointerAdaptiveMutator(base Mutator, ptr *float64) PointerAdaptiveMutator

NewPointerAdaptiveMutator creates a new PointerAdaptiveMutator wrapping the base mutator.

func (PointerAdaptiveMutator) Mutate added in v0.12.0

func (m PointerAdaptiveMutator) Mutate(g Genome) Genome

Mutate dynamically adjusts the probability of the wrapped mutator and performs the mutation.

type Population

type Population[Env any, State any] []*Individual[Env, State]

Population is a collection of individuals.

func BestIndividualElitism

func BestIndividualElitism[Env any, State any](pop Population[Env, State], size int) Population[Env, State]

BestIndividualElitism carries over the best individual.

func DefaultPopulationFunc

func DefaultPopulationFunc[Env any, State any](def *Definition[Env, State], size int) Population[Env, State]

DefaultPopulationFunc creates a random population based on the definition.

func TopNElitism

func TopNElitism[Env any, State any](pop Population[Env, State], size int) Population[Env, State]

TopNElitism sorts the population and carries over the top N individuals.

func (Population[Env, State]) AverageFitness

func (p Population[Env, State]) AverageFitness() []float64

AverageFitness returns the average fitness for each objective.

func (Population[Env, State]) Best

func (p Population[Env, State]) Best() *Individual[Env, State]

Best returns the individual with the highest fitness.

type PopulationFunc

type PopulationFunc[Env any, State any] func(def *Definition[Env, State], size int) Population[Env, State]

PopulationFunc is a function that creates an initial population.

type PopulationScheduleType added in v0.11.0

type PopulationScheduleType int

PopulationScheduleType defines scheduling methods for population sizing.

const (
	PopulationScheduleLinear PopulationScheduleType = iota
	PopulationScheduleExponential
	PopulationScheduleCosine
)

type RankSelector

type RankSelector[Env any, State any] struct {
	SelectionPressure float64 // typically in [1.0, 2.0], defaults to 1.5 if <= 0
}

RankSelector selects individuals based on their fitness rank rather than absolute fitness.

func (RankSelector[Env, State]) Select

func (s RankSelector[Env, State]) Select(pop interface{}) interface{}

func (RankSelector[Env, State]) SelectTyped

func (s RankSelector[Env, State]) SelectTyped(pop Population[Env, State]) *Individual[Env, State]

type RechenbergController

type RechenbergController[Env any, State any] struct {
	Interval           int     // Number of generations between adjustments (e.g., 5)
	TargetSuccessRatio float64 // Targeted ratio of successful mutations (default 0.2)
	IncreaseFactor     float64 // Multiplier to increase mutation (default 1.22)
	DecreaseFactor     float64 // Multiplier to decrease mutation (default 0.82)
	MinScaler          float64 // Minimum allowed scaling factor (default 0.1)
	MaxScaler          float64 // Maximum allowed scaling factor (default 5.0)
	// contains filtered or unexported fields
}

RechenbergController adjusts mutation scale based on the ratio of successful mutations.

func NewRechenbergController

func NewRechenbergController[Env any, State any](interval int, targetSuccessRatio float64) *RechenbergController[Env, State]

NewRechenbergController creates a new RechenbergController.

func (*RechenbergController[Env, State]) GetMutationScaler

func (c *RechenbergController[Env, State]) GetMutationScaler(e *Engine[Env, State]) float64

GetMutationScaler checks the success ratio over the interval and scales.

type RouletteWheelSelector

type RouletteWheelSelector[Env any, State any] struct {
	AutoShift bool
}

RouletteWheelSelector selects individuals proportionally to their fitness.

func (RouletteWheelSelector[Env, State]) Select

func (s RouletteWheelSelector[Env, State]) Select(pop interface{}) interface{}

Select implements the Selector interface.

func (RouletteWheelSelector[Env, State]) SelectTyped

func (s RouletteWheelSelector[Env, State]) SelectTyped(pop Population[Env, State]) *Individual[Env, State]

SelectTyped performs type-safe selection using a roulette wheel model.

type Selector

type Selector interface {
	// We use any here because Selector might work with different Individual types.
	// However, usually we want it to be specific.
	// Since Selector is an interface, and Go doesn't support generic methods in interfaces,
	// we have a few options. One is to make Selector generic too.
	Select(pop interface{}) interface{}
}

Selector defines the interface for selecting individuals from a population.

type SelfAdaptiveController

type SelfAdaptiveController[Env any, State any] struct {
	LearningRate float64 // Learning rate tau parameter (default 0.15)
	MinRate      float64 // Minimum allowed mutation probability (default 0.005)
	MaxRate      float64 // Maximum allowed mutation probability (default 0.3)
}

SelfAdaptiveController implements individual-level mutation rate adaptation.

func NewSelfAdaptiveController

func NewSelfAdaptiveController[Env any, State any](learningRate, minRate, maxRate float64) *SelfAdaptiveController[Env, State]

NewSelfAdaptiveController creates a new SelfAdaptiveController.

func (*SelfAdaptiveController[Env, State]) GetMutationScaler

func (c *SelfAdaptiveController[Env, State]) GetMutationScaler(e *Engine[Env, State]) float64

GetMutationScaler returns the baseline scale. Self-adaptation is processed per individual.

type SequenceGenome

type SequenceGenome []int

SequenceGenome represents a permutation genome.

func (SequenceGenome) Copy

func (g SequenceGenome) Copy() Genome

func (SequenceGenome) Size

func (g SequenceGenome) Size() int

type SequencingContext

type SequencingContext[Env any, State any] struct {
	BehavioralLoci      []*Locus[Env, State]
	SelectedGeneIDs     []string
	SelectedGeneIndices []int
}

SequencingContext provides information to the sequencer.

type SigmoidDiversityFeedbackController

type SigmoidDiversityFeedbackController[Env any, State any] struct {
	TargetDiversity float64 // The desired diversity level (e.g., 0.3)
	Sensitivity     float64 // Controls the steepness of the curve (e.g., 10.0)
	MinScaler       float64 // Minimum allowed scaling factor (e.g., 0.1)
	MaxScaler       float64 // Maximum allowed scaling factor (e.g., 5.0)
}

SigmoidDiversityFeedbackController implements a smooth logistic (sigmoid) feedback loop centered on a target diversity.

func NewSigmoidDiversityFeedbackController

func NewSigmoidDiversityFeedbackController[Env any, State any](target, sensitivity, minS, maxS float64) *SigmoidDiversityFeedbackController[Env, State]

NewSigmoidDiversityFeedbackController creates a new SigmoidDiversityFeedbackController.

func (*SigmoidDiversityFeedbackController[Env, State]) GetMutationScaler

func (c *SigmoidDiversityFeedbackController[Env, State]) GetMutationScaler(e *Engine[Env, State]) float64

GetMutationScaler computes the scaling factor using a sigmoid curve.

type SinglePointCrossover

type SinglePointCrossover struct{}

SinglePointCrossover performs crossover at a single random point.

func (SinglePointCrossover) Crossover

func (c SinglePointCrossover) Crossover(p1, p2 Genome) (Genome, Genome)

type StagnationPopulationController added in v0.11.0

type StagnationPopulationController[Env any, State any] struct {
	StagnationLimit int
	IncreaseFactor  float64
	DecreaseFactor  float64
	BaselineSize    int
	// contains filtered or unexported fields
}

StagnationPopulationController adjusts population size based on fitness stagnation. If the best fitness has not improved for StagnationLimit generations, it increases the size. Once it starts improving, it decays or resets the size.

func NewStagnationPopulationController added in v0.11.0

func NewStagnationPopulationController[Env any, State any](limit int, inc, dec float64, baseline int) *StagnationPopulationController[Env, State]

NewStagnationPopulationController creates a new StagnationPopulationController.

func (*StagnationPopulationController[Env, State]) GetPopulationSize added in v0.11.0

func (c *StagnationPopulationController[Env, State]) GetPopulationSize(e *Engine[Env, State]) int

GetPopulationSize evaluates stagnation and scales size if needed.

type StandardGeneration

type StandardGeneration[Env any, State any] struct{}

StandardGeneration implements single-objective reproduction, crossover, mutation, and elitism replacement.

func (*StandardGeneration[Env, State]) Initialize

func (s *StandardGeneration[Env, State]) Initialize(e *Engine[Env, State]) error

func (*StandardGeneration[Env, State]) NextGeneration

func (s *StandardGeneration[Env, State]) NextGeneration(e *Engine[Env, State], def *Definition[Env, State], current Population[Env, State]) (Population[Env, State], error)

type StochasticUniversalSamplingSelector

type StochasticUniversalSamplingSelector[Env any, State any] struct {
	AutoShift bool
	// contains filtered or unexported fields
}

StochasticUniversalSamplingSelector selects individuals using SUS (Stochastic Universal Sampling). Since the Selector interface selects one-by-one, this selector caches selections globally and refills the cache by performing a full SUS spin whenever the cache is fully consumed.

func (*StochasticUniversalSamplingSelector[Env, State]) Select

func (s *StochasticUniversalSamplingSelector[Env, State]) Select(pop interface{}) interface{}

Select implements the Selector interface.

func (*StochasticUniversalSamplingSelector[Env, State]) SelectTyped

func (s *StochasticUniversalSamplingSelector[Env, State]) SelectTyped(pop Population[Env, State]) *Individual[Env, State]

SelectTyped performs type-safe selection using Stochastic Universal Sampling.

type SwapCategoricalMutator added in v0.12.0

type SwapCategoricalMutator struct {
	Probability float64
}

SwapCategoricalMutator swaps the values of two compatible loci in a CategoricalGenome.

func (SwapCategoricalMutator) Mutate added in v0.12.0

func (m SwapCategoricalMutator) Mutate(g Genome) Genome

type SwapMutator

type SwapMutator struct {
	Probability float64
}

SwapMutator swaps two random elements in a SequenceGenome with a given probability.

func (SwapMutator) Mutate

func (m SwapMutator) Mutate(g Genome) Genome

type TemporalScheduleController

type TemporalScheduleController[Env any, State any] struct {
	Type        MutationScheduleType
	InitialRate float64 // Initial scaling factor (typically 1.0 or higher)
	FinalRate   float64 // Minimum baseline scaling factor (e.g., 0.1)
	CycleLength int     // Generation period for Cosine Annealing (e.g., 20 generations)
}

TemporalScheduleController scales the mutation rate based on generation count.

func (*TemporalScheduleController[Env, State]) GetMutationScaler

func (c *TemporalScheduleController[Env, State]) GetMutationScaler(e *Engine[Env, State]) float64

GetMutationScaler calculates the scheduling-based scaling factor.

type TemporalSchedulePopulationController added in v0.11.0

type TemporalSchedulePopulationController[Env any, State any] struct {
	Type        PopulationScheduleType
	InitialSize int
	TargetSize  int
	CycleLength int
}

TemporalSchedulePopulationController scales population size based on progress towards MaxGenerations.

func NewTemporalSchedulePopulationController added in v0.11.0

func NewTemporalSchedulePopulationController[Env any, State any](sType PopulationScheduleType, initSize, targetSize, cycle int) *TemporalSchedulePopulationController[Env, State]

NewTemporalSchedulePopulationController creates a new TemporalSchedulePopulationController.

func (*TemporalSchedulePopulationController[Env, State]) GetPopulationSize added in v0.11.0

func (c *TemporalSchedulePopulationController[Env, State]) GetPopulationSize(e *Engine[Env, State]) int

GetPopulationSize returns the scheduled population size for the current generation.

type TournamentSelector

type TournamentSelector struct {
	Size int
}

TournamentSelector selects the best individual from a random subset.

func (TournamentSelector) Select

func (s TournamentSelector) Select(pop interface{}) interface{}

type TwoPointCrossover

type TwoPointCrossover struct{}

TwoPointCrossover performs crossover at two random points.

func (TwoPointCrossover) Crossover

func (c TwoPointCrossover) Crossover(p1, p2 Genome) (Genome, Genome)

type UniformCrossover

type UniformCrossover struct {
	Probability float64 // typically 0.5
}

UniformCrossover swaps genes at each locus with a given probability.

func (UniformCrossover) Crossover

func (c UniformCrossover) Crossover(p1, p2 Genome) (Genome, Genome)

type WeightedCrossoverer

type WeightedCrossoverer struct {
	Crossoverer Crossoverer
	Weight      float64
}

WeightedCrossoverer pairs a crossoverer operator with its selection probability weight.

type WeightedMutator

type WeightedMutator struct {
	Mutator Mutator
	Weight  float64
}

WeightedMutator pairs a mutator operator with its selection probability weight.

type WindowAwareEnvironment added in v0.13.0

type WindowAwareEnvironment interface {
	SetWindowSize(size int)
}

WindowAwareEnvironment allows Env implementations to dynamically receive the active evaluation window size.

Directories

Path Synopsis
examples
advanced command
comprehensive command
gp_regression command
islands command
multiobjective command
onemax command
structured command

Jump to

Keyboard shortcuts

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