Operators API Reference¶
NEW in v1.1.0 - Exact, compositional, invertible transformations for reasoning.
Overview¶
The operators module provides Clifford-inspired operators for exact transformations in VSA reasoning.
Key classes:
- CliffordOperator - Phase-based operator for FHRR hypervectors
- AbstractOperator - Base interface for all operators
- OperatorKind - Enum for semantic operator types
- OperatorMetadata - Metadata dataclass for operators
Module Structure¶
vsax.operators/
├── CliffordOperator # Core operator implementation
├── AbstractOperator # Abstract base class
├── OperatorKind # Semantic type enum
└── OperatorMetadata # Metadata dataclass
Quick Reference¶
Creating Operators¶
from vsax.operators import CliffordOperator, OperatorKind
import jax
# Create random operator
op = CliffordOperator.random(
dim=512,
kind=OperatorKind.SPATIAL,
name="LEFT_OF",
key=jax.random.PRNGKey(42)
)
Applying Transformations¶
from vsax import create_fhrr_model, VSAMemory
model = create_fhrr_model(dim=512)
memory = VSAMemory(model)
memory.add("concept")
# Apply operator
transformed = op.apply(memory["concept"])
# Exact inversion
recovered = op.inverse().apply(transformed)
Composing Operators¶
# Create two operators
op1 = CliffordOperator.random(512, key=jax.random.PRNGKey(1))
op2 = CliffordOperator.random(512, key=jax.random.PRNGKey(2))
# Compose
composed = op1.compose(op2)
Detailed API¶
CliffordOperator¶
vsax.operators.clifford.CliffordOperator
dataclass
¶
Bases: AbstractOperator
Clifford-inspired operator for FHRR hypervectors.
Represents a phase-based transformation that compiles to FHRR operations. The operator applies element-wise phase rotation to complex hypervectors:
apply(v) = v * exp(i * params)
This provides exact, compositional, invertible transformations inspired by Clifford algebra, where: - Elementary operators act as bivectors (phase generators) - Composed operators act as rotors (sum of generators) - Operator composition uses phase addition - Inversion uses phase negation
The operator is compatible with FHRR's phase algebra and preserves the unit-magnitude property of complex hypervectors.
Attributes:
| Name | Type | Description |
|---|---|---|
params |
ndarray
|
Phase rotation parameters as JAX array (shape: dim). Each element specifies the phase shift for that dimension. |
metadata |
Optional[OperatorMetadata]
|
Optional semantic metadata (kind, name, description). |
Example
from vsax import create_fhrr_model, VSAMemory from vsax.operators import CliffordOperator import jax
model = create_fhrr_model(dim=512) memory = VSAMemory(model) memory.add("test")
Create operator¶
op = CliffordOperator.random(512, key=jax.random.PRNGKey(0))
Apply transformation¶
transformed = op.apply(memory["test"])
Verify exact inversion¶
recovered = op.inverse().apply(transformed) from vsax.similarity import cosine_similarity similarity = cosine_similarity(recovered.vec, memory["test"].vec) assert similarity > 0.999 # Exact inverse
Source code in vsax/operators/clifford.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 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 | |
Attributes¶
dim
property
¶
Dimensionality of operator.
Returns:
| Type | Description |
|---|---|
int
|
Integer dimension matching the hypervectors this operator |
int
|
can transform. |
Functions¶
__init__(params, metadata=None)
¶
apply(v)
¶
Apply phase rotation to hypervector.
Transforms the input hypervector by applying element-wise phase rotation:
result = v * exp(i * params)
This operation is: - Norm-preserving (maintains unit magnitude for FHRR) - Exactly invertible - Compatible with FHRR circular convolution
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
v
|
AbstractHypervector
|
ComplexHypervector to transform. Must have same dimensionality as operator. |
required |
Returns:
| Type | Description |
|---|---|
ComplexHypervector
|
Transformed ComplexHypervector with same shape as input. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If v is not a ComplexHypervector. CliffordOperator only works with FHRR (complex-valued) representations. |
ValueError
|
If dimension of v doesn't match operator dimension. |
Example
from vsax import create_fhrr_model, VSAMemory from vsax.operators import CliffordOperator import jax
model = create_fhrr_model(dim=512) memory = VSAMemory(model) memory.add("test")
op = CliffordOperator.random(512, key=jax.random.PRNGKey(0)) transformed = op.apply(memory["test"]) print(transformed.shape) (512,)
Source code in vsax/operators/clifford.py
inverse()
¶
Return exact inverse operator.
For phase rotations, the inverse is phase negation:
inverse(params) = -params
exp(i * (-params)) = exp(-i * params) = conj(exp(i * params))
This provides exact inversion with similarity > 0.999:
op.inverse().apply(op.apply(v)) ≈ v
Returns:
| Type | Description |
|---|---|
CliffordOperator
|
CliffordOperator with negated phase parameters that exactly |
CliffordOperator
|
undoes this operator's transformation. |
Example
from vsax import create_fhrr_model, VSAMemory from vsax.operators import CliffordOperator from vsax.similarity import cosine_similarity import jax
model = create_fhrr_model(dim=512) memory = VSAMemory(model) memory.add("test")
op = CliffordOperator.random(512, key=jax.random.PRNGKey(0)) transformed = op.apply(memory["test"]) recovered = op.inverse().apply(transformed)
similarity = cosine_similarity(recovered.vec, memory["test"].vec) print(f"Inversion accuracy: {similarity:.6f}") Inversion accuracy: 1.000000
Source code in vsax/operators/clifford.py
compose(other)
¶
Compose two operators.
Creates a new operator that applies both transformations in sequence. For phase-based operators, composition uses phase addition:
compose(op1, op2).params = op1.params + op2.params
exp(i * (params1 + params2)) applies both rotations
Composition is: - Associative: (op1 ∘ op2) ∘ op3 = op1 ∘ (op2 ∘ op3) - Commutative: op1 ∘ op2 = op2 ∘ op1 (for phase addition)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
AbstractOperator
|
Another CliffordOperator to compose with. Must have same dimensionality. |
required |
Returns:
| Type | Description |
|---|---|
CliffordOperator
|
Composed CliffordOperator representing both transformations. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If other is not a CliffordOperator. |
ValueError
|
If dimensions don't match. |
Example
from vsax.operators import CliffordOperator import jax
op1 = CliffordOperator.random(512, name="OP1", ... key=jax.random.PRNGKey(0)) op2 = CliffordOperator.random(512, name="OP2", ... key=jax.random.PRNGKey(1))
composed = op1.compose(op2) print(composed.metadata.name) compose(OP1, OP2)
Source code in vsax/operators/clifford.py
random(dim, kind=OperatorKind.GENERAL, name='random_op', key=None)
staticmethod
¶
Create random operator with uniform phase distribution.
Samples phase parameters uniformly from [0, 2π) to create a random operator. Useful for generating basis operators for spatial relations, semantic roles, or other symbolic transformations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dim
|
int
|
Dimensionality of the operator. |
required |
kind
|
OperatorKind
|
Semantic type of the operator (default: GENERAL). |
GENERAL
|
name
|
str
|
Human-readable name for the operator. |
'random_op'
|
key
|
Optional[Array]
|
JAX random key for reproducibility. If None, uses key(0). |
None
|
Returns:
| Type | Description |
|---|---|
CliffordOperator
|
Random CliffordOperator with uniformly distributed phase parameters. |
Example
from vsax.operators import CliffordOperator, OperatorKind import jax
Create reproducible random operator¶
op = CliffordOperator.random( ... dim=512, ... kind=OperatorKind.SPATIAL, ... name="LEFT_OF", ... key=jax.random.PRNGKey(42) ... ) print(op.metadata.name) LEFT_OF
Source code in vsax/operators/clifford.py
AbstractOperator¶
vsax.operators.base.AbstractOperator
¶
Bases: ABC
Abstract base class for all operators.
Operators provide exact, compositional, invertible transformations for hypervectors. They represent "what happens" in a VSA system, while hypervectors represent "what exists".
All concrete operator implementations must inherit from this class and implement the abstract methods: apply(), inverse(), and compose().
Example
from vsax.operators import CliffordOperator import jax
Create operator¶
op = CliffordOperator.random(512, key=jax.random.PRNGKey(0))
Apply to hypervector¶
transformed = op.apply(hypervector)
Invert¶
original = op.inverse().apply(transformed)
Source code in vsax/operators/base.py
Attributes¶
dim
abstractmethod
property
¶
Dimensionality of operator.
Returns:
| Type | Description |
|---|---|
int
|
Integer dimensionality that matches the hypervectors |
int
|
this operator can transform. |
Functions¶
apply(v)
abstractmethod
¶
Apply operator to hypervector.
Transforms the input hypervector according to the operator's transformation rule. The specific transformation depends on the concrete operator implementation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
v
|
AbstractHypervector
|
Hypervector to transform. |
required |
Returns:
| Type | Description |
|---|---|
AbstractHypervector
|
Transformed hypervector of the same type as input. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If input hypervector type is not supported. |
ValueError
|
If dimensions don't match. |
Source code in vsax/operators/base.py
inverse()
abstractmethod
¶
Return exact inverse operator.
The inverse operator undoes the transformation of the original operator. For exact operators:
op.inverse().apply(op.apply(v)) ≈ v
with high precision (similarity > 0.999).
Returns:
| Type | Description |
|---|---|
AbstractOperator
|
Inverse operator that undoes this operator's transformation. |
Source code in vsax/operators/base.py
compose(other)
abstractmethod
¶
Compose with another operator.
Creates a new operator that applies both transformations in sequence:
composed = self.compose(other)
composed.apply(v) ≈ self.apply(other.apply(v))
Composition order follows mathematical convention (self ∘ other).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
AbstractOperator
|
Operator to compose with. |
required |
Returns:
| Type | Description |
|---|---|
AbstractOperator
|
Composed operator representing both transformations. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If other is not compatible operator type. |
ValueError
|
If dimensions don't match. |
Source code in vsax/operators/base.py
OperatorKind¶
vsax.operators.kinds.OperatorKind
¶
Bases: Enum
Semantic types for operators.
Operator kinds provide semantic metadata inspired by Clifford algebra grades. They help categorize operators by their intended use and transformation type.
Attributes:
| Name | Type | Description |
|---|---|---|
RELATION |
Semantic or abstract relations (e.g., graph edges, roles). |
|
TRANSFORM |
Geometric transformations (e.g., rotations, reflections). |
|
LOGICAL |
Logical operations and constraints. |
|
SPATIAL |
Spatial relations (e.g., LEFT_OF, ABOVE, NEAR). |
|
TEMPORAL |
Temporal relations and sequences. |
|
SEMANTIC |
Semantic roles (e.g., AGENT, PATIENT, THEME). |
|
GENERAL |
General-purpose operators without specific semantics. |
Example
from vsax.operators import OperatorKind, CliffordOperator import jax
op = CliffordOperator.random( ... dim=512, ... kind=OperatorKind.SPATIAL, ... name="LEFT_OF", ... key=jax.random.PRNGKey(0) ... ) print(op.metadata.kind) OperatorKind.SPATIAL
Source code in vsax/operators/kinds.py
OperatorMetadata¶
vsax.operators.kinds.OperatorMetadata
dataclass
¶
Optional metadata for operators.
Provides semantic information about an operator, including its kind, name, description, and properties. This metadata helps with debugging, visualization, and understanding operator compositions.
Attributes:
| Name | Type | Description |
|---|---|---|
kind |
OperatorKind
|
Semantic type of the operator. |
name |
str
|
Human-readable name for the operator. |
description |
Optional[str]
|
Optional detailed description of what the operator does. |
invertible |
bool
|
Whether the operator has an exact inverse (default: True). |
commutative |
bool
|
Whether the operator commutes with others (default: False). |
Example
from vsax.operators import OperatorMetadata, OperatorKind
metadata = OperatorMetadata( ... kind=OperatorKind.SPATIAL, ... name="LEFT_OF", ... description="Spatial relation: object A is left of object B", ... invertible=True, ... commutative=False ... ) print(metadata.name) LEFT_OF
Source code in vsax/operators/kinds.py
Usage Examples¶
Spatial Reasoning¶
from vsax import create_fhrr_model, VSAMemory
from vsax.operators import CliffordOperator, OperatorKind
from vsax.similarity import cosine_similarity
import jax
# Setup
model = create_fhrr_model(dim=512)
memory = VSAMemory(model)
memory.add_many(["cup", "plate", "table"])
# Create spatial operators
LEFT_OF = CliffordOperator.random(
512, kind=OperatorKind.SPATIAL, name="LEFT_OF", key=jax.random.PRNGKey(100)
)
RIGHT_OF = LEFT_OF.inverse()
# Encode: "cup LEFT_OF plate"
scene = model.opset.bundle(
memory["cup"].vec,
LEFT_OF.apply(memory["plate"]).vec
)
# Query: What's LEFT_OF plate?
answer = RIGHT_OF.apply(model.rep_cls(scene))
similarity = cosine_similarity(answer.vec, memory["cup"].vec)
print(f"Similarity to 'cup': {similarity:.3f}") # High similarity
Semantic Roles¶
# Create semantic operators
AGENT = CliffordOperator.random(
512, kind=OperatorKind.SEMANTIC, name="AGENT", key=jax.random.PRNGKey(200)
)
PATIENT = CliffordOperator.random(
512, kind=OperatorKind.SEMANTIC, name="PATIENT", key=jax.random.PRNGKey(201)
)
memory.add_many(["dog", "cat", "chase"])
# Encode: "dog chases cat"
sentence = model.opset.bundle(
AGENT.apply(memory["dog"]).vec,
memory["chase"].vec,
PATIENT.apply(memory["cat"]).vec
)
# Query: Who is the AGENT?
who = AGENT.inverse().apply(model.rep_cls(sentence))
similarity = cosine_similarity(who.vec, memory["dog"].vec)
print(f"AGENT is 'dog': {similarity:.3f}") # High similarity
Operator Composition¶
# Compose spatial relations
left_and_up = LEFT_OF.compose(ABOVE)
# Apply composed transformation
transformed = left_and_up.apply(memory["origin"])
# Exact inverse
recovered = left_and_up.inverse().apply(transformed)
similarity = cosine_similarity(recovered.vec, memory["origin"].vec)
print(f"Recovery: {similarity:.6f}") # > 0.999
Properties¶
Exact Inversion¶
CliffordOperator provides exact inversion with similarity > 0.999:
op = CliffordOperator.random(512, key=jax.random.PRNGKey(0))
hv = memory["test"]
transformed = op.apply(hv)
recovered = op.inverse().apply(transformed)
similarity = cosine_similarity(recovered.vec, hv.vec)
assert similarity > 0.999 # Exact recovery
Associativity¶
Composition is associative:
op1 = CliffordOperator.random(512, key=jax.random.PRNGKey(1))
op2 = CliffordOperator.random(512, key=jax.random.PRNGKey(2))
op3 = CliffordOperator.random(512, key=jax.random.PRNGKey(3))
hv = memory["test"]
# (op1 ∘ op2) ∘ op3
left = op1.compose(op2).compose(op3).apply(hv)
# op1 ∘ (op2 ∘ op3)
right = op1.compose(op2.compose(op3)).apply(hv)
similarity = cosine_similarity(left.vec, right.vec)
assert similarity > 0.999 # Associative
Commutativity¶
For phase-based operators, composition is commutative:
# op1 ∘ op2
comp_12 = op1.compose(op2).apply(hv)
# op2 ∘ op1
comp_21 = op2.compose(op1).apply(hv)
similarity = cosine_similarity(comp_12.vec, comp_21.vec)
assert similarity > 0.999 # Commutative
Norm Preservation¶
Operators preserve the unit magnitude of FHRR vectors:
hv = memory["test"]
transformed = op.apply(hv)
# Both have unit magnitude
assert jnp.allclose(jnp.abs(hv.vec), 1.0, atol=1e-5)
assert jnp.allclose(jnp.abs(transformed.vec), 1.0, atol=1e-5)
Type Safety¶
CliffordOperator only works with ComplexHypervector (FHRR):
from vsax.representations import ComplexHypervector, RealHypervector
# Works with ComplexHypervector ✅
complex_hv = memory["test"] # ComplexHypervector from FHRR model
result = op.apply(complex_hv)
# Error with other types ❌
real_hv = RealHypervector(jnp.ones(512))
result = op.apply(real_hv) # TypeError with helpful message
Performance¶
Computational Complexity¶
| Operation | Complexity | JAX-native | GPU-accelerated |
|---|---|---|---|
apply() |
O(dim) | ✅ | ✅ |
inverse() |
O(dim) | ✅ | ✅ |
compose() |
O(dim) | ✅ | ✅ |
Test Coverage¶
- 96% coverage on CliffordOperator module
- 23 comprehensive tests covering all properties
- Properties tested: inversion, composition, associativity, commutativity, type safety
Design Principles¶
JAX-Native¶
All operations use JAX for GPU acceleration:
import jax
# JIT-compile operator application
@jax.jit
def transform(op, hv):
return op.apply(hv)
# GPU-accelerated
result = transform(op, memory["test"])
Immutable¶
Operators are immutable (frozen dataclasses):
op = CliffordOperator.random(512, key=jax.random.PRNGKey(0))
# Cannot modify ❌
# op.params = new_params # Raises FrozenInstanceError
# Create new operator instead ✅
new_op = CliffordOperator(params=new_params)
FHRR-Compatible¶
Operators compile to FHRR's phase algebra:
# Phase-based implementation
# apply(v) = v * exp(i * params)
# Compatible with FHRR circular convolution
bound = model.opset.bind(
op.apply(hv1).vec,
hv2.vec
)
Comparison with Other Approaches¶
VSA Bundling¶
| Aspect | Bundling | CliffordOperator |
|---|---|---|
| Inversion | ~0.6-0.7 similarity | >0.999 similarity |
| Directionality | Lost | Preserved |
| Use case | Symmetric relations | Asymmetric transformations |
| Example | "dog AND cat" | "dog CHASES cat" |
Other VSA Libraries¶
VSAX is the first VSA library to provide: - Clifford-inspired operators with exact inversion - Compositional algebra for transformations - Semantic typing with OperatorKind enum - Full integration with VSA operations
Future Extensions¶
Planned for future releases:
- Pre-defined spatial operators (LEFT_OF, ABOVE, NEAR, etc.)
- Pre-defined semantic operators (AGENT, PATIENT, THEME, etc.)
- Operator learning from data
- Batch operator application with vmap
- Non-commutative operators for sequences
- Visualization tools
Related Documentation¶
- User Guide: Operators Guide
- Tutorial: Tutorial 10: Clifford Operators
- Design Spec: VSAX Design Specification
References¶
Clifford Algebra: - Hestenes & Sobczyk (1984) - "Clifford Algebra to Geometric Calculus" - Dorst et al. (2007) - "Geometric Algebra for Computer Science"
VSA Theory: - Kanerva (2009) - "Hyperdimensional Computing" - Plate (1995) - "Holographic Reduced Representations" - Gayler (2004) - "Vector Symbolic Architectures answer Jackendoff's challenges"