Sequence stepping

#1

How about populating this part of the forum with a few toy circuits? :wink:

Here’s a simple thing that does something nifty: a BG is used to step through a sequence of items but rather than the model repeatedly running through the sequence by itself, the stepping is controlled by the user.

The model steps whenever the “switch” state is set to “On”. Since that cannot be set via the UI directly, a node is used (“inp”) whose value is sent through a change detector (by computing the derivative of inp). So every time the user moves the slider up or down, a brief “On” pulse appears in switch, which triggers the BG rules and the stepping.

The other nice thing about this model (which was Terry’s idea) is the use of a cleanup memory connected bidirectionally with the stepper to stabilise the content of the stepper. That idea in itself can probably find a few uses in other cases when a simple feedback connection on the spa.State is not actually what’s desired.

To run this particular example, “start” needs to be set to “A” in the GUI and then cleared again once the stepper shows the A. Flicking the slider from inp up and down should step reasonably reliably. Removing the deriv2 population (and adjusting the time constants on the derivative-computing connections a bit) would make the stepper react to changes in one direction only.

Anyway, just a toy circuit :slight_smile:

import nengo
import nengo.spa as spa
import numpy as np

D = 32  

model = spa.SPA()

vocab = spa.Vocabulary(D)
vocab2 = spa.Vocabulary(D)

with model:
    
    vocab.parse("ON")
    vocab2.parse("A+B+C+D+E")

    inp = nengo.Node([0])
    deriv = nengo.Ensemble(n_neurons= 200, dimensions = 1)
    deriv2 = nengo.Ensemble(n_neurons= 200, dimensions = 1)
    
    model.start = spa.State(D)
    model.switch = spa.State(D, vocab=vocab)
    model.stepper = spa.State(D, vocab=vocab2)
    model.cleanup = spa.AssociativeMemory(input_vocab=vocab2, wta_output=True)

    
    nengo.Connection(inp, deriv)
    nengo.Connection(inp, deriv, transform=-1, synapse=0.05)

    nengo.Connection(deriv, deriv2, function= lambda x: np.square(x))
    nengo.Connection(deriv2, model.switch.input, transform=10*vocab["ON"].v.reshape(D, 1))

    nengo.Connection(model.cleanup.output, model.stepper.input, synapse=0.01)
    nengo.Connection(model.stepper.output, model.cleanup.input, synapse=0.01)
    
    actions = spa.Actions(
        'dot(stepper, A)+dot(switch, ON)-1 --> stepper=B-A, switch=3*OFF',
        'dot(stepper, B)+dot(switch, ON)-1 --> stepper=C-B, switch=3*OFF',
        'dot(stepper, C)+dot(switch, ON)-1 --> stepper=D-C, switch=3*OFF',
        'dot(stepper, D)+dot(switch, ON)-1 --> stepper=E-D, switch=3*OFF',
        'dot(stepper, E)+dot(switch, ON)-1 --> stepper=A-E, switch=3*OFF',
        'dot(start, A) --> stepper=start',
        '0.5 --> '
        )

    model.bg = spa.BasalGanglia(actions)
    model.thalamus = spa.Thalamus(model.bg)
2 Likes