def __init__( self, dimensions, strict=True, max_similarity=0.1, pointer_gen=None, name=None, algebra=None): if algebra is None: algebra = HrrAlgebra() self.algebra = algebra if not is_integer(dimensions) or dimensions < 1: raise ValidationError("dimensions must be a positive integer", attr='dimensions', obj=self) if pointer_gen is None: pointer_gen = UnitLengthVectors(dimensions) elif isinstance(pointer_gen, np.random.RandomState): pointer_gen = UnitLengthVectors(dimensions, pointer_gen) if not is_iterable(pointer_gen) or is_string(pointer_gen): raise ValidationError( "pointer_gen must be iterable or RandomState", attr='pointer_gen', obj=self) self.dimensions = dimensions self.strict = strict self.max_similarity = max_similarity self._key2idx = {} self._keys = [] self._vectors = np.zeros((0, dimensions), dtype=float) self.pointer_gen = pointer_gen self.name = name
def test_get_swapping_matrix(rng): gen = UnitLengthVectors(64, rng) a = SemanticPointer(next(gen), algebra=VtbAlgebra()).v b = SemanticPointer(next(gen), algebra=VtbAlgebra()).v m = VtbAlgebra().get_swapping_matrix(64) assert np.allclose(VtbAlgebra().bind(a, b), np.dot(m, VtbAlgebra().bind(b, a)))
def test_dot(rng): gen = UnitLengthVectors(50, rng) a = SemanticPointer(next(gen)) * 1.1 b = SemanticPointer(next(gen)) * (-1.5) assert np.allclose(a.dot(b), np.dot(a.v, b.v)) assert np.allclose(a.dot(b.v), np.dot(a.v, b.v)) assert np.allclose(a.dot(list(b.v)), np.dot(a.v, b.v)) assert np.allclose(a.dot(tuple(b.v)), np.dot(a.v, b.v))
def test_compare(rng): gen = UnitLengthVectors(50, rng) a = SemanticPointer(next(gen)) * 10 b = SemanticPointer(next(gen)) * 0.1 assert a.compare(a) > 0.99 assert a.compare(b) < 0.2 assert np.allclose(a.compare(b), a.dot(b) / (a.length() * b.length()))
def test_make_unitary(algebra, d, rng): a = next(UnitLengthVectors(d, rng)) b = algebra.make_unitary(a) for i in range(3): assert np.allclose(1, np.linalg.norm(a)) assert np.allclose(1, np.linalg.norm(b)) a = algebra.bind(a, b) assert np.allclose(1, np.linalg.norm(a))
def test_get_binding_matrix(algebra, rng): gen = UnitLengthVectors(16, rng) a = next(gen) b = next(gen) m = algebra.get_binding_matrix(b) assert np.allclose(algebra.bind(a, b), np.dot(m, a))
def test_absorbing_element(algebra, rng): a = next(UnitLengthVectors(16, rng)) try: p = algebra.absorbing_element(16) r = algebra.bind(a, p) r /= np.linalg.norm(r) assert np.allclose(p, r) or np.allclose(p, -r) except NotImplementedError: pass
def test_binding_and_invert(algebra, d, rng): gen = UnitLengthVectors(d, rng) a = next(gen) b = next(gen) bound = algebra.bind(a, b) r = algebra.bind(bound, algebra.invert(b)) for v in (a, b): assert np.dot(v, bound / np.linalg.norm(b)) < 0.7 assert np.dot(a, r / np.linalg.norm(r)) > 0.6
def test_copy(): a = SemanticPointer(next(UnitLengthVectors(5))) b = a.copy() assert a is not b assert a.v is not b.v assert np.allclose(a.v, b.v) assert a.algebra is b.algebra assert a.vocab is b.vocab assert a.name is b.name
def test_binding_matrix(algebra, rng): gen = UnitLengthVectors(64, rng) a = SemanticPointer(next(gen), algebra=algebra) b = SemanticPointer(next(gen), algebra=algebra) m = b.get_binding_matrix() m_swapped = a.get_binding_matrix(swap_inputs=True) assert np.allclose((a * b).v, np.dot(m, a.v)) assert np.allclose((a * b).v, np.dot(m_swapped, b.v))
def test_make_unitary(algebra, d, rng): if not algebra.is_valid_dimensionality(d): return a = SemanticPointer(next(UnitLengthVectors(d, rng)), algebra=algebra) b = a.unitary() assert a is not b assert np.allclose(1, b.length()) assert np.allclose(1, (b * b).length()) assert np.allclose(1, (b * b * b).length())
def test_superpose(algebra, rng): gen = UnitLengthVectors(16, rng) a = next(gen) b = next(gen) # Orthogonalize b -= np.dot(a, b) * a b /= np.linalg.norm(b) r = algebra.superpose(a, b) for v in (a, b): assert np.dot(v, r / np.linalg.norm(r)) > 0.6
def test_binding_and_invert(algebra, d, rng): dissimilarity_passed = 0 unbinding_passed = 0 for i in range(10): gen = UnitLengthVectors(d, rng) a = next(gen) b = next(gen) bound = algebra.bind(a, b) r = algebra.bind(bound, algebra.invert(b)) for v in (a, b): dissimilarity_passed += np.dot(v, bound / np.linalg.norm(b)) < 0.7 unbinding_passed += np.dot(a, r / np.linalg.norm(r)) > 0.6 assert dissimilarity_passed >= 2 * 8 assert unbinding_passed >= 8
def test_add_sub(algebra, rng): gen = UnitLengthVectors(10, rng) a = SemanticPointer(next(gen), algebra=algebra) b = SemanticPointer(next(gen), algebra=algebra) c = a.copy() d = b.copy() c += b d -= -a assert np.allclose((a + b).v, algebra.superpose(a.v, b.v)) assert np.allclose((a + b).v, c.v) assert np.allclose((a + b).v, d.v) assert np.allclose((a + b).v, (a - (-b)).v)
def test_multiply(): a = SemanticPointer(next(UnitLengthVectors(50))) assert np.allclose((a * 5).v, a.v * 5) assert np.allclose((5 * a).v, a.v * 5) assert np.allclose((a * 5.7).v, a.v * 5.7) assert np.allclose((5.7 * a).v, a.v * 5.7) assert np.allclose((0 * a).v, np.zeros(50)) assert np.allclose((1 * a).v, a.v) with pytest.raises(Exception): a * None with pytest.raises(Exception): a * 'string' with pytest.raises(TypeError): a * np.array([1, 2])
def test_add_output(Simulator, seed, rng, plt): d = 8 pointer = next(UnitLengthVectors(d, rng)) with nengo.Network(seed=seed) as model: ea = IdentityEnsembleArray(15, d, 4) input_node = nengo.Node(pointer) nengo.Connection(input_node, ea.input) out = ea.add_output('const', lambda x: -x) assert ea.const is out p = nengo.Probe(out, synapse=0.01) with Simulator(model) as sim: sim.run(0.3) plt.plot(sim.trange(), np.dot(sim.data[p], -pointer)) assert_sp_close(sim.trange(), sim.data[p], SemanticPointer(-pointer), skip=0.2, atol=0.3)
def test_binding_and_inversion(algebra, d, rng): if not algebra.is_valid_dimensionality(d): return gen = UnitLengthVectors(d, rng) a = SemanticPointer(next(gen), algebra=algebra) b = SemanticPointer(next(gen), algebra=algebra) identity = Identity(d, algebra=algebra) c = a.copy() c *= b conv_ans = algebra.bind(a.v, b.v) assert np.allclose((a * b).v, conv_ans) assert np.allclose(a.bind(b).v, conv_ans) assert np.allclose(c.v, conv_ans) assert np.allclose((a * identity).v, a.v) assert (a * b * ~b).compare(a) > 0.6
def get_or_create(self, dimensions): """Gets or creates a vocabulary of given dimensionality. If the mapping already maps the given dimensionality to a vocabulary, it will be returned. Otherwise, a new vocabulary will be created, added to the mapping, and returned. Parameters ---------- dimensions : int Dimensionality of vocabulary to return. Returns ------- Vocabulary Vocabulary of given dimensionality. """ if dimensions not in self._vocabs: self._vocabs[dimensions] = Vocabulary( dimensions, strict=False, pointer_gen=UnitLengthVectors(dimensions, self.rng)) return self._vocabs[dimensions]
def test_neuron_connections(Simulator, seed, rng): d = 8 pointer = next(UnitLengthVectors(d, rng)) with nengo.Network(seed=seed) as model: ea = IdentityEnsembleArray(15, d, 4) input_node = nengo.Node(pointer) nengo.Connection(input_node, ea.input) bias = nengo.Node(1) neuron_in = ea.add_neuron_input() assert ea.neuron_input is neuron_in nengo.Connection( bias, neuron_in, transform=-3. * np.ones((neuron_in.size_in, 1))) neuron_out = ea.add_neuron_output() assert ea.neuron_output is neuron_out p = nengo.Probe(neuron_out) with Simulator(model) as sim: sim.run(0.3) assert_almost_equal(sim.data[p][sim.trange() > 0.1], 0.)
def test_add_output_multiple_fn(Simulator, seed, rng, plt): d = 8 pointer = next(UnitLengthVectors(d, rng)) with nengo.Network(seed=seed) as model: ea = IdentityEnsembleArray(15, d, 4) input_node = nengo.Node(pointer) nengo.Connection(input_node, ea.input) out = ea.add_output("const", (lambda x: -x, lambda x: 0.5 * x, lambda x: x)) assert ea.const is out p = nengo.Probe(out, synapse=0.01) with Simulator(model) as sim: sim.run(0.3) expected = np.array(pointer) expected[0] *= -1.0 expected[1:4] *= 0.5 plt.plot(sim.trange(), np.dot(sim.data[p], expected)) assert_sp_close( sim.trange(), sim.data[p], SemanticPointer(expected), skip=0.2, atol=0.3 )
def test_dot_matmul(rng): gen = UnitLengthVectors(50, rng) a = SemanticPointer(next(gen)) * 1.1 b = SemanticPointer(next(gen)) * (-1.5) assert np.allclose(eval('a @ b'), np.dot(a.v, b.v))
def test_length(rng): a = SemanticPointer([1, 1]) assert np.allclose(a.length(), np.sqrt(2)) a = SemanticPointer(next(UnitLengthVectors(10, rng))) * 1.2 assert np.allclose(a.length(), 1.2)
def test_incompatible_algebra(op): gen = UnitLengthVectors(32) a = SemanticPointer(next(gen), algebra=AbstractAlgebra()) # noqa: F841 b = SemanticPointer(next(gen), algebra=AbstractAlgebra()) # noqa: F841 with pytest.raises(TypeError): eval('a' + op + 'b')
def test_fixed_pointer_network_creation(rng): with spa.Network(): A = SemanticPointer(next(UnitLengthVectors(16))) node = A.construct() assert_equal(node.output, A.v)
def test_none_vocab_is_always_compatible(op): gen = UnitLengthVectors(50) v = Vocabulary(50) a = SemanticPointer(next(gen), vocab=v) # noqa: F841 b = SemanticPointer(next(gen), vocab=None) # noqa: F841 eval(op) # no assertion, just checking that no exception is raised
def test_ops_check_vocab_compatibility(op): gen = UnitLengthVectors(50) a = SemanticPointer(next(gen), vocab=Vocabulary(50)) # noqa: F841 b = SemanticPointer(next(gen), vocab=Vocabulary(50)) # noqa: F841 with pytest.raises(SpaTypeError): eval(op)
def test_ops_preserve_vocab(op): v = Vocabulary(50) a = SemanticPointer(next(UnitLengthVectors(50)), vocab=v) # noqa: F841 x = eval(op) assert x.vocab is v
def test_mse(): gen = UnitLengthVectors(50) a = SemanticPointer(next(gen)) b = SemanticPointer(next(gen)) assert np.allclose(((a - b).length()**2) / 50, a.mse(b))
def test_distance(rng): gen = UnitLengthVectors(50, rng) a = SemanticPointer(next(gen)) b = SemanticPointer(next(gen)) assert a.distance(a) < 1e-5 assert a.distance(b) > 0.7
def test_len(): a = SemanticPointer(next(UnitLengthVectors(5))) assert len(a) == 5 a = SemanticPointer(list(range(10))) assert len(a) == 10