|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +NEAT-Python is a pure-Python implementation of NEAT (NeuroEvolution of Augmenting Topologies), a method for evolving arbitrary neural networks. This project has no dependencies beyond the Python standard library and supports Python 3.8-3.14 and PyPy3. |
| 8 | + |
| 9 | +## Key Development Commands |
| 10 | + |
| 11 | +### Testing |
| 12 | +```bash |
| 13 | +# Run all tests with coverage |
| 14 | +pytest tests/ --cov=neat --cov-report=term --cov-report=xml -v |
| 15 | + |
| 16 | +# Run a single test file |
| 17 | +pytest tests/test_genome.py -v |
| 18 | + |
| 19 | +# Run a specific test |
| 20 | +pytest tests/test_genome.py::TestGenome::test_mutate_add_node -v |
| 21 | +``` |
| 22 | + |
| 23 | +### Installation |
| 24 | +```bash |
| 25 | +# Install in development mode |
| 26 | +pip install -e . |
| 27 | + |
| 28 | +# Install with optional dependencies |
| 29 | +pip install -e ".[dev]" # Development tools (pytest, coverage, etc.) |
| 30 | +pip install -e ".[docs]" # Documentation building tools |
| 31 | +pip install -e ".[examples]" # Dependencies for running examples |
| 32 | +pip install -e ".[all]" # Everything |
| 33 | + |
| 34 | +# Build distributions (requires build package) |
| 35 | +python -m build |
| 36 | +``` |
| 37 | + |
| 38 | +### Documentation |
| 39 | +```bash |
| 40 | +# Build documentation (from docs/ directory) |
| 41 | +cd docs |
| 42 | +make clean && make html |
| 43 | + |
| 44 | +# View built docs at docs/_build/html/index.html |
| 45 | +``` |
| 46 | + |
| 47 | +### Running Examples |
| 48 | +```bash |
| 49 | +# Start with the simplest example |
| 50 | +python examples/xor/evolve-minimal.py |
| 51 | + |
| 52 | +# Other examples demonstrate various NEAT features |
| 53 | +python examples/xor/evolve-feedforward.py |
| 54 | +python examples/xor/evolve-feedforward-parallel.py |
| 55 | +python examples/single-pole-balancing/evolve-feedforward.py |
| 56 | +``` |
| 57 | + |
| 58 | +## Architecture Overview |
| 59 | + |
| 60 | +### Core Evolution Loop (neat/population.py) |
| 61 | +The `Population` class implements the main NEAT algorithm: |
| 62 | +1. Evaluate fitness of all genomes |
| 63 | +2. Check termination criterion |
| 64 | +3. Generate next generation via reproduction |
| 65 | +4. Partition into species based on genetic similarity |
| 66 | +5. Repeat |
| 67 | + |
| 68 | +The population accepts a fitness function that takes `(genomes, config)` as arguments and assigns a fitness value to each genome. |
| 69 | + |
| 70 | +### Genome Representation (neat/genome.py) |
| 71 | +- **DefaultGenome**: Represents a single individual/network |
| 72 | +- Consists of node genes (neurons) and connection genes (synapses) |
| 73 | +- Supports various mutation operators: add/delete nodes, add/delete connections, mutate weights |
| 74 | +- Configuration controls network topology (feed-forward vs recurrent, initial connectivity) |
| 75 | + |
| 76 | +### Innovation Tracking (neat/innovation.py) |
| 77 | +- **InnovationTracker**: Ensures consistent numbering of genes across population |
| 78 | +- Critical for proper crossover - matching genes have same innovation numbers |
| 79 | +- Tracks both node and connection innovations separately |
| 80 | +- Reset at each generation to maintain consistency |
| 81 | + |
| 82 | +### Speciation (neat/species.py) |
| 83 | +- **DefaultSpeciesSet**: Groups similar genomes into species |
| 84 | +- Uses genetic distance metric based on disjoint/excess genes and weight differences |
| 85 | +- Each species has a representative that determines membership |
| 86 | +- Protects innovation by allowing new structures time to optimize |
| 87 | + |
| 88 | +### Reproduction (neat/reproduction.py) |
| 89 | +- **DefaultReproduction**: Handles creation of offspring |
| 90 | +- Implements crossover (combining parent genomes) and mutation |
| 91 | +- Allocates offspring to species based on fitness |
| 92 | +- Manages stagnation removal of underperforming species |
| 93 | + |
| 94 | +### Network Implementations (neat/nn/) |
| 95 | +- **FeedForwardNetwork**: Fast implementation for acyclic networks |
| 96 | +- **RecurrentNetwork**: Supports networks with cycles |
| 97 | +- Both created from evolved genomes via `.create(genome, config)` |
| 98 | + |
| 99 | +### Specialized Neuron Models |
| 100 | +- **neat/ctrnn/**: Continuous-Time Recurrent Neural Networks |
| 101 | +- **neat/iznn/**: Izhikevich spiking neuron model |
| 102 | + |
| 103 | +### Configuration System (neat/config.py) |
| 104 | +- Config files are INI format with sections like `[DefaultGenome]`, `[DefaultReproduction]` |
| 105 | +- The `Config` class loads and validates all parameters |
| 106 | +- Each major component has its own config class (e.g., `DefaultGenomeConfig`) |
| 107 | +- Config parameter types are strictly enforced |
| 108 | + |
| 109 | +### Parallel Evaluation (neat/parallel.py) |
| 110 | +- **ParallelEvaluator**: Uses multiprocessing to evaluate fitness in parallel |
| 111 | +- Pass it to population.run() instead of a regular fitness function |
| 112 | +- Example: `pe = ParallelEvaluator(num_workers, eval_genome); p.run(pe.evaluate)` |
| 113 | + |
| 114 | +### Network Export (neat/export/) |
| 115 | +- Exports trained networks to JSON format for interoperability |
| 116 | +- Framework-agnostic format with metadata support |
| 117 | +- See `docs/network-json-format.md` for format specification |
| 118 | +- Example conversion tools in `examples/export/` |
| 119 | + |
| 120 | +## Configuration Files |
| 121 | + |
| 122 | +All examples include a config file (e.g., `config-feedforward`) that specifies: |
| 123 | +- Network structure (num_inputs, num_outputs, num_hidden) |
| 124 | +- Mutation rates (node_add_prob, conn_add_prob, etc.) |
| 125 | +- Activation functions, aggregation functions |
| 126 | +- Speciation parameters (compatibility threshold) |
| 127 | +- Reproduction parameters (elitism, survival threshold) |
| 128 | +- Population size and fitness criterion |
| 129 | + |
| 130 | +## Common Patterns |
| 131 | + |
| 132 | +### Basic NEAT Run |
| 133 | +```python |
| 134 | +config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction, |
| 135 | + neat.DefaultSpeciesSet, neat.DefaultStagnation, |
| 136 | + 'config-file') |
| 137 | +p = neat.Population(config) |
| 138 | +p.add_reporter(neat.StdOutReporter(False)) |
| 139 | +winner = p.run(eval_genomes, n=300) # Run for max 300 generations |
| 140 | +``` |
| 141 | + |
| 142 | +### Reproducibility |
| 143 | +Set random seed for deterministic evolution: |
| 144 | +```python |
| 145 | +p = neat.Population(config, seed=42) |
| 146 | +# or in config file: seed = 42 |
| 147 | +``` |
| 148 | + |
| 149 | +### Checkpointing |
| 150 | +```python |
| 151 | +p.add_reporter(neat.Checkpointer(generation_interval=10)) |
| 152 | +# Restore from checkpoint |
| 153 | +p = neat.Checkpointer.restore_checkpoint('neat-checkpoint-50') |
| 154 | +``` |
| 155 | + |
| 156 | +### Custom Reporters |
| 157 | +Reporters receive callbacks for events like generation start/end, species creation, etc. See `neat/reporting.py` for the interface. |
| 158 | + |
| 159 | +## Progress Logs |
| 160 | + |
| 161 | +Do NOT commit `progress-*.md` files to this repository. They are local working notes excluded via `.gitignore`. Continue writing them locally per the global instructions, but do not `git add` them. |
| 162 | + |
| 163 | +## Testing Notes |
| 164 | + |
| 165 | +- Test files use configuration files in `tests/` directory (e.g., `test_configuration`) |
| 166 | +- Many tests verify evolutionary properties statistically (may have rare failures) |
| 167 | +- Coverage is tracked via coveralls |
| 168 | +- Tests include edge cases for graph cycles, gene mutations, and crossover operations |
| 169 | + |
| 170 | +## Important Implementation Details |
| 171 | + |
| 172 | +### Feed-forward Networks |
| 173 | +- `initial_connection` config determines starting topology |
| 174 | +- `feed_forward = True` enables cycle detection to enforce acyclic structure |
| 175 | +- Feed-forward networks are evaluated in a single pass |
| 176 | + |
| 177 | +### Recurrent Networks |
| 178 | +- `feed_forward = False` allows cycles |
| 179 | +- Require multiple activation steps to propagate signals |
| 180 | +- Use time_constant parameter for CTRNN variant |
| 181 | + |
| 182 | +### Structural Mutations |
| 183 | +- Adding a node splits an existing connection |
| 184 | +- `single_structural_mutation = True` limits to one structural change per mutation |
| 185 | +- Disabled connections can be re-enabled by mutation |
| 186 | + |
| 187 | +### Crossover |
| 188 | +- Only occurs between genomes in same species |
| 189 | +- Matching genes (same innovation number) are randomly selected from either parent |
| 190 | +- Disjoint/excess genes come from more fit parent |
| 191 | +- See `test_genome_crossover.py` for detailed test cases |
0 commit comments