Quick Start Guide

Get up and running with NEAT-JavaScript in a few minutes, install, configure, and evolve your first population.

Installation

Node.js

To install via npm, run the following command:

bash
npm install neat-javascript

Browser

To use NEAT-JavaScript in the browser, add the following script tag to your HTML file:

html
<script src="https://neat-javascript.org/releases/NEAT-JavaScript-1.1.0.js"></script>

Browser namespace

In browser environments, all components are available under the NEATJavaScript namespace by default. You can make everything available globally with:

javascript
// Make all NEAT-JavaScript components available in the global namespace
Object.assign(window, NEATJavaScript);

This lets you use all components without the NEATJavaScript. prefix.

Configuration

Begin by creating a configuration instance and customizing any parameters as needed. The configuration system uses a flexible object-based approach. For details, see the Configuration section.

javascript
// Create a new instance of Config
const config = new Config({
// Basic network structure
inputSize: 2, // Number of input nodes
outputSize: 1, // Number of output nodes
// Activation function (string-based selection)
activationFunction: 'Sigmoid', // 'Sigmoid', 'NEATSigmoid', 'Tanh', 'ReLU', 'LeakyReLU', 'Gaussian'
// Bias settings
bias: 1.0, // Bias value
connectBias: true, // Connect the bias node to all output nodes
biasMode: 'WEIGHTED_NODE', // Bias implementation mode
// Fitness function
fitnessFunction: 'XOR', // Default XOR fitness function
// Weight initialization
weightInitialization: {
type: 'Random',
params: [-1, 1] // Min and max values for random weights
},
// Speciation parameters
c1: 1.0, // Coefficient for excess genes
c2: 1.0, // Coefficient for disjoint genes
c3: 0.4, // Coefficient for weight differences
compatibilityThreshold: 3.0, // Species compatibility threshold
interspeciesMatingRate: 0.001, // Rate of interspecies mating
// Mutation parameters
mutationRate: 1.0, // Overall mutation rate
weightMutationRate: 0.8, // Mutation rate for weights
addConnectionMutationRate: 0.05, // Rate for adding new connections
addNodeMutationRate: 0.03, // Rate for adding new nodes
minWeight: -4.0, // Minimum allowed weight
maxWeight: 4.0, // Maximum allowed weight
reinitializeWeightRate: 0.1, // Rate to completely reinitialize weights
minPerturb: -0.5, // Minimum perturbation value
maxPerturb: 0.5, // Maximum perturbation value
// Evolution parameters
populationSize: 150, // Size of the population
generations: 100, // Number of generations
targetFitness: 0.95, // Target fitness to achieve
survivalRate: 0.2, // Proportion that survives each generation
numOfElite: 10, // Number of elite individuals to retain
dropOffAge: 15, // Maximum age before dropping off
populationStagnationLimit: 20, // Generations with no improvement before reset
keepDisabledOnCrossOverRate: 0.75, // Keep disabled connections during crossover
mutateOnlyProb: 0.25, // Probability for mutation-only
// Recurrent network options
allowRecurrentConnections: true, // Allow recurrent connections
recurrentConnectionRate: 1.0 // Rate for recurrent connections
});

Note

When you leave out any specific parameter, its default value is used automatically — you only need to specify the parameters you want to customize.

Creating a Population

The first step in using NEAT-JavaScript is to create a population of genomes. The Population class manages all aspects of the evolutionary process, including:

  • Maintaining a collection of genomes
  • Organizing genomes into species
  • Handling selection, reproduction, and mutation

Create a population instance by passing your configuration:

javascript
// Create a new population with your configuration
let population = new Population(config);

Note

The initial population consists of minimal networks with random weights. These simple networks evolve into more complex structures through the NEAT process.

Accessing and Propagating Genomes

After creating a population, you can access individual genomes through the population.genomes array:

javascript
// Access the first genome in the population
const genome = population.genomes[0];
// Access all genomes
population.genomes.forEach(genome => {
// Do something with each genome
});

To activate a neural network, propagate inputs through a genome to get its outputs. This is essential for both fitness evaluation and for using the network to produce results:

javascript
// Create an array of inputs matching your inputSize
let inputs = [0, 1];
// Get outputs by propagating inputs through the network
let outputs = genome.propagate(inputs);

The propagate method passes the input values through the network and returns an array of output values. The input array length should match the inputSize in your configuration, and the output array length will match the outputSize.

Running the Evolution

To evolve your population, evaluate the fitness of each genome and then evolve to the next generation. There are two main approaches for fitness evaluation.

Option 1: Manual Fitness Assignment (Recommended)

The most direct approach is to manually assign fitness values to each genome and then call the evolve method:

javascript
population.genomes.forEach(genome => {
// Manually evaluate each genome
genome.fitness = /* your fitness calculation logic */;
});
// Evolve to the next generation
population.evolve()

For example:

javascript
// Create a new population
let population = new Population(config);
// For each generation
for (let i = 0; i < config.generations; i++) {
// Manually evaluate each genome
population.genomes.forEach(genome => {
// Your own evaluation logic here
// Use genome.propagate() to test inputs and calculate fitness
genome.fitness = /* your fitness calculation */;
});
// Track progress
const bestGenome = population.getBestGenome();
console.log(`Generation ${i}: Best fitness = ${bestGenome.fitness}`);
// Evolve to the next generation
population.evolve();
}

Option 2: Using a Fitness Function

Alternatively, you can create a reusable fitness function class:

javascript
class XOR {
calculateFitness(genome) {
const inputs = [
[0, 0],
[0, 1],
[1, 0],
[1, 1]
];
const expectedOutputs = [0, 1, 1, 0];
let error = 0;
for (let i = 0; i < inputs.length; i++) {
const input = inputs[i];
const output = genome.propagate(input);
error += Math.pow(output[0] - expectedOutputs[i], 2);
}
return 1.0 / (1.0 + error);
}
}

After creating your fitness function, assign it to the configuration instance:

javascript
config.fitnessFunction = new XOR();

To run the algorithm with your fitness function, use:

javascript
let algorithm = new Algorithm(config);
algorithm.run(); // Starts the evolution process

This runs the algorithm until the target fitness is reached, displaying the generation number and best fitness in the console.