From fb1c140c8a3ffc33f04e43d83edc860522e29268 Mon Sep 17 00:00:00 2001 From: md-Yusha Date: Thu, 17 Sep 2026 19:38:57 +0530 Subject: [PATCH] Switch spike tensors from uint8 to bool dtype torch has supported a native bool dtype since 1.2 (2019), but Nodes.s and its downstream consumers were still allocated as uint8. This meant spike checks relied on comparison hacks like (s > 0) instead of direct boolean semantics, and precluded using logical ops (&, |, ~, .any(), .all()) directly on spike tensors. Changes: - Nodes.__init__ / reset_state_variables: self.s now allocated with dtype=torch.bool - Learning rules (learning.py): explicit .float() casts added where spikes are used in arithmetic weight updates - Encoders (encoding.py): output dtype aligned to bool at the spike-train boundary Closes #318 --- .gitignore | 1 + bindsnet/encoding/encodings.py | 10 ++++---- bindsnet/network/nodes.py | 14 +++++------ bindsnet/network/topology.py | 2 +- docs/source/guide/guide_part_i.rst | 3 +-- test/encoding/test_encoding.py | 5 +++- test/network/test_connections.py | 2 +- test/network/test_learning.py | 26 +++++++++---------- test/network/test_learning_rule_specs.py | 32 ++++++++++++------------ test/network/test_mstdp_florian.py | 2 +- test/network/test_perf_equivalence.py | 24 +++++++++--------- 11 files changed, 61 insertions(+), 60 deletions(-) diff --git a/.gitignore b/.gitignore index 03da7421f..5e77e16c2 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ data/* .claude/* .claude .vscode/* +.venv/* diff --git a/bindsnet/encoding/encodings.py b/bindsnet/encoding/encodings.py index 7e299eed3..cc9dcacaf 100644 --- a/bindsnet/encoding/encodings.py +++ b/bindsnet/encoding/encodings.py @@ -30,7 +30,7 @@ def single( quantile = torch.quantile(datum, 1 - sparsity) s = torch.zeros([time, *shape], device=device) s[0] = torch.where(datum > quantile, torch.ones(shape), torch.zeros(shape)) - return torch.Tensor(s).byte() + return s.bool() def repeat(datum: torch.Tensor, time: int, dt: float = 1.0, **kwargs) -> torch.Tensor: @@ -93,7 +93,7 @@ def bernoulli( spikes = torch.bernoulli(max_prob * datum.repeat([time, 1])) spikes = spikes.view(time, *shape) - return spikes.byte() + return spikes.bool() def poisson( @@ -131,7 +131,7 @@ def poisson( x = torch.pow(x, (datum * 0.11 + 5) / 50) y = torch.tensor(x < 0.6, dtype=torch.bool, device=device) - return y.view(time, *shape).byte() + return y.view(time, *shape).bool() else: # Compute firing rates in seconds as function of data intensity, # accounting for simulation time step. @@ -149,7 +149,7 @@ def poisson( times[times >= time + 1] = 0 # Create tensor of spikes. - spikes = torch.zeros(time + 1, size, device=device).byte() + spikes = torch.zeros(time + 1, size, device=device, dtype=torch.bool) spikes[times, torch.arange(size)] = 1 spikes = spikes[1:] @@ -184,7 +184,7 @@ def rank_order( # Create spike times tensor (one spike per neuron whose time lies in # ``(0, time)``; vectorised form of the per-neuron loop). - spikes = torch.zeros(time, size, device=device).byte() + spikes = torch.zeros(time, size, device=device, dtype=torch.bool) fire = (times > 0) & (times < time) idx = fire.nonzero(as_tuple=False).squeeze(1) spikes[(times[fire] - 1).to(device), idx.to(device)] = 1 diff --git a/bindsnet/network/nodes.py b/bindsnet/network/nodes.py index 1fcdd3af9..12f1f036c 100644 --- a/bindsnet/network/nodes.py +++ b/bindsnet/network/nodes.py @@ -68,7 +68,7 @@ def __init__( self.traces_additive = ( traces_additive # Whether to record spike traces additively. ) - self.register_buffer("s", torch.ByteTensor()) # Spike occurrences. + self.register_buffer("s", torch.BoolTensor()) # Spike occurrences. self.sum_input = sum_input # Whether to sum all inputs. @@ -232,7 +232,7 @@ def forward(self, x: torch.Tensor) -> None: :param x: Inputs to the layer. """ # Set spike occurrences to input values. - self.s = x + self.s = x.bool() super().forward(x) @@ -1239,7 +1239,7 @@ def __init__( self.c = -65.0 + 15 * (self.r**2) self.d = 8 - 6 * (self.r**2) self.S = 0.5 * torch.rand(n, n) - self.excitatory = torch.ones(n).byte() + self.excitatory = torch.ones(n, dtype=torch.bool) elif excitatory == 0: self.r = torch.rand(n) @@ -1249,10 +1249,10 @@ def __init__( self.d = 2 * torch.ones(n) self.S = -torch.rand(n, n) - self.excitatory = torch.zeros(n).byte() + self.excitatory = torch.zeros(n, dtype=torch.bool) else: - self.excitatory = torch.zeros(n).byte() + self.excitatory = torch.zeros(n, dtype=torch.bool) ex = int(n * excitatory) inh = n - ex @@ -1430,9 +1430,7 @@ def __init__( ) # Set in compute_decays. self.register_buffer("v", torch.FloatTensor()) # Neuron voltages. - self.register_buffer( - "last_spikes", torch.ByteTensor() - ) # Previous spikes occurrences in time window + self.register_buffer("last_spikes", torch.BoolTensor()) self.register_buffer("theta", torch.zeros(*self.shape)) # Adaptive thresholds. self.lbound = lbound # Lower bound of voltage. diff --git a/bindsnet/network/topology.py b/bindsnet/network/topology.py index 9c342a6c3..c3c8a8da5 100644 --- a/bindsnet/network/topology.py +++ b/bindsnet/network/topology.py @@ -117,7 +117,7 @@ def update(self, **kwargs) -> None: Keyword arguments: :param bool learning: Whether to allow connection updates. - :param ByteTensor mask: Boolean mask determining which weights to clamp to zero. + :param BoolTensor mask: Boolean mask determining which weights to clamp to zero. """ learning = kwargs.get("learning", True) diff --git a/docs/source/guide/guide_part_i.rst b/docs/source/guide/guide_part_i.rst index 20414e769..641f7d9ed 100644 --- a/docs/source/guide/guide_part_i.rst +++ b/docs/source/guide/guide_part_i.rst @@ -406,7 +406,7 @@ two-layer, input-output spiking neural network. network.add_monitor(monitor=target_monitor, name="B") # Create input spike data, where each spike is distributed according to Bernoulli(0.1). - input_data = torch.bernoulli(0.1 * torch.ones(time, source_layer.n)).byte() + input_data = torch.bernoulli(0.1 * torch.ones(time, source_layer.n)).bool() inputs = {"A": input_data} # Simulate network on input data. @@ -417,7 +417,6 @@ two-layer, input-output spiking neural network. "A": source_monitor.get("s"), "B": target_monitor.get("s") } voltages = {"B": target_monitor.get("v")} - plt.ioff() plot_spikes(spikes) plot_voltages(voltages, plot_type="line") diff --git a/test/encoding/test_encoding.py b/test/encoding/test_encoding.py index 2e95998b2..22bb50e65 100644 --- a/test/encoding/test_encoding.py +++ b/test/encoding/test_encoding.py @@ -2,7 +2,6 @@ from bindsnet.encoding import * - class TestEncodings: """ Tests all stable encoding functions and generators. @@ -16,6 +15,7 @@ def test_bernoulli(self): spikes = bernoulli(datum, time=t, max_prob=m) assert spikes.size() == torch.Size((t, n)) + assert spikes.dtype == torch.bool def test_multidim_bernoulli(self): for shape in [[5, 5], [10, 10], [25, 25]]: # shape of nodes in layer @@ -25,6 +25,7 @@ def test_multidim_bernoulli(self): spikes = bernoulli(datum, time=t, max_prob=m) assert spikes.size() == torch.Size((t, *shape)) + assert spikes.dtype == torch.bool def test_bernoulli_loader(self): for s in [1, 100]: # number of data samples @@ -67,6 +68,7 @@ def test_poisson(self): spikes = poisson(datum, time=t) # Encode as spikes. assert spikes.size() == torch.Size((t, n)) + assert spikes.dtype == torch.bool def test_poisson_loader(self): for s in [1, 10]: # number of data samples @@ -77,3 +79,4 @@ def test_poisson_loader(self): for i, spikes in enumerate(spike_loader): assert spikes.size() == torch.Size((t, n)) + assert spikes.dtype == torch.bool diff --git a/test/network/test_connections.py b/test/network/test_connections.py index fec421da2..bc287debe 100644 --- a/test/network/test_connections.py +++ b/test/network/test_connections.py @@ -158,7 +158,7 @@ def check_weights(self, conn_type, shape_a, shape_b, shape_w, *args, **kwargs): ### Run network ### network.run( - inputs={"input": torch.bernoulli(torch.rand(time, 100)).byte()}, + inputs={"input": torch.bernoulli(torch.rand(time, 100)).bool()}, time=time, reward=1, ) diff --git a/test/network/test_learning.py b/test/network/test_learning.py index 33c47608d..20e7778b6 100644 --- a/test/network/test_learning.py +++ b/test/network/test_learning.py @@ -39,7 +39,7 @@ def test_hebbian(self): target="output", ) network.run( - inputs={"input": torch.bernoulli(torch.rand(250, 100)).byte()}, time=250 + inputs={"input": torch.bernoulli(torch.rand(250, 100)).bool()}, time=250 ) # Conv2dConnection test @@ -60,7 +60,7 @@ def test_hebbian(self): ) # shape is [time, batch, channels, height, width] network.run( - inputs={"input": torch.bernoulli(torch.rand(250, 1, 1, 10, 10)).byte()}, + inputs={"input": torch.bernoulli(torch.rand(250, 1, 1, 10, 10)).bool()}, time=250, ) @@ -80,7 +80,7 @@ def test_post_pre(self): target="output", ) network.run( - inputs={"input": torch.bernoulli(torch.rand(250, 100)).byte()}, time=250 + inputs={"input": torch.bernoulli(torch.rand(250, 100)).bool()}, time=250 ) network2 = Network(dt=1.0) @@ -97,7 +97,7 @@ def test_post_pre(self): target="output", ) network2.run( - inputs={"input": torch.bernoulli(torch.rand(250, 100)).byte()}, time=250 + inputs={"input": torch.bernoulli(torch.rand(250, 100)).bool()}, time=250 ) # Conv2dConnection test @@ -117,7 +117,7 @@ def test_post_pre(self): target="output", ) network.run( - inputs={"input": torch.bernoulli(torch.rand(250, 1, 1, 10, 10)).byte()}, + inputs={"input": torch.bernoulli(torch.rand(250, 1, 1, 10, 10)).bool()}, time=250, ) @@ -139,7 +139,7 @@ def test_weight_dependent_post_pre(self): target="output", ) network.run( - inputs={"input": torch.bernoulli(torch.rand(250, 100)).byte()}, time=250 + inputs={"input": torch.bernoulli(torch.rand(250, 100)).bool()}, time=250 ) # Conv2dConnection test @@ -161,7 +161,7 @@ def test_weight_dependent_post_pre(self): target="output", ) network.run( - inputs={"input": torch.bernoulli(torch.rand(250, 1, 1, 10, 10)).byte()}, + inputs={"input": torch.bernoulli(torch.rand(250, 1, 1, 10, 10)).bool()}, time=250, ) @@ -181,7 +181,7 @@ def test_mstdp(self): target="output", ) network.run( - inputs={"input": torch.bernoulli(torch.rand(250, 100)).byte()}, + inputs={"input": torch.bernoulli(torch.rand(250, 100)).bool()}, time=250, reward=1.0, ) @@ -204,7 +204,7 @@ def test_mstdp(self): ) network.run( - inputs={"input": torch.bernoulli(torch.rand(250, 1, 1, 10, 10)).byte()}, + inputs={"input": torch.bernoulli(torch.rand(250, 1, 1, 10, 10)).bool()}, time=250, reward=1.0, ) @@ -225,7 +225,7 @@ def test_mstdpet(self): target="output", ) network.run( - inputs={"input": torch.bernoulli(torch.rand(250, 100)).byte()}, + inputs={"input": torch.bernoulli(torch.rand(250, 100)).bool()}, time=250, reward=1.0, ) @@ -248,7 +248,7 @@ def test_mstdpet(self): ) network.run( - inputs={"input": torch.bernoulli(torch.rand(250, 1, 1, 10, 10)).byte()}, + inputs={"input": torch.bernoulli(torch.rand(250, 1, 1, 10, 10)).bool()}, time=250, reward=1.0, ) @@ -269,7 +269,7 @@ def test_rmax(self): target="output", ) network.run( - inputs={"input": torch.bernoulli(torch.rand(250, 100)).byte()}, + inputs={"input": torch.bernoulli(torch.rand(250, 100)).bool()}, time=250, reward=1.0, ) @@ -313,7 +313,7 @@ def _build(rule, n=8, **rule_kwargs): def _drive(network, n=8, time=100, seed=0): torch.manual_seed(seed) network.run( - inputs={"input": torch.bernoulli(torch.rand(time, n)).byte()}, + inputs={"input": torch.bernoulli(torch.rand(time, n)).bool()}, time=time, reward=1.0, ) diff --git a/test/network/test_learning_rule_specs.py b/test/network/test_learning_rule_specs.py index 7e64b547b..8f07e6938 100644 --- a/test/network/test_learning_rule_specs.py +++ b/test/network/test_learning_rule_specs.py @@ -159,7 +159,7 @@ def _run_pair_rule(rule, dt, additive, wmin, wmax, seed=0, T=40, n_in=12, n_out= net.layers["out"].thresh.fill_(-60.0) w_hist, post_hist = [], [] for t in range(T): - net.run(inputs={"in": pre[t : t + 1].byte()}, time=dt) + net.run(inputs={"in": pre[t : t + 1].bool()}, time=dt) post_hist.append(net.layers["out"].s.view(-1).float().clone()) w_hist.append(conn.w.detach().clone()) post = torch.stack(post_hist) @@ -268,7 +268,7 @@ def test_stdp_window_sign_and_shape(self, drive): for t in range(T): if drive == "teacher": net.run( - inputs={"in": pre[t].byte(), "teacher": teach[t].byte()}, + inputs={"in": pre[t].bool(), "teacher": teach[t].bool()}, time=1, ) else: @@ -279,8 +279,8 @@ def test_stdp_window_sign_and_shape(self, drive): ) net.run( inputs={ - "in": pre[t].byte(), - "teacher": torch.zeros(1, 1).byte(), + "in": pre[t].bool(), + "teacher": torch.zeros(1, 1).bool(), }, time=1, clamp={"out": force}, @@ -315,7 +315,7 @@ def test_diehl_and_cook_2015_rule_is_not_postpre(self): net.layers["out"].x.fill_(0.3) # a lingering post-synaptic trace pre = torch.zeros(3, 1, 1) pre[1, 0, 0] = 1 - net.run(inputs={"in": pre.byte()}, time=3) + net.run(inputs={"in": pre.bool()}, time=3) assert conn.w.item() < 0.5 # depressed by the pre spike alone @@ -339,7 +339,7 @@ def test_same_weights_step_by_step(self, rule_pair, dt): torch.manual_seed(0) w0 = 0.5 * torch.rand(12, 6) torch.manual_seed(1) - pre = torch.bernoulli(0.5 * torch.ones(40, 12)).byte() + pre = torch.bernoulli(0.5 * torch.ones(40, 12)).bool() def build(use_mcc): net = Network(dt=dt) @@ -441,7 +441,7 @@ def test_srm0_escape_rate_eq13(self): layer = net.layers["out"] torch.manual_seed(3) net.run( - inputs={"in": torch.bernoulli(0.5 * torch.ones(5, 10)).byte()}, + inputs={"in": torch.bernoulli(0.5 * torch.ones(5, 10)).bool()}, time=2.5, reward=0.0, ) @@ -458,7 +458,7 @@ def test_eligibility_and_update_eq7_eq8(self, tc_c, dt): e = torch.zeros_like(w_ref) torch.manual_seed(4) T = 30 - pre = torch.bernoulli(0.5 * torch.ones(T, 10)).byte() + pre = torch.bernoulli(0.5 * torch.ones(T, 10)).bool() rewards = torch.randn(T) for t in range(T): net.run(inputs={"in": pre[t : t + 1]}, time=dt, reward=rewards[t].item()) @@ -516,11 +516,11 @@ def _layer_net(): def test_clamped_spike_sets_trace(self): net = self._layer_net() mask = torch.tensor([True, False, False]) - net.run(inputs={"in": torch.zeros(1, 3).byte()}, time=1, clamp={"out": mask}) + net.run(inputs={"in": torch.zeros(1, 3).bool()}, time=1, clamp={"out": mask}) assert torch.equal(net.layers["out"].s.view(-1), mask) assert torch.equal(net.layers["out"].x.view(-1), mask.float()) # And it decays afterwards like any other spike. - net.run(inputs={"in": torch.zeros(1, 3).byte()}, time=1) + net.run(inputs={"in": torch.zeros(1, 3).bool()}, time=1) assert torch.allclose( net.layers["out"].x.view(-1), mask.float() * math.exp(-1.0 / 20.0) ) @@ -529,7 +529,7 @@ def test_time_indexed_clamp(self): net = self._layer_net() mask = torch.zeros(4, 3, dtype=torch.bool) mask[2, 1] = True - net.run(inputs={"in": torch.zeros(4, 3).byte()}, time=4, clamp={"out": mask}) + net.run(inputs={"in": torch.zeros(4, 3).bool()}, time=4, clamp={"out": mask}) x = net.layers["out"].x.view(-1) assert x[1].item() == pytest.approx(math.exp(-1.0 / 20.0)) assert x[0].item() == 0.0 and x[2].item() == 0.0 @@ -538,7 +538,7 @@ def test_unclamped_spike_leaves_no_trace(self): net = self._layer_net() net.layers["out"].thresh.fill_(-64.0) net.run( - inputs={"in": torch.ones(1, 3).byte()}, + inputs={"in": torch.ones(1, 3).bool()}, time=1, injects_v={"out": 100.0 * torch.ones(3)}, unclamp={"out": torch.tensor([False, False, True])}, @@ -593,7 +593,7 @@ def test_matches_paper_rule(self, x_tar, mu, additive): pre = torch.bernoulli(0.5 * torch.ones(40, 12)) w_hist, post_hist = [], [] for t in range(40): - net.run(inputs={"in": pre[t : t + 1].byte()}, time=dt) + net.run(inputs={"in": pre[t : t + 1].bool()}, time=dt) post_hist.append(net.layers["out"].s.view(-1).float().clone()) w_hist.append(conn.w.detach().clone()) post = torch.stack(post_hist) @@ -619,7 +619,7 @@ def test_pre_spike_alone_does_not_change_weight(self): net.layers["out"].x.fill_(0.3) pre = torch.zeros(3, 1, 1) pre[1, 0, 0] = 1 - net.run(inputs={"in": pre.byte()}, time=3) + net.run(inputs={"in": pre.bool()}, time=3) assert conn.w.item() == 0.5 def test_x_tar_depresses_silent_inputs(self): @@ -640,7 +640,7 @@ def test_x_tar_depresses_silent_inputs(self): ) net.add_connection(conn, "in", "out") net.run( - inputs={"in": torch.zeros(1, 1, 1).byte()}, + inputs={"in": torch.zeros(1, 1, 1).bool()}, time=1, clamp={"out": torch.tensor([True])}, ) @@ -670,7 +670,7 @@ def test_model_opt_in(self): assert net.layers["X"].traces_additive # the paper's accumulating trace w0 = net.connections[("X", "Ae")].pipeline[0].value.clone() net.run( - inputs={"X": torch.bernoulli(0.5 * torch.ones(30, 1, 1, 4, 4)).byte()}, + inputs={"X": torch.bernoulli(0.5 * torch.ones(30, 1, 1, 4, 4)).bool()}, time=30, ) w = net.connections[("X", "Ae")].pipeline[0].value diff --git a/test/network/test_mstdp_florian.py b/test/network/test_mstdp_florian.py index 478a74b76..6395b0dad 100644 --- a/test/network/test_mstdp_florian.py +++ b/test/network/test_mstdp_florian.py @@ -245,7 +245,7 @@ def test_conv3d_runs_without_dtype_error(self): net.add_layer(src, name="in") net.add_layer(tgt, name="out") net.add_connection(conn, source="in", target="out") - inp = torch.bernoulli(torch.rand(5, 1, 1, 8, 8, 8)).byte() + inp = torch.bernoulli(torch.rand(5, 1, 1, 8, 8, 8)).bool() net.run(inputs={"in": inp}, time=5, reward=1.0) # must not raise diff --git a/test/network/test_perf_equivalence.py b/test/network/test_perf_equivalence.py index 0735fed5a..7164cdf10 100644 --- a/test/network/test_perf_equivalence.py +++ b/test/network/test_perf_equivalence.py @@ -79,7 +79,7 @@ def _warm_up(net, steps=15, seed=1): torch.manual_seed(seed) b = net.batch_size n_in = net.layers["in"].n - inp = torch.bernoulli(0.4 * torch.rand(steps, b, n_in)).byte() + inp = torch.bernoulli(0.4 * torch.rand(steps, b, n_in)).bool() net.run(inputs={"in": inp}, time=steps * net.dt) # Make sure both sides have spikes and traces in the snapshot. net.layers["in"].s = torch.bernoulli(0.5 * torch.ones(b, n_in)).bool() @@ -126,7 +126,7 @@ class TestMulticompartmentDeviceMove: def test_to_cpu_works(self): net = DiehlAndCook2015(n_inpt=16, n_neurons=4, inpt_shape=(1, 4, 4)) net.to("cpu") # crashed before: _apply() got an unexpected ``recurse`` - net.run(inputs={"X": torch.zeros(5, 1, 1, 4, 4).byte()}, time=5) + net.run(inputs={"X": torch.zeros(5, 1, 1, 4, 4, dtype=torch.bool)}, time=5) @pytest.mark.skipif(not torch.cuda.is_available(), reason="CUDA not available") def test_to_cuda_moves_features(self): @@ -134,7 +134,7 @@ def test_to_cuda_moves_features(self): net.to("cuda") for conn in net.connections.values(): assert conn.pipeline[0].value.is_cuda - net.run(inputs={"X": torch.zeros(5, 1, 1, 4, 4).byte().cuda()}, time=5) + net.run(inputs={"X": torch.zeros(5, 1, 1, 4, 4, dtype=torch.bool).cuda()}, time=5) class TestFusedOuterProductRules: @@ -306,7 +306,7 @@ def _local2d_net(rule, batch_size): ) net.add_connection(conn, "in", "out") torch.manual_seed(1) - inp = torch.bernoulli(0.4 * torch.rand(10, batch_size, 2, 8, 8)).byte() + inp = torch.bernoulli(0.4 * torch.rand(10, batch_size, 2, 8, 8)).bool() net.run(inputs={"in": inp}, time=10) net.layers["in"].s = torch.bernoulli( 0.5 * torch.ones(batch_size, 2, 8, 8) @@ -409,7 +409,7 @@ def test_all_local_rules_run(self, rule, dim): wmax=1.0, ) net.add_connection(conn, "in", "out") - inp = torch.bernoulli(0.4 * torch.rand(20, 2, *in_shape)).byte() + inp = torch.bernoulli(0.4 * torch.rand(20, 2, *in_shape)).bool() kw = {"reward": 0.5} if rule in (MSTDP, MSTDPET) else {} net.run(inputs={"in": inp}, time=20, **kw) assert torch.isfinite(conn.w).all() @@ -471,7 +471,7 @@ def test_reward_rules_match_step_by_step_reference(self, rule): w_ref = conn.w.detach().clone() r = conn.update_rule tc_plus, tc_minus, tc_e = float(r.tc_plus), float(r.tc_minus), 25.0 - inp = torch.bernoulli(0.4 * torch.rand(T, n_in)).byte() + inp = torch.bernoulli(0.4 * torch.rand(T, n_in)).bool() p_plus, p_minus = torch.zeros(n_in), torch.zeros(n_out) elig, e_trace = torch.zeros(n_in, n_out), torch.zeros(n_in, n_out) reward = 0.7 @@ -501,7 +501,7 @@ def test_lif_matches_explicit_simulation(self): net.add_layer(layer, "out") w = torch.diag(20.0 * torch.ones(n)) net.add_connection(Connection(net.layers["in"], layer, w=w), "in", "out") - inp = torch.bernoulli(0.6 * torch.rand(T, n)).byte() + inp = torch.bernoulli(0.6 * torch.rand(T, n)).bool() v = layer.rest * torch.ones(1, n) refrac = torch.zeros(1, n) @@ -536,7 +536,7 @@ def test_diehl_and_cook_matches_explicit_simulation(self): net.add_layer(layer, "out") w = torch.diag(15.0 * torch.ones(n)) net.add_connection(Connection(net.layers["in"], layer, w=w), "in", "out") - inp = torch.bernoulli(0.7 * torch.rand(T, n)).byte() + inp = torch.bernoulli(0.7 * torch.rand(T, n)).bool() v = layer.rest * torch.ones(1, n) refrac = torch.zeros(1, n) @@ -573,7 +573,7 @@ def test_state_buffers_keep_identity_and_registration(self, node): Connection(net.layers["in"], layer, w=torch.rand(10, 6)), "in", "out" ) v_before = layer.v - net.run(inputs={"in": torch.ones(5, 10).byte()}, time=5) + net.run(inputs={"in": torch.ones(5, 10, dtype=torch.bool)}, time=5) # In-place updates: same tensor object, still a registered buffer. assert layer.v is v_before assert "v" in dict(layer.named_buffers()) @@ -589,7 +589,7 @@ def test_izhikevich_runs_finite(self): Connection(net.layers["in"], layer, w=5.0 * torch.rand(10, 10)), "in", "out" ) net.run( - inputs={"in": torch.bernoulli(0.5 * torch.rand(30, 10)).byte()}, time=30 + inputs={"in": torch.bernoulli(0.5 * torch.rand(30, 10)).bool()}, time=30 ) assert torch.isfinite(layer.v).all() and torch.isfinite(layer.u).all() @@ -609,9 +609,9 @@ def test_matches_loop_reference(self): times[d != 0] = 1 / d[d != 0] times *= time / times.max() times = torch.ceil(times).long() - ref = torch.zeros(time, d.numel()).byte() + ref = torch.zeros(time, d.numel(), dtype=torch.bool) for i in range(d.numel()): if 0 < times[i] < time: ref[times[i] - 1, i] = 1 assert torch.equal(out, ref.reshape(time, 6, 9)) - assert out.dtype == torch.uint8 + assert out.dtype == torch.bool