In [203]:
import nengo
import nengo.spa

D = 128
N = 50

vocab = nengo.spa.Vocabulary(D)

In [204]:
class LinearRule(object):
    def __init__(self, vocab, pre, post, gain=2, min=0):
        self.gain = 2
        self.min = 0
        self.pre = vocab.parse(pre).v
        self.post = vocab.parse(post).v
    def apply(self, state):
        x = np.dot(state, self.pre)
        if x < self.min:
            x = self.min
        v = x * self.gain
        return v * self.post    
    
class PairRule(object):
    def __init__(self, vocab, pre1, pre2, post, gain=2, min=0):
        self.gain = 2
        self.min = 0
        self.pre1 = vocab.parse(pre1).v
        self.pre2 = vocab.parse(pre2).v
        self.post = vocab.parse(post).v
    def apply(self, state):
        x = np.dot(state, self.pre1) * np.dot(state, self.pre2)
        if x < self.min:
            x = self.min
        v = x * self.gain
        return v * self.post    
    

    
    
class RuleSet(object):
    def __init__(self, vocab, tau, gain):
        self.vocab = vocab
        self.tau = tau
        self.gain = gain
        self.rules = []
    def add(self, rule):
        self.rules.append(rule)
        
    def apply(self, x):
        delta = np.zeros_like(x)
        for r in self.rules:
            delta += r.apply(x)
        return x * self.gain + self.tau * delta

    
nouns = ['DOG', 'CAT', 'N0', 'N1'][:2]
verbs = ['CHASE', 'V0', 'V1'][:1]

rules = RuleSet(vocab, tau=0.5, gain=1.2)

for noun in nouns:
    rules.add(LinearRule(vocab, noun, 'N_'+noun))
    rules.add(LinearRule(vocab, 'N_'+noun, '-0.2*'+noun))
    
    rules.add(LinearRule(vocab, 'N_'+noun, 'NP_'+noun))
    rules.add(LinearRule(vocab, 'NP_'+noun, '-0.2*N_'+noun))
for verb in verbs:
    rules.add(LinearRule(vocab, verb, 'V_'+verb))
    rules.add(LinearRule(vocab, 'V_'+verb, '-0.2*'+verb))
    
    for noun in nouns:
        rules.add(PairRule(vocab, 'V_'+verb, 'NP_'+noun, '10*VP_'+verb+'_'+noun+'-5*NP_'+noun+'-2*V_'+verb))

In [205]:
model = nengo.Network(seed=1)
with model:
    state = nengo.Ensemble(n_neurons=N*D, dimensions=D, neuron_type=nengo.LIFRate(), radius=2)
    
    
    nengo.Connection(state, state, synapse=0.1, function=rules.apply)
    
    def stim_func(t):
        stim = ['DOG', 'CHASE', 'CAT', '0', '0', '0', '0', '0']
        index = int(t / 0.5) % len(stim)
        return vocab.parse(stim[index]).v
        
    stimulus = nengo.Node(stim_func)
    nengo.Connection(stimulus, state, transform=0.3)
    
    probe = nengo.Probe(state)
    
sim = nengo.Simulator(model, seed=1)

In [206]:
sim.run(2)

In [207]:
figure(figsize=(10,7))
lines = plot(sim.trange(), vocab.dot(sim.data[probe].T).T, linewidth=5)
legend(lines, vocab.keys, loc='best')
show()



In [208]:
print vocab.text(sim.data[probe][-1], maximum_count=3)


3.22NP_DOG;0.61V_CHASE;0.46VP_CHASE_CAT

In [208]:


In [ ]: