# Fly Brain Lab A simulated fruit fly learns, by reinforcement learning, to dodge a flip-flop swat. Three brains control the same body with the same training budget: a plain MLP, a network wired like the real escape circuit of the fly (from the FlyWire connectome), and that same wiring shuffled as a control. Everything is plain JavaScript with no dependencies: the world, the eye, the brains, PPO with hand-written gradients, and the evaluation. It runs on Node 18 or newer. ## Result Five seeds per brain, 1.97 million training steps each, then 1,024 identical swats per seed (128 at each of 8 speeds, 0.5 to 12 m/s). | Brain | Mean escape rate | Worst and best seed | | --- | --- | --- | | Plain MLP | 63.8% | 62.0 to 65.3 | | Fly wiring, trained strengths | 62.2% | 58.4 to 65.2 | | Shuffled wiring, trained strengths | 59.7% | 54.8 to 63.7 | | Fly wiring, frozen synapses | 25.6% | 22.3 to 27.4 | | Shuffled wiring, frozen synapses | 27.2% | 17.4 to 32.1 | The three trained brains tie within the seed-to-seed spread, and the real wiring does not clearly beat the shuffled control. With synapses frozen at the connectome's counts, neither wiring solves the task. ## Files | File | What it is | | --- | --- | | `core.js` | the world (table, hand, flip-flop, fly), the eye, the brains, PPO and the evaluation | | `exp.js` | trains one brain with one seed and writes the result to `res/` | | `jobs.txt` | the list of runs in the experiment: 5 brains × 5 seeds, plus one run under the v1 rules | | `circuit.json` | the escape-circuit cut: 698 neurons, 5,734 connections, 92,612 synapses, with the sign of each connection | | `extract.py` | how the cut was taken from FlyWire v783 | | `published-results/` | the raw output of the 26 runs behind the table above: training curve, final evaluation and trained weights | ## Running it ```bash node exp.js mlp 1 120 # brain, seed, rounds node exp.js fly 1 120 node exp.js shuffled 1 120 node exp.js flyFrozen 1 120 node exp.js shuffledFrozen 1 120 node exp.js mlp 1 40 flight # v1 rules: the fly is allowed to take off # the whole experiment, 2 runs at a time cat jobs.txt | xargs -P 2 -L 1 node exp.js ``` Each run writes `res/_.json`. A run that already has a file in `res/` is skipped, so delete the file to redo it. A 120-round run takes 2 to 7 minutes on one CPU core. Runs are deterministic. `node exp.js mlp 1 120` ends at an escape rate of 0.648, the same value stored in `published-results/mlp_1.json`. ## The brains | Name | What it is | Trained parameters in the brain | | --- | --- | --- | | `mlp` | dense 579 → 10 → 19 network | 6,009 | | `fly` | real wiring, sign of each connection fixed, strength trained | 5,854 | | `shuffled` | the same with connection targets shuffled, keeping each neuron's number of inputs and outputs | 5,854 | | `flyFrozen` | real wiring, strength set by the synapse count, one global gain trained | 1 | | `shuffledFrozen` | the shuffled control for the frozen version | 1 | The body is identical for all of them. The eye turns the angular size of the flip-flop, its expansion rate and its bearing into the activity of 579 looming detectors. A small decoder (19 → 32 → 10) turns the 19 descending signals into an action: stay still or jump in one of eight directions. The decoder and the critic are trained for every brain. ## The task - The simulator advances in 10 ms steps. The hand holds still for 0.2 to 0.6 s, then swings in a straight line at 50 degrees, from 40 to 80 cm away, at 0.5 to 12 m/s. - The flip-flop is a 25 by 9 cm capsule aligned with the swing. - The aim follows the fly with a 50 ms lag and locks in the last 150 ms. - The jump is built in: 30 ms to prepare, 120 ms in the air at 60 cm/s, 100 ms before the next one. - Rewards: escaped +10, swatted −10, each jump −0.5. - Under the v1 rules (`flight`), a tenth action lets the fly take off and stay airborne at no cost. The policy learns to take off as soon as the hand appears and escapes every swat, which is why that action was removed. ## The circuit `circuit.json` holds: - 579 looming detectors from the eye: LC4, LPLC2, LPLC1 and LC6 cells - the 19 descending neurons that receive 200 or more synapses directly from them, including the Giant Fiber (DNp01) - the 100 interneurons with the most synapses both from the detectors and onto those descending neurons Only connections with 5 or more synapses are kept. `extract.py` reproduces the cut from two public files: - `Connectivity_783.parquet` from [philshiu/Drosophila_brain_model](https://github.com/philshiu/Drosophila_brain_model) - `Supplemental_file1_neuron_annotations.tsv` from [flyconnectome/flywire_annotations](https://github.com/flyconnectome/flywire_annotations) It needs `pandas` and `pyarrow`, and prints `698 neurons, 5734 connections, 92612 synapses`. ## Limits - The world is 2D with toy physics. There are no legs, wings or aerodynamics. - The connectome gives wiring, sign and synapse count. Synaptic strength and neuron dynamics are not in the data. - The cut is 698 neurons out of about 139 thousand. Connections feeding back onto the eye are left out. - Each detector is given an arbitrary position within the eye on its side, so the animal's fine retinotopy is not modelled. - LC4 and LPLC1 encode expansion rate here, and LPLC2 and LC6 encode size. Only the LC4/LPLC2 assignment follows the literature (Ache et al., 2019). - Hyperparameters were tuned on the plain MLP and reused for the other brains. - Five seeds show the trend but are too few to assert small differences. ## References - Dorkenwald et al., 2024, the FlyWire connectome: [flywire.ai](https://flywire.ai/) - Shiu et al., whole-brain model and connectivity table: [philshiu/Drosophila_brain_model](https://github.com/philshiu/Drosophila_brain_model) - [Card and Dickinson, 2008](https://www.cell.com/current-biology/fulltext/S0960-9822(08)01048-8), escape planning in the real fly - [Ache et al., 2019](https://www.cell.com/current-biology/fulltext/S0960-9822(19)30138-1), looming size and velocity in the Giant Fiber pathway - [Schulman et al., 2017](https://arxiv.org/abs/1707.06347), PPO