neat

package
v1.1.4 Latest Latest
Warning

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

Go to latest
Published: Apr 7, 2025 License: MIT Imports: 10 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ActivationFunctions = map[string]ActivationType{
	"sigmoid":  Sigmoid,
	"tanh":     Tanh,
	"relu":     ReLU,
	"identity": Identity,
	"clamped":  Clamped,
	"gaussian": Gaussian,
	"absolute": Absolute,
	"sine":     Sine,
	"cosine":   Cosine,

	"inv":    Inv,
	"log":    Log,
	"exp":    Exp,
	"abs":    Absolute,
	"hat":    Hat,
	"square": Square,
	"cube":   Cube,
}

ActivationFunctions maps function names to the actual activation functions. This allows configuration to specify activations by name.

View Source
var AggregationFunctions = map[string]AggregationType{
	"sum":     AggregateSum,
	"product": AggregateProduct,
	"min":     AggregateMin,
	"max":     AggregateMax,
	"mean":    AggregateMean,
	"median":  AggregateMedian,

	"average": AggregateMean,
}

AggregationFunctions maps function names to the actual aggregation functions.

View Source
var StatFunctions = map[string]func([]float64) float64{
	"mean":   Mean,
	"stdev":  Stdev,
	"sum":    Sum,
	"max":    MaxFloat,
	"min":    MinFloat,
	"median": Median,
}

StatFunctions maps function names to the actual statistical functions. Used by Stagnation config.

Functions

func Absolute

func Absolute(x float64, params ...float64) float64

Absolute value activation function.

func AggregateMax

func AggregateMax(inputs []float64) float64

AggregateMax finds the maximum value among the inputs.

func AggregateMaxAbs

func AggregateMaxAbs(inputs []float64) float64

Example: MaxAbs (if needed)

func AggregateMean

func AggregateMean(inputs []float64) float64

AggregateMean calculates the average of the inputs.

func AggregateMedian

func AggregateMedian(inputs []float64) float64

AggregateMedian calculates the median of the inputs.

func AggregateMin

func AggregateMin(inputs []float64) float64

AggregateMin finds the minimum value among the inputs.

func AggregateProduct

func AggregateProduct(inputs []float64) float64

AggregateProduct calculates the product of the inputs.

func AggregateSum

func AggregateSum(inputs []float64) float64

AggregateSum calculates the sum of the inputs.

func Clamped

func Clamped(x float64, params ...float64) float64

Clamped activation function (clamps output between -1 and 1).

func Cosine

func Cosine(x float64, params ...float64) float64

Cosine activation function.

func Cube

func Cube(x float64, params ...float64) float64

Cube activation function (x^3).

func Exp

func Exp(x float64, params ...float64) float64

Exp activation function (e^x).

func Gaussian

func Gaussian(x float64, params ...float64) float64

Gaussian activation function.

func Hat

func Hat(x float64, params ...float64) float64

Hat activation function (triangular pulse centered at 0).

func Identity

func Identity(x float64, params ...float64) float64

Identity activation function (linear).

func Inv

func Inv(x float64, params ...float64) float64

Inv (Inverse) activation function.

func Log

func Log(x float64, params ...float64) float64

Log activation function (natural logarithm).

func MaxFloat

func MaxFloat(values []float64) float64

MaxFloat calculates the maximum value in a slice of float64 values. Returns negative infinity if the slice is empty.

func Mean

func Mean(values []float64) float64

Mean calculates the average of a slice of float64 values.

func Median

func Median(values []float64) float64

Median calculates the median of a slice of float64 values. Returns NaN if the slice is empty.

func MinFloat

func MinFloat(values []float64) float64

MinFloat calculates the minimum value in a slice of float64 values. Returns positive infinity if the slice is empty.

func ReLU

func ReLU(x float64, params ...float64) float64

ReLU (Rectified Linear Unit) activation function.

func Sigmoid

func Sigmoid(x float64, params ...float64) float64

Sigmoid activation function.

func Sine

func Sine(x float64, params ...float64) float64

Sine activation function.

func Square

func Square(x float64, params ...float64) float64

Square activation function (x^2).

func Stdev

func Stdev(values []float64) float64

Stdev calculates the standard deviation of a slice of float64 values.

func Sum

func Sum(values []float64) float64

Sum calculates the sum of a slice of float64 values.

func Tanh

func Tanh(x float64, params ...float64) float64

Tanh activation function.

Types

type ActivationType

type ActivationType func(input float64, params ...float64) float64

ActivationType defines the type for activation functions.

func GetActivation

func GetActivation(name string) (ActivationType, error)

GetActivation retrieves an activation function by name.

type AggregationType

type AggregationType func(inputs []float64) float64

AggregationType defines the type for aggregation functions.

func GetAggregation

func GetAggregation(name string) (AggregationType, error)

GetAggregation retrieves an aggregation function by name.

type Config

type Config struct {
	Neat         NeatConfig
	Genome       GenomeConfig
	Reproduction ReproductionConfig
	SpeciesSet   SpeciesSetConfig
	Stagnation   StagnationConfig
}

Config stores the configuration parameters for the NEAT algorithm.

func LoadConfig

func LoadConfig(filePath string) (*Config, error)

LoadConfig loads configuration parameters from an INI file.

type ConnectionGene

type ConnectionGene struct {
	Key     ConnectionKey // Represents the (in_node_id, out_node_id) tuple
	Weight  float64
	Enabled bool
}

ConnectionGene represents a connection between two nodes in the genome. The Key is a tuple (in Python), represented here as ConnectionKey struct.

func NewConnectionGene

func NewConnectionGene(key ConnectionKey, config *GenomeConfig) *ConnectionGene

NewConnectionGene creates a new ConnectionGene with attributes initialized according to the config.

func (*ConnectionGene) Copy

func (cg *ConnectionGene) Copy() *ConnectionGene

Copy creates a deep copy of the ConnectionGene.

func (*ConnectionGene) Crossover

func (cg *ConnectionGene) Crossover(other *ConnectionGene) *ConnectionGene

Crossover creates a new ConnectionGene by randomly inheriting attributes from two parent ConnectionGenes.

func (*ConnectionGene) Distance

func (cg *ConnectionGene) Distance(other *ConnectionGene, config *GenomeConfig) float64

Distance calculates the genetic distance between two ConnectionGenes.

func (*ConnectionGene) Mutate

func (cg *ConnectionGene) Mutate(genome *Genome, config *GenomeConfig)

Mutate adjusts the attributes of the ConnectionGene based on mutation rates in the config. It now accepts the genome to check for cycles when enabling connections in feedforward mode.

func (*ConnectionGene) String

func (cg *ConnectionGene) String() string

String returns a string representation of the ConnectionGene.

type ConnectionKey

type ConnectionKey struct {
	InNodeID  int
	OutNodeID int
}

ConnectionKey uniquely identifies a connection gene (innovation).

type FitnessFunc

type FitnessFunc func(genomes map[int]*Genome) error

FitnessFunc is the type for the function provided by the user to evaluate genome fitness. It takes the current generation of genomes and should update their Fitness field. The genomes map maps genome key to the Genome object.

type GeneType

type GeneType int

GeneType defines the type of gene (Node or Connection)

const (
	NodeGeneType GeneType = iota
	ConnectionGeneType
)

type Genome

type Genome struct {
	Key         int                               // Unique identifier for this genome.
	Nodes       map[int]*NodeGene                 // Map node ID -> NodeGene
	Connections map[ConnectionKey]*ConnectionGene // Map connection key -> ConnectionGene
	Fitness     float64                           // Fitness score of the genome.
	// Config holds a reference to the configuration for easy access to parameters.
	// Note: Storing the whole config might be overkill; maybe just GenomeConfig?
	// Let's start with GenomeConfig.
	Config *GenomeConfig
}

Genome represents an individual organism in the population. It consists of NodeGenes and ConnectionGenes.

func NewGenome

func NewGenome(key int, config *GenomeConfig) *Genome

NewGenome creates a new Genome instance with the specified key and config reference.

func (*Genome) ConfigureCrossover

func (g *Genome) ConfigureCrossover(parent1, parent2 *Genome)

ConfigureCrossover creates a new genome by combining genes from two parent genomes.

func (*Genome) ConfigureNew

func (g *Genome) ConfigureNew()

ConfigureNew initializes a new genome based on the configuration. It creates input, output, and potentially hidden nodes, and sets up initial connections.

func (*Genome) Distance

func (g *Genome) Distance(other *Genome) float64

Distance calculates the genetic distance between this genome and another. It considers disjoint/excess genes and differences in matching gene attributes.

func (*Genome) Mutate

func (g *Genome) Mutate()

Mutate applies mutations to the genome, including structural and attribute mutations.

type GenomeConfig

type GenomeConfig struct {
	// --- Top-level Genome parameters ---
	NumInputs                        int     `ini:"num_inputs"`
	NumOutputs                       int     `ini:"num_outputs"`
	NumHidden                        int     `ini:"num_hidden"`
	FeedForward                      bool    `ini:"feed_forward"` // If true, recurrent connections are disallowed
	CompatibilityDisjointCoefficient float64 `ini:"compatibility_disjoint_coefficient"`
	CompatibilityWeightCoefficient   float64 `ini:"compatibility_weight_coefficient"`
	ConnAddProb                      float64 `ini:"conn_add_prob"`
	ConnDeleteProb                   float64 `ini:"conn_delete_prob"`
	NodeAddProb                      float64 `ini:"node_add_prob"`
	NodeDeleteProb                   float64 `ini:"node_delete_prob"`
	SingleStructuralMutation         bool    `ini:"single_structural_mutation"` // Python default: false
	StructuralMutationSurer          string  `ini:"structural_mutation_surer"`  // Python default: 'default'
	InitialConnection                string  `ini:"initial_connection"`         // Python default: 'unconnected'

	// --- Node Gene parameters ---
	BiasInitMean    float64 `ini:"bias_init_mean"`
	BiasInitStdev   float64 `ini:"bias_init_stdev"`
	BiasInitType    string  `ini:"bias_init_type"` // Default: 'gaussian'
	BiasReplaceRate float64 `ini:"bias_replace_rate"`
	BiasMutateRate  float64 `ini:"bias_mutate_rate"`
	BiasMutatePower float64 `ini:"bias_mutate_power"`
	BiasMaxValue    float64 `ini:"bias_max_value"`
	BiasMinValue    float64 `ini:"bias_min_value"`

	ResponseInitMean    float64 `ini:"response_init_mean"`
	ResponseInitStdev   float64 `ini:"response_init_stdev"`
	ResponseInitType    string  `ini:"response_init_type"` // Default: 'gaussian'
	ResponseReplaceRate float64 `ini:"response_replace_rate"`
	ResponseMutateRate  float64 `ini:"response_mutate_rate"`
	ResponseMutatePower float64 `ini:"response_mutate_power"`
	ResponseMaxValue    float64 `ini:"response_max_value"`
	ResponseMinValue    float64 `ini:"response_min_value"`

	ActivationDefault    string   `ini:"activation_default"`           // Default: 'random'
	ActivationOptions    []string `ini:"activation_options" delim:" "` // Space-separated list
	ActivationMutateRate float64  `ini:"activation_mutate_rate"`

	AggregationDefault    string   `ini:"aggregation_default"`           // Default: 'random'
	AggregationOptions    []string `ini:"aggregation_options" delim:" "` // Space-separated list
	AggregationMutateRate float64  `ini:"aggregation_mutate_rate"`

	// --- Connection Gene parameters ---
	WeightInitMean    float64 `ini:"weight_init_mean"`
	WeightInitStdev   float64 `ini:"weight_init_stdev"`
	WeightInitType    string  `ini:"weight_init_type"` // Default: 'gaussian'
	WeightReplaceRate float64 `ini:"weight_replace_rate"`
	WeightMutateRate  float64 `ini:"weight_mutate_rate"`
	WeightMutatePower float64 `ini:"weight_mutate_power"`
	WeightMaxValue    float64 `ini:"weight_max_value"`
	WeightMinValue    float64 `ini:"weight_min_value"`

	EnabledDefault        string  `ini:"enabled_default"` // Default: 'True'
	EnabledMutateRate     float64 `ini:"enabled_mutate_rate"`
	EnabledRateToTrueAdd  float64 `ini:"enabled_rate_to_true_add"`  // Python default: 0.0
	EnabledRateToFalseAdd float64 `ini:"enabled_rate_to_false_add"` // Python default: 0.0

	// --- Calculated/Derived ---
	InputKeys    []int // Derived
	OutputKeys   []int // Derived
	NodeKeyIndex int   // Derived, used for assigning new node keys
}

GenomeConfig holds parameters specific to the structure and mutation of genomes.

func (*GenomeConfig) GetNewNodeKey

func (gc *GenomeConfig) GetNewNodeKey() int

Helper to get next node key - ensures unique positive integers >= NumOutputs

type GenomeDistanceCache

type GenomeDistanceCache struct {
	Distances map[ConnectionKey]float64 // Using ConnectionKey as a proxy for genome pair (g1.Key, g2.Key)
	Hits      int
	Misses    int
	Config    *GenomeConfig // Needed for the Distance function
}

GenomeDistanceCache stores calculated distances between genomes to avoid redundant computations.

func NewGenomeDistanceCache

func NewGenomeDistanceCache(config *GenomeConfig) *GenomeDistanceCache

NewGenomeDistanceCache creates a new distance cache.

func (*GenomeDistanceCache) Distance

func (dc *GenomeDistanceCache) Distance(genome1, genome2 *Genome) float64

Distance calculates or retrieves the distance between two genomes.

type NeatConfig

type NeatConfig struct {
	PopSize              int     `ini:"pop_size"`
	FitnessCriterion     string  `ini:"fitness_criterion"` // e.g., "max", "min", "mean"
	FitnessThreshold     float64 `ini:"fitness_threshold"`
	ResetOnExtinction    bool    `ini:"reset_on_extinction"`
	NoFitnessTermination bool    `ini:"no_fitness_termination"`
}

NeatConfig holds parameters specific to the NEAT algorithm itself.

type NodeGene

type NodeGene struct {
	Key         int // Unique identifier for this node gene (negative for inputs, >=0 for outputs/hidden)
	Bias        float64
	Response    float64
	Activation  string // Name of the activation function
	Aggregation string // Name of the aggregation function
}

NodeGene represents a node (neuron) in the neural network genome.

func NewNodeGene

func NewNodeGene(key int, config *GenomeConfig) *NodeGene

NewNodeGene creates a new NodeGene with attributes initialized according to the config.

func (*NodeGene) Copy

func (ng *NodeGene) Copy() *NodeGene

Copy creates a deep copy of the NodeGene.

func (*NodeGene) Crossover

func (ng *NodeGene) Crossover(other *NodeGene) *NodeGene

Crossover creates a new NodeGene by randomly inheriting attributes from two parent NodeGenes.

func (*NodeGene) Distance

func (ng *NodeGene) Distance(other *NodeGene, config *GenomeConfig) float64

Distance calculates the genetic distance between two NodeGenes based on their attributes.

func (*NodeGene) Mutate

func (ng *NodeGene) Mutate(config *GenomeConfig)

Mutate adjusts the attributes of the NodeGene based on mutation rates in the config.

func (*NodeGene) String

func (ng *NodeGene) String() string

String returns a string representation of the NodeGene.

type Population

type Population struct {
	Config       *Config
	Population   map[int]*Genome // Current generation of genomes (maps genome key -> genome)
	SpeciesSet   *SpeciesSet
	Reproduction *Reproduction
	Stagnation   *Stagnation
	Generation   int
	BestGenome   *Genome // Best genome found so far

}

Population holds the state of the NEAT evolutionary process.

func LoadCheckpoint

func LoadCheckpoint(checkpointPath string, configPath string) (*Population, error)

LoadCheckpoint loads a Population state from a checkpoint file. It requires the original configuration file path to reconstruct the Config object.

func NewPopulation

func NewPopulation(config *Config) (*Population, error)

NewPopulation creates a new Population instance. It initializes the first generation of genomes based on the config.

func (*Population) RunGeneration

func (p *Population) RunGeneration(fitnessFunc FitnessFunc) (*Genome, error)

RunGeneration executes a single generation of the NEAT algorithm. Returns the winning genome if the fitness threshold is met this generation, otherwise nil.

func (*Population) SaveCheckpoint

func (p *Population) SaveCheckpoint(filePath string) error

SaveCheckpoint saves the current state of the Population to a file. Uses gzip compression for smaller file size.

type PopulationSaveData

type PopulationSaveData struct {
	Population   map[int]*Genome
	SpeciesSet   *SpeciesSet
	Reproduction *Reproduction // Includes NextGenomeKey and Ancestors
	Generation   int
	BestGenome   *Genome
}

PopulationSaveData is a helper struct to hold only the parts of Population needed for saving. We don't save the full Config, as it's reloaded from the original file. We also need to explicitly save the random number generator state.

type Reproduction

type Reproduction struct {
	Config *ReproductionConfig
	// GenomeIndexer func() int // Function removed, state stored in NextGenomeKey
	NextGenomeKey int           // State for the next genome key
	Ancestors     map[int][]int // Map genome key -> parent keys (for tracking lineage)
	// Reporters   *reporting.ReporterSet // TODO: Add reporters later
	Stagnation *Stagnation // Reference to stagnation info for filtering
}

Reproduction handles the creation of new genomes, either from scratch or through crossover and mutation.

func NewReproduction

func NewReproduction(config *ReproductionConfig, stagnation *Stagnation) *Reproduction

NewReproduction creates a new reproduction manager.

func (*Reproduction) CreateNewPopulation

func (r *Reproduction) CreateNewPopulation(genomeConfig *GenomeConfig, popSize int) map[int]*Genome

CreateNewPopulation creates an initial population of genomes.

func (*Reproduction) Reproduce

func (r *Reproduction) Reproduce(overallConfig *Config, speciesSet *SpeciesSet, popSize int, generation int) (map[int]*Genome, error)

Reproduce creates the next generation of genomes based on the current species and their fitness.

type ReproductionConfig

type ReproductionConfig struct {
	Elitism           int     `ini:"elitism"`            // Python default: 0
	SurvivalThreshold float64 `ini:"survival_threshold"` // Python default: 0.2
	MinSpeciesSize    int     `ini:"min_species_size"`   // Python default: 1
}

ReproductionConfig holds parameters related to reproduction.

type Species

type Species struct {
	Key             int             // Unique identifier for the species.
	Created         int             // Generation number when the species was created.
	LastImproved    int             // Last generation where fitness improved.
	Representative  *Genome         // The representative genome for this species.
	Members         map[int]*Genome // Genomes belonging to this species (maps genome key -> genome).
	Fitness         float64         // Calculated fitness for the species (e.g., mean fitness of members).
	AdjustedFitness float64         // Fitness adjusted by sharing.
	FitnessHistory  []float64       // History of fitness values for stagnation detection.
}

Species represents a group of genetically similar genomes.

func NewSpecies

func NewSpecies(key, generation int) *Species

NewSpecies creates a new species.

func (*Species) GetFitnesses

func (s *Species) GetFitnesses() []float64

GetFitnesses returns a slice containing the fitness values of all members.

func (*Species) Update

func (s *Species) Update(representative *Genome, members map[int]*Genome)

Update adjusts the species' representative and members.

type SpeciesSet

type SpeciesSet struct {
	Species         map[int]*Species  // Map species key -> Species
	GenomeToSpecies map[int]int       // Map genome key -> species key
	Indexer         int               // Counter for assigning new species keys (start at 1)
	Config          *SpeciesSetConfig // Reference to speciation config

}

SpeciesSet manages the collection of species within a population.

func NewSpeciesSet

func NewSpeciesSet(config *SpeciesSetConfig) *SpeciesSet

NewSpeciesSet creates a new species set manager.

func (*SpeciesSet) GetSpecies

func (ss *SpeciesSet) GetSpecies(genomeID int) (*Species, bool)

GetSpecies returns the Species object for a given genome ID.

func (*SpeciesSet) GetSpeciesID

func (ss *SpeciesSet) GetSpeciesID(genomeID int) (int, bool)

GetSpeciesID returns the species ID for a given genome ID.

func (*SpeciesSet) Speciate

func (ss *SpeciesSet) Speciate(config *Config, population map[int]*Genome, generation int) error

Speciate partitions the population into species based on genetic distance.

type SpeciesSetConfig

type SpeciesSetConfig struct {
	CompatibilityThreshold float64 `ini:"compatibility_threshold"`
}

SpeciesSetConfig holds parameters related to speciation.

type Stagnation

type Stagnation struct {
	Config             *StagnationConfig
	SpeciesFitnessFunc func([]float64) float64
}

Stagnation manages the detection of stagnant species.

func NewStagnation

func NewStagnation(config *StagnationConfig) (*Stagnation, error)

NewStagnation creates a new stagnation manager.

func (*Stagnation) Update

func (s *Stagnation) Update(speciesSet *SpeciesSet, generation int) ([]StagnationInfo, error)

Update checks for stagnant species within the species set. It updates species fitness history and marks species for removal based on stagnation criteria.

type StagnationConfig

type StagnationConfig struct {
	SpeciesFitnessFunc string `ini:"species_fitness_func"` // Python default: 'mean'
	MaxStagnation      int    `ini:"max_stagnation"`       // Python default: 15
	SpeciesElitism     int    `ini:"species_elitism"`      // Python default: 0
}

StagnationConfig holds parameters related to species stagnation.

type StagnationInfo

type StagnationInfo struct {
	SpeciesID  int
	Species    *Species
	IsStagnant bool
}

StagnationInfo holds the results of the stagnation update for a single species.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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