Step 1

Define the model


In [1]:
import nengo
import nengo.spa as spa

dimensions = 32
model = spa.SPA()
with model:
     model.state1 = spa.Buffer(dimensions=dimensions)                            
     model.state2 = spa.Buffer(dimensions=dimensions)                            
     model.output = spa.Buffer(dimensions=dimensions)                            
                                                                                 
     model.bg = spa.BasalGanglia(spa.Actions('0.5 --> output=state1*state2'))    
     model.thal = spa.Thalamus(model.bg)


/home/tcstewar/github/nengo/nengo/base.py:59: SyntaxWarning: Creating new attribute 'vocab' on '<Node "input">'. Did you mean to change an existing attribute?
  SyntaxWarning)
/home/tcstewar/github/nengo/nengo/base.py:59: SyntaxWarning: Creating new attribute 'vocab' on '<Node "output">'. Did you mean to change an existing attribute?
  SyntaxWarning)

Step 2

Use the default backend to build the model. This uses the standard approach for creating encoders, defining neuron models, and computing decoders


In [2]:
sim = nengo.Simulator(model)

Step 3

Extract the data from Ensembles


In [3]:
for ens in model.all_ensembles:
    # data defined by the model is directly accessed
    n_neurons = ens.n_neurons
    dimensions = ens.dimensions
    # data generated by the default backend is accessed via sim.model.params
    encoder = sim.model.params[ens].encoders
    bias = sim.model.params[ens].bias
    gain = sim.model.params[ens].gain

Step 4

Find all the decoders for each Ensemble. An Ensemble will have multiple Connections coming out of it, but is likely to share the same decoder across many of them.


In [4]:
decoders = {}
for ens in model.all_ensembles:
    decoders[ens] = {}
for connection in model.all_connections:
    if isinstance(connection.pre_obj, nengo.Ensemble):
        ens = connection.pre_obj
        function = connection.function
        if function not in decoders[ens]:
            decoders[ens][function] = sim.model.params[connection].decoders

Step 5 (optional)

Remove internal Nodes from the network. When creating models, we often introduce Nodes that do nothing other than act as conventient shortcuts for referring to collections of ensembles. So we might have a Node that acts like the output from 10 ensembles, allowing us to just connect to that Node rather than making a separate connection from each Ensemble. These Nodes are just a programming convenience, and are generally compiled out by most backends.


In [5]:
objects = model.all_ensembles + model.all_nodes
connections = model.all_connections

import nengo.utils.builder
objects, connections = nengo.utils.builder.remove_passthrough_nodes(objects, connections)

Step 6

Extract data from Nodes. These are the inputs and outputs from the system


In [6]:
for node in objects:
    if isinstance(node, nengo.Node):
        size_in = node.size_in    # input to the node (output from the model)
        size_out = node.size_out  # output from the node (input to the model)
        output = node.output      # the actual output.  May be callable() or a constant

Step 7

Extract data from Connections


In [7]:
for connection in connections:
    pre = connection.pre_obj      # the Ensemble or Node that is the source for this connection
    post = connection.post_obj    # the Ensemble or Node that is the target for this connection
    synapse = connection.synapse  # filter
    function = connection.function         # the function to compute
    if isinstance(pre, nengo.Ensemble):
        decoder = decoders[pre][function]  # the decoder for that function
        
    transform = nengo.utils.builder.full_transform(connection, allow_scalars=False)    # the transform
    
    if isinstance(post, nengo.ensemble.Neurons):
        # this is a rare case where we are bypassing the encoder
        # In general, this allows for specifying arbitary networks.
        # In Spaun, we only ever use this in cases where the weight matrix is all -1
        #  so we could actually replace it with adding a new dimension to the encoder
        #  that is also all -1.
        bypass_encoders = True
        post = post.ensemble