def test_scalar(self): """A network that represents sin(t).""" N = 30 m = nengo.Model('test_scalar', seed=123) m.make_node('in', output=np.sin) m.make_ensemble('A', nengo.LIF(N), 1) m.connect('in', 'A') m.probe('in') m.probe('A', filter=0.02) sim = m.simulator(dt=0.001, sim_class=self.Simulator) sim.run(5.0) with Plotter(self.Simulator) as plt: t = sim.data(m.t) plt.plot(t, sim.data('in'), label='Input') plt.plot(t, sim.data('A'), label='Neuron approximation, pstc=0.02') plt.legend(loc=0) plt.savefig('test_ensemble.test_scalar.pdf') plt.close() target = np.sin(np.arange(5000) / 1000.) target.shape = (-1, 1) logger.debug("[New API] input RMSE: %f", rmse(target, sim.data('in'))) logger.debug("[New API] A RMSE: %f", rmse(target, sim.data('A'))) self.assertTrue(rmse(target, sim.data('in')) < 0.001) self.assertTrue(rmse(target, sim.data('A')) < 0.1)
def test_prod(self): def product(x): return x[0] * x[1] N = 250 seed = 123 net = nef.Network('Matrix Multiplication', seed=seed, simulator=self.Simulator) net.make_input('sin', value=np.sin) net.make_input('neg', value=[-.5]) net.make_array('p', 2 * N, 1, dimensions=2, radius=1.5) net.make_array('D', N, 1, dimensions=1) net.connect('sin', 'p', transform=[[1], [0]]) net.connect('neg', 'p', transform=[[0], [1]]) net.connect('p', 'D', func=product, pstc=0.01) p_raw = net._probe_decoded_signals( [net.ensembles['p'].origin['product'].sigs[0]], dt_sample=.01, pstc=.01) probe_p = net.make_probe('p', dt_sample=.01, pstc=.01) probe_d = net.make_probe('D', dt_sample=.01, pstc=.01) net.run(6) data_p = probe_p.get_data() data_d = probe_d.get_data() data_r = p_raw.get_data() with Plotter(self.Simulator) as plt: plt.subplot(211) plt.plot(data_p) plt.plot(np.sin(np.arange(0, 6, .01))) plt.subplot(212) plt.plot(data_d) plt.plot(data_r) plt.plot(-.5 * np.sin(np.arange(0, 6, .01))) plt.savefig('test_old_api.test_prod.pdf') plt.close() self.assertTrue( np.allclose(data_p[:, 0], np.sin(np.arange(0, 6, .01)), atol=.1, rtol=.01)) self.assertTrue(np.allclose(data_p[20:, 1], -0.5, atol=.1, rtol=.01)) def match(a, b): self.assertTrue(np.allclose(a, b, .1, .1)) match(data_d[:, 0], -0.5 * np.sin(np.arange(0, 6, .01))) match(data_r[:, 0], -0.5 * np.sin(np.arange(0, 6, .01)))
def test_decoder_to_nonlinearity(self): N = 30 m = nengo.Model('test_decoder_to_nonlinearity', seed=123) a = m.make_ensemble('A', nengo.LIF(N), dimensions=1) b = m.make_ensemble('B', nengo.LIF(N), dimensions=1) m.make_node('in', output=np.sin) m.make_node('inh', piecewise({0: 0, 2.5: 1})) m.make_node('ideal', piecewise({0: np.sin, 2.5: 0})) m.connect('in', 'A') m.connect('inh', 'B') con = m.connect('B', a.neurons, transform=[[-2.5]] * N) m.probe('in') m.probe('A', filter=0.1) m.probe('B', filter=0.1) m.probe('inh') m.probe('ideal') sim = m.simulator(dt=0.001, sim_class=self.Simulator) sim.run(5.0) with Plotter(self.Simulator) as plt: t = sim.data(m.t) plt.plot(t, sim.data('in'), label='Input') plt.plot(t, sim.data('A'), label='Neuron approx, pstc=0.1') plt.plot(t, sim.data('B'), label='Neuron approx of inhib sig, pstc=0.1') plt.plot(t, sim.data('inh'), label='Inhib signal') plt.plot(t, sim.data('ideal'), label='Ideal output') plt.legend(loc=0, prop={'size': 10}) plt.savefig( 'test_tononlinearity_connection.test_decoder_to_nonlinearity.pdf' ) plt.close() self.assertTrue( np.allclose(sim.data('A')[-10:], sim.data('ideal')[-10:], atol=.1, rtol=.01)) self.assertTrue( np.allclose(sim.data('B')[-10:], sim.data('inh')[-10:], atol=.1, rtol=.01))
def test_product(self): def product(x): return x[0] * x[1] m = nengo.Model('test_product', seed=124) N = 80 m.make_node('sin', output=np.sin) m.make_node('-0.5', output=-.5) factors = m.make_ensemble( 'factors', nengo.LIF(2 * N), dimensions=2, radius=1.5) factors.encoders = np.tile([[1, 1],[-1, 1],[1, -1],[-1, -1]], (factors.n_neurons / 4, 1)) m.make_ensemble('product', nengo.LIF(N), dimensions=1) m.connect('sin', 'factors', transform=[[1], [0]]) m.connect('-0.5', 'factors', transform=[[0], [1]]) conn = m.connect('factors', 'product', function=product, filter=0.01) m.probe('sin', sample_every=.01) # m.probe(conn, sample_every=.01) # FIXME m.probe('factors', sample_every=.01, filter=.01) m.probe('product', sample_every=.01, filter=.01) sim = m.simulator(dt=0.001, sim_class=self.Simulator) sim.run(6) with Plotter(self.Simulator) as plt: plt.subplot(211) plt.plot(sim.data('factors')) plt.plot(np.sin(np.arange(0, 6, .01))) plt.plot(sim.data('sin')) plt.subplot(212) plt.plot(sim.data('product')) #plt.plot(sim.data(conn)) plt.plot(-.5 * np.sin(np.arange(0, 6, .01))) plt.savefig('test_ensemble.test_prod.pdf') plt.close() self.assertTrue(rmse(sim.data('factors')[:, 0], np.sin(np.arange(0, 6, .01))) < 0.1) self.assertTrue(rmse(sim.data('factors')[20:, 1], -0.5) < 0.1) def match(a, b): self.assertTrue(rmse(a, b) < 0.1) match(sim.data('product')[:, 0], -0.5 * np.sin(np.arange(0, 6, .01)))
def test_simple(self): dt = 0.001 m = nengo.Model('test_simple', seed=123) m.make_node('in', output=np.sin) m.probe('in') sim = m.simulator(dt=dt, sim_class=self.Simulator) runtime = 0.5 sim.run(runtime) with Plotter(self.Simulator) as plt: plt.plot(sim.data(m.t), sim.data('in'), label='sin') plt.legend(loc='best') plt.savefig('test_node.test_simple.pdf') plt.close() sim_t = sim.data(m.t).ravel() sim_in = sim.data('in').ravel() t = dt * np.arange(len(sim_t)) self.assertTrue(np.allclose(sim_t, t)) self.assertTrue(np.allclose(sim_in[1:], np.sin(t[:-1]))) # 1-step delay
def test_vector(self): """A network that represents sin(t), cos(t), arctan(t).""" simulator = self.Simulator params = dict(simulator=simulator, seed=123, dt=0.001) N = 40 target = np.vstack( (np.sin(np.arange(4999) / 1000.), np.cos(np.arange(4999) / 1000.), np.arctan(np.arange(4999) / 1000.))).T # Old API net = nef.Network('test_vector', **params) net.make_input('sin', value=np.sin) net.make_input('cos', value=np.cos) net.make_input('arctan', value=np.arctan) net.make('A', N * 3, 3, radius=2) net.connect('sin', 'A', transform=[[1], [0], [0]]) net.connect('cos', 'A', transform=[[0], [1], [0]]) net.connect('arctan', 'A', transform=[[0], [0], [1]]) sin_p = net.make_probe('sin', dt_sample=0.001, pstc=0.0) cos_p = net.make_probe('cos', dt_sample=0.001, pstc=0.0) arctan_p = net.make_probe('arctan', dt_sample=0.001, pstc=0.0) a_p = net.make_probe('A', dt_sample=0.001, pstc=0.02) net.run(5) sin_data = sin_p.get_data() cos_data = cos_p.get_data() arctan_data = arctan_p.get_data() a_data = a_p.get_data() with Plotter(simulator) as plt: t = net.model.data[net.model.simtime] plt.plot(t, sin_data, label='sin') plt.plot(t, cos_data, label='cos') plt.plot(t, arctan_data, label='arctan') plt.plot(t, a_data, label='Neuron approximation, pstc=0.02') plt.legend(loc=0, prop={'size': 10}) plt.savefig('test_ensemble.test_vector-old.pdf') plt.close() logger.debug("[Old API] sin RMSE: %f", rmse(target[:, 0], sin_data)) logger.debug("[Old API] cos RMSE: %f", rmse(target[:, 1], cos_data)) logger.debug("[Old API] atan RMSE: %f", rmse(target[:, 2], arctan_data)) logger.debug("[Old API] A RMSE: %f", rmse(target, a_data)) self.assertTrue(rmse(target, a_data) < 0.1) # New API m = nengo.Model('test_vector', **params) m.make_node('sin', output=np.sin) m.make_node('cos', output=np.cos) m.make_node('arctan', output=np.arctan) m.make_ensemble('A', nengo.LIF(N * 3), 3, radius=2) m.connect('sin', 'A', transform=[[1], [0], [0]]) m.connect('cos', 'A', transform=[[0], [1], [0]]) m.connect('arctan', 'A', transform=[[0], [0], [1]]) m.probe('sin') m.probe('cos') m.probe('arctan') m.probe('A', filter=0.02) m.run(5) with Plotter(simulator) as plt: t = m.data[m.simtime] plt.plot(t, m.data['sin'], label='sin') plt.plot(t, m.data['cos'], label='cos') plt.plot(t, m.data['arctan'], label='arctan') plt.plot(t, m.data['A'], label='Neuron approximation, pstc=0.02') plt.legend(loc=0, prop={'size': 10}) plt.savefig('test_ensemble.test_vector-new.pdf') plt.close() # Not sure why, but this isn't working... logger.debug("[New API] sin RMSE: %f", rmse(target[:, 0], m.data['sin'])) logger.debug("[New API] cos RMSE: %f", rmse(target[:, 1], m.data['cos'])) logger.debug("[New API] atan RMSE: %f", rmse(target[:, 2], m.data['arctan'])) logger.debug("[New API] A RMSE: %f", rmse(target, m.data['A'])) self.assertTrue(rmse(target, m.data['A']) < 0.1) # Check old/new API similarity logger.debug("Old/New API RMSE: %f", rmse(a_data, m.data['A'])) self.assertTrue(rmse(a_data, m.data['A']) < 0.1)
def _test_circularconv(self, dims=5, neurons_per_product=128): rng = np.random.RandomState(42342) n_neurons = neurons_per_product * dims n_neurons_d = 2 * neurons_per_product * (2 * dims - (2 if dims % 2 == 0 else 1)) radius = 1 a = rng.normal(scale=np.sqrt(1. / dims), size=dims) b = rng.normal(scale=np.sqrt(1. / dims), size=dims) c = circconv(a, b) self.assertTrue(np.abs(a).max() < radius) self.assertTrue(np.abs(b).max() < radius) self.assertTrue(np.abs(c).max() < radius) ### model model = nengo.Model("circular convolution") inputA = model.make_node("inputA", output=a) inputB = model.make_node("inputB", output=b) A = model.add( EnsembleArray('A', nengo.LIF(n_neurons), dims, radius=radius)) B = model.add( EnsembleArray('B', nengo.LIF(n_neurons), dims, radius=radius)) C = model.add( EnsembleArray('C', nengo.LIF(n_neurons), dims, radius=radius)) D = model.add( CircularConvolution('D', neurons=nengo.LIF(n_neurons_d), dimensions=A.dimensions, radius=radius)) inputA.connect_to(A) inputB.connect_to(B) A.connect_to(D.A) B.connect_to(D.B) D.output.connect_to(C) model.probe(A, filter=0.03) model.probe(B, filter=0.03) model.probe(C, filter=0.03) model.probe(D.ensemble, filter=0.03) # check FFT magnitude d = np.dot(D.transformA, a) + np.dot(D.transformB, b) self.assertTrue(np.abs(d).max() < radius) ### simulation sim = model.simulator(sim_class=self.Simulator) sim.run(1.0) t = sim.data(model.t).flatten() with Plotter(self.Simulator) as plt: def plot(sim, a, A, title=""): a_ref = np.tile(a, (len(t), 1)) a_sim = sim.data(A) colors = ['b', 'g', 'r', 'c', 'm', 'y'] for i in xrange(min(dims, len(colors))): plt.plot(t, a_ref[:, i], '--', color=colors[i]) plt.plot(t, a_sim[:, i], '-', color=colors[i]) plt.title(title) plt.subplot(221) plot(sim, a, A, title="A") plt.subplot(222) plot(sim, b, B, title="B") plt.subplot(223) plot(sim, c, C, title="C") plt.subplot(224) plot(sim, d, D.ensemble, title="D") plt.savefig('test_circularconv.test_circularconv_%d.pdf' % dims) plt.close() ### results tmask = t > (0.5 + sim.model.dt / 2) self.assertEqual(sim.data(A)[tmask].shape, (499, dims)) a_sim = sim.data(A)[tmask].mean(axis=0) b_sim = sim.data(B)[tmask].mean(axis=0) c_sim = sim.data(C)[tmask].mean(axis=0) d_sim = sim.data(D.ensemble)[tmask].mean(axis=0) rtol, atol = 0.1, 0.05 self.assertTrue(np.allclose(a, a_sim, rtol=rtol, atol=atol)) self.assertTrue(np.allclose(b, b_sim, rtol=rtol, atol=atol)) self.assertTrue(np.allclose(d, d_sim, rtol=rtol, atol=atol)) self.assertTrue(rmse(c, c_sim) < 0.075)
def test_multidim(self): """Test an ensemble array with multiple dimensions per ensemble""" dims = 3 n_neurons = 3 * 60 radius = 1.5 rng = np.random.RandomState(523887) a = rng.uniform(low=-0.7, high=0.7, size=dims) b = rng.uniform(low=-0.7, high=0.7, size=dims) ta = np.zeros((6, 3)) ta[[0, 2, 4], [0, 1, 2]] = 1 tb = np.zeros((6, 3)) tb[[1, 3, 5], [0, 1, 2]] = 1 c = np.dot(ta, a) + np.dot(tb, b) model = nengo.Model('Multidim', seed=123) inputA = model.make_node('input A', output=a) inputB = model.make_node('input B', output=b) A = model.add( EnsembleArray('A', nengo.LIF(n_neurons), dims, radius=radius)) B = model.add( EnsembleArray('B', nengo.LIF(n_neurons), dims, radius=radius)) C = model.add( EnsembleArray('C', nengo.LIF(n_neurons * 2), dims, dimensions_per_ensemble=2, radius=radius)) model.connect(inputA, A) model.connect(inputB, B) model.connect(A, C, transform=ta) model.connect(B, C, transform=tb) model.probe(A, filter=0.03) model.probe(B, filter=0.03) model.probe(C, filter=0.03) sim = model.simulator(sim_class=self.Simulator) sim.run(1.0) t = sim.data(model.t).flatten() with Plotter(self.Simulator) as plt: def plot(sim, a, A, title=""): a_ref = np.tile(a, (len(t), 1)) a_sim = sim.data(A) colors = ['b', 'g', 'r', 'c', 'm', 'y'] for i in xrange(a_sim.shape[1]): plt.plot(t, a_ref[:, i], '--', color=colors[i]) plt.plot(t, a_sim[:, i], '-', color=colors[i]) plt.title(title) plt.subplot(131) plot(sim, a, A, title="A") plt.subplot(132) plot(sim, b, B, title="B") plt.subplot(133) plot(sim, c, C, title="C") plt.savefig('test_ensemble_array.test_multidim.pdf') plt.close() a_sim = sim.data(A)[t > 0.5].mean(axis=0) b_sim = sim.data(B)[t > 0.5].mean(axis=0) c_sim = sim.data(C)[t > 0.5].mean(axis=0) rtol, atol = 0.1, 0.05 self.assertTrue(np.allclose(a, a_sim, atol=atol, rtol=rtol)) self.assertTrue(np.allclose(b, b_sim, atol=atol, rtol=rtol)) self.assertTrue(np.allclose(c, c_sim, atol=atol, rtol=rtol))
def test_matrix_mul(self): N = 100 Amat = np.asarray([[.5, -.5]]) Bmat = np.asarray([[ 0, -1., ], [.7, 0]]) model = nengo.Model('Matrix Multiplication', seed=123) radius = 1 model.add( EnsembleArray('A', nengo.LIF(N * Amat.size), Amat.size, radius=radius)) model.add( EnsembleArray('B', nengo.LIF(N * Bmat.size), Bmat.size, radius=radius)) inputA = model.make_node('input A', output=Amat.ravel()) inputB = model.make_node('input B', output=Bmat.ravel()) model.connect('input A', 'A') model.connect('input B', 'B') model.probe('A', sample_every=0.01, filter=0.01) model.probe('B', sample_every=0.01, filter=0.01) C = model.add( EnsembleArray('C', nengo.LIF(N * Amat.size * Bmat.shape[1] * 2), Amat.size * Bmat.shape[1], dimensions_per_ensemble=2, radius=1.5 * radius)) for ens in C.ensembles: ens.encoders = np.tile([[1, 1], [-1, 1], [1, -1], [-1, -1]], (ens.n_neurons / 4, 1)) transformA = np.zeros((C.dimensions, Amat.size)) transformB = np.zeros((C.dimensions, Bmat.size)) for i in range(Amat.shape[0]): for j in range(Amat.shape[1]): for k in range(Bmat.shape[1]): tmp = (j + k * Amat.shape[1] + i * Bmat.size) transformA[tmp * 2][j + i * Amat.shape[1]] = 1 transformB[tmp * 2 + 1][k + j * Bmat.shape[1]] = 1 model.connect('A', 'C', transform=transformA) model.connect('B', 'C', transform=transformB) model.probe('C', sample_every=0.01, filter=0.01) D = model.add( EnsembleArray('D', nengo.LIF(N * Amat.shape[0] * Bmat.shape[1]), Amat.shape[0] * Bmat.shape[1], radius=radius)) def product(x): return x[0] * x[1] transformC = np.zeros((D.dimensions, Bmat.size)) for i in range(Bmat.size): transformC[i / Bmat.shape[0]][i] = 1 model.connect('C', 'D', function=product, transform=transformC) model.probe('D', sample_every=0.01, filter=0.01) sim = model.simulator(sim_class=self.Simulator) sim.run(1) with Plotter(self.Simulator) as plt: plt.plot(sim.data('D')) for d in np.dot(Amat, Bmat).flatten(): plt.axhline(d, color='k') plt.savefig('test_ensemble_array.test_matrix_mul.pdf') plt.close() self.assertTrue( np.allclose(sim.data('A')[50:, 0], 0.5, atol=.1, rtol=.01)) self.assertTrue( np.allclose(sim.data('A')[50:, 1], -0.5, atol=.1, rtol=.01)) self.assertTrue( np.allclose(sim.data('B')[50:, 0], 0, atol=.1, rtol=.01)) self.assertTrue( np.allclose(sim.data('B')[50:, 1], -1, atol=.1, rtol=.01)) self.assertTrue( np.allclose(sim.data('B')[50:, 2], .7, atol=.1, rtol=.01)) self.assertTrue( np.allclose(sim.data('B')[50:, 3], 0, atol=.1, rtol=.01)) Dmat = np.dot(Amat, Bmat) for i in range(Amat.shape[0]): for k in range(Bmat.shape[1]): self.assertTrue( np.allclose(sim.data('D')[-10:, i * Bmat.shape[1] + k], Dmat[i, k], atol=0.1, rtol=0.1), (sim.data('D')[-10:, i * Bmat.shape[1] + k], Dmat[i, k]))
def test_multidim_probe(self): # Adjust these values to change the matrix dimensions # Matrix A is D1xD2 # Matrix B is D2xD3 # result is D1xD3 D1 = 1 D2 = 2 D3 = 3 seed = 123 N = 200 Amat = np.asarray([[.4, .8]]) Bmat = np.asarray([[-1.0, -0.6, -.15], [0.25, .5, .7]]) net = nef.Network('V', seed=seed, simulator=self.Simulator) # values should stay within the range (-radius,radius) radius = 2.0 # make 2 matrices to store the input logging.debug("make_array: input matrices A and B") net.make_array('A', neurons=N, array_size=D1 * D2, radius=radius, neuron_type='lif') net.make_array('B', neurons=N, array_size=D2 * D3, radius=radius, neuron_type='lif') # connect inputs to them so we can set their value inputA = net.make_input('input A', value=Amat.flatten()) inputB = net.make_input('input B', value=Bmat.flatten()) logging.debug("connect: input matrices A and B") net.connect('input A', 'A') net.connect('input B', 'B') # the C matrix holds the intermediate product calculations # need to compute D1*D2*D3 products to multiply 2 matrices together logging.debug("make_array: intermediate C") net.make_array('C', 4 * N, D1 * D2 * D3, dimensions=2, radius=1.5 * radius, encoders=[[1, 1], [1, -1], [-1, 1], [-1, -1]], neuron_type='lif') transformA = [[0] * (D1 * D2) for i in range(D1 * D2 * D3 * 2)] transformB = [[0] * (D2 * D3) for i in range(D1 * D2 * D3 * 2)] for i in range(D1): for k in range(D3): for j in range(D2): tmp = (j + k * D2 + i * D2 * D3) transformA[tmp * 2][j + i * D2] = 1 transformB[tmp * 2 + 1][k + j * D3] = 1 logging.debug("transA: %s", str(transformA)) logging.debug("transB: %s", str(transformB)) logging.debug("connect A->C") net.connect('A', 'C', transform=transformA) logging.debug("connect B->C") net.connect('B', 'C', transform=transformB) Cprobe = net.make_probe('C', dt_sample=0.01, pstc=0.01) net.run(1) logging.debug("Cprove.shape=%s", str(Cprobe.get_data().shape)) logging.debug("Amat=%s", str(Amat)) logging.debug("Bmat=%s", str(Bmat)) data = Cprobe.get_data() with Plotter(self.Simulator) as plt: for i in range(D1): for k in range(D3): for j in range(D2): tmp = (j + k * D2 + i * D2 * D3) plt.subplot(D1 * D2 * D3, 2, 1 + 2 * tmp) plt.title('A[%i, %i]' % (i, j)) plt.axhline(Amat[i, j]) plt.ylim(-radius, radius) plt.plot(data[:, 2 * tmp]) plt.subplot(D1 * D2 * D3, 2, 2 + 2 * tmp) plt.title('B[%i, %i]' % (j, k)) plt.axhline(Bmat[j, k]) plt.ylim(-radius, radius) plt.plot(data[:, 2 * tmp + 1]) plt.savefig('test_old_api.test_multidimprobe.pdf') plt.close() for i in range(D1): for k in range(D3): for j in range(D2): tmp = (j + k * D2 + i * D2 * D3) self.assertTrue( np.allclose(data[-10:, 2 * tmp], Amat[i, j], atol=0.1, rtol=0.1), (data[-10:, 2 * tmp], Amat[i, j])) self.assertTrue( np.allclose(data[-10:, 1 + 2 * tmp], Bmat[j, k], atol=0.1, rtol=0.1))
def test_matrix_mul(self): # Adjust these values to change the matrix dimensions # Matrix A is D1xD2 # Matrix B is D2xD3 # result is D1xD3 D1 = 1 D2 = 2 D3 = 2 seed = 123 N = 200 Amat = np.asarray([[.5, -.5]]) Bmat = np.asarray([[ 0, -1., ], [.7, 0]]) net = nef.Network('Matrix Multiplication', seed=seed, simulator=self.Simulator) # values should stay within the range (-radius,radius) radius = 1 # make 2 matrices to store the input logging.debug("make_array: input matrices A and B") net.make_array('A', neurons=N, array_size=D1 * D2, radius=radius, neuron_type='lif') net.make_array('B', neurons=N, array_size=D2 * D3, radius=radius, neuron_type='lif') # connect inputs to them so we can set their value inputA = net.make_input('input A', value=Amat.ravel()) inputB = net.make_input('input B', value=Bmat.ravel()) logging.debug("connect: input matrices A and B") net.connect('input A', 'A') net.connect('input B', 'B') # the C matrix holds the intermediate product calculations # need to compute D1*D2*D3 products to multiply 2 matrices together logging.debug("make_array: intermediate C") net.make_array('C', 4 * N, D1 * D2 * D3, dimensions=2, radius=1.5 * radius, encoders=[[1, 1], [1, -1], [-1, 1], [-1, -1]], neuron_type='lif') # determine the transformation matrices to get the correct pairwise # products computed. This looks a bit like black magic but if # you manually try multiplying two matrices together, you can see # the underlying pattern. Basically, we need to build up D1*D2*D3 # pairs of numbers in C to compute the product of. If i,j,k are the # indexes into the D1*D2*D3 products, we want to compute the product # of element (i,j) in A with the element (j,k) in B. The index in # A of (i,j) is j+i*D2 and the index in B of (j,k) is k+j*D3. # The index in C is j+k*D2+i*D2*D3, multiplied by 2 since there are # two values per ensemble. We add 1 to the B index so it goes into # the second value in the ensemble. transformA = [[0] * (D1 * D2) for i in range(D1 * D2 * D3 * 2)] transformB = [[0] * (D2 * D3) for i in range(D1 * D2 * D3 * 2)] for i in range(D1): for j in range(D2): for k in range(D3): tmp = (j + k * D2 + i * D2 * D3) transformA[tmp * 2][j + i * D2] = 1 transformB[tmp * 2 + 1][k + j * D3] = 1 logging.debug("connect A->C") net.connect('A', 'C', transform=transformA) logging.debug("connect B->C") net.connect('B', 'C', transform=transformB) # now compute the products and do the appropriate summing logging.debug("make_array: output D") net.make_array('D', N, D1 * D3, radius=radius, neuron_type='lif') def product(x): return x[0] * x[1] # the mapping for this transformation is much easier, since we want to # combine D2 pairs of elements (we sum D2 products together) net.connect('C', 'D', index_post=[i / D2 for i in range(D1 * D2 * D3)], func=product) Aprobe = net.make_probe('A', dt_sample=0.01, pstc=0.01) Bprobe = net.make_probe('B', dt_sample=0.01, pstc=0.01) Cprobe = net.make_probe('C', dt_sample=0.01, pstc=0.01) Dprobe = net.make_probe('D', dt_sample=0.01, pstc=0.01) prod_probe = net._probe_decoded_signals( net.ensembles['C'].origin['product'].sigs, dt_sample=0.01, pstc=.01) net.run(1) Dmat = np.dot(Amat, Bmat) data = Dprobe.get_data() with Plotter(self.Simulator) as plt: for i in range(D1): for k in range(D3): plt.subplot(D1, D3, i * D3 + k + 1) plt.title('D[%i, %i]' % (i, k)) plt.plot(data[:, i * D3 + k]) plt.axhline(Dmat[i, k]) plt.ylim(-radius, radius) plt.savefig('test_old_api.test_matrix_mul.pdf') plt.close() self.assertTrue( np.allclose(Aprobe.get_data()[50:, 0], 0.5, atol=.1, rtol=.01)) self.assertTrue( np.allclose(Aprobe.get_data()[50:, 1], -0.5, atol=.1, rtol=.01)) self.assertTrue( np.allclose(Bprobe.get_data()[50:, 0], 0, atol=.1, rtol=.01)) self.assertTrue( np.allclose(Bprobe.get_data()[50:, 1], -1, atol=.1, rtol=.01)) self.assertTrue( np.allclose(Bprobe.get_data()[50:, 2], .7, atol=.1, rtol=.01)) self.assertTrue( np.allclose(Bprobe.get_data()[50:, 3], 0, atol=.1, rtol=.01)) for i in range(D1): for k in range(D3): self.assertTrue( np.allclose(data[-10:, i * D3 + k], Dmat[i, k], atol=0.1, rtol=0.1), (data[-10:, i * D3 + k], Dmat[i, k]))