Why ECS for a GNN?
ECS decomposes the tensor and autograd abstractions into individually addressable components in a relational registry. The result is an experimentation platform: graph topology, autograd, dispatch, and experimental configuration share one data structure, each variable independently. For research where topology is the thing under test, the substrate is the experiment.
Where does the graph live in code?
A graph neural network operates on graph-shaped data: molecules with bonds, social networks, citation graphs. The connections between items are part of the input. But the graph itself has to live somewhere in code, and conventional ML stacks default to representing it as a tensor: an adjacency matrix or an edge index sitting next to the model parameters. This project doesn't.
A PyTorch tensor wraps four things into one type: a data array, a gradient array, an operation history recorded during the forward pass, and metadata about shape, device, and gradient tracking. Those four things are a database with two tables (the activations and the gradients) and a write-ahead log (the autograd tape). PyTorch packages them as the tensor type. This project keeps them as separate entities.
Every piece of the network is an entity in a registry. The nodes are entities. The connections between nodes are entities. Some connection entities carry activations during the forward pass; others carry gradients during the backward pass. The operation history is the lifecycle of these entities: when they spawn, when they despawn. The metadata is type-level: the entity's component types encode shape and direction. One relational substrate, traversed forward for activations and backward for gradients.
Pruning a connection is one line: despawning the entity that represents the connection. The lifecycle cascade is structural. When a hub entity is despawned, its incoming and outgoing connections go with it through the ECS relationship system. No dangling references, no parallel structure to keep in sync, no orphan cleanup pass. The next forward pass produces a sparser graph automatically.
Some state is global. The seed that determines the wiring. The learning rate that governs the run. These live in Resources: one value every System reads from. Other state is per-entity. The tag that marks an entity as a hub. The weight on a connection. These live in Components, individually attached.
The compiler enforces the partition. The rule is scope: global or per-entity. Hyperparameters happen to be global; that's a consequence, not the rule.
Algorithm dispatch follows the same logic. Two zero-sized tag types, one for mean aggregation and one for winner-take-all, get attached to hub entities. The mean-aggregation System queries entities with the first tag; the winner-take-all System queries entities with the second. The dispatch is structural; the two Systems can never interfere because they operate on disjoint sets of entities. Adding a third aggregation algorithm is adding a third tag and a third System.
A different experiment isn't a different codebase. It means different tags spawning on entities, different values loaded into shared state at startup. The same forward, backward, and update Systems run. The hypothesis being tested is the configuration of the registry: which tags are present on which entities, which values are loaded at startup. New experiments are new configurations of the registry.
The research claim being tested is that hubs in the network connect preferentially to non-hubs, a hub-and-spoke wiring pattern observed in avian brain anatomy. The function that builds this wiring queries the registry for entities tagged as hubs and entities that aren't, and connects them. The query shape is the research claim it implements. The function's name says what it does; its query says how. There's no translation layer between the network the paper describes and the code that builds it. The research vocabulary and the implementation vocabulary are the same vocabulary.
What this gets you is one place to look. The graph, the autograd, the dispatch: they're all in the registry. Graph topology is what ECS expresses natively. This project is research about topology, so that's where I went.