Skip to content

examples/static_net: slots instead of Features/Slot<i>/Store<i>; compare_emlearn and the generators with it - #6

Merged
neu-rah merged 1 commit into
mainfrom
static-net-slots
Sep 30, 2026
Merged

neu-rah merged 1 commit into
mainfrom
static-net-slots

Conversation

@neu-rah

@neu-rah neu-rah commented Sep 30, 2026

Copy link
Copy Markdown
Member

What

examples/static_net on the slot core merged in #5 (hapi/slots.h). The values a net reads are now the slots of a state, read by tag: Field<Tag,&S::m> for a field, Elem<Tag,&S::arr,k> for an element of an array field. No hand-typed slot index is left (the old Features<N> array and its Slot<i> / Store<i> / x<i> / Wave<n> / In<n> / T<n> are gone): inputs are named (the Banknote features by their dataset names, a 60-band input is one array field), cells stay pure proc(in), and a value that survives a pass is a register, a layer of the state whose step evaluates cells on the previous state (include/registers.h, the example's own contract on the core; update/Store<i> wrote into the array being read, which cannot be right for two registers that read each other).

The example uses the HAPI core alone: no names, no hash, no wire format, nothing from another library.

In the same change, so the example is never half-converted:

  • compare_emlearn/: gen_models.py names the four features once and writes BNC_COL_* and typed sources; the committed bnc_rows.h, bnc_lin.h, bnc_wave.h, bnc.cpp are what it writes. bnc_table.h and the emlearn models stay positional on purpose (they are the hand-indexed comparison points).
  • train/bn2x.c and gen_lin_sonar.py emit the named forms directly, so a retraining cannot reintroduce a positional mapping.
  • README (this example's and HAPI's paragraph), CHANGELOG (the 0.8.0 bullet).

Checked, against the example as it is on main (18b8d77, extracted with git archive)

  • Same behaviour: the 12 host programs of check/ print the same bytes (g++ and clang++, ASan+UBSan); src/main.cpp prints agree 274/274, correct 274/274.
  • Same code: the flashed image (.text + .data) of 21 AVR programs is byte-identical (27 372 bytes: mixed, refid, sugar, the Sonar cells, roll unrolled/rolled/sparse, the Banknote board program, the simavr bit-exact program, the measure/ programs).
  • check/build.sh: 65 ok, 0 FAIL (the 61 checks it had, sizes unchanged, plus 4 for registers). tests/single_header/run.sh: 36 ok (the converted example's AVR programs and the bnc models are identical built from include/ and from single/hapi.h).
  • compare_emlearn: run.sh over every model on the simulated ATmega328p regenerates results.md identical to the committed one; gen_models.py, run (numpy 2.5.3, scikit-learn 1.9.1, emlearn 0.23.2), writes all 22 generated files exactly as committed; the Sonar pipeline and the 8-minute bn2x retraining reproduce models/sonar/ and models/banknote/ byte for byte.
  • One register example is wrong in the old design and right in the new: (a,b)' = (b, a+b) in place was wrong on 30 of 30 passes, on the previous state 0 of 30 (check/registers_check.cpp; the same step as a hand-indexed array is the same size, registers_avr.cpp).

Not checked

platformio.ini's own environments were not run (the file://../.. dependency copies a whole tree); src/main.cpp was built with the same flags natively and compiled for the Uno against the Arduino core (syntax only). CI does not build this example (GCC/Clang, AVR), so its checks are the ones listed above.

🤖 Generated with Claude Code

…ompare_emlearn and the generators with it

The values a net reads are the slots of a state (hapi/slots.h), read by tag: Field<Tag,&S::m> for a field, Elem<Tag,&S::arr,k> for an
element of an array field. No hand-typed slot index is left: inputs are named (the Banknote features by their dataset names; a 60-band
input is one array field), cells stay pure proc(in), and a value that survives a pass is a register, a layer of the state whose step
evaluates cells on the previous state (registers.h). Two registers that read each other are now right.

compare_emlearn/ and its generator follow in the same change (gen_models.py names the four features once, writes BNC_COL_* and typed
sources), and so do train/bn2x.c and gen_lin_sonar.py, which emit the named forms directly. bnc_table.h and the emlearn models stay
positional: they are the hand-indexed comparison points.

Against this example as it was at 18b8d77: the 12 host programs of check/ print the same bytes, the flashed image of 21 AVR programs is
byte-identical, src/main.cpp prints the same, compare_emlearn measures the same on the simulated ATmega328p. check/build.sh: 65 ok
(61 as before, plus the register checks). tests/single_header/run.sh: 36 ok.

From R&D/HAPI/typedState @ 2a40b60.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@neu-rah
neu-rah merged commit 2ab588d into main Sep 30, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant