In most systems, code and model are separate things. Code is static—compiled once, deployed, done. Models are trained—adjusted by gradient descent over datasets, frozen, shipped. The boundary between them is hard: code doesn't learn, models don't compile. Simplex 0.20.0 erases that line. When every value carries its own derivative, when the compiler knows that a weight is a dual number, the distinction between “executing code” and “running inference” ceases to be meaningful. This is the story of everything that makes that possible.
Liquid Neural Networks: Code That Flows
Start with the most revealing piece: liquid neural networks.
A conventional neural network is a fixed graph. Inputs enter, activations flow through static weight matrices, outputs emerge. The weights don't change during inference. The topology doesn't change during inference. The entire structure is frozen at deployment.
A liquid neuron is different. Its dynamics are governed by a continuous-time ODE:
tau_i * dx_i/dt = -x_i + f(sum_j w_ij(x_j) * x_j + I_i)
The key is that w_ij(x_j)—the weight from neuron j to neuron i—is a function of the input. Not a constant. The weight itself depends on the state of the network. The network rewires as it runs.
// Dynamic weight: base + modulation * sigmoid(state)
w_ij(x_j) = w_base + w_mod * sigmoid(x_j)
This is Hasani et al.'s work from MIT CSAIL—Liquid Time-Constant Networks (AAAI 2021) and Closed-form Continuous-time Neural Networks (Nature Machine Intelligence 2022). It's the most parameter-efficient recurrent architecture known. A 19-neuron liquid network can drive an autonomous car. An LSTM needs 100,000+ parameters for the same task.
Now consider what happens when you implement this in Simplex, where every value is dual32.
The time constant tau is a dual32. The weight w_base is a dual32. The modulation w_mod is a dual32. The state x_j is a dual32. When the dynamic weight computation runs—w_base + w_mod * sigmoid(x_j)—the derivative component propagates automatically through every operation. The sensitivity of the output to w_base is computed as a consequence of the arithmetic. No backward pass. No tape. No autograd library. Just dual32 doing what dual32 does.
The Insight
A liquid neuron's forward pass is its gradient computation. In Simplex, running inference and computing learning signals are the same operation. The boundary between “executing” and “training” doesn't exist because it can't—the data type won't allow it.
Simplex implements the full liquid architecture: individual liquid neurons with dynamic weights, Neural Circuit Policies (NCPs) with biologically-inspired sparse connectivity—sensory neurons, interneurons, command neurons, motor neurons—and Closed-form Continuous-time (CfC) cells that solve the neuron ODE analytically, avoiding numerical integration entirely.
// Neural Circuit Policy: biologically-wired liquid network
let ncp = ncp_new(
n_neurons: 19, // 4 sensory + 8 inter + 4 command + 3 motor
n_inputs: 4,
n_outputs: 3,
);
ncp_init(&ncp, seed: 42);
ncp_wire_sparse(&ncp, sparsity: 0.6);
// Forward pass: ODE dynamics + gradient propagation in one step
let output = ncp_forward(&ncp, &input); // dual32 in, dual32 out
// CfC cell: closed-form solution, no ODE solver needed
let cfc = cfc_cell_new(input_dim: 8, hidden_dim: 32);
cfc_cell_init(&cfc, seed: 42);
let (output, hidden) = cfc_forward(&cfc, &input, &prev_hidden);
19 neurons. The ODE dynamics rewire the network continuously. The derivatives propagate through the dynamics. The system learns while it runs. This is not a model being trained and then deployed. This is a model that is always both.
dual32 Learning: One Pass, Zero Overhead
The liquid network demonstrates the principle. The dual32_learning module generalises it.
In a conventional framework, a linear layer stores weights as floats. A forward pass computes outputs. A backward pass computes gradients. An optimiser updates the weights. Three distinct phases, three passes over the data, two copies of every parameter (weights + gradient buffer).
In Simplex, a weight is a dual32. The value slot holds the weight. The derivative slot holds the gradient. A forward pass through d32_mul and d32_add computes the output and the gradient simultaneously. One pass. One copy of each parameter. The gradient is literally the other half of the same 64-bit integer.
// Every weight IS a dual number
// Value slot = weight, Derivative slot = gradient
// d32_mul propagates gradients through the product rule — automatically
let layer = linear_layer_new(input_dim: 4, output_dim: 2);
let output = linear_forward(&layer, &input); // forward + gradients in one pass
linear_update(&layer, learning_rate: 0.001); // update from the derivative slots
Memory: 1x model size. Passes: 1. There is no gradient tape because the gradient is in the number. There is no backward pass because there's nothing to go back through.
The Conduit: Where Bytes Enter
If everything inside Simplex is dual32, there must be a boundary where external data enters. That's the conduit.
A conduit is a read-only adapter. It pulls data from the outside world—HTTP endpoints, message queues, file systems, event streams, databases—and converts external bytes into Simplex types at the boundary. It doesn't process. It doesn't interpret. It conducts.
// Conduit: the pipe from external world to Simplex
let config = ConduitConfig::new("https://api.example.com/data")
.with_bearer(token)
.with_timeout(30000)
.with_batch_size(100);
let conduit = HttpConduit::connect(&config)?;
let raw_data: Vec<RawData> = conduit.pull()?;
// The boundary: external bytes become dual32
let dvec_handle: i64 = bytes_to_dvec(&raw_data.bytes);
That last line is the boundary. Before it, bytes are bytes—opaque, without derivatives, without meaning to the learning system. After it, every value is dual32: a value and its derivative, ready to flow through any computation in the system. The conduit is the only place this conversion happens. Everything downstream operates on dual32 natively.
Five conduit types—HTTP, SQL, file, queue, stream—share a common trait: connect, pull, status, close. The data enters as RawData—bytes, source identifier, format hint, metadata. The conversion to dual32 uses the DualVec SoA layout: values in one contiguous array, derivatives in another. Ready for SIMD. Ready for the sieve.
The Sieve: Distilling Signal from Noise
Raw data from the conduit is mostly noise. An HTTP response is 80% HTML boilerplate, navigation, ads, scripts. A database row is mostly schema overhead. The sieve sits between the conduit and the model, and its job is to discard the 98% that isn't meaning.
Five layers, applied in order:
| Layer | What It Does | What It Removes |
|---|---|---|
| Format | Detects and strips transport structure | HTML tags, XML wrappers, JSON structure |
| Template | Fingerprints and removes repeated boilerplate | Navigation, headers, footers, cookie banners |
| Entropy | Measures information density, gates low-entropy blocks | Repetitive text, filler, whitespace-heavy regions |
| Semantic | Extracts meaning-bearing elements | Decorative content, non-semantic markup |
| Compress | Reduces redundancy while preserving meaning | Semantic duplicates, verbose phrasing |
The output is a SievedContent: pure signal, with provenance tracked, entropy scored, and noise discarded. Every step reports what it removed and how long it took.
Here's the critical detail: the sieve has a native dual32 pipeline. Instead of converting dual32 data back to bytes between layers, all five layers operate on Vec<i64> dual32 data directly. The entropy measurement uses the derivative component—conditional entropy from the dual32's derivative slot. Template detection hashes blocks of dual32 values natively. Only at the final output does the data convert to a string for human consumption.
// The dual32-native sieve path
let sieve = Sieve::with_config(SieveConfig::aggressive());
// Data stays dual32 through all 5 layers — no byte conversion between layers
let result = sieve.process_dual(&dual_data, source);
// result.signal_ratio = 0.03 → 97% noise removed
// result.entropy_score = 4.2 → high information density in what remains
The sieve doesn't just clean data. It measures. Every layer produces statistics. The scaffold watches those measurements.
The Scaffold: Six Boundaries, One Diagnostic
The scaffold is the nervous system of Simplex. It doesn't make decisions. It measures, it emits signals, and the system responds.
The mathematics come from the same place as Navier-Stokes regularity analysis: enstrophy (rate of change), convergence scoring, PID control over convergence, stability margins, fragility trends, perturbation analysis. Eight diagnostic levels (L0–L7) that together answer one question: is the system healthy, and if not, where is it breaking?
In 0.20.0, the scaffold extends from a single diagnostic hierarchy into six boundaries, each observing a different layer of the system:
| Boundary | Observes | Key Signals |
|---|---|---|
| Code | Compilation and tests | Success rate, error categories, regressions, new passes |
| Model | Belief dynamics and gradient health | Enstrophy, convergence, PID signal, stability margin, fragility |
| Data | The sieve and conduit | Throughput, conversion loss, entropy, template stability, novel pattern rate |
| Hardware | The dual32 runtime | Saturation count, saturation rate, ops throughput |
| Protocol | Hive-to-hive communication | Sync latency, compression ratio, federation convergence, message loss |
| Contraction Engine | Cross-boundary coupling | N×N contraction matrix: does improving one boundary help or hurt others? |
Every signal from every boundary is dual32. Value = current reading. Derivative = delta from last cycle. The scaffold doesn't need a separate change-detection system because the derivative is change detection. It's built into the number.
The contraction engine is the piece that ties it together. Given N boundaries, each emitting a dual32 health signal, the engine computes an N×N matrix of contraction ratios:
// Contraction ratio: when boundary i improves, what happens to boundary j?
rho(i, j) = Delta_j / Delta_i
// rho < 1 : contractive — improvement dampens (stable)
// rho > 1 : divergent — improvement amplifies (unstable)
// rho < 0 : conflict — improvement in i degrades j (attention needed)
// rho == 1 : neutral — no coupling
This is how the system knows whether fixing one thing is breaking another. A code change that improves compilation health but degrades model convergence shows up as a negative contraction ratio between the code and model boundaries. The scaffold doesn't fix it. The scaffold measures it. The system decides what to do.
The Learning Framework: 30 Architectures on dual32
The liquid networks are one architecture among many. Simplex-learning in 0.20.0 includes:
- Liquid Neural Networks — continuous-time ODEs with dynamic weights
- Closed-form Continuous-time (CfC) Cells — analytical ODE solution
- Neural ODEs — continuous-depth networks, Euler/RK4/adaptive solvers
- Kolmogorov-Arnold Networks (KAN) — B-spline edge activations
- Mixture of Experts (MoE) — sparse gating, load balancing, top-k routing
- Modern Hopfield Networks — exponential-capacity associative memory
- State Space Models — S4 (structured) and Mamba (selective)
- Sparse Distributed Memory — Kanerva SDM + hyperdimensional computing
- Diffusion Language Models — discrete denoising, masking, iterative generation
- Tensor Network Compression — TT/MPS decomposition, SVD, Tucker
- Hyperbolic Embeddings — Poincaré ball, Möbius ops, RSGD
- Geometric Equivariant Layers — rotations, GNNs, spherical harmonics
- Conformal Prediction — calibrated prediction sets with coverage guarantees
- Causal Inference — DAGs, do-calculus, d-separation, adjustment sets
- Neuro-Symbolic Reasoning — KB, Horn clauses, forward/backward chaining
- Information Geometry — natural gradients, K-FAC, Fisher information
Every one of these operates on dual32. Every one gets forward-mode AD for free. Every one can be observed by the scaffold. And here's the part that matters: every one of these blurs the boundary between code and model differently.
A Hopfield network stores patterns as attractors. Is that code or data? The stored patterns are weights, but they function like a database. A neuro-symbolic system chains Horn clauses with neural confidence scores. Is the logic engine code or model? The causal inference module builds DAGs and computes do-calculus interventions. The graph is structural knowledge, but the edge weights learn.
When the representation is uniform—dual32 everywhere—these aren't philosophical questions. They're implementation details. The scaffold measures all of it the same way.
The Progressive Adaptation Loop
Here's how it all connects:
- The conduit pulls external data and converts it to dual32 at the boundary
- The sieve strips noise, measures entropy, passes signal through
- The learning system—liquid networks, KAN, MoE, whatever architecture—processes dual32 data, computing output and gradients in one pass
- The scaffold observes all six boundaries: code health, model health, data quality, hardware saturation, protocol latency, cross-boundary coupling
- The contraction engine computes whether the system is improving holistically or whether one boundary is degrading while another improves
- The scaffold signals feed back into the learning system: gated learning rates, adaptive EWC strength, probe scheduling—all driven by the scaffold's dual32 health signals
This is not a training loop. There's no “train, then deploy”. The conduit is always pulling. The sieve is always filtering. The models are always processing. The scaffold is always measuring. The gradients are always flowing. The system adapts continuously, and the scaffold prevents that adaptation from destabilising.
The scaffold-gated learning system makes this explicit:
// Scaffold-gated learning: the scaffold controls the learning rate
let health = scaffold.update(&beliefs);
// If convergence is healthy, learn normally
// If diverging, reduce learning rate
// If fragile, increase EWC strength to protect what works
let lr = gated_learning_rate(health.convergence, base_lr: 0.001);
let ewc = gated_ewc_strength(health.stability_margin, base_lambda: 1.0);
// The meta-gate adapts its own thresholds from scaffold signals
meta_gate_adapt(&gate, &health);
The meta-gate is the most revealing piece. It's a gate that controls learning parameters, and its own parameters are adapted by the scaffold. The scaffold observes the model. The model's learning is gated by the scaffold. The scaffold's observation thresholds are adapted by the meta-gate. The meta-gate's parameters are updated by the scaffold's signals. It's circular—deliberately. The system tunes itself.
The Boundary Dissolves
Consider what “code” means in this system.
A liquid neuron's time constant adapts based on input dynamics. Is that parameter a weight (model) or a configuration value (code)? A sieve's entropy threshold determines what data reaches the model. If that threshold is a dual32 whose derivative tracks information loss, is the sieve code or a learnable filter? The scaffold's PID gains control how aggressively the system responds to instability. If those gains are adapted by the meta-gate, are they tuning parameters or learned weights?
The answer, in every case, is: it doesn't matter. They're all dual32. They all carry derivatives. They can all be observed. They can all adapt.
This is what happens when you build a language around a single data type that carries its own gradient. The traditional separation—code is static, models are trained, data is inert—stops making sense. Everything is a computation on dual32. Everything has a derivative. Everything can learn.
Code that measures the model.
Models that adapt the code.
A scaffold that observes both
and adapts itself.
The boundary was never real.
We just didn't have the right data type to see it.
What Ships in 0.20.0
Everything described here is in the release:
| Component | What |
|---|---|
| simplex-learning | 30+ architectures on dual32: liquid, CfC, KAN, MoE, Hopfield, S4, Mamba, SDM, diffusion, neural ODE, tensor networks, hyperbolic, equivariant, conformal, causal, neuro-symbolic, information geometry |
| simplex-conduit | 5 conduit types (HTTP, SQL, file, queue, stream) with dual32 boundary conversion and DualVec SoA layout |
| simplex-sieve | 5-layer noise removal (format, template, entropy, semantic, compress) with native dual32 pipeline |
| scaffold | 6 boundaries (code, model, data, hardware, protocol, contraction engine) with L0–L7 diagnostics |
| dual32_learning | Single-pass training primitives: forward = gradient, 1x memory, zero tape overhead |
| belief system | Grounded beliefs with provenance, falsification conditions, calibrated confidence, epistemic annealing |
| unified pipeline | Scaffold-gated learning: adaptive LR, EWC gating, meta-gate self-adaptation, online LoRA |
179 tests pass. The entire stack is dual32 from register to application.
The Shape of What Comes Next
Each release makes the adaptation loop tighter. In 0.20.0, code measures model and model adapts. In the next cycle, the scaffold signals will drive not just learning rates but architecture selection—switching between liquid, KAN, and MoE based on what the data demands. The sieve will learn its own entropy thresholds from the model's feedback. The conduit will adapt its pull frequency based on the data boundary's throughput signals.
The trajectory is clear: every component observes, every component adapts, every boundary signal carries a derivative. The system progressively dissolves the distinction between the parts that compute and the parts that learn, until there is no distinction left.
That's the road less traveled. Not just faster arithmetic. A different kind of system entirely.
Try It
Simplex 0.20.0
Source, documentation, and the full learning framework