e64 — stepping f

The 64-byte enwik9 prefix, settled one time step at a time under live settling rules. Select a position; step f; the patterns that reach it light up the data they were learned from. Generation 5, in which f is split in two: what a k=1 application delivers is axis G and what a position does with the applications that reach it over time is axis H, so for the first time the decay rule can be moved with the delivery held still. Below the grid, the k=2 LPP on rings: three memory cell positions and the 65536-event AND that joins the first two. Notes and open questions · what licenses any of this.

the controls
controlwhat it changes
G1 · pass · attWhat a k=1 application DELIVERS. Since generation 5 this is an axis of its own (#f-p8-forward, model header byte 42) rather than half of a pair. G1 is the built baseline: the argmax is delivered at min(8, ws), forward and backward agreeing on wp after the backward direction has paid its predecessor split. pass-through delivers ws unchanged — 255 is the identity of min — and attenuate delivers lsa_sub(ws, c), a rate rather than a ceiling, which is the only form in which a strength of 1 can be applied at all. Both are named in #f-p8-forward as the points the axis exists for and neither is built: generation 5 moved the decay axis only, so every frame under them is this viewer's own. Under B2 the stored weights are the delivery and this axis has no effect.
H1…H7What a position does with the applications that reach it over time (#f-p8-decay, model header byte 43). All seven ran. H1 accumulate, constant fall-off 1 — the baseline, and the same run as generation 4's v024. H2 assignment: the longest k that fires assigns, no accumulation and therefore no decay; the one rule on this axis that draws no entropy. H3 accumulate, constant fall-off 2 — the one-constant control that fills in the corner of the square generation 4 could not measure. H4 renormalise: subtract enough that the position's total support is what the arriving evidence justifies, which is the LSA sum of the supports of the applications that fired. H5 decay by the support deficit smax−s of the strongest arrival. H6 no decay; a pattern of support s is applied only on time steps that are multiples of 2smax−s, so the schedule is the fall-off. H7 decay by the number of applications that arrived. Read every one against the constraint #f-p8-decay states: a uniform fall-off cannot reorder an event space, because lsa_sub is monotone — it can only act through the 0 floor and through what the next time step accumulates.
smaxThe reference support H5 and H6 measure a deficit from. Which reading the runs used is an open choice, so it is a control and not a constant.
B1 B2The backward k=1 application. B1 reconstructs it from the forward argmax table, each of the n predecessors paying the ceiling of the base-2 logarithm of n. B2 reads a stored 65536-byte LPP — refused where that would borrow it from a model with a different learned k=1.
C1 C2The AND gate at partial activation. C1 min(wa,wb). C2 sums and thresholds at 128. C2 never binds at any runnable sample: the learned k=2 weights are 1 and 2 and the gate has nothing to bite on.
min / subThe application rule. min(wp,ws) is what every run used and is frozen normatively in #f-p8. wp−(255−ws) was tried and rejected, is implemented in no variant, and every frame under it is unverified. Set it on the baseline and step: every non-absolute application dies one hop from a clamped position and the window collapses. That collapse is the single most useful thing on this control.
D E FWhich learned model is loaded — not settling rules. Sparsification, replay and pruning change what was learned, so each selects a different model file. Only single-axis combinations were run; two at once is refused rather than borrowed.
stepsHow far f runs. An application travels one position per time step, so stopping short of W leaves the far end of the window on its initial state.
presetThe eight runs. Each carries its recorded settled_ok (positions whose settled argmax is the sample byte, clamped ones included, so it is bounded below by the recorded positions, which is why the ladder reports the unrecorded ones separately) and conv (the time step after which the window's argmax sequence stops changing; equal to W means it never did). Anything not on a preset is the viewer's own and is marked as such.
how to read the grid
bytethe sample. Non-printable bytes are ·. Shaded where the selected pattern or application was learned from, in that application's colour; striped where two of them share a position.
argmaxthe settled argmax at this time step. Blue = clamped (the trace records it, held at 255 on its own event, never updated). Green = agrees with the byte, red = disagrees.
w1the weight of that entry, in log support: v stands for a magnitude of about 2v. Over 99 is shown as tens with a subscript zero.
bpcHow far this position is from the truth, in bits — −log2 of the share the true byte holds once the settled event space is read as the distribution it is. 8 is a position that knows nothing (uniform over 256), ~0 a clamped one. It is not a compression rate: what it is, and what it is not. Exact value on hover.
chgshaded where this time step changed the position's argmax. A clear row means the window has stopped changing.
“the causal pass”, and what it does not mean

The causal pass is omega’s, and “causal” here means one thing only: left to right, left context only, no lookahead. It is the NLP sense of the word — most literally true of a character-level RNN, one symbol at a time — and it is not a claim about causation. Concretely (the fixture, #omega-p8-frozen): one left-to-right sweep that predicts each byte from its left context — the kept k=2 rule for (p−2, p−1) if there is one, the k=1 table from p−1 otherwise — and records the byte into the trace exactly when that prediction is wrong. Everywhere below, read causal as left-context.

Do not carry the word forward onto f, because settling is deliberately not causal in that sense, and that is the whole point of it. A transformer, or that RNN, goes one token at a time and can only ever look left. Settling does the opposite: put a set of salient points into a memory trace, then work out the intermediate points through the window of indeterminacy from both sides. Every position on this page takes a forward application from its left neighbour and a backward application from its right one; the second is information the causal pass structurally could not use. Backward causality from a memory trace is a claim this work makes — in these models and, the argument goes, in the brain — and it is exactly what a borrowed word about one left-to-right pass would quietly deny.

Kept and glossed rather than renamed, per MJC 2026-08-17: short and clear once you know what it means, but overloaded enough that it does not travel unannotated (#viz_standard).

the bpc row, and what it is not

Softmax of the log support of each event in an event space is that event space’s probability distribution — by definition, not by derivation. A support is the log of a count, so 2w is the count and the shares of the counts are the probabilities. The bpc row is −log2 of the share the true byte holds in the settled event space at that position: log2(∑ 2w) − wtrue, computed live from the vector on screen.

IT IS NOT A COMPRESSION RATE AND MUST NOT BE READ AS ONE. MJC, 2026-08-17, in the goal this was built from (#p8v2_ring_viz_goal_20260817): “here bpc doesn’t relate to the compression because we are storing a memory trace and not entropy coding. However, the bpc still measures how far away a position is from truth, and when the argmax is wrong, that’s interesting. It also gives a sense of what the model is doing ‘under’ the argmax, and everything that the argmax throws away.” Nothing here is entropy coded, no k is measured, and this number is not on any chart (#viz_standard, #hutter_metrics).

Three readings that follow from it. A clamped position sits at 255 on its own event and 0 on the other 255, so its bpc is ~0 by construction and says nothing about settling. A position whose vector is all zeros is uniform over 256 events, so its bpc is exactly 8 — the floor a position starts from, and the number to read every other one against. And where the argmax is wrong the bpc says by how much: a near-miss and a position that has put its mass somewhere else entirely are the same red cell in the argmax row and different numbers here.

the axes

the operations, in ordinary arithmetic

Every weight here is a log support, which is why the arithmetic is not the arithmetic it looks like. Nothing on this page names an operation without a row here.

The k=2 LPP, on rings

Three memory cell positions and the AND that joins the first two. p−2 and p−1 are event spaces of 256 events each; the pair of them is an event space of 65536, one event per two-byte context, and that is the ring a grid cannot draw. The k=2 LPP is what connects that ring to p. MJC, 2026-08-17: “the point of a ring is that it shows the full picture of an LPP such as the k=2 one which is captured as 65536 values” (#p8v2_ring_viz_goal_20260817). Ported from the UM viewer at umr.html, laid out left to right because that is the memory chain. Drag to turn, wheel to zoom, hover any event to hold it at 255 and see where it projects, click to freeze it — freeze one on p−2 and one on p−1 and the AND ring is left holding a single event. Nothing is drawn over the picture: what the cursor touches is written into the SN pane on the right, as an SN state, with a held event at 255. — three layouts of that pane ship side by side (the chain, one space, the rules) so the reading can be chosen against real data rather than described. Full screen gives it the screen — browser chrome and all, where the browser allows it, and the whole viewport where it does not; the surface is wide and the page column is not. Press f, or the button; Escape comes back. The fibre ink slider trades the two readings of a bundle against each other — faint and thin, where a hundred fibres lying together read as a density; or thick and cased, where one fibre can be followed by eye but paints out its neighbours. Neither end is the honest one, so it is a slider, and no number on the page moves with it.

Every pattern the model holds inside the window — 256 k=1 rules and the k=2 tokens — each expanding to the input positions that formed it. Selecting one writes its concordance and lights those positions in the grid above. At this sample the model header says n = M = 64, so the training set is the 64 bytes on screen and the expansion is exact, not sampled.

Every settled prediction, the patterns that produced it, and the input positions those patterns record. One row per position, over the full run of f under the current controls. Click a row to drive the instrument to it.

Two things in that table are not defects. A row often lists a pattern out of 0x00: at the first time steps an unclamped neighbour is all zeros, its argmax is byte 0, and the rule out of byte 0 is genuinely what fired. And the backward direction is named as a reconstruction rather than by an atom, because under B1 it is not a stored pattern — the query layer prints no atom for it and this page will not mint one. It has a support set all the same.

Every decay rule at every rung of the prefix ladder, from the dumps. The instrument above is e64 only — one 64-byte window, one sample — and #viz_standard is explicit that a number measured on one prefix is a point on a curve and is read as one. This is the curve.

Is any of this probability?

The chain the instrument puts on screen is: input positions → a pattern's log support for a joint event → f → the log support values of the settled event space. What licenses each link. Nothing here is this page's own derivation — everything asserted is quoted from a document published beside this page, and where no document says it, this section says that instead.

the linkwhat licenses it
input positions → a pattern. A pattern is about the positions the concordance lists. #f-p8: “the M-1 pattern with one byte and the next byte being input and output spaces … is a sufficient statistic on the frequency of the joint events, i.e. the byte pairs.” So the antecedent–consequent pair names a joint event and the strength is a log count of it. That count is what the concordance enumerates, which is why LATD is not a debugging view but the pattern's own definition read back.
a count → a byte. Why a strength of 1 is not “seen twice”. LSA.md: an LSA value “represents the log value of a count”, the error is uniform in the log domain, two values are required to have uncorrelated error distributions, and the increment gives w+1 with probability 2−w. The stored weight is a stochastic estimate of the count, so the two are not required to agree — and on this sample they do not.
one pattern → a probability, from an absolute antecedent. #f-p8: “In the case of assignment, given the full joint pattern on the ESs in which t_i and t_j participate, we see immediately that softmax on the ES of t_j gives the correct probability distribution given the event e_i (corresponding to t_i = 255) and the information about the frequency of the joint events, the sufficient statistic, captured by the pattern.” With LSA.md: “LSA variables which form an event space are interpretable as probabilities via softmax.” Read the conditions: assignment, not accumulation; t_i = 255; before f has run.
two patterns → one distribution, and the condition under which that is correct. #f-p8 states it with its condition attached: “If another pattern that is derived from a disjoint set of observations is brought in, these two distributions can be combined into the correct (per probability theory) combined distribution, which is not true if this additional parameter is not known (or if the observations are not disjoint, or more generally, are correlated in a way that is unknown).”

Four places the chain is not covered

1. THE ANTECEDENT IS NOT ABSOLUTE. The softmax result is derived for t_i = 255. In f a forward application delivers min(wp, ws) where ws is the source position's current activation — after one time step that is neither 255 nor a count of anything observed, it is the output of the previous time step. min of a log count of a joint event and an activation is not derived anywhere we can find. Axis B is frozen at b1 normatively, but a freeze is a decision, not a derivation.
2. THE PATTERNS THAT MEET AT A POSITION ARE NOT DISJOINT, AND THE GRID SHOWS IT. The condition quoted above is disjointness of the observation sets. The forward k=1, the backward k=1 and the k=2 token that meet at one position were all learned from the same 64 bytes, and their support sets overlap — which is what the striped cells in the grid are. Measured live, for the position selected: Under every decay rule except H2 those three vectors are combined with LSA addition, which is log2(2a + 2b): addition in the count domain. Adding the counts of two event sets that share observations counts the shared observations twice. Whether that is the intended reading, and what the operation should be when the sets are known to overlap, is not written down in any document published beside this page.
3. THE k=1 STRENGTH IS STATED, NOT STORED. The k=1 section of the model is 256 bytes of argmax and stores no weight, so what a pattern delivers is a READING and not a value read out of the file. Generation 5 makes that reading an axis of its own: under G1 the argmax is delivered at min(8, ws), where 8 is the weight that makes the argmax carry half the mass of an event space whose other 255 events sit at 0, and the argmax’s measured share expresses as 9 / 8 / 7 at e64 / e1k / e10k — so 8 is the measured value at e1k and within one unit of it everywhere (#f-p8-forward). Under B2 the same pattern is applied at its actual learned weight, which at this sample is 0, 1 or 2. Whether a stated constant or the stored count is the right delivery is exactly what v024 against v025 measures, and it cuts both ways: at e64 and e1k the stated 8 recovers more unrecorded positions than the stored truth does (14 against 1, and 220 against 151), and at e10k the truth wins (1369 against 1288). A 1-unit delivery drowns in a window where the stochastic add is the same size; by e10k there is enough of it to be worth reading. What the split changed is that this is now separable from the fall-off: generation 4 could only move the pair, and the three runs H1, H3 and generation 4’s (255, 2) now show that the fall-off carries essentially the whole gain and the delivery carries two positions at e1k (the report).
4. THE SETTLED VECTOR. Is softmax of a settled activation vector a probability distribution over the next byte? The softmax result is stated for one pattern, from an absolute antecedent, by assignment, before f runs. After W time steps of accumulate and fall off, no document published beside this page makes the claim again. The original derivation had a bridge — a constant sum through time, from which the fall-off rate followed — and #p8v2_gen3 removed it: “There is no constant sum ever in an ES. The only thing constant is total probability = 1 and that is after softmax.” That passage of #f-p8 is marked WITHDRAWN and nothing has replaced it. H4 is the one setting on this page that addresses the question rather than inheriting it: it rescales the position to the support the arriving evidence justifies, so its vectors mean the same thing at time step 5 and at time step 100 — and because the subtraction is uniform it cannot reorder the event space, so it changes what the position claims to rest on and never which byte it favours. That is not an answer to whether the settled vector is a distribution; it is the only alternative here for which the question is well posed.

ANSWERED, 2026-08-17, and the answer is that the question was misput. MJC, in #p8v2_ring_viz_goal_20260817: “Softmax of the log support of each event in an ES is the probability distribution by definition. I'm not sure what #f-p8 is referring to, but something has been misread somewhere. It's worth including this if nothing else because it eliminates any misunderstandings about what an ES is, which apparently is an ongoing source of confusion.” So the distribution does not need licensing from the assignment passage: it is what an event space of log supports is, before and after f alike, and the bpc row renders it. What this does not settle is gaps 1 and 2, which are about the arithmetic that produced the vector — min against an activation that is not 255, and LSA addition over observation sets that overlap — and those are still open. A distribution can be read off any event space; whether this event space is the one f should have produced is the other question.

One of the four is now answered — gap 4, above, and the answer is that softmax of an event space's log supports is its distribution by definition, so there was nothing to derive. The other three remain a request for a document, not a finding: the derivation is the programmer's, and inventing one here would be the same failure as rendering a rule that was never run. Written up as #p8v2_latd_probability_ask_20260815. When the document exists, this section renders it instead of asking for it.

what the conformance check does and does not pin

which page this is, and what it is not

Generation 5. Generation 4's instrument is /hutter/pprog/p8v2-gen4-e64/, frozen as that generation's record; generation 3's is /hutter/pprog/p8v2-gen3-e64/ and generation 2's is /hutter/pprog/p8v2-e64/. A page is not rebuilt in place when its generation is superseded: the generation-1 page was, and no longer exists to be compared with. The convention is in #viz_standard, “Versioning a viewer”.

Eight variants were run — v024 (the baseline, which is (G1, H1) and is generation 4's run unchanged), v025 (B2 off it, the ground-truth column and the only one here that stores the count matrix) and v026…v031, the six restated decay rules — and are marked RUN. The two forward settings other than G1 are not built in any variant, and every other combination is the viewer's own; all of them are marked not a measurement. There is no pick, no ranking and no compression number here; the picks are the programmer's (#variant_protocol).

settled_ok is partly circular and the page reports around it. H2's readout is the argmax of the single strongest application, which is very nearly the predictor omega used to decide which bytes to record — so a rule whose readout coincides with the sparsifier's scores near-perfectly without settling doing any work. Every settled_ok in generations 1–5 is a measure of agreement with the causal pass — that is, the left-context pass, not of recovery (the report). The ladder below therefore reports the UNRECORDED positions separately, which is the number the recorded ones cannot flatter. And on that set the two readings are the same event: the unrecorded positions are, by construction, exactly the ones the left-context predictor already got right — — so “settled back to the true byte” and “agreed with the left-context prediction” cannot be told apart there. That is the circularity, and it is why a rule whose readout collapses back to the left context scores near-perfectly while contributing nothing that settling is for.

sources
models/p8v2/enwik9/64/the retained models; k=1 argmax table at offset 48, backward LPP at 304, then four bytes per token rule. No k=0 section
gen5-pos/generation 5's recorded endpoints, which the conformance check compares against
gen5.tsvgeneration 5's measured facts, including the e64 settling diagnostics. gen4.tsv is published beside it because the split’s central claim is that v024 and v025 reproduce their generation-4 rows byte for byte
axes.jsonthe axes, their alternatives and their definitions — the page reads it, it is not copied here
#f-p8f itself: the single normative statement. The application rule, the window and its tiling, the time steps, initialisation, clamping and the argmax tie-break are all in it
#f-p8-forward, #f-p8-decaythe two halves of f, each in its own words: what an application delivers, and what a position does with the applications that reach it. #f-p8-cap8 is the pair they were carved out of
#f-p8-decay-assign, #f-p8-decay-const2, #f-p8-decay-renorm, #f-p8-decay-deficit, #f-p8-decay-period, #f-p8-decay-indegreeH2…H7, each in its own words — the six retired axis-A ideas restated on the cap-8 delivery
LSA.mdwhat an LSA value is: the log of a count, uniform expected error in the log domain, uncorrelated between values by construction
#p8v2_latd_probability_ask_20260815the four questions above, written as a request for a derivation
p8v2-words.mdthe fixture; the f blocks are the settling shell this page implements
the generation 5 reportwhat these runs say, including the finding that settled_ok is partly circular
#pprog_p8v2_gen5_goal_20260815the goal generation 5 was run against, with the programmer’s answers inline
#p8v2_gen3the push that opened the generation, with the programmer's answers inline
#p8v2_gen3_viz_goal_20260810the goal this page was built from
#viz_standardwhat goes on anything we publish, including how a viewer is versioned
#hutter_publication_handoffthe division of labour between the two trees
build-p8v2-gen5-e64rebuilds this page and the notes. Runs no compression
check-p8v2-gen5-e64runs this page’s own script headlessly and drives it: all 168 combinations of the controls against every pane, every position at every step, the ring surface under both modes, and the two checks that carry the most — that H2 still conforms exactly, and that the bpc of a clamped position is 0 and of an untouched one is 8. What the page claims about itself, run rather than asserted
p8v2-gen1/the generation panels: every variant of a generation over the same input positions

Published under #viz_standard. Self-contained: no external stylesheet, no script, no font, no image, nothing fetched. Data symlinked from ../cmpr-src/; page regenerated by docs/pprog/build-p8v2-gen5-e64, never hand-edited. The blocks are the authority.