BinaryOperations¶
XOR and majority voting operations for binary hypervectors.
vsax.ops.BinaryOperations
¶
Bases: AbstractOpSet
Binary VSA operations for bipolar {-1, +1} vectors.
Binary VSA uses: - Binding: XOR (element-wise multiplication in bipolar representation) - Bundling: Majority vote - Inverse: Self-inverse (XOR is its own inverse)
This algebra is particularly efficient for hardware implementation and provides exact unbinding (unlike MAP).
Note: Operations assume bipolar {-1, +1} encoding. For {0, 1} encoding, convert to bipolar first.
Example
import jax import jax.numpy as jnp
ops = BinaryOperations() key = jax.random.PRNGKey(0) a = jax.random.choice(key, jnp.array([-1, 1]), shape=(1024,)) b = jax.random.choice(key, jnp.array([-1, 1]), shape=(1024,))
bound = ops.bind(a, b) assert jnp.all(jnp.isin(bound, jnp.array([-1, 1])))
Source code in vsax/ops/binary.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 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 | |
Functions¶
bind(a, b)
¶
Bind two hypervectors using XOR (element-wise multiplication).
In bipolar {-1, +1} representation, XOR is implemented as element-wise multiplication: - (+1) XOR (+1) = +1 (same) - (+1) XOR (-1) = -1 (different) - (-1) XOR (+1) = -1 (different) - (-1) XOR (-1) = +1 (same)
This operation is: - Commutative: bind(a, b) = bind(b, a) - Associative: bind(a, bind(b, c)) = bind(bind(a, b), c) - Self-inverse: bind(bind(a, b), b) = a (exact unbinding)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
ndarray
|
First hypervector as JAX array (bipolar values). |
required |
b
|
ndarray
|
Second hypervector as JAX array (bipolar values). |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Bound hypervector as JAX array (bipolar values). |
Example
import jax.numpy as jnp ops = BinaryOperations() a = jnp.array([1, -1, 1, -1]) b = jnp.array([1, 1, -1, -1]) result = ops.bind(a, b) expected = jnp.array([1, -1, -1, 1]) assert jnp.array_equal(result, expected)
Source code in vsax/ops/binary.py
bundle(*vecs)
¶
Bundle multiple hypervectors using majority vote.
Each element in the bundled vector is determined by the majority value at that position across all input vectors.
For even counts, ties are broken by the sign of the sum.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*vecs
|
ndarray
|
Variable number of hypervectors as JAX arrays (bipolar values). |
()
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Bundled hypervector as JAX array (bipolar values). |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no vectors are provided. |
Example
import jax.numpy as jnp ops = BinaryOperations() a = jnp.array([1, -1, 1, -1]) b = jnp.array([1, 1, -1, -1]) c = jnp.array([1, 1, 1, 1]) result = ops.bundle(a, b, c) expected = jnp.array([1, 1, 1, -1]) # Majority at each position assert jnp.array_equal(result, expected)
Source code in vsax/ops/binary.py
inverse(a)
¶
Compute the inverse for unbinding.
For binary XOR, the inverse is the vector itself (self-inverse property). This means: bind(bind(a, b), b) = a (exact unbinding).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
ndarray
|
Hypervector as JAX array (bipolar values). |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Inverse hypervector (same as input for XOR). |
Example
import jax.numpy as jnp ops = BinaryOperations() a = jnp.array([1, -1, 1, -1]) inv_a = ops.inverse(a) assert jnp.array_equal(inv_a, a)
Source code in vsax/ops/binary.py
unbind(a, b)
¶
Unbind b from a using XOR (self-inverse property).
Since XOR is self-inverse in binary VSA, unbinding is identical to binding: unbind(a, b) = bind(a, b) = a XOR b
This provides exact unbinding: if c = bind(x, y), then unbind(c, y) = x.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
ndarray
|
Bound hypervector as JAX array (bipolar values). |
required |
b
|
ndarray
|
Hypervector to unbind as JAX array (bipolar values). |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Recovered hypervector as JAX array (exact recovery for Binary VSA). |
Example
import jax.numpy as jnp ops = BinaryOperations() x = jnp.array([1, -1, 1, -1]) y = jnp.array([1, 1, -1, -1])
Bind and unbind¶
bound = ops.bind(x, y) recovered = ops.unbind(bound, y)
Exact recovery¶
assert jnp.array_equal(recovered, x)
Source code in vsax/ops/binary.py
permute(a, shift)
¶
Permute a hypervector by circular rotation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
ndarray
|
Hypervector as JAX array (bipolar values). |
required |
shift
|
int
|
Number of positions to rotate (positive = right, negative = left). |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Permuted hypervector as JAX array. |
Example
import jax.numpy as jnp ops = BinaryOperations() a = jnp.array([1, -1, 1, -1]) rotated = ops.permute(a, 1) expected = jnp.array([-1, 1, -1, 1]) assert jnp.array_equal(rotated, expected)