Items we discussed and decided to defer. Each section is self-contained so anyone returning to this can pick up the work without re-deriving the context.
Status: deferred. Decision date: 2026-05-01.
What: A NumPy-accelerated implementation of _calibrate (in
world_model/dynamics/reseed.py) that processes many test cases in
parallel via matrix-matrix multiplication, replacing the per-case
Python-loop path.
Why deferred: the unbatched version is fast enough for the demos
we have. The Digits demo (demo_digits.py) runs 200 test cases in
~30 seconds; not worth optimizing yet.
When to revisit: when we want to run the engine on datasets with thousands of test cases, or when we start the cosmological novelty curve experiment (which involves many reseed calls per epoch).
The graph-propagation calibration computes, each iteration, a target for every non-anchored tendency as a weighted average of its neighbors' allocations. In math:
targets = (W @ allocations) / row_sums
allocations = allocations + lr * (targets - allocations)
allocations = allocations / sum(allocations) # normalize
where W is the (n_tendencies x n_tendencies) edge-weight matrix.
This is already a tight inner loop in NumPy terms.
For multiple test cases at once, stack the allocation vectors as
columns: allocations becomes (n_tendencies x n_cases). Every step
remains a single matrix-matrix multiply. The classifier's outer loop
collapses to one batched call.
3-5 hours. Steps:
- Build a
_GraphMatrixhelper that convertsStakeWeightGraphto a numpy array once, with anid -> row_indexmap. - Add a
_calibrate_numpythat takes (n_tendencies x n_cases) allocation matrices and returns the same shape after convergence. - Add a wrapper at the demo level (
classify_batch(cases, ...)) that builds the substitution matrix, calls_calibrate_numpy, and reads out winners per column. - Write a test that pure-Python and NumPy paths produce identical results on the same input (within numerical tolerance, say 1e-9).
- Bench script confirming the speedup.
- No Keras / PyTorch. Those are tools for training parametric models via gradient descent. We don't have learnable parameters. Adopting them would be cargo culting.
- No GPU acceleration yet. Premature; we are nowhere near the scale (10^5+ tendencies) where GPU matters.
- No closed-form eigenvector solution. The graph propagation
fixed-point IS the dominant eigenvector of the transition matrix
modified by the anchored boundary conditions.
scipy.sparse.linalg.eigscould replace the iteration loop entirely. Real optimization, but premature -- it would obscure what the engine is doing for marginal gain at our current scale.
If we decide to learn graph edge weights from data instead of taking them from domain priors -- i.e., the engine learns its own wiring -- that's a different architectural decision, not a library swap. At that point an autograd library is the right tool. Until then, we are doing relaxation on a weighted graph; NumPy is sufficient.