Skip to content

Stateful encoders: LevelEncoder and RandomProjection - #64

Merged
cvigilv merged 2 commits into
mainfrom
encoders
Jul 29, 2026
Merged

Stateful encoders: LevelEncoder and RandomProjection#64
cvigilv merged 2 commits into
mainfrom
encoders

Conversation

@MichielStock

Copy link
Copy Markdown
Collaborator

Summary

Introduces the stateful encoder layer (AbstractEncoder{HV}): encoder objects hold hypervector state built once at construction and slot in as the first argument of encode, with decode as the inverse. Two members land here.

LevelEncoder — scalars (breaking)

  • Replaces and deletes the level / encodelevel / decodelevel / convertlevel family, no deprecation shims (package is unregistered). The old design rebuilt the level set per call, so separate calls produced incomparable encodings (TODO §1.4/§1.4b); the struct builds the level set once, fixing this by construction.
  • Two mechanisms by dispatch: a perturbation ladder for all seven types (bandwidth = flip fraction per step, exposed as a keyword) and fractional power encoding for FHRR (continuous, β bandwidth; explicit level count requests a ladder instead).
  • decode is nearest-neighbour by similarity (robust); FHRR additionally offers method = :analytic for clean vectors.

RandomProjection — feature vectors

  • x ∈ ℝᵈ ↦ nonlinearity(R·x) with a fixed D × d matrix (:gaussian, :bipolar, :sparse_ternary), per-type nonlinearities, and a parametric scalar-or-vector ternary threshold θ (plus a data-driven target_sparsity constructor and rethreshold sharing R).
  • Immutable, no fit; supplied-matrix constructor for reproducible/saved projections.
  • decode(rp, hv, references) is nearest-neighbour clean-up only — a random projection is lossy, so no fake analytic inverse is offered; calling without a codebook errors.
  • FHRR + :gaussian is exactly a Rahimi–Recht random Fourier feature map (similarity ≈ Gaussian kernel with bandwidth β), locked by a kernel-identity test.

Shared machinery

  • New internal phase_encode(z, β) is the single FHRR phase-encoding primitive; both LevelEncoder's fractional power path and RandomProjection's FHRR nonlinearity route through it (equality-locked in tests).

Test hardening

  • Regression testsets for two known sharp edges: the ternary constructor's positional collision (supplied matrix vs training data — residual square-matrix ambiguity and silently ignored kwargs recorded as TODO §2.6 for a follow-up rename) and BipolarHV's raw-bits / zero-state polarity traps, pinned so the obvious-but-wrong idioms trip red tests.

Test plan

  • Full suite: 825 assertions across types/operations/encoding/inference/representations/extension, all passing
  • Doctests machine-generated via doctest(fix = true) and verified in a fresh process (same invocation as the CI doctests job)
  • runic --check clean on all touched files

🤖 Generated with Claude Code

MichielStock and others added 2 commits July 15, 2026 10:36
Completes the stateful AbstractEncoder pair begun with LevelEncoder:

- RandomProjection{HV, T}: fixed D×d projection matrix (gaussian /
  bipolar / sparse_ternary), per-type nonlinearities, scalar-or-vector
  ternary threshold θ with a data-driven target_sparsity constructor,
  supplied-matrix constructor, rethreshold sharing R, and
  nearest-neighbour-only decode (lossy encoding: no analytic inverse).
- phase_encode(z, β): single shared FHRR phase-encoding helper; both
  LevelEncoder's fractional power path and RandomProjection's FHRR
  nonlinearity (random Fourier features) route through it.
- Regression tests for two known sharp edges: the ternary constructor's
  positional collision (supplied matrix vs training data; the residual
  square-matrix ambiguity and silently ignored kwargs are recorded as
  TODO §2.6, fix is a follow-up rename) and BipolarHV's raw-bits /
  zero-state polarity traps, pinned as behaviour-locking tests so the
  obvious-but-wrong idioms trip red instead of shipping corruption.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cvigilv

cvigilv commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

This looks good, I would merge this to main, merge it against #63, update tutorials and then merge that to main. LMKWYT

@MichielStock
MichielStock requested a review from cvigilv July 16, 2026 07:11
This was referenced Jul 27, 2026
@MichielStock

Copy link
Copy Markdown
Collaborator Author

Superseded by #66.

This branch is merged into #66, which combines it with the tutorial work. The encoder side is unchanged; #66 adds the documentation that goes with it (LevelEncoder and RandomProjection had no tutorial coverage at all) and ports iris.jl, which used all four of the level/encodelevel/decodelevel/convertlevel functions this PR removes.

Merging this alone would leave main with docs that fail to build, which is why the two were combined. Closing in favour of #66 seems right, but leaving that to you.

@cvigilv
cvigilv merged commit 8776f94 into main Jul 29, 2026
3 of 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.

2 participants