Quick Start Guide

Welcome to the Quick Start Guide for NEAT-JavaScript! This guide will help you get up and running quickly with basic installation and configuration.

Installation

Node.js Installation

To install via npm, run the following command:

npm install neat-javascript

Browser Usage

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

<script src="path/to/neat-javascript.js"></script>

Important Note

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

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

This allows you to use all components without the NEATJavaScript. prefix.

Configuration

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

// 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', // Options: 'Sigmoid', 'NEATSigmoid', 'Tanh', 'ReLU', 'LeakyReLU', 'Gaussian' // Fitness function fitnessFunction: 'XOR', // Default XOR fitness function // Weight initialization weightInitialization: { type: 'Random', params: [-1, 1] // Min and max values for random weights }, // Network topology 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 perturbRange: 0.5, // Range for weight perturbation minWeight: -4.0, // Minimum allowed weight maxWeight: 4.0, // Maximum allowed weight // Evolution parameters populationSize: 150, // Size of the population generations: 100, // Number of generations 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, // Chance to keep disabled genes in 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 in the configuration, its default value will be used automatically. This means 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 is responsible for managing all aspects of the evolutionary process including:

Create a population instance by passing your configuration:

// 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 will 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:

// 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, you can propagate inputs through a genome to get its outputs. This is essential for both fitness evaluation and using the network to produce results:

// 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 neural network and returns an array of output values. The length of the input array should match the inputSize in your configuration, and the length of the output array will match the outputSize.

Running the Evolution

To evolve your population, you need to 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:

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

For example:

// 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:

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 like this:

config.fitnessFunction = new XOR();

To run the algorithm with your fitness function, use the following:

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

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