Neat

Documentation for Neat.

Neat.NeatConfig.load_configMethod

load_config() -> Dict{String,Any}

Load the configuration from neat_config.toml. If the file does not exist, write the DEFAULT_CONFIG to that file first, then parse and return it. If the file exists, log that the existing configuration is being used.

source
Neat.CreateGenome.create_genomeMethod
create_genome(num_inputs::Int, num_outputs::Int) → Genome

Creates a Genome with:

  • The specified number of input nodes
  • The specified number of output nodes
  • Fully connected input-to-output connections with random weights

NO HIDDEN NODES ARE CREATED INITIALLY

Arguments

  • num_inputs::Int: Number of input nodes.
  • num_outputs::Int: Number of output nodes.

Returns

  • Genome: A new genome with nodes and fully connected input-output links.
source
Neat.Fitness.evaluate_fitnessMethod
evaluate_fitness(genome::Genome; ds_name::Union{String,Missing}=missing) -> Float64

Compute the fitness of a genome on a specified dataset by running its neural network and summing the squared errors between outputs and targets, then returning the negative total error.

A more positive return value indicates better performance (lower overall error).

Keyword Arguments

  • genome : The Genome whose network will be evaluated.
  • ds_name : Optional name of the dataset to use (e.g., "XOR_DATA" or "PARITY3_DATA"). If not defined, the default training_data key from the configuration is used.

Returns

  • Float64 : Negative sum of squared errors over all input–target pairs in the dataset.
source
Neat.ForwardPass.forward_passMethod
forward_pass(genome::Genome, input::Vector{Float64}) → Dict{Int, Float64}

Performs a forward pass through the network defined by genome, computing activation values for all nodes.

Arguments

  • genome::Genome: The genome containing nodes and connections.
  • input::Vector{Float64}: Activation values for input nodes.

Returns

  • Dict{Int, Float64}: A dictionary mapping each node ID to its activation value.
source
Neat.ForwardPass.topological_sortMethod
topological_sort(genome::Genome) → Vector{Int}

Performs a topological sort of all nodes in the genome. The resulting order ensures each node appears only after all its predecessors have been processed.

Arguments

  • genome::Genome: The genome containing nodes and connections.

Returns

  • Vector{Int}: A list of node IDs in a valid computation order.
  • Vector{Connection}: A list of all enabled connections in the genome.

Errors

  • Throws an error if the graph contains cycles, making topological sorting impossible.
source
Neat.Mutation.add_connection!Method
add_connection!(genome::Genome; max_attempts::Int=50) -> Nothing

Try up to max_attempts times to add a new connection between two previously unconnected nodes without creating a cycle.

Selects random input and output nodes (skipping invalid or existing edges) until a valid pair is found or attempts exhausted.

Keyword Arguments

  • max_attempts : Maximum number of trials before giving up (default: 50).
source
Neat.Mutation.add_node!Method
add_node!(genome::Genome) -> Nothing

Insert a new hidden node by splitting an existing enabled connection.

  • Chooses a random enabled connection A → B and disables it.
  • Creates a new hidden node C with a unique ID.
  • Adds two connections: A → C (weight = 1.0) and C → B (weight equal to the original connection).

This mutation allows the network topology to grow.

Arguments

  • genome : The Genome to modify.
source
Neat.Mutation.causes_cycleMethod
causes_cycle(genome::Genome, src_id::Int, dst_id::Int) -> Bool

Determine whether adding a connection from node src_id to dst_id would introduce a cycle.

Performs a depth-first search starting from dst_id to see if src_id is reachable.

Arguments

  • genome : The Genome whose topology is checked.
  • src_id : Identifier of the potential source node.
  • dst_id : Identifier of the potential destination node.

Returns

  • true if a path exists from dst_id back to src_id (a cycle would form), otherwise false.
source
Neat.Mutation.mutateMethod
mutate(genome::Genome; perturb_chance, sigma, add_connection_prob, node_add_prob, max_attempts) -> Nothing

Apply a full suite of mutation operators to genome according to configured probabilities.

  • Weight mutations via mutate_weights!.
  • With probability add_connection_prob, attempt add_connection!.
  • With probability node_add_prob, attempt add_node!.

If any probability or max_attempts is not defined, the value is loaded from the mutation section of the configuration.

Keyword Arguments

  • perturb_chance : Probability for weight perturbation.
  • sigma : Stddev for weight perturbation.
  • add_connection_prob : Chance to add a new connection.
  • node_add_prob : Chance to add a new node.
  • max_attempts : Max trials for adding a connection.
source
Neat.Mutation.mutate_weights!Method
mutate_weights!(genome::Genome; perturb_chance::Float64, sigma::Float64) -> Nothing

Apply weight mutations to all connections of genome by replacing each with a new modified connection.

  • With probability perturb_chance, add a perturbation drawn from Normal(0, sigma).
  • Otherwise, assign a completely new weight sampled from Normal(0, 1).

Arguments

  • genome : The Genome whose connection weights will be mutated.
  • perturb_chance : Probability of choosing a small perturbation over full replacement.
  • sigma : Standard deviation of the Gaussian perturbation.
source
Neat.Population.initialize_populationMethod
initialize_population(num_genomes::Int, num_inputs::Int, num_outputs::Int) → Vector{Genome}

Create a population of n genomes initialized with given number of input/output nodes. Each genome is assigned a unique ID.

Arguments

  • num_genomes: Number of genomes to create.
  • num_inputs: Number of input nodes.
  • num_outputs: Number of output nodes.

Returns

  • A vector of Genome objects.
source
Neat.Crossover.crossoverFunction
crossover(parent1::Genome, parent2::Genome) → Genome

Perform crossover between two parent genomes. The fitter parent contributes all disjoint and excess genes. Matching genes are randomly inherited from either parent. Disabled genes may remain disabled in the child.

Arguments

  • parent1::Genome: One parent genome.
  • parent2::Genome: Another parent genome.

Returns

  • Genome: A new child genome composed from both parents' genes.
source
Neat.Speciation.adjust_fitness!Method
adjust_fitness!(species_list::Vector{Vector{Genome}})

Applies fitness sharing to scale each genome’s fitness relative to its species size.

Modifies each genome's fitness value in-place by applying NEAT-style fitness sharing:

  • Divides each genome's fitness by the number of members in its species.

Arguments

  • species_list : A vector of species (each a vector of genomes).

Side Effects

  • Sets each genome’s adjusted_fitness to fitness / species_size.
source
Neat.Speciation.assign_species!Method
assign_species!(population::Vector{Genome}, species_list::Vector{Vector{Genome}}; speciation_threshold::Union{Float64,Missing}=missing, c1::Union{Float64,Missing}=missing, c2::Union{Float64,Missing}=missing, c3::Union{Float64,Missing}=missing)

Divide a population of genomes into species based on compatibility distance.

For each genome (in random order), compute its distance to the representative of each existing species (the first member). If the smallest distance is ≤ speciation_threshold, add it to that species; otherwise, start a new species with this genome as its representative.

If speciation_threshold, c1, c2, or c3 is missing, the corresponding value is loaded from the training parameters in the configuration.

Arguments

  • population : Vector of genomes to classify.
  • species_list : Vector of species (each a vector of genomes) to populate.
  • speciation_threshold : Maximum compatibility distance to join an existing species.
  • c1, c2, c3 : Coefficients forwarded to compatibility_distance.

Side Effects

  • Clears and reassigns species_list in-place.
source
Neat.Speciation.compatibility_distanceMethod
compatibility_distance(g1::Genome, g2::Genome; c1::Union{Float64,Missing}=missing, c2::Union{Float64,Missing}=missing, c3::Union{Float64,Missing}=missing) -> Float64

Compute the NEAT compatibility distance between two genomes:

δ = (c1 * E / N) + (c2 * D / N) + (c3 * W)

where

  • E is the number of excess genes,
  • D is the number of disjoint genes,
  • W is the average weight difference of matching genes,
  • N is the number of genes in the larger genome (treated as 1 if small for stability).

If any of c1, c2, or c3 is not defined, its value is loaded from the speciation section of the configuration.

Arguments

  • g1, g2 : The two Genome instances to compare.
  • c1 : Coefficient for excess genes.
  • c2 : Coefficient for disjoint genes.
  • c3 : Coefficient for average weight differences.

Returns

  • Float64 : The compatibility distance (lower means more similar).
source
Neat.Speciation.compute_offspring_countsFunction
compute_offspring_counts(species_list::Vector{Vector{Genome}}, population_size::Int=300) -> Vector{Int}

Allocate the total number of offspring among species proportionally to their total adjusted fitness.

Arguments

  • species_list : List of species (each a vector of genomes).
  • population_size : Total number of offspring to distribute.

Returns

  • A vector of integers indicating the offspring count for each species (in the same order).
source
Neat.Speciation.select_elitesMethod
select_elites(species::Vector{T}, elite_frac::Float64) where {T}

Select the top-performing genomes in a species based on adjusted fitness.

Arguments

  • species : Vector of genomes (each with an adjusted_fitness field).
  • elite_frac : Fraction of the species to keep as elites (e.g., 0.1 for 10%).

Returns

  • A vector of the top ceil(elite_frac * length(species)) genomes, sorted by descending adjusted_fitness.
source
Neat.Innovation.get_innovation_numberMethod

Returns a unique innovation number for the connection from in_node to out_node. If this connection has been seen before, returns the previously assigned number. Otherwise, assigns a new innovation number and stores it. Used in NEAT to track structural mutations consistently across genomes. !Ensures that even if two genomes both add a connection from node A → B, they will NOT get different innovation numbers.

Returns

  • Int: The innovation number for the (innode, outnode) pair.
source
Neat.Visualize.plot_fitness_historyMethod
plot_fitness_history(best_fitness_history; filename="fitness_history.png")

Create and save a line plot of the best fitness values over generations.

Arguments

  • best_fitness_history::Vector{Float64}: History of best fitness per generation.
  • filename::String: Output file path (defaults to "fitness_history.png").
source