Resonator Networks API¶
Overview¶
The resonator module implements resonator networks for VSA factorization.
Given a composite vector s = a ⊙ b ⊙ c, resonator networks iteratively recover the factors a, b, c from known codebooks.
CleanupMemory¶
vsax.resonator.CleanupMemory
¶
Cleanup memory for projecting vectors onto a codebook.
This class implements codebook projection, which finds the nearest vector from a set of known vectors (codebook) to a query vector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
codebook
|
list[str]
|
List of named symbols from VSAMemory to use as codebook. |
required |
memory
|
VSAMemory
|
VSAMemory containing the basis vectors. |
required |
threshold
|
float
|
Optional similarity threshold for cleanup (default: 0.0). If best match is below threshold, returns None. |
0.0
|
Example
model = create_binary_model(dim=10000) memory = VSAMemory(model) memory.add_many(["red", "blue", "green"]) cleanup = CleanupMemory(["red", "blue", "green"], memory) noisy = model.opset.bundle(memory["red"].vec, memory["blue"].vec) result = cleanup.query(noisy) print(result) # Should return "red" or "blue"
Source code in vsax/resonator/cleanup.py
14 15 16 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 51 52 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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | |
Functions¶
__init__(codebook, memory, threshold=0.0)
¶
Initialize cleanup memory with codebook.
Source code in vsax/resonator/cleanup.py
query(vec, return_similarity=False)
¶
Project vector onto codebook and return nearest symbol.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vec
|
Union[ndarray, AbstractHypervector]
|
Query vector to cleanup (array or hypervector). |
required |
return_similarity
|
bool
|
If True, also return similarity score. |
False
|
Returns:
| Type | Description |
|---|---|
Union[Optional[str], tuple[Optional[str], float]]
|
If return_similarity=False: Symbol name or None if below threshold. |
Union[Optional[str], tuple[Optional[str], float]]
|
If return_similarity=True: Tuple of (symbol, similarity) or (None, similarity). |
Example
result = cleanup.query(noisy_vec) result_with_score = cleanup.query(noisy_vec, return_similarity=True) print(result_with_score) # ("red", 0.95)
Source code in vsax/resonator/cleanup.py
query_top_k(vec, k=3)
¶
Return top-k closest symbols with similarity scores.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vec
|
Union[ndarray, AbstractHypervector]
|
Query vector to cleanup. |
required |
k
|
int
|
Number of top matches to return. |
3
|
Returns:
| Type | Description |
|---|---|
list[tuple[str, float]]
|
List of (symbol, similarity) tuples sorted by similarity (descending). |
Example
top_matches = cleanup.query_top_k(noisy_vec, k=3) for symbol, sim in top_matches: ... print(f"{symbol}: {sim:.3f}")
Source code in vsax/resonator/cleanup.py
__len__()
¶
Example¶
from vsax import create_binary_model, VSAMemory
from vsax.resonator import CleanupMemory
model = create_binary_model(dim=10000, bipolar=True)
memory = VSAMemory(model)
memory.add_many(["red", "blue", "green"])
# Create cleanup memory
cleanup = CleanupMemory(["red", "blue", "green"], memory)
# Query with noisy vector
result = cleanup.query(noisy_vector)
print(result) # "red"
# Get top-k matches
top_3 = cleanup.query_top_k(noisy_vector, k=3)
for symbol, similarity in top_3:
print(f"{symbol}: {similarity:.3f}")
Resonator¶
vsax.resonator.Resonator
¶
Resonator network for factorizing composite VSA vectors.
Given a composite vector s = a ⊙ b ⊙ c, this class implements an iterative algorithm to find the factors a, b, c from known codebooks.
The algorithm alternates between: 1. Unbinding current estimates of other factors from s 2. Cleaning up the result using codebook projection
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
codebooks
|
list[CleanupMemory]
|
List of CleanupMemory objects, one per factor position. |
required |
opset
|
AbstractOpSet
|
Operation set defining bind/unbind operations. |
required |
max_iterations
|
int
|
Maximum number of iterations (default: 100). |
100
|
convergence_threshold
|
int
|
Stop if estimates don't change (default: 3). |
3
|
Example
model = create_binary_model(dim=10000) memory = VSAMemory(model) memory.add_many(["red", "blue", "circle", "square"])
Create codebooks for two factor positions¶
colors = CleanupMemory(["red", "blue"], memory) shapes = CleanupMemory(["circle", "square"], memory)
Create composite: red ⊙ circle¶
composite = model.opset.bind( ... memory["red"].vec, ... memory["circle"].vec ... )
Factorize¶
resonator = Resonator([colors, shapes], model.opset) factors = resonator.factorize(composite) print(factors) # ["red", "circle"]
Source code in vsax/resonator/resonator.py
15 16 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 51 52 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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | |
Functions¶
__init__(codebooks, opset, max_iterations=100, convergence_threshold=3)
¶
Initialize resonator network.
Source code in vsax/resonator/resonator.py
factorize(composite, initial_estimates=None, return_history=False)
¶
Factorize a composite vector into its constituent factors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
composite
|
Union[ndarray, AbstractHypervector]
|
Composite vector to factorize. |
required |
initial_estimates
|
Optional[list[str]]
|
Optional initial guesses for factors. If None, uses superposition of all codebook vectors. |
None
|
return_history
|
bool
|
If True, return iteration history. |
False
|
Returns:
| Type | Description |
|---|---|
Union[list[Optional[str]], tuple[list[Optional[str]], list[list[Optional[str]]]]]
|
If return_history=False: List of factor names (or None if not converged). |
Union[list[Optional[str]], tuple[list[Optional[str]], list[list[Optional[str]]]]]
|
If return_history=True: Tuple of (factors, history) where history is a list of factor estimates at each iteration. |
Example
factors = resonator.factorize(composite) factors, history = resonator.factorize(composite, return_history=True)
Source code in vsax/resonator/resonator.py
factorize_batch(composites, initial_estimates=None)
¶
Factorize multiple composite vectors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
composites
|
ndarray
|
Array of composite vectors, shape (batch_size, dim). |
required |
initial_estimates
|
Optional[list[list[str]]]
|
Optional initial guesses for each composite. |
None
|
Returns:
| Type | Description |
|---|---|
list[list[Optional[str]]]
|
List of factor lists, one per composite. |
Example
composites = jnp.stack([comp1, comp2, comp3]) all_factors = resonator.factorize_batch(composites)
Source code in vsax/resonator/resonator.py
__repr__()
¶
Return string representation.
Example¶
from vsax import create_binary_model, VSAMemory
from vsax.resonator import CleanupMemory, Resonator
# Setup
model = create_binary_model(dim=10000, bipolar=True)
memory = VSAMemory(model)
memory.add_many(["red", "blue", "circle", "square"])
# Create composite
composite = model.opset.bind(
memory["red"].vec,
memory["circle"].vec
)
# Create codebooks
colors = CleanupMemory(["red", "blue"], memory)
shapes = CleanupMemory(["circle", "square"], memory)
# Factorize
resonator = Resonator([colors, shapes], model.opset)
factors = resonator.factorize(composite)
print(factors) # ["red", "circle"]
Algorithm Details¶
Resonance Equations¶
For a composite s = a ⊙ b ⊙ c, the update equations are:
x̂(t+1) = g(XX^T(s ⊙ ŷ(t) ⊙ ẑ(t)))
ŷ(t+1) = g(YY^T(s ⊙ x̂(t) ⊙ ẑ(t)))
ẑ(t+1) = g(ZZ^T(s ⊙ x̂(t) ⊙ ŷ(t)))
Where:
- x̂, ŷ, ẑ are factor estimates
- X, Y, Z are codebook matrices
- g(XX^T·) is the cleanup operation (codebook projection)
- ⊙ is the binding operation
Cleanup Operation¶
The cleanup operation g(XX^T v) projects vector v onto the nearest vector in codebook X.
For binary/bipolar vectors:
For complex/real vectors:
similarities = [cosine_similarity(v, c) for c in codebook]
best_idx = argmax(similarities)
result = codebook[best_idx]
Initialization¶
On the first iteration (no prior estimates), the algorithm uses superposition initialization:
This provides information about all possible factors simultaneously.
Convergence¶
The algorithm stops when:
- Stable convergence: Estimates unchanged for
convergence_thresholditerations (default: 3) - Max iterations: Reached
max_iterations(default: 100)
Binary VSA typically converges in < 10 iterations due to exact unbinding.
Performance Characteristics¶
Time Complexity¶
Per iteration for N factors with codebook size M and dimension D: - Unbinding: O(N × D) - binding operations - Cleanup: O(M × D) - dot products with codebook - Total: O(N × M × D) per iteration
Typical iterations to convergence: 5-20
Space Complexity¶
- Codebooks: O(M × D) per codebook
- Estimates: O(N × D)
- Total: O((N + M) × D)
Recommendations¶
Dimensionality: - Binary VSA: ≥10,000 dimensions - FHRR: ≥512 dimensions - MAP: ≥512 dimensions
Codebook Size: - Works well with codebooks of 2-100 items - Larger codebooks may require more iterations
Number of Factors: - Tested with 2-3 factors - Can handle more but convergence may slow
Common Patterns¶
Two-Factor Factorization¶
# Encode
composite = bind(a, b)
# Setup codebooks
codebook_a = CleanupMemory(["a1", "a2", "a3"], memory)
codebook_b = CleanupMemory(["b1", "b2", "b3"], memory)
# Factorize
resonator = Resonator([codebook_a, codebook_b], opset)
factors = resonator.factorize(composite)
Three-Factor Factorization¶
# Encode
composite = bind(bind(a, b), c)
# Setup
codebook_a = CleanupMemory([...], memory)
codebook_b = CleanupMemory([...], memory)
codebook_c = CleanupMemory([...], memory)
# Factorize
resonator = Resonator([codebook_a, codebook_b, codebook_c], opset)
factors = resonator.factorize(composite)
Batch Processing¶
import jax.numpy as jnp
# Create multiple composites
composites = jnp.stack([comp1, comp2, comp3, comp4])
# Batch factorize
results = resonator.factorize_batch(composites)
# results[i] contains factors for composites[i]
Monitoring Convergence¶
factors, history = resonator.factorize(
composite,
return_history=True
)
print(f"Converged in {len(history)} iterations")
for i, step in enumerate(history):
print(f"Iteration {i}: {step}")
Error Handling¶
Invalid Codebook¶
# Raises ValueError if symbol not in memory
cleanup = CleanupMemory(["missing_symbol"], memory)
# ValueError: Symbol 'missing_symbol' not found in memory
Wrong Number of Estimates¶
# Raises ValueError if initial estimates don't match codebook count
resonator = Resonator([codebook1, codebook2], opset)
factors = resonator.factorize(composite, initial_estimates=["a"])
# ValueError: Expected 2 initial estimates, got 1
Invalid Initial Estimate¶
# Raises ValueError if estimate not in corresponding codebook
factors = resonator.factorize(
composite,
initial_estimates=["valid", "not_in_codebook"]
)
# ValueError: Initial estimate 'not_in_codebook' not in codebook 1