Source code for nengo_spa.modules.state

import nengo
from nengo.exceptions import ValidationError
from nengo.networks.ensemblearray import EnsembleArray
from nengo.params import BoolParam, Default, IntParam, NumberParam

from nengo_spa.network import Network
from nengo_spa.networks import IdentityEnsembleArray
from nengo_spa.vocabulary import VocabularyOrDimParam


[docs]class State(Network): """Represents a single vector, with optional memory. This is a minimal SPA network, useful for passing data along (for example, visual input). Parameters ---------- vocab : Vocabulary or int The vocabulary to use to interpret the vector. If an integer is given, the default vocabulary of that dimensionality will be used. subdimensions : int, optional (Default: 16) The dimension of the individual ensembles making up the vector. Must divide *dimensions* evenly. The number of sub-ensembles will be ``dimensions // subdimensions``. neurons_per_dimension : int, optional (Default: 50) Number of neurons per dimension. Each ensemble will have ``neurons_per_dimension * subdimensions`` neurons, for a total of ``neurons_per_dimension * dimensions`` neurons. feedback : float, optional (Default: 0.0) Gain of feedback connection. Set to 1.0 for perfect memory, or 0.0 for no memory. Values in between will create a decaying memory. represent_cc_identity : bool, optional Whether to use optimizations to better represent the circular convolution identity vector. If activated, the `.IdentityEnsembleArray` will be used internally, otherwise a normal `nengo.networks.EnsembleArray` split up regularly according to *subdimensions*. feedback_synapse : float, optional (Default: 0.1) The synapse on the feedback connection. **kwargs : dict Keyword arguments passed through to `nengo_spa.Network`. Attributes ---------- input : nengo.Node Input. output : nengo.Node Output. """ vocab = VocabularyOrDimParam("vocab", default=None, readonly=True) subdimensions = IntParam("subdimensions", default=16, low=1, readonly=True) neurons_per_dimension = IntParam( "neurons_per_dimension", default=50, low=1, readonly=True ) feedback = NumberParam("feedback", default=0.0, readonly=True) feedback_synapse = NumberParam("feedback_synapse", default=0.1, readonly=True) represent_cc_identity = BoolParam( "represent_cc_identity", default=True, readonly=True ) def __init__( self, vocab=Default, subdimensions=Default, neurons_per_dimension=Default, feedback=Default, represent_cc_identity=Default, feedback_synapse=Default, **kwargs, ): super(State, self).__init__(**kwargs) self.vocab = vocab self.subdimensions = subdimensions self.neurons_per_dimension = neurons_per_dimension self.feedback = feedback self.feedback_synapse = feedback_synapse self.represent_cc_identity = represent_cc_identity dimensions = self.vocab.dimensions if dimensions % self.subdimensions != 0: raise ValidationError( f"Dimensions ({dimensions}) must be divisible by " f"subdimensions ({self.subdimensions})", attr="dimensions", obj=self, ) with self: if self.represent_cc_identity: self.state_ensembles = IdentityEnsembleArray( self.neurons_per_dimension, dimensions, self.subdimensions, label="state", ) else: self.state_ensembles = EnsembleArray( self.neurons_per_dimension * self.subdimensions, dimensions // self.subdimensions, ens_dimensions=self.subdimensions, eval_points=nengo.dists.CosineSimilarity(dimensions + 2), intercepts=nengo.dists.CosineSimilarity(dimensions + 2), label="state", ) if self.feedback is not None and self.feedback != 0.0: nengo.Connection( self.state_ensembles.output, self.state_ensembles.input, transform=self.feedback, synapse=self.feedback_synapse, ) self.input = self.state_ensembles.input self.output = self.state_ensembles.output self.declare_input(self.input, self.vocab) self.declare_output(self.output, self.vocab)