BitBrain campaign phase 1: the missing gain sweep and BitBrain as a lead-gain corrector
Task A — the gain region Phase 0 never covered (gain < 1). Extend the prediction-quality ruler with gain 0.25/0.50/0.75 arms and a fixed causal per-band arm. Full 70-run result: the hitProxy-argmax curve is [1.00, 1.00, 1.00, 0.00, 0.00] — Pattern below 300 px, HeadOn above — worth +0.13 pp at 300-450 and +2.16 pp at 450+ (0.0767 -> 0.0984). Lead correlation is identical for every g>0 (Pearson is scale-invariant), so a shrinking gain adds no lead information; and the least-squares optimum [1,1,1,1,0.25,0.25] diverges from the hitProxy optimum because Pattern's lead errors are bimodal. Task B — rebuild guns/bitbrain_gun.nim as a lead-gain corrector: aim = LOS + gain*(patternAim - LOS), gain learned online per range band by ranking candidate gains on the hit-probability proxy (the observed lead label via tmhObservedAt), gated to range >= 300 px. ADE+SBC output removed. Offline (70 runs): Pattern below 300 px, +0.37 pp at 300-450, +1.90 pp at 450+ (hitProxy 0.0957 vs 0.0767), matching the fixed rule to within 0.27 pp at 450+ and exceeding it at 300-450. ~0.0007 ms/tick marginal (old gun ~0.114 ms/tick). Default off; rack membership, env report and guard tests (bitbrain 32, registration 13, rack 48, tm_pattern 20, env_report) unchanged and green. Ledger: docs/bitbrain_campaign.md Phase 1, including the three on-file negatives and the causal-shippability note. No live claim.
This commit is contained in:
@@ -30,8 +30,29 @@ const
|
||||
A_NAIVE* = 7
|
||||
A_TMH* = 8
|
||||
A_BB* = 9
|
||||
# ── Phase 1: the MISSING gain sweep. Gains >= 1 were measured worse at every
|
||||
# band in Phase 0; the unexplored region is gain < 1. gain 0.0 is HeadOn
|
||||
# (A_HEADON) and gain 1.0 is Pattern (A_PATTERN), so only 0.25/0.50/0.75 are
|
||||
# new arms. Their `leadCorr` is IDENTICAL to Pattern's by construction (Pearson
|
||||
# correlation is invariant under positive scaling) — printed only to prove it.
|
||||
A_G025* = 10
|
||||
A_G050* = 11
|
||||
A_G075* = 12
|
||||
# Phase 1 fixed causal per-band gain rule: the hitProxy-argmax curve measured by
|
||||
# the sub-unity sweep ([1,1,1,0,0] == Pattern below 300 px, HeadOn above). This
|
||||
# is the rule BitBrain must match; it needs no learning (range is known at fire
|
||||
# time). The table was selected in-sample from this corpus.
|
||||
A_BAND* = 13
|
||||
BandGainTable* = [1.0, 1.0, 1.0, 0.0, 0.0]
|
||||
ArmNames* = ["Oracle", "OracleQuant", "HeadOn", "Pattern", "PatternGain1.5",
|
||||
"PatternGain2.0", "PatternGain3.0", "NaiveLinear", "TMHorizon", "BitBrain"]
|
||||
"PatternGain2.0", "PatternGain3.0", "NaiveLinear", "TMHorizon", "BitBrain",
|
||||
"PatternGain0.25", "PatternGain0.50", "PatternGain0.75", "PatternBandGain"]
|
||||
|
||||
const
|
||||
## The five sub-unity gain arms, in increasing order, resolved to arm indices.
|
||||
## gain 0.0 == HeadOn, gain 1.0 == Pattern.
|
||||
GainArmIdx* = [A_HEADON, A_G025, A_G050, A_G075, A_PATTERN]
|
||||
GainValues* = [0.0, 0.25, 0.50, 0.75, 1.0]
|
||||
|
||||
# ── the naive-linear control (job-95's LIN_M = 4 extrapolation) ──────────────
|
||||
#
|
||||
@@ -133,6 +154,13 @@ proc runRound(ctx: var Ctx, arms: var seq[ArmAcc], r: int) =
|
||||
arms[A_G15].record(rng, wrap180(1.5 * plead - targetLead), 1.5 * plead, targetLead)
|
||||
arms[A_G20].record(rng, wrap180(2.0 * plead - targetLead), 2.0 * plead, targetLead)
|
||||
arms[A_G30].record(rng, wrap180(3.0 * plead - targetLead), 3.0 * plead, targetLead)
|
||||
# sub-unity gains (Phase 1) — the region Phase 0 never covered
|
||||
arms[A_G025].record(rng, wrap180(0.25 * plead - targetLead), 0.25 * plead, targetLead)
|
||||
arms[A_G050].record(rng, wrap180(0.50 * plead - targetLead), 0.50 * plead, targetLead)
|
||||
arms[A_G075].record(rng, wrap180(0.75 * plead - targetLead), 0.75 * plead, targetLead)
|
||||
# the fixed causal per-band rule (Phase 1 hitProxy-argmax curve)
|
||||
let bg = BandGainTable[bandOf(rng)]
|
||||
arms[A_BAND].record(rng, wrap180(bg * plead - targetLead), bg * plead, targetLead)
|
||||
# naive linear
|
||||
let np = predict(ctx.naive, ctx.st, speed)
|
||||
let nl = wrap180(bearingDeg(ox, oy, np.x, np.y) - los)
|
||||
@@ -332,6 +360,75 @@ proc main() =
|
||||
if g30 < bestV: bestV = g30; best = "3.0"
|
||||
echo fmt"{BandLabels[b]:<9} {fmt3(g1):>10} {fmt3(g15):>10} {fmt3(g20):>10} {fmt3(g30):>10} {best} ({fmt3(bestV)})"
|
||||
|
||||
echo ""
|
||||
echo "=".repeat(120)
|
||||
echo "PHASE 1 — THE MISSING GAIN SWEEP: Pattern lead x gain in [0.00, 1.00] (0 = HeadOn, 1 = Pattern)"
|
||||
echo "=".repeat(120)
|
||||
echo "Format per cell: mean|err| deg [hitProxy]. hitProxy is the objective. gain 0.0 is HeadOn,"
|
||||
echo "gain 1.0 is Pattern. The per-band gain table IS causal to APPLY (range is known at fire time,"
|
||||
echo "so a per-band lookup needs no learning); its ESTIMATION from these same runs is in-sample."
|
||||
echo ""
|
||||
var hdrg = "band |req| deg"
|
||||
for gi in 0 ..< GainValues.len: hdrg.add fmt" g={GainValues[gi]:.2f} [hpx]"
|
||||
hdrg.add " bestHpx dHpx bestErr"
|
||||
echo hdrg
|
||||
echo "-".repeat(hdrg.len)
|
||||
for b in 0 ..< NBands:
|
||||
var line = fmt"{BandLabels[b]:<9} {fmt3(meanAbsReq(arms[A_PATTERN].bands[b])):>9}"
|
||||
var bestHi = 0
|
||||
var bestHp = -1.0
|
||||
var bestEi = 0
|
||||
var bestEr = Inf
|
||||
for gi in 0 ..< GainValues.len:
|
||||
let s = arms[GainArmIdx[gi]].bands[b]
|
||||
let e = meanAbs(s)
|
||||
let hp = s.hitProxy
|
||||
line.add fmt"{fmt3(e):>7} [{fmt3(hp)}] "
|
||||
if hp > bestHp: bestHp = hp; bestHi = gi
|
||||
if e < bestEr: bestEr = e; bestEi = gi
|
||||
let patHp = arms[A_PATTERN].bands[b].hitProxy
|
||||
line.add fmt" {GainValues[bestHi]:.2f} {bestHp-patHp:+.4f} {GainValues[bestEi]:.2f}"
|
||||
echo line
|
||||
echo ""
|
||||
echo "OPTIMAL GAIN CURVE (hitProxy-argmax per band) and its implied hit-probability gain vs Pattern:"
|
||||
var curve = " gain = [ "
|
||||
for b in 0 ..< NBands:
|
||||
var bestHi = 0
|
||||
var bestHp = -1.0
|
||||
for gi in 0 ..< GainValues.len:
|
||||
let hp = arms[GainArmIdx[gi]].bands[b].hitProxy
|
||||
if hp > bestHp: bestHp = hp; bestHi = gi
|
||||
curve.add fmt"{BandLabels[b]}->{GainValues[bestHi]:.2f} "
|
||||
let patHp = arms[A_PATTERN].bands[b].hitProxy
|
||||
echo fmt" {BandLabels[b]:<9} best gain {GainValues[bestHi]:.2f} hitProxy {bestHp:.4f} vs Pattern {patHp:.4f} => {bestHp-patHp:+.4f} pp"
|
||||
echo curve & "]"
|
||||
echo ""
|
||||
echo "DIRECT COMPARISON — Pattern vs the FIXED causal per-band rule [1,1,1,0.00,0.00] vs BitBrain (learned online):"
|
||||
let hdrd = "band Pattern hpx fixed-band hpx BitBrain hpx fixed-Pat pp BB-Pat pp"
|
||||
echo hdrd
|
||||
echo "-".repeat(hdrd.len)
|
||||
for b in 0 ..< NBands:
|
||||
let patHp = arms[A_PATTERN].bands[b].hitProxy
|
||||
let fixHp = arms[A_BAND].bands[b].hitProxy
|
||||
let bbHp = arms[A_BB].bands[b].hitProxy
|
||||
echo fmt"{BandLabels[b]:<9} {patHp:>11.4f} {fixHp:>16.4f} {bbHp:>14.4f} {fixHp-patHp:>+14.4f} {bbHp-patHp:>+10.4f}"
|
||||
echo "fixed-band hpx = the [1,1,1,0,0] table applied causally; it was selected in-sample."
|
||||
echo "BitBrain is learned online from labels inside each run (cold start at gain 1.0)."
|
||||
echo ""
|
||||
echo "LEAD CORRELATION PER GAIN (Pearson of applied lead with required lead). Pearson is invariant"
|
||||
echo "under positive scaling, so every g>0 column must be IDENTICAL to Pattern; g=0 has no lead and"
|
||||
echo "therefore no correlation. If they match, a shrinking gain does NOT add lead information — it"
|
||||
echo "only shrinks the magnitude of an uninformative signal (the gain-sweep mechanism)."
|
||||
let hdrc = "band " & " corr(g) "
|
||||
var hdrc2 = hdrc
|
||||
for gi in 1 ..< GainValues.len: hdrc2.add fmt" g={GainValues[gi]:.2f}"
|
||||
echo hdrc2
|
||||
for b in 0 ..< NBands:
|
||||
var line = fmt"{BandLabels[b]:<9}"
|
||||
for gi in 1 ..< GainValues.len:
|
||||
line.add fmt" {fmt3(leadCorr(arms[GainArmIdx[gi]].bands[b])):>8}"
|
||||
echo line
|
||||
|
||||
echo ""
|
||||
echo "=".repeat(120)
|
||||
echo "LEAD INFORMATIVENESS -- capture slope (regression of applied lead on required lead) and lead correlation"
|
||||
|
||||
Reference in New Issue
Block a user