RESONATE / RESEARCH / ACT II GitHub
Research statusWork in progress, September 2026. One seed, one consumer GPU, self-reported, negatives kept in; nothing here is filed on a leaderboard. This page continues Act I, which measured the representation on three Stanford boards. Here we ask what else the same memory can do, and tell it in the order it happened.

Independent research / 2026 / Act II

A memory
that computes.

Act I trained a compact graph representation — unit-norm rows and block-diagonal relation operators — to predict links. Act II keeps that memory exactly as it is and asks two questions of it. Numbers: can it hold and compute with numbers it never stored, and take instructions in words? Reasoning: can it follow chains of facts it has never seen? Yes to both, within limits we list — and one clear no.

What we did, in order →
ONE GPU (1080 Ti)ONE SEEDNO LLM ANYWHERENEGATIVES INCLUDED
parameters that hold every number below 10²⁴
12k
eleven rows and one move; a number is a chain of its digits, read back exactly to 24 digits.
worked examples per operation
3
add, subtract, compare, multiply — each found, exact on lengths never shown.
"to double something, add it to itself."
1.00
commands and definitions in words, on numbers and names never shown.
CLUTRR, ten hops, from the graph
0.99
1,146 test stories, trained on 2–3 hops; 0.988 ± 0.008 over ten seeds; wrong ≤ 1.2 % at 4–10 hops, 2.2 % at three (the ambiguous chain); 41k parameters. From raw text: a negative, below.

00 / The map

What we did, in order

Two tracks on the same memory. Each step is one experiment with one number; the sections below give each step its own page. Green is a result we can defend; brown is a negative we keep.

Track one

Numbers

The question: can a memory that stores sixteen symbols hold every number, compute with them, and take its instructions in words — without any number ever being written into it?

Step 01Numbers as places

We did
Stored only the digits 0–9 and the place anchors 10, 100 … 10⁶, with two relations, + and ×. To reach 347 the memory walks: three × hundred, + four × ten, + seven. The result is a point in the same space as the sixteen rows — computed, never written.
3×100+4×10+7→a place for 347
We found
Walking the chain back — one reverse hop, one light over the sixteen rows per step — reads every digit of numbers never seen in training. Growing is a continuation: to a billion with two more anchors, to a trillion with three more (513 s), the operators allowed to keep learning while old numbers are replayed; freezing the operators and adding rows alone fails (0.000): depth lives in the operator, not in rows.
Then
The place rows were the last hand-placed structure, so we removed them. A number is now a chain of its digits under one repeated move, built onto an END symbol: eleven rows in all, no row per magnitude, no fixed length. The move is trained on random digit strings with the same walk-back objective — no labels, nothing arithmetic. Reading back is the move in reverse, one digit per step, until END lights. Width sets how deep such a chain can go (16 dimensions hold 6 digits, 64 hold 13, 144 hold 24 — roughly a third of the dimension), and training sets the depth reached within that: all widths from 144 up are exact through every trained length and fall off just past it.
memorydimensionsparametersread-back exact to
digit chain, k = 4161,3776 digits
digit chain, k = 8644,67313 digits
digit chain, k = 1214412,38524 digits (all trained)
digit chain, k = 2040034,40124 digits (all trained)
anchored table to 10¹², k = 1214424,48112 digits
Number
1.000 on unseen numbers to 24 digits from 12,385 parameters · comparison 1.000 on 6,000 unseen pairs at every distance
Kept
Our first version let the anchors superpose and read 347 as 437 (cosine 0.993): superposition keeps what is present, direction keeps what is paired with what. Learning = as a relation fails at everything — evaluation is a light over the memory, not a move in it. And the 144-dimensional digit chain read random strings exactly to 24 digits while misreading runs of nines from length 9 — a pattern random training strings never show; test the patterns sampling never produces. To be explicit about which checkpoints carry it: the published k = 12 chain has this fault; the k = 20 chain that the programs, the digit-sum and parity results run on reads every run of one digit correctly (checked for all ten digits at length 24), as does k = 32; the trainer now samples runs, and the seeded reruns use it. The sentence memory of the language layer had the same fault on numerals like 4444444; retrained with runs in its training strings, it reads them correctly (4444444 → digit sum 28, 999999999 → 81) and the language-layer results above were re-established on it.

Step 02Operations found from three worked examples

We did
Built a small machine over the memory: six slots that hold places, and a dozen primitives of three kinds — moves (walk a place one step, bind two values, call a program), lights (read a slot against the 0–19 line, the times table, the digit order), writes. Nothing in it knows what a carry is. Showed it three worked examples of an operation (the steps of 12+11, 383+47, 19+65) and searched for a program whose loop reproduces them, accepting only if exact on cases two digits longer than any shown.
We found
Addition at generation 1, subtraction, comparison and single-digit multiplication likewise, multiplication at generation 5 as calls to the ones below it. Each exact at every length tested. The controller must keep no state of its own — with the verdict kept in a hidden state, comparison generalised to 0.24 at nine digits; with it in a slot, 1.000.
# addition, as found from the three traces
body  LOAD 0>3  LOAD 1>4   # one place back, each
      BIND 3,4  BIND 3,2   # digit ⊙ digit ⊙ carry
      READ 3               # light on the 0..19 line
      SETD 5  SETC 2       # digit out, carry kept
      WRITE 5              # next digit of the result
Number
add, sub, cmp, muld, mul: 1.000 at 1–9 digits (4–9 never shown) — and, byte-for-byte unchanged, 1.000 at 1–24 digits on the digit chain, a representation that did not exist when they were found; blank-slate search: nothing
Kept
Searching from nothing has no slope — the six-instruction core earns no credit until complete. Nobody discovers addition; one is shown a few worked examples. And a found program can have a hole an acceptance test never sampled: our first addition dropped the top carry when the second operand was shorter (99+1 = 0); the first digit-sum program found on the chain wrote a constant 0 for the hundreds, exact on every number it had been shown. Both fixed by sampling the failure patterns explicitly, and re-found. Two more operations found on the chain from three examples each: double (a call to the found addition with the same operand twice) and digit sum (a new three-accumulator structure).

Step 03Programs stored in the same table

We did
Bound each instruction to four role relations into one place, chained four instructions into a page, and continued the number table with the instruction rows: one table, one +, one ×, for numbers and procedures.
We found
The five found programs walk back from their pages identically and execute from memory; numbers still walk back exactly after the continuation; a new program's name is a freshly appended row and a call to it reads back with no training. Adding a skill is a write.
Number
1.000 for all five programs executed from the one memory, at 1 / 3 / 5 / 7 digits

Step 04Instructions in words

We did
Made every word a row — the ten digit words and a few function words stored, any new word a fresh row — and a sentence a chain of word places, read back by walking. A numeral is read digit by digit; the number is the place its digits walk to. Then searched for a reader: a program that walks the sentence, lights each word (is it a digit? a program's name? "from"?) and either calls a found program or defines a new one.
We found
Commands work on numbers and filler words never shown; a definition names a program the next sentence can call:
add 3421 and 57 .                            → 3478
please subtract 9114 from 95365 .            → 86251
compare 99 and 100 ?                         → smaller
to double something , add it to itself .     → (defined double)
double 34324 .                               → 68648
frobnicate 12 and 7 .                        → (nothing called)
Number
1.00 on 1–7-digit numbers (train 1–3), 0–4 fillers (train 0–1), unseen definition names and bodies
Kept
Number places must not be sentence tokens — they are near-parallel as vectors (cos 0.98) and no light can tell two apart. Digits as words removed the problem. And "found at generation 1" here means the search selected the reader from the worked traces; discovery from answers alone is not shown.

Track two

Reasoning

The question: can the same memory follow a chain of facts it has never seen — first in a synthetic world, then on a benchmark, first from its graph and then from its text?

Step 05A story memory

We did
A fact is one place, subject⊗SUBJECT + relation⊗RELATION + object⊗OBJECT, with three role relations trained once on random triples (25 seconds). A story is a set of such places in working memory; the names are fresh rows the memory has never seen. The machine gained one read — the fact keyed by a name and a relation, verified by reading its subject and relation back, a light and never a threshold — and the search was shown three worked stories of at most three links.
We found
The chain-following program, the YES / NO / UNKNOWN decision that calls it, and the program that refuses to propagate a non-transitive relation, each found at generation 1.
Number
1.000 on chains of 1–10 links with fresh names (only ≤ 3 shown)

Step 06CLUTRR from the graph

We did
CLUTRR (Sinha et al., 2019): given a chain of family relations — Ann's mother's brother's daughter — what is Ann to the last person? Training stories have 2–3 hops, test stories 2–10. We took the benchmark's graph form (the relation sequence along the path), the setting of the strongest published systems. Each of the twenty relation words became a learned operator; a training story says only "applying the chain's operators to any random place must land where the target word's operator lands". No rules, no genders, no meanings.
We found
The product of the operators answers ten-hop questions after seeing two and three. The remaining abstentions are the benchmark's own ambiguities: all fifteen at length 3 are one chain, wife → son → grandmother — either mother or mother-in-law, and the test set labels it both ways, ten to five.
Exact answers at ten hops, trained on 2–3, graph input, full test set. Published rows from Minervini et al. 2020; ours is the mean of ten seeds, 119 stories at ten hops, and abstains on the 1 % it does not answer (no wrong answers at ten hops). Controls: shuffled training targets → 0.00 exact, 1.00 abstain; the model sees only the relation-word sequence; no test chain of three or more words occurs in training.
hops2345678910
exact38 · 1.0090 · 0.86189 · 0.99172 · 0.99106 · 0.99143 · 0.99148 · 0.99112 · 0.94118 · 0.99
abstain015 · 0.141 · 0.010002 · 0.017 · 0.061 · 0.01
wrong0002 · 0.011 · 0.011 · 0.01000
exact, ten seeds1.00 ± .000.89 ± .041.00 ± .000.99 ± .000.98 ± .010.99 ± .010.99 ± .010.98 ± .010.99 ± .01
wrong, ten seeds0.000.02 ± .020.000.01 ± .000.01 ± .010.01 ± .010.000.000.00 ± .01

A note on every "1.000" on this page: it means every sampled case was exact — n fresh cases per length (60–400), plus a fixed regression set of the carry and unequal-length patterns — which is sampled exactness, not a proof over all numbers. First three rows: seed 0 — counts, then fractions of the stories at that length; 1,146 test stories in all. Last two rows: mean ± standard deviation over seeds 0–9 (ten-hop exact per seed: 0.99 0.98 0.98 0.98 1.00 0.99 1.00 0.99 0.98 0.98 → 0.988 ± 0.008). k = 8 (64-dimensional places, four 16×16 blocks per word, ~20k complex parameters), 20,000 steps, 64 probes. Every remaining miss is a chain with two logically valid answers — wife → son → grandmother is a mother or a mother-in-law, … → daughter → sister a daughter or a niece — and the model's two top words are exactly those two, 0.00–0.05 apart; kinship is one-to-many and the benchmark labels one member.

Number
0.99 exact at ten hops (0.988 ± 0.008 over ten seeds); wrong, ten-seed mean: ≤ 0.012 at 4–10 hops, 0.022 ± 0.023 at three hops (the chain the benchmark labels both ways); 41,473 parameters · best published on this split: CTP_A 0.90 · at 16 dimensions (10k parameters) still 0.87
Kept
Before this we spent three hours hand-writing a kinship algebra; the words came out right and every rule we touched made generalisation worse. Do not write the algebra.

Step 07 — negativeCLUTRR from raw text

We did
Put a reader in front of the same reasoner. The text is crowd-written: 4,620 sentence templates in training, 1,423 of the 1,438 test templates unseen. We built four readers: cue rules over the sentence chain (relation word, names, 's / of for direction); a sequence model over the story; a local classifier over windows around each relation word; the cue reader with a table counted from the training data. Each turned sentences into facts; the facts went to the operators of step 06.
We found
The cue reader reads the English correctly for 0.96 of clean sentences on unseen templates. Yet every reader stops at the same wall — about 0.55 precision against the gold facts — and the pipeline abstains on nearly everything rather than guess. The wall is in the benchmark: the gold graph writes the same reading in a template-dependent form. "A's son B" is (A, son, B) in 900 training sentences and (B, father or mother, A) in 378; fixed within a template, unpredictable across templates, and the test templates are unseen. Add facts split across sentences by pronouns, synonyms outside the twenty words, and 4 % of templates that contradict their own graph, and a ten-hop path is intact for 0.39 of test stories at best.
Number
0.08 exact / 0.02 wrong / 0.90 abstain overall from text · gold facts through the same pipeline: 0.97
Kept
Why step 04 worked and this does not: a controlled grammar (one fact per sentence, local cues, closed vocabulary) versus real text. The memory and the chain are not what failed. The fix this points to is in the reasoner, not the reader: a fact should be usable in whichever form the text gives it, which needs the reverse of an operator to be its exact inverse — kept unitary by construction. Free reverse hops learned nothing; the adjoint drifted. That is the next experiment.

What we learned

Five principles, each bought with a negative

What we can and cannot conclude

Observed, and not established

Observed

  • Unseen numbers to 24 digits composed, decomposed, compared, added and multiplied exactly from eleven rows and one move (12k parameters); programs found on the anchored 10⁹ table run unchanged on the digit chain.
  • Five arithmetic and three logic programs induced from three worked examples each, exact on lengths never shown; commands and definitions in words on numbers and names never shown.
  • Ten-hop CLUTRR from the graph at 0.99 exact; wrong ≤ 1.2 % at 4–10 hops and 2.2 % at three hops over ten seeds, the abstentions and most of the wrong answers traceable to the benchmark's ambiguities.
  • From raw text, a negative with a located cause.

Not established

  • Seeds: the CLUTRR headline now has ten (0.988 ± 0.008 at ten hops); the arithmetic and program-search tables are still one seed each.
  • The machine's primitives and the word → program aliases are ours; the programs are found, the instruction set is not. "Found at generation 1" is selection from worked traces, not discovery from answers.
  • Baselines we owe on the same tasks: an NPI-style program-induction baseline and a VSA / holographic baseline.
  • Reading real text: open. The graph-to-text gap is where the work is, and it is a different problem from the memory.
  • No real-graph result yet (compositional queries on wikikg2 / biokg) to connect this page to Act I's tables.

Code, found programs, run logs, result files and the working paper log for this part: github.com/jinxmcg/resonate2. The CLUTRR result reproduces from a clean clone in under six minutes on a GTX 1080 Ti (clutrr_prepare.py, then kinship_ops.py); resonate.py is imported from Act I's repository unchanged.