def test_split_no_node_neuron_error(): with nengo.Network() as net: add_params(net) node_offchip = nengo.Node(np.sin) ens_onchip = nengo.Ensemble(10, 1) nengo.Connection(node_offchip, ens_onchip) with pytest.raises(BuildError, match="DecodeNeurons"): split(net, precompute=False, node_neurons=None, node_tau=None)
def test_split_precompute_loop_error(): with nengo.Network() as net: add_params(net) node_offchip = nengo.Node(lambda t, x: x + 1, size_in=1, size_out=1) ens_onchip = nengo.Ensemble(10, 1) nengo.Connection(node_offchip, ens_onchip) nengo.Connection(ens_onchip, node_offchip) with pytest.raises(BuildError, match="precompute"): split(net, precompute=True, node_neurons=default_node_neurons, node_tau=0.005)
def test_split_conv2d_transform_error(): with nengo.Network() as net: add_params(net) node_offchip = nengo.Node([1]) ens_onchip = nengo.Ensemble(10, 1) conv2d = nengo.Convolution(n_filters=1, input_shape=(1, 1, 1), kernel_size=(1, 1)) nengo.Connection(node_offchip, ens_onchip, transform=conv2d) with pytest.raises(BuildError, match="Conv2D"): split(net, precompute=False, node_neurons=default_node_neurons, node_tau=0.005)
def test_identity_array(n_ensembles, ens_dimensions): with nengo.Network() as model: a = nengo.networks.EnsembleArray(10, n_ensembles, ens_dimensions) b = nengo.networks.EnsembleArray(10, n_ensembles, ens_dimensions) nengo.Connection(a.output, b.input) nengo_loihi.add_params(model) networks = splitter.split(model, precompute=False, remove_passthrough=True, max_rate=1000, inter_tau=0.005) # ignore the a.input -> a.ensemble connections connections = [ c for c in networks.chip.connections if not (isinstance(c.pre_obj, splitter.ChipReceiveNode) and c.post_obj in a.ensembles) ] assert len(connections) == n_ensembles pre = set() post = set() for c in connections: assert c.pre in a.all_ensembles or c.pre_obj is a.input assert c.post in b.all_ensembles assert np.allclose(c.transform, np.eye(ens_dimensions)) pre.add(c.pre) post.add(c.post) assert len(pre) == n_ensembles assert len(post) == n_ensembles
def test_full_array(n_ensembles, ens_dimensions): with nengo.Network() as model: a = nengo.networks.EnsembleArray(10, n_ensembles, ens_dimensions) b = nengo.networks.EnsembleArray(10, n_ensembles, ens_dimensions) D = n_ensembles * ens_dimensions nengo.Connection(a.output, b.input, transform=np.ones((D, D))) nengo_loihi.add_params(model) networks = splitter.split(model, precompute=False, remove_passthrough=True, max_rate=1000, inter_tau=0.005) # ignore the a.input -> a.ensemble connections connections = [ c for c in networks.chip.connections if not (isinstance(c.pre_obj, splitter.ChipReceiveNode) and c.post_obj in a.ensembles) ] assert len(connections) == n_ensembles**2 pairs = set() for c in connections: assert c.pre in a.all_ensembles assert c.post in b.all_ensembles assert np.allclose(c.transform, np.ones((ens_dimensions, ens_dimensions))) pairs.add((c.pre, c.post)) assert len(pairs) == n_ensembles**2
def test_consistent_order(): with nengo.Network() as model: add_params(model) u0 = nengo.Node(0, label="u0") for i in range(5): e = nengo.Ensemble(i + 1, 1, label="e%d" % i) f = nengo.Ensemble(i + 1, 1, label="f%d" % i) nengo.Connection(u0, e, label="c0%d" % i) nengo.Connection(e, f, label="cf%d" % i) nengo.Probe(e) nengo.Probe(f.neurons) # Test splitting a number of times, making sure the order of things matches # the original network each time split_params = dict( precompute=False, node_neurons=OnOffDecodeNeurons(dt=0.001), node_tau=0.005, remove_passthrough=False, ) networks0 = split(model, **split_params) for _ in range(5): networks = split(model, **split_params) # --- order matches original network assert len(model.all_ensembles) == len(networks.chip.all_ensembles) for ea, eb in zip(model.all_ensembles, networks.chip.all_ensembles): assert ea.n_neurons == eb.n_neurons and ea.label == eb.label # --- order matches previous split for attr in ('connections', 'ensembles', 'nodes', 'probes'): for net in ('host_pre', 'host', 'chip'): aa = getattr(getattr(networks0, net), 'all_' + attr) bb = getattr(getattr(networks, net), 'all_' + attr) for a, b in zip(aa, bb): assert a.label == b.label
def test_synapse_merging(Simulator, seed): with nengo.Network(seed=seed) as model: a = nengo.networks.EnsembleArray(10, n_ensembles=2) b = nengo.Node(None, size_in=2) c = nengo.networks.EnsembleArray(10, n_ensembles=2) nengo.Connection(a.output[0], b[0], synapse=None) nengo.Connection(a.output[1], b[1], synapse=0.1) nengo.Connection(b[0], c.input[0], synapse=None) nengo.Connection(b[0], c.input[1], synapse=0.2) nengo.Connection(b[1], c.input[0], synapse=None) nengo.Connection(b[1], c.input[1], synapse=0.2) nengo_loihi.add_params(model) networks = splitter.split(model, precompute=False, remove_passthrough=True, max_rate=1000, inter_tau=0.005) # ignore the a.input -> a.ensemble connections connections = [ c for c in networks.chip.connections if not (isinstance(c.pre_obj, splitter.ChipReceiveNode) and c.post_obj in a.ensembles) ] assert len(connections) == 4 desired_filters = { ('0', '0'): None, ('0', '1'): 0.2, ('1', '0'): 0.1, ('1', '1'): 0.3, } for c in connections: if desired_filters[(c.pre.label, c.post.label)] is None: assert c.synapse is None else: assert isinstance(c.synapse, nengo.Lowpass) assert np.allclose(c.synapse.tau, desired_filters[(c.pre.label, c.post.label)]) # check that model builds/runs correctly with Simulator(model, remove_passthrough=True) as sim: sim.step()
def test_passthrough_placement(): with nengo.Network() as model: stim = nengo.Node(0) a = nengo.Node(None, size_in=1) # should be off-chip b = nengo.Ensemble(10, 1) c = nengo.Node(None, size_in=1) # should be removed d = nengo.Node(None, size_in=1) # should be removed e = nengo.Node(None, size_in=1) # should be removed f = nengo.Ensemble(10, 1) g = nengo.Node(None, size_in=1) # should be off-chip nengo.Connection(stim, a) nengo.Connection(a, b) nengo.Connection(b, c) nengo.Connection(c, d) nengo.Connection(d, e) nengo.Connection(e, f) nengo.Connection(f, g) nengo.Probe(g) nengo_loihi.add_params(model) networks = splitter.split(model, precompute=False, remove_passthrough=True, max_rate=1000, inter_tau=0.005) chip = networks.chip host = networks.host assert a in host.nodes assert a not in chip.nodes assert c not in host.nodes assert c not in chip.nodes assert d not in host.nodes assert d not in chip.nodes assert e not in host.nodes assert e not in chip.nodes assert g in host.nodes assert g not in chip.nodes
def test_transform_merging(d1, d2, d3): with nengo.Network() as model: a = nengo.Ensemble(10, d1) b = nengo.Node(None, size_in=d2) c = nengo.Ensemble(10, d3) t1 = np.random.uniform(-1, 1, (d2, d1)) t2 = np.random.uniform(-1, 1, (d3, d2)) nengo.Connection(a, b, transform=t1) nengo.Connection(b, c, transform=t2) nengo_loihi.add_params(model) networks = splitter.split(model, precompute=False, remove_passthrough=True, max_rate=1000, inter_tau=0.005) chip = networks.chip assert len(chip.connections) == 1 conn = chip.connections[0] assert np.allclose(conn.transform, np.dot(t2, t1))
def __init__( # noqa: C901 self, network, dt=0.001, seed=None, model=None, precompute=False, target=None, progress_bar=None, remove_passthrough=True, hardware_options=None, ): # initialize values used in __del__ and close() first self.closed = True self.precompute = precompute self.networks = None self.sims = OrderedDict() self._run_steps = None hardware_options = {} if hardware_options is None else hardware_options if progress_bar: warnings.warn("nengo-loihi does not support progress bars") if HAS_DL: install_dl_builders() if model is None: # Call the builder to make a model self.model = Model(dt=float(dt), label="%s, dt=%f" % (network, dt)) else: assert isinstance(model, Model), ( "model is not type 'nengo_loihi.builder.Model'") self.model = model assert self.model.dt == dt if network is not None: nengo.rc.set("decoder_cache", "enabled", "False") config.add_params(network) # ensure seeds are identical to nengo seed_network(network, seeds=self.model.seeds, seeded=self.model.seeded) # split the host into one, two or three networks self.networks = split( network, precompute=precompute, node_neurons=self.model.node_neurons, node_tau=self.model.decode_tau, remove_passthrough=remove_passthrough, ) network = self.networks.chip self.model.chip2host_params = self.networks.chip2host_params self.chip = self.networks.chip self.host = self.networks.host self.host_pre = self.networks.host_pre if len(self.host_pre.all_objects) > 0: host_pre_model = self._get_host_model( self.host_pre, dt=dt, seeds=self.model.seeds, seeded=self.model.seeded) self.sims["host_pre"] = nengo.Simulator(self.host_pre, dt=self.dt, model=host_pre_model, progress_bar=False, optimize=False) if len(self.host.all_objects) > 0: host_model = self._get_host_model( self.host, dt=dt, seeds=self.model.seeds, seeded=self.model.seeded) self.sims["host"] = nengo.Simulator( self.host, dt=self.dt, model=host_model, progress_bar=False, optimize=False) elif not precompute: # If there is no host and precompute=False, then all objects # must be on the chip, which is precomputable in the sense that # no communication has to happen with the host. # We could warn about this, but we want to avoid people having # to specify `precompute` unless they absolutely have to. self.precompute = True # Build the network into the model self.model.build(network) self._probe_outputs = self.model.params self.data = ProbeDict(self._probe_outputs) for sim in self.sims.values(): self.data.add_fallback(sim.data) if seed is None: if network is not None and network.seed is not None: seed = network.seed + 1 else: seed = np.random.randint(npext.maxint) if target is None: target = 'loihi' if HAS_NXSDK else 'sim' self.target = target logger.info("Simulator target is %r", target) logger.info("Simulator precompute is %r", self.precompute) if target != "simreal": discretize_model(self.model) if target in ("simreal", "sim"): self.sims["emulator"] = EmulatorInterface(self.model, seed=seed) elif target == 'loihi': assert HAS_NXSDK, "Must have NxSDK installed to use Loihi hardware" self.sims["loihi"] = HardwareInterface( self.model, use_snips=not self.precompute, seed=seed, **hardware_options) else: raise ValidationError("Must be 'simreal', 'sim', or 'loihi'", attr="target") assert "emulator" in self.sims or "loihi" in self.sims self.closed = False self.reset(seed=seed)
def __init__( # noqa: C901 self, network, dt=0.001, seed=None, model=None, precompute=False, target=None, progress_bar=None, remove_passthrough=True ): self.closed = True # Start closed in case constructor raises exception if progress_bar is not None: raise NotImplementedError("progress bars not implemented") if model is None: # Call the builder to make a model self.model = Model(dt=float(dt), label="%s, dt=%f" % (network, dt)) else: assert isinstance(model, Model), ( "model is not type 'nengo_loihi.builder.Model'") self.model = model assert self.model.dt == dt max_rate = self.model.inter_rate * self.model.inter_n rtol = 1e-8 # allow for floating point inaccuracies if max_rate > (1. / self.dt) * (1 + rtol): raise BuildError("Simulator `dt` must be <= %s (got %s)" % (1. / max_rate, self.dt)) self.precompute = precompute self.networks = None self.sims = OrderedDict() self._run_steps = None if network is not None: nengo.rc.set("decoder_cache", "enabled", "False") config.add_params(network) # split the host into one, two or three networks self.networks = split( network, precompute, max_rate, self.model.inter_tau, remove_passthrough=remove_passthrough, ) network = self.networks.chip self.model.chip2host_params = self.networks.chip2host_params self.chip = self.networks.chip self.host = self.networks.host self.host_pre = self.networks.host_pre if len(self.host_pre.all_objects) > 0: self.sims["host_pre"] = nengo.Simulator(self.host_pre, dt=self.dt, progress_bar=False, optimize=False) if len(self.host.all_objects) > 0: self.sims["host"] = nengo.Simulator( self.host, dt=self.dt, progress_bar=False, optimize=False) elif not precompute: # If there is no host and precompute=False, then all objects # must be on the chip, which is precomputable in the sense that # no communication has to happen with the host. # We could warn about this, but we want to avoid people having # to specify `precompute` unless they absolutely have to. self.precompute = True # Build the network into the model self.model.build(network) self._probe_outputs = self.model.params self.data = ProbeDict(self._probe_outputs) for sim in self.sims.values(): self.data.add_fallback(sim.data) if seed is None: if network is not None and network.seed is not None: seed = network.seed + 1 else: seed = np.random.randint(npext.maxint) if target is None: try: import nxsdk target = 'loihi' except ImportError: target = 'sim' self.target = target logger.info("Simulator target is %r", target) logger.info("Simulator precompute is %r", self.precompute) if target != "simreal": self.model.discretize() if target in ("simreal", "sim"): self.sims["emulator"] = CxSimulator(self.model, seed=seed) elif target == 'loihi': self.sims["loihi"] = LoihiSimulator( self.model, use_snips=not self.precompute, seed=seed) else: raise ValidationError("Must be 'simreal', 'sim', or 'loihi'", attr="target") assert "emulator" in self.sims or "loihi" in self.sims self.closed = False self.reset(seed=seed)