Note
Go to the end to download the full example code.
VSA Models Comparison Guide¶
Topics: MAP, FHRR, HRR, BSC model selection and characteristics Time: 15 minutes Prerequisites: 00_quickstart.py, 01_basic_operations.py Related: 40_model_hrr_correlation.py, 41_model_ghrr_diagonality.py, 42_model_bsdc_seg.py
This example helps you choose the right VSA model for your application by demonstrating the key differences, trade-offs, and use cases for each model in the HoloVec library.
15 from holovec import VSA
16
17 print("=" * 70)
18 print("VSA Models Comparison - Choosing the Right Model")
19 print("=" * 70)
20 print()
21
22 # ============================================================================
23 # Overview: Available Models
24 # ============================================================================
25 print("Available VSA Models in HoloVec")
26 print("-" * 70)
27 print()
28 print("1. MAP (Multiply-Add-Permute)")
29 print(" - Element-wise operations, self-inverse binding")
30 print(" - Fast, simple, works on CPU")
31 print()
32 print("2. FHRR (Fourier Holographic Reduced Representations)")
33 print(" - Complex-valued, exact inverses")
34 print(" - Best capacity, recommended for most applications")
35 print()
36 print("3. HRR (Holographic Reduced Representations)")
37 print(" - Real-valued circular convolution")
38 print(" - Classic model, good for research reproduction")
39 print()
40 print("4. BSC (Binary Spatter Codes)")
41 print(" - Binary vectors with XOR binding")
42 print(" - Memory-efficient, exact inverse")
43 print()
44 print("5. BSDC (Binary Sparse Distributed Codes)")
45 print(" - Sparse binary representation")
46 print(" - Inspired by neuroscience, brain-like sparsity")
47 print()
48
49 # ============================================================================
50 # Comparison 1: Model Characteristics
51 # ============================================================================
52 print("=" * 70)
53 print("Comparison 1: Model Characteristics")
54 print("=" * 70)
55 print()
56
57 models_info = {}
58
59 # Create each model
60 for model_name in ['MAP', 'FHRR', 'HRR', 'BSC']:
61 model = VSA.create(model_name, dim=10000, seed=42)
62 models_info[model_name] = {
63 'model': model,
64 'self_inverse': model.is_self_inverse,
65 'commutative': model.is_commutative,
66 'exact_inverse': model.is_exact_inverse,
67 'space': model.space.space_name
68 }
69
70 # Print comparison table
71 print(f"{'Model':<8} {'Space':<12} {'Self-Inv':<10} {'Commut':<10} {'Exact-Inv':<10}")
72 print("-" * 70)
73 for name, info in models_info.items():
74 print(f"{name:<8} {info['space']:<12} {str(info['self_inverse']):<10} "
75 f"{str(info['commutative']):<10} {str(info['exact_inverse']):<10}")
76 print()
77
78 print("Key:")
79 print(" Self-Inverse: bind(A, B) can be unbound without separate inverse")
80 print(" Commutative: bind(A, B) = bind(B, A)")
81 print(" Exact-Inverse: Unbinding recovers exact original (no approximation)")
82 print()
83
84 # ============================================================================
85 # Comparison 2: Capacity (Bundling Performance)
86 # ============================================================================
87 print("=" * 70)
88 print("Comparison 2: Bundling Capacity")
89 print("=" * 70)
90 print()
91 print("Testing: How many random vectors can be bundled before similarity degrades?")
92 print()
93
94 # Test bundling capacity for each model
95 for model_name in ['FHRR', 'MAP', 'HRR']:
96 model = models_info[model_name]['model']
97
98 # Create a target vector and bundle it with noise
99 target = model.random(seed=100)
100 n_items_list = [1, 5, 10, 20, 50]
101
102 print(f"{model_name} Bundling:")
103 for n in n_items_list:
104 # Bundle target with (n-1) random vectors
105 vectors = [target] + [model.random(seed=100+i) for i in range(1, n)]
106 bundled = model.bundle(vectors)
107
108 # Measure similarity to target
109 similarity = float(model.similarity(bundled, target))
110 print(f" {n:3d} items bundled: similarity = {similarity:.3f}")
111 print()
112
113 print("Observation:")
114 print(" - FHRR maintains highest similarity (best capacity)")
115 print(" - MAP and HRR degrade faster with more items")
116 print(" - For >20 bundled items, prefer FHRR")
117 print()
118
119 # ============================================================================
120 # Comparison 3: Binding/Unbinding Accuracy
121 # ============================================================================
122 print("=" * 70)
123 print("Comparison 3: Binding/Unbinding Accuracy")
124 print("=" * 70)
125 print()
126 print("Testing: Can we accurately recover bound information?")
127 print()
128
129 for model_name in ['FHRR', 'MAP', 'HRR']:
130 model = models_info[model_name]['model']
131
132 # Create vectors
133 a = model.random(seed=1)
134 b = model.random(seed=2)
135
136 # Bind
137 c = model.bind(a, b)
138
139 # Unbind to recover b
140 b_recovered = model.unbind(c, a)
141
142 # Measure recovery accuracy
143 similarity = float(model.similarity(b, b_recovered))
144
145 print(f"{model_name}: bind(A, B) then unbind(·, A) → similarity = {similarity:.4f}")
146
147 print()
148 print("Observation:")
149 print(" - FHRR: Exact inverse (similarity ≈ 1.000)")
150 print(" - MAP: Approximate but very good (similarity ≈ 0.999)")
151 print(" - HRR: Good approximation (similarity ≈ 0.990)")
152 print()
153
154 # ============================================================================
155 # Comparison 4: Performance Characteristics
156 # ============================================================================
157 print("=" * 70)
158 print("Comparison 4: Performance Characteristics")
159 print("=" * 70)
160 print()
161
162 import time
163
164 # Time binding operations
165 n_iterations = 1000
166 results = {}
167
168 for model_name in ['MAP', 'FHRR', 'HRR']:
169 model = models_info[model_name]['model']
170 a = model.random(seed=1)
171 b = model.random(seed=2)
172
173 # Time binding
174 start = time.time()
175 for _ in range(n_iterations):
176 _ = model.bind(a, b)
177 elapsed = time.time() - start
178
179 results[model_name] = elapsed
180
181 # Normalize to MAP
182 map_time = results['MAP']
183 print(f"Binding Speed (relative to MAP, {n_iterations} operations):")
184 print(f" MAP: 1.00x (fastest - element-wise multiply)")
185 print(f" FHRR: {results['FHRR']/map_time:.2f}x (complex FFT operations)")
186 print(f" HRR: {results['HRR']/map_time:.2f}x (circular convolution via FFT)")
187 print()
188 print("Note: Times may vary by backend (NumPy vs PyTorch vs JAX)")
189 print()
190
191 # ============================================================================
192 # Decision Guide: When to Use Each Model
193 # ============================================================================
194 print("=" * 70)
195 print("Decision Guide: When to Use Each Model")
196 print("=" * 70)
197 print()
198
199 print("🏆 FHRR - **Recommended for most applications**")
200 print(" Use when:")
201 print(" - You need high capacity (bundling many items)")
202 print(" - Exact inverse is important")
203 print(" - Working with continuous encoders (FractionalPowerEncoder)")
204 print(" - Moderate performance is acceptable")
205 print()
206
207 print("⚡ MAP - **Best for speed-critical applications**")
208 print(" Use when:")
209 print(" - Performance is critical (real-time systems)")
210 print(" - Self-inverse binding is beneficial")
211 print(" - Simple element-wise operations preferred")
212 print(" - Lower capacity is acceptable")
213 print()
214
215 print("📚 HRR - **Good for research and reproduction**")
216 print(" Use when:")
217 print(" - Reproducing classic HDC papers")
218 print(" - Real-valued representations required")
219 print(" - Good balance of capacity and performance")
220 print()
221
222 print("💾 BSC - **Binary and memory-efficient**")
223 print(" Use when:")
224 print(" - Memory is extremely limited")
225 print(" - Binary operations preferred")
226 print(" - Exact XOR-based inverse needed")
227 print()
228
229 print("🧠 BSDC - **Brain-inspired sparse coding**")
230 print(" Use when:")
231 print(" - Biological plausibility important")
232 print(" - Sparse representations desired")
233 print(" - Neuromorphic hardware targeted")
234 print()
235
236 # ============================================================================
237 # Example: Same Application, Different Models
238 # ============================================================================
239 print("=" * 70)
240 print("Example: Temperature Encoding with Different Models")
241 print("=" * 70)
242 print()
243
244 from holovec.encoders import FractionalPowerEncoder, ThermometerEncoder
245
246 # Encode same data with different models
247 temps = [20.0, 21.0, 40.0]
248
249 # FPE works with FHRR and HRR
250 print("Using FractionalPowerEncoder (works with FHRR, HRR):")
251 for model_name in ['FHRR', 'HRR']:
252 model = models_info[model_name]['model']
253 encoder = FractionalPowerEncoder(model, min_val=0, max_val=100, bandwidth=0.1)
254
255 hvs = [encoder.encode(t) for t in temps]
256
257 # Check similarity between similar temps (20°C vs 21°C)
258 sim_close = float(model.similarity(hvs[0], hvs[1]))
259
260 # Check similarity between distant temps (20°C vs 40°C)
261 sim_far = float(model.similarity(hvs[0], hvs[2]))
262
263 print(f" {model_name}: sim(20°C, 21°C)={sim_close:.3f}, sim(20°C, 40°C)={sim_far:.3f}")
264
265 print()
266
267 # ThermometerEncoder works with all models
268 print("Using ThermometerEncoder (works with all models):")
269 for model_name in ['FHRR', 'MAP', 'HRR', 'BSC']:
270 model = models_info[model_name]['model']
271 encoder = ThermometerEncoder(model, min_val=0, max_val=100, n_bins=100)
272
273 hvs = [encoder.encode(t) for t in temps]
274
275 # Check similarity between similar temps (20°C vs 21°C)
276 sim_close = float(model.similarity(hvs[0], hvs[1]))
277
278 # Check similarity between distant temps (20°C vs 40°C)
279 sim_far = float(model.similarity(hvs[0], hvs[2]))
280
281 print(f" {model_name}: sim(20°C, 21°C)={sim_close:.3f}, sim(20°C, 40°C)={sim_far:.3f}")
282
283 print()
284 print("Observation:")
285 print(" - All models preserve similarity structure")
286 print(" - Different encoders may have model compatibility constraints")
287 print(" - Check encoder.compatible_models before use")
288 print()
289
290 # ============================================================================
291 # Summary
292 # ============================================================================
293 print("=" * 70)
294 print("Summary: Quick Reference")
295 print("=" * 70)
296 print()
297 print("Model Selection Flowchart:")
298 print()
299 print(" Need exact inverses? → Use FHRR")
300 print(" Need maximum speed? → Use MAP")
301 print(" Reproducing research? → Use HRR")
302 print(" Need binary/sparse? → Use BSC or BSDC")
303 print()
304 print(" **Default recommendation: FHRR**")
305 print(" (Best balance of capacity, accuracy, and features)")
306 print()
307 print("Next steps:")
308 print(" → Try different models with your specific use case")
309 print(" → See model-specific examples: 40-42_model_*.py")
310 print(" → Explore encoders with your chosen model: 10-18_encoders_*.py")
311 print()
312 print("=" * 70)