def test_routing(Simulator, seed, plt): model = spa.Network(seed=seed) model.config[spa.State].vocab = 3 model.config[spa.State].subdimensions = 3 with model: model.ctrl = spa.State(16, subdimensions=16, label='ctrl') def input_func(t): if t < 0.2: return 'A' elif t < 0.4: return 'B' else: return 'C' model.input = spa.Transcode(input_func, output_vocab=16) model.buff1 = spa.State(label='buff1') model.buff2 = spa.State(label='buff2') model.buff3 = spa.State(label='buff3') node1 = nengo.Node([0, 1, 0]) node2 = nengo.Node([0, 0, 1]) nengo.Connection(node1, model.buff1.input) nengo.Connection(node2, model.buff2.input) model.input >> model.ctrl with spa.ActionSelection(): spa.ifmax(spa.dot(model.ctrl, spa.sym.A), model.buff1 >> model.buff3) spa.ifmax(spa.dot(model.ctrl, spa.sym.B), model.buff2 >> model.buff3) spa.ifmax(spa.dot(model.ctrl, spa.sym.C), model.buff1 * model.buff2 >> model.buff3) buff3_probe = nengo.Probe(model.buff3.output, synapse=0.03) with Simulator(model) as sim: sim.run(0.6) data = sim.data[buff3_probe] plt.plot(sim.trange(), data) valueA = np.mean(data[150:200], axis=0) # should be [0, 1, 0] valueB = np.mean(data[350:400], axis=0) # should be [0, 0, 1] valueC = np.mean(data[550:600], axis=0) # should be [1, 0, 0] assert valueA[0] < 0.2 assert valueA[1] > 0.7 assert valueA[2] < 0.2 assert valueB[0] < 0.2 assert valueB[1] < 0.2 assert valueB[2] > 0.7 assert valueC[0] > 0.7 assert valueC[1] < 0.2 assert valueC[2] < 0.2
def test_constructed_objects_are_accessible(): with spa.Network() as model: model.config[spa.State].vocab = 16 model.state1 = spa.State() model.state2 = spa.State() model.state3 = spa.State() with spa.ActionSelection() as actions: spa.ifmax(spa.dot(model.state1, spa.sym.A), model.state3 >> model.state2) spa.ifmax(0.5, spa.sym.B >> model.state2) bg = actions.bg thalamus = actions.thalamus assert isinstance(thalamus.gates[0], nengo.Ensemble) assert isinstance(thalamus.gate_in_connections[0], nengo.Connection) assert isinstance(thalamus.gate_out_connections[0], nengo.Connection) assert isinstance(thalamus.channels[0], spa.State) assert isinstance(thalamus.channel_out_connections[0], nengo.Connection) assert isinstance(thalamus.fixed_connections[1], nengo.Connection) assert thalamus.bg_connection.pre is bg.output assert thalamus.bg_connection.post is thalamus.input
def test_nondefault_routing(Simulator, seed): m = spa.Network(seed=seed) m.config[spa.State].vocab = 3 m.config[spa.State].subdimensions = 3 with m: m.ctrl = spa.State(16, subdimensions=16, label="ctrl") def input_func(t): if t < 0.2: return "A" elif t < 0.4: return "B" else: return "C" m.input = spa.Transcode(input_func, output_vocab=16) m.buff1 = spa.State(label="buff1") m.buff2 = spa.State(label="buff2") m.cmp = spa.Compare(3) node1 = nengo.Node([0, 1, 0]) node2 = nengo.Node([0, 0, 1]) nengo.Connection(node1, m.buff1.input) nengo.Connection(node2, m.buff2.input) m.input >> m.ctrl with spa.ActionSelection(): spa.ifmax( spa.dot(m.ctrl, spa.sym.A), m.buff1 >> m.cmp.input_a, m.buff1 >> m.cmp.input_b, ) spa.ifmax( spa.dot(m.ctrl, spa.sym.B), m.buff1 >> m.cmp.input_a, m.buff2 >> m.cmp.input_b, ) spa.ifmax( spa.dot(m.ctrl, spa.sym.C), m.buff2 >> m.cmp.input_a, m.buff2 >> m.cmp.input_b, ) compare_probe = nengo.Probe(m.cmp.output, synapse=0.03) with Simulator(m) as sim: sim.run(0.6) similarity = sim.data[compare_probe] valueA = np.mean(similarity[150:200], axis=0) # should be [1] valueB = np.mean(similarity[350:400], axis=0) # should be [0] valueC = np.mean(similarity[550:600], axis=0) # should be [1] assert valueA > 0.6 assert valueB < 0.3 assert valueC > 0.6
def test_dummy_action(): with spa.Network(): with spa.ActionSelection(): spa.ifmax(0) spa.ifmax("named-dummy", 0) with pytest.raises(ValueError): spa.ifmax("must-provide-condition")
def test_constructed_input_connections_are_accessible(): with spa.Network() as model: model.config[spa.State].vocab = 16 model.state1 = spa.State() model.state2 = spa.State() with spa.ActionSelection() as actions: spa.ifmax(spa.dot(model.state1, spa.sym.A), spa.sym.A >> model.state2) bg = actions.bg assert isinstance(bg.input_connections[0], nengo.Connection)
def test_routing_recurrency_compilation(Simulator, seed): model = spa.Network(seed=seed) model.config[spa.State].vocab = 2 model.config[spa.State].subdimensions = 2 with model: model.buff1 = spa.State(label="buff1") model.buff2 = spa.State(label="buff2") with spa.ActionSelection(): spa.ifmax(0.5, model.buff1 >> model.buff2, model.buff2 >> model.buff1) with Simulator(model) as sim: assert sim
def test_access_thal_and_bg_objects(): with spa.Network() as m: m.a = spa.Scalar() m.b = spa.Scalar() m.c = spa.Scalar() m.d = spa.Scalar() with spa.ActionSelection() as actions: spa.ifmax(m.a, 0 >> m.c) spa.ifmax(m.b, 1 >> m.c) assert isinstance(actions.bg, spa.BasalGanglia) assert isinstance(actions.thalamus, spa.Thalamus)
def __init__(self, vocab, label, n_neurons_per_dim, rng, BG_bias, BG_thr, feedback, sender=True, receiver=True, **kwargs): super(ADDProcessor, self).__init__(input_vocab=vocab, output_vocab=vocab, label=label, n_neurons_per_dim=n_neurons_per_dim, mapping=['D2', 'D4', 'D6', 'D8'], threshold=0, feedback=feedback, sender=sender, receiver=receiver, **kwargs) with self: # Domain specific processing self.bind = spa.Bind(vocab, n_neurons_per_dim['Bind']) with spa.Network() as self.result_controller: self.result_controller.labels = [] with spa.ActionSelection() as self.result_controller.AS: self.result_controller.labels.append("D0 -> D8") spa.ifmax(self.result_controller.labels[-1], BG_bias + spa.dot(s.D0, self.bind.output), s.D8 >> self.AM.input) self.result_controller.labels.append("D10 -> D2") spa.ifmax(self.result_controller.labels[-1], BG_bias + spa.dot(s.D10, self.bind.output), s.D2 >> self.AM.input) self.result_controller.labels.append("no cycle") spa.ifmax(self.result_controller.labels[-1], BG_bias + BG_thr, self.bind >> self.AM.input) nengo.Connection(self.input.output, self.bind.input_left)
def test_thalamus(Simulator, plt, seed): with spa.Network(seed=seed) as m: m.vision = spa.State(vocab=16, neurons_per_dimension=80) m.motor = spa.State(vocab=16, neurons_per_dimension=80) with spa.ActionSelection(): spa.ifmax(spa.dot(m.vision, spa.sym.A), spa.sym.A >> m.motor) spa.ifmax(spa.dot(m.vision, spa.sym.B), m.vision >> m.motor) spa.ifmax(spa.dot(m.vision, ~spa.sym.A), ~m.vision >> m.motor) def input_f(t): if t < 0.1: return 'A' elif t < 0.3: return 'B' elif t < 0.5: return '~A' else: return '0' m.input = spa.Transcode(input_f, output_vocab=16) m.input >> m.vision p = nengo.Probe(m.motor.output, synapse=0.03) with Simulator(m) as sim: sim.run(0.5) t = sim.trange() data = m.motor.vocab.dot(sim.data[p].T) plt.plot(t, data.T) # Action 1 assert data[0, t == 0.1] > 0.8 assert data[1, t == 0.1] < 0.2 # Action 2 assert data[0, t == 0.3] < 0.2 assert data[1, t == 0.3] > 0.8 # Action 3 assert data[0, t == 0.5] > 0.8 assert data[1, t == 0.5] < 0.2
def test_basal_ganglia(Simulator, seed, plt): d = 64 with spa.Network(seed=seed) as m: m.vision = spa.State(vocab=d) m.motor = spa.State(vocab=d) m.compare = spa.Compare(vocab=d) def input(t): if t < 0.1: return '0' elif t < 0.2: return 'CAT' elif t < 0.3: return 'DOG*~CAT' elif t < 0.4: return 'PARROT' elif t < 0.5: return 'MOUSE' else: return '0' m.encode = spa.Transcode(input, output_vocab=d) # test all acceptable condition formats with spa.ActionSelection() as actions: spa.ifmax(0.5, spa.sym.A >> m.motor) spa.ifmax(spa.dot(m.vision, spa.sym.CAT), spa.sym.B >> m.motor) spa.ifmax(spa.dot(m.vision * spa.sym.CAT, spa.sym.DOG), spa.sym.C >> m.motor) spa.ifmax(2 * spa.dot(m.vision, spa.sym.CAT * 0.5), spa.sym.D >> m.motor) spa.ifmax( spa.dot(m.vision, spa.sym.CAT) + 0.5 - spa.dot(m.vision, spa.sym.CAT), spa.sym.E >> m.motor) spa.ifmax( spa.dot(m.vision, spa.sym.PARROT) + m.compare, spa.sym.F >> m.motor) spa.ifmax(0.5 * spa.dot(m.vision, spa.sym.MOUSE) + 0.5 * m.compare, spa.sym.G >> m.motor) spa.ifmax((spa.dot(m.vision, spa.sym.MOUSE) - m.compare) * 0.5, spa.sym.H >> m.motor) m.encode >> m.vision spa.sym.SHOOP >> m.compare.input_a spa.sym.SHOOP >> m.compare.input_b bg = actions.bg p = nengo.Probe(bg.input, 'output', synapse=0.03) with Simulator(m) as sim: sim.run(0.5) t = sim.trange() plt.plot(t, sim.data[p]) plt.legend(["A", "B", "C", "D", "E", "F", "G", "H"]) plt.title('Basal Ganglia output') # assert the basal ganglia is prioritizing things correctly # Motor F assert sim.data[p][t == 0.4, 5] > 0.8 # Motor G assert sim.data[p][t == 0.5, 6] > 0.8 # Motor A assert 0.6 > sim.data[p][t == 0.1, 0] > 0.4 # Motor B assert sim.data[p][t == 0.2, 1] > 0.8 # Motor C assert sim.data[p][t == 0.3, 2] > 0.5 # Motor B should be the same as Motor D assert np.allclose(sim.data[p][:, 1], sim.data[p][:, 3], atol=0.2) # Motor A should be the same as Motor E assert np.allclose(sim.data[p][:, 0], sim.data[p][:, 4], atol=0.2)
def construct_network(self): self.send_n_neurons_per_dim() s = spa.sym net = self.network # temporary parameters self.crosstalk = False self.crosstalk_lr = 5e-12 with net: net.input_net = spa.Network(label='inputs', seed=self.seed) with net.input_net: net.input_net.RETINA_input = spa.Transcode( self.experiment.RETINA_input, input_vocab=self.vocabs['GW'], output_vocab=self.vocabs['GW']) net.V = DirectProcessor( self.vocabs['GW'], self.vocabs['GW'], 'V', receiver=False, # V only sends info to GW seed=self.seed, prediction_out=self.crosstalk, n_neurons_per_dim=self.n_neurons_per_dim) nengo.Connection(net.input_net.RETINA_input.output, net.V.input.input, synapse=None) net.FIXATE_detector = nengo.Node(size_in=1, label='FIXATE detector') nengo.Connection( net.V.input.output, net.FIXATE_detector, transform=net.V.output_vocab.parse('FIXATE').v[None, :], synapse=.05 ) # some synaptic delay is necessary to ensure the stimulus has time to enter GW net.declare_output(net.FIXATE_detector, None) net.M = DirectProcessor( self.vocabs['GW'], self.vocabs['GW'], 'M', sender=False, # M only receives info from GW seed=self.seed, n_neurons_per_dim=self.n_neurons_per_dim) net.BTN = nengo.Node(Button( SP_vectors=[ self.vocabs['GW'].parse('LESS').v, self.vocabs['GW'].parse('MORE').v ], trial_length=self.experiment.trial_length, wait_length=self.experiment.t_start), label='button', size_in=self.vocabs['GW'].dimensions) nengo.Connection( net.M.output.output, net.BTN ) # Connect output of M to BTN that records behavioral response net.ADD = ADDProcessor(self.vocabs['GW'], 'ADD', self.n_neurons_per_dim, self.rng, self.BG_bias, self.BG_thr, feedback=self.proc_feedback, seed=self.seed) with net.input_net: net.input_net.ADDEND = spa.Transcode( self.experiment.ADDEND_input, input_vocab=self.vocabs['GW'], output_vocab=self.vocabs['GW'], label='ADDEND') nengo.Connection(net.input_net.ADDEND.output, net.ADD.bind.input_right, synapse=None) if self.compare_tau != 0: net.COM = CompareProcessor( self.vocabs['GW'], self.vocabs['GW'], 'COM', self.experiment.trial_length, self.experiment.t_start if self.integrator_reset else 0, self.n_neurons_per_dim, self.rng, self.n_samples, tau=self.compare_tau, seed=self.seed, prediction_in=self.crosstalk) else: net.COM = AMProcessor(self.vocabs['GW'], self.vocabs['GW'], 'COM', { 'D2': 'LESS', 'D4': 'LESS', 'D6': 'MORE', 'D8': 'MORE' }, n_neurons_per_dim=self.n_neurons_per_dim, seed=self.seed, prediction_in=self.crosstalk) self.processors = [net.V, net.COM, net.M, net.ADD] if self.crosstalk: net.crosstalk = Prediction(net.V, net.COM, rate=self.crosstalk_lr) net.GW = GlobalWorkspace(self.vocabs['GW'], mappings={ net.V: ['D2', 'D4', 'D6', 'D8', 'FIXATE'], net.ADD: ['D2', 'D4', 'D6', 'D8'], net.COM: ['MORE', 'LESS'], }, n_neurons=self.n_neurons_per_dim['AM'], seed=self.seed) for detector in net.GW.detectors.values(): net.declare_output(detector, None) net.POS = WM(200, self.vocabs['PRIM']) net.clean_POS = spa.WTAAssocMem( threshold=0, input_vocab=net.POS.vocab, mapping=['D1', 'D2', 'D3', 'D4'], n_neurons=self.n_neurons_per_dim['AM'], function=lambda x: x > 0) nengo.Connection(net.POS.output, net.clean_POS.input) net.INCREMENT = WM(200, self.vocabs['PRIM']) nengo.Connection( net.clean_POS.output, net.INCREMENT.input, transform=net.POS.vocab.parse('D1').get_binding_matrix()) nengo.Connection(net.INCREMENT.output, net.POS.input) with net.input_net: net.input_net.INSTRUCTIONS = spa.Transcode( self.experiment.INSTRUCTIONS_input, input_vocab=self.vocabs['PRIM'], output_vocab=self.vocabs['PRIM'], label='INSTRUCTIONS') net.PRIM = spa.Bind( neurons_per_dimension=self.n_neurons_per_dim['Bind'], vocab=self.vocabs['PRIM'], unbind_right=True) net.input_net.INSTRUCTIONS >> net.PRIM.input_left net.clean_POS >> net.PRIM.input_right # GET selector with spa.Network(label='GET selector', seed=self.seed) as net.GET_selector: net.GET_selector.labels = [] with spa.ActionSelection() as net.GET_selector.AS: net.GET_selector.labels.append("GET V (FIXATE)") spa.ifmax(net.GET_selector.labels[-1], self.BG_bias + net.FIXATE_detector, net.V.preconscious >> net.GW.AMs[net.V].input, s.D1 >> net.POS.input, 1 >> net.INCREMENT.reset) net.GET_selector.labels.append("GET ADD") spa.ifmax( net.GET_selector.labels[-1], self.BG_bias + spa.dot(net.PRIM, s.GET_ADD) * (1 - net.GW.detectors[net.ADD]), net.ADD.preconscious >> net.GW.AMs[net.ADD].input, 1 >> net.POS.gate, ) net.GET_selector.labels.append("GET COM") spa.ifmax( net.GET_selector.labels[-1], self.BG_bias + spa.dot(net.PRIM, s.GET_COM) * (1 - net.GW.detectors[net.COM]), net.COM.preconscious >> net.GW.AMs[net.COM].input, 1 >> net.POS.gate, ) net.GET_selector.labels.append("Thresholder") spa.ifmax( net.GET_selector.labels[-1], self.BG_bias + self.BG_thr, 1 >> net.INCREMENT.gate, ) # SET selector with spa.Network(label='SET selector', seed=self.seed) as net.SET_selector: net.SET_selector.labels = [] with spa.ActionSelection() as net.SET_selector.AS: net.SET_selector.labels.append("SET ADD") spa.ifmax( net.SET_selector.labels[-1], self.BG_bias + spa.dot(net.PRIM, s.SET_ADD) * (1 - net.GW.detectors[net.ADD]), net.GW.AMs[net.COM] >> net.ADD.broadcast, net.GW.AMs[net.V] >> net.ADD.broadcast, ) net.SET_selector.labels.append("SET COM") spa.ifmax( net.SET_selector.labels[-1], self.BG_bias + spa.dot(net.PRIM, s.SET_COM) * (1 - net.GW.detectors[net.COM]), net.GW.AMs[net.ADD] >> net.COM.broadcast, net.GW.AMs[net.V] >> net.COM.broadcast, ) net.SET_selector.labels.append("SET M") spa.ifmax( net.SET_selector.labels[-1], self.BG_bias + spa.dot(net.PRIM, s.SET_M), net.GW.AMs[net.COM] >> net.M.broadcast, net.GW.AMs[net.V] >> net.M.broadcast, net.GW.AMs[net.ADD] >> net.M.broadcast, ) net.SET_selector.labels.append("Thresholder") spa.ifmax(net.SET_selector.labels[-1], self.BG_bias + self.BG_thr) # Threshold for action
def test_new_action_syntax(Simulator, seed, plt, rng): model = spa.Network(seed=seed) model.config[spa.State].vocab = 3 model.config[spa.State].subdimensions = 3 with model: model.ctrl = spa.State(16, subdimensions=16, label="ctrl") def input_func(t): if t < 0.2: return "A" elif t < 0.4: return "B" else: return "C" model.input = spa.Transcode(input_func, output_vocab=16) model.state = spa.State(label="state") model.buff1 = spa.State(label="buff1") model.buff2 = spa.State(label="buff2") model.buff3 = spa.State(label="buff3") node1 = nengo.Node([0, 1, 0]) node2 = nengo.Node([0, 0, 1]) nengo.Connection(node1, model.buff1.input) nengo.Connection(node2, model.buff2.input) model.input >> model.ctrl model.buff1 >> model.state with spa.ActionSelection(): spa.ifmax(spa.dot(model.ctrl, spa.sym.A), model.buff1 >> model.buff3) spa.ifmax(spa.dot(model.ctrl, spa.sym.B), model.buff2 >> model.buff3) spa.ifmax(spa.dot(model.ctrl, spa.sym.C), model.buff1 * model.buff2 >> model.buff3) state_probe = nengo.Probe(model.state.output, synapse=0.03) buff3_probe = nengo.Probe(model.buff3.output, synapse=0.03) with Simulator(model) as sim: sim.run(0.6) data = sim.data[buff3_probe] plt.plot(sim.trange(), data) state_val = np.mean(sim.data[state_probe][200:], axis=0) assert state_val[0] < 0.2 assert state_val[1] > 0.8 assert state_val[2] < 0.2 valueA = np.mean(data[150:200], axis=0) # should be [0, 1, 0] valueB = np.mean(data[350:400], axis=0) # should be [0, 0, 1] valueC = np.mean(data[550:600], axis=0) # should be [1, 0, 0] assert valueA[0] < 0.2 assert valueA[1] > 0.75 assert valueA[2] < 0.2 assert valueB[0] < 0.2 assert valueB[1] < 0.2 assert valueB[2] > 0.75 assert valueC[0] > 0.75 assert valueC[1] < 0.2 assert valueC[2] < 0.2
stim_cue >> ppc stim_cue >> pfcCUE motorClean = spa.WTAAssocMem(threshold=0.1, input_vocab=vocab, output_vocab=vocab, mapping=movesMap, function=lambda x: 1 if x > 0.1 else 0, label='motorClean') nengo.Connection(mdRULE.output, pfcRULEmemo.input, transform=5, synapse=0.05) with spa.ActionSelection() as act_sel: spa.ifmax(spa.dot(pfcRULEasso, s.AUD), s.AUD >> mdRULE) spa.ifmax(spa.dot(pfcRULEasso, s.VIS), s.VIS >> mdRULE) spa.ifmax(spa.dot(stim_target, s.AUD * s.RIGHT + s.VIS * s.LEFT), stim_target * ~pfcRULEmemo >> motorClean) spa.ifmax(spa.dot(stim_target, s.VIS * s.RIGHT + s.AUD * s.LEFT), stim_target * ~pfcRULEmemo >> motorClean) # learning mdCUE_ens = list(mdCUE.all_ensembles) mdRULE_ens = list(mdRULE.all_ensembles) ppc_ens = list(ppc.all_ensembles) errorPPC_ens = list(errorPPC.all_ensembles) -ppc >> errorPPC mdCUE >> errorPPC
# stores an association between mem1 and mem2 in working memory model.memory.mem_2 = spa.State(vocab=vocab_dim) # indicates one element of a pair to attempt to recall from working memory model.memory.request = spa.State(vocab=vocab_dim) # the vector associated with the currently requested vector model.memory.recall = spa.State(vocab=vocab_dim) with nengo.Network('motor') as model.motor: # tells the motor system which disk to move (A, B, C) model.motor.move_disk = spa.State(vocab=vocab_dim) # tells the motor system where to move the disk to (A, B, C) model.motor.move_peg = spa.State(vocab=vocab_dim) # Table E.2 is used to define the spa rules for the Tower of Hanoi model with nengo.Network('TOH Rules') as model.rules: with spa.ActionSelection() as model.rules.action_sel: spa.ifmax('LookDone', -spa.dot(model.buffer.focus, spa.sym.D0) + spa.dot(model.buffer.goal, model.buffer.focus) + spa.dot(model.sensory.goal_current, model.buffer.goal_target) + spa.dot(model.buffer.state, spa.sym.STORE), model.buffer.goal * spa.sym.NEXT >> model.buffer.focus, model.buffer.goal * spa.sym.NEXT >> model.buffer.goal, model.sensory.goal_final >> model.buffer.goal_target) spa.ifmax('LookNotDone', -spa.dot(model.buffer.focus, spa.sym.D0) + spa.dot(model.buffer.goal, model.buffer.focus) + -spa.dot(model.sensory.goal_current, model.buffer.goal_target) + spa.dot(model.buffer.state, spa.sym.STORE), model.buffer.goal * spa.sym.NEXT >> model.buffer.focus) spa.ifmax('InTheWay1',
def toh_agent(): model = nengo.Network('ToH Agent') with model: env = nengo.Node() # Table E.1 is used to define the spa states and subnetworks # of the cortical elements for the Tower of Hanoi model with nengo.Network('buffer') as model.buffer: # used to control the different stages of the problem-solving algorithm model.buffer.state = spa.State(vocab=vocab_dim) # stores the disk currently being attended to (D0, D1, D2, D3) model.buffer.focus = spa.State(vocab=vocab_dim) # stores the disk we are trying to move (D0, D1, D2, D3) model.buffer.goal = spa.State(vocab=vocab_dim) # stores the location we want to move the goal disk to (A, B, C) model.buffer.goal_target = spa.State(vocab=vocab_dim) with nengo.Network('sensory') as model.sensory: # automatically contains the location of the focus disk (A, B, C) model.sensory.focus_peg = spa.State(vocab=vocab_dim) # automatically contains the location of the goal disk (A, B, C) model.sensory.goal_current = spa.State(vocab=vocab_dim) # automatically contains the final desired location of the goal disk (A, B, C) model.sensory.goal_final = spa.State(vocab=vocab_dim) # automatically contains the largest visible disk (D3) model.sensory.largest = spa.State(vocab=vocab_dim) # automcatically contains DONE if the motor action is finished model.sensory.motor = spa.State(vocab=vocab_dim) with nengo.Network('memory') as model.memory: # stores an association between mem1 and mem2 in working memory model.memory.mem_1 = spa.State(vocab=vocab_dim) # stores an association between mem1 and mem2 in working memory model.memory.mem_2 = spa.State(vocab=vocab_dim) # indicates one element of a pair to attempt to recall from working memory model.memory.request = spa.State(vocab=vocab_dim) # the vector associated with the currently requested vector model.memory.recall = spa.State(vocab=vocab_dim) with nengo.Network('motor') as model.motor: # tells the motor system which disk to move (A, B, C) model.motor.move_disk = spa.State(vocab=vocab_dim) # tells the motor system where to move the disk to (A, B, C) model.motor.move_peg = spa.State(vocab=vocab_dim) # Table E.2 is used to define the spa rules for the Tower of Hanoi model with nengo.Network('TOH Rules') as model.rules: with spa.ActionSelection() as model.rules.action_sel: spa.ifmax( 'LookDone', -spa.dot(model.buffer.focus, spa.sym.D0) + spa.dot(model.buffer.goal, model.buffer.focus) + spa.dot( model.sensory.goal_current, model.buffer.goal_target) + spa.dot(model.buffer.state, spa.sym.STORE), model.buffer.goal * spa.sym.NEXT >> model.buffer.focus, model.buffer.goal * spa.sym.NEXT >> model.buffer.goal, model.sensory.goal_final >> model.buffer.goal_target) spa.ifmax( 'LookNotDone', -spa.dot(model.buffer.focus, spa.sym.D0) + spa.dot(model.buffer.goal, model.buffer.focus) + -spa.dot( model.sensory.goal_current, model.buffer.goal_target) + spa.dot(model.buffer.state, spa.sym.STORE), model.buffer.goal * spa.sym.NEXT >> model.buffer.focus) spa.ifmax( 'InTheWay1', -spa.dot(model.buffer.focus, model.buffer.goal) + spa.dot( model.sensory.focus_peg, model.sensory.goal_current) + -spa.dot(model.sensory.focus_peg, model.buffer.goal_target) + -spa.dot(model.buffer.state, spa.sym.STORE), model.buffer.goal * spa.sym.NEXT >> model.buffer.focus) spa.ifmax( 'InTheWay2', -spa.dot(model.buffer.focus, model.buffer.goal) + -spa.dot( model.sensory.focus_peg, model.sensory.goal_current) + spa.dot(model.sensory.focus_peg, model.buffer.goal_target) + -spa.dot(model.buffer.state, spa.sym.STORE), model.buffer.goal * spa.sym.NEXT >> model.buffer.focus) spa.ifmax( 'NotInTheWay', -spa.dot(model.buffer.focus, model.buffer.goal) + -spa.dot( model.sensory.focus_peg, model.sensory.goal_current) + -spa.dot(model.sensory.focus_peg, model.buffer.goal_target) + -spa.dot(model.buffer.focus, spa.sym.D0), model.buffer.goal * spa.sym.NEXT >> model.buffer.focus) spa.ifmax( 'MoveD0', spa.dot(model.buffer.focus, spa.sym.D0) + spa.dot(model.buffer.goal, spa.sym.D0) + -spa.dot( model.sensory.goal_current, model.buffer.goal_target), spa.sym.D0 >> model.motor.move_disk, model.buffer.goal_target >> model.motor.move_peg) spa.ifmax( 'MoveGoal', spa.dot(model.buffer.focus, spa.sym.D0) + -spa.dot(model.buffer.goal, spa.sym.D0) + -spa.dot(model.sensory.focus_peg, model.buffer.goal_target) + -spa.dot(model.buffer.goal_target, model.sensory.goal_current) + -spa.dot(model.sensory.focus_peg, model.sensory.goal_current), model.buffer.goal >> model.motor.move_disk, model.buffer.goal_target >> model.motor.move_peg) spa.ifmax( 'MoveDone', spa.dot(model.sensory.motor, spa.sym.DONE) + -spa.dot(model.buffer.goal, model.sensory.largest) + -spa.dot(model.buffer.state, spa.sym.RECALL), spa.sym.RECALL >> model.buffer.state, model.buffer.goal * ~spa.sym.NEXT >> model.buffer.goal) spa.ifmax( 'MoveDone2', spa.dot(model.sensory.motor, spa.sym.DONE) + spa.dot(model.buffer.goal, model.sensory.largest) + -spa.dot(model.buffer.state, spa.sym.RECALL), model.sensory.largest * ~spa.sym.NEXT >> model.buffer.focus, model.sensory.largest * ~spa.sym.NEXT >> model.buffer.goal, model.sensory.goal_final >> model.buffer.goal_target, spa.sym.HANOI >> model.buffer.state) spa.ifmax( 'Store', spa.dot(model.buffer.state, spa.sym.STORE) + -spa.dot(model.memory.recall, model.buffer.goal_target), model.buffer.goal >> model.memory.mem_1, model.buffer.goal_target >> model.memory.mem_2, model.buffer.goal >> model.memory.request) spa.ifmax( 'StoreDone', spa.dot(model.buffer.state, spa.sym.STORE) + spa.dot(model.memory.recall, model.buffer.goal_target), spa.sym.FIND >> model.buffer.state) spa.ifmax( 'FindFree1', spa.dot(model.buffer.state, spa.sym.FIND) + -spa.dot(model.buffer.focus, model.buffer.goal) + spa.dot( model.sensory.focus_peg, model.sensory.goal_current) + -spa.dot(model.sensory.focus_peg, model.buffer.goal_target), spa.sym.A + spa.sym.B + spa.sym.C - model.sensory.focus_peg - model.buffer.goal_target >> model.buffer.goal_target, model.buffer.focus >> model.buffer.goal, spa.sym.HANOI >> model.buffer.state) spa.ifmax( 'FindFree2', spa.dot(model.buffer.state, spa.sym.FIND) + -spa.dot(model.buffer.focus, model.buffer.goal) + -spa.dot( model.sensory.focus_peg, model.sensory.goal_current) + spa.dot(model.sensory.focus_peg, model.buffer.goal_target), spa.sym.A + spa.sym.B + spa.sym.C - model.sensory.goal_current - model.buffer.goal_target >> model.buffer.goal_target, model.buffer.focus >> model.buffer.goal, spa.sym.HANOI >> model.buffer.state) spa.ifmax( 'Recall', spa.dot(model.buffer.state, spa.sym.RECALL) + -spa.dot(model.memory.recall, spa.sym.A + spa.sym.B + spa.sym.C), model.buffer.goal >> model.memory.request) spa.ifmax( 'RecallDo', spa.dot(model.buffer.state, spa.sym.RECALL) + spa.dot(model.memory.recall, spa.sym.A + spa.sym.B + spa.sym.C) + -spa.dot(model.memory.recall, model.sensory.goal_current), spa.sym.HANOI >> model.buffer.state, model.buffer.goal >> model.buffer.focus, 4 * model.memory.recall >> model.buffer.goal_target) spa.ifmax( 'RecallNext', spa.dot(model.buffer.state, spa.sym.RECALL) + spa.dot(model.memory.recall, spa.sym.A + spa.sym.B + spa.sym.C) + spa.dot(model.memory.recall, model.sensory.goal_current), spa.sym.HANOI >> model.buffer.state, model.buffer.goal * ~spa.sym.NEXT >> model.buffer.goal, model.buffer.goal >> model.memory.request) return model
def test_scalar_product(): with spa.Network() as model: model.scalar = spa.Scalar() with spa.ActionSelection(): spa.ifmax(model.scalar * model.scalar, 1 >> model.scalar)
def evaluate(self, p, plt): stimuli = [] for i in range(p.n_stims): stimuli.append(('NEUTRAL%d' % i, 'COLOR%d' % i, 'neutral')) for i in range(p.n_stims): stimuli.append(('COLOR%d' % i, 'COLOR%d' % i, 'congruent')) for i in range(p.n_stims): stimuli.append(('COLOR%d' % ((i + 1) % p.n_stims), 'COLOR%d' % i, 'incongruent')) vocab = spa.Vocabulary(p.D, pointer_gen=np.random.RandomState(seed=p.seed)) for i in range(p.n_stims): vocab.populate('NEUTRAL%d' % i) vocab.populate('COLOR%d' % i) vocab.populate('COLOR; WORD') model = spa.Network(seed=p.seed) with model: def word_func(t): index = int(t / (p.t_stim + p.t_isi)) t = t % (p.t_stim + p.t_isi) if t < p.t_isi: return '0' else: return stimuli[index % len(stimuli)][0] def color_func(t): index = int(t / (p.t_stim + p.t_isi)) t = t % (p.t_stim + p.t_isi) if t < p.t_isi: return '0' else: return stimuli[index % len(stimuli)][1] stim_w = spa.Transcode(word_func, output_vocab=vocab) stim_c = spa.Transcode(color_func, output_vocab=vocab) stim_a = spa.Transcode('(1-%g)*COLOR + %g*WORD' % (p.attention_error, p.attention_error), output_vocab=vocab) wm = spa.State(vocab) (spa.sym.COLOR * stim_c + spa.sym.WORD * stim_w) * ~stim_a >> wm if p.auto_direct != 0: stim_w * p.auto_direct >> wm speech = spa.State(vocab) if p.decision == 'bg': with spa.ActionSelection() as action_sel: for i in range(p.n_stims): spa.ifmax(spa.dot(wm, spa.sym('COLOR%d' % i)), spa.sym('COLOR%d' % i) >> speech) spa.ifmax(0.35, spa.sym('0') >> speech) elif p.decision == 'ia': def reset_func(t): index = int(t / (p.t_stim + p.t_isi)) t = t % (p.t_stim + p.t_isi) if t < p.t_isi: return 1 else: return 0 reset = nengo.Node(reset_func) decision = spa.IAAssocMem( vocab, mapping=['COLOR%d' % i for i in range(p.n_stims)], accum_timescale=p.ia_accum_timescale) wm >> decision nengo.Connection(reset, decision.input_reset) else: raise Exception('Unknown decision param: %s' % p.decision) if not p.use_neurons: for ens in model.all_ensembles: ens.neuron_type = nengo.Direct() p_output = nengo.Probe(wm.output, synapse=0.02) p_correct = nengo.Probe(stim_c.output) p_speech = nengo.Probe(speech.output, synapse=0.02) if p.decision == 'bg': p_act = nengo.Probe(action_sel.thalamus.output, synapse=0.01) elif p.decision == 'ia': p_act = nengo.Probe(decision.selection.output, synapse=0.01) sim = nengo.Simulator(model, progress_bar=p.verbose) with sim: sim.run(p.n_stims * (p.t_isi + p.t_stim) * 3) v = np.einsum('ij,ij->i', sim.data[p_correct], sim.data[p_output]) steps = int((p.t_isi + p.t_stim) / sim.dt) scores = v[steps - 2::steps] data = sim.data[p_act] rts = [] accuracy = [] for condition in range(3): for i in range(p.n_stims): t_start = (p.t_isi + p.t_stim) * i + p.t_isi + condition * ( p.t_isi + p.t_stim) * p.n_stims t_end = t_start + p.t_stim d = data[int(t_start / sim.dt):int(t_end / sim.dt), i] correct = np.max(d) > p.output_threshold if correct: rt = np.where(d > p.output_threshold)[0][0] * sim.dt else: rt = None rts.append(rt) accuracy.append(correct) if plt: plt.subplot(2, 1, 1) plt.plot(sim.trange(), sim.data[p_output].dot(vocab.vectors.T)) plt.subplot(2, 1, 2) if p.decision == 'bg': plt.plot(sim.trange(), sim.data[p_act][:, :-1]) elif p.decision == 'ia': plt.plot(sim.trange(), sim.data[p_act]) for i in range(p.n_stims * 3): plt.axvline(i * (p.t_isi + p.t_stim) + p.t_isi, ls='--') acc_neutral = sum([0.0 if r is None else 1.0 for r in rts[:p.n_stims]]) / p.n_stims acc_congruent = sum( [0.0 if r is None else 1.0 for r in rts[p.n_stims:p.n_stims * 2]]) / p.n_stims acc_incongruent = sum( [0.0 if r is None else 1.0 for r in rts[p.n_stims * 2:]]) / p.n_stims if acc_neutral == 0: rt_neutral = None else: rt_neutral = np.mean([r for r in rts[:p.n_stims] if r is not None]) if acc_congruent == 0: rt_congruent = None else: rt_congruent = np.mean( [r for r in rts[p.n_stims:p.n_stims * 2] if r is not None]) if acc_incongruent == 0: rt_incongruent = None else: rt_incongruent = np.mean( [r for r in rts[p.n_stims * 2:] if r is not None]) return dict( scores=scores, stimuli=stimuli, neutral=np.mean(scores[:p.n_stims]), congruent=np.mean(scores[p.n_stims:p.n_stims * 2]), incongruent=np.mean(scores[p.n_stims * 2:]), rts=rts, accuracy=accuracy, rt_neutral=rt_neutral, rt_congruent=rt_congruent, rt_incongruent=rt_incongruent, acc_neutral=acc_neutral, acc_congruent=acc_congruent, acc_incongruent=acc_incongruent, )
if t<.1: return "D0" else: return "0" with spa.Network() as model: utility = nengo.Node([0]) trigger = TwoStepsTrigger(50) output_cmd = spa.Transcode(input_vocab=vocab, output_vocab=vocab) with spa.ActionSelection(): spa.ifmax( utility, 1 >> trigger.input ) spa.ifmax( .5, ) POSITION = WM(100, vocab, label='position') INCREMENT = WM(100, vocab, label='added') nengo.Connection(POSITION.output, INCREMENT.input, transform=vocab.parse('D1').get_binding_matrix()) nengo.Connection(INCREMENT.output, POSITION.input) with spa.ActionSelection():
mapping=['SET_COM', 'SET_ADD', 'SET_M'], n_neurons=50, function=lambda x: x > 0) PRIM >> GET_PRIM PRIM >> SET_PRIM input_INSTRUCTIONS >> PRIM.input_left spa.translate(clean_POS, vocab) >> PRIM.input_right SET_exec = spa.Transcode(input_vocab=vocab, output_vocab=vocab) GET_exec = spa.Transcode(input_vocab=vocab, output_vocab=vocab) # GET selector with spa.Network(label='GET selector') as GET_selector: GET_selector.labels = [] with spa.ActionSelection() as GET_selector.AS: GET_selector.labels.append("GET V (FIXATE)") spa.ifmax(GET_selector.labels[-1], BG_bias + FIXATE_detector, V.preconscious >> GW.AMs[V].input, s.D1 >> POS.input, s.D1 * clean_POS >> INCREMENT.input) # GET_selector.labels.append("GET V") # spa.ifmax(GET_selector.labels[-1], BG_bias + spa.dot(GET_PRIM, s.GET_V) * (1-spa.dot(GET_exec, s.GET_V)), # s.GET_V >> GET_exec, # 1 >> POS.gate, # ) GET_selector.labels.append("GET ADD") spa.ifmax( GET_selector.labels[-1], BG_bias +