axiomrnn
Design for the memory budget you have, not the memory you wish you had.
A recurrent spiking network you extend without forking, plus a memory planner that tells you what your model will cost before you train it.
import axiomrnn as ax
spec = ax.Model()
spec.add_spiking(192, horizon=24) # 192 neurons, 24 promised steps
spec.add_spiking(192, horizon=24)
spec.add_dense(4)
print(ax.explain_budget(spec, ax.Budget.consumer_8gb(), verbose=False))
That prints a real memory plan and needs no TensorFlow. The spiking layers need TensorFlow, which is a required dependency.
What you get
| Train a spiking network | recurrent layers whose state is carried by binary spikes, trained through ordinary keras.fit |
| Replace the neuron without forking | override membrane and membrane_dstate together; the gradient hooks are checked against finite differences |
| Know the memory cost first | ask the planner what a model costs at a given budget before you spend the GPU time |
| Invert the question | ask which model a budget can actually train, and what stops the next step up |
| Generate text | the recurrent state feeds back one token at a time; see examples/07_generate.py |
What it is not
It is not faster than a dense network on an ordinary GPU, and it does not save energy, because no measurement here involves neuromorphic hardware. The spiking choice costs about nothing in quality and earns its keep only where spikes are cheap.
It also does not beat transformers in general. That is a measured finding, not a guess. The reasoning is long and unflattering enough to deserve its own file: docs/RESEARCH_NOTES.md.
Read it before you cite this work.
Install
Not on PyPI yet. The artifacts below are built and verified, but nothing has
been uploaded, and the name axiomrnn is still unclaimed. So pip install axiomrnn will fail, or one day will install somebody else's project unrelated
to this one. Until a release exists, install from the wheel.
A wheel has been built locally and is in the tree:
dist/axiomrnn-0.1.0-py3-none-any.whl 68,153 bytes, 18 files
dist/axiomrnn-0.1.0.tar.gz 427,657 bytes
MEASURED — ls -l dist/, run in the repository root. The wheel ships
axiomrnn.py, axon/, axplan/ and axtf/, declares Requires-Python >=3.10,
numpy>=1.24 and tensorflow>=2.16, offers extras tf-gpu and dev, and
installs one console script, axiomrnn-explain.
TensorFlow is a required dependency, not an extra. It was one once, so that the
memory planner stayed usable without a deep learning framework, and that is
still true — import axiomrnn works with numpy alone. But the extra made the
default install a package that could not build a spiking layer, which is the one
thing anyone installing this is here for.
The wheel does not ship axcore/, tests/ or examples/. axcore holds
one C++ file with no __init__.py; the gate compiles and runs it, and it travels
in the sdist instead.
The wheel install, verified
python3 -m venv /tmp/v && /tmp/v/bin/python -m pip install dist/axiomrnn-0.1.0-py3-none-any.whl
/tmp/v/bin/axiomrnn-explain --budget 6gb --layers 2 --width 1024 --horizon 256
MEASURED 2026-10-04, re-run by this file's author against the environment
Release built:
Package Version
-------- -------
axiomrnn 0.1.0
numpy 2.5.3
pip 25.0.1
find_spec(tensorflow) = None
find_spec(keras) = None
ax._HAS_TF = False
ax._TF_ERR = No module named 'tensorflow'
ax.SpikingCell = None
site-packages path = .../site-packages/axiomrnn.py
any sys.path entry in /home/cune/axiomrnn: False
Budget = Budget(consumer 6 GB: 6.0 GB VRAM, host 32.0 GB, offload=True)
Three things follow, and they matter:
- The planning path works with no TensorFlow installed at all. Exactly
three packages land:
axiomrnn,numpy,pip. - The soft-fail is a soft-fail.
ax.SpikingCellisNoneandax._TF_ERRexplains why, instead of anImportErrorat package import. axplanandaxonare TensorFlow-free;axtfis not.MEASURED— module by module in that venv:axplan,axplan.memory,axplan.planner,axplan.solve,axplan.credit,axon,axon.lif,axon.gateand theaxtfnamespace all import;axtf.cellsandaxtf.buildboth raiseModuleNotFoundError. So do not read "the wheel works without TensorFlow" as "axtfworks without TensorFlow". It does not.
MEASURED — the console script exits 0 and prints
tape share: 98.6%, peak: 0.78 GiB of 6 GiB, HEADROOM: 3.33 GiB unused,
independently agreeing with examples/02_budget.py.
What works today from a checkout
cd axiomrnn
python3 examples/02_budget.py # works, no TensorFlow
MEASURED — env -u PYTHONPATH /usr/bin/python3 -c "import axiomrnn as ax; print(ax._HAS_TF)" in the repository root prints import ok, _HAS_TF = False.
The five-minute path
What TensorFlow is, and why it is unavoidable here
TensorFlow is Google's numerical library; Keras is its model-building layer, and you meet Keras whether or not you asked for it. A Keras model is not a Python object full of layers you call yourself — it is a graph: you declare the shape of the data going in, list the layers, and Keras wires them into one callable that moves the data through. This project needs it because a spiking layer's memory cost is a function of the graph the layer sits in, and because the layer has to be differentiable by a framework that owns the backward pass. There is no way to get a trained neuron here without it. Planning, however, needs nothing but NumPy — see the third step below, which is the part that runs in under a second.
Step 1 — get the code, no install (0 min)
git clone <this repository>
cd axiomrnn
Nothing to install. The planning path runs on a bare python3 with NumPy.
MEASURED — the system interpreter here is Python 3.14.4 with NumPy
2.5.0 and no TensorFlow, and python3 examples/02_budget.py exits 0
on it.
If you would rather install the built wheel than use the checkout, the Install section has the verified transcript. Either way, step 2 works with no TensorFlow anywhere.
Step 2 — the first budget, and it needs no TensorFlow (about 1 second)
python3 examples/02_budget.py
MEASURED — exit code 0 in 0.11 s, 15 MB peak RSS
(/usr/bin/time -f "%e s %M KB peakRSS" python3 examples/02_budget.py). Its
first line of output is the claim being tested:
TensorFlow in this environment: ABSENT, and not needed
and the core of it is this table:
budget usable needed fits?
consumer 6 GB 4.12 GiB 0.78 GiB yes
pro 24 GB 17.96 GiB 0.78 GiB yes
datacenter 80 GB 61.04 GiB 0.78 GiB yes
The same architecture at width 20480 needs 7.58 GiB and the planner says
NO on a 6 GB card rather than promising and failing later. This is the
product: the budget is an input, and the tool tells you what it buys.
Step 3 — the inverse question (about 1 second)
python3 examples/advanced/15_what_to_build.py
Still no TensorFlow. Every other tool answers "what does this network
cost?". This one answers the question you actually have. MEASURED — exit
code 0; at a 6 GiB budget:
LARGEST THAT FITS
hidden 8192, layers 32, horizon 256, batch 1
connections 2,147,745,792 bytes per synapse 2.00
peak 5.604 GiB of 6.000 GiB headroom 0.396 GiB binding term static
FIRST THAT DOES NOT FIT
hidden 32768, layers 4, horizon 1
peak 8.509 GiB of 6.000 GiB overshoot 1.42x
Three fields earn their keep:
- the binding term —
staticmeans the weights dominate, so the credit rule and the spike coding save you nothing on this budget and width is the only lever. That one word saves a wasted afternoon. - the failure boundary — the smallest step up that does not fit, with the overshoot. A tool that only reports successes cannot be told apart from a tool that is simply optimistic.
- refusal —
Nonewhen nothing in the searched space fits, and no invented boundary when the answer sits on the search ceiling. The same run prints both refusals on demand: with a budget too small for anything it printssolution: None, and at the width ceiling it printsreported overflow: None.
One caveat it states in its own output: this is a capacity answer, not a
quality one. This package has no verified quality model. The one quality
figure it carries — what the local credit rule costs — is printed next to the
capacity gain, because a capacity number without its price is a sales pitch.
MEASURED — same run: capacity ratio under the local rule is 1.00x, and
local rule at T=256 keeps 64.7% of BPTT.
Step 4 — a neuron that actually fires (75 s of compute, plus a 1.9 GB download)
Read this before step 4. TensorFlow has no build for Python 3.14. The
system interpreter on this machine is 3.14.4, so pip install tensorflow
into it will not work; you need an environment on Python 3.12 or older.
MEASURED — /usr/bin/python3 -V is Python 3.14.4; the TensorFlow
environment here is /home/cune/.venvs/ax/bin/python, Python 3.12.13.
(tests/run_all.py:25 carries the same note in a comment.)
TensorFlow is a large dependency: 1.9 GB for the tensorflow package,
21 MB for keras, 6.3 GB for the whole environment including the
interpreter. MEASURED — du -sh on each. That download, not the code, is
what decides whether this step fits in five minutes.
# with a Python 3.12-or-older environment that has TensorFlow 2.x:
python examples/01_minimal.py
MEASURED — TensorFlow 2.21.0, Keras 3.15.1, CPU only
(CUDA_VISIBLE_DEVICES=), exit code 0 in 75.2 s, 641 MB peak RSS,
running standalone. Held-out accuracy 0.9983 against a 0.2500 chance
baseline, after 15 epochs at batch 64; final training loss 3.7285e-04, final
validation loss 0.0071; 51,844 total parameters.
MEASURED — the same script as a suite of the gate took 190.9 s and
reported 0.9975. The wall clock differs because the gate run had other work
on the machine; the accuracy differs by run-to-run variance on a 1,200-example
held-out set. Both numbers are from this session, and the difference is why
this file quotes a range rather than a constant.
One warning about this file, MEASURED: it used to run the entire test
gate as a subprocess at the end (examples/01_minimal.py:165-175), so running
it trained the network, then ran the whole gate, which trained it a second time.
Observed with pgrep during this documentation pass: 01_minimal.py spawned
run_all.py, whose EXAMPLE 01 suite spawned 01_minimal.py again.
Fixed at 23:58:59 on 2026-10-03, during this pass, by the code owner — the
subprocess is now behind AX_RUN_GATE=1 and the script otherwise prints the
gate command for you to run yourself. This is the one number in this file that
was correct when written and became wrong an hour later.
Step 5 — check the work before you believe it
python3 tests/run_all.py
MEASURED — this is 21 min 12 s, not five minutes. It is deliberately
outside the five-minute path: the five minutes are for getting a neuron to
fire, and the gate is for deciding whether to believe anything. See Verify it
yourself below for the real output, its date, and its per-suite inventory.
The five minutes, honestly totalled
MEASURED:
| step | wall clock | blocking download |
|---|---|---|
| clone | seconds | the repository |
| step 2 — budget as an input | 0.04 s | none |
| step 3 — the inverse question | 0.06 s | none |
| step 4 — a neuron that fires | 75.2 s | 1.9 GB of TensorFlow, on a Python ≤ 3.12 environment |
What you can genuinely do in under a minute, with no install at all: run
python3 examples/02_budget.py and python3 examples/advanced/15_what_to_build.py on a bare interpreter with NumPy, and
get the entire planning surface — hardware profiles, the codec decision, the
precision arithmetic, the segmentation answer, the largest network a budget
buys, and the boundary that stops it.
What you cannot do in five minutes: train. Not because the code is slow — 75 seconds of compute — but because TensorFlow is a 1.9 GB download that needs a different Python than the one already on your machine. That download is the entire cost of the five-minute path, and no amount of documentation removes it.
The neuron is an abstraction, not a model of biology
Stated plainly, because the name invites the wrong assumption:
- The cell is a leaky integrator with a threshold. It is not Hodgkin–Huxley. There are no ion channels, no gating variables, no reversal potentials, and no spike-initiation mechanism.
- Adaptive thresholds and drive-gated leaks are still LIF-family. Calling them ALIF or adaptive-LIF would be a claim this interface cannot honour, so it is not done here.
- "Spiking" means the signal is a binary event and the gradient is an explicit surrogate, checked against finite differences on the smoothed model. The biological reading is a design analogy, nothing more.
- Nothing in this repository is a neuroscience claim. The honest summary: an integer-valued activation with a hand-written derivative, chosen because it makes the backward pass cheap to check.
Extending without forking
Neuron dynamics are an object, so a professional can replace them without touching the kernel, the backward pass, or the planner:
import tensorflow as tf
from axtf.cells import SpikingCell
class SaturatingCell(SpikingCell):
"""Membrane with a nonlinearity, so du/dstate is not the leak."""
def membrane(self, state, drive, thr):
return self.leak * state + drive - tf.square(state)
def membrane_dstate(self, state, drive, thr):
return self.leak - 2.0 * state
spec = ax.Model()
spec.add_spiking(192, horizon=64, cell=SaturatingCell())
spec.add_spiking(192, horizon=64) # a plain LIF, same network
Override a derivative hook only when you replace the function it belongs
to. spike_fn needs spike_d1; membrane needs membrane_dstate. If you
override one and not the other, the core builds a backward pass with a
derivative that does not match the forward pass and reports nothing. That is
the one thing it will not do: guess.
MEASURED — the gate's TF CORE suite checks membrane_dstate against
finite differences for four different membranes at rel.err between 1.06e-05
and 1.24e-04, and separately checks that the kernel calls the hook
(membrane_dstate called 7 times for T=7) and that a wrong
membrane_dstate breaks gradient entries (18/30 entries differ by more than 50%, worst 95.6%). See the gate block below.
The four places this codebase silently broke
Found by the gate, invisible to the eye, documented so they cannot return:
1. The 1/T normalisation. With a mean readout the maths requires
dL/ds_t = (1/T)·dL/dmean. Without it the gradient grows linearly with the
horizon and training diverges. It was completely absent from the TF kernel:
the parameter was threaded through four signatures and never applied. The
test that should have caught it re-implemented the backward pass inline and
compared it against itself.
MEASURED — the gate now checks both directions:
without 1/T grows 0.44x, with it 0.11x (same weights, so this is norm_t and nothing else), and T=4,8,16 -> 0.0186, 0.0094, 0.0021.
2. The time axis in compute_output_shape. _as_shape mistook a shape
tuple (None, 16, 24) for a list of layer inputs, because the batch dim is
None. Since the batch dim is always None, this was the common case, not
an edge case. Every Functional model broke.
3. Model input is not layer input. Calibration read model.inputs[0],
which for an embedding stem is the integer token tensor, not the activations
the layer receives.
4. The backward pass guessed a derivative. _lif_backward read
cell.leak as du/dstate. For a linear membrane that is accidentally
correct; for any other membrane it is wrong, and a user's cell had no way to
say so without forking the kernel. Fixed by adding
SpikingCell.membrane_dstate(state, drive, thr), which the kernel now calls.
The verification for that fix is the interesting part: finite differences are invalid on the hard spike, because it is a step function. The check therefore verifies the smooth membrane separately, counts that the hook is actually called, and compares gradients element by element — after sabotaging the kernel in the opposite direction and confirming the test fails.
Full account, including the mistakes made while finding all four:
docs/UX_RULES.md.
MEASURED note on the count: this list is four silent breaks of the
kind "no error, just a quietly wrong model". docs/UX_RULES.md:209 separately
enumerates five backward-pass and algorithmic errors the gate caught — a
(1−s) factor on the wrong term, an inverted time recursion, a dL/dthr with
no path through the reset, an early return in the DP, and a wrong tuple field
in the Pareto filter. Two lists, two scopes, nine bugs in total.
What is not built
Stated as absence, not as a roadmap.
| not built | what that means for you |
|---|---|
| a PyPI release | pip install axiomrnn does not work; use the checkout, or the local wheel by path |
| a byte-reproducible build | rebuilding the sdist yields a wheel of the same size but a different sha256 (zip timestamps, no SOURCE_DATE_EPOCH); two builds are not the same bits |
| a CPU-graph-native layer | run_eagerly=True is mandatory; tf.while_loop is not done |
| energy measurement | no neuromorphic device exists here; no energy number is measured by anyone on this project |
| speed measurement | not measured. Operation counts are not latency |
| the sparse/bit crossover point | measured by nobody, this project included |
| large-vocabulary quality | the T9 corpus is a smoke test, not a benchmark |
| a quality model | largest_that_fits is a capacity answer; the package has no verified accuracy model and says so |
| sub-segment graph partitioning | Segment has no notion of internal structure, so memopt-style splitting is not expressible |
| gradient rules that cut inside a segment | a segment larger than the budget is simply infeasible |
Known code-level limitations, all stated by the framework's own output:
run_eagerly=Trueis the default because Keras 3 caches a forward pass that contains a Python loop over time, and the gradient then lands on stale activations. The proper fix is atf.while_loop; not done.- The segmentation planner is optimal but almost always answers "no cuts",
because its peak is
stored + max_interwheremax_interis a floor. That is a property of the conservative model, not a bug.MEASURED—python3 examples/advanced/05_segmentation_planner.py:(0,4)→3.50G, 0 cuts;(0,2,4)→4.00G, 1 cut;(0,1,3,4)→4.50G, 2 cuts;(0,1,2,3,4)→5.00G, 3 cuts. Cutting the graph makes memory worse, and the planner agrees with brute force on 5 of 5 budgets. - Spike density is not a constant.
MEASURED— same run as the budget table:between tasks: 0.175 .. 0.324butwithin a net: 0.00 .. 0.83. A single mean is useless; the planner budgets the worst case.
Known limitations
These are the ones a reader will hit while trying this, as opposed to the ones they will hit at scale.
-
Bit-packing buys much less than the headline number suggests, and I could not reproduce the headline number.
FROM LITERATURE—16.8×on its own line, that line being0.16–0.32%of memory, so2.6–5.1%overall. These three figures appear only inside a block thatexamples/advanced/03_credit_rule.pyexplicitly labels "QUOTED, not recomputed in this script", and no command I ran prints16.8×. Whatexamples/advanced/04_budget_and_precision.pydoes print live is the codec table (reproduced inexamples/README.md), from which the shape of the claim is checkable: at firing rate0.25the bit codec uses124,780bytes, the sparse codec1,999,646, and ANS219,494— so sparsity is what costs, and past rate ≈0.5the bit codec wins because sparsity stops paying. One sentence explains the whole thing: binary activations do not make the gradient binary. The backward tape is much larger than the forward tape and is always dense, because the surrogate derivative is non-zero everywhere. -
The credit rule is a function of the horizon and the batch size, not a constant.
MEASURED—python3 examples/advanced/03_credit_rule.pyprints BPTT against e-prop at three scales and the ratio rises toward 1.0 asTgrows:config BPTT e-prop ratio L=8 h=1024 T=32 b=8 8.1 MiB 32.0 MiB 0.3x L=16 h=2048 T=64 b=16 129.3 MiB 256.0 MiB 0.5x L=32 h=4096 T=128 b=32 2069.3 MiB 2048.0 MiB 1.0xRead carefully: at
T=32, b=8the local rule is more expensive than BPTT. It pays only above a crossover batch that falls as the horizon grows —48, 24, 12, 6, 3forT = 16, 32, 64, 128, 256(MEASURED, same run). Any single "e-prop is Nx cheaper" figure is a number without itsTandb, and this file will not print one. -
The local rule's quality price is real and large.
MEASURED— same run:T=60 -> 85.5%of full BPTT,T=500 -> 38.9%, a 47-point gap. Beyond the measured range the API returnsNonerather than extrapolating, because a linear extrapolation would read0.0atT=1024and look like a claim that the local rule is useless. It simply is not known. -
A readout that averages over time destroys temporal tasks. This is not about spiking; it is the readout.
MEASURED—python3 examples/04_equal_budget.pycompares four readouts on one task; the numbers are inexamples/README.mdwith the command. -
A Keras model is not reproducible across two builds unless you assign seeds explicitly; the NumPy core and the planner are bit-exact under a fixed seed.
MEASURED—python examples/advanced/08_reproducibility.py. -
The gate proves less than its length suggests, and here is exactly where. See the gate block below.
Verify it yourself
python3 tests/run_all.py
Real output, produced 2026-10-04 at 00:09 MSK, 21 min 12 s wall clock,
CPU only (CUDA_VISIBLE_DEVICES=), TensorFlow 2.21.0, exit code 0:
SUMMARY
==========================================================================
[ OK ] GATE (numpy core, gradient proven)
[ OK ] PLANNER (DP optimal vs brute force)
[ OK ] MEMORY MODEL (31 tests, Korthikanti)
[ OK ] CREDIT RULES (e-prop vs BPTT, quality price)
[ OK ] TF CORE (gradient, normalisation, custom cell)
[ OK ] KERAS ASSEMBLY + training via keras.fit
[ OK ] API AUDIT (every advertised function called)
[ OK ] C++ KERNELS (bit-packing, layout)
[ OK ] EXAMPLE 02 (budget, NO TensorFlow)
[ OK ] EXAMPLE 01 (train a network)
[ OK ] EXAMPLE 03 (custom neuron, no fork)
[ OK ] EXAMPLE 05 (T9 next-word prediction)
[ OK ] ADV 01 (embedding + stacked layers)
[ OK ] ADV 02 (horizon sweep)
[ OK ] ADV 03 (credit rule, the real lever)
[ OK ] ADV 04 (budget, codec, precision)
[ OK ] ADV 05 (segmentation planner)
[ OK ] ADV 06 (devices: CPU and GPU)
[ OK ] CAPACITY SOLVER (axplan.solve)
[ OK ] ADV 15 (what to build: the inverse question)
[ OK ] ADV 07 (silence diagnosis)
[ OK ] ADV 08 (reproducibility)
[ OK ] ADV 09 (API tour)
[ OK ] ADV 10 (save and load)
[ OK ] ADV 11 (derivative hooks)
[ OK ] ADV 12 (failure modes)
[ OK ] ADV 13 (when not to use)
[ OK ] ADV 14 (budget matrix)
==========================================================================
ALL GREEN. Results may be published.
Twenty-eight suites. An earlier version of this file said twenty, and an
earlier version still said eighteen inside examples/02_budget.py and
examples/advanced/02_horizon_sweep.py. All three were wrong. The count is
28 and the date is above.
What the gate actually examined, and what "OK" is worth
Rule 6: a green that verified nothing is a failure, so here is the inventory
per suite rather than the word "green". MEASURED — parsed from the same
run:
| suite | declared checks | wall |
|---|---|---|
| GATE (numpy core, gradient proven) | 12 | 1.7 s |
| PLANNER (DP optimal vs brute force) | 12 | 0.2 s |
| MEMORY MODEL (Korthikanti) | 38 printed, label says 31 | 0.0 s |
| CREDIT RULES (e-prop vs BPTT, quality price) | 23 | 0.1 s |
| TF CORE (gradient, normalisation, custom cell) | 20 | 6.7 s |
KERAS ASSEMBLY + training via keras.fit |
45 | 73.9 s |
| API AUDIT (every advertised function called) | 119 (SKIPPED 0) |
4.4 s |
| C++ KERNELS (bit-packing, layout) | 5 printed, no aggregate | 2.8 s |
| EXAMPLE 02 · 01 · 03 · 05 | 0 surfaced | 0.1 · 190.9 · 84.6 · 770.1 s |
| ADV 01 · 02 · 03 · 04 · 05 · 06 | 0 surfaced | 41.3 · 0.2 · 0.1 · 0.1 · 0.0 · 5.7 s |
| CAPACITY SOLVER · ADV 15 | 0 surfaced | 0.1 · 0.1 s |
| ADV 07 · 08 · 09 · 10 · 11 · 12 · 13 · 14 | 0 surfaced | 54.3 · 2.2 · 3.2 · 23.2 · 2.1 · 3.9 · 0.0 · 0.0 s |
269 declared checks across the seven suites that report a count, and
1272 s of suite time. One suite, EXAMPLE 05, is 61% of the whole gate.
One artefact of running it, so nobody is confused by it. The gate writes its
pid into tests/.gate.lock and holds an flock on that file for the duration.
flock is tied to the file descriptor, so the kernel releases it even if the
process is SIGKILLed — the lock cannot go stale the way a lockfile normally
can. The text in the file can still name a dead pid, and after that run it
reads pid 1411367. That string is harmless and blocks nothing; a second
gate refuses only if another process genuinely holds the descriptor, and then it
exits 2 and says so.
Three honest caveats, all MEASURED from that run:
- The four
EXAMPLEsuites and the fifteenADVsuites print zero check lines.tests/run_all.py:150-154filters suite output down to lines containingPASS/ok]/Error/Traceback/SKIPPED, and the examples print none of those. For those nineteen suites an[ OK ]attests only that the process exited 0. It does not surface the example's own numbers, and it cannot catch a wrong number — only a non-zero exit. - One example is not in the gate at all.
examples/04_equal_budget.py— the honest spiking-versus-dense comparison, the single most-quoted measurement in this repository — is not a suite, even thoughtests/run_all.py:86-89says "every example is now a suite". Nineteen of the twenty examples are covered;04is the exception. Reported to the owner; documented here rather than papered over. - The MEMORY MODEL suite's label undercounts itself. It is named
(31 tests, Korthikanti)and prints 38[ok]lines. The label is stale.
The gate is not optional. No result here is published until it is green — a rule adopted after three consecutive experiments looked convincing and were wrong. But a green is only worth its inventory size, so the inventory size is printed above.
Documentation
docs/GETTING_STARTED.md |
the same five-minute path, expanded |
examples/README.md |
all 20 examples, each with its real output and the command that produced it |
docs/ARCHITECTURE.md |
what we deliberately do not build, and the four packages |
docs/UX_RULES.md |
20 rules, each grown from a specific failure |
docs/ATTACKING_THE_QUADRATIC.md |
an independent attack on the premise: replacing the KV cache with a spike-gated fast-weight state |
docs/DESIGN_LOG.md |
the original design record (Russian, unedited) |
License
Apache-2.0. See LICENSE.
Metadata
Release files for axiomrnn 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| axiomrnn-0.1.0.tar.gz | 440.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| axiomrnn-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 511.1 kB
Release files / axiomrnn-0.1.0.tar.gz
| Download URL | axiomrnn-0.1.0.tar.gz |
|---|---|
| Size | 440.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6c235292beda9ad54b1a54de3004968d0003c752815231ec4602a853144dfae6
|
|
BLAKE2b-256 checksum How to use checksums |
fd95b5293f90c8a5a5c400da730642f405f41260bd7769fa68ba9193d3df31f8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.
Transparency logRelease files / axiomrnn-0.1.0-py3-none-any.whl
| Download URL | axiomrnn-0.1.0-py3-none-any.whl |
|---|---|
| Size | 70.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ba2c362f1803abcb084c1c450c916fe0c29ce57abec0a7f01726c50ca1b0610d
|
|
BLAKE2b-256 checksum How to use checksums |
246ce638758042049f861b1310f3095b9e38ee75d72cdde12aa22af2d21edf1b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.
Transparency log