A clean-room, standalone Rust port of Hierarchical Temporal Memory (HTM) — the algorithm architecture whose reference implementation is htm.core (C++/Python), the community continuation of Numenta's NuPIC. Pinned to upstream commit bef3088.
HTM models a cortical region as a sheet of minicolumns learning sparse distributed representations of a stream. A spatial pooler turns each input into a fixed-sparsity SDR; a temporal memory learns which cells follow which, so that on each step some cells are predictive — and an input that no cell predicted makes its column burst, which is the anomaly signal.
This is a standalone, self-contained crate. It was extracted from the dcc-core workspace and now builds and versions independently, with no dependency on dcc-core.
Core inference stack ported. Random (a faithful std::mt19937), Sdr, Connections, SpatialPooler, TemporalMemory (incl. external predictive inputs), Classifier/Predictor, ScalarEncoder, Rdse, DateEncoder, SimHashDocumentEncoder (+ a SHAKE256 port), SdrMetrics, AnomalyLikelihood, and serde save/load.
Deferred: NetworkAPI/Regions, and Cereal-byte-compatible serialization. Save/load here is Rust-native serde — it round-trips within this crate but is not byte-compatible with htm.core's Cereal format.
Demos: six runnable examples under examples/, documented in doc/Demos.md.
cargo run --release --example high_order_sequence
cargo run --release --example noise_robustness -- --sweep noise=0,0.4,0.45,0.5 --repeat 5Three of them — high_order_sequence, classify_stream and noise_robustness — implement a demo contract shared with the sibling ports dcc-sph and dcc-sparsey, so an experiment run against any of the three takes the same flags and emits the same JSONL records. The three repositories share no code and cannot: this crate is AGPL-3.0 and dcc_sph is CC BY-NC-SA 4.0, which do not mix. The other three demos show what HTM does that the siblings cannot — anomaly_stream, spatial_pooling and multistep_predict.
examples/support/pipeline.rs is worth reading on its own: it is the encoder → SpatialPooler → TemporalMemory → Classifier wiring this crate does not otherwise provide, NetworkAPI being deferred.
- Bit-exact parity with htm.core — seeded runs reproduce the C++ SDR and cell streams exactly
- Faithful RNG —
Randomis a realstd::mt19937, which is what makes the above possible - Full encoder set — scalar, RDSE, date/time, and SimHash document encoding
- Anomaly detection — raw anomaly score plus
AnomalyLikelihood's distribution-based refinement - Classification —
Classifier/Predictorfor supervised readout over SDRs - Dependency-light —
serdeis the only runtime dependency
Requires a Rust toolchain (stable).
git clone https://github.com/jacobeverist/dcc-htm
cd dcc-htm
cargo build # build the library
cargo test # unit + integration + determinism testsTo use it from another crate:
[dependencies]
dcc_htm = { git = "https://github.com/jacobeverist/dcc-htm" }| Term | Meaning |
|---|---|
| SDR | Sparse Distributed Representation — a large binary vector with few active bits. The universal currency between every component here. |
| Minicolumn | A group of cells sharing one proximal (feed-forward) receptive field. The spatial pooler selects a sparse set of columns; the temporal memory picks cells within them. |
| Proximal / distal | Proximal synapses carry feed-forward input (column selection); distal synapses carry lateral context from other cells (prediction). |
| Spatial pooler | Maps an input SDR to a fixed-sparsity column SDR, with boosting to keep column usage even. |
| Temporal memory | Learns cell→cell transitions so the next step is partially predicted; unpredicted input bursts its column. |
| Predictive / bursting | A cell is predictive when enough distal synapses are active. A column bursts when its input arrived unpredicted — the raw anomaly signal. |
| Anomaly score | Fraction of active columns that burst, in [0, 1]. AnomalyLikelihood turns that into a distribution-relative probability. |
Full vocabulary, with the upstream C++ name beside each so a reader can move between this crate and htm.core without guessing: doc/NameReference.md.
use dcc_htm::{Sdr, SpatialPooler};
let mut sp = SpatialPooler::new(
vec![100], vec![64], 16, 0.5, true, 0.1, 0, 1,
0.008, 0.05, 0.1, 0.001, 1000, 0.0, /*seed*/ 1, /*wrap*/ true);
let mut input = Sdr::new(vec![100]);
let mut active = Sdr::new(vec![64]);
input.set_sparse(vec![1, 5, 9, 13, 17]);
sp.compute(&input, /*learn*/ true, &mut active);- Encode:
ScalarEncoder,Rdse,DateEncoder,SimHashDocumentEncoder→ anSdr. - Pool:
SpatialPooler::compute(&input, learn, &mut active)— input SDR to column SDR. - Predict:
TemporalMemory—compute/activate_cells/activate_dendrites, plusanomaly()and external predictive inputs. - Read out:
Classifier/Predictorfor supervised inference;argmaxfor the winning category. - Measure:
Metrics,Sparsity,Overlap,ActivationFrequency(SdrMetrics);AnomalyLikelihoodfor distribution-relative anomaly. - Low level:
Connections(synapse/segment store),Random(thestd::mt19937port),AnMode.
| Document | Description |
|---|---|
doc/UserGuide.md |
Full user guide: concepts, API, worked usage |
doc/Architecture.md |
Component structure and how the pieces compose |
doc/Tuning.md |
Parameter descriptions and tuning advice |
doc/NameReference.md |
HTM vocabulary with the upstream C++ name beside each |
doc/PortNotes.md |
Mapping from C++ names/types to Rust equivalents |
doc/MethodFidelity.md |
Method-by-method correspondence with htm.core |
doc/Divergences.md |
Where this port intentionally differs, and why |
src/
lib.rs — crate root and public re-exports
random.rs — std::mt19937 port; the keystone of bit-exactness
sdr.rs — Sdr: the sparse binary representation
connections.rs — synapse/segment store shared by the learners
spatial_pooler.rs — SpatialPooler
temporal_memory.rs — TemporalMemory, AnMode
classifier.rs — Classifier, Predictor, argmax
encoders.rs — ScalarEncoder, Rdse, DateEncoder
simhash.rs — SimHashDocumentEncoder (+ SHAKE256)
sdr_metrics.rs — Metrics, Sparsity, Overlap, ActivationFrequency
anomaly_likelihood.rs — AnomalyLikelihood
topology.rs — neighbourhood/wrapping helpers
types.rs — shared numeric types
tests/
fidelity.rs — C++ golden comparison (skips without the fixture)
serialization.rs — serde round-trips
fixtures/ — committed golden data
fidelity/ — harness for regenerating fixtures (needs an htm.core checkout)
doc/ — documentation
This is a transliteration, not an idiomatic rewrite. Module and function names, and loop structure, deliberately mirror the C++ so doc/MethodFidelity.md can be audited method by method. That is why several clippy lints are allowed at the crate root — see the comment block in src/lib.rs, particularly approx_constant: htm.core computes 0.5 * erfc(z / 1.4142) with that literal, and 1.4142 != SQRT_2, so "fixing" it would silently change every anomaly likelihood this crate produces.
The port targets bit-exact parity with htm.core. The keystone is random::Random, a faithful std::mt19937 reimplementation — every algorithm draws from it in the same order as the C++, so seeded runs reproduce the C++ SDR and cell streams exactly.
cargo test runs the unit and determinism tests everywhere. The C++ golden comparison runs when the committed fixture is present and skips with a notice when it is not, so a checkout with no htm.core beside it is still green. See fidelity/README.md and doc/MethodFidelity.md.
json-schema— derivesschemarsJSON Schema for the config types (cargo build --features json-schema).
AGPL-3.0-only, matching htm.core — whose source headers say "version 3" with no "or any later version". Full text in LICENSE.
Copyright (c) 2026 Jacob Everist, for the Rust port. Upstream copyright and license notices are preserved in the ported sources.
Upstream is htm-community/htm.core. The htm.core README asks to be cited; that citation, the pinned upstream commit, and the attribution notices are in PROVENANCE.md.