MultiNEAT is a portable library for neuroevolution - evolving neural networks with a genetic algorithm. It is based on NEAT (NeuroEvolution of Augmenting Topologies): networks start minimal and grow over the generations, and the population is divided into species so new structures get time to improve. The core is fast, dependency-free C++17 with Python bindings.
- NEAT - generational and steady-state (rtNEAT) evolution, speciation, phased searching
- HyperNEAT and ES-HyperNEAT - large geometric networks painted by an evolved CPPN
- Novelty search and behavior-based speciation
- Evolvable traits for neurons, links and genomes, including custom Python objects
- Recurrent networks, leaky integrator neurons, Hebbian plasticity, RTRL
- Everything is picklable - evaluate genomes in parallel processes
- A built-in 2D physics engine for simulated agents
Documentation (also in docs/)
pip install git+https://github.com/peter-ch/MultiNEAT.gitYou need Python 3.8+ and a C++17 compiler; nothing else (no Boost). See Installation for details and for building the C++ library alone.
import MultiNEAT as NEAT
params = NEAT.Parameters()
params.PopulationSize = 150
params.MinActivationA = 4.9 # steep sigmoids
params.MaxActivationA = 4.9
params.AllowLoops = False # feed-forward networks
params.TournamentSelection = False # truncation selection
# 3 inputs (x1, x2 and the bias), 0 hidden, 1 output
genome = NEAT.Genome(0, 3, 0, 1, False, NEAT.ActivationFunction.UNSIGNED_SIGMOID,
NEAT.ActivationFunction.UNSIGNED_SIGMOID, 0, params, 0)
pop = NEAT.Population(genome, params, True, 1.0, 0)
def evaluate(genome):
net = NEAT.NeuralNetwork()
genome.BuildPhenotype(net)
error = 0
for inputs, target in [([0, 0, 1], 0), ([0, 1, 1], 1), ([1, 0, 1], 1), ([1, 1, 1], 0)]:
net.Flush()
net.Input(inputs)
for _ in range(3):
net.Activate()
error += abs(net.Output()[0] - target)
return (4 - error) ** 2
for generation in range(300):
genomes = NEAT.GetGenomeList(pop)
for g in genomes:
g.SetFitness(evaluate(g))
best = max(g.GetFitness() for g in genomes)
print(generation, best)
if best > 15:
break
pop.Epoch()The tutorial explains it step by step.
| Tutorial | evolving XOR, step by step |
| How NEAT works | genomes, speciation, reproduction, mutations, phased and steady-state search |
| Neural networks | activation, activation functions, Hebbian learning, RTRL |
| HyperNEAT and ES-HyperNEAT | substrates and CPPNs |
| Traits | evolvable properties of neurons, links and genomes |
| Novelty search | searching for novelty instead of fitness |
| Saving and parallel evaluation | files, pickling, multiprocessing |
| Visualization, Physics engine, C++ | |
| Parameters reference, API reference, FAQ |
TestNEAT_xor.py |
NEAT solving XOR |
TestHyperNEAT_xor.py |
HyperNEAT solving XOR |
TestESHyperNEAT_xor.py, TestESHyperNEAT_xor_3d.py |
ES-HyperNEAT on 2D and 3D substrates |
NoveltySearch_simple.py |
novelty search finding XOR without being asked to |
NoveltySearch.py |
novelty search vs. fitness search in a deceptive maze |
ball_keeper.py |
a robot learning to keep a ball in the air |
TestTraits.py, TestCondTraits.py, PythonObjectTraits.ipynb |
evolving traits |
src/Main.cpp |
XOR in pure C++ |
See CONTRIBUTING.md. Changes are listed in the CHANGELOG.
GNU Lesser General Public License v3.0 - see LICENSE.
NEAT was developed by Kenneth O. Stanley and Risto Miikkulainen. MultiNEAT was written by Peter Chervenski with contributions from Shane Ryan and others.