Files
Robert Allan JamesandClaude Sonnet 5 7e2fd9f044 Fix SWAP-MTX: Fisher-Yates shuffle was never actually shuffling correctly
Found while building the analysis report for the ACL-RWT relaunch
campaign: cfg=0 was missing from run coverage for 2 of 3 seeds, reproduced
identically across all three architectures. Root-caused rather than
worked around, per Captain Bob's "this is worrisome."

SWAP-MTX (capsules/doe.4th Block 2104) never actually swapped two
RUN-MATRIX cells -- it performed a lossy one-way copy (second MATRIX!
call mis-targeted mat[i] again instead of mat[j]). Confirmed by direct
empirical test on the hosted build: INIT-MATRIX gives mat[0]=0, mat[5]=5;
after 0 5 SWAP-MTX, mat[0]=0 (unchanged, should be 5) and mat[5]=0
(correct), with the original value 5 permanently destroyed. Every
Fisher-Yates shuffle this mechanism has ever run silently duplicated some
values and dropped others -- not a true permutation. Not new, not
introduced by item 4.6/Stadium work; predates this session.

Fixed with explicit temp variables (SW-I/SW-J/SW-VI/SW-VJ), trivially
verifiable by inspection over clever stack juggling. Verified on the
hosted build for all three seeds used by the relaunch campaign: each now
produces all 16 cfg values exactly 30 times, run_id 0-479 fully distinct.
Three-arch QEMU acceptance clean: 1012/0/0 POST on all three, identical
dict_hash (expected -- doe.4th isn't C-registered or auto-loaded at
boot). BLOCK_MAP.md correctly shows only doe.4th's own hash changed.

Also includes the R analysis/chart pipeline (analyse_stadium_relaunch.R)
built for the relaunch campaign report, and the three acceptance boot
logs.

Retroactive caveat: the relaunch campaign's own run-matrix coverage
(experiments/bare_metal/runs/acl-rwt-20260820/) is not a valid uniform
permutation, having run against the buggy shuffle. Whether to re-run it
against the fix is a separate call, not made here.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-20 10:56:12 -04:00

116 lines
3.2 KiB
Forth

Block 2100
( doe.4th - unified L8 adaptive-map DoE for LithosAnanke )
( Factors: entropy,cv,temporal_decay,stability; 2 levels )
( 2^4 = 16 configurations x 30 reps = 480 randomised runs )
( Run matrix: 0..479 sequential; Fisher-Yates shuffled. )
( cfg=idx/N-REPS rep=idx MOD N-REPS at decode time )
( Self-executing: DOE on load; CSV streams to serial. )
49152 CONSTANT ENT-HI ( 0.75 * 65536 )
9830 CONSTANT CV-HI ( 0.15 * 65536 )
32768 CONSTANT TMP-HI ( 0.50 * 65536 )
32768 CONSTANT STB-HI ( 0.50 * 65536 )
16 CONSTANT N-CFG
30 CONSTANT N-REPS
480 CONSTANT N-RUNS
Block 2101
( serial output primitives )
: N. ( n -- )
DUP 0 < IF 45 EMIT ABS THEN
0 SWAP <# #S #> TYPE ;
: COMMA 44 EMIT ;
: CRLF 13 EMIT 10 EMIT ;
: CSV-COL ( n -- ) N. COMMA ;
: CSV-LAST ( n -- ) N. CRLF ;
: CSV-HEADER ( -- )
." run_id,cfg,rep,ent_in,cv_in,tmp_in,stb_in," CRLF
." l8_mode,win_div,infer_win,infer_dec_q," CRLF
." infer_var_q,early_exit,bc_mean_q,bb_mean_q,fit_q" CRLF ;
Block 2102
( factor extraction: cfg bits b3=ent b2=cv b1=tmp b0=stb )
VARIABLE CURR-CFG
VARIABLE CURR-REP
VARIABLE RUN-ID
: CFG-ENT ( cfg -- q ) 8 AND IF ENT-HI ELSE 0 THEN ;
: CFG-CV ( cfg -- q ) 4 AND IF CV-HI ELSE 0 THEN ;
: CFG-TMP ( cfg -- q ) 2 AND IF TMP-HI ELSE 0 THEN ;
: CFG-STB ( cfg -- q ) 1 AND IF STB-HI ELSE 0 THEN ;
: APPLY-CFG ( cfg -- )
CURR-CFG !
CURR-CFG @ CFG-ENT
CURR-CFG @ CFG-CV
CURR-CFG @ CFG-TMP
CURR-CFG @ CFG-STB
L8-UPDATE L8-APPLY ;
Block 2103
( DOE-WORK: arithmetic workload; ~35000 word executions )
: DOE-WORK ( -- )
PHYSICS-RESET-STATS
5000 0 DO
I 13 * 7 +
I 11 MOD +
I 3 AND CASE
0 OF DUP * ENDOF
1 OF NEGATE ENDOF
2 OF 1 + ENDOF
3 OF DROP 0 ENDOF
ENDCASE
DROP
LOOP ;
Block 2104
( run matrix: 480 cells, indices 0..479, Fisher-Yates shuffled )
( cfg = mat[i] / N-REPS, rep = mat[i] MOD N-REPS )
CREATE RUN-MATRIX N-RUNS 8 * ALLOT
: MATRIX! ( val idx -- ) 8 * RUN-MATRIX + ! ;
: MATRIX@ ( idx -- val ) 8 * RUN-MATRIX + @ ;
VARIABLE SW-I VARIABLE SW-J VARIABLE SW-VI VARIABLE SW-VJ
: SWAP-MTX ( i j -- )
SW-J ! SW-I !
SW-I @ MATRIX@ SW-VI !
SW-J @ MATRIX@ SW-VJ !
SW-VJ @ SW-I @ MATRIX!
SW-VI @ SW-J @ MATRIX! ;
: INIT-MATRIX ( -- )
N-RUNS 0 DO I I MATRIX! LOOP ;
Block 2105
( Fisher-Yates: i in [0,N-RUNS-2] -> j=rand swap )
: SHUFFLE-MATRIX ( -- )
N-RUNS 1 - 0 DO
I N-RUNS 1 - RANDOM
I SWAP-MTX
LOOP ;
Block 2106
( CSV row emitter )
: EMIT-ROW ( -- )
INFER-RUN
RUN-ID @ CSV-COL CURR-CFG @ CSV-COL
CURR-REP @ CSV-COL CURR-CFG @ CFG-ENT CSV-COL
CURR-CFG @ CFG-CV CSV-COL CURR-CFG @ CFG-TMP CSV-COL
CURR-CFG @ CFG-STB CSV-COL L8-MODE CSV-COL
WINDOW-DIVERSITY CSV-COL INFER-WINDOW@ CSV-COL
INFER-DECAY@ CSV-COL INFER-VARIANCE@ CSV-COL
INFER-EARLY-EXIT@ CSV-COL BAYES-CACHE-MEAN CSV-COL
BAYES-BUCKET-MEAN CSV-COL INFER-FIT@ CSV-LAST ;
Block 2107
: EXEC-DOE ( seed n-reps -- )
SWAP SEED INIT-MATRIX
SHUFFLE-MATRIX CSV-HEADER
0 RUN-ID !
N-CFG * 0 DO
I MATRIX@
DUP N-REPS / CURR-CFG !
N-REPS MOD CURR-REP !
CURR-CFG @ APPLY-CFG
DOE-WORK
EMIT-ROW
RUN-ID @ 1 + RUN-ID !
LOOP
." DOE: complete" CRLF ;
: DOE ( -- ) 12345 3 EXEC-DOE ;