Skip to main content

Sparse Distributed Memory (SDM) implementation based on Kanerva (1992)

Project description

KanervaSDM

A high-performance C++ implementation of Sparse Distributed Memory (SDM) with Python bindings, based on Pentti Kanerva's 1992 technical report.

Overview

Sparse Distributed Memory is a cognitive model that stores information in a distributed manner across many locations. This implementation provides:

  • Fast C++ core with Python bindings via pybind11.
  • Hamming distance-based activation for memory retrieval.
  • Support for arbitrary address and memory dimensions.
  • Reproducible results with seeded random initialization.

Installation

From Source

git clone https://github.com/made-by-simon/KanervaSDM.git
cd KanervaSDM
pip install .

Development Installation

pip install -e ".[dev]"

Requirements

  • Python >= 3.7.
  • C++11 compatible compiler.
  • pybind11 >= 2.6.0.

Quick Start

import kanerva_sdm

# Initialize SDM with 100-dimensional addresses and memories
sdm = kanerva_sdm.KanervaSDM(
    address_dimension=100,
    memory_dimension=100,
    num_locations=1000,
    hamming_threshold=37,
    random_seed=42
)

# Write a memory to an address
address = [0, 1] * 50  # Binary address vector
memory = [1, 0] * 50   # Binary memory vector
sdm.write(address, memory)

# Read memory back
recalled = sdm.read(address)
print(f"Recalled memory: {recalled}")

# Check memory count
print(f"Stored memories: {sdm.memory_count}")

API Reference

KanervaSDM

Main class for Sparse Distributed Memory operations.

Initialization

KanervaSDM(
    address_dimension: int,
    memory_dimension: int,
    num_locations: int,
    hamming_threshold: int,
    random_seed: int = 42
)

Parameters:

  • address_dimension: Length of address vectors (N).
  • memory_dimension: Length of memory vectors (U).
  • num_locations: Number of hard locations (M).
  • hamming_threshold: Hamming distance threshold for activation (H).
  • random_seed: Seed for reproducible random generation.

Raises:

  • ValueError: If any dimension or threshold is non-positive.

Methods

write(address, memory)

Store a memory at the given address.

sdm.write([0, 1, 0, 1], [1, 1, 0, 0])

Parameters:

  • address: Binary list of length address_dimension.
  • memory: Binary list of length memory_dimension.

Raises:

  • ValueError: If vectors have incorrect size or contain non-binary values.

read(address)

Retrieve memory from the given address.

recalled = sdm.read([0, 1, 0, 1])

Parameters:

  • address: Binary list of length address_dimension.

Returns:

  • Binary list of length memory_dimension.
  • Returns all zeros if no locations are activated.

Raises:

  • ValueError: If address has incorrect size or contains non-binary values.

erase_memory()

Reset all memory counters to zero while preserving hard locations.

sdm.erase_memory()

Properties

  • address_dimension: Length of address vectors.
  • memory_dimension: Length of memory vectors.
  • num_locations: Number of hard locations.
  • hamming_threshold: Activation threshold.
  • memory_count: Number of stored memories.

How It Works

Core Concepts

  1. Hard Locations (A): Random binary vectors that serve as reference points in the address space.
  2. Memory Matrix (C): Counters that accumulate memory values at each location.
  3. Activation: Locations within Hamming distance H of the query address are activated.
  4. Polar Encoding: Binary values {0,1} are converted to {-1,+1} for storage.

Write Operation

  1. Find all hard locations within Hamming distance H of the target address.
  2. Convert memory vector from binary to polar form.
  3. Add polar values to the memory counters at activated locations.

Read Operation

  1. Find all hard locations within Hamming distance H of the target address.
  2. Sum memory counters across activated locations.
  3. Threshold summation to produce binary output (>= 0 → 1, < 0 → 0).

Examples

Basic Usage

import kanerva_sdm

# Create SDM instance
sdm = kanerva_sdm.KanervaSDM(
    address_dimension=100,
    memory_dimension=100,
    num_locations=1000,
    hamming_threshold=37
)

# Store multiple memories
patterns = [
    ([0]*100, [1]*100),
    ([1]*100, [0]*100),
    ([0,1]*50, [1,0]*50)
]

for addr, mem in patterns:
    sdm.write(addr, mem)

print(f"Total memories stored: {sdm.memory_count}")

# Retrieve a memory
recalled = sdm.read([0]*100)
print(f"Recalled: {recalled[:10]}...")  # First 10 elements

Testing Recall Accuracy

import kanerva_sdm

sdm = kanerva_sdm.KanervaSDM(100, 100, 1000, 37, random_seed=42)

# Store a pattern
original_address = [0, 1] * 50
original_memory = [1, 0] * 50
sdm.write(original_address, original_memory)

# Test recall
recalled = sdm.read(original_address)
accuracy = sum(r == m for r, m in zip(recalled, original_memory)) / len(original_memory)
print(f"Recall accuracy: {accuracy * 100:.1f}%")

Experimenting with Parameters

import kanerva_sdm

# Test different thresholds
for threshold in [30, 35, 40, 45]:
    sdm = kanerva_sdm.KanervaSDM(100, 100, 1000, threshold)
    sdm.write([0]*100, [1]*100)
    recalled = sdm.read([0]*100)
    accuracy = sum(recalled) / len(recalled)
    print(f"Threshold {threshold}: {accuracy * 100:.1f}% ones recalled")

Testing

Run the test suite using pytest:

# Run all tests
pytest tests/

# Run with verbose output
pytest tests/ -v

# Run specific test
pytest tests/test_kanerva_sdm.py::TestKanervaSDM::test_write_and_read

Performance Considerations

  • C++ implementation provides significant speedup over pure Python.
  • Memory operations are O(M × N) where M is num_locations and N is address_dimension.
  • Larger Hamming thresholds activate more locations, increasing computation.
  • Optimal threshold is typically around 40-45% of address_dimension.

Project Structure

kanerva-sdm/
│
├── include/
│   └── kanerva_sdm/
│       └── kanerva_sdm.h          # C++ header
│
├── src/
│   └── kanerva_sdm/
│       ├── __init__.py            # Python package init
│       └── bindings.cpp           # pybind11 bindings
│
├── tests/
│   └── kanerva_sdm/
│       ├── __init__.py
│       └── test_kanerva_sdm.py    # Unit tests
│
├── .gitignore
├── LICENSE
├── MANIFEST.in
├── pyproject.toml
├── README.md
└── setup.py

Reference

This implementation is based on:

Pentti Kanerva (1992). "Sparse Distributed Memory and Related Models."

License

MIT License. See LICENSE for details.

Author

Simon Wong (smw2@ualberta.ca)

Contributing

Contributions are welcome. Please:

  1. Fork the repository.
  2. Create a feature branch.
  3. Add tests for new functionality.
  4. Ensure all tests pass.
  5. Submit a pull request.

Issues

Report bugs and request features at GitHub Issues.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kanervasdm-1.0.1.tar.gz (11.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kanervasdm-1.0.1-cp314-cp314-win_amd64.whl (93.4 kB view details)

Uploaded CPython 3.14Windows x86-64

File details

Details for the file kanervasdm-1.0.1.tar.gz.

File metadata

  • Download URL: kanervasdm-1.0.1.tar.gz
  • Upload date:
  • Size: 11.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for kanervasdm-1.0.1.tar.gz
Algorithm Hash digest
SHA256 7423ecf28fc8f34ad5fadb6d306a092bbdd685505faa66ad3f6b5e65d12a00cb
MD5 6568ae4324a1019a02ed8099e1a7e3aa
BLAKE2b-256 ee11be5b96a8b101a06acdbe5566aa5be319ac395fd00f466da21a22aed24d34

See more details on using hashes here.

File details

Details for the file kanervasdm-1.0.1-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: kanervasdm-1.0.1-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 93.4 kB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for kanervasdm-1.0.1-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 b6fb96298e48cdc865950762c56e477a0264132d4f1d7e02cd499483e39c0e00
MD5 16cdbd8cccde913b4f197363e637001c
BLAKE2b-256 315f78e223f30700d3581ad50903b7c672bdcb14cbb83ecdf365d1845acca2ac

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page