Skip to content

Encoders - #65

Closed
MichielStock wants to merge 25 commits into
docs-new-tutorialsfrom
encoders
Closed

Encoders#65
MichielStock wants to merge 25 commits into
docs-new-tutorialsfrom
encoders

Conversation

@MichielStock

Copy link
Copy Markdown
Collaborator

Same as #64, but moving in docs. Ok to merge @cvigilv ?

cvigilv and others added 25 commits July 13, 2026 17:12
Previously, whenever one called `+` over more than 2 hypervectors, the
operation worked at each pair, that is:

a+b+c+d+e = ((((a+b)+c)+d)+e)

This behaviour breaks the binary hypervectors because at each step it
introduced noise whenever we have a tie. This fix rewrites the `+`
overload so it correctly calls the `bundle` function as an array of
hypervectors instead of pairwise operations. Added some tests to cover
this behaviour.
…verloaded-operations

fix: correct `+` call
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bit true now maps to -1, so XOR on stored bits is exactly the +-1 product.
Sign-based real-vector constructor (zero elements throw, pointing to
TernaryHV), corrected summary labels, regenerated doctests, and
polarity-locking tests (x * x is the all-+1 identity, construction/indexing
round-trip, summary counts).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
perturbate(::FHRR, ...) threw a MethodError (no eldist); dedicated methods
now resample e^(2pi*i*rand()) at the selected positions. Locked by tests
asserting unit modulus, untouched positions, and exact resample counts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The vector decodelevel methods now accept (and ignore) testbound so the
generic forwarding no longer mis-dispatches into a MethodError. Adjacent
bug flagged, not fixed: the instance path builds encoder and decoder over
different random ladders (TODO 1.4b).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
RealHV/GradedHV/GradedBipolarHV results carried the default distr, which
silently changed normalize! numerics. Locked by metadata assertions and a
numerical test that normalize! rescales to the original spread.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Generic shift! and the clamp!-based normalize! methods returned the raw
wrapped vector. Locked by op!(hv) === hv tests for all types and all
in-place operations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
δ was an exported non-const global (type-unstable at call sites).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
isequal compared raw storage across types, so a BinaryHV equalled a
BipolarHV whenever the bits matched; the one-arg hash override was
inconsistent with two-arg hashing. isequal is now a same-type storage
fast path, cross-type comparisons fall back to Base element semantics,
and hashing is element-based. Locked by same-bits/different-type tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The previous fix (2e952a7) let cross-type comparisons fall back to Base
elementwise semantics, but Julia treats Bool as numeric (true == 1), so an
all-true BinaryHV still equalled an all-+1 BipolarHV — whose stored bits are
the exact opposite since the polarity flip. == and isequal between different
hypervector types now return false unconditionally; same-family comparisons
(e.g. TernaryHV{Int8} vs TernaryHV{Int64}) compare by value, and comparisons
against plain vectors keep Base elementwise semantics. Hashing stays on the
element-based AbstractArray fallback: isequal(hv, ::Vector) can be true, so a
type-salted hash would break the hash/equality contract.

Locked by tests covering the numeric-coincidence case, the same-family case,
and the hash contract for all seven types (including BipolarHV, where storage
and elements disagree) and against plain vectors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds the missing encoder layer (raw data in, hypervector out) and gives every
constructor form exactly one meaning:

- encode(HV, x; D) is the canonical deterministic token path (hash -> seed);
  HV(x) is shorthand for it. encode(HV, x, strategy) dispatches on the new
  AbstractEncoding strategies: KMer(k) (windows as atomic hashed tokens —
  resolves #53), NGram(n) (symbol-level shift-binding via ngrams), Sequence()
  (bundlesequence) and BagOfSymbols() (multiset). KMer and NGram are genuinely
  different operations and are documented as such. Extension point: one struct
  subtyping AbstractEncoding plus one encode method.
- HV(n::Number) throws an ArgumentError naming both alternatives (D = n /
  encode(HV, n)); the one-time @warn and its testset are gone.
- Data constructors are widened to AbstractVector{<:Real} and validate each
  type's element domain: BinaryHV {0,1}; BipolarHV strictly ±1 (zero points to
  TernaryHV, no more silent sign-taking); TernaryHV {-1,0,+1} (inner
  constructors stay permissive for operation results); Graded types
  range-checked instead of silently clamped; FHRR unit modulus. Invalid arrays
  throw instead of silently token-encoding — BinaryHV([1, 0]) is now a
  2-element hypervector, killing that trapdoor. Tuples of reals read as data.

BREAKING: numeric constructor tokens throw; graded out-of-range data throws
instead of clamping; bipolar non-±1 data throws instead of sign-coercion;
Vector{<:Real} data construction added for BinaryHV. Also fixes a tutorial
example that constructed an invalid TernaryHV from 0:9 (now RealHV).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The §1.6 fix (9049cb9) is verified correct for every argument form; the
locking test only covered the count form — now also fraction, mask, and
index-vector.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
eldist(hv) now returns hv.distr for RealHV, GradedHV and GradedBipolarHV
instead of falling back to the type default, so perturbate (and level
ladders built from custom-distr hypervectors) draw replacement elements
from the vector's own distribution. Locked by a resampled-element
statistics testset. Closes TODO §1.5c.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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 27, 2026

Copy link
Copy Markdown
Collaborator

Got lost; does this PR contain the contents from #63? #64? I see this as the same PR, but it has some conflicts that the other one doesn't.

@MichielStock

Copy link
Copy Markdown
Collaborator Author

Superseded by #66.

This is the same integration — the encoders branch merged into the tutorial work — but done against docs-new-tutorials, whereas #66 does it against 38-integration.

I went with 38-integration as the base after comparing them: it already sits on top of the #62 merge, and it carries docstrings for shift/shift!/ρ/ρ! plus LaTeX and code-fence fixes that docs-new-tutorials does not have. The two things that branch had and 38-integration lacked — the kitchen-analogy table and the closing wrap-up of the intro tutorial — are merged into #66, so nothing is lost.

@MichielStock

Copy link
Copy Markdown
Collaborator Author

Everything is now in #66. Review and approve this one, #63 and #65 are then outdated

@cvigilv cvigilv closed this Jul 29, 2026
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