## Task 3 — VALIDATE THE DIAGNOSTICS AGAINST A KNOWN GROUND TRUTH. ## ## A synthetic dataset is generated from a planted decision list over the DRAFT ## 49-bit encoding: ## A = bit 0 ("dist-wall<50", WALLS block) ## B = bit 45 ("lat DEAD-ON -18..+18", BULLETS block) ## class 2 = A AND B ; class 1 = A AND NOT B ; class 0 = NOT A ## Deliberately irrelevant: the whole US block (bits 8..16) plus one pure-noise ## MOTION bit (bit 17). ## ## The kit must recover the rule, flag the dead inputs, show ~0 ablation delta ## for the irrelevant block, and sit at the majority baseline under shuffled ## labels. Every number printed here is MEASURED. ## ## Run: nim c -r --path:common_libs common_libs/tests/diag_synthetic.nim import std/[random, strformat, strutils, algorithm] import tm_diag/diagnostics const NBits = 49 BitA = 0 ## dist-wall<50 BitB = 45 ## bullet lateral DEAD-ON NoiseBit = 17 NClasses = 3 var failures = 0 proc check(name: string, ok: bool) = if ok: echo "PASS: ", name else: echo "FAIL: ", name; inc failures proc genDataset(n, seed: int): seq[DiagSample] = var rng = initRand(seed) for i in 0..2 | A&!B->1 | !A->0" # ── GROUP 1: data checks ── var labels = newSeq[int](train.len) for i, s in train: labels[i] = s.label let dc = dataChecks(labels, NClasses) echo "\n## GROUP 1 data checks" echo &"# n={dc.n} counts={dc.classCounts} shares={dc.classShares} " & &"majority=class{dc.majorityClass} share={dc.majorityShare*100:.2f}% " & &"overThreshold={dc.overThreshold}" for f in dc.flags: echo "# FLAG ", f # manual majority for the check var manualMaj = 0 for c in 0.. dc.classCounts[manualMaj]: manualMaj = c check "majority class computed from the counts", dc.majorityClass == manualMaj and abs(dc.majorityShare - dc.classCounts[manualMaj].float / dc.n.float) < 1e-9 # ── train the reference TM ── let tmpl = newMachine(NBits, NClasses, nClauses = 40, nStates = 64, sValue = 3.0, seed = 1) let m = trainModel(tmpl, train, epochs = 25, seed = 777) let trainAcc = evalAcc(m, train) let testAcc = evalAcc(m, eval) echo &"\n## trained reference TM: trainAcc={trainAcc*100:.2f}% testAcc={testAcc*100:.2f}%" # ── GROUP 2: clause introspection ── let infos = clauseInfo(m, eval, spec) let summ = clauseSummary(infos) echo "\n## GROUP 2 clause introspection" echo &"# totalClauses={summ.totalClauses} empty={summ.emptyClauses} " & &"nonEmpty={summ.nonEmpty} fired>=1={summ.firedAtLeastOnce} " & &"neverFired={summ.neverFired} posFired={summ.posFired} negFired={summ.negFired} " & &"meanLen={summ.meanLength:.2f} maxLen={summ.maxLength}" echo "# lengthHist (idx=len): ", summ.lengthHist echo "## top firing POSITIVE clauses per class (rule-encoding; polarity annotated)" for cls in 0..2} {ranked[i].name:<22} appearances={ranked[i].appearances} weighted={ranked[i].weighted:.1f}" echo "# DEAD-INPUT LIST (weighted < 5% of top, plus never-in-voting-clause): ", dead echo "# never-used (strict appearances==0): ", neverUsed echo "# constant inputs: ", consts check "the planted relevant bits are the top-2 contributors", ranked[0].bit in {BitA, BitB} and ranked[1].bit in {BitA, BitB} # the whole US block must be dead var usDead = true for b in 8..16: if b notin dead: usDead = false check "the whole irrelevant US block is on the dead-input list", usDead check "the pure-noise MOTION bit is on the dead-input list", NoiseBit in dead check "no planted relevant bit is called dead", BitA notin dead and BitB notin dead # ── GROUP 4: accuracy diagnostics ── let ad = accuracyDiagnostics(m, eval) echo "\n## GROUP 4 accuracy diagnostics" echo &"# n={ad.n} correct={ad.correct} acc={ad.acc*100:.2f}% " & &"majority=class{ad.majorityClass} baseline={ad.majorityBaseline*100:.2f}% " & &"margin={ad.margin*100:+.2f}pp predMajorityShare={ad.predMajorityShare*100:.2f}%" echo "# confusion [true][pred]:" for c in 0.. 0.3 check "uniform-ish predictions (not majority-spam): predMajorityShare < 0.7", ad.predMajorityShare < 0.7 # ── GROUP 5: learning curve ── let lc = learningCurve(tmpl, train, eval, nPoints = 10, seed = 31) echo "\n## GROUP 5 learning curve" echo &"# trend={lc.trend}" for i in 0.. 0: echo &"{failures} check(s) FAILED" quit(1) echo "All synthetic diagnostic validation checks passed."