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

HDCEncoder dataclass

Hyperdimensional Computing Encoder. Dimension D usually >= 10,000.

Source code in src/sc_neurocore/hdc/base.py
Python
17
18
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
@dataclass
class HDCEncoder:
    """
    Hyperdimensional Computing Encoder.
    Dimension D usually >= 10,000.
    """

    dim: int = 10000

    def generate_random_vector(self) -> np.ndarray:
        """Generates a random D-dimensional bipolar vector {-1, 1} or {0, 1}."""
        # We use {0, 1} for compatibility with our SC
        return np.random.randint(0, 2, self.dim).astype(np.uint8)

    def bind(self, v1: np.ndarray, v2: np.ndarray) -> np.ndarray:
        """XOR Binding operation."""
        return np.bitwise_xor(v1, v2)

    def bundle(self, vectors: list[np.ndarray]) -> np.ndarray:
        """
        Majority Bundling (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

        return (sum_vec > threshold).astype(np.uint8)

    def permute(self, v: np.ndarray, shifts: int = 1) -> np.ndarray:
        """Cyclic shift (Permutation)."""
        return np.roll(v, shifts)

generate_random_vector()

Generates a random D-dimensional bipolar vector {-1, 1} or {0, 1}.

Source code in src/sc_neurocore/hdc/base.py
Python
26
27
28
29
def generate_random_vector(self) -> np.ndarray:
    """Generates a random D-dimensional bipolar vector {-1, 1} or {0, 1}."""
    # We use {0, 1} for compatibility with our SC
    return np.random.randint(0, 2, self.dim).astype(np.uint8)

bind(v1, v2)

XOR Binding operation.

Source code in src/sc_neurocore/hdc/base.py
Python
31
32
33
def bind(self, v1: np.ndarray, v2: np.ndarray) -> np.ndarray:
    """XOR Binding operation."""
    return np.bitwise_xor(v1, v2)

bundle(vectors)

Majority Bundling (Superposition).

Source code in src/sc_neurocore/hdc/base.py
Python
35
36
37
38
39
40
41
42
43
44
45
46
def bundle(self, vectors: list[np.ndarray]) -> np.ndarray:
    """
    Majority Bundling (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

    return (sum_vec > threshold).astype(np.uint8)

permute(v, shifts=1)

Cyclic shift (Permutation).

Source code in src/sc_neurocore/hdc/base.py
Python
48
49
50
def permute(self, v: np.ndarray, shifts: int = 1) -> np.ndarray:
    """Cyclic shift (Permutation)."""
    return np.roll(v, shifts)

AssociativeMemory dataclass

Simple HDC Associative Memory (Clean-Up Memory). Stores (Key, Value) pairs or just prototypes.

Source code in src/sc_neurocore/hdc/base.py
Python
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
@dataclass
class AssociativeMemory:
    """
    Simple HDC Associative Memory (Clean-Up Memory).
    Stores (Key, Value) pairs or just prototypes.
    """

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

    def __post_init__(self) -> None:
        pass

    def store(self, label: str, vector: np.ndarray) -> None:
        self.memory[label] = vector

    def query(self, query_vec: np.ndarray) -> str | None:
        """Returns label of closest vector (Hamming Distance)."""
        best_label = None
        min_dist = float("inf")

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

        return best_label

query(query_vec)

Returns label of closest vector (Hamming Distance).

Source code in src/sc_neurocore/hdc/base.py
Python
68
69
70
71
72
73
74
75
76
77
78
79
80
def query(self, query_vec: np.ndarray) -> str | None:
    """Returns label of closest vector (Hamming Distance)."""
    best_label = None
    min_dist = float("inf")

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

    return best_label