Files
SirRoboGarage/common_libs/guns/bitbrain_net.README.md
T
SirStone e9302bc9f6 j140 rebuild a real BitBrain gun: ADE+SBC at rack id 17, default off, and measure its scaling
The BITBRAIN name was sitting on a gun with no network in it. This is the gun
that actually runs the algorithm: an ADE layer (thresholded random projections
with ONLINE threshold adaptation) feeding the SBC head from
common_libs/bitbrain/, with the counted+decay mode available.

  common_libs/guns/bitbrain_net.nim     the gun
  rack name BITBRAIN, rack id 17 (rack 17 -> 18 guns), both new guns default OFF
  admitted by TR_RACK_BITBRAIN=both AND TR_BITBRAIN_NET=1 (the switch that also
  disowns LEADGAIN's legacy TR_BITBRAIN_* aliases)

OUTPUT: a fine-grained aim CORRECTION on top of Pattern - the probability-
weighted mean of the nClasses class centres under inferProb - not a direct aim
point from the argmax. That is the shape docs/bitbrain_gate.md measured, and
Pattern is already a strong predictor, so the net's job is the signed residual.
Below TR_BITBRAIN_MINOBS the shift is exactly 0 and Pattern is returned
unchanged.

INPUT: a CONFIGURED set of FEATURE BLOCKS (TR_BITBRAIN_FEATURES=name:W), each
block's width == its resolution, laid out as a thermometer code over 0/255 slots
(so an ADE synapse 'matches' when its polarity agrees with the slot and a random
ADE fires iff its w synapses all match, rate 2^-w). Default is 52 slots over 9
blocks. NO long temporal window, per docs/state_window_gate.md: the only history
is a 12-tick ring feeding three rate/turn quantities.

Every knob env-configurable: _INPUT (width), _NCLASSES, _NADES, _WIDTHS
(clause widths), _FEATURES, _SPAN, _MODE, _DECAY_EVERY, _DECAY_SHIFT,
_MINOBS, _ADAPT_EVERY, _TARGET, _NETSEED, _NETLOG, _NET_RESET_ON_TARGET.

MEASURED SCALING (measure_bitbrain_scaling.nim, 3 recorded runs, 37412 ticks,
-d:release, one predict per power bin per tick, timed region = predicts only):
  RAM 1.59 MB default (98.6% SBC tensors); linear in nClasses, QUADRATIC in
      nAde, FLAT in input width; counted/bitset = 7.30x on RAM, ~1x on time.
  ms/tick 2.70 default = 21% of the 13.16 ms budget; 64 classes busts it (149%),
      nAde 512 uses 74%, nAde 64 uses 2%.
  CAPACITY vs ACCURACY: over a 100x RAM range the offline mean |err| moves
      17.254 -> 17.115 deg around Pattern's 16.964, and the sign flips along the
      nClasses axis, so it is noise, not a trend. The corrector is consistently
      slightly WORSE than Pattern. The ceiling is the STATE, not the classifier.
      VETO-CAPABLE OFFLINE CHECK ONLY (docs/offline_harness_trust.md), never
      presented as a live win.

ENGAGEMENT is proven, not assumed: test_bitbrain_net.nim (42 checks) shows 0
bytes before first use, different inputs -> different class outputs, a learn
raises SBC occupancy, bitset learn idempotent while counted learn is monotone,
threshold adaptation runs, and the global RNG is untouched.

Parity: shipped rack still onlyPattern, shipped movement still strafe. Guards:
test_env_report 25, test_rack_membership 48, test_tm_pattern_registration 20,
test_lead_gain_registration 13, test_lead_gain_legacy 24, test_bitbrain 56,
test_gun_harness 39, test_tfil_commit_env 30, test_bitbrain_net 42.
Clean archive build: [SuccessX].

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-26 16:50:21 +02:00

11 KiB
Raw Blame History

bitbrain_net — quick recap (inputs / outputs)

Recap card. Everything below is read off common_libs/guns/bitbrain_net.nim. Companion to the library's own README (common_libs/bitbrain/README.md) and to common_libs/guns/lead_gain.README.md (the other gun, the per-range-band lead-gain corrector at rack id 16).

What it is

The real ADE+SBC gun: an ADE layer (thresholded random projections with online threshold adaptation) feeding the SBC head from common_libs/bitbrain/, with the counted + decay mode available (the mode that delivers forgetting and true per-class probabilities — docs/bitbrain_counted_sbc.md).

It took the BITBRAIN rack name (id 17) and the TR_BITBRAIN_* knob prefix that the renamed corrector gave up. Default OFF: it needs BOTH TR_RACK_BITBRAIN (rack table) and TR_BITBRAIN_NET=1 (the gun's own master switch, the same switch that disowns the legacy TR_BITBRAIN_* aliases of LEADGAIN). The network is built lazily, so an unset environment never allocates a byte.

OUTPUT SHAPE — a fine-grained correction ON TOP of Pattern

Not a direct aim point from the argmax class. The class-resolved angular correction added to Pattern's bearing is the shape docs/bitbrain_gate.md actually measured, and Pattern is already a strong predictor, so the net's job is the small signed residual, not the whole aim.

Output Formula / meaning
Correction shift = Σ_k P(k)·centre_k / Σ_k P(k) — the probability-weighted mean of the nClasses class centres under inferProb, in degrees, over ±TR_BITBRAIN_SPAN
Aim point tmhApplyShift(self, Pattern prediction, shift). Below TR_BITBRAIN_MINOBS resolved samples, or when the posterior has no mass, shift == 0.0 and Pattern's prediction is returned unchanged
[bbn] log (only TR_BITBRAIN_NETLOG=1, change-gated) t, shift (deg), class (argmax), in, ncl, nAde, mode, trained, adapts, pend, dropped
Does NOT output an aim point of its own; it never discards Pattern

INPUT — a CONFIGURED SET OF FEATURE BLOCKS

The input vector is a concatenation of feature blocks, each independently selectable (TR_BITBRAIN_FEATURES) and with a settable width. A block is a list of scalar quantities; a block of width W lays each quantity out as a W-slot thermometer code, so width == resolution. Slots are 0/255 uint8, which the ADE scorer centres at 127 (DefaultCenter): a synapse matches when its polarity agrees with the slot, so a random ADE fires iff its w synapses all match — a thresholded random projection with firing rate 2^-w, which online homeostasis then drives toward TR_BITBRAIN_TARGET.

The default block set is 52 slots:

block quantities width slots quantity
epos 2 4 8 enemy offset from us, x and y, over the arena span
evel 2 3 6 enemy speed; enemy heading minus the bearing to us
eturn 2 2 4 turn direction this tick; turn consistency over the ring
eself 2 2 4 our speed; our heading minus the bearing to the enemy
dist 2 5 10 range; signed range rate over the last 10 ticks
bear 1 4 4 relative bearing (enemy bearing minus our heading)
walls 4 2 8 distance to each of the four arena walls
bull 2 2 4 live-bullet count; nearest bullet's signed lateral offset
hzn 1 4 4 bullet flight time to the current range

docs/state_window_gate.md measured that a long temporal window of states destroys recurrence, so there is deliberately no window block: the only history-derived inputs are the three rate/turn quantities above (a 12-tick ring), i.e. the same causal information Pattern itself uses.

KNOB TABLE

Env Default Meaning
TR_RACK_BITBRAIN off rack admission for id 17 (the current name of the rack key)
TR_BITBRAIN_NET 0 master switch. 0 = off and the TR_BITBRAIN_* names are LEGACY aliases of LEADGAIN; 1 = on and the names below are the new gun's
TR_BITBRAIN_INPUT 52 total input slots; pads or truncates the block layout so the ADE codes can never index out of range
TR_BITBRAIN_FEATURES all blocks at their shipped width name:W list, comma separated. name:0 switches a block OFF; an unlisted block keeps its shipped width; an unknown name warns and is ignored
TR_BITBRAIN_NCLASSES 8 output resolution
TR_BITBRAIN_NADES 256 ADEs per address decoder (RAM is quadratic in this)
TR_BITBRAIN_WIDTHS 4,5,6 ADE clause widths; one AD per width, one cross-AD SBC per pair (3 widths → 3 SBCs)
TR_BITBRAIN_SPAN 40.0 class half-range, degrees
TR_BITBRAIN_MODE counted bitset | counted (saturating counters + decay)
TR_BITBRAIN_DECAY_EVERY 64 counted mode: learns between global decay passes
TR_BITBRAIN_DECAY_SHIFT 3 counted mode: c -= c shr shift per pass (0 disables)
TR_BITBRAIN_MINOBS 32 resolved samples before the correction is applied at all
TR_BITBRAIN_ADAPT_EVERY 200 inputs between ADE threshold-adaptation passes
TR_BITBRAIN_TARGET 0.01 the paper's target ADE firing rate
TR_BITBRAIN_NETSEED 20240921 network seed (a private RNG, never the global one)
TR_BITBRAIN_NETLOG 0 1 = emit the [bbn] line
TR_BITBRAIN_CALIB_EVERY — compat alias for TR_BITBRAIN_ADAPT_EVERY
TR_BITBRAIN_NET_RESET_ON_TARGET 1 wipe the SBC counters when the enemy id changes

HOW TO TURN IT ON

TR_BITBRAIN_NET=1            # the master switch — the legacy aliases go quiet
TR_RACK_BITBRAIN=both
TR_RACK_PATTERN=off
TR_BITBRAIN_NETLOG=1

MEASURED SCALING (RAM / ms-per-tick / quality)

common_libs/tests/measure_bitbrain_scaling.nim, replaying 3 recorded live runs (37 412 recorded ticks, 149 650 tick × power-bin samples), -d:release, single-threaded, one predict per power bin per tick — the same call pattern as the live loop. The timed region contains only the gun's predict calls: the interception solve is done once, up front, so the ruler's own cost cannot contaminate the timing.

arm in nCl nAde mode RAM B SBC B AD B ms/tick % of 13.16 mean|err|° hit% Pattern|err|°
input-small 26 8 256 counted 1 594 368 1 572 864 21 504 2.60 20 % 17.329 8.00 16.964
input-medium 52 8 256 counted 1 594 368 1 572 864 21 504 2.70 21 % 17.270 8.04 16.964
input-large 84 8 256 counted 1 594 368 1 572 864 21 504 2.54 19 % 17.259 8.06 16.964
classes-small 52 2 256 counted 414 720 393 216 21 504 1.07 8 % 17.201 8.12 16.964
classes-medium 52 8 256 counted 1 594 368 1 572 864 21 504 2.70 21 % 17.270 8.04 16.964
classes-large 52 64 256 counted 12 604 416 12 582 912 21 504 19.56 149 % 17.115 8.27 16.964
nAde-small 52 8 64 counted 103 680 98 304 5 376 0.30 2 % 17.254 8.08 16.964
nAde-medium 52 8 256 counted 1 594 368 1 572 864 21 504 2.72 21 % 17.270 8.04 16.964
nAde-large 52 8 512 counted 6 334 464 6 291 456 43 008 9.76 74 % 17.264 8.03 16.964
mode-bitset 52 8 256 bitset 218 112 196 608 21 504 2.72 21 % 16.975 8.53 16.964
mode-counted 52 8 256 counted 1 594 368 1 572 864 21 504 2.71 21 % 17.270 8.04 16.964

Reproduce:

nim c -r -d:release --path:common_libs common_libs/tests/measure_bitbrain_scaling.nim --limit 3

The scaling laws, as MEASURED

  • RAM is dominated by the SBC tensors (98.6 % at the default). One SBC is nAde² × nClasses cells. Bitset: 1 bit/cell. Counted: 1 byte/cell. The measured counted/bitset factor is 7.30× on the default geometry (1 594 368 / 218 112), which is the bitset tensor's 1/8-of-a-uint32-slot overhead — the tensors are uint32-slot-packed, so 8 classes share slots.
  • RAM vs nClasses: exactly linear. 2 → 8 → 64 classes: 0.41 → 1.59 → 12.60 MB (4× and 32× for 4× and 8× the classes). RAM vs nAde: quadratic — 64 → 256 → 512 gives 0.10 → 1.59 → 6.33 MB (4× then 16× for 4× then 2×).
  • RAM vs input width: FLAT. 26 → 52 → 84 slots: 1 594 368 B in all three cases. The input width only sets how many of the 2^inputWidth synapses the ADE codes may draw from; the codes are still nAde × w per AD. The only width-dependent term is the ADE scoring cost and the tiny AD B column (unchanged here because it is dominated by nAde × w, not by input width).
  • ms/tick vs input width: flat (2.60 / 2.70 / 2.54 ms). vs nClasses: linear (1.07 / 2.70 / 19.56 ms — the 64-class arm busts the 13.16 ms budget at 149 %). vs nAde: quadratic-ish (0.30 / 2.72 / 9.76 ms), because the ADE pass is O(nAde × w) and the SBC read is O(|row| × |col|).
  • counted vs bitset: same time, 7.3× the RAM (2.71 vs 2.72 ms/tick).

Capacity vs accuracy — the direct answer

More capacity buys essentially nothing here; it costs RAM and, past a point, the tick budget. Across a 100× range of RAM (0.10 MB → 12.60 MB) the offline mean |angular error| moves from 17.254° to 17.115° — a 0.14° spread around Pattern's own 16.964°, and the sign of the effect flips across the nClasses axis (17.201° at 2 classes, 17.115° at 64), so it is not a trend, it is noise. The only arm that helps is mode-bitset (16.975° vs 17.270° counted), and even that costs nothing in accuracy terms until you switch to counted for forgetting — at which point you pay 7.3× the RAM and lose the 0.3°.

The honest reading is that the information ceiling here is the state, not the classifier: docs/bitbrain_gate.md measured ~1 bit of information in a 53-bit input, and this sweep reproduces that at 26, 52 and 84 slots alike. The corrector is consistently slightly WORSE than Pattern offline (17.2° vs 17.0°), which is the same verdict the campaign already reached for every additive-shift design. Capacity is not the binding constraint and buying more of it is not the fix.

VETO-CAPABLE CHECK ONLY. Per docs/offline_harness_trust.md this is the single trustworthy use of the offline harness — per-gun single-tick prediction quality on a fixed trajectory. It is not a live result: nothing here says anything about damage, survival or round wins, and it is never presented as one.

Tests

# 42 checks: the gun really engages the network (not just that it links)
nim c -r -d:release --path:common_libs common_libs/tests/test_bitbrain_net.nim
# the library itself (56 checks, unchanged)
nim c -r -d:release --path:common_libs common_libs/tests/test_bitbrain.nim

test_bitbrain_net.nim proves engagement by observation, not by linkage: the network is 0 bytes before first use, two different inputs give different class outputs, a learn visibly raises SBC occupancy, a bitset learn is idempotent while a counted learn is monotone, ADE threshold adaptation runs, and construction + first predict leave the global RNG untouched.