Skip to content

Hyper-Dimensional Computing — Binary Vector Algebra

High-dimensional binary vector algebra for symbolic reasoning in spiking networks. HDC maps naturally to stochastic computing hardware: bind = XOR gate, bundle = popcount tree, similarity = Hamming distance.

Theory

HDC represents symbols as random binary vectors of dimension D (typically D >= 10,000). At high D, random vectors are quasi-orthogonal with high probability: E[d_H(a,b)] = D/2. Three operations form an algebra:

Operation Implementation Property
Bind (⊗) XOR Self-inverse: a ⊗ a = 0, a ⊗ b ⊗ b = a
Bundle (⊕) Majority vote Preserves similarity to all inputs
Permute (ρ) Cyclic shift Breaks commutativity for ordered structures

Components

  • HDCEncoder — Generate random D-dimensional binary vectors and perform algebraic operations.
Parameter Default Meaning
dim 10000 Hypervector dimension

Methods: generate_random_vector(), bind(v1, v2), bundle(vectors), permute(v, shifts).

  • AssociativeMemory — Clean-up memory via Hamming distance nearest-neighbor lookup. Store labeled vectors, retrieve by similarity. Tolerates up to ~35% bit noise.

Usage

Python
from sc_neurocore.hdc import HDCEncoder, AssociativeMemory
import numpy as np

np.random.seed(42)
enc = HDCEncoder(dim=10000)

# Create symbols
country = enc.generate_random_vector()
capital = enc.generate_random_vector()
usa = enc.generate_random_vector()
washington = enc.generate_random_vector()

# Encode: USA_record = bind(country, usa) ⊕ bind(capital, washington)
record = enc.bundle([
    enc.bind(country, usa),
    enc.bind(capital, washington),
])

# Query: "What is the capital of USA?" → bind(record, capital)
query = enc.bind(record, capital)

# Store in associative memory and retrieve
mem = AssociativeMemory()
mem.store("washington", washington)
mem.store("usa", usa)
print(mem.query(query))  # → "washington"

See Tutorial 4: Hyper-Dimensional Computing.

sc_neurocore.hdc.base

Hyperdimensional computing encoder and associative clean-up memory.

HDCEncoder dataclass

Hyperdimensional computing encoder.

Dimension D is usually >= 10,000.

Source code in src/sc_neurocore/hdc/base.py
Python
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
@dataclass
class HDCEncoder:
    """Hyperdimensional computing encoder.

    Dimension D is usually >= 10,000.
    """

    dim: int = 10000

    def generate_random_vector(self) -> np.ndarray[Any, Any]:
        """Generate a random D-dimensional binary vector in {0, 1}."""
        # We use {0, 1} for compatibility with our SC
        vector: np.ndarray[Any, Any] = np.random.randint(0, 2, self.dim).astype(np.uint8)
        return vector

    def bind(self, v1: np.ndarray[Any, Any], v2: np.ndarray[Any, Any]) -> np.ndarray[Any, Any]:
        """Bind two hypervectors via XOR."""
        bound: np.ndarray[Any, Any] = np.bitwise_xor(v1, v2)
        return bound

    def bundle(self, vectors: list[np.ndarray[Any, Any]]) -> np.ndarray[Any, Any]:
        """Bundle hypervectors by majority superposition."""
        if not vectors:
            return np.zeros(self.dim, dtype=np.uint8)

        # Sum columns
        sum_vec = np.sum(vectors, axis=0)
        threshold = len(vectors) / 2.0

        bundled: np.ndarray[Any, Any] = (sum_vec > threshold).astype(np.uint8)
        return bundled

    def permute(self, v: np.ndarray[Any, Any], shifts: int = 1) -> np.ndarray[Any, Any]:
        """Permute a hypervector by a cyclic shift."""
        shifted: np.ndarray[Any, Any] = np.roll(v, shifts)
        return shifted

generate_random_vector()

Generate a random D-dimensional binary vector in {0, 1}.

Source code in src/sc_neurocore/hdc/base.py
Python
28
29
30
31
32
def generate_random_vector(self) -> np.ndarray[Any, Any]:
    """Generate a random D-dimensional binary vector in {0, 1}."""
    # We use {0, 1} for compatibility with our SC
    vector: np.ndarray[Any, Any] = np.random.randint(0, 2, self.dim).astype(np.uint8)
    return vector

bind(v1, v2)

Bind two hypervectors via XOR.

Source code in src/sc_neurocore/hdc/base.py
Python
34
35
36
37
def bind(self, v1: np.ndarray[Any, Any], v2: np.ndarray[Any, Any]) -> np.ndarray[Any, Any]:
    """Bind two hypervectors via XOR."""
    bound: np.ndarray[Any, Any] = np.bitwise_xor(v1, v2)
    return bound

bundle(vectors)

Bundle hypervectors by majority superposition.

Source code in src/sc_neurocore/hdc/base.py
Python
39
40
41
42
43
44
45
46
47
48
49
def bundle(self, vectors: list[np.ndarray[Any, Any]]) -> np.ndarray[Any, Any]:
    """Bundle hypervectors by majority superposition."""
    if not vectors:
        return np.zeros(self.dim, dtype=np.uint8)

    # Sum columns
    sum_vec = np.sum(vectors, axis=0)
    threshold = len(vectors) / 2.0

    bundled: np.ndarray[Any, Any] = (sum_vec > threshold).astype(np.uint8)
    return bundled

permute(v, shifts=1)

Permute a hypervector by a cyclic shift.

Source code in src/sc_neurocore/hdc/base.py
Python
51
52
53
54
def permute(self, v: np.ndarray[Any, Any], shifts: int = 1) -> np.ndarray[Any, Any]:
    """Permute a hypervector by a cyclic shift."""
    shifted: np.ndarray[Any, Any] = np.roll(v, shifts)
    return shifted

AssociativeMemory dataclass

Simple HDC associative clean-up memory.

Stores (key, value) pairs or bare prototypes for nearest-match retrieval.

Source code in src/sc_neurocore/hdc/base.py
Python
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
@dataclass
class AssociativeMemory:
    """Simple HDC associative clean-up memory.

    Stores (key, value) pairs or bare prototypes for nearest-match retrieval.
    """

    memory: dict[str, Any] = field(default_factory=dict)

    def store(self, label: str, vector: np.ndarray[Any, Any]) -> None:
        """Store a labelled hypervector in the clean-up memory."""
        self.memory[label] = vector

    def query(self, query_vec: np.ndarray[Any, Any]) -> str | None:
        """Return the label of the closest stored vector by Hamming distance."""
        best_label = None
        min_dist = float("inf")

        for label, mem_vec in self.memory.items():
            # Hamming distance = count(XOR)
            dist = float(np.count_nonzero(np.bitwise_xor(query_vec, mem_vec)))
            if dist < min_dist:
                min_dist = dist
                best_label = label

        return best_label

store(label, vector)

Store a labelled hypervector in the clean-up memory.

Source code in src/sc_neurocore/hdc/base.py
Python
66
67
68
def store(self, label: str, vector: np.ndarray[Any, Any]) -> None:
    """Store a labelled hypervector in the clean-up memory."""
    self.memory[label] = vector

query(query_vec)

Return the label of the closest stored vector by Hamming distance.

Source code in src/sc_neurocore/hdc/base.py
Python
70
71
72
73
74
75
76
77
78
79
80
81
82
def query(self, query_vec: np.ndarray[Any, Any]) -> str | None:
    """Return the label of the closest stored vector by Hamming distance."""
    best_label = None
    min_dist = float("inf")

    for label, mem_vec in self.memory.items():
        # Hamming distance = count(XOR)
        dist = float(np.count_nonzero(np.bitwise_xor(query_vec, mem_vec)))
        if dist < min_dist:
            min_dist = dist
            best_label = label

    return best_label