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 ssp_weighted_plane_basis(K, W): # The above but plane waves aren't just all summed. Instead there's a weighted sum - can get distortions in patterns # or make place cells more refined this way d = K.shape[0] FX = np.ones((d * 2 + 1, ), dtype="complex") FX[0:d] = W * np.exp(1.j * K[:, 0]) FX[-d:] = np.flip(np.conj(FX[0:d])) FX = np.fft.ifftshift(FX) FY = np.ones((d * 2 + 1, ), dtype="complex") FY[0:d] = W * np.exp(1.j * K[:, 1]) FY[-d:] = np.flip(np.conj(FY[0:d])) FY = np.fft.ifftshift(FY) X = SemanticPointer(data=np.fft.ifft(FX), algebra=HrrAlgebra()) Y = SemanticPointer(data=np.fft.ifft(FY), algebra=HrrAlgebra()) return X, Y
def ssp(X, Y, x, y, alg=HrrAlgebra()): # Return a ssp if ((type(X) == SemanticPointer) & (type(Y) == SemanticPointer)): return (X**x) * (Y**y) else: return (SemanticPointer(data=X, algebra=alg)**x) * (SemanticPointer( data=Y, algebra=alg)**y)
def ssp_plane_basis(K): # Create the bases vectors X,Y as described in the paper with the wavevectors # (k_i = (u_i,v_i)) given in a matrix K. To get hexganal patterns use 3 K vectors 120 degs apart # To get mulit-scales/orientation, give many such sets of 3 K vectors # K is _ by 2 d = K.shape[0] FX = np.ones((d * 2 + 1, ), dtype="complex") FX[0:d] = np.exp(1.j * K[:, 0]) FX[-d:] = np.flip(np.conj(FX[0:d])) FX = np.fft.ifftshift(FX) FY = np.ones((d * 2 + 1, ), dtype="complex") FY[0:d] = np.exp(1.j * K[:, 1]) FY[-d:] = np.flip(np.conj(FY[0:d])) FY = np.fft.ifftshift(FY) X = SemanticPointer(data=np.fft.ifft(FX), algebra=HrrAlgebra()) Y = SemanticPointer(data=np.fft.ifft(FY), algebra=HrrAlgebra()) return X, Y
def test_circularconv_transforms(invert_a, invert_b, rng): """Test the circular convolution transforms""" dims = 100 x = a = rng.randn(dims) y = b = rng.randn(dims) inv = HrrAlgebra().get_inversion_matrix(dims) if invert_a: a = np.dot(inv, a) if invert_b: b = np.dot(inv, b) z0 = HrrAlgebra().bind(a, b) tr_a = transform_in(dims, "A", invert_a) tr_b = transform_in(dims, "B", invert_b) tr_out = transform_out(dims) XY = np.dot(tr_a, x) * np.dot(tr_b, y) z1 = np.dot(tr_out, XY) assert np.allclose(z0, z1)
def _get_algebra(cls, vocab, algebra): if algebra is None: if vocab is None: algebra = HrrAlgebra() else: algebra = vocab.algebra elif vocab is not None and vocab.algebra is not algebra: raise ValueError( "vocab and algebra argument are mutually exclusive") return algebra
def __init__(self, X, Y, alg=HrrAlgebra(), radius=1): super().__init__() self.radius = radius if ((type(X) == SemanticPointer) & (type(Y) == SemanticPointer)): self.X = X.v self.Y = Y.v self.alg = X.algebra else: self.X = X self.Y = Y self.alg = alg
def __init__(self, env, d, X=None, Y=None): super().__init__(env) self.alg = HrrAlgebra() img_shape = env.observation_space['image'].shape self.img_shape = img_shape self.d = d self.X = X or make_good_unitary(d) self.Y = Y or make_good_unitary(d) colors = [x.upper() for x in list(COLOR_TO_IDX.keys())] vocab = spa.Vocabulary(d) vocab.add('NULL', np.zeros(d)) vocab.populate(';'.join(colors)) objects = [x.upper() for x in list(OBJECT_TO_IDX.keys())] vocab.populate(';'.join(objects)) #states = [x.upper() for x in list(STATE_TO_IDX.keys())] #vocab.populate(';'.join(states)) vocab.add('OPEN', self.alg.identity_element(d)) vocab.populate('CLOSED;LOCKED') self.vocab = vocab obs_shape = (d, ) self.observation_space.spaces["image"] = SSPSpace( basis=[self.X.v, self.Y.v], bounds=[[-1, 1], [-1, 1]], shape=(obs_shape[0], )) #xi = np.arange(0.5,img_shape[0],1) xi = np.arange(img_shape[0] - 0.5, 0, -1) yi = np.arange(img_shape[1] // 2, -img_shape[1] // 2, -1) xx, yy = np.meshgrid(xi, yi) basis = np.vstack([self.X.v, self.Y.v]).T positions = np.vstack([xx.reshape(-1), yy.reshape(-1)]).T S_ids = ssp_vectorized(basis, positions).T.real S_ids = S_ids.reshape(len(xi), len(yi), d) #.swapaxes(0,1) self.S_list = S_ids
class TestConfig(object): """Parameters affecting all Nengo SPA testes. These are essentially global variables used by py.test to modify aspects of the Nengo SPA tests. We collect them in this class to provide a mini namespace and to avoid using the ``global`` keyword. The values below are defaults. The functions in the remainder of this module modify these values accordingly. """ algebras = [HrrAlgebra(), VtbAlgebra()]
def __init__(self, basis, bounds, shape=None, dtype=complex, alg=HrrAlgebra()): self.nbasis = len(basis) self.basis = basis self.dim = len(basis[0]) self.bounds = bounds self.alg = alg self.seed()
def _get_algebra(cls, vocab, algebra): if algebra is None: if vocab is None: algebra = HrrAlgebra() else: algebra = vocab.algebra elif vocab is not None and vocab.algebra is not algebra: raise ValueError( "vocab and algebra argument are mutually exclusive") if not isinstance(algebra, AbstractAlgebra): raise ValidationError( "'algebra' must be an instance of AbstractAlgebra", "algebra", algebra) return algebra
def test_neural_accuracy(Simulator, seed, rng, dims, neurons_per_product=128): a = rng.normal(scale=np.sqrt(1.0 / dims), size=dims) b = rng.normal(scale=np.sqrt(1.0 / dims), size=dims) a /= np.linalg.norm(a) b /= np.linalg.norm(b) result = HrrAlgebra().bind(a, b) model = nengo.Network(label="circular conv", seed=seed) model.config[nengo.Ensemble].neuron_type = nengo.LIFRate() with model: input_a = nengo.Node(a) input_b = nengo.Node(b) cconv = nengo_spa.networks.CircularConvolution(neurons_per_product, dimensions=dims) nengo.Connection(input_a, cconv.input_a, synapse=None) nengo.Connection(input_b, cconv.input_b, synapse=None) res_p = nengo.Probe(cconv.output) with Simulator(model) as sim: sim.run(0.01) error = rms(result - sim.data[res_p][-1]) assert error < 0.2
def test_input_magnitude(Simulator, seed, rng, dims=16, magnitude=10): """Test to make sure the magnitude scaling works. Builds two different CircularConvolution networks, one with the correct magnitude and one with 1.0 as the input_magnitude. """ neurons_per_product = 128 a = rng.normal(scale=np.sqrt(1.0 / dims), size=dims) * magnitude b = rng.normal(scale=np.sqrt(1.0 / dims), size=dims) * magnitude result = HrrAlgebra().bind(a, b) model = nengo.Network(label="circular conv", seed=seed) model.config[nengo.Ensemble].neuron_type = nengo.LIFRate() with model: input_a = nengo.Node(a) input_b = nengo.Node(b) cconv = nengo_spa.networks.CircularConvolution( neurons_per_product, dimensions=dims, input_magnitude=magnitude) nengo.Connection(input_a, cconv.input_a, synapse=None) nengo.Connection(input_b, cconv.input_b, synapse=None) res_p = nengo.Probe(cconv.output) cconv_bad = nengo_spa.networks.CircularConvolution( neurons_per_product, dimensions=dims, input_magnitude=1) # incorrect magnitude nengo.Connection(input_a, cconv_bad.input_a, synapse=None) nengo.Connection(input_b, cconv_bad.input_b, synapse=None) res_p_bad = nengo.Probe(cconv_bad.output) with Simulator(model) as sim: sim.run(0.01) error = rms(result - sim.data[res_p][-1]) / (magnitude**2) error_bad = rms(result - sim.data[res_p_bad][-1]) / (magnitude**2) assert error < 0.2 assert error_bad > 0.1
def test_invalid_algebra(): gen = UnitLengthVectors(32) with pytest.raises(ValidationError, match="AbstractAlgebra"): SemanticPointer(next(gen), algebra=HrrAlgebra) SemanticPointer(next(gen), algebra=HrrAlgebra())
class SSPWrapper(gym.core.ObservationWrapper): def __init__(self, env, d, X=None, Y=None): super().__init__(env) self.alg = HrrAlgebra() img_shape = env.observation_space['image'].shape self.img_shape = img_shape self.d = d self.X = X or make_good_unitary(d) self.Y = Y or make_good_unitary(d) colors = [x.upper() for x in list(COLOR_TO_IDX.keys())] vocab = spa.Vocabulary(d) vocab.add('NULL', np.zeros(d)) vocab.populate(';'.join(colors)) objects = [x.upper() for x in list(OBJECT_TO_IDX.keys())] vocab.populate(';'.join(objects)) #states = [x.upper() for x in list(STATE_TO_IDX.keys())] #vocab.populate(';'.join(states)) vocab.add('OPEN', self.alg.identity_element(d)) vocab.populate('CLOSED;LOCKED') self.vocab = vocab obs_shape = (d, ) self.observation_space.spaces["image"] = SSPSpace( basis=[self.X.v, self.Y.v], bounds=[[-1, 1], [-1, 1]], shape=(obs_shape[0], )) #xi = np.arange(0.5,img_shape[0],1) xi = np.arange(img_shape[0] - 0.5, 0, -1) yi = np.arange(img_shape[1] // 2, -img_shape[1] // 2, -1) xx, yy = np.meshgrid(xi, yi) basis = np.vstack([self.X.v, self.Y.v]).T positions = np.vstack([xx.reshape(-1), yy.reshape(-1)]).T S_ids = ssp_vectorized(basis, positions).T.real S_ids = S_ids.reshape(len(xi), len(yi), d) #.swapaxes(0,1) self.S_list = S_ids def observation(self, obs): img = obs['image'] M = spa.SemanticPointer(data=np.zeros(self.d)) for i in range(img.shape[0]): for j in range(img.shape[1]): obj = img[i, j, 0] color = img[i, j, 1] state = img[i, j, 2] if obj not in [0, 1]: S = spa.SemanticPointer(data=self.S_list[i, j, :]) M = M + (S * self.vocab[IDX_TO_OBJECT[obj].upper()] * self.vocab[IDX_TO_COLOR[color].upper()] * self.vocab[IDX_TO_STATE[state].upper()]) #M = M.normalized() return {'mission': obs['mission'], 'image': M.v}
def test_is_singleton(): assert HrrAlgebra() is HrrAlgebra()