Skip to content

I/O API Reference

JSON-based persistence for VSA basis vectors.

Overview

The I/O module provides two functions for saving and loading basis vectors:

  • save_basis() - Save VSAMemory to JSON file
  • load_basis() - Load VSAMemory from JSON file

Both functions work with all three VSA models (FHRR, MAP, Binary).

Functions

save_basis

vsax.io.save_basis(memory, path)

Save VSAMemory basis vectors to a JSON file.

Parameters:

Name Type Description Default
memory VSAMemory

VSAMemory instance containing named basis vectors

required
path Union[str, Path]

File path to save JSON (will be created/overwritten)

required
Example

model = create_fhrr_model(dim=128) memory = VSAMemory(model) memory.add_many(["apple", "orange", "banana"]) save_basis(memory, "fruit_basis.json")

Source code in vsax/io/save.py
def save_basis(memory: VSAMemory, path: Union[str, Path]) -> None:
    """Save VSAMemory basis vectors to a JSON file.

    Args:
        memory: VSAMemory instance containing named basis vectors
        path: File path to save JSON (will be created/overwritten)

    Example:
        >>> model = create_fhrr_model(dim=128)
        >>> memory = VSAMemory(model)
        >>> memory.add_many(["apple", "orange", "banana"])
        >>> save_basis(memory, "fruit_basis.json")
    """
    path = Path(path)

    # Determine representation type
    rep_cls = memory.model.rep_cls
    if rep_cls == ComplexHypervector:
        rep_type = "complex"
    elif rep_cls == RealHypervector:
        rep_type = "real"
    elif rep_cls == BinaryHypervector:
        rep_type = "binary"
    else:
        raise ValueError(f"Unknown representation type: {rep_cls}")

    # Prepare data structure
    data: dict[str, Any] = {
        "metadata": {
            "dim": memory.model.dim,
            "rep_type": rep_type,
            "num_vectors": len(memory._symbols),
        },
        "vectors": {},
    }

    # Serialize each vector
    for name, hv in memory._symbols.items():
        vec = hv.vec

        if rep_type == "complex":
            # Split complex into real and imaginary parts
            data["vectors"][name] = {
                "real": vec.real.tolist(),
                "imag": vec.imag.tolist(),
            }
        elif rep_type == "real":
            # Store real vector
            data["vectors"][name] = vec.tolist()
        elif rep_type == "binary":
            # Store binary/bipolar vector as integers
            data["vectors"][name] = vec.astype(int).tolist()

    # Write to file
    with open(path, "w") as f:
        json.dump(data, f, indent=2)

Example:

from vsax import create_fhrr_model, VSAMemory, save_basis

model = create_fhrr_model(dim=512)
memory = VSAMemory(model)
memory.add_many(["dog", "cat", "animal"])

save_basis(memory, "animals.json")

load_basis

vsax.io.load_basis(memory, path)

Load basis vectors from a JSON file into VSAMemory.

Parameters:

Name Type Description Default
memory VSAMemory

VSAMemory instance to populate (must be empty)

required
path Union[str, Path]

File path to load JSON from

required

Raises:

Type Description
ValueError

If dimension or representation type doesn't match

ValueError

If memory is not empty

FileNotFoundError

If file doesn't exist

Example

model = create_fhrr_model(dim=128) memory = VSAMemory(model) load_basis(memory, "fruit_basis.json") "apple" in memory True

Source code in vsax/io/load.py
def load_basis(memory: VSAMemory, path: Union[str, Path]) -> None:
    """Load basis vectors from a JSON file into VSAMemory.

    Args:
        memory: VSAMemory instance to populate (must be empty)
        path: File path to load JSON from

    Raises:
        ValueError: If dimension or representation type doesn't match
        ValueError: If memory is not empty
        FileNotFoundError: If file doesn't exist

    Example:
        >>> model = create_fhrr_model(dim=128)
        >>> memory = VSAMemory(model)
        >>> load_basis(memory, "fruit_basis.json")
        >>> "apple" in memory
        True
    """
    path = Path(path)

    # Check that memory is empty
    if len(memory._symbols) > 0:
        raise ValueError(
            f"Memory must be empty to load basis. "
            f"Current memory contains {len(memory._symbols)} vectors."
        )

    # Load JSON file
    with open(path) as f:
        data = json.load(f)

    # Validate metadata
    metadata = data["metadata"]
    saved_dim = metadata["dim"]
    saved_rep_type = metadata["rep_type"]

    # Check dimension matches
    if saved_dim != memory.model.dim:
        raise ValueError(
            f"Dimension mismatch: memory has dim={memory.model.dim}, but file has dim={saved_dim}"
        )

    # Check representation type matches
    rep_cls = memory.model.rep_cls
    if rep_cls == ComplexHypervector:
        expected_type = "complex"
    elif rep_cls == RealHypervector:
        expected_type = "real"
    elif rep_cls == BinaryHypervector:
        expected_type = "binary"
    else:
        raise ValueError(f"Unknown representation type: {rep_cls}")

    if saved_rep_type != expected_type:
        raise ValueError(
            f"Representation type mismatch: memory expects {expected_type}, "
            f"but file has {saved_rep_type}"
        )

    # Load vectors
    vectors_data = data["vectors"]

    for name, vec_data in vectors_data.items():
        if saved_rep_type == "complex":
            # Reconstruct complex vector from real and imaginary parts
            real_part = jnp.array(vec_data["real"], dtype=jnp.float32)
            imag_part = jnp.array(vec_data["imag"], dtype=jnp.float32)
            vec = real_part + 1j * imag_part
        elif saved_rep_type == "real":
            # Reconstruct real vector
            vec = jnp.array(vec_data, dtype=jnp.float32)
        elif saved_rep_type == "binary":
            # Reconstruct binary vector
            vec = jnp.array(vec_data, dtype=jnp.float32)
        else:
            raise ValueError(f"Unknown rep_type: {saved_rep_type}")

        # Create hypervector and add to memory
        hv = rep_cls(vec)
        memory._symbols[name] = hv

Example:

from vsax import create_fhrr_model, VSAMemory, load_basis

model = create_fhrr_model(dim=512)
memory = VSAMemory(model)

load_basis(memory, "animals.json")
print(f"Loaded {len(memory._vectors)} vectors")

JSON Format

FHRR (Complex Vectors)

Complex hypervectors are stored with separate real and imaginary parts:

{
  "metadata": {
    "dim": 512,
    "rep_type": "complex",
    "num_vectors": 2
  },
  "vectors": {
    "dog": {
      "real": [0.12, -0.34, 0.56, ...],
      "imag": [0.78, -0.23, 0.45, ...]
    },
    "cat": {
      "real": [-0.67, 0.89, -0.12, ...],
      "imag": [0.34, 0.56, -0.78, ...]
    }
  }
}

MAP (Real Vectors)

Real hypervectors are stored as simple float arrays:

{
  "metadata": {
    "dim": 512,
    "rep_type": "real",
    "num_vectors": 2
  },
  "vectors": {
    "red": [0.23, -0.45, 0.67, ...],
    "blue": [-0.12, 0.34, -0.56, ...]
  }
}

Binary (Bipolar Vectors)

Binary hypervectors are stored as integer arrays:

{
  "metadata": {
    "dim": 1000,
    "rep_type": "binary",
    "num_vectors": 2
  },
  "vectors": {
    "x": [-1, 1, -1, 1, -1, ...],
    "y": [1, -1, 1, 1, -1, ...]
  }
}

Error Handling

Dimension Mismatch

from vsax import create_fhrr_model, VSAMemory, save_basis, load_basis

# Save with dim=128
model_128 = create_fhrr_model(dim=128)
memory_128 = VSAMemory(model_128)
memory_128.add("test")
save_basis(memory_128, "test.json")

# Try to load with dim=256
model_256 = create_fhrr_model(dim=256)
memory_256 = VSAMemory(model_256)

try:
    load_basis(memory_256, "test.json")
except ValueError as e:
    print(e)  # Dimension mismatch: memory has dim=256, but file has dim=128

Representation Type Mismatch

from vsax import create_fhrr_model, create_map_model

# Save FHRR
fhrr_memory = VSAMemory(create_fhrr_model(dim=128))
fhrr_memory.add("test")
save_basis(fhrr_memory, "test.json")

# Try to load as MAP
map_memory = VSAMemory(create_map_model(dim=128))

try:
    load_basis(map_memory, "test.json")
except ValueError as e:
    print(e)  # Representation type mismatch: memory expects real, but file has complex

Non-Empty Memory

memory = VSAMemory(create_fhrr_model(dim=128))
memory.add("existing_vector")

try:
    load_basis(memory, "test.json")
except ValueError as e:
    print(e)  # Memory must be empty to load basis. Current memory contains 1 vectors.

Use Cases

Persistent Semantic Spaces

# Build once
model = create_fhrr_model(dim=1024)
memory = VSAMemory(model)
memory.add_many(["concept1", "concept2", ...])
save_basis(memory, "knowledge_base.json")

# Reuse across sessions
memory_new = VSAMemory(model)
load_basis(memory_new, "knowledge_base.json")

Sharing Vocabularies

# Project A
save_basis(memory_a, "shared_vocab.json")

# Project B (same dimension and model type!)
load_basis(memory_b, "shared_vocab.json")

Reproducible Research

# Version control basis vectors
git add experiment_basis.json
git commit -m "Add basis for reproducibility"

See Also