This page documents the neural network layer classes in the algovivo/mmgrten/nn/ module: Linear, ReLU, Tanh, and Sequential. These classes form the building blocks for learnable controllers used in soft-body simulation. For how these layers are assembled into a full locomotion policy, see MLPPolicy. For the tensor and memory primitives these layers depend on, see Memory Management (mmgrten).
The algovivo.nn subsystem is a minimal, WASM-backed neural network library that runs entirely within the WASM heap. It is accessed through the mmgrten Engine instance, which exposes a nn namespace via the nn class constructor algovivo/mmgrten/nn/index.js6-9 All layers allocate their parameter and intermediate tensors via the engine's memory manager and must be explicitly dispose()d to free memory algovivo/mmgrten/nn/Linear.js25-29
Module location: algovivo/mmgrten/nn/
Access pattern:
Sources: algovivo/mmgrten/nn/index.js6-27 algovivo/mmgrten/nn/Linear.js4-16
All layer classes inherit from a base Module class algovivo/mmgrten/nn/Module.js1-5
Diagram: Neural Network Entity Mapping
Sources: algovivo/mmgrten/nn/Linear.js3-30 algovivo/mmgrten/nn/ReLU.js3-23 algovivo/mmgrten/nn/Tanh.js3-23 algovivo/mmgrten/nn/Sequential.js3-23 algovivo/mmgrten/nn/Module.js1-5
The nn class acts as a factory for layers, holding a reference to the mmgrten engine algovivo/mmgrten/nn/index.js8-9 When a layer like Linear is created, it uses this engine to allocate Tensor objects algovivo/mmgrten/nn/Linear.js10-15
Sources: algovivo/mmgrten/nn/index.js6-27 algovivo/mmgrten/nn/Linear.js4-16
File: algovivo/mmgrten/nn/Linear.js
Linear implements an affine transformation: $y = Wx + b$ algovivo/mmgrten/nn/Linear.js18-23
| Property | Shape | Description |
|---|---|---|
weight | [outputSize, inputSize] | Weight matrix, initialized via ten.zeros algovivo/mmgrten/nn/Linear.js12 |
bias | [outputSize] | Bias vector, initialized via ten.zeros algovivo/mmgrten/nn/Linear.js13 |
output | [outputSize] | Pre-allocated output buffer, reused on each forward call algovivo/mmgrten/nn/Linear.js15 |
The forward(x) method utilizes the engine's functional interface (F):
F.matvec(this.weight, x, this.output) — matrix-vector multiplication algovivo/mmgrten/nn/Linear.js20F.add(this.output, this.bias, this.output) — adds the bias to the intermediate result in-place algovivo/mmgrten/nn/Linear.js21this.output algovivo/mmgrten/nn/Linear.js22Frees the weight, bias, and output tensors from the memory manager algovivo/mmgrten/nn/Linear.js25-29 Tests verify that calling dispose() returns the reserved byte count to its initial state test/ten/nn/linear.test.js32-35
Sources: algovivo/mmgrten/nn/Linear.js1-31 test/ten/nn/linear.test.js7-35
ReLU and Tanh are activation modules that lazily allocate their output buffers on the first forward pass to match the input shape algovivo/mmgrten/nn/ReLU.js13-15 algovivo/mmgrten/nn/Tanh.js13-15
Computes $max(0, x)$ element-wise using ten.functional.relu(x, this.output) algovivo/mmgrten/nn/ReLU.js16
Computes $tanh(x)$ element-wise using ten.functional.tanh(x, this.output) algovivo/mmgrten/nn/Tanh.js16
Sources: algovivo/mmgrten/nn/ReLU.js1-23 algovivo/mmgrten/nn/Tanh.js1-23
Sequential composes an ordered list of modules into a single execution chain algovivo/mmgrten/nn/Sequential.js4-8
Sequential.forward(x) iterates through the layers array, passing the output of one layer as the input to the next algovivo/mmgrten/nn/Sequential.js10-16
Diagram: Sequential Data Flow in Code
Sequential.dispose() ensures recursive cleanup by calling dispose() on every layer in its layers array algovivo/mmgrten/nn/Sequential.js18-22 Tests confirm that disposing a Sequential model correctly cleans up all internal layer allocations test/ten/nn/sequential.test.js29-32
Sources: algovivo/mmgrten/nn/Sequential.js1-24 test/ten/nn/sequential.test.js8-33
The system uses a manual memory management model. The nn module's layers own Tensor objects. These tensors wrap pointers to the WASM heap managed by a MemoryManager algovivo/mmgrten/mmgr/MemoryManager.js4-30
Diagram: Tensor Memory Allocation Flow
The MemoryManager tracks segments of memory using slots, freeSlots, and reservedSlots which are all instances of a linked List algovivo/mmgrten/mmgr/MemoryManager.js13-15 The List class provides the underlying linked structure for tracking memory nodes algovivo/mmgrten/mmgr/linked/List.js25-30 It supports iteration via [Symbol.iterator] to traverse allocated or free blocks algovivo/mmgrten/mmgr/linked/List.js70-77
When malloc is called, the manager iterates through freeSlots to find a segment of sufficient size algovivo/mmgrten/mmgr/MemoryManager.js100-115
Sources: algovivo/mmgrten/nn/Linear.js11-29 algovivo/mmgrten/mmgr/MemoryManager.js4-131 algovivo/mmgrten/mmgr/linked/List.js25-78
| Class | Factory Method (in nn class) | Primary Logic |
|---|---|---|
Linear | Linear(inputSize, outputSize) | F.matvec + F.add algovivo/mmgrten/nn/Linear.js20-21 |
ReLU | ReLU() | F.relu algovivo/mmgrten/nn/ReLU.js16 |
Tanh | Tanh() | F.tanh algovivo/mmgrten/nn/Tanh.js16 |
Sequential | Sequential(...layers) | layers.forEach(l => x = l.forward(x)) algovivo/mmgrten/nn/Sequential.js12-14 |
Sources: algovivo/mmgrten/nn/index.js11-26 algovivo/mmgrten/nn/Linear.js18-23 algovivo/mmgrten/nn/ReLU.js10-18 algovivo/mmgrten/nn/Tanh.js10-18 algovivo/mmgrten/nn/Sequential.js10-16