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)

Gallery generated by Sphinx-Gallery