~/satyajit

Sketchpad: certified exact arithmetic from a 0.8B model that only sees three cells

mdjsonmcp

2026-11-12 · 28 min · formal-methods · math · verifiers · small-models · lora · vision-language-models · webgpu · reasoning

A 4:34 narrated explainer, drawn in code. Every number and picture in it is this article's own; the sources are below.

› transcript

Add one to a long row of nines, and every column flips. Why do language models lose that carry? And how does a tiny model never lose it? Hi, I'm Zephyrine! This is Sketchpad: exact long arithmetic from a tiny model, with a certificate. Chapter one. Why the carry gets lost. A model trained on short sums usually struggles on long ones. The literature points at three suspects. Position. A model trained on twenty-digit sums has never seen column three hundred. The carry. One carry can depend on every digit to its right, and a forward pass has fixed depth. Chain of thought writes steps down. But step nine hundred reads nine hundred steps of history nobody tested. Chapter two. A sheet and a window. The system has three parts. The sheet holds everything: operands, carries, the answer. The runtime crops one column, three cells tall. Qwen three point five, zero point eight billion, with a small adapter, reads that strip as an image. Nothing else is in its prompt. It answers a digit, a carry, and the next operation. Plain code paints the answer and moves the window. The model is the transition function of a Turing machine. The project's own animation. The window reads three cells of one column. The model answers a digit, a carry and the next step. The runtime stamps it, and the window moves on. Here's the hard case, the one that breaks a fixed-depth forward pass: nine nines, plus one. The window shows the first column: no carry, a nine over a one. The model answers one token. a means digit zero, carry one. The runtime writes the zero, puts the carry one column left, and moves. Now the view is a carry over a nine. Same kind of step, again and again, all the way along. The carry chain is never computed inside one pass. It is written on the sheet. The last column is just the carry. Then all three cells are blank, and the model says halt. Chapter three. Checking every view. Here's the idea. Every step reads only a three-cell view. So checking every possible view checks every run, of every length. In addition, the carry is blank or one, and each digit cell is blank or a digit. Two hundred and forty-two views, at any length. Multiplication's five tables add one thousand five hundred and fifty-three. Subtraction, estimation for division, and a decrement add six hundred and fifty-one. Two thousand four hundred and forty-six views, in all. Every step has the same shape. The runtime shows a view, from a finite list. The answer depends on that view alone. So matching the table on every view means matching every run, step by step. Checked means a margin. Every view is scored on the device, and each must put the right token ahead. All two thousand four hundred and forty-six pass. The weakest, five plus six, leads by three point zero two logits. Why not just test sums? The article broke that one view. Ten-digit sums still came out right ninety-four percent of the time. Enumerating the views catches it with certainty. Chapter four. What the proof covers. Chain of thought grows its context. No finite test certifies it. The pinned sheet has a fixed list of inputs. Check them all. The paper proves it in Lean: the model's run equals the reference run, for every length, if and only if it agrees on every view. And when a step can read its own history, a decoder can pass every test up to some length, then fail just past it. So what did Lean prove? A chain of three links, and only the middle one is formal. The model is right on every view: a measurement, on one GPU path. Right on every view implies right at every length: the Lean theorem. And the runtime only ever shows table views: assumed, and asserted at every step. Bound what each step can see, and exactness at every length becomes a finite list you can check. Three cells in, one step out. Check every view, and induction does the rest. Thanks for watching! Every source is in the full article. I'm Zephyrine. Bye!

Why read this

Solidtop 85%

Separates what Lean proves, what the certificate measures and what the runtime assumes, with the real 242 margins and a sheet you can break.

  • Original analysis
  • A lasting reference
  • A new technique

Evals & benchmarksRuns in a browserMixed licencesResearch paper

How this was scored
Is it new?
2 of 3: A real new idea, method or capability
Can I trust it?
2 of 3: Measures key facts from files, code or configs
Can I run it?
1 of 3: API-only, gated or restrictive licence
Will I understand it?
2 of 3: Mechanism from first principles with figures
Can I act on it?
1 of 3: General advice
Will it last?
2 of 3: A reference for a year or more
Does it affect many?
1 of 3: A specialist community
Only here?
2 of 3: A teardown or measurement few others did

Score 59 of 100, ranked 456 of 740 rated articles. Each question is answered 0–3 by hand, and a 3 is rare. How articles are scored

A post on X this week put it in one breath: a 0.8B-parameter model doing arithmetic that is "provably exact at every input length, proven in Lean", and the conclusion that "small models plus external memory become certifiable machines". The source is Sketchpad (arXiv 2611.04434), a single-author paper by Mostafa Mohsenvand of the MIT Media Lab, with its code, paper sources and Lean proofs in NeoVand/sketchpad and the model on Hugging Face as mohsenvand/sketchpad-0.8b-preview.

The result is real, and it is a cleaner idea than the post makes it sound. Nobody proved anything about the weights of a neural network in Lean. What Lean proves is a short, general fact about any machine that is built a certain way. The paper's contribution is to build a vision-language model that way, then measure the one thing the general fact needs from the network, on the exact GPU path that runs it. Where the guarantee lives, and where it stops, is the whole story, so that is what this piece is about.

Why a transformer loses the carry

Long addition is the cleanest test of length generalisation there is. The algorithm is tiny, the training data is unlimited, and a model that has learned it should add 1,000-digit numbers as easily as 10-digit ones. Transformers trained on short sums mostly do not, and the literature has spent five years on why.

The first suspect is position. A model trained on sums of up to 20 digits has never seen the positional signal for column 300, and with absolute position embeddings that column is out of distribution in the most literal way. Nogueira, Jiang and Lin showed that the surface format alone (how digits and their positions are written) swings accuracy enormously. The later fixes all attack alignment: Abacus embeddings give each digit a position relative to the start of its own number, and position coupling gives digits of the same significance the same position id, so column ii of the top number and column ii of the bottom one line up whatever the length. Relative schemes like RoPE do not by themselves tell attention which digits belong together.

The second suspect is the carry. One carry can depend on every digit to its right: 999…9+1999\ldots9 + 1 flips every column. A transformer with LL layers runs a fixed amount of sequential computation per output token, so a model that tries to emit the answer digit in one pass has to resolve a carry chain of arbitrary length inside a fixed-depth circuit. Hardware solves this with carry-lookahead, which needs depth logarithmic in the length; a network trained on short sums has no reason to discover a circuit that keeps working when the chains get longer than anything it saw. Zhou et al. titled their result accordingly: transformers can achieve length generalisation, but not robustly, with results that vary across random seeds and data orders.

The standard way out is to write the intermediate steps down. Scratchpads and chain of thought turn one hard forward pass into many easy ones, each of which only has to handle a single column. It works, but each step now reads a context that grows with the problem, so step 900 depends on 900 steps of history nobody tested, and benchmark accuracy stays an estimate.

Sketchpad keeps the scratchpad and takes the history away.

A sheet, a window, and nothing else

The system has three parts.

The sheet is a grid of 32-pixel cells, each blank or one of ten digit glyphs, drawn from a fixed sprite set. It holds all of the state: operands, carries, partial products, the answer.

The model is Qwen3.5-0.8B with a rank-16 LoRA adapter. At each step it sees a prompt made of an operation token (SUM, MUL, SUB and so on), a 32 by 96 pixel image of three cells, an = and two placeholder tokens. The vision encoder turns the strip into three image tokens. The model's answers are read at the = and the two placeholders, in one forward pass: a digit, a carry or borrow, and the name of the next operation. The prompt contains nothing else. The paper calls this the pinned-sheet policy.

The runtime is ordinary code, a few hundred lines per procedure. It lays out the operands, crops the view, calls the model, paints the outputs onto the sheet and moves the window. It copies digits (bringing one down in long division, say) but by design writes no digit of a result.

If you want a classical frame, this is a Turing machine with the parts relabelled. The sheet is the tape. The runtime is the head and the outer control loop. The network is the transition function: a pure map from what is under the head to what to write and where to go. Its output is a function f(v)f(v) of the view vv and nothing more.

One view in, one step out: the window reads three cells, the model answers a digit, a carry and the next operation, and the runtime writes them and moves on. This is the project's own animation of its machine (sketchpad-loop.mp4 in the Sketchpad repository).
Three panels. Panel a: one step of the long multiplication 74,829 times 6,153; a three-cell view (8, 1, 0) enters Qwen3.5-0.8B as three image tokens after the operation token MUL, and the model outputs digit 8, carry 0 and next step A, which the runtime stamps onto the sheet; below, the 56-step operation sequence. Panel b: heat maps of the margins of all 2,446 views grouped by table, with the weakest view, SUM 5 plus 6 with no carry, at 3.02 logits. Panel c: bar chart of exact answers on 220 problems, Sketchpad at 100 percent, GPT-6.1 Sol at 98.6, Claude Opus 5.5 at 98.2, Gemini 4 Argon at 94.1, open models from 90.5 down to 67.7, Qwen3.5-27B at 55 and Qwen3.5-0.8B at 10.5.
One step of a long multiplication, the margins of every view on the deployment device, and the 220-problem comparison. The bars in panel c are the paper's runs, each model run once per problem (Sketchpad paper, Figure 1).

Addition shows the shape best. A view is one column: the carry cell above the top digit above the bottom digit, each blank or a glyph. The answer is the column's digit and carry, which the addition adapter emits as a single token: 0 to 9 for a digit with no carry, a to j for digit 0 to 9 with a carry, and H to halt when all three cells are blank. The runtime writes the digit under the column, writes the carry one column to the left, and moves the window left. The widget below is that machine, with the exact table standing in for the network.

Step through 999999999 + 1. The carry chain that defeats a fixed-depth forward pass is no problem here, because it is not computed inside any one pass. It is written onto the sheet one column at a time, and each step only has to know how to add three small things.

Why 2,446 checks cover every length

Count what the model can ever be shown. In addition, the carry cell is blank or 1, and the top and bottom cells are each blank or a digit: 2×11×11=2422 \times 11 \times 11 = 242 views. That number does not depend on how long the operands are. A 10-digit sum and a 10,000-digit sum are both sequences of views drawn from the same 242.

The paper's tables cover nine operations. I recounted them from their definitions in the paper's Methods and Extended Data Table 1 with a short script of my own, and the counts come out exactly:

TableWhat the view holdsViews
SUMcarry (blank, 1) · top · bottom (blank, 0-9)242
MULmultiplicand digit (blank, 0-9) · multiplier digit · carry (blank, 0-8)1,100
ADD, ADZcarry · partial-product digit · running-total digit220 each
FLS, NXTflush the final carry; fetch the next multiplier digit2, 11
SUBborrow · top · bottom242
ESTleading remainder digits and the divisor's leading digit400
DEClower a quotient guess by one9

That is 242 for addition, 1,553 for the five multiplication tables and 651 for subtraction, estimation and decrement: 2,446 in all.

Now the argument. Write ctc_t for the configuration at step tt (the sheet, the window's position, the control state). The runtime either halts or shows the model view(ct)\mathrm{view}(c_t) and paints what it says:

ct+1=paint(ct,  f(view(ct))).c_{t+1} = \mathrm{paint}\big(c_t,\; f(\mathrm{view}(c_t))\big).

The reference run is the same recursion with the correct table TT in place of ff. Suppose f(v)=T(v)f(v) = T(v) for every view the reference run can reach. Then by induction on tt: if the model's run and the reference run agree at ctc_t, they show the same view, the model gives the table's answer, and they agree at ct+1c_{t+1}. They agree at c0c_0 trivially. So they agree at every step of every run, for inputs of any length.

That is the paper's Theorem 1, and it is the whole trick. The induction is over steps, not over digits, and it goes through because the step function has a finite domain. The converse also holds when painting is injective (different answers produce different sheets): if the runs agree everywhere, the model must be right on every view the reference run shows it. So exactness at all lengths is equivalent to exactness on a finite list, and a finite list can be checked.

"Checked" means a margin. At output position kk of view vv, with logits zk(v)z_k(v) and correct token Tk(v)T_k(v),

m(v)=min⁡k(zk(v)Tk(v)−max⁡a≠Tk(v)zk(v)a),m(v) = \min_k \Big( z_k(v)_{T_k(v)} - \max_{a \neq T_k(v)} z_k(v)_a \Big),

taken over the full 248,320-token vocabulary. A view passes when m(v)>0m(v) > 0, so the argmax is the right token under any tie-breaking rule. The certificate is a file listing m(v)m(v) for all 2,446 views.

I downloaded it. arithmetic/certificate.json in the model repository was produced on Apple metal-3 on 31 October 2026 with transformers.js 4.2.0, a 4-bit embedding and 16-bit vision encoder and decoder, and it binds itself to the model files by hash. All 2,446 rows pass. The smallest margins per group are 3.016 for addition, 6.516 for multiplication and 4.609 for the calculator tables, which round to the paper's 3.02, 6.52 and 4.61. The median over all 2,446 is 12.766 logits, and only one view sits below 4.

The certificate being computed: every view of every table scored on the device, one cell at a time. The project's own screen recording, from sketchpad-loop.mp4 in the repository; the margins themselves are in the certificate file discussed above.

The weakest row is row 73 of the addition table, which in the repository's row order (carry, then top, then bottom, blank first; ADD_DOMAIN in src/lib/sketchpad/adder.ts) is 5 over 6 with no carry in. The model has to answer b: digit 1, carry 1. The next weakest is 5 over 5, at 5.266. Both are sums that just cross ten, and the third-weakest row in the table is already at 7.906. The 40 views that only operands of unequal length can reach (one of top and bottom blank) are comfortably safe: their lowest margin is 10.016.

That also lets me check the paper's Figure 3a, which says sums of equal-length operands reach 202 of the 242 views and the other 40 need numbers of unequal length. I simulated the addition sheet in Python with the table as the controller, on 600 random equal-length sums from 1 to 1,024 digits and 3,000 sums whose two operands each had a random length of up to 60 digits. Every result was exact against Python's integers, as it must be for the table. The equal-length runs touched exactly 202 distinct views, and adding the unequal ones touched all 242. The paper's nine sums are not published, so this is my own run of the same construction rather than a reproduction of theirs, but the counts agree.

What Lean actually checked

The proofs are in paper/lean/ of the repository: about 2,560 lines across Sheet.lean, Paper.lean and five files under Sketchpad/, on Lean 4.35.0 with Mathlib. A search for sorry, admit, axiom and native_decide finds only one hit, the docstring in Sheet.lean that says there are none. The paper reports that #print axioms lists only propext, Classical.choice and Quot.sound. I read Sheet.lean in full and the statements of the Theorem 2 and caching lemmas in Unpinned.lean and Pinned.lean. I did not build any of it: a Mathlib build is several gigabytes and this machine is short on disk.

The pattern matches what this site found with the Lean-checked AES circuits and the openai/math release: a green tick certifies exactly the statement on the page, and the work is reading what that statement assumes.

Here is the heart of it, from Sheet.lean at commit 03bb36b:

variable {C V A : Type*}
 
theorem sheet_certified {query : C → Option V} {paint : C → A → C} {f T : V → A} {I : Set C}
    {W : Set V} (hW : reachedViews query paint T I ⊆ W) (hcert : ∀ v ∈ W, f v = T v) :
    ∀ c₀ ∈ I, ∀ n, trace query paint f c₀ n = trace query paint T c₀ n

Read the types. C, V and A are arbitrary. There is no Qwen in this file, no sheet layout, no digit and no logit. f is any function from views to answers. The theorem says: for any machine of this shape, if the model agrees with the table on a set W of views (hcert), and every view a reference run can reach lies in W (hW), then every run of every length equals the reference run. Both of those are hypotheses. Lean does not establish either of them for Sketchpad.

So the guarantee is a chain of three links, and only the middle one is formal:

  1. The network is right on all 2,446 views. This is hcert, and it is a measurement: the device certificate. It holds for one execution path (those model files, that library, that GPU kind, at 16-bit).
  2. Right on the views implies right at every length. This is the Lean theorem, proved once for every machine with this structure.
  3. The runtime only ever shows table views, and the table procedures compute the intended functions. This is hW plus the correctness of the classical algorithms. The paper is direct about it: these "are assumptions of these theorems, not formalised for the concrete layouts." The runtime asserts at every step that the view is a table row, and a reference implementation checked this on 1,000 random problems per procedure.

An assertion that fires at every step turns a silent violation into a loud crash, so link 3 is not hand-waving. But it means the accurate form of the X post's sentence is: the model is exact at every length provided the runtime (conventional, unverified TypeScript) lays out sheets as its authors intend, and provided the GPU path matches the one certified. For long addition, link 3 is close to trivial; for long division, it rests on a normalisation argument from Knuth, which I come back to below.

A smaller gap: that a causal decoder reusing a cached prefix computes a function of the view alone is Lemma 4 (cachedForward_eq), proved for an abstract decoder in exact arithmetic. That the ONNX graph on WebGPU is such a decoder is a modelling assumption.

Floating point, and why the margin is a number to read

The theorems assume exact arithmetic. The model runs in 16-bit floats in a browser, and the numbers on that path differ from any reference computation. They can differ a lot: the paper reports that a 4-bit quantised decoder moved some margins of a preliminary adapter from +9.4 to −8.9.

Theorem 3 converts a margin into a tolerance. If every logit on the execution path is within τ\tau of the certified one, and every certified margin exceeds 2τ2\tau, the argmax cannot change. The proof is one line: a wrong token aa would need z~a≥z~y\tilde z_a \ge \tilde z_y, but z~a≤za+τ<zy−τ≤z~y\tilde z_a \le z_a + \tau < z_y - \tau \le \tilde z_y. With a smallest margin of 3.02, any perturbation under 1.51 logits is harmless.

The certificate scores each view alone, while inference batches up to 32 views, and batching changes 16-bit logits. The paper placed every view in random batches of 2, 4 and 32 and saw no logit move by more than 1.09, under the 1.51 that could flip an answer. It also says the check "samples batch compositions; it does not bound all of them." That is a measured headroom of about 0.4 logits on the weakest view, on sampled batches, and I would describe it that way rather than as a proof.

The deployment story has the same texture. On a GPU other than the one certified, the client by default rechecks only the lowest-margin tenth of each table before running. That is a sensible engineering default: in the published certificate the tenth-percentile margin is 10.344 for addition, 11.188 for multiplication and 9.023 for the calculator tables, so the views skipped sit far from the edge. It is still a heuristic, and the paper says so in its discussion: on a new GPU the guarantee "requires the full check," which takes 3.5 minutes on the M4.

Why chain of thought cannot be certified this way

The pinned-sheet policy is what makes the domain finite. Theorem 2 shows the restriction is necessary rather than merely convenient.

Take a two-state table where state u with event a stays u. Build a decoder from a correct lookup plus one attention head that attends to a sink token with score cc and writes a little to the logit of the wrong state for every a it has seen in the context. On a context with nn tokens after the sink, kk of them events, the head adds

η=4Rkec+n\eta = \frac{4Rk}{e^{c} + n}

to the wrong logit, where RR is the lookup's margin. Pick ec=3M+5e^{c} = 3M + 5 for MM the length of the longest context in your test suite. On every test context the head's write stays below RR, so the decoder passes every test, with positive margins. When the context keeps growing, as it does if each step reads all earlier steps, η\eta climbs toward 2R2R and eventually exceeds RR. The decoder then flips to the wrong state and stays there. Under the pinned policy the same decoder only ever sees the fixed prompt plus one row, so it is exact forever.

I evaluated the paper's formula directly: with a longest test context of M=100M = 100 tokens, the unpinned decoder first goes wrong at step 152; at M=16M = 16, at step 26. Whatever MM you test to, there is a decoder that passes and then fails on a longer run. A sibling theorem, no_finite_check, is sharper: a decoder exact on every input of length up to NN and wrong at N+2N + 2.

Theorem 1 as the Lean file states it, then the Theorem 2 counterexample. A segment of the project's own explainer film (sketchpad-film.mp4 in the repository), muted.

The Lean name is no_finite_test_suite, and the paper connects it to Moore's 1956 result that no finite experiment identifies a machine with an unbounded number of states.

Two cautions about reading this. It is an existence result: it says no finite test certifies every decoder that reads its history, not that chain of thought fails. And the same file proves a positive companion (unpinned_exact_of_close): if the history moves every logit by at most τ\tau and every margin exceeds 2τ2\tau, unpinned decoding is exact too. Nobody can bound that drift for a real model over unbounded contexts, which is what the pinned policy sidesteps. Inductive scratchpads and PENCIL also bound what a step reads; Sketchpad takes the limit where a step reads only a bounded view.

The same logic is why sample testing is weak evidence even for the pinned machine. In the widget above, tick "break one row", which corrupts the single view 5 over 6 with no carry. I ran that broken machine in Python on random equal-length sums: a 10-digit sum came out exact 94.2% of the time, a 100-digit sum 59.9%, and a 1,000-digit sum only 0.7%. A suite of twenty 10-digit sums would pass a machine with a wrong row about 30% of the time (my arithmetic: 0.942 to the twentieth). Enumerating the 242 views catches it with certainty.

Division and square roots need a trick

Addition, subtraction and schoolbook multiplication satisfy link 3 by their layout: every column holds two digits and a carry or borrow, which is a table row. Division does not, because a quotient digit is normally guessed by looking at the whole remainder and divisor.

Sketchpad follows Knuth's Algorithm D. Both operands are first multiplied on the sheet by ⌊10/(d0+1)⌋\lfloor 10/(d_0 + 1)\rfloor, where d0d_0 is the divisor's leading digit, so the scaled divisor's leading digit dd is at least 5. The EST table then guesses from three cells only, the remainder's two leading digits r1r2r_1 r_2 and dd:

q^=min⁡(9, ⌊10r1+r2d⌋),q≤q^≤q+2,\hat q = \min\Big(9,\ \Big\lfloor \frac{10 r_1 + r_2}{d} \Big\rfloor\Big), \qquad q \le \hat q \le q + 2,

where qq is the true quotient digit. The bound is Knuth's Theorems A and B for base 10. A borrow out of the multiply-subtract pass says the guess was too big; DEC lowers it and the divisor is added back, at most twice. The EST domain is r1∈{0,…,d}r_1 \in \{0,\dots,d\}, r2∈{0,…,9}r_2 \in \{0,\dots,9\}, d∈{5,…,9}d \in \{5,\dots,9\}, which is 10∑d=59(d+1)=40010 \sum_{d=5}^{9}(d+1) = 400 views.

This bound is part of link 3, the unformalised part, so I brute-forced it: every divisor from 10 to 999 with a leading digit of at least 5, and every remainder below ten times the divisor. That is 3,784,750 pairs, with no violation, and the guess overshoots by at most 2. Square roots use the same table after scaling the radicand by c2c^2 with c∈{1,2,4,5}c \in \{1, 2, 4, 5\}, chosen so twice the partial root starts with a digit of at least 5. The paper says it verified that scaling for every radicand from 1 to 999,999.

Four panels. Panel a: one view and its outputs for each calculator table, for example SUM reads 1, 7, 8 and answers g meaning 6 carry 1, MUL reads 7, 6, 4 and answers 6, 4, A, EST reads 4, 7, 6 and guesses 7. Panel b: the long division 4,100 divided by 59 on the sheet, where a borrow out of the top column shows the guess 8 is too high, and the operation sequences for that division and for the square root of 2,000,000. Panel c: batching four procedures into 32 forward passes instead of 73, and measured time against the cost model. Panel d: per-problem times in the browser test, all 200 exact.
The calculator tables, a division where the estimate is too high and gets lowered, and the browser timing test (Sketchpad paper, Figure 2).

220 of 220, and what that comparison is worth

The browser demo multiplying two long numbers: the sheet, the view, the machine, the layer readout, the state space and the table of checked views update on every step. The demo GIF from the Sketchpad README; it plays recorded runs until you load the model.

The paper reports two end-to-end tests. In the browser test, 200 pre-registered problems (50 each of division to 10 places, square roots to 6 places, GCDs of numbers up to 999, and signed sums of up to 20 digits) ran on the M4 in Chrome, and all 200 were exact. Median times were 7.0 s for division, 9.8 s for square roots, 7.0 s for GCD and 2.0 s for sums. A forward pass costs about 0.065 s plus 0.037 s per view in it, so a step is roughly a tenth of a second.

The headline comparison is 220 pre-registered problems: sums of 10, 30, 100, 300 and 1,000 digits and products of 2- to 20-digit numbers, 20 per length, against ten other models with a 32,768-token budget. Sketchpad answered 220. GPT-6.1 Sol answered 217, Claude Opus 5.5 216 and Gemini 4 Argon 207, all exact on every product and wrong only on sums of 300 or 1,000 digits. The open-weight models scored between 149 and 199, mostly by running out of tokens. Qwen3.5-0.8B, the base model, answered 23 without chain of thought.

mohsenvand/sketchpad-0.8b-preview@5d0ee15 · snapshot 2026-11-12
repo size
2.10 GB
task
image-text-to-text
library
transformers.js
license
other
safetensors
2 shards
largest file
1.50 GB
files
34
downloads
0
likes
1
onnxwebgputransformers.jsarithmetic

repo last modified 2026-11-08

That table (Extended Data Table 5) needs footnotes more than a headline. First, each model was run once per problem, and the paper itself says a difference of a few problems is within sampling variation, so 220 against 217 is not the result. Second, Sketchpad ran this comparison in batched PyTorch on a server, 64,700 views in 1,001 forward passes, not on the certified browser path; the browser path is the 200-problem test. By Theorem 3 that is fine as long as the server's logits are within tolerance, and the server certificate's smallest margin is 3.96, but it is a different path. Third, the frontier models' errors are the instructive part. GPT-6.1 Sol's and Claude Opus 5.5's were completed answers, well within budget, in the same form as correct ones, and differing from the right sum in 1 to 637 digits (most of Gemini's ran out of tokens instead). That is the failure Sketchpad rules out. A certified procedure cannot be silently wrong on an input whose views it has checked.

The guarantee is the result. The leaderboard is decoration.

Four panels. Panel a: sums of 4 to 1,024 digits, one dot per column, with lines into the 242-cell addition table; the nine sums read 202 views, and the other 40 need numbers of unequal length. Panel b: the Theorem 2 counterexample; with state in the context, the margin of the right answer falls below zero just after the longest test length N of 4, 8 or 16, while the pinned-sheet margin stays constant. Panel c: margins of all 2,446 views on the M4 by operation, smallest 3.02 for SUM, 6.52 MUL, 9.50 ADD, 8.00 ADZ, 13.11 FLS, 10.22 NXT, 8.19 SUB, 4.61 EST, 10.09 DEC. Panel d: lowest margin per operation on the server against the browser, 16-bit decoders on the identity line, 4-bit decoders of earlier adapters off it.
Certification: which views sums actually read, the chain-of-thought counterexample, every margin on the M4, and server against browser. The arXiv HTML omits this figure, so it is rendered from paper/figures/out/fig3.pdf in the repository at commit 03bb36b (Sketchpad paper, Figure 3).

What the adapter is, and what it cost

Reading only the safetensors header of arithmetic/adapter/adapter_model.safetensors gives 300 tensors (an A and a B for each of 150 matrices) totalling 10,223,616 parameters, the paper's figure exactly. The config targets the query, key, value and output projections of the six full-attention layers, the input and output projections of the eighteen Gated DeltaNet layers (more on that layer type here), and the three MLP projections of every layer, with r: 16 and lora_alpha: 32, so a scale of 2. The base config confirms 24 layers, hidden size 1,024 and full attention every fourth layer.

The tables are learned, not inherited. Without the adapter, Qwen3.5-0.8B passes 12 of the 2,446 views, all of them addition views that copy a single digit. Training uses cross-entropy plus a hinge loss on the margin (target 4), replays any row whose margin falls below 2, and stops once every row clears 3. The arithmetic adapter passed every row at step 1,200 and was stopped at 1,600, which took 19.8 minutes on one H100. Training is outside the guarantee: nothing proves the recipe finds a certifiable adapter; the certificate checks the one it found.

A logit lens and class-mean interventions place the multiplication digit's decision in the fifth full-attention layer (depth 20). That is a nice result, and orthogonal to the certificate, which says what the model outputs without saying where.

Then there is the chat side. Arithmetic fine-tuning damages other abilities: a preliminary adapter cost 16.4 points of IFEval. Sketchpad multiplies every adapter branch by a scalar gate gg, so that at g=0g = 0 each branch adds an exact floating-point zero and the model is the base model bit for bit, which the paper confirmed on logits, hidden states and caches. A separate dialogue adapter learns to emit a sheet program when a reply needs exact arithmetic. On fresh items it fell short of its own pre-registered bar: GSM8K dropped 5.8 points against the base model. The paper places the loss in multi-step reasoning rather than in the sheet. Deciding when to compute and transcribing a word problem into calls is uncertified model behaviour, and the dialogue adapter mistranslates about 7% of held-out word problems. Theorem 4 makes the accounting explicit: a wrong final answer needs a wrong table, a wrong transcription or a wrong combining program, and the certificate removes only the first.

The weights come with a short leash

The code is Apache-2.0. The weights are not. The model repository's LICENSE grants permission to "run the model, unmodified, inside the official Polyformer demo page, for your own personal evaluation," and forbids modifying it (including re-quantising or converting), redistributing it, using it for any commercial purpose, and using it or its outputs "to train, distil or evaluate another model."

That sits awkwardly with the thesis. A certificate is valuable because anyone can recompute it. Recomputing it in the demo in your own browser is permitted; re-certifying a quantised build or running the check under another runtime is not, without written permission. The method and code are open. The certified artifact is locked to one deployment.

NeoVand/sketchpad@03bb36b · snapshot 2026-11-12

A small vision-language model that computes exactly on its own sheet: the paper and the live demo

stars
1
license
Apache-2.0
branch
main
forks
0
open issues
0
source
1.7 MB
commit date
2026-11-02
source by language
TypeScript574.3 kBTeX295.9 kBPython287.0 kBJavaScript191.6 kBSvelte171.7 kBLean140.8 kBHTML10.3 kB

GitHub REST API, 2026-11-12 — branch, commit, commitDate, createdAt, description, forks, homepage, languages, license, openIssues, pushedAt, stars

Where I land

The X post is right about the direction and loose about the object. "Provably exact at every input length" is true of a specific thing: this network, on this execution path, inside this runtime, for these procedures. The proof part is a general induction that would be equally true of a lookup table, and it is meant to be. The engineering part is making a pretrained vision-language model satisfy the induction's hypothesis and then measuring that hypothesis on the hardware, with a margin that turns floating-point noise into a number you can compare against a measured bound.

What sets the paper apart is that it states every one of those boundaries itself and ships the certificate as a file. I opened it, and it says what the paper says.

What it does not do is make small models into certifiable reasoners in general. It makes them certifiable transition functions, which only helps for problems that can be cut into steps with a bounded, enumerable view. Long arithmetic is the best case for that. Most of what people want from a language model (deciding which computation to run, reading a word problem, following a proof that does not fit a template) does not have a finite view set, and Theorem 2 says you cannot test your way to a guarantee there. I think the right reading is narrower and more useful: when a sub-task does have a finite view set, put the model behind a runtime that enforces it, and you can stop estimating its accuracy and start checking it. For arithmetic inside an agent, I would take that over a 217-of-220 model every time, and I would still want the runtime verified next.

Cite this article

For attribution, please use the following reference or BibTeX:

Satyajit Ghana, "Sketchpad: certified exact arithmetic from a 0.8B model that only sees three cells", ai.satyajit.si, November 2026.

bibtex
@misc{ghana2026sketchpadexactarithmetic,
  author = {Satyajit Ghana},
  title  = {Sketchpad: certified exact arithmetic from a 0.8B model that only sees three cells},
  url    = {https://ai.satyajit.si/articles/sketchpad-exact-arithmetic},
  year   = {2026}
}
share