# NEAT

Edit on Github

The built-in NEAT class allows you create evolutionary algorithms with just a few lines of code. If you want to evolve neural networks to conform a given dataset, check out this page. The following code is from the Agario-AI built with Neataptic.

    /** Construct the genetic algorithm */
    function initNeat(){
      neat = new Neat(
        1 + PLAYER_DETECTION * 3 + FOOD_DETECTION * 2,
        2,
        null,
        {
          mutation: methods.mutation.ALL
          popsize: PLAYER_AMOUNT,
          mutationRate: MUTATION_RATE,
          elitism: Math.round(ELITISM_PERCENT * PLAYER_AMOUNT),
          network: new architect.Random(
            1 + PLAYER_DETECTION * 3 + FOOD_DETECTION * 2,
            START_HIDDEN_SIZE,
            2
          )
        }
      );

      if(USE_TRAINED_POP) neat.population = population;
    }

    /** Start the evaluation of the current generation */
    function startEvaluation(){
      players = [];
      highestScore = 0;

      for(var genome in neat.population){
        genome = neat.population[genome];
        new Player(genome);
      }
    }

    /** End the evaluation of the current generation */
    function endEvaluation(){
      console.log('Generation:', neat.generation, '- average score:', neat.getAverage());

      neat.sort();
      var newPopulation = [];

      // Elitism
      for(var i = 0; i < neat.elitism; i++){
        newPopulation.push(neat.population[i]);
      }

      // Breed the next individuals
      for(var i = 0; i < neat.popsize - neat.elitism; i++){
        newPopulation.push(neat.getOffspring());
      }

      // Replace the old population with the new population
      neat.population = newPopulation;
      neat.mutate();

      neat.generation++;
      startEvaluation();
    }

You might also want to check out the target-seeking project built with Neataptic.

## Options

The constructor comes with various options. The constructor works as follows:

    new Neat(input, output, fitnessFunction, options); // options should be an object

Every generation, each genome will be tested on the `fitnessFunction`. The fitness function should return a score (a number). Through evolution, the genomes will try to maximize the output of the fitness function.

Negative scores are allowed.

You can provide the following options in an object for the `options` argument:

popsize
Sets the population size of each generation. Default is 50.

elitism
Sets the elitism of every evolution loop. Default is 0.

provenance
Sets the provenance of the genetic algorithm. Provenance means that during every evolution, the given amount of genomes will be inserted which all have the original network template (which is `Network(input,output)` when no `network` option is given). Default is 0.

mutation
Sets the allowed mutation methods used in the evolutionary process. Must be an array (e.g. `[methods.mutation.ADD_NODE, methods.mutation.SUB_NODE]`). Default mutation methods are all non-recurrent mutation methods. A random mutation method will be chosen from the array when mutation occrus.

selection
Sets the allowed selection method used in the evolutionary process. Must be a single method (e.g. `Selection.FITNESS_PROPORTIONATE`). Default is `FITNESS_PROPORTIONATE`.

crossover
Sets the allowed crossover methods used in the evolutionary process. Must be an array. disabled as of now

fitnessPopulation
If set to `true`, you will have to specify a fitness function that takes an array of genomes as input and sets their `.score` property.

mutationRate
Sets the mutation rate. If set to `0.3`, 30% of the new population will be mutated. Default is `0.3`.

mutationAmount
If mutation occurs (`randomNumber < mutationRate`), sets the amount of times a mutation method will be applied to the network. Default is `1`.

network
If you want to start the algorithm from a specific network, specify your network here.

equal
If set to true, all networks will be viewed equal during crossover. This stimulates more diverse network architectures. Default is `false`.

clear
Clears the context of the network before activating the fitness function. Should be applied to get consistent outputs from recurrent networks. Default is `false`.

## Properties

There are only a few properties

input
The amount of input neurons each genome has

output
The amount of output neurons each genome has

fitness
The fitness function that is used to evaluate genomes

generation
Generation counter

population
An array containing all the genomes of the current generation

## Functions

There are a few built-in functions. For the client, only `getFittest()` and `evolve()` is important. In the future, there will be a combination of backpropagation and evolution. Stay tuned

createPool()
Initialises the first set of genomes. Should not be called manually.

async evolve()
Loops the generation through a evaluation, selection, crossover and mutation process.

async evaluate()
Evaluates the entire population by passing on the genome to the fitness function and taking the score.

sort()
Sorts the entire population by score. Should be called after `evaluate()`

getFittest()
Returns the fittest genome (highest score) of the current generation

mutate()
Mutates genomes in the population, each genome has `mutationRate` chance of being mutated.

getOffspring()
This function selects two genomes from the population with `getParent()`, and returns the offspring from those parents.

getAverage()
Returns the average fitness of the current population

getParent()
Returns a parent selected using one of the selection methods provided. Should be called after evaluation. Should not be called manually.

export()
Exports the current population of the set up algorithm to a list containing json objects of the networks. Can be used later with `import(json)` to reload the population

import(json)
Imports population from a json. Must be an array of networks that have converted to json (with `myNetwork.toJSON()`)