Complete API documentation auto-generated from source code docstrings.
VSA Factory
The main entry point for creating VSA models.
holovec.VSA
High-level factory interface for creating VSA models.
This class provides a simple, unified API for creating and using different VSA models. It's the recommended entry point for most users.
Examples: >>> # Create a MAP model with default settings >>> model = VSA.create('MAP') >>> >>> # Create FHRR with specific dimension and backend >>> model = VSA.create('FHRR', dim=512, backend='torch', device='cuda') >>> >>> # Use the model >>> a, b = model.random(), model.random() >>> c = model.bind(a, b) >>> similarity = model.similarity(a, model.unbind(c, b))
Source code in holovec/__init__.py
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 235 236 237 238 | |
create(model_type, dim=10000, backend=None, space=None, seed=None, **kwargs)
classmethod
Create a VSA model with the specified configuration.
Args:
model_type: Model name ('MAP', 'FHRR', 'HRR', 'BSC', etc.)
dim: Dimensionality of hypervectors
backend: Backend name ('numpy', 'torch', 'jax'), a :class:Backend
instance, or None for the default backend
space: Vector space name or None for model's default
seed: Random seed for reproducibility
**kwargs: Additional arguments passed to backend (e.g., device='cuda')
Returns: VSA model instance
Raises: ValueError: If model_type is not recognized
Examples: >>> model = VSA.create('MAP', dim=10000) >>> model = VSA.create('FHRR', dim=512, backend='torch', device='cuda') >>> model = VSA.create('MAP', space='real') # Use real-valued MAP
Source code in holovec/__init__.py
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 | |
Models
All VSA model implementations.
Base Model
holovec.models.base.VSAModel
Bases: ABC
Abstract base class for VSA models.
A VSA model defines the core operations: - bind: Associate two vectors (creates dissimilar result) - unbind: Recover one vector given the other and their binding - bundle: Combine multiple vectors (preserves similarity) - permute: Reorder vector to represent position/sequence
Different models have different algebraic properties: - Self-inverse binding: bind(a, b) = unbind(a, b) - Exact vs approximate inverse - Commutativity of binding
Source code in holovec/models/base.py
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 | |
bind(a, b)
abstractmethod
Bind two vectors to create an association.
Binding creates a new vector that is dissimilar to both inputs but preserves structured similarity (similar inputs → similar bindings).
Args: a: First vector b: Second vector
Returns: Bound vector representing the association of a and b
Source code in holovec/models/base.py
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
unbind(a, b)
abstractmethod
Unbind to recover one vector given the other.
For self-inverse models: unbind(a, b) = bind(a, b) For others: approximately recovers a from bind(a, b) and b
Args: a: Bound vector or first operand b: Second operand
Returns: Recovered vector (exact or approximate depending on model)
Source code in holovec/models/base.py
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | |
bundle(vectors)
abstractmethod
Bundle (superpose) multiple vectors.
Bundling combines vectors while preserving similarity to all inputs. The result is similar to each input vector.
Args: vectors: Sequence of vectors to bundle
Returns: Bundled vector representing the superposition
Raises: ValueError: If vectors is empty
Source code in holovec/models/base.py
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | |
permute(vec, k=1)
abstractmethod
Permute vector to represent position or sequence.
Permutation reorders coordinates and is used to encode position or create sequences. It's invertible and preserves similarity.
Args: vec: Vector to permute k: Number of positions to shift (default: 1)
Returns: Permuted vector
Source code in holovec/models/base.py
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | |
unpermute(vec, k=1)
Inverse permutation.
Args: vec: Vector to unpermute k: Number of positions to shift back (default: 1)
Returns: Unpermuted vector
Source code in holovec/models/base.py
114 115 116 117 118 119 120 121 122 123 124 | |
similarity(a, b)
Compute similarity between two vectors.
Delegates to the vector space's similarity metric.
Args: a: First vector b: Second vector
Returns: Similarity score (space-dependent metric)
Source code in holovec/models/base.py
128 129 130 131 132 133 134 135 136 137 138 139 140 | |
normalize(vec)
Normalize vector according to space conventions.
Args: vec: Vector to normalize
Returns: Normalized vector
Source code in holovec/models/base.py
142 143 144 145 146 147 148 149 150 151 | |
random(seed=None)
Generate a random vector from the space.
Args: seed: Optional random seed
Returns: Random vector
Source code in holovec/models/base.py
155 156 157 158 159 160 161 162 163 164 | |
FHRR
holovec.models.fhrr.FHRRModel
Bases: VSAModel
FHRR (Fourier HRR) model using complex phasors.
Binding: element-wise complex multiplication (phase addition) Unbinding: element-wise multiplication with conjugate (phase subtraction) Bundling: element-wise addition + normalization to unit magnitude Permutation: circular shift (can also use phase rotation)
Uses ComplexSpace with unit-magnitude phasors.
Source code in holovec/models/fhrr.py
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 | |
__init__(dimension=512, space=None, backend=None, seed=None)
Initialize FHRR model.
Args: dimension: Dimensionality of hypervectors (can be smaller than MAP due to better capacity) space: Vector space (defaults to ComplexSpace) backend: Computational backend seed: Random seed for space
Source code in holovec/models/fhrr.py
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | |
bind(a, b)
Bind using element-wise complex multiplication.
For unit phasors: (a * b)[i] = a[i] * b[i] This adds phase angles: ∠(a*b) = ∠a + ∠b
Args: a: First vector (unit phasors) b: Second vector (unit phasors)
Returns: Bound vector c = a ⊙ b (element-wise product)
Source code in holovec/models/fhrr.py
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | |
bundle(vectors)
Bundle using element-wise addition.
Sum phasors and normalize back to unit magnitude. The result points in the "average" direction of inputs.
Args: vectors: Sequence of vectors to bundle
Returns: Bundled vector (normalized to unit magnitude)
Raises: ValueError: If vectors is empty
Source code in holovec/models/fhrr.py
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 | |
fractional_power(vec, exponent)
Raise phasor to a fractional power.
For unit phasor z = exp(iθ): z^α = exp(iαθ) This is useful for encoding continuous values.
Args: vec: Vector of unit phasors exponent: Power to raise to
Returns: Vector with phases scaled by exponent
Example: >>> base = model.random() >>> # Encode value 2.5 using fractional power >>> encoded = model.fractional_power(base, 2.5)
Source code in holovec/models/fhrr.py
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 | |
permute(vec, k=1)
Permute using circular shift.
For FHRR, permutation can be done as: 1. Circular shift (coordinate permutation) 2. Phase rotation (multiply by exp(i*2πk/D))
We use circular shift for consistency with other models.
Args: vec: Vector to permute k: Number of positions to shift
Returns: Permuted vector
Source code in holovec/models/fhrr.py
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | |
unbind(a, b)
Unbind using element-wise multiplication with conjugate.
To recover original from c = a ⊙ b: unbind(c, b) = c ⊙ b = (a ⊙ b) ⊙ b = a ⊙ (b ⊙ b*) = a ⊙ 1 = a
Args: a: Bound vector (or first operand) b: Second operand
Returns: Unbound vector (exact recovery)
Source code in holovec/models/fhrr.py
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | |
GHRR
holovec.models.ghrr.GHRRModel
Bases: VSAModel
GHRR (Generalized Holographic Reduced Representations) model.
Binding: element-wise matrix multiplication (phase addition per matrix) Unbinding: element-wise multiplication with conjugate transpose Bundling: element-wise addition + normalization Permutation: circular shift (or use non-commutativity instead)
Uses MatrixSpace with m×m unitary matrices.
Source code in holovec/models/ghrr.py
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 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | |
commutativity_degree
property
Degree of commutativity in [0, 1].
For GHRR, this depends on the diagonality of Q matrices. More diagonal → more commutative.
Returns: 0.0 if maximally non-commutative, 1.0 if fully commutative
__init__(dimension=100, matrix_size=3, space=None, backend=None, seed=None, diagonality=None)
Initialize GHRR model.
Args: dimension: Number of matrices in hypervector (can be smaller than scalar models due to better capacity) matrix_size: Size m of each m×m matrix (default: 3) Larger m → more non-commutative, better for complex structures m=1 recovers FHRR space: Vector space (defaults to MatrixSpace) backend: Computational backend seed: Random seed for space diagonality: Control commutativity in [0, 1] None: Random (default) 0.0: Maximally non-commutative 1.0: Fully commutative (FHRR-like)
Source code in holovec/models/ghrr.py
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 | |
bind(a, b)
Bind using element-wise matrix multiplication.
For matrices at position j: (a ⊗ b)_j = a_j @ b_j
This is non-commutative: a ⊗ b ≠ b ⊗ a in general.
Args: a: First hypervector (D, m, m) b: Second hypervector (D, m, m)
Returns: Bound hypervector c where c_j = a_j @ b_j for all j
Source code in holovec/models/ghrr.py
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | |
bundle(vectors)
Bundle using element-wise addition.
Sum all hypervectors element-wise. Each element is an m×m matrix.
For GHRR: (a + b)_j = a_j + b_j (matrix addition)
Args: vectors: Sequence of hypervectors to bundle
Returns: Bundled hypervector
Raises: ValueError: If vectors is empty
Source code in holovec/models/ghrr.py
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 | |
compute_diagonality(vec)
Compute average diagonality of matrices in hypervector.
Diagonality metric: Σ|Q_jj| / ΣΣ|Q_jk|
Args: vec: Hypervector (D, m, m)
Returns: Diagonality in [0, 1]
Source code in holovec/models/ghrr.py
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | |
permute(vec, k=1)
Permute using circular shift.
For GHRR, permutation is less critical since non-commutativity can encode order. But still useful for some applications.
Args: vec: Hypervector to permute (D, m, m) k: Number of positions to shift
Returns: Permuted hypervector
Source code in holovec/models/ghrr.py
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | |
test_non_commutativity(a, b)
Test degree of non-commutativity for two hypervectors.
Computes: δ(a ⊗ b, b ⊗ a)
A similarity of 1.0 means commutative, close to 0 means non-commutative.
Args: a: First hypervector b: Second hypervector
Returns: Similarity between a⊗b and b⊗a
Source code in holovec/models/ghrr.py
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | |
unbind(a, b)
Unbind using element-wise multiplication with conjugate transpose.
To recover original from c = a ⊗ b: unbind(c, b) = c_j @ b_j† for all j
This provides exact recovery: unbind(bind(a, b), b) = a
Args: a: Bound hypervector (or first operand) b: Second operand
Returns: Unbound hypervector (exact recovery)
Source code in holovec/models/ghrr.py
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | |
MAP
holovec.models.map.MAPModel
Bases: VSAModel
MAP (Multiply-Add-Permute) model.
Binding: element-wise multiplication Unbinding: element-wise multiplication (self-inverse) Bundling: element-wise addition + normalization Permutation: circular shift
Best used with BipolarSpace or RealSpace.
Source code in holovec/models/map.py
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 | |
__init__(dimension=10000, space=None, backend=None, seed=None)
Initialize MAP model.
Args: dimension: Dimensionality of hypervectors space: Vector space (defaults to BipolarSpace) backend: Computational backend seed: Random seed for space
Source code in holovec/models/map.py
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 | |
bind(a, b)
Bind using element-wise multiplication.
For bipolar: XOR when represented as {0,1} For real: Hadamard product
Args: a: First vector b: Second vector
Returns: Bound vector c = a ⊙ b
Source code in holovec/models/map.py
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | |
bundle(vectors)
Bundle using element-wise addition.
For bipolar: majority vote after summing For real: sum and normalize
Args: vectors: Sequence of vectors to bundle
Returns: Bundled vector
Raises: ValueError: If vectors is empty
Source code in holovec/models/map.py
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 | |
permute(vec, k=1)
Permute using circular shift.
Shifts vector elements by k positions to the right. Negative k shifts left.
Args: vec: Vector to permute k: Number of positions to shift
Returns: Permuted vector
Source code in holovec/models/map.py
154 155 156 157 158 159 160 161 162 163 164 165 166 167 | |
unbind(a, b)
Unbind using element-wise multiplication (self-inverse).
Since binding is self-inverse: unbind(c, b) = c ⊙ b
Args: a: Bound vector (or first operand) b: Second operand
Returns: Unbound vector (exact for bipolar, approximate for continuous)
Source code in holovec/models/map.py
99 100 101 102 103 104 105 106 107 108 109 110 111 112 | |
HRR
holovec.models.hrr.HRRModel
Bases: VSAModel
HRR (Holographic Reduced Representations) model.
Binding: circular convolution (via FFT) Unbinding: circular correlation (via FFT) Bundling: element-wise addition + normalization Permutation: circular shift
Uses RealSpace with Gaussian distribution N(0, 1/D).
Source code in holovec/models/hrr.py
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 | |
__init__(dimension=10000, space=None, backend=None, seed=None)
Initialize HRR model.
Args: dimension: Dimensionality of hypervectors (recommend 1000-10000) space: Vector space (defaults to RealSpace) backend: Computational backend seed: Random seed for space
Source code in holovec/models/hrr.py
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
bind(a, b)
Bind using circular convolution.
Implemented via FFT: conv(a, b) = IFFT(FFT(a) * FFT(b))
Args: a: First vector b: Second vector
Returns: Bound vector c = a ⊛ b (circular convolution)
Source code in holovec/models/hrr.py
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | |
bundle(vectors)
Bundle using element-wise addition (superposition).
For HRR, bundling is simple vector addition without normalization. This preserves the magnitude relationships needed for proper unbinding.
Args: vectors: Sequence of vectors to bundle
Returns: Bundled vector (unnormalized sum)
Raises: ValueError: If vectors is empty
Notes: Unlike some VSA models, HRR does NOT normalize after bundling. Normalization would interfere with the circular correlation unbinding operation. The unbind() method handles normalization of its output.
Source code in holovec/models/hrr.py
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 | |
permute(vec, k=1)
Permute using circular shift.
Shifts vector elements by k positions to the right. Negative k shifts left.
Args: vec: Vector to permute k: Number of positions to shift
Returns: Permuted vector
Source code in holovec/models/hrr.py
213 214 215 216 217 218 219 220 221 222 223 224 225 226 | |
unbind(a, b)
Unbind using circular correlation (approximate inverse of convolution).
This is the classic HRR unbinding operation that uses circular correlation to approximately recover the original vector from a bound pair.
Args: a: Bound vector c = x ⊛ b (result of circular convolution) b: Key vector (second operand in binding)
Returns: Approximate recovery of x (original vector), normalized to unit length
Notes
Mathematical Foundation:
HRR binding via circular convolution: c = x ⊛ b
In frequency domain (Fourier): C(ω) = X(ω) · B(ω)
Unbinding via circular correlation: x̂ = c ⋆ b = IFFT(C(ω) · B*(ω))
Where B*(ω) is the complex conjugate of B(ω).
Substituting C(ω) = X(ω) · B(ω): x̂ = IFFT(X(ω) · B(ω) · B*(ω)) = IFFT(X(ω) · |B(ω)|²)
For random vectors with approximately uniform power spectrum (|B(ω)|² ≈ 1), this gives x̂ ≈ x.
Approximation Quality:
Recovery similarity depends on: - Dimension D: Higher D → better recovery - Noise level: Clean binding → better unbind - Bundle size: More items → more interference
Empirical performance (D=10000): - Clean unbind: similarity ≈ 0.70-0.72 (approximate inverse) - After bundling 2 items: similarity ≈ 0.57 - After bundling 10 items: similarity ≈ 0.30 - After bundling 100 items: similarity decreases further
Note: Unlike FHRR which achieves exact (1.0) recovery, HRR's circular correlation provides only approximate recovery. The ~0.71 similarity is sufficient for retrieval tasks but requires cleanup/thresholding.
References
- Plate (1995): "Holographic Reduced Representations"
- Plate (2003): "Holographic Reduced Representations" (full book)
Examples:
>>> model = VSA.create('HRR', dim=10000)
>>> x = model.random(seed=1)
>>> b = model.random(seed=2)
>>> c = model.bind(x, b)
>>> x_recovered = model.unbind(c, b)
>>> similarity = model.similarity(x, x_recovered)
>>> print(f"Recovery similarity: {similarity:.3f}") # ~0.71
Source code in holovec/models/hrr.py
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 | |
VTB
holovec.models.vtb.VTBModel
Bases: VSAModel
VTB (Vector-derived Transformation Binding) model.
Binding (MBAT-style): c = Σ_k w_k(a) · roll(b, s_k) Unbinding (approximate): b̂ = Σ_k w_k(a) · roll(c, -s_k) Bundling: element-wise addition + normalization Permutation: circular shift
Uses RealSpace with L2-normalized real-valued vectors.
Source code in holovec/models/vtb.py
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 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 | |
__init__(dimension=10000, space=None, backend=None, seed=None, n_bases=4, shifts=None, temperature=100.0)
Initialize VTB model.
Args: dimension: Dimensionality of hypervectors space: Vector space (defaults to RealSpace) backend: Computational backend seed: Random seed for space
Source code in holovec/models/vtb.py
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 | |
bind(a, b)
Bind using MBAT-style weighted basis transforms.
c = Σ_k w_k(a) · roll(b, s_k)
Source code in holovec/models/vtb.py
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | |
bind_sequence(items, use_permute=True)
Bind a sequence of items with positional encoding.
Two strategies: 1. With permutation: c = a₁ ⊗ ρ⁰(pos) + a₂ ⊗ ρ¹(pos) + ... 2. Without permutation: c = (...((a₁ ⊗ a₂) ⊗ a₃)...) (nested binding)
Args: items: Sequence of hypervectors to bind use_permute: If True, use permutation strategy; else nested binding
Returns: Sequence hypervector
Raises: ValueError: If items is empty
Source code in holovec/models/vtb.py
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | |
bundle(vectors)
Bundle using element-wise addition.
Sum all hypervectors element-wise and normalize.
Args: vectors: Sequence of hypervectors to bundle
Returns: Bundled hypervector
Raises: ValueError: If vectors is empty
Source code in holovec/models/vtb.py
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | |
permute(vec, k=1)
Permute using circular shift.
Shifts vector elements by k positions. Combined with binding, this can encode position in sequences.
Args: vec: Hypervector to permute k: Number of positions to shift (default: 1)
Returns: Permuted hypervector
Source code in holovec/models/vtb.py
232 233 234 235 236 237 238 239 240 241 242 243 244 245 | |
test_non_commutativity(a, b)
Test degree of non-commutativity for two hypervectors.
Computes: similarity(a ⊗ b, b ⊗ a)
A similarity of 1.0 means commutative, close to 0 means non-commutative.
Args: a: First hypervector b: Second hypervector
Returns: Similarity between a⊗b and b⊗a (should be low for VTB)
Source code in holovec/models/vtb.py
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 | |
unbind(c, b)
Approximate unbinding using weighted inverse transforms.
IMPORTANT: Due to non-commutativity, this recovers b from c = bind(a, b). You must pass the FIRST argument of bind (a) as the second argument here.
For c = bind(a, b): - unbind(c, a) → recovers b (correct usage) - unbind(c, b) → does NOT recover a
b̂ = Σ_k w_k(b) · roll(c, -s_k)
Source code in holovec/models/vtb.py
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 | |
BSC
holovec.models.bsc.BSCModel
Bases: VSAModel
BSC (Binary Spatter Codes) model.
Binding: XOR Unbinding: XOR (self-inverse) Bundling: element-wise addition + majority vote Permutation: circular shift
Uses BinarySpace with values in {0, 1}.
Source code in holovec/models/bsc.py
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 | |
__init__(dimension=10000, space=None, backend=None, seed=None)
Initialize BSC model.
Args: dimension: Dimensionality of hypervectors space: Vector space (defaults to BinarySpace) backend: Computational backend seed: Random seed for space
Source code in holovec/models/bsc.py
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | |
bind(a, b)
Bind using XOR.
For binary vectors: a XOR b Property: a XOR b XOR b = a (self-inverse)
Args: a: First vector (binary {0, 1}) b: Second vector (binary {0, 1})
Returns: Bound vector c = a XOR b
Source code in holovec/models/bsc.py
77 78 79 80 81 82 83 84 85 86 87 88 89 90 | |
bundle(vectors)
Bundle using element-wise addition + majority vote.
Sum all binary vectors element-wise, then threshold at n/2 where n is the number of vectors.
Args: vectors: Sequence of vectors to bundle
Returns: Bundled vector (binary {0, 1})
Raises: ValueError: If vectors is empty
Source code in holovec/models/bsc.py
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 | |
from_bipolar(vec)
Convert bipolar {-1, +1} to binary {0, 1}.
Transformation: x → (x + 1) / 2
Args: vec: Bipolar vector
Returns: Binary vector
Source code in holovec/models/bsc.py
166 167 168 169 170 171 172 173 174 175 176 177 | |
permute(vec, k=1)
Permute using circular shift.
Shifts vector elements by k positions to the right. Negative k shifts left.
Args: vec: Vector to permute k: Number of positions to shift
Returns: Permuted vector
Source code in holovec/models/bsc.py
138 139 140 141 142 143 144 145 146 147 148 149 150 151 | |
to_bipolar(vec)
Convert binary {0, 1} to bipolar {-1, +1}.
Transformation: x → 2x - 1
Args: vec: Binary vector
Returns: Bipolar vector
Source code in holovec/models/bsc.py
153 154 155 156 157 158 159 160 161 162 163 164 | |
unbind(a, b)
Unbind using XOR (self-inverse).
Since XOR is self-inverse: unbind(c, b) = c XOR b
Args: a: Bound vector (or first operand) b: Second operand
Returns: Unbound vector (exact recovery)
Source code in holovec/models/bsc.py
92 93 94 95 96 97 98 99 100 101 102 103 104 105 | |
BSDC
holovec.models.bsdc.BSDCModel
Bases: VSAModel
BSDC (Binary Sparse Distributed Codes) model.
Binding: XOR (element-wise, self-inverse) or CDT (context-dependent thinning) Unbinding: XOR (same as binding) or similarity-based (CDT) Bundling: Majority voting with sparsity preservation Permutation: circular shift
Uses SparseSpace with optimal sparsity p = 1/√D.
Binding Modes: - 'xor': Traditional XOR binding. Self-inverse, result dissimilar to inputs. - 'cdt': Context-Dependent Thinning (Rachkovskij 2001). Preserves both structured similarity (similar inputs → similar outputs) and unstructured similarity (result similar to its components).
Example: >>> # Default XOR mode >>> model = BSDCModel(dimension=10000) >>> >>> # CDT mode for analogical reasoning >>> model = BSDCModel(dimension=10000, binding_mode='cdt')
Source code in holovec/models/bsdc.py
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 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 | |
__init__(dimension=10000, sparsity=None, space=None, backend=None, seed=None, binding_mode='xor')
Initialize BSDC model.
Args: dimension: Dimensionality of hypervectors (typically > 1000) sparsity: Fraction of 1s (default: 1/√D which is optimal) space: Vector space (defaults to SparseSpace with optimal sparsity) backend: Computational backend seed: Random seed for space binding_mode: 'xor' (default) or 'cdt' for context-dependent thinning
Source code in holovec/models/bsdc.py
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 | |
bind(a, b)
Bind two hypervectors.
Behavior depends on binding_mode: - 'xor': XOR binding (self-inverse, result dissimilar to inputs) - 'cdt': Context-dependent thinning (preserves similarity to inputs)
For XOR mode: - Preserves sparsity on average: p(1-p) + (1-p)p = 2p(1-p) - For optimal p = 1/√D, result sparsity ≈ 2/√D
For CDT mode: - Result is similar to both a and b (unstructured similarity) - Similar inputs produce similar outputs (structured similarity)
Args: a: First hypervector b: Second hypervector
Returns: Bound hypervector
Source code in holovec/models/bsdc.py
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | |
bundle(vectors, maintain_sparsity=True)
Bundle using majority voting.
For sparse codes, bundling requires careful handling to maintain sparsity: 1. Sum all vectors element-wise 2. Apply threshold to get binary result 3. Optionally re-sparsify to maintain target sparsity
Args: vectors: Sequence of hypervectors to bundle maintain_sparsity: If True, enforce target sparsity (default: True)
Returns: Bundled hypervector
Raises: ValueError: If vectors is empty
Source code in holovec/models/bsdc.py
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 | |
context_dependent_thinning(components)
Bind components using context-dependent thinning (CDT).
Algorithm (Rachkovskij 2001): 1. Superpose components via OR: Z = X₁ ∨ X₂ ∨ ... ∨ Xₛ 2. Thin via permuted self-conjunction: ⟨Z⟩ = Z ∧ (Z^~(1) ∨ Z^~(2) ∨ ... ∨ Z^~(K))
Properties: - Preserves unstructured similarity: result is similar to each component - Preserves structured similarity: similar inputs → similar outputs - Maintains target sparsity automatically
Args: components: Sequence of hypervectors to bind together
Returns: Bound hypervector with preserved similarity to components
Example: >>> model = BSDCModel(dimension=10000, binding_mode='cdt') >>> a, b, c = model.random(), model.random(), model.random() >>> bound = model.context_dependent_thinning([a, b, c]) >>> # bound is similar to a, b, and c (unstructured similarity)
Source code in holovec/models/bsdc.py
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 235 236 237 | |
encode_sequence(items, use_ngrams=False, n=2)
Encode sequence of items.
Two strategies: 1. Position binding: item_i ⊗ ρⁱ(position) 2. N-grams: Bundle all n-grams in sequence
Args: items: Sequence of hypervectors use_ngrams: If True, use n-gram encoding (default: False) n: N-gram size (default: 2 for bigrams)
Returns: Sequence hypervector
Raises: ValueError: If items is empty
Source code in holovec/models/bsdc.py
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 | |
measure_sparsity(vec)
Measure actual sparsity of a vector.
Args: vec: Hypervector to measure
Returns: Fraction of 1s in the vector
Source code in holovec/models/bsdc.py
360 361 362 363 364 365 366 367 368 369 370 371 | |
permute(vec, k=1)
Permute using circular shift.
Shifts vector elements by k positions. For sparse codes, this maintains sparsity perfectly.
Args: vec: Hypervector to permute k: Number of positions to shift (default: 1)
Returns: Permuted hypervector
Source code in holovec/models/bsdc.py
345 346 347 348 349 350 351 352 353 354 355 356 357 358 | |
rehash(vec)
Rehash vector to restore optimal sparsity.
Useful after multiple operations that may have changed sparsity. Randomly selects positions to maintain target sparsity while preserving as much similarity as possible.
Args: vec: Hypervector to rehash
Returns: Rehashed hypervector with target sparsity
Source code in holovec/models/bsdc.py
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 | |
unbind(a, b)
Unbind to recover value.
Behavior depends on binding_mode: - 'xor': XOR is self-inverse, exact recovery: unbind(bind(a, b), b) = a - 'cdt': No inverse exists; returns the bound vector itself since it's already similar to the components (use similarity search for retrieval)
Args: a: Bound hypervector (or first operand) b: Second operand (key for XOR mode, ignored for CDT mode)
Returns: For XOR: Exact unbound hypervector For CDT: The bound vector (use similarity search to find components)
Source code in holovec/models/bsdc.py
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | |
BSDC-SEG
holovec.models.bsdc_seg.BSDCSEGModel
Bases: VSAModel
Segment-sparse binary VSA model (BSDC-SEG).
Binding: XOR (element-wise, self-inverse) Unbinding: XOR (self-inverse) Bundling: segment-wise majority (exactly 1 per segment) Permutation: circular shift
Uses SparseSegmentSpace with S segments (D % S == 0).
Source code in holovec/models/bsdc_seg.py
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 | |
bind(a, b)
Bind using XOR (self-inverse).
Source code in holovec/models/bsdc_seg.py
67 68 69 | |
bundle(vectors)
Segment-wise majority with exactly 1 winner per segment.
Counts votes per index within each segment and selects the index with maximum count (deterministic tie-break: lowest index).
Source code in holovec/models/bsdc_seg.py
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 | |
unbind(a, b)
Unbind using XOR (self-inverse).
Source code in holovec/models/bsdc_seg.py
71 72 73 | |
Encoders
Scalar Encoders
holovec.encoders.scalar.FractionalPowerEncoder
Bases: ScalarEncoder
Fractional Power Encoding (FPE) for continuous scalars.
Based on Frady et al. (2021) "Computing on Functions Using Randomized Vector Representations". Encodes scalars by exponentiating a random phasor base vector: encode(x) = φ^x.
The inner product between encoded vectors approximates a similarity kernel (sinc for uniform phase distribution). This encoding preserves linearity and enables precise decoding via sinc kernel reconstruction.
Works best with FHRR (complex domain) but also supports HRR (real domain).
References: Frady et al. (2021): https://arxiv.org/abs/2109.03429 Verges et al. (2025): Learning encoding phasors with FPE
Attributes: bandwidth: Controls kernel width (lower = wider kernel) base_phasor: Random phasor vector φ = [e^(iφ₁), ..., e^(iφₙ)]
Source code in holovec/encoders/scalar.py
13 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 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 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 | |
compatible_models
property
FPE works best with FHRR, also compatible with HRR.
is_reversible
property
FPE supports approximate decoding.
__init__(model, min_val, max_val, bandwidth=1.0, seed=None, phase_dist='uniform', mixture_bandwidths=None, mixture_weights=None)
Initialize FractionalPowerEncoder.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
VSAModel
|
VSA model (FHRR or HRR). FHRR (complex-valued) is preferred for exact fractional powers. HRR (real-valued) uses cosine projection. |
required |
min_val
|
float
|
Minimum value of encoding range. Values below this will be clipped. |
required |
max_val
|
float
|
Maximum value of encoding range. Values above this will be clipped. |
required |
bandwidth
|
float
|
Bandwidth parameter β controlling kernel width (default: 1.0). Mathematical Role: - Encoding: z(x) = φ^(β·x_normalized) - Kernel: K(x₁, x₂) ≈ sinc(β·π·|x₁ - x₂|) for uniform phase distribution - Smaller β → wider kernel → more generalization - Larger β → narrower kernel → more discrimination Typical Values: - β = 0.01: Wide kernel, high generalization (classification) - β = 1.0: Medium kernel (default) - β = 10.0: Narrow kernel, low generalization (regression) |
1.0
|
seed
|
int or None
|
Random seed for generating base phasor (for reproducibility). Different seeds produce different random frequency vectors θ. |
None
|
phase_dist
|
str
|
Distribution for sampling frequency vector θ (default: 'uniform'). Available Distributions: - 'uniform': θⱼ ~ Uniform[-π, π] → sinc kernel (default) - 'gaussian': θⱼ ~ N(0, 1) → Gaussian kernel approximation - 'laplace': θⱼ ~ Laplace(0, 1) → Exponential kernel, heavy tails - 'cauchy': θⱼ ~ Cauchy(0, 1) → Very heavy tails, long-range - 'student': θⱼ ~ Student-t(df=3) → Moderate tails, robust Different distributions induce different similarity kernels, affecting generalization properties. |
'uniform'
|
mixture_bandwidths
|
List[float] or None
|
List of K bandwidth values [β₁, β₂, ..., βₖ] for mixture encoding. Mixture Encoding: Instead of single bandwidth β, use weighted combination: z_mix(x) = Σₖ αₖ · φ^(βₖ·x) where αₖ are mixture_weights. This creates multi-scale representation combining coarse (small β) and fine (large β) kernels. Example: mixture_bandwidths = [0.01, 0.1, 1.0, 10.0] # 4 scales Creates encoding with both local and global similarity. |
None
|
mixture_weights
|
List[float] or None
|
Weights αₖ for each bandwidth in mixture (must sum to 1). If None and mixture_bandwidths is provided, uses uniform weights: αₖ = 1/K for all k Weights can be:
1. Hand-crafted (domain knowledge)
2. Learned via |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If phase_dist not in valid set, or if mixture_weights/mixture_bandwidths have mismatched lengths. |
Notes
Mathematical Foundation:
Fractional Power Encoding maps scalar x to hypervector via: z(x) = φ^(β·x_normalized)
where: - φ = [e^(iθ₁), e^(iθ₂), ..., e^(iθₐ)] is base phasor (D dimensions) - θⱼ are random frequencies sampled from phase_dist - x_normalized ∈ [0, 1] is x mapped to unit interval - β is bandwidth parameter
Inner Product Kernel:
For uniform phase distribution θⱼ ~ Uniform[-π, π]: ⟨z(x₁), z(x₂)⟩ / D ≈ sinc(β·π·|x₁ - x₂|)
This sinc kernel has important properties: - Smooth interpolation between similar values - Exact at x₁ = x₂ (similarity = 1) - Decreases monotonically with distance - Zero-crossings at integer multiples of 1/β
Comparison to Random Fourier Features:
FPE is equivalent to Random Fourier Features (Rahimi & Recht, 2007) for kernel approximation: k(x₁, x₂) ≈ φ(x₁)ᵀφ(x₂) / D
where φ(x) = [cos(θ₁x), sin(θ₁x), ..., cos(θₐx), sin(θₐx)]
For complex hypervectors, FPE uses complex exponentials instead: φ(x) = [e^(iθ₁x), e^(iθ₂x), ..., e^(iθₐx)]
which provides more compact representation and supports exact fractional power operations in frequency domain.
References
- Frady et al. (2021): "Computing on Functions Using Randomized Vector Representations" - Original FPE paper
- Rahimi & Recht (2007): "Random Features for Large-Scale Kernel Machines"
- Sutherland & Schneider (2015): "On the Error of Random Fourier Features"
- Verges et al. (2025): "Learning Encoding Phasors with Fractional Power Encoding"
Examples:
>>> # Basic FPE for temperature encoding
>>> model = VSA.create('FHRR', dim=10000)
>>> encoder = FractionalPowerEncoder(model, min_val=0, max_val=100)
>>> temp_25 = encoder.encode(25.0)
>>> temp_26 = encoder.encode(26.0)
>>> similarity = model.similarity(temp_25, temp_26) # ≈ 0.95
>>> # Multi-scale mixture encoding
>>> encoder_mix = FractionalPowerEncoder(
... model, min_val=0, max_val=100,
... mixture_bandwidths=[0.01, 0.1, 1.0, 10.0],
... mixture_weights=[0.4, 0.3, 0.2, 0.1] # Emphasize coarse scales
... )
>>> # Alternative kernel via phase distribution
>>> encoder_gauss = FractionalPowerEncoder(
... model, min_val=0, max_val=100,
... phase_dist='gaussian' # Gaussian kernel instead of sinc
... )
Source code in holovec/encoders/scalar.py
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 | |
__repr__()
String representation.
Source code in holovec/encoders/scalar.py
722 723 724 725 726 727 728 729 730 731 732 | |
decode(hypervector, resolution=1000, max_iterations=100, tolerance=1e-06)
Decode hypervector back to scalar value using two-stage optimization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hypervector
|
Array
|
Hypervector to decode (typically a noisy/bundled encoding). |
required |
resolution
|
int
|
Number of grid points for coarse search (default: 1000). Higher resolution improves initial guess but increases cost. |
1000
|
max_iterations
|
int
|
Maximum gradient descent iterations (default: 100). Typical convergence: 20-50 iterations. |
100
|
tolerance
|
float
|
Convergence tolerance for gradient descent (default: 1e-6). Stop when |Δx| < tolerance. |
1e-06
|
Returns:
| Type | Description |
|---|---|
float
|
Decoded scalar value in [min_val, max_val]. |
Notes
Decoding Algorithm:
Uses two-stage optimization to find value x maximizing similarity: x* = argmax_x ⟨encode(x), hypervector⟩
Stage 1: Coarse Grid Search (O(resolution · D))
- Evaluate similarity at resolution uniformly-spaced points
- Find x₀ with highest similarity
- Provides good initialization for gradient descent
Stage 2: Gradient Descent (O(max_iterations · D)) - Starting from x₀, perform gradient ascent: x_{t+1} = x_t + η_t · ∇_x ⟨encode(x_t), hypervector⟩ - Gradient computed via finite differences: ∇_x ≈ (sim(x + ε) - sim(x)) / ε - Step size η_t decays: η_t = η_0 · 0.95^t (prevents oscillation) - Clips updates to [0, 1] normalized range
Why This Works:
For FPE with sinc kernel K(x₁, x₂) = sinc(β·π·|x₁ - x₂|): - Similarity function is unimodal (single peak) - Peak occurs at x = x_true (encoded value) - Gradient descent converges to global maximum
However, for noisy hypervectors (e.g., bundled encodings): - Multiple local maxima may exist - Coarse search reduces chance of local minimum trap - Wider kernels (small β) → smoother objective → easier optimization
Approximation Quality:
Decoding accuracy depends on several factors:
- Dimension D: Higher D → more accurate encoding → better decoding
- D = 1000: Moderate accuracy (similarity ≈ 0.85)
-
D = 10000: High accuracy (similarity ≈ 0.99)
-
Signal-to-Noise Ratio: Clean encoding vs bundled/noisy
- Clean: Near-perfect recovery (error < 1%)
- Bundled (10 items): Good recovery (error ≈ 5-10%)
-
Bundled (100 items): Degraded (error ≈ 20-30%)
-
Bandwidth β: Wider kernels → smoother similarity landscape
- β = 0.01: Very smooth, easy to optimize
-
β = 10.0: Narrow kernel, may have local maxima
-
Mixture Encoding: Multiple bandwidths complicate landscape
- May require finer grid search (higher resolution)
- May need more gradient descent iterations
Computational Cost:
Total operations: O(resolution · D + max_iterations · D)
Typical values: - resolution = 1000, max_iterations = 100, D = 10000 - Total: ~1.1M evaluations - Runtime: ~0.1-1.0 seconds (CPU), ~0.01-0.1 seconds (GPU)
For real-time applications, reduce resolution or max_iterations: - resolution = 100 (coarser search) - max_iterations = 20 (early stopping)
Comparison to Other Decoders:
-
Codebook Lookup (LevelEncoder): O(K · D) for K levels Faster but discrete, no interpolation
-
Resonator Network (cleanup): O(iterations · M · D) for M items Better for structured/compositional decoding
-
FPE Gradient Descent: O(resolution · D + iterations · D) Best for continuous scalar recovery
References
- Frady et al. (2021): "Computing on Functions Using Randomized Vector Representations" - Section on FPE decoding
- Nocedal & Wright (2006): "Numerical Optimization" - Gradient descent methods and convergence analysis
Examples:
>>> # Basic decoding
>>> model = VSA.create('FHRR', dim=10000)
>>> encoder = FractionalPowerEncoder(model, min_val=0, max_val=100)
>>> hv = encoder.encode(25.0)
>>> decoded = encoder.decode(hv)
>>> print(f"Decoded: {decoded:.2f}") # ≈ 25.00
>>> # Decoding noisy hypervector (bundled encoding)
>>> hv_bundle = model.bundle([encoder.encode(25.0), encoder.encode(26.0)])
>>> decoded_bundle = encoder.decode(hv_bundle)
>>> print(f"Decoded bundle: {decoded_bundle:.2f}") # ≈ 25.5
>>> # Fast decoding (lower resolution/iterations)
>>> decoded_fast = encoder.decode(hv, resolution=100, max_iterations=20)
Source code in holovec/encoders/scalar.py
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 | |
encode(value)
Encode scalar value to hypervector using fractional power.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
float
|
Scalar value to encode. Will be clipped to [min_val, max_val]. |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Encoded hypervector of shape (dimension,) in backend format. |
Notes
Single Bandwidth Encoding:
For single bandwidth β, implements: z(x) = φ^(β·x_normalized)
where: - x_normalized = (value - min_val) / (max_val - min_val) ∈ [0, 1] - φ = [e^(iθ₁), ..., e^(iθₐ)] is base phasor with random frequencies θⱼ - Result is normalized according to model's space
Element-wise computation: z_j(x) = e^(i·θⱼ·β·x_normalized) (complex models) z_j(x) = cos(θⱼ·β·x_normalized) (real models)
Mixture Encoding:
When mixture_bandwidths = [β₁, ..., βₖ] is provided, uses weighted sum: z_mix(x) = Σₖ αₖ · φ^(βₖ·x_normalized)
where αₖ are mixture_weights (default: uniform αₖ = 1/K).
Advantages of Mixture Encoding:
-
Multi-Scale Representation: Combines coarse (small β) and fine (large β) similarity kernels in single hypervector
-
Improved Generalization: Coarse scales provide robustness, fine scales provide discrimination
-
Learned Weights: Weights αₖ can be learned via
learn_mixture_weights()to optimize for specific task -
Kernel Combination: Mixture is equivalent to combining multiple kernels: K_mix(d) = Σₖ αₖ·K_βₖ(d)
Computational Complexity:
- Single bandwidth: O(D) operations (element-wise exponential)
- Mixture with K bandwidths: O(K·D) operations
- Backend operations (exp, multiply) are vectorized/GPU-accelerated
Normalization:
Output is normalized using model's normalization scheme: - FHRR/HRR: L2 normalization (unit norm) - MAP: Element-wise normalization - BSC/BSDC: No normalization (binary)
This ensures hypervectors are in valid space for subsequent binding/bundling operations.
Examples:
>>> # Basic encoding
>>> model = VSA.create('FHRR', dim=10000)
>>> encoder = FractionalPowerEncoder(model, min_val=0, max_val=100)
>>> hv_25 = encoder.encode(25.0) # Encode temperature 25°C
>>> hv_26 = encoder.encode(26.0)
>>> similarity = model.similarity(hv_25, hv_26)
>>> print(f"Similarity: {similarity:.3f}") # ≈ 0.950 (close values)
>>> # Mixture encoding for multi-scale representation
>>> encoder_mix = FractionalPowerEncoder(
... model, min_val=0, max_val=100,
... mixture_bandwidths=[0.01, 1.0, 100.0]
... )
>>> hv_mix = encoder_mix.encode(25.0) # Combines 3 scales
>>> # Effect of bandwidth on similarity
>>> enc_wide = FractionalPowerEncoder(model, 0, 100, bandwidth=0.1)
>>> enc_narrow = FractionalPowerEncoder(model, 0, 100, bandwidth=10.0)
>>> sim_wide = model.similarity(enc_wide.encode(25), enc_wide.encode(30))
>>> sim_narrow = model.similarity(enc_narrow.encode(25), enc_narrow.encode(30))
>>> # sim_wide > sim_narrow (wider kernel → more generalization)
Source code in holovec/encoders/scalar.py
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 | |
learn_mixture_weights(values, labels, reg=0.001)
Learn mixture weights (alphas) for fixed mixture_bandwidths using a simple ridge-style objective that aligns encoded mixtures to per-class prototypes.
Approach: - Build class prototypes p_c as the mean of current encodings (using current weights) - For each sample i, compute per-band encodings E_i = [e_{i1},...,e_{iK}] (shape d×K) - Solve (Σ E_i^T E_i + reg I) α = Σ E_i^T p_{y_i} - Project α onto simplex (nonnegative, sum=1)
Args: values: list of scalar inputs labels: list of integer class labels (same length as values) reg: L2 regularization strength (default 1e-3)
Returns: Learned mixture weights (list of floats summing to 1)
Notes: - Requires mixture_bandwidths to be set (K>=2) - Uses numpy for solving normal equations; backend remains unchanged
Source code in holovec/encoders/scalar.py
735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 | |
holovec.encoders.scalar.ThermometerEncoder
Bases: ScalarEncoder
Thermometer encoding for scalar values.
Divides value range into N bins and encodes a value as the bundle of all bins it exceeds. Creates monotonic similarity profile.
Simpler and more robust than FPE, but with coarser granularity. Works with all VSA models.
References: Kanerva (2009): "Hyperdimensional Computing"
Source code in holovec/encoders/scalar.py
838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 | |
compatible_models
property
Works with all VSA models.
is_reversible
property
Thermometer encoding is not reversible.
__init__(model, min_val, max_val, n_bins=100, seed=None)
Initialize ThermometerEncoder.
Args: model: VSA model (any) min_val: Minimum value of encoding range max_val: Maximum value of encoding range n_bins: Number of bins to divide range into (default 100) seed: Random seed for generating bin vectors
Raises: ValueError: If n_bins < 2
Source code in holovec/encoders/scalar.py
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 | |
__repr__()
String representation.
Source code in holovec/encoders/scalar.py
939 940 941 942 943 944 945 946 947 | |
decode(hypervector)
Decode is not implemented for ThermometerEncoder.
Thermometer encoding is not easily reversible without storing additional information.
Raises: NotImplementedError: Always raises
Source code in holovec/encoders/scalar.py
914 915 916 917 918 919 920 921 922 923 924 925 926 927 | |
encode(value)
Encode scalar as bundle of all bins it exceeds.
Args: value: Scalar value to encode
Returns: Encoded hypervector (bundle of activated bins)
Source code in holovec/encoders/scalar.py
890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 | |
holovec.encoders.scalar.LevelEncoder
Bases: ScalarEncoder
Level (codebook) encoding for discrete scalar values.
Maps discrete levels to random orthogonal vectors via lookup table. Fast (O(1) encode/decode) and exact for discrete values.
Best used when you have a small number of discrete values rather than continuous range.
Example: >>> # Encode weekdays (7 discrete values) >>> model = VSA.create('FHRR', dim=10000) >>> encoder = LevelEncoder(model, min_val=0, max_val=6, n_levels=7) >>> monday = encoder.encode(0) # Exact encoding >>> friday = encoder.encode(4)
Source code in holovec/encoders/scalar.py
950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 | |
compatible_models
property
Works with all VSA models.
is_reversible
property
Level encoding is reversible (to nearest level).
__init__(model, min_val, max_val, n_levels, seed=None)
Initialize LevelEncoder.
Args: model: VSA model (any) min_val: Minimum value (corresponds to level 0) max_val: Maximum value (corresponds to level n_levels-1) n_levels: Number of discrete levels seed: Random seed for generating level vectors
Raises: ValueError: If n_levels < 2
Source code in holovec/encoders/scalar.py
968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 | |
__repr__()
String representation.
Source code in holovec/encoders/scalar.py
1063 1064 1065 1066 1067 1068 1069 1070 1071 | |
decode(hypervector)
Decode hypervector to nearest level value.
Args: hypervector: Hypervector to decode
Returns: Decoded scalar value (will be one of the discrete levels)
Source code in holovec/encoders/scalar.py
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 | |
encode(value)
Encode scalar to nearest level's hypervector.
Args: value: Scalar value to encode
Returns: Hypervector corresponding to nearest level
Source code in holovec/encoders/scalar.py
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 | |
Sequence Encoders
holovec.encoders.sequence.PositionBindingEncoder
Bases: SequenceEncoder
Position binding encoder for sequences using permutation-based positions.
Based on Plate (2003) "Holographic Reduced Representations" and Schlegel et al. (2021) "A comparison of vector symbolic architectures".
Encodes sequences by binding each element with a position-specific permutation of a base position vector:
encode([A, B, C]) = bind(A, ρ¹) + bind(B, ρ²) + bind(C, ρ³)
where ρ is the permutation operation and ρⁱ represents i applications.
This encoding is: - Order-sensitive: Different positions create different bindings - Variable-length: Works with any sequence length - Partial-match capable: Similar sequences have similar encodings
Attributes: codebook: Dictionary mapping symbols to hypervectors auto_generate: Whether to auto-generate vectors for unknown symbols seed_offset: Offset for generating consistent symbol vectors
Example: >>> model = VSA.create('MAP', dim=10000) >>> encoder = PositionBindingEncoder(model) >>> >>> # Encode a sequence of symbols >>> seq = ['hello', 'world', '!'] >>> hv = encoder.encode(seq) >>> >>> # Similar sequences have high similarity >>> seq2 = ['hello', 'world'] >>> hv2 = encoder.encode(seq2) >>> model.similarity(hv, hv2) # High (shared prefix)
Source code in holovec/encoders/sequence.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 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 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | |
compatible_models
property
Works with all VSA models that support permutation.
Returns: List of all model names
is_reversible
property
PositionBindingEncoder supports approximate decoding.
Returns: True (approximate decoding available)
__init__(model, codebook=None, max_length=None, auto_generate=True, seed=None)
Initialize position binding encoder.
Args: model: VSA model instance codebook: Pre-defined symbol → hypervector mapping (optional) max_length: Maximum sequence length (None for unlimited) auto_generate: Auto-generate vectors for unknown symbols (default: True) seed: Random seed for generating symbol vectors
Raises: ValueError: If model is not compatible
Source code in holovec/encoders/sequence.py
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 | |
__repr__()
String representation.
Source code in holovec/encoders/sequence.py
269 270 271 272 273 274 275 276 277 | |
add_symbol(symbol, vector=None)
Add a symbol to the codebook.
Args: symbol: Symbol to add vector: Hypervector to associate (generated if None)
Example:
>>> # Pre-define a vector for a special symbol
>>> special_vec = model.random(seed=42)
>>> encoder.add_symbol('
Source code in holovec/encoders/sequence.py
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | |
decode(hypervector, max_positions=10, threshold=0.3)
Decode sequence hypervector to recover symbols.
Uses cleanup memory approach: for each position, unpermute and find most similar symbol in codebook.
Args: hypervector: Sequence hypervector to decode max_positions: Maximum positions to try decoding (default: 10) threshold: Minimum similarity threshold for valid symbols (default: 0.3)
Returns: List of decoded symbols (may be shorter than original)
Raises: RuntimeError: If codebook is empty
Note: Decoding is approximate and works best for sequences shorter than max_positions with high SNR.
Example: >>> encoded = encoder.encode(['a', 'b', 'c']) >>> decoded = encoder.decode(encoded, max_positions=5) >>> decoded # ['a', 'b', 'c'] (approximate)
Source code in holovec/encoders/sequence.py
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 | |
encode(sequence)
Encode sequence using position binding.
Each element is bound with a position-specific permutation and all bound pairs are bundled:
result = Σᵢ bind(element_i, permute(position_vector, i))
Args: sequence: List of symbols (strings or integers) to encode
Returns: Hypervector representing the sequence
Raises: ValueError: If sequence is empty ValueError: If sequence exceeds max_length ValueError: If symbol not in codebook and auto_generate=False
Example: >>> encoder.encode(['cat', 'sat', 'on', 'mat'])
Source code in holovec/encoders/sequence.py
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 | |
get_codebook_size()
Get number of symbols in codebook.
Returns: Number of symbols stored
Source code in holovec/encoders/sequence.py
240 241 242 243 244 245 246 247 | |
holovec.encoders.sequence.NGramEncoder
Bases: SequenceEncoder
N-gram encoder for capturing local sequence patterns using sliding windows.
Based on Plate (2003), Rachkovskij (1996), and Kleyko et al. (2023) Section 3.3.4.
Encodes sequences by extracting n-grams (sliding windows of n consecutive symbols) and encoding each n-gram compositionally:
For sequence [A, B, C, D] with n=2, stride=1:
- Extract n-grams: [A,B], [B,C], [C,D]
- Encode each n-gram using position binding
- Combine via bundling or chaining
Two encoding modes:
- Bundling mode (bag-of-ngrams): encode(seq) = bundle([encode_ngram([A,B]), encode_ngram([B,C]), ...])
- Order-invariant across n-grams (but preserves within n-gram)
- Good for classification (e.g., text categorization)
-
Similar to bag-of-words but with local context
-
Chaining mode (ordered n-grams): encode(seq) = Σᵢ bind(encode_ngram(ngramᵢ), ρⁱ)
- Order-sensitive across n-grams
- Good for sequence matching
- Enables partial decoding
Attributes: n: Size of n-grams (1=unigrams, 2=bigrams, 3=trigrams, etc.) stride: Step size between n-grams (1=overlapping, n=non-overlapping) mode: 'bundling' or 'chaining' ngram_encoder: Internal PositionBindingEncoder for individual n-grams
Example: >>> model = VSA.create('MAP', dim=10000) >>> encoder = NGramEncoder(model, n=2, stride=1, mode='bundling') >>> >>> # Encode text as bigrams >>> seq = ['the', 'cat', 'sat', 'on', 'mat'] >>> hv = encoder.encode(seq) # Bigrams: [the,cat], [cat,sat], [sat,on], [on,mat] >>> >>> # Similar text has high similarity >>> seq2 = ['the', 'cat', 'sat', 'on', 'hat'] >>> hv2 = encoder.encode(seq2) # Shares 3/4 bigrams >>> model.similarity(hv, hv2) # High similarity
Source code in holovec/encoders/sequence.py
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 | |
compatible_models
property
Works with all VSA models.
Returns: List of all model names
is_reversible
property
NGramEncoder supports decoding only in 'chaining' mode.
Returns: True if mode is 'chaining', False if 'bundling'
__init__(model, n=2, stride=1, mode='bundling', codebook=None, auto_generate=True, seed=None)
Initialize n-gram encoder.
Args: model: VSA model instance n: Size of n-grams (must be >= 1) stride: Step between n-grams (must be >= 1) mode: 'bundling' for bag-of-ngrams or 'chaining' for ordered n-grams codebook: Optional pre-defined symbol → hypervector mapping auto_generate: Auto-generate vectors for unknown symbols seed: Random seed for symbol vector generation
Raises: ValueError: If n < 1, stride < 1, or mode is invalid
Source code in holovec/encoders/sequence.py
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 | |
__repr__()
String representation.
Source code in holovec/encoders/sequence.py
541 542 543 544 545 546 547 548 549 550 | |
decode(hypervector, max_ngrams=10, threshold=0.3)
Decode n-gram hypervector to recover n-grams.
Only supported for 'chaining' mode. For 'bundling' mode, n-grams are order-invariant and cannot be sequentially decoded.
Args: hypervector: Encoded sequence hypervector max_ngrams: Maximum number of n-grams to decode threshold: Minimum similarity threshold for valid n-grams
Returns: List of decoded n-grams, each as a list of symbols
Raises: NotImplementedError: If mode is 'bundling' (not decodable) RuntimeError: If codebook is empty
Example: >>> encoder = NGramEncoder(model, n=2, mode='chaining') >>> hv = encoder.encode(['A', 'B', 'C']) >>> decoder.decode(hv, max_ngrams=3) # [['A', 'B'], ['B', 'C']]
Source code in holovec/encoders/sequence.py
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 | |
encode(sequence)
Encode sequence using n-gram representation.
Extracts all n-grams using sliding window with specified stride, encodes each n-gram, then combines via bundling or chaining.
Args: sequence: List of symbols to encode
Returns: Hypervector representing the sequence as n-grams
Raises: ValueError: If sequence is too short (length < n)
Example: >>> # Bigrams with stride=1 (overlapping) >>> encoder = NGramEncoder(model, n=2, stride=1) >>> encoder.encode(['A', 'B', 'C']) # N-grams: AB, BC >>> >>> # Trigrams with stride=2 (partial overlap) >>> encoder = NGramEncoder(model, n=3, stride=2) >>> encoder.encode(['A', 'B', 'C', 'D', 'E']) # N-grams: ABC, CDE
Source code in holovec/encoders/sequence.py
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 | |
get_codebook()
Get the internal symbol codebook.
Returns: Dictionary mapping symbols to hypervectors
Source code in holovec/encoders/sequence.py
503 504 505 506 507 508 509 510 | |
get_codebook_size()
Get number of unique symbols in codebook.
Returns: Number of symbols
Source code in holovec/encoders/sequence.py
512 513 514 515 516 517 518 519 | |
holovec.encoders.sequence.TrajectoryEncoder
Bases: SequenceEncoder
Trajectory encoder for continuous sequences (time series, paths, motion).
Based on Frady et al. (2021) "Computing on Functions" and position binding from Plate (2003), encoding trajectories by binding temporal information with spatial positions.
A trajectory is a sequence of positions over time: - 1D: time series [v₁, v₂, v₃, ...] - 2D: path [(x₁,y₁), (x₂,y₂), ...] - 3D: motion [(x₁,y₁,z₁), (x₂,y₂,z₂), ...]
Encoding strategy: For each time step tᵢ with position pᵢ: 1. Encode time: time_hv = scalar_encode(tᵢ) 2. Encode position coords: coord_hvs = [scalar_encode(c) for c in pᵢ] 3. Bind coords to dimensions: pos_hv = Σⱼ bind(Dⱼ, coord_hv_j) 4. Bind time with position: point_hv = bind(time_hv, pos_hv) 5. Permute by index: indexed_hv = permute(point_hv, i)
trajectory_hv = Σᵢ indexed_hv
This creates an encoding that: - Preserves temporal ordering (via permutation) - Captures smooth trajectories (via continuous scalar encoding) - Enables partial matching and interpolation - Supports multi-dimensional paths
Attributes: scalar_encoder: Encoder for continuous values (FPE or Thermometer) n_dimensions: Dimensionality of trajectory (1D, 2D, or 3D) time_range: (min_time, max_time) for temporal normalization dim_vectors: Hypervectors for spatial dimensions (x, y, z)
Example: >>> from holovec import VSA >>> from holovec.encoders import FractionalPowerEncoder, TrajectoryEncoder >>> >>> model = VSA.create('FHRR', dim=10000) >>> scalar_enc = FractionalPowerEncoder(model, min_val=0, max_val=100) >>> encoder = TrajectoryEncoder(model, scalar_encoder=scalar_enc, n_dimensions=2) >>> >>> # Encode a 2D path >>> path = [(10, 20), (15, 25), (20, 30), (25, 35)] >>> hv = encoder.encode(path) >>> >>> # Similar paths have high similarity >>> path2 = [(10, 20), (15, 25), (20, 30), (25, 40)] # Slightly different >>> hv2 = encoder.encode(path2) >>> model.similarity(hv, hv2) # High similarity
Source code in holovec/encoders/sequence.py
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 | |
compatible_models
property
Works with all VSA models.
Returns: List of all model names
input_type
property
Input type description.
is_reversible
property
TrajectoryEncoder does not yet support decoding.
Returns: False (decoding not implemented)
Note: Decoding requires multi-level unbinding and interpolation, which will be implemented in a future version.
__init__(model, scalar_encoder, n_dimensions=1, time_range=None, seed=None)
Initialize trajectory encoder.
Args: model: VSA model instance scalar_encoder: Encoder for continuous values (FPE or Thermometer recommended) n_dimensions: Trajectory dimensionality (1, 2, or 3) time_range: (min, max) time values for normalization (optional) seed: Random seed for dimension vector generation
Raises: ValueError: If n_dimensions not in {1, 2, 3} TypeError: If scalar_encoder is not reversible
Source code in holovec/encoders/sequence.py
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 | |
__repr__()
String representation.
Source code in holovec/encoders/sequence.py
885 886 887 888 889 890 891 892 893 | |
decode(hypervector, max_points=10)
Decode trajectory hypervector to recover approximate points.
Note: Trajectory decoding is not yet implemented. It requires: 1. Unpermuting each position 2. Unbinding time from position 3. Unbinding each coordinate from dimension vectors 4. Decoding scalar values 5. Interpolation for smooth trajectories
Args: hypervector: Encoded trajectory hypervector max_points: Maximum points to decode
Returns: List of decoded points (not implemented yet)
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
Trajectory decoding requires solving nested binding inverse problem. |
Notes
Trajectory decoding is not implemented because it requires multi-level unbinding with cascading error accumulation:
Mathematical Challenge:
The encoding process creates nested bindings: trajectory_hv = bundle([ bind(time(t), bind(dimension(d), scalar(coord[t,d]))) for all t, d ])
To decode a single point at time t: 1. Unbind time: point_hv[t] = unbind(trajectory_hv, time(t)) 2. For each dimension d: a. Unbind dimension: coord_hv[d] = unbind(point_hv[t], dimension(d)) b. Decode scalar: coord[t,d] = scalar_decode(coord_hv[d])
Why This Is Intractable:
- Two-level unbinding: Time then dimension (or vice versa)
- Error compounding: Each unbind adds noise
- No known time points: Must search over possible time values
- Interpolation complexity: Smooth trajectory requires dense sampling
- Computational cost:
- For T time points, D dimensions
- Requires: T × D × (decode_iterations) evaluations
- Example: 100 points × 3D × 100 iterations = 30,000 evals
Additional Challenges:
- Order Ambiguity: Don't know which time point comes first
- Density Unknown: Don't know temporal sampling rate
- Dimension Count: Must know dimensionality a priori
- Coordinate Ranges: Scalar decoder needs value bounds
Possible Approaches (Future Work):
- Constrained Decoding: If time points are known:
- Unbind each known time point
- Decode coordinates independently
-
Complexity: O(T × D × decode_cost)
-
Template Matching: Pre-encode common trajectory patterns
- Create codebook of canonical trajectories
- Use cleanup to find nearest match
-
Works for classification, not reconstruction
-
Learned Decoder: Train neural network trajectory_hv → points
- Requires large training dataset
- Can learn to handle noise and ambiguity
-
See: Imani et al. (2019) for similar approach
-
Iterative Resonator: Use resonator cleanup at each level
- Unbind time with resonator cleanup
- Unbind dimension with resonator cleanup
- Requires codebooks for both time and coordinates
Current Recommendation:
Use TrajectoryEncoder for one-way encoding in applications like: - Trajectory classification (gesture recognition, motion analysis) - Trajectory similarity search (find similar paths) - Trajectory clustering (group similar motions)
For reconstruction, consider storing original trajectories separately and using hypervector encoding only for similarity queries.
References
- Plate (2003): "Holographic Reduced Representations" - Section 4.3 on error accumulation in multi-level binding
- Räsänen & Saarinen (2016): "Sequence prediction with sparse distributed hyperdimensional coding" - Analysis of temporal binding
Source code in holovec/encoders/sequence.py
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 | |
encode(trajectory)
Encode a trajectory as a hypervector.
Each point in the trajectory is encoded with temporal information, then all points are combined with position-based permutation.
Args: trajectory: List of points - 1D: List[float] e.g., [1.0, 2.5, 3.7, ...] - 2D: List[Tuple[float, float]] e.g., [(1,2), (3,4), ...] - 3D: List[Tuple[float, float, float]] e.g., [(1,2,3), ...]
Returns: Hypervector representing the trajectory
Raises: ValueError: If trajectory is empty or points have wrong dimensionality
Example: >>> # 1D time series >>> encoder_1d = TrajectoryEncoder(model, scalar_enc, n_dimensions=1) >>> hv = encoder_1d.encode([1.0, 2.5, 3.7, 5.2]) >>> >>> # 2D path >>> encoder_2d = TrajectoryEncoder(model, scalar_enc, n_dimensions=2) >>> hv = encoder_2d.encode([(0,0), (1,1), (2,2)])
Source code in holovec/encoders/sequence.py
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 | |
Spatial Encoders
holovec.encoders.spatial.ImageEncoder
Bases: Encoder
Image encoder for 2D images (grayscale, RGB, or RGBA).
Encodes images by binding spatial positions (x, y) with pixel values. For color images, each channel is bound to a channel dimension vector before being combined with position information.
Encoding strategy: For each pixel at position (x, y) with value v: 1. Encode position: pos_hv = bundle([bind(X, enc(x)), bind(Y, enc(y))]) 2. Encode value(s): - Grayscale: val_hv = enc(v) - RGB: val_hv = bundle([bind(R, enc(r)), bind(G, enc(g)), bind(B, enc(b))]) 3. Bind position with value: pixel_hv = bind(pos_hv, val_hv) 4. Bundle all pixels: image_hv = bundle([all pixel_hvs])
This creates a distributed representation that preserves both spatial structure and pixel values, enabling similarity-based image comparison.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
VSAModel
|
The VSA model to use for encoding operations. |
required |
scalar_encoder
|
ScalarEncoder
|
Encoder for continuous pixel values (0-255 typically). |
required |
normalize_pixels
|
bool
|
Whether to normalize pixel values to [0, 1] before encoding. Default is True. |
True
|
seed
|
int
|
Random seed for reproducibility. Default is None. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
n_channels |
int
|
Number of channels in the last encoded image (1, 3, or 4). |
image_shape |
tuple
|
Shape (height, width, channels) of the last encoded image. |
Examples:
>>> from holovec import VSA
>>> from holovec.encoders import ImageEncoder, ThermometerEncoder
>>> import numpy as np
>>>
>>> model = VSA.create('MAP', dim=10000, seed=42)
>>> scalar_enc = ThermometerEncoder(model, min_val=0, max_val=1, n_bins=256, seed=42)
>>> encoder = ImageEncoder(model, scalar_enc, normalize_pixels=True, seed=42)
>>>
>>> # Encode a small grayscale image
>>> image = np.array([[100, 150], [200, 250]], dtype=np.uint8)
>>> hv = encoder.encode(image)
>>> print(hv.shape) # (10000,)
>>>
>>> # Encode RGB image
>>> rgb_image = np.random.randint(0, 256, (28, 28, 3), dtype=np.uint8)
>>> hv_rgb = encoder.encode(rgb_image)
Source code in holovec/encoders/spatial.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 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 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 | |
compatible_models
property
List of compatible VSA model names.
Returns:
| Type | Description |
|---|---|
list of str
|
All VSA models supported (depends on scalar encoder compatibility). |
input_type
property
Description of expected input type.
Returns:
| Type | Description |
|---|---|
str
|
Description of input format. |
is_reversible
property
Whether the encoder supports decoding.
Returns:
| Type | Description |
|---|---|
bool
|
False - image decoding not yet implemented. |
__init__(model, scalar_encoder, normalize_pixels=True, seed=None)
Initialize ImageEncoder.
Source code in holovec/encoders/spatial.py
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 | |
__repr__()
Return string representation.
Source code in holovec/encoders/spatial.py
357 358 359 360 361 362 363 | |
decode(hypervector, height, width, n_channels=1)
Decode a hypervector to reconstruct an approximate image.
Note: Image decoding is approximate and requires knowing the target image dimensions. Reconstruction quality depends on the scalar encoder's decoding capabilities and may require candidate value search.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hypervector
|
Array
|
The hypervector to decode. |
required |
height
|
int
|
Target image height. |
required |
width
|
int
|
Target image width. |
required |
n_channels
|
int
|
Number of channels (1, 3, or 4). Default is 1. |
1
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Reconstructed image with shape (height, width) for grayscale or (height, width, n_channels) for color. |
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
Image decoding is computationally intractable without additional constraints. |
Notes
Image decoding is not implemented because it requires solving a high-dimensional inverse problem that is fundamentally ill-posed:
Mathematical Challenge:
The encoding process binds pixel values with position vectors: image_hv = bundle([bind(position(i,j), scalar(pixel[i,j])) for all i,j])
To decode, we must: 1. Unbind each position: pixel_hv[i,j] = unbind(image_hv, position(i,j)) 2. Decode each scalar: pixel[i,j] = scalar_decode(pixel_hv[i,j])
Why This Is Intractable:
- Unbinding is approximate (except for FHRR with exact inverse)
- Each unbind operation introduces noise
- For H×W image: H×W unbind operations compound errors
- Scalar decoding via optimization (1000 evals × 100 iterations)
- Total: ~100M evaluations for 100×100 image
- No gradient available for joint optimization
Alternative Approaches:
- Database Retrieval: Encode query image, find nearest match in database
- Complexity: O(N) for N known images
-
Works well for classification/recognition tasks
-
Iterative Resonator: Use resonator cleanup with pixel codebook
- Requires pre-built codebook of common pixel patterns
-
May reconstruct coarse structure but not fine details
-
Neural Decoder: Train neural network image_hv → image
- Requires supervised training data
- Can learn inverse mapping empirically
- See: Imani et al. (2019) "VoiceHD" for similar approach
For practical applications, use ImageEncoder for one-way encoding (e.g., image→hypervector→classifier) rather than reconstruction.
References
- Imani et al. (2019): "VoiceHD: Hyperdimensional Computing for Efficient Speech Recognition"
- Plate (2003): "Holographic Reduced Representations" - Chapter 4 on approximate unbinding and error accumulation
Source code in holovec/encoders/spatial.py
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 | |
encode(image)
Encode an image into a hypervector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image
|
array - like
|
Image array with shape (height, width) for grayscale or (height, width, channels) for color images. Pixel values should be in range [0, 255] for uint8 or [0, 1] for float. Typically a NumPy array from PIL, OpenCV, or similar libraries. |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Hypervector encoding of the image. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If image has invalid shape or number of channels. |
Notes
This encoder accepts images as NumPy arrays (the standard format from image libraries like PIL, OpenCV, scikit-image) and processes them using the configured backend. While input must be NumPy, internal VSA operations use the model's backend (NumPy/PyTorch/JAX).
Source code in holovec/encoders/spatial.py
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 | |
holovec.encoders.structured.VectorEncoder
Bases: StructuredEncoder
Vector encoder for multi-dimensional numeric data using role-filler binding.
Encodes vectors by binding each dimension with its scalar-encoded value:
encode([v₁, v₂, ..., vₐ]) = Σᵢ bind(Dᵢ, scalar_encode(vᵢ))
where: - Dᵢ is a random hypervector for dimension i - scalar_encode(vᵢ) encodes the scalar value using FPE/Thermometer/Level - bind() creates a role-filler binding - Σ bundles all dimension-value pairs
This creates a compositional encoding where: - Each dimension has explicit representation (Dᵢ) - Similar values in corresponding dimensions → higher similarity - Supports partial matching across dimensions - Enables approximate decoding via unbinding
Attributes: scalar_encoder: Encoder for individual scalar values n_dimensions: Number of dimensions in input vectors dim_vectors: List of dimension hypervectors (Dᵢ) normalize_input: Whether to normalize input vectors
Example: >>> from holovec import VSA >>> from holovec.encoders import FractionalPowerEncoder, VectorEncoder >>> >>> model = VSA.create('FHRR', dim=10000) >>> scalar_enc = FractionalPowerEncoder(model, min_val=0, max_val=1) >>> encoder = VectorEncoder(model, scalar_encoder=scalar_enc, n_dims=128) >>> >>> # Encode a feature vector (list or any backend array) >>> features = [0.5] * 128 # Can also use numpy/torch/jax arrays >>> hv = encoder.encode(features) >>> >>> # Similar vectors have high similarity >>> features2 = [0.51] * 128 # Slightly different >>> hv2 = encoder.encode(features2) >>> model.similarity(hv, hv2) # High similarity >>> >>> # Decode to recover approximate values >>> recovered = encoder.decode(hv) >>> # Verify approximate recovery via similarity >>> model.similarity(encoder.encode(recovered), hv) > 0.9
Source code in holovec/encoders/structured.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 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 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 | |
compatible_models
property
Works with all VSA models.
Decoding quality varies: - Exact models (FHRR, MAP): High accuracy - Approximate models (HRR, BSC): Moderate accuracy
Returns: List of all model names
input_type
property
Input type description.
is_reversible
property
VectorEncoder supports approximate decoding if scalar_encoder does.
Returns: True if scalar_encoder supports decoding, False otherwise
__init__(model, scalar_encoder, n_dimensions, normalize_input=False, seed=None)
Initialize vector encoder.
Args: model: VSA model instance scalar_encoder: Encoder for individual scalar values n_dimensions: Number of dimensions in input vectors normalize_input: Whether to normalize input vectors to unit length seed: Random seed for dimension vector generation
Raises: ValueError: If n_dimensions < 1 TypeError: If scalar_encoder is not a ScalarEncoder
Source code in holovec/encoders/structured.py
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 | |
__repr__()
String representation.
Source code in holovec/encoders/structured.py
248 249 250 251 252 253 254 255 256 | |
decode(hypervector)
Decode vector hypervector to recover approximate values.
For each dimension i: 1. Unbind dimension: value_hv = unbind(hypervector, Dᵢ) 2. Decode scalar: value ≈ scalar_encoder.decode(value_hv)
Args: hypervector: Vector hypervector to decode, shape (dimension,)
Returns: Decoded vector, shape (n_dimensions,) (backend array type)
Raises: NotImplementedError: If scalar_encoder doesn't support decoding
Note: Decoding is approximate and quality depends on: - VSA model (exact vs. approximate binding) - Scalar encoder precision - Number of dimensions (more dims → more noise)
Example: >>> original = [1.0, 2.0, 3.0] >>> encoded = encoder.encode(original) >>> decoded = encoder.decode(encoded) >>> # Check approximate recovery (using backend operations) >>> model.similarity(encoder.encode(decoded), encoded) > 0.9
Source code in holovec/encoders/structured.py
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 | |
encode(vector)
Encode a vector using dimension binding.
Each element is bound with its corresponding dimension vector:
result = Σᵢ bind(Dᵢ, scalar_encode(vector[i]))
Args: vector: Input vector to encode, shape (n_dimensions,)
Returns: Hypervector representing the vector
Raises: ValueError: If vector shape doesn't match n_dimensions
Example: >>> encoder = VectorEncoder(model, scalar_enc, n_dims=3) >>> vector = [1.0, 2.0, 3.0] # Can also be numpy/torch/jax array >>> hv = encoder.encode(vector)
Source code in holovec/encoders/structured.py
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 | |
Retrieval
Codebook
holovec.retrieval.codebook.Codebook
Thin wrapper for label→vector mappings with convenience methods.
Keeps insertion order of labels. Vectors are backend arrays.
Source code in holovec/retrieval/codebook.py
8 9 10 11 12 13 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 | |
__contains__(label)
Check if label exists in codebook.
Source code in holovec/retrieval/codebook.py
41 42 43 | |
__getitem__(label)
Get vector by label. Raises KeyError if not found.
Source code in holovec/retrieval/codebook.py
37 38 39 | |
__iter__()
Iterate over labels.
Source code in holovec/retrieval/codebook.py
49 50 51 | |
__len__()
Return number of items in codebook.
Source code in holovec/retrieval/codebook.py
45 46 47 | |
as_matrix(backend=None)
Return (labels, matrix) where matrix has shape (L, D).
Source code in holovec/retrieval/codebook.py
72 73 74 75 76 77 78 79 | |
get(label, default=None)
Get vector by label, returning default if not found.
Source code in holovec/retrieval/codebook.py
65 66 67 | |
items()
Return iterator over (label, vector) pairs.
Source code in holovec/retrieval/codebook.py
53 54 55 | |
keys()
Return iterator over labels.
Source code in holovec/retrieval/codebook.py
57 58 59 | |
values()
Return iterator over vectors.
Source code in holovec/retrieval/codebook.py
61 62 63 | |
ItemStore
holovec.retrieval.itemstore.ItemStore
Thin retrieval wrapper around a Codebook and a CleanupStrategy.
Provides nearest-neighbor queries and multi-factor factorization via the configured cleanup strategy.
Source code in holovec/retrieval/itemstore.py
9 10 11 12 13 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 | |
query(vec, k=1, return_similarities=True, fast=True)
Query top-k nearest items.
If fast=True, uses a batched matrix routine when possible, otherwise falls back to scalar nearest_neighbors.
Source code in holovec/retrieval/itemstore.py
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 | |
AssocStore
holovec.retrieval.assocstore.AssocStore
Lean heteroassociative store: keys → values via aligned codebooks.
Stores two codebooks with aligned label order. Query by a key vector returns the best-matching key label and its corresponding value label/vector.
Source code in holovec/retrieval/assocstore.py
7 8 9 10 11 12 13 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 | |
Cleanup
holovec.utils.cleanup.BruteForceCleanup
Bases: CleanupStrategy
Brute-force cleanup via exhaustive codebook search.
This is the baseline cleanup strategy that computes similarity between the query and every codebook entry, returning the best match. Simple and effective, but slow for large codebooks.
Performance: - Time complexity: O(n × d) for n items, d dimensions - Space complexity: O(1) - Best for: Small codebooks (< 1000 items)
Examples: >>> # Create strategy >>> cleanup = BruteForceCleanup() >>> >>> # Single cleanup >>> label, sim = cleanup.cleanup(query, codebook, model) >>> print(f"Found: {label}") >>> >>> # Multi-factor factorization >>> labels, sims = cleanup.factorize(query, codebook, model, n_factors=3) >>> print(f"Factors: {labels}")
References: Kanerva (2009): Classic cleanup operation
Source code in holovec/utils/cleanup.py
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 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 | |
cleanup(query, codebook, model)
Find best match via exhaustive search.
Computes similarity between query and every codebook entry, returning the label with highest similarity.
Args: query: Query hypervector to clean up codebook: Dictionary mapping labels to hypervectors model: VSA model for similarity computation
Returns: Tuple of (label, similarity) for the best match
Raises: TypeError: If arguments are not correct types ValueError: If codebook is empty
Examples: >>> label, sim = cleanup.cleanup(query, codebook, model) >>> print(f"Best match: {label} (sim: {sim:.3f})")
Source code in holovec/utils/cleanup.py
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 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | |
factorize(query, codebook, model, n_factors=2, max_iterations=20, threshold=0.99)
Factorize via iterative cleanup and unbinding.
Repeatedly finds the best match, unbinds it from the query, and continues until n_factors are extracted or convergence.
Args: query: Composite hypervector to factorize codebook: Dictionary mapping labels to hypervectors model: VSA model for bind/unbind/similarity operations n_factors: Number of factors to extract (default: 2) max_iterations: Maximum iterations per factor (default: 20) threshold: Convergence threshold for similarity (default: 0.99)
Returns: Tuple of: - labels: List of factor labels in extraction order - similarities: List of similarities for each factor
Raises: TypeError: If arguments are not correct types ValueError: If n_factors < 1 or codebook is empty
Examples: >>> labels, sims = cleanup.factorize( ... query, codebook, model, n_factors=3, threshold=0.95 ... ) >>> print(f"Extracted {len(labels)} factors")
Source code in holovec/utils/cleanup.py
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 | |
holovec.utils.cleanup.ResonatorCleanup
Bases: CleanupStrategy
Resonator network cleanup via iterative refinement.
Implements the resonator network algorithm from Kymn et al. (2024), which uses iterative attention mechanisms to refine factor estimates. Achieves 10-100x speedup over brute-force for multi-factor unbinding.
Algorithm: 1. Initialize estimates for all factors 2. For each iteration: a. Unbind other factors to isolate target b. Cleanup against codebook c. Update estimate 3. Repeat until convergence or max_iterations
Performance: - Convergence: Typically 5-15 iterations - Speedup: 10-100x over brute-force - Best for: Multi-factor compositions (3+ factors)
Examples: >>> # Create resonator cleanup >>> cleanup = ResonatorCleanup() >>> >>> # Single cleanup (same as brute-force) >>> label, sim = cleanup.cleanup(query, codebook, model) >>> >>> # Multi-factor with resonator (much faster) >>> labels, sims = cleanup.factorize( ... query, codebook, model, n_factors=5, threshold=0.99 ... ) >>> print(f"Converged with {len(labels)} factors")
Attributes: None (stateless)
References: Kymn et al. (2024): Attention Mechanisms in VSAs - Section 3: Resonator Networks - Algorithm 1: Iterative factorization
Source code in holovec/utils/cleanup.py
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 | |
cleanup(query, codebook, model)
Find best match via exhaustive search.
For single-factor cleanup, resonator networks reduce to brute-force search. Use factorize() for multi-factor speedup.
Args: query: Query hypervector to clean up codebook: Dictionary mapping labels to hypervectors model: VSA model for similarity computation
Returns: Tuple of (label, similarity) for the best match
Raises: TypeError: If arguments are not correct types ValueError: If codebook is empty
Examples: >>> label, sim = cleanup.cleanup(query, codebook, model)
Source code in holovec/utils/cleanup.py
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 | |
factorize(query, codebook, model, n_factors=2, max_iterations=20, threshold=0.99, temperature=20.0, top_k=1, patience=3, min_delta=0.0001, mode='hard')
Factorize via resonator network iteration.
Uses iterative attention to refine factor estimates simultaneously, achieving much faster convergence than sequential unbinding.
Algorithm (from Kymn et al. 2024): 1. Initialize: estimates = [random from codebook] × n_factors 2. Repeat for max_iterations: a. For each factor i: - Unbind all other estimates from query - Cleanup result against codebook - Update estimate[i] b. Check convergence (all similarities >= threshold) 3. Return final estimates and similarities
Args: query: Composite hypervector to factorize codebook: Dictionary mapping labels to hypervectors model: VSA model for bind/unbind/similarity operations n_factors: Number of factors to extract (default: 2) max_iterations: Maximum iterations (default: 20) threshold: Convergence threshold for similarity (default: 0.99)
Returns: Tuple of: - labels: List of factor labels - similarities: List of similarities for each factor
Raises: TypeError: If arguments are not correct types ValueError: If n_factors < 1 or codebook is empty
Examples: >>> # Fast multi-factor unbinding >>> labels, sims = cleanup.factorize( ... query, codebook, model, n_factors=5 ... ) >>> print(f"Factors: {labels}") >>> print(f"Avg similarity: {sum(sims)/len(sims):.3f}")
Source code in holovec/utils/cleanup.py
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 | |
factorize_verbose(query, codebook, model, n_factors=2, max_iterations=20, threshold=0.99, temperature=20.0, top_k=1, patience=3, min_delta=0.0001, mode='hard')
Like factorize(), but also returns avg-similarity history per iteration.
Source code in holovec/utils/cleanup.py
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 | |
Backends
holovec.backends.base.Backend
Bases: ABC
Abstract base class for computational backends.
All backends must implement these operations to support VSA computations across different frameworks (NumPy, PyTorch, JAX).
Source code in holovec/backends/base.py
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 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 | |
zeros(shape, dtype='float32')
abstractmethod
Create an array of zeros with the given shape and dtype.
Source code in holovec/backends/base.py
99 100 101 102 | |
ones(shape, dtype='float32')
abstractmethod
Create an array of ones with the given shape and dtype.
Source code in holovec/backends/base.py
104 105 106 107 | |
random_normal(shape, mean=0.0, std=1.0, dtype='float32', seed=None)
abstractmethod
Create an array of random values from a normal distribution.
Source code in holovec/backends/base.py
109 110 111 112 113 114 115 116 117 118 119 | |
add(a, b)
abstractmethod
Element-wise addition.
Source code in holovec/backends/base.py
177 178 179 180 | |
multiply(a, b)
abstractmethod
Element-wise multiplication.
Source code in holovec/backends/base.py
172 173 174 175 | |
dot(a, b)
abstractmethod
Dot product of two vectors.
Source code in holovec/backends/base.py
275 276 277 278 | |
fft(a)
abstractmethod
1D Fast Fourier Transform.
Source code in holovec/backends/base.py
365 366 367 368 | |
ifft(a)
abstractmethod
1D Inverse Fast Fourier Transform.
Source code in holovec/backends/base.py
370 371 372 373 | |
norm(a, ord=2, axis=None)
abstractmethod
Compute the norm of an array.
Source code in holovec/backends/base.py
270 271 272 273 | |
normalize(a, ord=2, axis=None, eps=1e-12)
abstractmethod
Normalize an array to unit norm.
Source code in holovec/backends/base.py
336 337 338 339 | |
to_numpy(a)
abstractmethod
Convert array to NumPy array (for compatibility).
Source code in holovec/backends/base.py
428 429 430 431 | |
from_numpy(a)
abstractmethod
Create backend array from NumPy array.
Source code in holovec/backends/base.py
433 434 435 436 | |
supports_gpu()
Check if backend has GPU acceleration support.
GPU support enables significant speedups for large-scale operations and is critical for production deployments.
Returns: True if backend can utilize GPU hardware
Source code in holovec/backends/base.py
58 59 60 61 62 63 64 65 66 67 | |
supports_complex()
Check if backend supports complex number operations.
Complex operations are required for FHRR (Fourier HRR) and other frequency-domain VSA models.
Returns: True if backend can handle complex dtypes (complex64, complex128)
Source code in holovec/backends/base.py
36 37 38 39 40 41 42 43 44 45 | |
supports_sparse()
Check if backend supports sparse array operations.
Sparse operations are beneficial for BSC (Binary Spatter Codes) and BSDC (Binary Sparse Distributed Codes) which have high sparsity.
Returns: True if backend has native sparse array support
Source code in holovec/backends/base.py
47 48 49 50 51 52 53 54 55 56 | |